[add] Added ElementScheduledControllerFactory.

This commit is contained in:
falsycat 2019-10-06 00:00:00 +00:00
parent 94efeb6120
commit 4979b7f8fa
2 changed files with 114 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import gl4d;
import sjscript; import sjscript;
import sjplayer.CircleElement, import sjplayer.CircleElement,
sjplayer.ScheduledControllerFactory,
sjplayer.ScheduledControllerInterface, sjplayer.ScheduledControllerInterface,
sjplayer.VarStoreInterface; sjplayer.VarStoreInterface;
@ -46,3 +47,9 @@ class CircleElementScheduledController :
private: private:
CircleElement element_; CircleElement element_;
} }
///
alias CircleElementScheduledControllerFactory =
ElementScheduledControllerFactory!(
CircleElementScheduledController,
CircleElementDrawer);

View File

@ -0,0 +1,107 @@
/// License: MIT
module sjplayer.ScheduledControllerFactory;
import std.algorithm,
std.array,
std.conv,
std.meta,
std.range.primitives,
std.traits;
import sjscript;
import sjplayer.ElementInterface,
sjplayer.ElementProgramSet,
sjplayer.ScheduledControllerInterface,
sjplayer.VarStoreInterface,
sjplayer.util.compare;
///
struct ScheduledControllerCreationResult {
///
ElementInterface[] elements;
///
ScheduledControllerInterface[] controllers;
///
ElementDrawerInterface drawer;
}
///
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, ElementProgramSet.ElementPrograms.Types) >= 0);
static assert(is(Element[] :
Parameters!(__traits(getOverloads, ElementDrawer, "__ctor")[0])[1]));
///
this(ElementProgramSet programs, VarStoreInterface varstore) {
program_ = programs.Get!ElementProgram;
varstore_ = varstore;
}
///
ScheduledControllerCreationResult Create(R)(R params)
if (isInputRange!R && is(ElementType!R == ParametersBlock)) {
auto parallelized = params.ParallelizeParams();
auto elements = appender!(Element[]);
auto controllers = appender!(ScheduledController[]);
foreach (ref serial; parallelized) {
auto element = new Element;
elements ~= element;
controllers ~= new ScheduledController(element, varstore_, serial);
}
return ScheduledControllerCreationResult(
cast(ElementInterface[]) elements[],
cast(ScheduledControllerInterface[]) controllers[],
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;
}