RapidGameFramework
Reusable Godot managers for data-driven small games
Loading...
Searching...
No Matches
render_node_pool.gd
Go to the documentation of this file.
1extends RefCounted
2
3
10
11var parent:Control = null
12var pools := {}
13var used_counts := {}
14var render_index := 0
15var total_acquired:int = 0
16var total_created:int = 0
17var total_reused:int = 0
18var pass_acquired:int = 0
19var pass_created:int = 0
20var pass_reused:int = 0
21var last_hidden:int = 0
22
23
24func begin(next_parent:Control) -> void:
25 parent = next_parent
26 used_counts.clear()
27 render_index = 0
28 pass_acquired = 0
29 pass_created = 0
30 pass_reused = 0
31 last_hidden = 0
32
33
34func end() -> void:
35 for key in pools.keys():
36 var bucket = pools[key]
37 if not bucket is Array:
38 continue
39 var used = int(used_counts.get(key, 0))
40 for index in range(used, bucket.size()):
41 var node = bucket[index]
42 if node is CanvasItem:
43 node.visible = false
44 last_hidden += 1
45
46
47func rect(rect:Rect2, color:Color, name_prefix:String = "Rect") -> ColorRect:
48 var node = _acquire("rect:%s" % name_prefix, name_prefix, func():
49 var created = ColorRect.new()
50 created.mouse_filter = Control.MOUSE_FILTER_IGNORE
51 return created
52 ) as ColorRect
53 node.color = color
54 _apply_control_rect(node, rect)
55 return node
56
57
58func sprite(sprite_manager, sprite_id:String, rect:Rect2, name_prefix:String = "Sprite", options:Dictionary = {}) -> TextureRect:
59 if sprite_id == "" or sprite_manager == null:
60 return null
61 var key = "sprite:%s:%s" % [name_prefix, sprite_id]
62 var node = _acquire(key, name_prefix, func():
63 var created = sprite_manager.create_texture_node(sprite_id, options)
64 if created == null:
65 return null
66 created.mouse_filter = Control.MOUSE_FILTER_IGNORE
67 return created
68 ) as TextureRect
69 if node == null:
70 return null
71 node.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
72 node.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
73 _apply_control_rect(node, rect)
74 return node
75
76
77func label(rect:Rect2, text:String, name_prefix:String = "Label", options:Dictionary = {}) -> Label:
78 var node = _acquire("label:%s" % name_prefix, name_prefix, func():
79 var created = Label.new()
80 created.mouse_filter = Control.MOUSE_FILTER_IGNORE
81 return created
82 ) as Label
83 node.text = text
84 node.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART if bool(options.get("wrap", true)) else TextServer.AUTOWRAP_OFF
85 node.clip_text = true
86 node.max_lines_visible = int(options.get("max_lines", 4))
87 node.horizontal_alignment = int(options.get("horizontal_alignment", HORIZONTAL_ALIGNMENT_LEFT))
88 node.vertical_alignment = int(options.get("vertical_alignment", VERTICAL_ALIGNMENT_TOP))
89 node.add_theme_font_size_override("font_size", int(options.get("font_size", 12)))
90 node.add_theme_color_override("font_color", Color(str(options.get("font_color", "#eef3f8"))))
91 if options.has("outline_color"):
92 node.add_theme_color_override("font_outline_color", Color(str(options.get("outline_color", "#000000"))))
93 node.add_theme_constant_override("outline_size", int(options.get("outline_size", 1)))
94 _apply_control_rect(node, rect)
95 return node
96
97
98func clear() -> void:
99 for bucket in pools.values():
100 if not bucket is Array:
101 continue
102 for node in bucket:
103 if is_instance_valid(node):
104 node.queue_free()
105 pools.clear()
106 used_counts.clear()
107 parent = null
108 render_index = 0
109 total_acquired = 0
110 total_created = 0
111 total_reused = 0
112 pass_acquired = 0
113 pass_created = 0
114 pass_reused = 0
115 last_hidden = 0
116
117
118func get_stats() -> Dictionary:
119 var total := 0
120 var visible := 0
121 for bucket in pools.values():
122 if not bucket is Array:
123 continue
124 total += bucket.size()
125 for node in bucket:
126 if node is CanvasItem and node.visible:
127 visible += 1
128 return {
129 "pools": pools.size(),
130 "nodes": total,
131 "visible": visible,
132 "hidden_last_pass": last_hidden,
133 "pass_acquired": pass_acquired,
134 "pass_created": pass_created,
135 "pass_reused": pass_reused,
136 "total_acquired": total_acquired,
137 "total_created": total_created,
138 "total_reused": total_reused
139 }
140
141
142func _acquire(key:String, name_prefix:String, factory:Callable) -> Control:
143 if parent == null:
144 return null
145 var bucket = pools.get(key, [])
146 var index = int(used_counts.get(key, 0))
147 var node = null
148 if index < bucket.size():
149 node = bucket[index]
150 pass_reused += 1
151 total_reused += 1
152 else:
153 node = factory.call()
154 if node == null:
155 return null
156 bucket.append(node)
157 parent.add_child(node)
158 pools[key] = bucket
159 pass_created += 1
160 total_created += 1
161 used_counts[key] = index + 1
162 pass_acquired += 1
163 total_acquired += 1
164 node.name = name_prefix if index == 0 else "%s%d" % [name_prefix, index]
165 node.visible = true
166 node.mouse_filter = Control.MOUSE_FILTER_IGNORE
167 if node.get_parent() != parent:
168 if node.get_parent() != null:
169 node.get_parent().remove_child(node)
170 parent.add_child(node)
171 parent.move_child(node, min(render_index, parent.get_child_count() - 1))
172 render_index += 1
173 return node
174
175
176func _apply_control_rect(node:Control, rect:Rect2) -> void:
177 node.position = rect.position
178 node.size = rect.size