mirror of
https://codeberg.org/StreamGraph/StreamGraph.git
synced 2024-11-13 19:49:55 +01:00
UX improvements
This commit is contained in:
parent
0d7567e636
commit
6c804851a7
5 changed files with 127 additions and 47 deletions
|
@ -33,6 +33,7 @@ var group_output_node: String
|
|||
#var group_node: String
|
||||
|
||||
var emit_group_signals: bool = true
|
||||
var emit_node_added_signal: bool = true
|
||||
|
||||
## Emitted when a node has been added to this deck.
|
||||
signal node_added(node: DeckNode)
|
||||
|
@ -74,7 +75,9 @@ func add_node_inst(node: DeckNode, assign_id: String = "", assign_to_self: bool
|
|||
nodes[assign_id] = node
|
||||
node._id = assign_id
|
||||
|
||||
node_added.emit(node)
|
||||
if emit_node_added_signal:
|
||||
node_added.emit(node)
|
||||
|
||||
if is_group && emit_group_signals:
|
||||
node_added_to_group.emit(node, node._id, assign_to_self, self)
|
||||
|
||||
|
@ -215,6 +218,7 @@ func group_nodes(nodes_to_group: Array) -> Deck:
|
|||
|
||||
midpoint /= nodes_to_group.size()
|
||||
|
||||
emit_node_added_signal = false
|
||||
var _group_node := add_node_type("group_node")
|
||||
_group_node.group_id = group.id
|
||||
_group_node.group_instance_id = group.instance_id
|
||||
|
@ -222,6 +226,8 @@ func group_nodes(nodes_to_group: Array) -> Deck:
|
|||
_group_node.position.y = midpoint.y
|
||||
_group_node.position_updated.emit(_group_node.position)
|
||||
#group.group_node = _group_node._id
|
||||
node_added.emit(_group_node)
|
||||
emit_node_added_signal = true
|
||||
|
||||
var input_node := group.add_node_type("group_input")
|
||||
var output_node := group.add_node_type("group_output")
|
||||
|
|
|
@ -110,14 +110,18 @@ static func close_all_group_instances(group_id: String) -> void:
|
|||
decks.erase(group_id)
|
||||
|
||||
|
||||
## Unloads a deck.
|
||||
static func close_deck(deck_id: String) -> void:
|
||||
## Unloads a deck. Returns a list of groups that are closed as a result of
|
||||
## closing this deck.
|
||||
static func close_deck(deck_id: String) -> Array:
|
||||
if decks.get(deck_id) is Deck:
|
||||
var deck: Deck = decks[deck_id] as Deck
|
||||
var groups := deck.get_referenced_groups()
|
||||
for group in groups:
|
||||
close_all_group_instances(group)
|
||||
decks.erase(deck_id)
|
||||
return groups
|
||||
|
||||
return []
|
||||
|
||||
|
||||
static func send_event(event_name: StringName, event_data: Dictionary = {}) -> void:
|
||||
|
|
|
@ -62,7 +62,13 @@ func _ready() -> void:
|
|||
|
||||
tab_container.tab_close_requested.connect(
|
||||
func(tab: int):
|
||||
DeckHolder.close_deck(tab_container.get_tab_metadata(tab))
|
||||
var groups := DeckHolder.close_deck(tab_container.get_tab_metadata(tab, "id"))
|
||||
# close tabs associated with this deck's groups
|
||||
for group in groups:
|
||||
for c_tab in tab_container.get_tab_count():
|
||||
if tab_container.get_tab_metadata(c_tab, "id") == group:
|
||||
tab_container.close_tab(tab)
|
||||
await get_tree().process_frame
|
||||
tab_container.close_tab(tab)
|
||||
)
|
||||
|
||||
|
@ -72,7 +78,6 @@ func _ready() -> void:
|
|||
|
||||
Connections.twitch.chat_socket.chat_received_rich.connect(Connections._twitch_chat_received)
|
||||
|
||||
|
||||
file_popup_menu.set_item_shortcut(FileMenuId.NEW, new_deck_shortcut)
|
||||
file_popup_menu.set_item_shortcut(FileMenuId.OPEN, open_deck_shortcut)
|
||||
file_popup_menu.set_item_shortcut(FileMenuId.SAVE, save_deck_shortcut)
|
||||
|
@ -94,14 +99,16 @@ func _on_file_id_pressed(id: int) -> void:
|
|||
open_save_dialog("res://")
|
||||
FileMenuId.CLOSE:
|
||||
close_current_tab()
|
||||
_ when id in range(FileMenuId.RECENTS, FileMenuId.RECENTS + max_recents + 1):
|
||||
open_deck_at_path(file_popup_menu.get_item_text(id))
|
||||
|
||||
## 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.id)
|
||||
tab_container.add_content(inst, "<unsaved deck>")
|
||||
tab_container.set_tab_metadata(tab_container.get_current_tab(), "id", deck.id)
|
||||
inst.group_enter_requested.connect(_on_deck_renderer_group_enter_requested)
|
||||
|
||||
## Closes the current tab in [member tab_container]
|
||||
|
@ -135,22 +142,35 @@ func _on_file_dialog_save_file(path: String) -> void:
|
|||
return
|
||||
|
||||
deck.save_path = path
|
||||
tab_container.set_tab_title(tab_container.get_current_tab(), path.get_file())
|
||||
# TODO: put this into DeckHolder instead
|
||||
var json := JSON.stringify(deck.to_dict(), "\t")
|
||||
var f := FileAccess.open(path, FileAccess.WRITE)
|
||||
f.store_string(json)
|
||||
add_recent_file(get_active_deck().save_path)
|
||||
|
||||
|
||||
## 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))
|
||||
tab_container.set_tab_metadata(tab_container.get_current_tab(), deck.id)
|
||||
inst.initialize_from_deck()
|
||||
inst.group_enter_requested.connect(_on_deck_renderer_group_enter_requested)
|
||||
add_recent_file(path)
|
||||
open_deck_at_path(path)
|
||||
|
||||
|
||||
func open_deck_at_path(path: String) -> void:
|
||||
for tab in tab_container.get_tab_count():
|
||||
if tab_container.get_tab_metadata(tab, "path") == path:
|
||||
tab_container.set_current_tab(tab)
|
||||
return
|
||||
|
||||
var deck := DeckHolder.open_deck_from_file(path)
|
||||
var inst: DeckRendererGraphEdit = DECK_SCENE.instantiate()
|
||||
inst.deck = deck
|
||||
tab_container.add_content(inst, path.get_file())
|
||||
tab_container.set_tab_metadata(tab_container.get_current_tab(), "id", deck.id)
|
||||
inst.initialize_from_deck()
|
||||
inst.group_enter_requested.connect(_on_deck_renderer_group_enter_requested)
|
||||
add_recent_file(path)
|
||||
|
||||
## Gets the currently active [Deck] from [member tab_container]
|
||||
func get_active_deck() -> Deck:
|
||||
|
@ -167,6 +187,7 @@ func save_active_deck() -> void:
|
|||
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)
|
||||
add_recent_file(get_active_deck().save_path)
|
||||
|
||||
## Disconnects the [FileDialog] signals if they are already connected.
|
||||
func disconnect_file_dialog_signals() -> void:
|
||||
|
@ -181,12 +202,16 @@ func disconnect_file_dialog_signals() -> void:
|
|||
## a corresponding tab to [member tab_container]
|
||||
func _on_deck_renderer_group_enter_requested(group_id: String) -> void:
|
||||
#var group_deck := deck.get_group(group_id)
|
||||
for tab in tab_container.get_tab_count():
|
||||
if tab_container.get_tab_metadata(tab, "id") == group_id:
|
||||
tab_container.set_current_tab(tab)
|
||||
return
|
||||
var group_deck := DeckHolder.get_deck(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_id)
|
||||
tab_container.add_content(deck_renderer, "(g) %s" % group_id.left(8))
|
||||
tab_container.set_tab_metadata(tab_container.get_current_tab(), "id", group_id)
|
||||
deck_renderer.group_enter_requested.connect(_on_deck_renderer_group_enter_requested)
|
||||
|
||||
|
||||
|
@ -228,7 +253,7 @@ func _on_debug_decks_viewer_item_pressed(deck_id: String, instance_id: String) -
|
|||
var inst: DeckRendererGraphEdit = DECK_SCENE.instantiate()
|
||||
inst.deck = deck
|
||||
tab_container.add_content(inst, "<Deck %s>" % [deck_id.left(8)])
|
||||
tab_container.set_tab_metadata(tab_container.get_current_tab(), deck.id)
|
||||
tab_container.set_tab_metadata(tab_container.get_current_tab(), "id", deck.id)
|
||||
inst.initialize_from_deck()
|
||||
inst.group_enter_requested.connect(_on_deck_renderer_group_enter_requested)
|
||||
else:
|
||||
|
@ -236,7 +261,7 @@ func _on_debug_decks_viewer_item_pressed(deck_id: String, instance_id: String) -
|
|||
var inst: DeckRendererGraphEdit = DECK_SCENE.instantiate()
|
||||
inst.deck = deck
|
||||
tab_container.add_content(inst, "<Group %s::%s>" % [deck_id.left(8), instance_id.left(8)])
|
||||
tab_container.set_tab_metadata(tab_container.get_current_tab(), deck.id)
|
||||
tab_container.set_tab_metadata(tab_container.get_current_tab(), "id", deck.id)
|
||||
inst.initialize_from_deck()
|
||||
inst.group_enter_requested.connect(_on_deck_renderer_group_enter_requested)
|
||||
|
||||
|
@ -257,11 +282,32 @@ func add_recents_to_menu() -> void:
|
|||
return
|
||||
|
||||
if file_popup_menu.get_item_count() > FileMenuId.RECENTS + 1:
|
||||
for i in range(FileMenuId.RECENTS, file_popup_menu.get_item_count() - FileMenuId.RECENTS + 1):
|
||||
file_popup_menu.remove_item(i)
|
||||
var end := file_popup_menu.get_item_count() - FileMenuId.RECENTS - 1
|
||||
for i in end:
|
||||
file_popup_menu.remove_item(file_popup_menu.get_item_count() - 1)
|
||||
|
||||
for i in recent_files:
|
||||
file_popup_menu.add_item(i)
|
||||
var reduce_length := recent_files.any(func(x: String): return x.length() > 35)
|
||||
|
||||
for i in recent_files.size():
|
||||
var file = recent_files[i] as String
|
||||
if reduce_length:
|
||||
# shorten the basepath to be the first letter of all folders
|
||||
var base: String = Array(
|
||||
file.get_base_dir().split("/", false)
|
||||
).reduce(
|
||||
func(a: String, s: String):
|
||||
return a + s[0] + "/",
|
||||
"/")
|
||||
var filename := file.get_file()
|
||||
file = base.path_join(filename)
|
||||
|
||||
file_popup_menu.add_item(file)
|
||||
var s := Shortcut.new()
|
||||
var k := InputEventKey.new()
|
||||
k.keycode = KEY_1 + i
|
||||
k.ctrl_pressed = true
|
||||
s.events.append(k)
|
||||
file_popup_menu.set_item_shortcut(file_popup_menu.get_item_count() - 1, s)
|
||||
|
||||
RendererPersistence.set_value(PERSISTENCE_NAMESPACE, "config", "recent_files", recent_files)
|
||||
RendererPersistence.commit(PERSISTENCE_NAMESPACE)
|
||||
|
|
|
@ -19,6 +19,8 @@ func _ready() -> void:
|
|||
update_port(port)
|
||||
position_offset_changed.connect(_on_position_offset_changed)
|
||||
node.renamed.connect(_on_node_renamed)
|
||||
if node.node_type == "group_node":
|
||||
get_titlebar_hbox().tooltip_text = "Group %s" % node.group_id.left(8)
|
||||
|
||||
## Connected to [signal GraphElement.position_offset_updated] and updates the
|
||||
## [member node]s properties
|
||||
|
|
|
@ -3,32 +3,34 @@ class_name TabContainerCustom
|
|||
|
||||
## Custom Recreation of [TabContainer] for Flexibility
|
||||
##
|
||||
## Allows for more customizability within the [TabBar] thats used mainly. Extra buttons etc.
|
||||
## Alternative to [TabContainer]. Instead of using the tree hierarchy to add tabs directly,
|
||||
## tabs must be created by script.
|
||||
|
||||
## Reference to the [TabBar] at the top of the Container.
|
||||
## Reference to the [TabBar] at the top of the container.
|
||||
@onready var tab_bar: TabBar = %TabBar
|
||||
## Reference to the [Button] at the end of the [TabBar] that's
|
||||
## used for adding new Tabs
|
||||
## used for adding new tabs.
|
||||
@onready var add_tab_button: Button = %Button
|
||||
## Reference to the [MarginContainer] around the Tabs Contents.
|
||||
## Reference to the [MarginContainer] around the tab's contents.
|
||||
@onready var content_container: MarginContainer = %ContentContainer
|
||||
|
||||
## Emitted when the add [Button] within [member tab_bar] is pressed
|
||||
## Emitted when the add [Button] within [member tab_bar] is pressed.
|
||||
signal add_button_pressed
|
||||
## Emitted when the current tab in [member tab_bar] is changed.
|
||||
signal tab_changed(tab: int)
|
||||
## Emitted when a tab in [member tab_bar] has been closed.
|
||||
## See [signal TabBar.tab_close_requested]
|
||||
signal tab_closed(tab: int)
|
||||
## Emitted when a request to close a tab in the [member tab_bar] has been
|
||||
## requested using [signal TabBar.tab_close_pressed]
|
||||
## Emitted when a request to close a tab in the [member tab_bar] has been requested.
|
||||
signal tab_close_requested(tab: int)
|
||||
## Emitted when the order of the tabs in [member tab_bar] has been changed.
|
||||
signal tab_rearranged(old: int, new: int)
|
||||
|
||||
## Holds the previously active tab in [member tab_bar]
|
||||
# Holds the previously active tab in the internal tab_bar
|
||||
var _previous_active_tab: int = -1
|
||||
|
||||
var _tab_metadata: Dictionary #Dictionary[int -> tab idx, Dictionary[String -> key, Variant]]
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
tab_bar.tab_selected.connect(
|
||||
|
@ -58,44 +60,64 @@ func _ready() -> void:
|
|||
_previous_active_tab = idx_to
|
||||
)
|
||||
|
||||
## Adds the given [Node] as "content" for the given tabs name as a [String]
|
||||
## Adds the given [Node] as the displayed content for a tab.
|
||||
func add_content(c: Node, tab_title: String) -> void:
|
||||
tab_bar.add_tab(tab_title)
|
||||
content_container.add_child(c)
|
||||
tab_bar.set_current_tab(tab_bar.tab_count - 1)
|
||||
|
||||
## Returns the count of tabs in [member tab_bar]
|
||||
|
||||
## Updates the tab at index [param tab_idx]'s title to [param title].
|
||||
func set_tab_title(tab_idx: int, title: String) -> void:
|
||||
tab_bar.set_tab_title(tab_idx, title)
|
||||
|
||||
## Returns the number of tabs.
|
||||
func get_tab_count() -> int:
|
||||
return tab_bar.tab_count
|
||||
|
||||
## Returns [code]true[/code] if [method get_tab_count] returns 0.
|
||||
|
||||
## Returns [code]true[/code] if the tab bar has no tabs.
|
||||
func is_empty() -> bool:
|
||||
return get_tab_count() == 0
|
||||
|
||||
## Closes the tab that is at the given [param tab] in [member tab_bar]
|
||||
|
||||
## Closes a tab at the index [param tab].
|
||||
func close_tab(tab: int) -> void:
|
||||
content_container.get_child(tab).queue_free()
|
||||
if !tab_bar.select_previous_available():
|
||||
tab_bar.select_next_available()
|
||||
tab_bar.remove_tab(tab)
|
||||
_tab_metadata.erase(tab)
|
||||
tab_closed.emit(tab)
|
||||
if tab_bar.tab_count == 0:
|
||||
_previous_active_tab = -1
|
||||
|
||||
## Returns the currently selected tab in [member tab_bar]
|
||||
|
||||
## Returns the currently selected tab.
|
||||
func get_current_tab() -> int:
|
||||
return tab_bar.current_tab
|
||||
|
||||
## Returns the child of [member content_container] at the given [param idx]
|
||||
|
||||
## Sets the current tab to the tab at [param idx].
|
||||
func set_current_tab(idx: int) -> void:
|
||||
tab_bar.current_tab = idx
|
||||
|
||||
|
||||
## Returns the child of [member content_container] at the [param idx].
|
||||
func get_content(idx: int) -> Control:
|
||||
return content_container.get_child(idx)
|
||||
|
||||
## Sets the metadata value for the tab at index [param tab_idx], which can be
|
||||
## retrieved later using [method TabBar.get_tab_metadata()]
|
||||
func set_tab_metadata(tab: int, metadata: Variant) -> void:
|
||||
tab_bar.set_tab_metadata(tab, metadata)
|
||||
|
||||
## Returns the metadata value set to the tab at index [param tab_idx] using set_tab_metadata().
|
||||
## If no metadata was previously set, returns null by default.
|
||||
func get_tab_metadata(tab: int) -> Variant:
|
||||
return tab_bar.get_tab_metadata(tab)
|
||||
## Sets the metadata value for the tab at index [param tab_idx] at [param key], which can be
|
||||
## retrieved later using [method get_tab_metadata].
|
||||
func set_tab_metadata(tab: int, key: String, value: Variant) -> void:
|
||||
var m = _tab_metadata.get(tab, {})
|
||||
m[key] = value
|
||||
_tab_metadata[tab] = m
|
||||
|
||||
|
||||
## Returns the metadata value set to the tab at index [param tab_idx] using [method set_tab_metadata].
|
||||
## If no metadata was previously set, returns [code]null[/code] by default.
|
||||
func get_tab_metadata(tab: int, key: String) -> Variant:
|
||||
var m = _tab_metadata.get(tab, {})
|
||||
return m.get(key)
|
||||
|
|
Loading…
Reference in a new issue