1 /**
2 * Module for vectors.
3 *
4 * Authors:
5 *   Jacob Jensen
6 * License:
7 *   https://github.com/PoisonEngine/poison-ui/blob/master/LICENSE
8 */
9 module poison.core.vector;
10 
11 /**
12 * Vector mixin template to create vector types.
13 * Params:
14 *   T =     The type of the vector.
15 *   names = The names of all members of the vector.
16 */
17 private mixin template Vector(T, string[] names) {
18   /// Format for members.
19   enum memberFormat = q{
20     private %s _%s;
21   };
22 
23   /// Format for properties.
24   enum propertyFormat = q{
25     @property {
26       public auto %s() { return _%s; }
27 
28       public void %s(%s newValue) { _%s = newValue; }
29     }
30   };
31 
32   /// Format for parameters.
33   enum paramFormat = "%s %s,";
34 
35   /// Format for member sets.
36   enum memberSetFormat = "_%s = %s;";
37 
38   /// Generates the constructor.
39   static string generateConstructor() {
40     import std..string : format;
41 
42     auto paramsString = "";
43     auto memberSetString = "";
44 
45     foreach (name; names) {
46       paramsString ~= paramFormat.format(T.stringof, name);
47 
48       memberSetString ~= memberSetFormat.format(name, name);
49     }
50 
51     if (paramsString) {
52       paramsString.length -= 1;
53     }
54 
55     return "this(" ~ paramsString ~ ") { " ~ memberSetString ~ " }";
56   }
57 
58   mixin(generateConstructor);
59 
60   /// Generates the members.
61   static string generateMembers() {
62     import std..string : format;
63 
64     auto membersString = "";
65 
66     foreach (name; names) {
67       membersString ~= memberFormat.format(T.stringof, name);
68     }
69 
70     return membersString;
71   }
72 
73   mixin(generateMembers);
74 
75   /// Generates the properties.
76   static string generateProperties() {
77     import std..string : format;
78 
79     auto propertiesString = "";
80 
81     foreach (name; names) {
82       propertiesString ~= propertyFormat.format(name, name, name, T.stringof, name);
83     }
84 
85     return propertiesString;
86   }
87 
88   mixin(generateProperties);
89 }
90 
91 /// A 2d point vector.
92 private class Point2dVector(T) {
93   mixin Vector!(T, ["x", "y"]);
94 }
95 
96 /// Alias to create a 2d point vector of ptrdiff_t.
97 public alias Point = Point2dVector!ptrdiff_t;
98 
99 /// Alias to create a 2d point vector of float.
100 public alias PointF = Point2dVector!float;
101 
102 /// A 3d point vector.
103 private class Point3dVector(T) {
104   mixin Vector!(T, ["x", "y", "z"]);
105 }
106 
107 /// Alias to create a 3d point vector of ptrdiff_t.
108 public alias Point3d = Point3dVector!ptrdiff_t;
109 
110 /// Alias to create a 3d point vector of float.
111 public alias Point3dF = Point3dVector!float;
112 
113 /// A 2d size vector.
114 private class Size2dVector(T) {
115   mixin Vector!(T, ["width", "height"]);
116 }
117 
118 /// Alias to create a 2d size vector of size_t.
119 public alias Size = Size2dVector!size_t;
120 
121 /// Alias to create a 2d size vector of float.
122 public alias SizeF = Size2dVector!float;
123 
124 /// A 3d size vector.
125 private class Size3dVector(T) {
126   mixin Vector!(T, ["width", "height", "depth"]);
127 }
128 
129 /// Alias to create a 3d size vector of size_t.
130 public alias Size3d = Size3dVector!size_t;
131 
132 /// Alias to create a 3d size vector of float.
133 public alias Size3dF = Size3dVector!float;
134 
135 /// An edge vector.
136 private class EdgeVector(T) {
137   mixin Vector!(T, ["top", "right", "bottom", "left"]);
138 }
139 
140 /// Alias to create an edge vector of ptrdiff_t.
141 public alias Edge = EdgeVector!ptrdiff_t;
142 
143 /// Alias to create an edge vector of float.
144 public alias EdgeF = EdgeVector!float;