1 /// 2 module glui.utils; 3 4 import raylib; 5 6 import std.meta; 7 import std.functional; 8 9 import glui.style; 10 import glui.structs; 11 12 @safe: 13 14 /// Create a simple node constructor for declarative usage. 15 /// 16 /// Initial properties can be provided in the function provided in the second argument. 17 enum simpleConstructor(T, alias fun = "a") = SimpleConstructor!(T, fun).init; 18 19 /// Create a simple template node constructor for declarative usage. 20 /// 21 /// If the parent is a simple constructor, its initializer will be ran *after* this one. This is because the user 22 /// usually specifies the parent in templates, so it has more importance. 23 /// 24 /// T must be a template accepting a single parameter — Parent type will be passed to it. 25 template simpleConstructor(alias T, alias Parent, alias fun = "a") { 26 27 alias simpleConstructor = simpleConstructor!(T!(Parent.Type), (a) { 28 29 alias initializer = unaryFun!fun; 30 31 initializer(a); 32 Parent.initializer(a); 33 34 }); 35 36 } 37 38 /// ditto 39 alias simpleConstructor(alias T, Parent, alias fun = "a") = simpleConstructor!(T!Parent, fun); 40 41 enum isSimpleConstructor(T) = is(T : SimpleConstructor!(A, a), A, alias a); 42 43 struct SimpleConstructor(T, alias fun = "a") { 44 45 alias Type = T; 46 alias initializer = unaryFun!fun; 47 48 Type opCall(Args...)(Args args) { 49 50 auto result = new Type(args); 51 initializer(result); 52 return result; 53 54 } 55 56 } 57 58 unittest { 59 60 static class Foo { 61 62 string value; 63 64 this() { } 65 66 } 67 68 alias xfoo = simpleConstructor!Foo; 69 assert(xfoo().value == ""); 70 71 alias yfoo = simpleConstructor!(Foo, (a) { 72 a.value = "foo"; 73 }); 74 assert(yfoo().value == "foo"); 75 76 auto myFoo = new Foo; 77 yfoo.initializer(myFoo); 78 assert(myFoo.value == "foo"); 79 80 static class Bar(T) : T { 81 82 int foo; 83 84 this(int foo) { 85 86 this.foo = foo; 87 88 } 89 90 } 91 92 alias xbar(alias T) = simpleConstructor!(Bar, T); 93 94 const barA = xbar!Foo(1); 95 assert(barA.value == ""); 96 assert(barA.foo == 1); 97 98 const barB = xbar!xfoo(2); 99 assert(barB.value == ""); 100 assert(barB.foo == 2); 101 102 const barC = xbar!yfoo(3); 103 assert(barC.value == "foo"); 104 assert(barC.foo == 3); 105 106 } 107 108 // lmao 109 // AliasSeq!(AliasSeq!(T...)) won't work, this is a workaround 110 // too lazy to document, used to generate node constructors with variadic or optional arguments. 111 alias BasicNodeParamLength = Alias!5; 112 template BasicNodeParam(int index) { 113 114 static if (index == 0) alias BasicNodeParam = AliasSeq!(Layout, const Theme); 115 static if (index == 1) alias BasicNodeParam = AliasSeq!(const Theme, Layout); 116 static if (index == 2) alias BasicNodeParam = AliasSeq!(Layout); 117 static if (index == 3) alias BasicNodeParam = AliasSeq!(const Theme); 118 static if (index == 4) alias BasicNodeParam = AliasSeq!(); 119 120 } 121 122 /// Check if the rectangle contains a point. 123 bool contains(Rectangle rectangle, Vector2 point) { 124 125 return rectangle.x <= point.x 126 && point.x < rectangle.x + rectangle.width 127 && rectangle.y <= point.y 128 && point.y < rectangle.y + rectangle.height; 129 130 } 131 132 /// Get names of static fields in the given object. 133 /// 134 /// Ignores deprecated fields. 135 template StaticFieldNames(T) { 136 137 import std.traits : hasStaticMember; 138 import std.meta : Alias, Filter; 139 140 // Prepare data 141 alias Members = __traits(allMembers, T); 142 143 template isStaticMember(string member) { 144 145 enum isStaticMember = 146 147 // Make sure this isn't an alias 148 __traits(compiles, 149 Alias!(__traits(getMember, T, member)) 150 ) 151 152 && !__traits(isDeprecated, __traits(getMember, T, member)) 153 154 // Find the member 155 && hasStaticMember!(T, member); 156 157 } 158 159 // Result 160 alias StaticFieldNames = Filter!(isStaticMember, Members); 161 162 } 163 164 /// Get the current HiDPI scale. Returns Vector2(1, 1) if HiDPI is off. 165 Vector2 hidpiScale() @trusted { 166 167 // HiDPI is on 168 return IsWindowState(ConfigFlags.FLAG_WINDOW_HIGHDPI) 169 ? GetWindowScaleDPI 170 : Vector2.one; 171 172 }