[update] Splitted the large source files.
This commit is contained in:
parent
aa44c004af
commit
c760bd6b9b
105
sjplayer/src/sjplayer/AbstractScheduledController.d
Normal file
105
sjplayer/src/sjplayer/AbstractScheduledController.d
Normal file
@ -0,0 +1,105 @@
|
||||
/// License: MIT
|
||||
module sjplayer.AbstractScheduledController;
|
||||
|
||||
import std.algorithm,
|
||||
std.exception,
|
||||
std.typecons;
|
||||
|
||||
import sjscript;
|
||||
|
||||
import sjplayer.ScheduledControllerInterface,
|
||||
sjplayer.VarStoreInterface,
|
||||
sjplayer.util.Parameter,
|
||||
sjplayer.util.Period;
|
||||
|
||||
///
|
||||
abstract class AbstractScheduledController : ScheduledControllerInterface {
|
||||
public:
|
||||
///
|
||||
this(in VarStoreInterface varstore, in ParametersBlock[] operations) {
|
||||
varstore_ = varstore;
|
||||
operations_ = operations;
|
||||
}
|
||||
|
||||
override void Operate(float time) {
|
||||
FinalizeCurrentOperationIfEnded(time);
|
||||
PrepareNextOperationIfStarted(time);
|
||||
ProcessCurrentOperationIfAvailable(time);
|
||||
}
|
||||
|
||||
protected:
|
||||
static struct VarStore {
|
||||
public:
|
||||
float opIndex(string name) const {
|
||||
if (!time_.isNull && name == "time") return time_.get;
|
||||
return this_.GetVariable(name);
|
||||
}
|
||||
private:
|
||||
AbstractScheduledController this_;
|
||||
Nullable!float time_;
|
||||
}
|
||||
|
||||
void PrepareOperation(ref in ParametersBlock params) {
|
||||
user_vars_.clear();
|
||||
|
||||
auto vars = VarStore(this);
|
||||
params.parameters.
|
||||
filter!(x => x.type == ParameterType.OnceAssign).
|
||||
each !(x => SetParameter(x, vars));
|
||||
}
|
||||
void ProcessOperation(float time, ref in ParametersBlock params) {
|
||||
auto vars = VarStore(this, time.nullable);
|
||||
params.parameters.
|
||||
filter!(x => x.type != ParameterType.OnceAssign).
|
||||
each !(x => SetParameter(x, vars));
|
||||
}
|
||||
void FinalizeOperation(ref in ParametersBlock params) {
|
||||
}
|
||||
|
||||
float GetVariable(string name) const {
|
||||
if (name in user_vars_) return user_vars_[name];
|
||||
return varstore_[name];
|
||||
}
|
||||
void SetParameter(ref in Parameter param, ref in VarStore vars) {
|
||||
(param.name.length >= 2 && param.name[0..2] == "__").
|
||||
enforce("user defined variables must be prefixed '__'");
|
||||
user_vars_[param.name] = 0;
|
||||
param.CalculateParameter(user_vars_[param.name], vars);
|
||||
}
|
||||
|
||||
private:
|
||||
void FinalizeCurrentOperationIfEnded(float time) {
|
||||
if (next_operation_index_ < 1) return;
|
||||
|
||||
const current = &operations_[next_operation_index_-1];
|
||||
if (current.period.end > time) return;
|
||||
|
||||
FinalizeOperation(*current);
|
||||
}
|
||||
void PrepareNextOperationIfStarted(float time) {
|
||||
if (next_operation_index_ >= operations_.length) return;
|
||||
|
||||
const next = &operations_[next_operation_index_];
|
||||
if (next.period.start > time) return;
|
||||
|
||||
++next_operation_index_;
|
||||
PrepareOperation(*next);
|
||||
}
|
||||
void ProcessCurrentOperationIfAvailable(float time) {
|
||||
if (next_operation_index_ < 1) return;
|
||||
|
||||
const current = &operations_[next_operation_index_-1];
|
||||
if (current.period.end <= time) return;
|
||||
|
||||
ProcessOperation(
|
||||
current.period.ConvertToRelativeTime(time), *current);
|
||||
}
|
||||
|
||||
const VarStoreInterface varstore_;
|
||||
|
||||
const ParametersBlock[] operations_;
|
||||
|
||||
size_t next_operation_index_;
|
||||
|
||||
float[string] user_vars_;
|
||||
}
|
@ -7,7 +7,8 @@ import std.algorithm,
|
||||
|
||||
import gl4d;
|
||||
|
||||
import sjplayer.ElementInterface;
|
||||
import sjplayer.ElementDrawerInterface,
|
||||
sjplayer.ElementInterface;
|
||||
|
||||
///
|
||||
class CircleElement : ElementInterface {
|
||||
@ -24,7 +25,8 @@ class CircleElement : ElementInterface {
|
||||
align(1) vec4 color = vec4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
override void Initialize() {
|
||||
///
|
||||
void Initialize() {
|
||||
alive = false;
|
||||
damage = 0;
|
||||
nearness_coe = 0;
|
||||
|
@ -4,6 +4,7 @@ module sjplayer.CircleElementScheduledController;
|
||||
import std.typecons;
|
||||
|
||||
import sjplayer.CircleElement,
|
||||
sjplayer.ElementScheduledControllerFactory,
|
||||
sjplayer.ScheduledController;
|
||||
|
||||
///
|
||||
|
@ -9,6 +9,7 @@ import sjscript;
|
||||
|
||||
import sjplayer.Background,
|
||||
sjplayer.ContextBuilderInterface,
|
||||
sjplayer.ElementDrawerInterface,
|
||||
sjplayer.ElementInterface,
|
||||
sjplayer.ProgramSet,
|
||||
sjplayer.ScheduledControllerInterface,
|
||||
|
@ -1,7 +1,8 @@
|
||||
/// License: MIT
|
||||
module sjplayer.ContextBuilderInterface;
|
||||
|
||||
import sjplayer.ElementInterface,
|
||||
import sjplayer.ElementDrawerInterface,
|
||||
sjplayer.ElementInterface,
|
||||
sjplayer.ScheduledControllerInterface;
|
||||
|
||||
///
|
||||
|
9
sjplayer/src/sjplayer/ElementDrawerInterface.d
Normal file
9
sjplayer/src/sjplayer/ElementDrawerInterface.d
Normal file
@ -0,0 +1,9 @@
|
||||
/// License: MIT
|
||||
module sjplayer.ElementDrawerInterface;
|
||||
|
||||
///
|
||||
interface ElementDrawerInterface {
|
||||
public:
|
||||
///
|
||||
void Draw();
|
||||
}
|
@ -14,16 +14,6 @@ interface ElementInterface {
|
||||
float nearness;
|
||||
}
|
||||
|
||||
///
|
||||
void Initialize();
|
||||
|
||||
///
|
||||
DamageCalculationResult CalculateDamage(vec2 p1, vec2 p2) const;
|
||||
}
|
||||
|
||||
///
|
||||
interface ElementDrawerInterface {
|
||||
public:
|
||||
///
|
||||
void Draw();
|
||||
}
|
||||
|
98
sjplayer/src/sjplayer/ElementScheduledControllerFactory.d
Normal file
98
sjplayer/src/sjplayer/ElementScheduledControllerFactory.d
Normal file
@ -0,0 +1,98 @@
|
||||
/// License: MIT
|
||||
module sjplayer.ElementScheduledControllerFactory;
|
||||
|
||||
import sjscript;
|
||||
|
||||
import std.algorithm,
|
||||
std.array,
|
||||
std.conv,
|
||||
std.meta,
|
||||
std.range.primitives,
|
||||
std.traits;
|
||||
|
||||
import sjplayer.ContextBuilderInterface,
|
||||
sjplayer.ElementDrawerInterface,
|
||||
sjplayer.ElementInterface,
|
||||
sjplayer.ProgramSet,
|
||||
sjplayer.ScheduledControllerInterface,
|
||||
sjplayer.VarStoreInterface,
|
||||
sjplayer.util.Period;
|
||||
|
||||
///
|
||||
struct ElementScheduledControllerFactory(ScheduledController, ElementDrawer)
|
||||
if (is(ScheduledController : ScheduledControllerInterface) &&
|
||||
is(ElementDrawer : ElementDrawerInterface)) {
|
||||
public:
|
||||
/// ScheduledController's first constructor's first argument type.
|
||||
alias Element =
|
||||
Parameters!(__traits(getOverloads, ScheduledController, "__ctor")[0])[0];
|
||||
|
||||
static assert(is(Element : ElementInterface));
|
||||
|
||||
/// ElementDrawer's first constructor's first argument type.
|
||||
alias ElementProgram =
|
||||
Parameters!(__traits(getOverloads, ElementDrawer, "__ctor")[0])[0];
|
||||
|
||||
static assert(staticIndexOf!(
|
||||
ElementProgram, ProgramSet.Programs.Types) >= 0);
|
||||
static assert(is(Element[] :
|
||||
Parameters!(__traits(getOverloads, ElementDrawer, "__ctor")[0])[1]));
|
||||
|
||||
///
|
||||
this(ProgramSet programs, VarStoreInterface varstore) {
|
||||
program_ = programs.Get!ElementProgram;
|
||||
varstore_ = varstore;
|
||||
}
|
||||
|
||||
///
|
||||
void Create(R)(R params, ContextBuilderInterface builder)
|
||||
if (isInputRange!R && is(ElementType!R == ParametersBlock)) {
|
||||
auto parallelized = ParallelizeParams(params);
|
||||
auto elements = appender!(Element[]);
|
||||
|
||||
foreach (ref serial; parallelized) {
|
||||
auto element = new Element;
|
||||
elements ~= element;
|
||||
builder.AddElement(element);
|
||||
builder.AddScheduledController(
|
||||
new ScheduledController(element, varstore_, serial));
|
||||
}
|
||||
if (elements[].length > 0) {
|
||||
builder.AddElementDrawer(new ElementDrawer(program_, elements[]));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static ParametersBlock[][] ParallelizeParams(R)(R params)
|
||||
if (isInputRange!R && is(ElementType!R == ParametersBlock)) {
|
||||
ParametersBlock[][] parallelized;
|
||||
foreach (ref param; params) {
|
||||
auto inserted = false;
|
||||
foreach (ref serial; parallelized) {
|
||||
const found_index = serial.
|
||||
countUntil!(x => x.period.start > param.period.start);
|
||||
const insert_index =
|
||||
found_index >= 0? found_index.to!size_t: serial.length;
|
||||
|
||||
const intersect_prev = insert_index >= 1 &&
|
||||
IsPeriodIntersectedToPeriod(serial[insert_index-1].period, param.period);
|
||||
const intersect_next = insert_index < serial.length &&
|
||||
IsPeriodIntersectedToPeriod(serial[insert_index].period, param.period);
|
||||
|
||||
if (!intersect_prev && !intersect_next) {
|
||||
serial = serial[0..insert_index]~ param ~serial[insert_index..$];
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inserted) {
|
||||
parallelized ~= [param];
|
||||
}
|
||||
}
|
||||
return parallelized;
|
||||
}
|
||||
|
||||
ElementProgram program_;
|
||||
|
||||
VarStoreInterface varstore_;
|
||||
}
|
@ -1,60 +1,51 @@
|
||||
/// License: MIT
|
||||
module sjplayer.ScheduledController;
|
||||
|
||||
import std.algorithm,
|
||||
std.array,
|
||||
std.conv,
|
||||
std.meta,
|
||||
std.range.primitives,
|
||||
std.traits,
|
||||
import std.traits,
|
||||
std.typecons;
|
||||
|
||||
import gl4d;
|
||||
|
||||
import sjscript;
|
||||
|
||||
import sjplayer.ContextBuilderInterface,
|
||||
sjplayer.ElementInterface,
|
||||
sjplayer.ProgramSet,
|
||||
import sjplayer.AbstractScheduledController,
|
||||
sjplayer.ScheduledControllerInterface,
|
||||
sjplayer.VarStoreInterface,
|
||||
sjplayer.util.MatrixFactory,
|
||||
sjplayer.util.Parameter,
|
||||
sjplayer.util.Period;
|
||||
sjplayer.util.Parameter;
|
||||
|
||||
///
|
||||
class ScheduledController(
|
||||
Element, string[string] ParameterNameMap) :
|
||||
AbstractScheduledControllerWithOperationImpl {
|
||||
Target, string[string] ParameterNameMap) : AbstractScheduledController {
|
||||
public:
|
||||
///
|
||||
enum AliveManagementAvailable =
|
||||
is(typeof((Element e) => e.alive)) &&
|
||||
is(ReturnType!((Element e) => e.alive) == bool);
|
||||
is(typeof((Target x) => x.alive)) &&
|
||||
is(ReturnType!((Target x) => x.alive) == bool);
|
||||
///
|
||||
enum MatrixModificationAvailable =
|
||||
is(typeof((Element e) => e.matrix)) &&
|
||||
is(ReturnType!((Element e) => e.matrix) == mat3);
|
||||
is(typeof((Target x) => x.matrix)) &&
|
||||
is(ReturnType!((Target x) => x.matrix) == mat3);
|
||||
///
|
||||
enum AutoInitializationAvailable =
|
||||
is(typeof((Element e) => e.Initialize()));
|
||||
is(typeof((Target x) => x.Initialize()));
|
||||
|
||||
///
|
||||
this(
|
||||
Element element,
|
||||
Target target,
|
||||
in VarStoreInterface varstore,
|
||||
in ParametersBlock[] operations) {
|
||||
super(varstore, operations);
|
||||
element_ = element;
|
||||
target_ = target;
|
||||
}
|
||||
|
||||
protected:
|
||||
override void PrepareOperation(ref in ParametersBlock params) {
|
||||
static if (AutoInitializationAvailable) {
|
||||
element_.Initialize();
|
||||
target_.Initialize();
|
||||
}
|
||||
static if (AliveManagementAvailable) {
|
||||
element_.alive = true;
|
||||
target_.alive = true;
|
||||
}
|
||||
static if (MatrixModificationAvailable) {
|
||||
matrix_factory_ = matrix_factory_.init;
|
||||
@ -64,12 +55,12 @@ class ScheduledController(
|
||||
override void ProcessOperation(float time, ref in ParametersBlock params) {
|
||||
super.ProcessOperation(time, params);
|
||||
static if (MatrixModificationAvailable) {
|
||||
element_.matrix = matrix_factory_.Create().transposed;
|
||||
target_.matrix = matrix_factory_.Create().transposed;
|
||||
}
|
||||
}
|
||||
override void FinalizeOperation(ref in ParametersBlock params) {
|
||||
static if (AliveManagementAvailable) {
|
||||
element_.alive = false;
|
||||
target_.alive = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,17 +68,16 @@ class ScheduledController(
|
||||
switch (name) {
|
||||
static foreach (map_name, code; ParameterNameMap) {
|
||||
case map_name:
|
||||
return mixin("element_."~code);
|
||||
return mixin("target_."~code);
|
||||
}
|
||||
default: return super.GetVariable(name);
|
||||
}
|
||||
}
|
||||
override void SetParameter(Nullable!float time, ref in Parameter param) {
|
||||
auto vars = VarStore(this, time);
|
||||
override void SetParameter(ref in Parameter param, ref in VarStore vars) {
|
||||
switch (param.name) {
|
||||
static foreach (map_name, code; ParameterNameMap) {
|
||||
case map_name:
|
||||
param.CalculateParameter(mixin("element_."~code), vars);
|
||||
param.CalculateParameter(mixin("target_."~code), vars);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
@ -95,90 +85,12 @@ class ScheduledController(
|
||||
static if (MatrixModificationAvailable) {
|
||||
if (param.CalculateMatrixParameter(matrix_factory_, vars)) return;
|
||||
}
|
||||
super.SetParameter(time, param);
|
||||
super.SetParameter(param, vars);
|
||||
}
|
||||
|
||||
Element element_;
|
||||
Target target_;
|
||||
|
||||
static if (MatrixModificationAvailable) {
|
||||
MatrixFactory matrix_factory_;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
struct ElementScheduledControllerFactory(ScheduledController, ElementDrawer)
|
||||
if (is(ScheduledController : ScheduledControllerInterface) &&
|
||||
is(ElementDrawer : ElementDrawerInterface)) {
|
||||
public:
|
||||
/// ScheduledController's first constructor's first argument type.
|
||||
alias Element =
|
||||
Parameters!(__traits(getOverloads, ScheduledController, "__ctor")[0])[0];
|
||||
|
||||
static assert(is(Element : ElementInterface));
|
||||
|
||||
/// ElementDrawer's first constructor's first argument type.
|
||||
alias ElementProgram =
|
||||
Parameters!(__traits(getOverloads, ElementDrawer, "__ctor")[0])[0];
|
||||
|
||||
static assert(staticIndexOf!(
|
||||
ElementProgram, ProgramSet.Programs.Types) >= 0);
|
||||
static assert(is(Element[] :
|
||||
Parameters!(__traits(getOverloads, ElementDrawer, "__ctor")[0])[1]));
|
||||
|
||||
///
|
||||
this(ProgramSet programs, VarStoreInterface varstore) {
|
||||
program_ = programs.Get!ElementProgram;
|
||||
varstore_ = varstore;
|
||||
}
|
||||
|
||||
///
|
||||
void Create(R)(R params, ContextBuilderInterface builder)
|
||||
if (isInputRange!R && is(ElementType!R == ParametersBlock)) {
|
||||
auto parallelized = params.ParallelizeParams();
|
||||
auto elements = appender!(Element[]);
|
||||
|
||||
foreach (ref serial; parallelized) {
|
||||
auto element = new Element;
|
||||
elements ~= element;
|
||||
builder.AddElement(element);
|
||||
builder.AddScheduledController(
|
||||
new ScheduledController(element, varstore_, serial));
|
||||
}
|
||||
if (elements[].length > 0) {
|
||||
builder.AddElementDrawer(new ElementDrawer(program_, elements[]));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ElementProgram program_;
|
||||
VarStoreInterface varstore_;
|
||||
}
|
||||
|
||||
private ParametersBlock[][] ParallelizeParams(R)(R params)
|
||||
if (isInputRange!R && is(ElementType!R == ParametersBlock)) {
|
||||
ParametersBlock[][] parallelized;
|
||||
foreach (ref param; params) {
|
||||
auto inserted = false;
|
||||
foreach (ref serial; parallelized) {
|
||||
const found_index = serial.
|
||||
countUntil!(x => x.period.start > param.period.start);
|
||||
const insert_index =
|
||||
found_index >= 0? found_index.to!size_t: serial.length;
|
||||
|
||||
const intersect_prev = insert_index >= 1 &&
|
||||
IsPeriodIntersectedToPeriod(serial[insert_index-1].period, param.period);
|
||||
const intersect_next = insert_index < serial.length &&
|
||||
IsPeriodIntersectedToPeriod(serial[insert_index].period, param.period);
|
||||
|
||||
if (!intersect_prev && !intersect_next) {
|
||||
serial = serial[0..insert_index]~ param ~serial[insert_index..$];
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inserted) {
|
||||
parallelized ~= [param];
|
||||
}
|
||||
}
|
||||
return parallelized;
|
||||
}
|
||||
|
@ -1,121 +1,9 @@
|
||||
/// License: MIT
|
||||
module sjplayer.ScheduledControllerInterface;
|
||||
|
||||
import std.algorithm,
|
||||
std.array,
|
||||
std.exception,
|
||||
std.format,
|
||||
std.typecons;
|
||||
|
||||
import sjscript;
|
||||
|
||||
import sjplayer.VarStoreInterface,
|
||||
sjplayer.util.Parameter,
|
||||
sjplayer.util.Period;
|
||||
|
||||
///
|
||||
interface ScheduledControllerInterface {
|
||||
public:
|
||||
///
|
||||
void Operate(float time);
|
||||
}
|
||||
|
||||
///
|
||||
abstract class AbstractScheduledController : ScheduledControllerInterface {
|
||||
public:
|
||||
/// The operations must be sorted.
|
||||
this(in ParametersBlock[] operations) {
|
||||
operations_ = operations;
|
||||
}
|
||||
|
||||
override void Operate(float time) {
|
||||
scope(exit) last_operation_time_ = time;
|
||||
|
||||
if (next_operation_index_ >= 1) {
|
||||
assert(next_operation_index_ <= operations_.length);
|
||||
|
||||
const last_operation = &operations_[next_operation_index_-1];
|
||||
const period = last_operation.period;
|
||||
if (IsTimeInPeriod(time, period)) {
|
||||
ProcessOperation(period.ConvertToRelativeTime(time), *last_operation);
|
||||
return;
|
||||
}
|
||||
FinalizeOperation(*last_operation);
|
||||
}
|
||||
|
||||
if (next_operation_index_ >= operations_.length) return;
|
||||
|
||||
const next_operation = &operations_[next_operation_index_];
|
||||
if (IsTimeInPeriod(time, next_operation.period)) {
|
||||
PrepareOperation(*next_operation);
|
||||
ProcessOperation(
|
||||
next_operation.period.ConvertToRelativeTime(time), *next_operation);
|
||||
++next_operation_index_;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
abstract void PrepareOperation(ref in ParametersBlock params);
|
||||
|
||||
abstract void ProcessOperation(float time, ref in ParametersBlock params);
|
||||
|
||||
abstract void FinalizeOperation(ref in ParametersBlock params);
|
||||
|
||||
private:
|
||||
const ParametersBlock[] operations_;
|
||||
|
||||
float last_operation_time_ = -1;
|
||||
|
||||
size_t next_operation_index_;
|
||||
}
|
||||
|
||||
///
|
||||
abstract class AbstractScheduledControllerWithOperationImpl :
|
||||
AbstractScheduledController {
|
||||
public:
|
||||
///
|
||||
this(in VarStoreInterface varstore, in ParametersBlock[] operations) {
|
||||
super(operations);
|
||||
varstore_ = varstore;
|
||||
}
|
||||
|
||||
protected:
|
||||
static struct VarStore {
|
||||
public:
|
||||
float opIndex(string name) {
|
||||
if (!time_.isNull && name == "time") return time_.get;
|
||||
return this_.GetVariable(name);
|
||||
}
|
||||
private:
|
||||
AbstractScheduledControllerWithOperationImpl this_;
|
||||
Nullable!float time_;
|
||||
}
|
||||
|
||||
override void PrepareOperation(ref in ParametersBlock params) {
|
||||
user_vars_.clear();
|
||||
params.parameters.
|
||||
filter!(x => x.type == ParameterType.OnceAssign).
|
||||
each !(x => SetParameter(Nullable!float.init, x));
|
||||
}
|
||||
override void ProcessOperation(float time, ref in ParametersBlock params) {
|
||||
params.parameters.
|
||||
filter!(x => x.type != ParameterType.OnceAssign).
|
||||
each !(x => SetParameter(time.nullable, x));
|
||||
}
|
||||
|
||||
float GetVariable(string name) const {
|
||||
if (name in user_vars_) return user_vars_[name];
|
||||
return varstore_[name];
|
||||
}
|
||||
void SetParameter(Nullable!float time, ref in Parameter param) {
|
||||
(param.name.length >= 2 && param.name[0..2] == "__").
|
||||
enforce("user defined variables must be prefixed '__'");
|
||||
user_vars_[param.name] = 0;
|
||||
param.CalculateParameter(user_vars_[param.name], VarStore(this, time));
|
||||
}
|
||||
|
||||
private:
|
||||
const VarStoreInterface varstore_;
|
||||
|
||||
float[string] user_vars_;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ module sjplayer.util.Period;
|
||||
import sjscript;
|
||||
|
||||
///
|
||||
bool IsTimeInPeriod(float time, in Period period) {
|
||||
bool IsTimeInPeriod(in Period period, float time) {
|
||||
return period.start <= time && time < period.end;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user