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) pure @safe nothrow { 22 vertexOffsets = vertexOffsets.dup; 23 } 24 25 Deformation opUnary(string op : "-")() @safe pure nothrow { 26 Deformation new_; 27 28 new_.vertexOffsets.length = vertexOffsets.length; 29 foreach(i; 0..vertexOffsets.length) { 30 new_.vertexOffsets[i] = -vertexOffsets[i]; 31 } 32 33 return new_; 34 } 35 36 Deformation opBinary(string op : "*", T)(T other) @safe pure nothrow { 37 static if (is(T == Deformation)) { 38 Deformation new_; 39 40 new_.vertexOffsets.length = vertexOffsets.length; 41 42 foreach(i; 0..vertexOffsets.length) { 43 new_.vertexOffsets[i] = vertexOffsets[i] * other.vertexOffsets[i]; 44 } 45 46 return new_; 47 } else static if (is(T == vec2)) { 48 Deformation new_; 49 50 new_.vertexOffsets.length = vertexOffsets.length; 51 52 foreach(i; 0..vertexOffsets.length) { 53 new_.vertexOffsets[i] = vec2(vertexOffsets[i].x * other.x, vertexOffsets[i].y * other.y); 54 } 55 56 return new_; 57 } else { 58 Deformation new_; 59 60 new_.vertexOffsets.length = vertexOffsets.length; 61 62 foreach(i; 0..vertexOffsets.length) { 63 new_.vertexOffsets[i] = vertexOffsets[i] * other; 64 } 65 66 return new_; 67 } 68 } 69 70 Deformation opBinaryRight(string op : "*", T)(T other) @safe pure nothrow { 71 static if (is(T == Deformation)) { 72 Deformation new_; 73 74 new_.vertexOffsets.length = vertexOffsets.length; 75 76 foreach(i; 0..vertexOffsets.length) { 77 new_.vertexOffsets[i] = other.vertexOffsets[i] * vertexOffsets[i]; 78 } 79 80 return new_; 81 } else static if (is(T == vec2)) { 82 Deformation new_; 83 84 new_.vertexOffsets.length = vertexOffsets.length; 85 86 foreach(i; 0..vertexOffsets.length) { 87 new_.vertexOffsets[i] = vec2(other.x * vertexOffsets[i].x, other.y * vertexOffsets[i].y); 88 } 89 90 return new_; 91 } else { 92 Deformation new_; 93 94 new_.vertexOffsets.length = vertexOffsets.length; 95 96 foreach(i; 0..vertexOffsets.length) { 97 new_.vertexOffsets[i] = other * vertexOffsets[i]; 98 } 99 100 return new_; 101 } 102 } 103 104 Deformation opBinary(string op : "+", T)(T other) @safe pure nothrow { 105 static if (is(T == Deformation)) { 106 Deformation new_; 107 108 new_.vertexOffsets.length = vertexOffsets.length; 109 110 foreach(i; 0..vertexOffsets.length) { 111 new_.vertexOffsets[i] = vertexOffsets[i] + other.vertexOffsets[i]; 112 } 113 114 return new_; 115 } else static if (is(T == vec2)) { 116 Deformation new_; 117 118 new_.vertexOffsets.length = vertexOffsets.length; 119 120 foreach(i; 0..vertexOffsets.length) { 121 new_.vertexOffsets[i] = vec2(vertexOffsets[i].x + other.x, vertexOffsets[i].y + other.y); 122 } 123 124 return new_; 125 } else { 126 Deformation new_; 127 128 new_.vertexOffsets.length = vertexOffsets.length; 129 130 foreach(i; 0..vertexOffsets.length) { 131 new_.vertexOffsets[i] = vertexOffsets[i] + other; 132 } 133 134 return new_; 135 } 136 } 137 138 Deformation opBinary(string op : "-", T)(T other) @safe pure nothrow { 139 static if (is(T == Deformation)) { 140 Deformation new_; 141 142 new_.vertexOffsets.length = vertexOffsets.length; 143 144 foreach(i; 0..vertexOffsets.length) { 145 new_.vertexOffsets[i] = vertexOffsets[i] - other.vertexOffsets[i]; 146 } 147 148 return new_; 149 } else static if (is(T == vec2)) { 150 Deformation new_; 151 152 new_.vertexOffsets.length = vertexOffsets.length; 153 154 foreach(i; 0..vertexOffsets.length) { 155 new_.vertexOffsets[i] = vec2(vertexOffsets[i].x - other.x, vertexOffsets[i].y - other.y); 156 } 157 158 return new_; 159 } else { 160 Deformation new_; 161 162 new_.vertexOffsets.length = vertexOffsets.length; 163 164 foreach(i; 0..vertexOffsets.length) { 165 new_.vertexOffsets[i] = vertexOffsets[i] - other; 166 } 167 168 return new_; 169 } 170 } 171 172 void serialize(S)(ref S serializer) { 173 import inochi2d.math.serialization : serialize; 174 auto state = serializer.arrayBegin(); 175 foreach(offset; vertexOffsets) { 176 serializer.elemBegin; 177 offset.serialize(serializer); 178 } 179 serializer.arrayEnd(state); 180 } 181 182 SerdeException deserializeFromFghj(Fghj data) { 183 import inochi2d.math.serialization : deserialize; 184 foreach(elem; data.byElement()) { 185 vec2 offset; 186 offset.deserialize(elem); 187 188 vertexOffsets ~= offset; 189 } 190 191 return null; 192 } 193 } 194 195 /** 196 A stack of local deformations to apply to the mesh 197 */ 198 struct DeformationStack { 199 private: 200 Drawable parent; 201 202 public: 203 this(Drawable parent) { 204 this.parent = parent; 205 } 206 207 /** 208 Push deformation on to stack 209 */ 210 void push(ref Deformation deformation) { 211 enforce(this.parent.deformation.length == deformation.vertexOffsets.length, "Mismatched lengths"); 212 foreach(i; 0..this.parent.deformation.length) { 213 this.parent.deformation[i] += deformation.vertexOffsets[i]; 214 } 215 this.parent.notifyDeformPushed(deformation); 216 } 217 218 void preUpdate() { 219 foreach(i; 0..this.parent.deformation.length) { 220 this.parent.deformation[i] = vec2(0); 221 } 222 } 223 224 void update() { 225 parent.refreshDeform(); 226 } 227 }