extends Control class_name DeckHolderRenderer ## Renderer class for [DeckHolder] ## ## Entry point for the [GraphEdit] based Renderer ## Reference to the base scene for [DeckRendererGraphEdit] const DECK_SCENE := preload("res://graph_node_renderer/deck_renderer_graph_edit.tscn") ## Reference to the main windows [TabContainerCustom] @onready var tab_container: TabContainerCustom = %TabContainerCustom as TabContainerCustom ## Reference to the [FileDialog] used for File operations through the program. @onready var file_dialog: FileDialog = $FileDialog ## Enum for storing the Options in the "File" PopupMenu. enum FileMenuId { NEW, OPEN, SAVE = 3, SAVE_AS, CLOSE = 6, } enum ConnectionsMenuId { OBS, } ## Weak Reference to the Deck that is currently going to be saved. var _deck_to_save: WeakRef @onready var no_obsws: NoOBSWS = %NoOBSWS as NoOBSWS @onready var obs_setup_dialog: OBSWebsocketSetupDialog = $OBSWebsocketSetupDialog as OBSWebsocketSetupDialog func _ready() -> void: tab_container.add_button_pressed.connect(add_empty_deck) tab_container.tab_close_requested.connect( func(tab: int): DeckHolder.close_deck(tab_container.get_tab_metadata(tab)) tab_container.close_tab(tab) ) file_dialog.canceled.connect(disconnect_file_dialog_signals) Connections.obs_websocket = no_obsws ## Called when the File button in the [MenuBar] is pressed with the [param id] ## of the button within it that was pressed. func _on_file_id_pressed(id: int) -> void: match id: FileMenuId.NEW: add_empty_deck() FileMenuId.OPEN: open_open_dialog("res://") FileMenuId.SAVE: save_active_deck() FileMenuId.SAVE_AS: open_save_dialog("res://") FileMenuId.CLOSE: close_current_tab() ## Adds an empty [DeckRendererGraphEdit] with a corresponding [Deck] for it's data. func add_empty_deck() -> void: var deck := DeckHolder.add_empty_deck() var inst: DeckRendererGraphEdit = DECK_SCENE.instantiate() inst.deck = deck tab_container.add_content(inst, "Deck %s" % (tab_container.get_tab_count() + 1)) tab_container.set_tab_metadata(tab_container.get_current_tab(), deck) inst.group_enter_requested.connect(_on_deck_renderer_group_enter_requested.bind(deck)) ## Closes the current tab in [member tab_container] func close_current_tab() -> void: tab_container.close_tab(tab_container.get_current_tab()) ## Opens [member file_dialog] with the mode [member FileDialog.FILE_MODE_SAVE_FILE] ## as well as getting a weakref to the active [Deck] func open_save_dialog(path: String) -> void: file_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE file_dialog.title = "Save a Deck" file_dialog.current_path = path _deck_to_save = weakref(get_active_deck()) file_dialog.popup_centered() file_dialog.file_selected.connect(_on_file_dialog_save_file, CONNECT_ONE_SHOT) ## Opens [member file_dialog] with the mode [FileDialog.FILE_MODE_OPEN_FILES] ## with the supplied [param path] func open_open_dialog(path: String) -> void: file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILES file_dialog.title = "Open Deck(s)" file_dialog.current_path = path file_dialog.popup_centered() file_dialog.files_selected.connect(_on_file_dialog_open_files, CONNECT_ONE_SHOT) ## Connected to [signal FileDialog.save_file] on [member file_dialog]. ## Saves the selected [Deck] if it still exists. func _on_file_dialog_save_file(path: String) -> void: var deck: Deck = _deck_to_save.get_ref() as Deck if !deck: return deck.save_path = path var json := JSON.stringify(deck.to_dict(), "\t") var f := FileAccess.open(path, FileAccess.WRITE) f.store_string(json) ## Connected to [signal FileDialog.open_files] on [member file_dialog]. Opens ## the selected paths, instantiating [DeckRenderGraphEdit]s and [Deck]s for each. func _on_file_dialog_open_files(paths: PackedStringArray) -> void: for path in paths: var deck := DeckHolder.open_deck_from_file(path) var inst: DeckRendererGraphEdit = DECK_SCENE.instantiate() inst.deck = deck tab_container.add_content(inst, "Deck %s" % (tab_container.get_tab_count() + 1)) inst.initialize_from_deck() inst.group_enter_requested.connect(_on_deck_renderer_group_enter_requested.bind(deck)) ## Gets the currently active [Deck] from [member tab_container] func get_active_deck() -> Deck: if tab_container.is_empty(): return null 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: if get_active_deck().save_path.is_empty(): open_save_dialog("res://") else: var json := JSON.stringify(get_active_deck().to_dict(), "\t") var f := FileAccess.open(get_active_deck().save_path, FileAccess.WRITE) f.store_string(json) ## Disconnects the [FileDialog] signals if they are already connected. func disconnect_file_dialog_signals() -> void: if file_dialog.file_selected.is_connected(_on_file_dialog_save_file): file_dialog.file_selected.disconnect(_on_file_dialog_save_file) if file_dialog.files_selected.is_connected(_on_file_dialog_open_files): file_dialog.files_selected.disconnect(_on_file_dialog_open_files) ## Connected to [signal DeckRenderGraphEdit.group_entered_request] to allow entering ## groups based off the given [param group_id] and [param deck]. As well as adding ## a corresponding tab to [member tab_container] func _on_deck_renderer_group_enter_requested(group_id: String, deck: Deck) -> void: var group_deck := deck.get_group(group_id) var deck_renderer: DeckRendererGraphEdit = DECK_SCENE.instantiate() deck_renderer.deck = group_deck deck_renderer.initialize_from_deck() tab_container.add_content(deck_renderer, "Group %s" % (tab_container.get_tab_count() + 1)) tab_container.set_tab_metadata(tab_container.get_current_tab(), group_deck) deck_renderer.group_enter_requested.connect(_on_deck_renderer_group_enter_requested.bind(deck_renderer.deck)) func _on_connections_id_pressed(id: int) -> void: match id: ConnectionsMenuId.OBS: obs_setup_dialog.popup_centered() func _on_obs_websocket_setup_dialog_connect_button_pressed(state: OBSWebsocketSetupDialog.ConnectionState) -> void: match state: OBSWebsocketSetupDialog.ConnectionState.DISCONNECTED: obs_setup_dialog.set_button_state(OBSWebsocketSetupDialog.ConnectionState.CONNECTING) no_obsws.connect_to_obsws(obs_setup_dialog.get_port(), obs_setup_dialog.get_password()) await no_obsws.connection_ready obs_setup_dialog.set_button_state(OBSWebsocketSetupDialog.ConnectionState.CONNECTED)