1 module inochi2d.core.nodes.defstack;
2 import inochi2d.core;
3 import inochi2d.math;
4 import inochi2d;
5 import std.exception : enforce;
6 
7 /**
8     A deformation
9 */
10 struct Deformation {
11 
12     /**
13         Deformed values
14     */
15     vec2[] vertexOffsets;
16 
17     void update(vec2[] points) {
18         vertexOffsets = points.dup;
19     }
20 
21     this(this) {
22         vertexOffsets = vertexOffsets.dup;
23     }
24 
25     Deformation opBinary(string op : "*")(float other) {
26         Deformation new_;
27 
28         new_.vertexOffsets.length = vertexOffsets.length;
29 
30         foreach(i; 0..vertexOffsets.length) {
31             new_.vertexOffsets[i] = vertexOffsets[i] * other;
32         }
33 
34         return new_;
35     }
36 
37     Deformation opBinary(string op : "*")(vec2 scale) {
38         Deformation new_;
39 
40         new_.vertexOffsets.length = vertexOffsets.length;
41 
42         foreach(i; 0..vertexOffsets.length) {
43             new_.vertexOffsets[i] = vec2(vertexOffsets[i].x * scale.x, vertexOffsets[i].y * scale.y);
44         }
45 
46         return new_;
47     }
48 
49     Deformation opBinary(string op : "+")(Deformation other) {
50         assert(vertexOffsets.length == other.vertexOffsets.length);
51 
52         Deformation new_;
53         new_.vertexOffsets.length = vertexOffsets.length;
54 
55         foreach(i; 0..vertexOffsets.length) {
56             new_.vertexOffsets[i] = vertexOffsets[i] + other.vertexOffsets[i];
57         }
58 
59         return new_;
60     }
61 
62     void serialize(S)(ref S serializer) {
63         import inochi2d.math.serialization : serialize;
64         auto state = serializer.arrayBegin();
65             foreach(offset; vertexOffsets) {
66                 serializer.elemBegin;
67                 offset.serialize(serializer);
68             }
69         serializer.arrayEnd(state);
70     }
71 
72     SerdeException deserializeFromFghj(Fghj data) {
73         import inochi2d.math.serialization : deserialize;
74         foreach(elem; data.byElement()) {
75             vec2 offset;
76             offset.deserialize(elem);
77 
78             vertexOffsets ~= offset;
79         }
80 
81         return null;
82     }
83 }
84 
85 /**
86     A stack of local deformations to apply to the mesh
87 */
88 struct DeformationStack {
89 private:
90     Drawable parent;
91 
92 public:
93     this(Drawable parent) {
94         this.parent = parent;
95     }
96 
97     /**
98         Push deformation on to stack
99     */
100     void push(ref Deformation deformation) {
101         enforce(this.parent.deformation.length == deformation.vertexOffsets.length, "Mismatched lengths");
102         foreach(i; 0..this.parent.deformation.length) {
103             this.parent.deformation[i] += deformation.vertexOffsets[i];
104         }
105     }
106     
107     void preUpdate() {
108         foreach(i; 0..this.parent.deformation.length) {
109             this.parent.deformation[i] = vec2(0);
110         }
111     }
112 
113     void update() {
114         parent.refreshDeform();
115     }
116 }