[update] Splitted the large source files.

This commit is contained in:
falsycat 2019-10-08 00:00:00 +00:00
parent aa44c004af
commit c760bd6b9b
11 changed files with 241 additions and 234 deletions

View 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_;
}

View File

@ -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;

View File

@ -4,6 +4,7 @@ module sjplayer.CircleElementScheduledController;
import std.typecons;
import sjplayer.CircleElement,
sjplayer.ElementScheduledControllerFactory,
sjplayer.ScheduledController;
///

View File

@ -9,6 +9,7 @@ import sjscript;
import sjplayer.Background,
sjplayer.ContextBuilderInterface,
sjplayer.ElementDrawerInterface,
sjplayer.ElementInterface,
sjplayer.ProgramSet,
sjplayer.ScheduledControllerInterface,

View File

@ -1,7 +1,8 @@
/// License: MIT
module sjplayer.ContextBuilderInterface;
import sjplayer.ElementInterface,
import sjplayer.ElementDrawerInterface,
sjplayer.ElementInterface,
sjplayer.ScheduledControllerInterface;
///

View File

@ -0,0 +1,9 @@
/// License: MIT
module sjplayer.ElementDrawerInterface;
///
interface ElementDrawerInterface {
public:
///
void Draw();
}

View File

@ -14,16 +14,6 @@ interface ElementInterface {
float nearness;
}
///
void Initialize();
///
DamageCalculationResult CalculateDamage(vec2 p1, vec2 p2) const;
}
///
interface ElementDrawerInterface {
public:
///
void Draw();
}

View 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_;
}

View File

@ -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;
}

View File

@ -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_;
}

View File

@ -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;
}