[update] Tidied codes of elements.

This commit is contained in:
falsycat 2019-10-15 00:00:00 +00:00
parent a39c9f5001
commit f5500b0b98
11 changed files with 229 additions and 290 deletions

View File

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

View File

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

View File

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

View File

@ -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",

View File

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

View File

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

View File

@ -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) {
in (shapes.length > 0) {
program_ = program;
elements_ = elements;
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_;

View File

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

View File

@ -1,17 +1,27 @@
/// 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;
///
template ShapeElementScheduledController(Element)
if (is(Element : ElementInterface)) {
alias ShapeElementScheduledController = ScheduledController!(
Element,
[
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",
@ -20,9 +30,118 @@ template ShapeElementScheduledController(Element)
"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_;
}

View File

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

View File

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