From f5500b0b98b9fb352c6991a0b400b2204c86fc98 Mon Sep 17 00:00:00 2001 From: falsycat Date: Tue, 15 Oct 2019 00:00:00 +0000 Subject: [PATCH] [update] Tidied codes of elements. --- sjplayer/src/sjplayer/AbstractShapeElement.d | 31 ++++ sjplayer/src/sjplayer/CircleElement.d | 33 ++-- .../CircleElementScheduledController.d | 17 -- sjplayer/src/sjplayer/Context.d | 4 +- .../ElementScheduledControllerFactory.d | 98 ----------- sjplayer/src/sjplayer/ScheduledController.d | 51 +----- .../{ElementDrawer.d => ShapeElementDrawer.d} | 33 ++-- sjplayer/src/sjplayer/ShapeElementProgram.d | 27 +-- .../ShapeElementScheduledController.d | 163 +++++++++++++++--- sjplayer/src/sjplayer/SquareElement.d | 45 ++--- .../SquareElementScheduledController.d | 17 -- 11 files changed, 229 insertions(+), 290 deletions(-) create mode 100644 sjplayer/src/sjplayer/AbstractShapeElement.d delete mode 100644 sjplayer/src/sjplayer/CircleElementScheduledController.d delete mode 100644 sjplayer/src/sjplayer/ElementScheduledControllerFactory.d rename sjplayer/src/sjplayer/{ElementDrawer.d => ShapeElementDrawer.d} (57%) delete mode 100644 sjplayer/src/sjplayer/SquareElementScheduledController.d diff --git a/sjplayer/src/sjplayer/AbstractShapeElement.d b/sjplayer/src/sjplayer/AbstractShapeElement.d new file mode 100644 index 0000000..dd7ae7c --- /dev/null +++ b/sjplayer/src/sjplayer/AbstractShapeElement.d @@ -0,0 +1,31 @@ +/// License: MIT +module sjplayer.AbstractShapeElement; + +import gl4d; + +import sjplayer.ElementInterface, + sjplayer.ShapeElementProgram; + +/// +abstract class AbstractShapeElement : ElementInterface { + public: + /// + void Initialize() { + alive = false; + damage = 0; + nearness_coe = 0; + instance = instance.init; + } + + abstract override DamageCalculationResult CalculateDamage(vec2 p1, vec2 p2) const; + + /// + bool alive; + /// + float damage; + /// + float nearness_coe; + /// + ShapeElementProgramInstance instance; + alias instance this; +} diff --git a/sjplayer/src/sjplayer/CircleElement.d b/sjplayer/src/sjplayer/CircleElement.d index 5b819ce..635b169 100644 --- a/sjplayer/src/sjplayer/CircleElement.d +++ b/sjplayer/src/sjplayer/CircleElement.d @@ -6,22 +6,16 @@ import std.algorithm, import gl4d; -import sjplayer.ElementDrawer, +import sjplayer.AbstractShapeElement, sjplayer.ElementInterface, + sjplayer.ShapeElementDrawer, sjplayer.ShapeElementProgram, + sjplayer.ShapeElementScheduledController, sjplayer.util.linalg; /// -class CircleElement : ElementInterface { +class CircleElement : AbstractShapeElement { public: - /// - void Initialize() { - alive = false; - damage = 0; - nearness_coe = 0; - instance = instance.init; - } - override DamageCalculationResult CalculateDamage(vec2 p1, vec2 p2) const { if (!alive) return DamageCalculationResult(0, 0); @@ -35,22 +29,11 @@ class CircleElement : ElementInterface { } return DamageCalculationResult(0, 1 - (d-1).clamp(0, 1)); } - - /// - bool alive; - /// - float damage; - /// - float nearness_coe; - /// - CircleElementProgram.Instance instance; - alias instance this; } /// -alias CircleElementDrawer = ElementDrawer!( +alias CircleElementDrawer = ShapeElementDrawer!( CircleElementProgram, - CircleElement, [vec2(-1, 1), vec2(1, 1), vec2(1, -1), vec2(-1, -1)]); /// @@ -61,3 +44,9 @@ alias CircleElementProgram = ShapeElementProgram!(q{ smoothstep(w-smooth_, w, r) * (1 - smoothstep(1-smooth_, 1, r)); }); + +/// +alias CircleElementScheduledControllerFactory = + ShapeElementScheduledControllerFactory!( + CircleElement, + CircleElementDrawer); diff --git a/sjplayer/src/sjplayer/CircleElementScheduledController.d b/sjplayer/src/sjplayer/CircleElementScheduledController.d deleted file mode 100644 index 04a95f5..0000000 --- a/sjplayer/src/sjplayer/CircleElementScheduledController.d +++ /dev/null @@ -1,17 +0,0 @@ -/// License: MIT -module sjplayer.CircleElementScheduledController; - -import sjplayer.CircleElement, - sjplayer.ElementScheduledControllerFactory, - sjplayer.ScheduledController, - sjplayer.ShapeElementScheduledController; - -/// -alias CircleElementScheduledController = - ShapeElementScheduledController!CircleElement; - -/// -alias CircleElementScheduledControllerFactory = - ElementScheduledControllerFactory!( - CircleElementScheduledController, - CircleElementDrawer); diff --git a/sjplayer/src/sjplayer/Context.d b/sjplayer/src/sjplayer/Context.d index 1472ab0..e845600 100644 --- a/sjplayer/src/sjplayer/Context.d +++ b/sjplayer/src/sjplayer/Context.d @@ -21,7 +21,6 @@ import sjplayer.Actor, sjplayer.PostEffectControllerInterface, sjplayer.ProgramSet, sjplayer.ScheduledControllerInterface, - sjplayer.SquareElementScheduledController, sjplayer.VarStore, sjplayer.VarStoreScheduledController; @@ -38,7 +37,8 @@ class Context { auto varstore = new VarStore(actor_); import sjplayer.BackgroundScheduledController, - sjplayer.CircleElementScheduledController; + sjplayer.CircleElement, + sjplayer.SquareElement; auto factories = tuple( tuple( "actor", diff --git a/sjplayer/src/sjplayer/ElementScheduledControllerFactory.d b/sjplayer/src/sjplayer/ElementScheduledControllerFactory.d deleted file mode 100644 index 1b386d1..0000000 --- a/sjplayer/src/sjplayer/ElementScheduledControllerFactory.d +++ /dev/null @@ -1,98 +0,0 @@ -/// 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_; -} diff --git a/sjplayer/src/sjplayer/ScheduledController.d b/sjplayer/src/sjplayer/ScheduledController.d index b634dfc..7db65c4 100644 --- a/sjplayer/src/sjplayer/ScheduledController.d +++ b/sjplayer/src/sjplayer/ScheduledController.d @@ -1,15 +1,13 @@ /// License: MIT module sjplayer.ScheduledController; -import std.traits, - std.typecons; +import std.typecons; import gl4d; import sjscript; import sjplayer.AbstractScheduledController, - sjplayer.ScheduledControllerInterface, sjplayer.VarStoreInterface, sjplayer.util.Parameter; @@ -17,18 +15,6 @@ import sjplayer.AbstractScheduledController, class ScheduledController( Target, string[string] ParameterNameMap) : AbstractScheduledController { public: - /// - enum AliveManagementAvailable = - is(typeof((Target x) => x.alive)) && - is(ReturnType!((Target x) => x.alive) == bool); - /// - enum MatrixModificationAvailable = - is(typeof((Target x) => x.matrix)) && - is(ReturnType!((Target x) => x.matrix) == mat3); - /// - enum AutoInitializationAvailable = - is(typeof((Target x) => x.Initialize())); - /// this( Target target, @@ -39,30 +25,6 @@ class ScheduledController( } protected: - override void PrepareOperation(ref in ParametersBlock params) { - static if (AutoInitializationAvailable) { - target_.Initialize(); - } - static if (AliveManagementAvailable) { - target_.alive = true; - } - static if (MatrixModificationAvailable) { - matrix_factory_ = matrix_factory_.init; - } - super.PrepareOperation(params); - } - override void ProcessOperation(float time, ref in ParametersBlock params) { - super.ProcessOperation(time, params); - static if (MatrixModificationAvailable) { - target_.matrix = matrix_factory_.Create(); - } - } - override void FinalizeOperation(ref in ParametersBlock params) { - static if (AliveManagementAvailable) { - target_.alive = false; - } - } - override Nullable!float GetVariable(string name) const { switch (name) { static foreach (map_name, code; ParameterNameMap) { @@ -71,10 +33,6 @@ class ScheduledController( } default: } - static if (MatrixModificationAvailable) { - const value = matrix_factory_.GetModelMatrixParameterValueByName(name); - if (!value.isNull) return value; - } return super.GetVariable(name); } override void SetParameter(ref in Parameter param, ref in VarStore vars) { @@ -86,15 +44,8 @@ class ScheduledController( } default: } - static if (MatrixModificationAvailable) { - if (param.CalculateModelMatrixParameter(matrix_factory_, vars)) return; - } super.SetParameter(param, vars); } Target target_; - - static if (MatrixModificationAvailable) { - ModelMatrixFactory!3 matrix_factory_; - } } diff --git a/sjplayer/src/sjplayer/ElementDrawer.d b/sjplayer/src/sjplayer/ShapeElementDrawer.d similarity index 57% rename from sjplayer/src/sjplayer/ElementDrawer.d rename to sjplayer/src/sjplayer/ShapeElementDrawer.d index d053e4c..3136041 100644 --- a/sjplayer/src/sjplayer/ElementDrawer.d +++ b/sjplayer/src/sjplayer/ShapeElementDrawer.d @@ -1,26 +1,28 @@ /// License: MIT -module sjplayer.ElementDrawer; +module sjplayer.ShapeElementDrawer; import std.algorithm, - std.conv; + std.conv, + std.exception; import gl4d; -import sjplayer.ElementDrawerInterface; +import sjplayer.AbstractShapeElement, + sjplayer.ElementDrawerInterface, + sjplayer.ShapeElementProgram; /// -class ElementDrawer(Program, Element, vec2[] vertices) : - ElementDrawerInterface { +class ShapeElementDrawer(Program, vec2[] vertices) : ElementDrawerInterface { public: /// - alias Instance = typeof(Element.instance); + enum MaxInstanceCount = 512; /// - this(Program program, in Element[] elements) + this(Program program, in AbstractShapeElement[] shapes) in (program) - in (elements.length > 0) { - program_ = program; - elements_ = elements; + in (shapes.length > 0) { + program_ = program; + shapes_ = shapes; vao_ = VertexArray.Create(); verts_ = ArrayBuffer.Create(); @@ -41,7 +43,7 @@ class ElementDrawer(Program, Element, vec2[] vertices) : instances_.Bind(); with (ArrayBufferAllocator()) { - size = Instance.sizeof * elements.length; + size = ShapeElementProgramInstance.sizeof * MaxInstanceCount; usage = GL_DYNAMIC_DRAW; Allocate(instances_); } @@ -52,9 +54,10 @@ class ElementDrawer(Program, Element, vec2[] vertices) : instances_.Bind(); { - auto ptr = instances_.MapToWrite!Instance(); - foreach (const element; elements_.filter!"a.alive") { - ptr[alive_count++] = element.instance; + auto ptr = instances_.MapToWrite!ShapeElementProgramInstance(); + foreach (const shape; shapes_.filter!"a.alive") { + enforce(alive_count <= MaxInstanceCount); + ptr[alive_count++] = shape.instance; } } @@ -69,7 +72,7 @@ class ElementDrawer(Program, Element, vec2[] vertices) : private: Program program_; - const Element[] elements_; + const AbstractShapeElement[] shapes_; ArrayBufferRef verts_; ArrayBufferRef instances_; diff --git a/sjplayer/src/sjplayer/ShapeElementProgram.d b/sjplayer/src/sjplayer/ShapeElementProgram.d index 63b9305..39d0f27 100644 --- a/sjplayer/src/sjplayer/ShapeElementProgram.d +++ b/sjplayer/src/sjplayer/ShapeElementProgram.d @@ -8,18 +8,6 @@ import gl4d; /// class ShapeElementProgram(string ShaderSrc) { public: - /// - static struct Instance { - /// - align(1) mat3 matrix = mat3.identity; - /// - align(1) float weight = 1; - /// - align(1) float smooth = 0.001; - /// - align(1) vec4 color = vec4(0, 0, 0, 0); - } - /// enum ShaderHeader = "#version 330 core #extension GL_ARB_explicit_uniform_location : enable"; @@ -91,7 +79,7 @@ class ShapeElementProgram(string ShaderSrc) { type = GL_FLOAT; divisor = 1; - stride = Instance.sizeof; + stride = ShapeElementProgramInstance.sizeof; offset = 0; // matrix @@ -134,3 +122,16 @@ class ShapeElementProgram(string ShaderSrc) { private: ProgramRef program_; } + +/// +struct ShapeElementProgramInstance { + public: + /// + align(1) mat3 matrix = mat3.identity; + /// + align(1) float weight = 1; + /// + align(1) float smooth = 0.001; + /// + align(1) vec4 color = vec4(0, 0, 0, 0); +} diff --git a/sjplayer/src/sjplayer/ShapeElementScheduledController.d b/sjplayer/src/sjplayer/ShapeElementScheduledController.d index d046ff0..3170e97 100644 --- a/sjplayer/src/sjplayer/ShapeElementScheduledController.d +++ b/sjplayer/src/sjplayer/ShapeElementScheduledController.d @@ -1,28 +1,147 @@ /// License: MIT module sjplayer.ShapeElementScheduledController; -import sjplayer.CircleElement, - sjplayer.ElementInterface, - sjplayer.ElementScheduledControllerFactory, - sjplayer.ScheduledController; +import std.algorithm, + std.array, + std.conv, + std.range.primitives, + std.traits, + std.typecons; + +import gl4d; + +import sjscript; + +import sjplayer.AbstractShapeElement, + sjplayer.ContextBuilderInterface, + sjplayer.ProgramSet, + sjplayer.ScheduledController, + sjplayer.ShapeElementScheduledController, + sjplayer.VarStoreInterface, + sjplayer.util.Parameter, + sjplayer.util.Period; + +private enum NameMap = [ + "damage": "damage", + "nearness_coe": "nearness_coe", + "weight": "weight", + "smooth": "smooth", + "color_r": "color.r", + "color_g": "color.g", + "color_b": "color.b", + "color_a": "color.a", +]; /// -template ShapeElementScheduledController(Element) - if (is(Element : ElementInterface)) { - alias ShapeElementScheduledController = ScheduledController!( - Element, - [ - "damage": "damage", - "nearness_coe": "nearness_coe", - "weight": "weight", - "smooth": "smooth", - "color_r": "color.r", - "color_g": "color.g", - "color_b": "color.b", - "color_a": "color.a", - ] - ); - static assert(ShapeElementScheduledController.AliveManagementAvailable); - static assert(ShapeElementScheduledController.MatrixModificationAvailable); - static assert(ShapeElementScheduledController.AutoInitializationAvailable); +class ShapeElementScheduledController : + ScheduledController!(AbstractShapeElement, NameMap) { + public: + /// + this( + AbstractShapeElement shape, + in VarStoreInterface varstore, + in ParametersBlock[] operations) { + super(shape, varstore, operations); + shape_ = shape; + } + + protected: + override void PrepareOperation(ref in ParametersBlock params) { + shape_.Initialize(); + shape_.alive = true; + + matrix_factory_ = matrix_factory_.init; + super.PrepareOperation(params); + } + override void ProcessOperation(float time, ref in ParametersBlock params) { + super.ProcessOperation(time, params); + shape_.matrix = matrix_factory_.Create(); + } + override void FinalizeOperation(ref in ParametersBlock params) { + shape_.alive = false; + } + + override Nullable!float GetVariable(string name) const { + const value = matrix_factory_. + GetModelMatrixParameterValueByName(name); + if (!value.isNull) return value; + + return super.GetVariable(name); + } + override void SetParameter(ref in Parameter param, ref in VarStore vars) { + if (param.CalculateModelMatrixParameter(matrix_factory_, vars)) return; + super.SetParameter(param, vars); + } + + private: + AbstractShapeElement shape_; + + ModelMatrixFactory!3 matrix_factory_; +} + +/// +struct ShapeElementScheduledControllerFactory(ShapeElement, ShapeElementDrawer) + if (is(ShapeElement : AbstractShapeElement)) { + public: + /// + alias ShapeElementProgram = + Parameters!(__traits(getOverloads, ShapeElementDrawer, "__ctor")[0])[0]; + + /// + this(ProgramSet programs, VarStoreInterface varstore) { + program_ = programs.Get!ShapeElementProgram; + varstore_ = varstore; + } + + /// + void Create(R)(R params, ContextBuilderInterface builder) + if (isInputRange!R && is(ElementType!R == ParametersBlock)) { + auto parallelized = ParallelizeParams(params); + auto elements = appender!(ShapeElement[]); + + foreach (ref serial; parallelized) { + auto element = new ShapeElement; + elements ~= element; + builder.AddElement(element); + builder.AddScheduledController( + new ShapeElementScheduledController(element, varstore_, serial)); + } + if (elements[].length > 0) { + builder.AddElementDrawer(new ShapeElementDrawer(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; + } + + ShapeElementProgram program_; + + VarStoreInterface varstore_; } diff --git a/sjplayer/src/sjplayer/SquareElement.d b/sjplayer/src/sjplayer/SquareElement.d index e5ba13d..2da737e 100644 --- a/sjplayer/src/sjplayer/SquareElement.d +++ b/sjplayer/src/sjplayer/SquareElement.d @@ -6,34 +6,16 @@ import std.algorithm, import gl4d; -import sjplayer.ElementDrawer, +import sjplayer.AbstractShapeElement, sjplayer.ElementInterface, + sjplayer.ShapeElementDrawer, + sjplayer.ShapeElementScheduledController, sjplayer.ShapeElementProgram, sjplayer.util.linalg; /// -class SquareElement : ElementInterface { +class SquareElement : AbstractShapeElement { public: - /// - static struct Instance { - /// - align(1) mat3 matrix = mat3.identity; - /// - align(1) float weight = 1; - /// - align(1) float smooth = 0.001; - /// - align(1) vec4 color = vec4(0, 0, 0, 0); - } - - /// - void Initialize() { - alive = false; - damage = 0; - nearness_coe = 0; - instance = instance.init; - } - override DamageCalculationResult CalculateDamage(vec2 p1, vec2 p2) const { if (!alive) return DamageCalculationResult(0, 0); @@ -63,22 +45,11 @@ class SquareElement : ElementInterface { } return DamageCalculationResult(0, 1-(min_distance-1).clamp(0f, 1f)); } - - /// - bool alive; - /// - float damage; - /// - float nearness_coe; - /// - Instance instance; - alias instance this; } /// -alias SquareElementDrawer = ElementDrawer!( +alias SquareElementDrawer = ShapeElementDrawer!( SquareElementProgram, - SquareElement, [vec2(-1, 1), vec2(1, 1), vec2(1, -1), vec2(-1, -1)]); /// @@ -89,3 +60,9 @@ alias SquareElementProgram = ShapeElementProgram!(q{ smoothstep(w-s, w, abs(uv_.x)) + smoothstep(w-s, w, abs(uv_.y)), 0, 1); }); + +/// +alias SquareElementScheduledControllerFactory = + ShapeElementScheduledControllerFactory!( + SquareElement, + SquareElementDrawer); diff --git a/sjplayer/src/sjplayer/SquareElementScheduledController.d b/sjplayer/src/sjplayer/SquareElementScheduledController.d deleted file mode 100644 index aee7e94..0000000 --- a/sjplayer/src/sjplayer/SquareElementScheduledController.d +++ /dev/null @@ -1,17 +0,0 @@ -/// License: MIT -module sjplayer.SquareElementScheduledController; - -import sjplayer.ElementScheduledControllerFactory, - sjplayer.ScheduledController, - sjplayer.ShapeElementScheduledController, - sjplayer.SquareElement; - -/// -alias SquareElementScheduledController = - ShapeElementScheduledController!SquareElement; - -/// -alias SquareElementScheduledControllerFactory = - ElementScheduledControllerFactory!( - SquareElementScheduledController, - SquareElementDrawer);