1 /*
2     Copyright © 2020, Inochi2D Project
3     Distributed under the 2-Clause BSD License, see LICENSE file.
4     
5     Authors:
6         Luna Nielsen
7         Asahi Lina
8 */
9 module inochi2d.math.transform;
10 public import inochi2d.math;
11 import inochi2d.fmt.serialize;
12 
13 /**
14     A transform
15 */
16 struct Transform {
17 private:
18     @Ignore
19     mat4 trs = mat4.identity;
20 
21 public:
22 
23     /**
24         The translation of the transform
25     */
26     vec3 translation = vec3(0, 0, 0);
27 
28     /**
29         The rotation of the transform
30     */
31     vec3 rotation = vec3(0, 0, 0);//; = quat.identity;
32 
33     /**
34         The scale of the transform
35     */
36     vec2 scale = vec2(1, 1);
37 
38     /**
39         Whether the transform should snap to pixels
40     */
41     bool pixelSnap = false;
42 
43     /**
44         Initialize a transform
45     */
46     this(vec3 translation, vec3 rotation = vec3(0), vec2 scale = vec2(1, 1)) {
47         this.translation = translation;
48         this.rotation = rotation;
49         this.scale = scale;
50     }
51 
52     Transform calcOffset(Transform other) {
53         Transform tnew;
54 
55         tnew.translation = this.translation+other.translation;
56         tnew.rotation = this.rotation+other.rotation;
57         tnew.scale = this.scale*other.scale;
58         tnew.update();
59 
60         return tnew;
61     }
62 
63     /**
64         Returns the result of 2 transforms multiplied together
65     */
66     Transform opBinary(string op : "*")(Transform other) {
67         Transform tnew;
68 
69         mat4 strs = other.trs * this.trs;
70         
71         // TRANSLATION
72         tnew.translation = vec3(strs * vec4(1, 1, 1, 1));
73         
74         // ROTATION
75         tnew.rotation = this.rotation+other.rotation;
76         
77         // SCALE
78         tnew.scale = this.scale*other.scale;
79         tnew.trs = strs;
80         return tnew;
81     }
82 
83     /**
84         Gets the matrix for this transform
85     */
86     @Ignore
87     mat4 matrix() {
88         return trs;
89     }
90 
91     /**
92         Updates the internal matrix of this transform
93     */
94     void update() {
95         trs = 
96             mat4.translation(this.translation) *
97             quat.eulerRotation(this.rotation.x, this.rotation.y, this.rotation.z).toMatrix!(4, 4) *
98             mat4.scaling(this.scale.x, this.scale.y, 1);
99     }
100 
101     void clear() {
102         translation = vec3(0);
103         rotation = vec3(0);
104         scale = vec2(1, 1);
105     }
106 
107     @Ignore
108     string toString() {
109         import std.format : format;
110         return "%s,\n%s,\n%s\n%s".format(trs.toPrettyString, translation.toString, rotation.toString, scale.toString);
111     }
112 
113     void serialize(S)(ref S serializer) {
114         auto state = serializer.objectBegin();
115             serializer.putKey("trans");
116             translation.serialize(serializer);
117 
118             serializer.putKey("rot");
119             rotation.serialize(serializer);
120 
121             serializer.putKey("scale");
122             scale.serialize(serializer);
123 
124         serializer.objectEnd(state);
125     }
126 
127     SerdeException deserializeFromFghj(Fghj data) {
128         translation.deserialize(data["trans"]);
129         rotation.deserialize(data["rot"]);
130         scale.deserialize(data["scale"]);
131         return null;
132     }
133 }
134 /**
135     A 2D transform;
136 */
137 struct Transform2D {
138 private:
139     @Ignore
140     mat3 trs;
141 
142 public:
143     /**
144         Translate
145     */
146     vec2 translation;
147     /**
148         Scale
149     */
150     vec2 scale;
151     
152     /**
153         Rotation
154     */
155     float rotation;
156 
157     /**
158         Gets the matrix for this transform
159     */
160     mat3 matrix() {
161         return trs;
162     }
163 
164     /**
165         Updates the internal matrix of this transform
166     */
167     void update() {
168         mat3 translation_ = mat3.translation(vec3(translation, 0));
169         mat3 rotation_ = mat3.zRotation(rotation);
170         mat3 scale_ = mat3.scaling(scale.x, scale.y, 1);
171         trs =  translation_ * rotation_ * scale_;
172     }
173 
174 }