1 /**
2     Vec4
3 
4     Copyright: (c) Enalye 2017
5     License: Zlib
6     Authors: Enalye
7 */
8 
9 module atelier.core.vec4;
10 
11 import bindbc.sdl;
12 
13 import atelier.core.vec2;
14 
15 struct Vec4(T) {
16     static assert(__traits(isArithmetic, T));
17 
18     static if (__traits(isUnsigned, T)) {
19         /// {1, 1, 1, 1} vector. Its length is not one !
20         enum one = Vec4!T(1u, 1u, 1u, 1u);
21         /// Null vector.
22         enum zero = Vec4!T(0u, 0u, 0u, 0u);
23     }
24     else {
25         static if (__traits(isFloating, T)) {
26             /// {1, 1, 1, 1} vector. Its length is not one !
27             enum one = Vec4!T(1f, 1f, 1f, 1f);
28             /// {0.5, 0.5, 0.5, 0.5} vector. Its length is not 0.5 !
29             enum half = Vec4!T(.5f, .5f, .5f, .5f);
30             /// Null vector.
31             enum zero = Vec4!T(0f, 0f, 0f, 0f);
32         }
33         else {
34             /// {1, 1, 1, 1} vector. Its length is not one !
35             enum one = Vec4!T(1, 1, 1, 1);
36             /// Null vector.
37             enum zero = Vec4!T(0, 0, 0, 0);
38         }
39     }
40 
41     T x, y, z, w;
42 
43     @property {
44         Vec2!T xy() const {
45             return Vec2!T(x, y);
46         }
47 
48         Vec2!T xy(Vec2!T v) {
49             x = v.x;
50             y = v.y;
51             return v;
52         }
53 
54         Vec2!T zw() const {
55             return Vec2!T(z, w);
56         }
57 
58         Vec2!T zw(Vec2!T v) {
59             z = v.x;
60             w = v.y;
61             return v;
62         }
63     }
64 
65     this(T nx, T ny, T nz, T nw) {
66         x = nx;
67         y = ny;
68         z = nz;
69         w = nw;
70     }
71 
72     this(Vec2!T nxy, Vec2!T nzw) {
73         x = nxy.x;
74         y = nxy.y;
75         z = nzw.x;
76         w = nzw.y;
77     }
78 
79     void set(T nx, T ny, T nz, T nw) {
80         x = nx;
81         y = ny;
82         z = nz;
83         w = nw;
84     }
85 
86     void set(Vec2!T nxy, Vec2!T nzw) {
87         x = nxy.x;
88         y = nxy.y;
89         z = nzw.x;
90         w = nzw.y;
91     }
92 
93     bool opEquals(const Vec4!T v) const {
94         return (x == v.x) && (y == v.y) && (z == v.z) && (w == v.w);
95     }
96 
97     Vec4!T opUnary(string op)() const {
98         return mixin("Vec4!T(" ~ op ~ " x, " ~ op ~ " y, " ~ op ~ " z, " ~ op ~ " w)");
99     }
100 
101     Vec4!T opBinary(string op)(const Vec4!T v) const {
102         return mixin("Vec4!T(x " ~ op ~ " v.x, y " ~ op ~ " v.y, z " ~ op ~ " v.z, w " ~ op
103                 ~ " v.w)");
104     }
105 
106     Vec4!T opBinary(string op)(T s) const {
107         return mixin("Vec4!T(x " ~ op ~ " s, y " ~ op ~ " s, z " ~ op ~ " s, w " ~ op ~ " s)");
108     }
109 
110     Vec4!T opBinaryRight(string op)(T s) const {
111         return mixin("Vec4!T(s " ~ op ~ " x, s " ~ op ~ " y, s " ~ op ~ " z, s " ~ op ~ "w)");
112     }
113 
114     Vec4!T opOpAssign(string op)(Vec4!T v) {
115         mixin("x = x" ~ op ~ "v.x;y = y" ~ op ~ "v.y;z = z" ~ op ~ "v.z;w = w" ~ op ~ "v.w;");
116         return this;
117     }
118 
119     Vec4!T opOpAssign(string op)(T s) {
120         mixin("x = x" ~ op ~ "s;y = y" ~ op ~ "s;z = z" ~ op ~ "s;w = w" ~ op ~ "s;");
121         return this;
122     }
123 
124     Vec4!U opCast(V : Vec4!U, U)() const {
125         return V(cast(U) x, cast(U) y, cast(U) z, cast(U) w);
126     }
127 
128     static if (__traits(isIntegral, T)) {
129         SDL_Rect toSdlRect() const {
130             SDL_Rect sdlRect = {x, y, z, w};
131             return sdlRect;
132         }
133     }
134 }
135 
136 alias Vec4f = Vec4!(float);
137 alias Vec4i = Vec4!(int);
138 alias Vec4u = Vec4!(uint);