-
Notifications
You must be signed in to change notification settings - Fork 62
/
array_map.gd
151 lines (118 loc) · 3.3 KB
/
array_map.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
tool
class_name ArrayMap
extends Resource
# author: willnationsdev
# license: MIT
# description:
# ArrayMap is a Resource that stores String->Variant pairs.
# Stores an Array of values and a Dictionary of names mapped to their indices.
#
# Because exporting Arrays results in globally shared Array references,
# this simulates all of its data as individual properties.
#
# The above bug is fixed in 4.0 via godotengine/godot#41983.
# internal data
var values := []
var keys := {}
# To more easily identify resource data in git diffs of *.tres files.
export var name := ""
# To accurately store type information.
# Initially empty, but updates during first `insert` after clear.
var _type := TYPE_NIL
var _hint := PROPERTY_HINT_NONE
var _hint_string := ""
func _init(p_name: String = "") -> void:
name = p_name
func has(p_key: String) -> bool:
return keys.has(p_key)
# Does not insert duplicates. Silently replaces record if found.
func insert(p_key: String, p_value) -> void:
if not keys:
# export Array/Dictionary hack
_type = typeof(p_value)
if _type == TYPE_OBJECT and p_value is Resource:
_hint = PROPERTY_HINT_RESOURCE_TYPE
_hint_string = p_value.get_class() # might not work in 4.0
elif _type == TYPE_ARRAY:
_hint = 24 # PROPERTY_HINT_TYPE_STRING
_hint_string = str(typeof(p_value)) + ":"
if keys.has(p_key):
values[keys[p_key]] = p_value
else:
keys[p_key] = values.size()
values.append(p_value)
func erase(p_key: String) -> void:
assert(keys.has(p_key))
values.remove(keys[p_key])
# warning-ignore:return_value_discarded
keys.erase(p_key)
# Getter
func get_value(p_key: String):
assert(keys.has(p_key))
return values[keys[p_key]]
# Finder, slow
func find(p_value) -> String:
for i in values.size():
if p_value == values[i]:
for a_key in keys:
if keys[a_key] == i:
return a_key as String
return ""
# Copied
func keys() -> Array:
return keys.keys()
# Direct reference
func values_ref() -> Array:
return values
# Copied
func dict() -> Dictionary:
var ret := {}
for a_key in keys:
ret[a_key] = values[keys[a_key]]
return ret
func clear() -> void:
values.clear()
keys.clear()
# Export Array/Dictionary hack
func _get_property_list():
var ret := []
for i in values.size():
ret.append({
"name": "values/" + str(i),
"type": _type,
"hint": _hint,
"hint_string": _hint_string,
"usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE
})
for a_key in keys:
ret.append({
"name": "keys/" + str(a_key),
"type": TYPE_INT,
"hint": PROPERTY_HINT_NONE,
"hint_string": "_hint_string",
"usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE
})
return ret
# Export Array/Dictionary hack
func _get(p_name: String):
if p_name.begins_with("values/"):
var i = int(p_name.replace("values/", ""))
if i < values.size() and i >= 0:
return values[i]
if p_name.begins_with("keys/"):
var key = p_name.replace("keys/", "")
if keys.has(key):
return keys[key]
# Export Array/Dictionary hack
func _set(p_name: String, p_value):
if p_name.begins_with("values/"):
var i = int(p_name.replace("values/", ""))
if i < values.size() and i >= 0:
values[i] = p_value
return true
if p_name.begins_with("keys/"):
var key = p_name.replace("keys/", "")
if keys.has(key):
keys[key] = p_value
return true
return false