1 /** 2 Variant hashmap/dictionary type. 3 4 Copyright: 5 Copyright (c) 2007 Juan Linietsky, Ariel Manzur. 6 Copyright (c) 2014 Godot Engine contributors (cf. AUTHORS.md) 7 Copyright (c) 2017 Godot-D contributors 8 Copyright (c) 2022 Godot-DLang contributors 9 10 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License) 11 12 13 */ 14 module godot.dictionary; 15 16 import godot.abi; 17 import godot; 18 import godot.builtins; 19 20 import std.meta; 21 22 /** 23 Associative container which contains values referenced by unique keys. Dictionaries are always passed by reference. 24 */ 25 struct Dictionary { 26 int opApply(int delegate(const(Variant), ref Variant) dg) { 27 28 godot_variant* k; 29 _godot_api.variant_iter_next(&_godot_dictionary, k, null); 30 while (k) { 31 Variant* v = cast(Variant*) _godot_api.dictionary_operator_index( 32 &_godot_dictionary, k); 33 int res = dg(*cast(const(Variant*)) k, *v); 34 if (res) 35 return res; 36 _godot_api.variant_iter_next(&_godot_dictionary, k, null); 37 } 38 return 0; 39 } 40 41 int opApply(int delegate(const(Variant), ref const(Variant)) dg) const { 42 godot_variant* k; 43 _godot_api.variant_iter_next(&_godot_dictionary, k, null); 44 while (k) { 45 Variant* v = cast(Variant*) _godot_api.dictionary_operator_index( 46 cast(godot_dictionary*)&_godot_dictionary, k); 47 int res = dg(*cast(const(Variant*)) k, *v); 48 if (res) 49 return res; 50 _godot_api.variant_iter_next(&_godot_dictionary, k, null); 51 } 52 return 0; 53 } 54 55 //@nogc nothrow: 56 57 package(godot) union dictionary { 58 godot_dictionary _godot_dictionary; 59 Dictionary_Bind _bind; 60 } 61 62 package(godot) dictionary _dictionary; 63 alias _dictionary this; 64 65 @disable this(); 66 67 package(godot) this(godot_dictionary opaque) { 68 _godot_dictionary = opaque; 69 } 70 71 this(this) { 72 const godot_dictionary tmp = _godot_dictionary; 73 _godot_api.variant_new_copy(&_godot_dictionary, &tmp); 74 } 75 76 Dictionary opAssign(in Dictionary other) { 77 _godot_api.variant_destroy(&_godot_dictionary); 78 _godot_api.variant_new_copy(&_godot_dictionary, &other._godot_dictionary); 79 return this; 80 } 81 82 /++ 83 Create a Dictionary and add the key-value pairs $(PARAM args) to it. 84 85 Example: 86 --- 87 Dictionary emptyDictionary = Dictionary.make(); 88 Dictionary status = Dictionary.make(gs!"health", 100, gs!"shields", 75); 89 --- 90 +/ 91 static Dictionary make(Args...)(Args args) 92 if (Args.length % 2 == 0 && allSatisfy!(Variant.compatibleToGodot, Args)) { 93 Dictionary ret = void; 94 //_godot_api.dictionary_new(&ret._godot_dictionary); 95 _godot_api.get_variant_from_type_constructor(GDEXTENSION_VARIANT_TYPE_DICTIONARY)( 96 cast(GDExtensionTypePtr)&ret._godot_dictionary, null); 97 /+ 98 BUG: wtf? when using static foreach(i; 0..Args.length/2): 99 Error: cannot use operator ~= in @nogc delegate godot.dictionary.Dictionary.make!(GodotStringLiteral!"name", String, GodotStringLiteral!"type", int).make.__lambda6 100 +/ 101 static foreach (i, Arg; Args) { 102 static if (i % 2 == 0) { 103 ret[args[i]] = args[i + 1]; 104 } 105 } 106 return ret; 107 } 108 109 /// FIXME: naming convention fail again 110 deprecated("Use Dictionary.make() with 0 args instead.") 111 static Dictionary empty_dictionary() { 112 Dictionary d = void; 113 _godot_api.get_variant_from_type_constructor(GDEXTENSION_VARIANT_TYPE_DICTIONARY)( 114 cast(GDExtensionTypePtr)&d._godot_dictionary, null); 115 return d; 116 } 117 118 void clear() { 119 //auto m =_godot_api.variant_get_ptr_builtin_method(GDEXTENSION_VARIANT_TYPE_DICTIONARY, "clear", 134152229); 120 //m(cast(GDExtensionTypePtr)&_godot_dictionary); 121 _bind.clear(); 122 } 123 124 bool empty() const { 125 //return cast(bool)_godot_api.dictionary_empty(&_godot_dictionary); 126 return _bind.isEmpty(); 127 } 128 129 void erase(K)(in K key) if (is(K : Variant) || Variant.compatibleToGodot!K) { 130 const Variant k = key; 131 //_godot_api.dictionary_erase(&_godot_dictionary, &k._godot_variant); 132 _bind.erase(k); 133 } 134 135 bool has(K)(in K key) const if (is(K : Variant) || Variant.compatibleToGodot!K) { 136 const Variant k = key; 137 return cast(bool) _godot_api.dictionary_has(&_godot_dictionary, &k._godot_variant); 138 } 139 140 bool hasAll(in Array keys) const { 141 //return cast(bool)_godot_api.dictionary_has_all(&_godot_dictionary, &keys._godot_array); 142 return _bind.hasAll(keys); 143 } 144 145 uint hash() const { 146 //return _godot_api.dictionary_hash(&_godot_dictionary); 147 return cast(uint) _bind.hash(); 148 } 149 150 Array keys() const { 151 Array a = void; 152 //a._godot_array = _godot_api.dictionary_keys(&_godot_dictionary); 153 a = _bind.keys(); 154 return a; 155 } 156 157 Variant opIndex(K)(in K key) const 158 if (is(K : Variant) || Variant.compatibleToGodot!K) { 159 const Variant k = key; 160 //Variant ret = void; 161 //ret._godot_variant = _godot_api.dictionary_get(&_godot_dictionary, &k._godot_variant); 162 //return ret; 163 return _bind.get(k, k); 164 } 165 166 void opIndexAssign(K, V)(in auto ref V value, in auto ref K key) 167 if ( 168 (is(K : Variant) || Variant.compatibleToGodot!K) && 169 (is(V 170 : Variant) || Variant.compatibleToGodot!V)) { 171 const Variant k = key; 172 const Variant v = value; 173 auto tmp = _godot_api.dictionary_operator_index(&_godot_dictionary, &k._godot_variant); 174 Variant t = void; 175 t._godot_variant = tmp; 176 t = value; 177 } 178 179 int size() const { 180 //return _godot_api.dictionary_size(&_godot_dictionary); 181 return cast(int) _bind.size; 182 } 183 184 String toJson() const { 185 import godot.json; 186 import godot.api; 187 188 Variant v = void; 189 v._godot_variant = *cast(godot_variant*)&this; 190 JSON json = memnew!JSON(); 191 return json.stringify(v, gs!(`""`), true, false); 192 193 //godot_string s = _godot_api.dictionary_to_json(&_godot_dictionary); 194 //return cast(String)s; 195 } 196 197 Array values() const { 198 //godot_array a = _godot_api.dictionary_values(&_godot_dictionary); 199 //return cast(Array)a; 200 return _bind.values(); 201 } 202 203 ~this() { 204 _godot_api.variant_destroy(&_godot_dictionary); 205 } 206 }