extends VBoxContainer export(Texture) var icon_shown : Texture = preload("res://addons/de.mewin.gduibasics/images/arrow_down.svg") export(Texture) var icon_hidden : Texture = preload("res://addons/de.mewin.gduibasics/images/arrow_right.svg") var child_visible : bool setget _set_child_visible, _get_child_visible var label := "" setget _set_label onready var _header : Control = GDBUtility.find_node_by_name(self, "header") onready var _tex_arrow : TextureRect = GDBUtility.find_node_by_name(self, "tex_arrow") var __last_child : Control = null ############# # overrides # ############# func _ready() -> void: __update_child() _header.label = label func add_child(child : Node, legible_unique_name := false): .add_child(child, legible_unique_name) __update_child() ################ # overridables # ################ func _lazy_load_child() -> Control: return null ################ # public stuff # ################ func toggle() -> void: _set_child_visible(!_get_child_visible()) ################# # private stuff # ################# func _get_child() -> Control: if get_child_count() < 2: return null return get_child(1) as Control func __update_child() -> void: var the_child := _get_child() if the_child == __last_child: return if __last_child: GDBUtility.disconnect_all(__last_child, self) if the_child: the_child.connect("visibility_changed", self, "_on_child_visibility_changed") the_child.connect("tree_exiting", self, "_on_child_tree_exiting") if the_child.visible != _get_child_visible(): emit_signal("child_visibility_changed") __last_child = the_child __update_icon() func __update_icon() -> void: if _get_child_visible(): _tex_arrow.texture = icon_shown else: _tex_arrow.texture = icon_hidden ##################### # setters & getters # ##################### func _set_label(val : String) -> void: label = val if _header: _header.label = val func _set_child_visible(val : bool) -> void: var child := _get_child() if val && !child: child = yield(GDBCoroutine.await(_lazy_load_child()), "completed") if child: emit_signal("child_created", child) child.visible = true add_child(child) return if child && child.visible != val: child.visible = val emit_signal("on_child_visibility_changed") func _get_child_visible() -> bool: var child := _get_child() if child: return child.visible return false ############ # handlers # ############ func _on_header_gui_input(event : InputEvent) -> void: if event is InputEventMouseButton && event.button_index == BUTTON_LEFT && event.pressed: toggle() func _on_child_visibility_changed() -> void: __update_icon() emit_signal("child_visibility_changed") func _on_child_tree_exiting() -> void: var tree := get_tree() if !tree: return yield(tree, "idle_frame") __update_child() ########### # signals # ########### signal child_created(child) signal child_visibility_changed()