diff --git a/graph_node_renderer/bottom_dock.gd b/graph_node_renderer/bottom_dock.gd index 3a867c2..3632bd5 100644 --- a/graph_node_renderer/bottom_dock.gd +++ b/graph_node_renderer/bottom_dock.gd @@ -4,8 +4,14 @@ extends TabContainer class_name BottomDock -@export var tab_names := ["Console"] +@export var tab_names := ["Console", "Variables"] +@onready var variable_viewer: VariableViewer = %VariableViewer + func _ready() -> void: for i in get_child_count(): set_tab_title(i, tab_names[i]) + + +func rebuild_variable_tree(data: Dictionary) -> void: + variable_viewer.rebuild_variable_tree(data) diff --git a/graph_node_renderer/bottom_dock.tscn b/graph_node_renderer/bottom_dock.tscn index 0778d41..6834156 100644 --- a/graph_node_renderer/bottom_dock.tscn +++ b/graph_node_renderer/bottom_dock.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=3 format=3 uid="uid://dayri1ejk20bc"] +[gd_scene load_steps=4 format=3 uid="uid://dayri1ejk20bc"] [ext_resource type="PackedScene" uid="uid://duvh3r740w2p5" path="res://graph_node_renderer/logger_renderer.tscn" id="1_6yuco"] [ext_resource type="Script" path="res://graph_node_renderer/bottom_dock.gd" id="1_mu1hf"] +[ext_resource type="PackedScene" uid="uid://ovf5nt5pt0oj" path="res://graph_node_renderer/variable_viewer.tscn" id="3_vlkh8"] [node name="BottomDock" type="TabContainer"] offset_right = 122.0 @@ -11,3 +12,8 @@ script = ExtResource("1_mu1hf") [node name="LoggerRenderer" parent="." instance=ExtResource("1_6yuco")] unique_name_in_owner = true layout_mode = 2 + +[node name="VariableViewer" parent="." instance=ExtResource("3_vlkh8")] +unique_name_in_owner = true +visible = false +layout_mode = 2 diff --git a/graph_node_renderer/deck_holder_renderer.gd b/graph_node_renderer/deck_holder_renderer.gd index f5973a1..06f805c 100644 --- a/graph_node_renderer/deck_holder_renderer.gd +++ b/graph_node_renderer/deck_holder_renderer.gd @@ -65,13 +65,14 @@ var _deck_to_save: WeakRef @onready var obs_setup_dialog := $OBSWebsocketSetupDialog as OBSWebsocketSetupDialog @onready var twitch_setup_dialog := $Twitch_Setup_Dialog as TwitchSetupDialog -@onready var bottom_dock: TabContainer = %BottomDock +@onready var bottom_dock: BottomDock = %BottomDock func _ready() -> void: get_tree().auto_accept_quit = false tab_container.add_button_pressed.connect(add_empty_deck) tab_container.tab_changed.connect(_on_tab_container_tab_changed) + tab_container.tab_about_to_change.connect(_on_tab_container_tab_about_to_change) RendererPersistence.init_namespace(PERSISTENCE_NAMESPACE) var embed_subwindows: bool = RendererPersistence.get_or_create(PERSISTENCE_NAMESPACE, "config", "embed_subwindows", true) @@ -115,10 +116,19 @@ func _ready() -> void: file_popup_menu.set_item_shortcut(FileMenuId.CLOSE, close_deck_shortcut) +func _on_tab_container_tab_about_to_change(previous_tab: int) -> void: + var deck := get_deck_at_tab(previous_tab) + if deck.variables_updated.is_connected(bottom_dock.rebuild_variable_tree): + deck.variables_updated.disconnect(bottom_dock.rebuild_variable_tree) + + func _on_tab_container_tab_changed(tab: int) -> void: var is_group = tab_container.get_tab_metadata(tab, "group", false) file_popup_menu.set_item_disabled(FileMenuId.SAVE, is_group) file_popup_menu.set_item_disabled(FileMenuId.SAVE_AS, is_group) + bottom_dock.rebuild_variable_tree(get_active_deck().variable_stack) + var deck := get_active_deck() + deck.variables_updated.connect(bottom_dock.rebuild_variable_tree.bind(deck.variable_stack)) ## Called when the File button in the [MenuBar] is pressed with the [param id] @@ -236,12 +246,18 @@ func open_deck_at_path(path: String) -> void: tab_container.set_current_tab(tab) -## Gets the currently active [Deck] from [member tab_container] +## Returns the current deck in the [member tab_container]. func get_active_deck() -> Deck: + return get_deck_at_tab(tab_container.get_current_tab()) + + +## Returns the deck at [param tab] in the [member tab_container]. +func get_deck_at_tab(tab: int) -> Deck: if tab_container.is_empty(): return null + + return (tab_container.get_content(tab) as DeckRendererGraphEdit).deck - return (tab_container.get_content(tab_container.get_current_tab()) as DeckRendererGraphEdit).deck ## Saves the active [Deck] in [member tab_container] func save_active_deck() -> void: diff --git a/graph_node_renderer/tab_container_custom.gd b/graph_node_renderer/tab_container_custom.gd index 1a331c4..1fbfcf0 100644 --- a/graph_node_renderer/tab_container_custom.gd +++ b/graph_node_renderer/tab_container_custom.gd @@ -21,6 +21,8 @@ class_name TabContainerCustom signal add_button_pressed ## Emitted when the current tab in [member tab_bar] is changed. signal tab_changed(tab: int) +## Emitted just before the current tab in [member tab_bar] is changed.s +signal tab_about_to_change(previous_tab: int) ## Emitted when a tab in [member tab_bar] has been closed. ## See [signal TabBar.tab_close_requested] signal tab_closed(tab: int) @@ -41,6 +43,8 @@ func _ready() -> void: if _previous_active_tab == tab: return + tab_about_to_change.emit(_previous_active_tab) + if _previous_active_tab > -1: content_container.get_child(_previous_active_tab).visible = false content_container.get_child(tab).visible = true diff --git a/graph_node_renderer/variable_viewer.gd b/graph_node_renderer/variable_viewer.gd new file mode 100644 index 0000000..a2fb11a --- /dev/null +++ b/graph_node_renderer/variable_viewer.gd @@ -0,0 +1,32 @@ +# (c) 2023-present Eroax +# (c) 2023-present Yagich +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +extends VBoxContainer +class_name VariableViewer + +@onready var variable_tree: Tree = %VariableTree +var root: TreeItem + +func _ready() -> void: + variable_tree.set_column_title(0, "Name") + variable_tree.set_column_title(1, "Value") + variable_tree.set_column_title(2, "Type") + variable_tree.set_column_expand(1, true) + variable_tree.set_column_expand_ratio(0, 15) + variable_tree.set_column_expand_ratio(1, 70) + variable_tree.set_column_expand_ratio(2, 15) + root = variable_tree.create_item() + rebuild_variable_tree() + + +func rebuild_variable_tree(data: Dictionary = {}) -> void: + #variable_tree.clear() # godot will raw dog a nullptr later if we clear the whole tree + for i in root.get_children(): + i.free() + + for i in data: + var item := variable_tree.create_item(root) + item.set_text(0, i) + item.set_text(1, data[i]) + var type: DeckType.Types = DeckType.INVERSE_GODOT_TYPES_MAP[typeof(data[i])] + item.set_text(2, DeckType.type_str(type)) diff --git a/graph_node_renderer/variable_viewer.tscn b/graph_node_renderer/variable_viewer.tscn new file mode 100644 index 0000000..ad576f8 --- /dev/null +++ b/graph_node_renderer/variable_viewer.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=2 format=3 uid="uid://ovf5nt5pt0oj"] + +[ext_resource type="Script" path="res://graph_node_renderer/variable_viewer.gd" id="1_b5gmj"] + +[node name="VariableViewer" type="VBoxContainer"] +anchors_preset = -1 +anchor_right = 0.182292 +anchor_bottom = 0.123457 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_b5gmj") +metadata/_edit_use_anchors_ = true + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +text = "Deck Variables" + +[node name="VariableTree" type="Tree" parent="."] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +columns = 3 +column_titles_visible = true +allow_search = false +hide_folding = true +hide_root = true