mirror of
https://codeberg.org/StreamGraph/StreamGraph.git
synced 2024-11-13 19:49:55 +01:00
lib group storage rework (#162)
saving decks that use lib groups will no longer save the whole file path to that library (at the expense of the structure needing to be the same) also some ui/ux improvements: - more menus in sidebar remember their collapsed state between deck/node switches - adding a lib group will name the group node appropriately - save dialog properly remembers the most recent path when invoked via ctrl+s and the deck hasn't been saved before Reviewed-on: https://codeberg.org/StreamGraph/StreamGraph/pulls/162 Co-authored-by: Lera Elvoé <yagich@poto.cafe> Co-committed-by: Lera Elvoé <yagich@poto.cafe>
This commit is contained in:
parent
32bda994f6
commit
f720efcc72
7 changed files with 85 additions and 59 deletions
|
@ -175,6 +175,7 @@ func add_lib_group_node(type: String) -> DeckNode:
|
|||
lib.group_output_node = node._id
|
||||
continue
|
||||
group_node.init_io()
|
||||
group_node.rename(NodeDB.get_library_descriptor(type).name)
|
||||
return group_node
|
||||
|
||||
|
||||
|
@ -696,7 +697,7 @@ static func from_dict(data: Dictionary, path: String = "") -> Deck:
|
|||
group = DeckHolder.add_group_from_dict(group_data, group_id, group_instance_id, deck.id)
|
||||
else:
|
||||
group = DeckHolder.add_lib_instance(
|
||||
node.group_id.get_file().trim_suffix(".deck"),
|
||||
node.group_id.get_file(),
|
||||
deck.id,
|
||||
node.group_instance_id
|
||||
)
|
||||
|
|
|
@ -153,8 +153,8 @@ static func add_lib_instance(type: String, to_deck: String, instance_id: String
|
|||
var nd: NodeDB.NodeDescriptor = NodeDB.libraries[type]
|
||||
var path := nd.script_path
|
||||
var deck_data: Dictionary
|
||||
if lib_groups.has(path):
|
||||
deck_data = (lib_groups[path].values()[0] as Deck).to_dict()
|
||||
if lib_groups.has(type):
|
||||
deck_data = (lib_groups[type].values()[0] as Deck).to_dict()
|
||||
else:
|
||||
if not NodeDB.libraries.has(type):
|
||||
return null
|
||||
|
@ -165,17 +165,17 @@ static func add_lib_instance(type: String, to_deck: String, instance_id: String
|
|||
|
||||
deck_data = JSON.parse_string(f.get_as_text())
|
||||
|
||||
var instances := lib_groups.get(path, {}) as Dictionary
|
||||
var instances := lib_groups.get(type, {}) as Dictionary
|
||||
|
||||
var deck := Deck.from_dict(deck_data)
|
||||
deck.id = path
|
||||
deck.id = type
|
||||
deck.instance_id = instance_id
|
||||
deck.is_group = true
|
||||
deck.is_library = true
|
||||
deck._belonging_to = to_deck
|
||||
|
||||
instances[instance_id] = deck
|
||||
lib_groups[path] = instances
|
||||
lib_groups[type] = instances
|
||||
|
||||
print_verbose("DeckHolder: added lib group %s::%s, id %s" % [deck.id, deck.instance_id, deck.get_instance_id()])
|
||||
return deck
|
||||
|
@ -296,20 +296,20 @@ static func pre_exit_cleanup() -> void:
|
|||
static func send_event(event_name: StringName, event_data: Dictionary = {}) -> void:
|
||||
for deck_id: String in decks:
|
||||
if decks[deck_id] is Deck:
|
||||
var deck: Deck = (decks[deck_id] as Deck)
|
||||
var deck: Deck = decks[deck_id]
|
||||
if not is_instance_valid(deck):
|
||||
continue
|
||||
deck.send_event(event_name, event_data)
|
||||
else:
|
||||
for deck_instance_id: String in decks[deck_id]:
|
||||
var deck: Deck = (decks[deck_id][deck_instance_id] as Deck)
|
||||
var deck: Deck = decks[deck_id][deck_instance_id]
|
||||
if not is_instance_valid(deck):
|
||||
continue
|
||||
deck.send_event(event_name, event_data)
|
||||
|
||||
for lib_group_id: String in lib_groups:
|
||||
for lib_instance_id: String in lib_groups[lib_group_id]:
|
||||
var deck: Deck = (lib_groups[lib_group_id][lib_instance_id] as Deck)
|
||||
var deck: Deck = lib_groups[lib_group_id][lib_instance_id]
|
||||
if not is_instance_valid(deck):
|
||||
continue
|
||||
deck.send_event(event_name, event_data)
|
||||
|
|
|
@ -89,7 +89,7 @@ static func create_lib_descriptors(path: String) -> void:
|
|||
if not deck.deck.has("library"):
|
||||
current_file = dir.get_next()
|
||||
continue
|
||||
var type := current_file.trim_suffix(".deck")
|
||||
var type := current_file
|
||||
if nodes.has(type):
|
||||
DeckHolder.logger.toast_error("Library group '%s' collides with a node with the same type." % type)
|
||||
current_file = dir.get_next()
|
||||
|
@ -113,7 +113,8 @@ static func create_lib_descriptors(path: String) -> void:
|
|||
true,
|
||||
true,
|
||||
)
|
||||
libraries[descriptor.type] = descriptor
|
||||
descriptor.added_by_library = path
|
||||
libraries[type] = descriptor
|
||||
current_file = dir.get_next()
|
||||
|
||||
|
||||
|
@ -200,6 +201,10 @@ static func is_library(type: String) -> bool:
|
|||
return libraries.has(type)
|
||||
|
||||
|
||||
static func get_library_descriptor(type: String) -> NodeDescriptor:
|
||||
return libraries.get(type, null) as NodeDescriptor
|
||||
|
||||
|
||||
## Returns a capitalized category string.
|
||||
static func get_category_capitalization(category: String) -> String:
|
||||
return CATEGORY_CAPITALIZATION.get(category, category.capitalize())
|
||||
|
@ -220,8 +225,10 @@ class NodeDescriptor:
|
|||
var category: String
|
||||
## Whether this [DeckNode] reference will appear when searching. See [member DeckNode.appears_in_search].
|
||||
var appears_in_search: bool
|
||||
|
||||
## Whether this describes a library group.
|
||||
var is_library: bool
|
||||
## If [member is_library] is [code]true[/code], this is the index that adds this library.
|
||||
var added_by_library: String
|
||||
|
||||
## Stores the path to this node's script for later instantiation.
|
||||
var script_path: String
|
||||
|
@ -258,6 +265,7 @@ class NodeDescriptor:
|
|||
"category": category,
|
||||
"appears_in_search": appears_in_search,
|
||||
"is_library": is_library,
|
||||
"added_by_library": added_by_library,
|
||||
}
|
||||
return d
|
||||
|
||||
|
@ -274,5 +282,5 @@ class NodeDescriptor:
|
|||
data.get("appears_in_search", false),
|
||||
data.get("is_library", false)
|
||||
)
|
||||
|
||||
nd.added_by_library = data.get("added_by_library", "")
|
||||
return nd
|
||||
|
|
|
@ -69,37 +69,41 @@ func make_unique() -> Deck:
|
|||
|
||||
|
||||
func setup_connections() -> void:
|
||||
input_node.ports_updated.connect(recalculate_ports)
|
||||
output_node.ports_updated.connect(recalculate_ports)
|
||||
if input_node != null:
|
||||
input_node.ports_updated.connect(recalculate_ports)
|
||||
if output_node != null:
|
||||
output_node.ports_updated.connect(recalculate_ports)
|
||||
|
||||
|
||||
func recalculate_ports() -> void:
|
||||
var _values := extra_port_values.duplicate()
|
||||
ports.clear()
|
||||
|
||||
for output_port: Port in output_node.get_input_ports().slice(0, output_node.get_input_ports().size() - 1):
|
||||
var port := add_output_port(
|
||||
output_port.type,
|
||||
output_port.label,
|
||||
output_port.descriptor,
|
||||
output_port.usage_type,
|
||||
)
|
||||
if _values.size() - 1 < port.index:
|
||||
continue
|
||||
if output_node != null:
|
||||
for output_port: Port in output_node.get_input_ports().slice(0, output_node.get_input_ports().size() - 1):
|
||||
var port := add_output_port(
|
||||
output_port.type,
|
||||
output_port.label,
|
||||
output_port.descriptor,
|
||||
output_port.usage_type,
|
||||
)
|
||||
if _values.size() - 1 < port.index:
|
||||
continue
|
||||
|
||||
port.set_value(_values[port.index])
|
||||
port.set_value(_values[port.index])
|
||||
|
||||
for input_port: Port in input_node.get_output_ports().slice(0, input_node.get_output_ports().size() - 1):
|
||||
var port := add_input_port(
|
||||
input_port.type,
|
||||
input_port.label,
|
||||
input_port.descriptor,
|
||||
input_port.usage_type,
|
||||
)
|
||||
if _values.size() - 1 < port.index:
|
||||
continue
|
||||
if input_node != null:
|
||||
for input_port: Port in input_node.get_output_ports().slice(0, input_node.get_output_ports().size() - 1):
|
||||
var port := add_input_port(
|
||||
input_port.type,
|
||||
input_port.label,
|
||||
input_port.descriptor,
|
||||
input_port.usage_type,
|
||||
)
|
||||
if _values.size() - 1 < port.index:
|
||||
continue
|
||||
|
||||
port.set_value(_values[port.index])
|
||||
port.set_value(_values[port.index])
|
||||
|
||||
extra_ports.clear()
|
||||
extra_port_values.clear()
|
||||
|
|
|
@ -40,17 +40,17 @@ func add_category(category_name: String) -> void:
|
|||
|
||||
|
||||
## Add an item to a category.
|
||||
func add_category_item(category: String, item: String, tooltip: String = "", favorite: bool = false, library: bool = false) -> void:
|
||||
func add_category_item(category: String, item: String, type: String, tooltip: String = "", favorite: bool = false, library: bool = false) -> void:
|
||||
var c: Category = categories[category]
|
||||
c.add_item(item, tooltip, favorite, library)
|
||||
c.add_item(item, tooltip, type, favorite, library)
|
||||
|
||||
|
||||
## Wrapper around [method add_category_item] and [method add_category]. Adds an item to a [param category], creating the category if it doesn't exist yet.
|
||||
func add_item(category: String, item: String, tooltip: String = "", favorite: bool = false, library: bool = false) -> void:
|
||||
func add_item(category: String, item: String, type: String, tooltip: String = "", favorite: bool = false, library: bool = false) -> void:
|
||||
if not categories.has(category):
|
||||
add_category(category)
|
||||
|
||||
add_category_item(category, item, tooltip, favorite, library)
|
||||
add_category_item(category, item, type, tooltip, favorite, library)
|
||||
|
||||
|
||||
## Get a [AddNodeMenu.Category] node by its' identifier.
|
||||
|
@ -74,7 +74,7 @@ func search(text: String) -> void:
|
|||
return
|
||||
|
||||
for nd in search_results:
|
||||
add_item(nd.category, nd.name, nd.description, NodeDB.is_node_favorite(nd.type), nd.is_library)
|
||||
add_item(nd.category, nd.name, nd.type, nd.description, NodeDB.is_node_favorite(nd.type), nd.is_library)
|
||||
var c := get_category(nd.category)
|
||||
c.set_item_metadata(c.get_item_count() - 1, "type", nd.type)
|
||||
c.set_item_metadata(c.get_item_count() - 1, "node_descriptor", weakref(nd))
|
||||
|
@ -231,8 +231,8 @@ class Category extends VBoxContainer:
|
|||
|
||||
|
||||
## Add an item to the category.
|
||||
func add_item(p_name: String, p_tooltip: String, p_favorite: bool = false, p_library: bool = false) -> void:
|
||||
var item := CategoryItem.new(p_name, p_tooltip, p_favorite, p_library)
|
||||
func add_item(p_name: String, p_tooltip: String, p_type: String, p_favorite: bool = false, p_library: bool = false) -> void:
|
||||
var item := CategoryItem.new(p_name, p_tooltip, p_favorite, p_library, p_type)
|
||||
item.favorite_toggled.connect(
|
||||
func(toggled: bool):
|
||||
item_favorite_button_toggled.emit(item.get_index(), toggled)
|
||||
|
@ -321,7 +321,7 @@ class CategoryItem extends HBoxContainer:
|
|||
signal favorite_toggled(toggled: bool)
|
||||
|
||||
|
||||
func _init(p_name: String, p_tooltip: String, p_favorite: bool, p_library: bool) -> void:
|
||||
func _init(p_name: String, p_tooltip: String, p_favorite: bool, p_library: bool, p_type: String) -> void:
|
||||
fav_button = Button.new()
|
||||
fav_button.icon = FAVORITE_ICON if p_favorite else NON_FAVORITE_ICON
|
||||
fav_button.toggle_mode = true
|
||||
|
@ -358,11 +358,14 @@ class CategoryItem extends HBoxContainer:
|
|||
inner_hb.add_child(name_button)
|
||||
|
||||
if p_library:
|
||||
var nd := NodeDB.get_library_descriptor(p_type)
|
||||
group_texture_rect = TextureRect.new()
|
||||
group_texture_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||
group_texture_rect.custom_minimum_size = Vector2(12, 12)
|
||||
group_texture_rect.texture = GROUP_ICON
|
||||
group_texture_rect.tooltip_text = "This is a library group. It will create a group node."
|
||||
group_texture_rect.tooltip_text += "\nAdded by %s" % nd.added_by_library
|
||||
|
||||
inner_hb.add_child(group_texture_rect)
|
||||
var m := MarginContainer.new()
|
||||
m.add_theme_constant_override(&"margin_right", 6)
|
||||
|
|
|
@ -324,7 +324,7 @@ func close_tab(tab: int) -> void:
|
|||
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
|
||||
file_dialog.current_path = path if not path.is_empty() else recent_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)
|
||||
|
@ -451,7 +451,8 @@ func save_tab(tab: int) -> void:
|
|||
var renderer := tab_container.get_content(tab) as DeckRendererGraphEdit
|
||||
var deck := renderer.deck
|
||||
if deck.save_path.is_empty():
|
||||
open_save_dialog("res://")
|
||||
#open_save_dialog("res://") # what the fuck?
|
||||
open_save_dialog(tab_container.get_tab_metadata(tab, "path", recent_path))
|
||||
else:
|
||||
var json := JSON.stringify(deck.to_dict(), "\t")
|
||||
var f := FileAccess.open(deck.save_path, FileAccess.WRITE)
|
||||
|
@ -485,7 +486,12 @@ func _on_deck_renderer_group_enter_requested(group_id: String) -> void:
|
|||
var deck_renderer: DeckRendererGraphEdit = DECK_SCENE.instantiate()
|
||||
deck_renderer.deck = group_deck
|
||||
deck_renderer.initialize_from_deck()
|
||||
var tab := tab_container.add_content(deck_renderer, "(g) %s" % group_id.left(8))
|
||||
var title := ""
|
||||
if group_deck.is_library:
|
||||
title = "(L) %s" % group_deck.id
|
||||
else:
|
||||
title = "(G) %s" % group_id.left(8)
|
||||
var tab := tab_container.add_content(deck_renderer, title)
|
||||
tab_container.set_tab_metadata(tab, "id", group_id)
|
||||
tab_container.set_tab_metadata(tab, "group", true)
|
||||
deck_renderer.group_enter_requested.connect(_on_deck_renderer_group_enter_requested)
|
||||
|
|
|
@ -136,6 +136,8 @@ func set_edited_node(id: String = "") -> void:
|
|||
|
||||
|
||||
static func create_menu(title: String, id: String, default_collapsed: bool = false) -> AccordionMenu:
|
||||
if id.is_empty():
|
||||
id = title
|
||||
var res := AccordionMenu.new()
|
||||
res.set_title(title)
|
||||
res.collapsed = collapsed_menus.get(id, default_collapsed)
|
||||
|
@ -190,14 +192,15 @@ class DeckInspector:
|
|||
ref = weakref(DeckHolder.get_deck(id))
|
||||
var deck: Deck = ref.get_ref() as Deck
|
||||
|
||||
var lib_menu := AccordionMenu.new()
|
||||
lib_menu.set_title("Library Group")
|
||||
#var lib_menu := AccordionMenu.new()
|
||||
#lib_menu.set_title("Library Group")
|
||||
var lib_menu := Sidebar.create_menu("Library Group", "lib_group", true)
|
||||
|
||||
var lib_group_text: String
|
||||
if deck.is_library:
|
||||
lib_group_text = "This deck is open as a library group. You may not edit it here.\nTo edit it, you have to open the file it's in."
|
||||
elif not deck.is_group:
|
||||
lib_group_text = "You may save this deck as a Library Group to reuse it in future decks.\nYou may edit how it will appear."
|
||||
lib_group_text = "You may save this deck as a Library Group to reuse it in future decks.\nYou may edit how it will appear in search results."
|
||||
else:
|
||||
lib_group_text = "This deck is a group."
|
||||
|
||||
|
@ -247,8 +250,9 @@ class GroupDescriptorsInspector:
|
|||
func _init(p_deck: Deck) -> void:
|
||||
deck = p_deck
|
||||
|
||||
menu = AccordionMenu.new()
|
||||
menu.set_title("Group Inputs/Outputs")
|
||||
#menu = AccordionMenu.new()
|
||||
#menu.set_title("Group Inputs/Outputs")
|
||||
menu = Sidebar.create_menu("Group Inputs/Outputs", "group_io", true)
|
||||
|
||||
inputs_menu = Sidebar.create_menu("Inputs", "group_inputs", true)
|
||||
outputs_menu = Sidebar.create_menu("Outputs", "group_outputs", true)
|
||||
|
@ -471,14 +475,15 @@ class NodeInspector:
|
|||
func add_port_menu(ports: Array[Port], node: DeckNode) -> void:
|
||||
if ports.is_empty():
|
||||
return
|
||||
var ports_menu := AccordionMenu.new()
|
||||
ports_menu.draw_background = true
|
||||
var is_output := ports[0].port_type == DeckNode.PortType.OUTPUT
|
||||
ports_menu.set_title("Output Ports" if is_output else "Input Ports")
|
||||
var ports_menu := Sidebar.create_menu("Output Ports" if is_output else "Input Ports", "", false)
|
||||
ports_menu.draw_background = true
|
||||
for port in ports:
|
||||
var acc := AccordionMenu.new()
|
||||
#var acc := AccordionMenu.new()
|
||||
var id = "output_%s_menu" if is_output else "input_%s_menu"
|
||||
var acc := Sidebar.create_menu("Port %s" % port.index_of_type, id % port.index_of_type, true)
|
||||
acc.draw_background = true
|
||||
acc.set_title("Port %s" % port.index_of_type)
|
||||
#acc.set_title("Port %s" % port.index_of_type)
|
||||
|
||||
var label_label := DeckInspector.create_label("Name: %s" % port.label)
|
||||
acc.add_child(label_label)
|
||||
|
@ -505,5 +510,4 @@ class NodeInspector:
|
|||
acc.add_child(port_hb)
|
||||
|
||||
ports_menu.add_child(acc)
|
||||
ports_menu.collapsed = true
|
||||
nodes.append(ports_menu)
|
||||
|
|
Loading…
Reference in a new issue