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