|
|
@@ -26,6 +26,7 @@ var uiscale = 1.0 #tracks scaling for retina screens
|
|
|
#scripts
|
|
|
var open_help
|
|
|
var run_thread
|
|
|
+var save_load
|
|
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
|
func _ready() -> void:
|
|
|
@@ -52,13 +53,16 @@ func _ready() -> void:
|
|
|
$LoadDialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
|
|
|
$LoadDialog.filters = ["*.thd"]
|
|
|
|
|
|
- #connect scripts
|
|
|
+ #load scripts
|
|
|
open_help = preload("res://scenes/main/scripts/open_help.gd").new()
|
|
|
open_help.init(self)
|
|
|
add_child(open_help)
|
|
|
run_thread = preload("res://scenes/main/scripts/run_thread.gd").new()
|
|
|
run_thread.init(self, $ProgressWindow, $ProgressWindow/ProgressLabel, $ProgressWindow/ProgressBar, $GraphEdit, $Console, $Console/ConsoleOutput)
|
|
|
add_child(run_thread)
|
|
|
+ save_load = preload("res://scenes/main/scripts/save_load.gd").new()
|
|
|
+ save_load.init(self, $GraphEdit, Callable(open_help, "show_help_for_node"), Callable(self, "_register_node_movement"), Callable(self, "_register_inputs_in_node"), Callable(self, "link_output"))
|
|
|
+ add_child(save_load)
|
|
|
|
|
|
#Goes through all nodes in scene and checks for buttons in the make_node_buttons group
|
|
|
#Associates all buttons with the _on_button_pressed fuction and passes the button as an argument
|
|
|
@@ -96,7 +100,7 @@ func _ready() -> void:
|
|
|
for arg in args:
|
|
|
var path = arg.strip_edges()
|
|
|
if FileAccess.file_exists(path) and path.get_extension().to_lower() == "thd":
|
|
|
- load_graph_edit(path)
|
|
|
+ save_load.load_graph_edit(path)
|
|
|
break
|
|
|
|
|
|
|
|
|
@@ -237,7 +241,7 @@ func _input(event):
|
|
|
savestate = "saveas"
|
|
|
$SaveDialog.popup_centered()
|
|
|
else:
|
|
|
- save_graph_edit(currentfile)
|
|
|
+ save_load.save_graph_edit(currentfile)
|
|
|
elif event.is_action_pressed("open_explore"):
|
|
|
open_explore()
|
|
|
|
|
|
@@ -667,7 +671,7 @@ func _on_file_button_index_pressed(index: int) -> void:
|
|
|
savestate = "saveas"
|
|
|
$SaveDialog.popup_centered()
|
|
|
else:
|
|
|
- save_graph_edit(currentfile)
|
|
|
+ save_load.save_graph_edit(currentfile)
|
|
|
2:
|
|
|
savestate = "saveas"
|
|
|
$SaveDialog.popup_centered()
|
|
|
@@ -678,179 +682,10 @@ func _on_file_button_index_pressed(index: int) -> void:
|
|
|
else:
|
|
|
$LoadDialog.popup_centered()
|
|
|
|
|
|
-func save_graph_edit(path: String):
|
|
|
- var file = FileAccess.open(path, FileAccess.WRITE)
|
|
|
- if file == null:
|
|
|
- print("Failed to open file for saving")
|
|
|
- return
|
|
|
-
|
|
|
- var node_data_list = []
|
|
|
- var connection_data_list = []
|
|
|
- var node_id_map = {} # Map node name to numeric ID
|
|
|
-
|
|
|
- var node_id = 1
|
|
|
- # Assign each node a unique numeric ID and gather node data
|
|
|
- for node in graph_edit.get_children():
|
|
|
- if node is GraphNode:
|
|
|
- node_id_map[node.name] = node_id
|
|
|
-
|
|
|
- var offset = node.position_offset
|
|
|
- var node_data = {
|
|
|
- "id": node_id,
|
|
|
- "name": node.name,
|
|
|
- "command": node.get_meta("command"),
|
|
|
- "offset": { "x": offset.x, "y": offset.y },
|
|
|
- "slider_values": {},
|
|
|
- "notes": {}
|
|
|
- }
|
|
|
-
|
|
|
- # Save slider values and metadata
|
|
|
- for child in node.find_children("*", "Slider", true, false):
|
|
|
- var relative_path = node.get_path_to(child)
|
|
|
- var path_str = str(relative_path)
|
|
|
-
|
|
|
- node_data["slider_values"][path_str] = {
|
|
|
- "value": child.value,
|
|
|
- "editable": child.editable,
|
|
|
- "meta": {}
|
|
|
- }
|
|
|
- for key in child.get_meta_list():
|
|
|
- node_data["slider_values"][path_str]["meta"][str(key)] = child.get_meta(key)
|
|
|
-
|
|
|
- # Save notes from CodeEdit children
|
|
|
- for child in node.find_children("*", "CodeEdit", true, false):
|
|
|
- node_data["notes"][child.name] = child.text
|
|
|
-
|
|
|
- node_data_list.append(node_data)
|
|
|
- node_id += 1
|
|
|
-
|
|
|
- # Save connections using node IDs instead of names
|
|
|
- for conn in graph_edit.get_connection_list():
|
|
|
- # Map from_node and to_node names to IDs
|
|
|
- var from_id = node_id_map.get(conn["from_node"], null)
|
|
|
- var to_id = node_id_map.get(conn["to_node"], null)
|
|
|
-
|
|
|
- if from_id != null and to_id != null:
|
|
|
- connection_data_list.append({
|
|
|
- "from_node_id": from_id,
|
|
|
- "from_port": conn["from_port"],
|
|
|
- "to_node_id": to_id,
|
|
|
- "to_port": conn["to_port"]
|
|
|
- })
|
|
|
- else:
|
|
|
- print("Warning: Connection references unknown node(s). Skipping connection.")
|
|
|
-
|
|
|
- var graph_data = {
|
|
|
- "nodes": node_data_list,
|
|
|
- "connections": connection_data_list
|
|
|
- }
|
|
|
-
|
|
|
- var json = JSON.new()
|
|
|
- var json_string = json.stringify(graph_data, "\t")
|
|
|
- file.store_string(json_string)
|
|
|
- file.close()
|
|
|
- print("Graph saved.")
|
|
|
- changesmade = false
|
|
|
- get_window().title = "SoundThread - " + path.get_file().trim_suffix(".thd")
|
|
|
-
|
|
|
-
|
|
|
-func load_graph_edit(path: String):
|
|
|
- var file = FileAccess.open(path, FileAccess.READ)
|
|
|
- if file == null:
|
|
|
- print("Failed to open file for loading")
|
|
|
- return
|
|
|
-
|
|
|
- var json_text = file.get_as_text()
|
|
|
- file.close()
|
|
|
-
|
|
|
- var json = JSON.new()
|
|
|
- if json.parse(json_text) != OK:
|
|
|
- print("Error parsing JSON")
|
|
|
- return
|
|
|
-
|
|
|
- var graph_data = json.get_data()
|
|
|
- graph_edit.clear_connections()
|
|
|
-
|
|
|
- # Remove all existing GraphNodes from graph_edit
|
|
|
- for node in graph_edit.get_children():
|
|
|
- if node is GraphNode:
|
|
|
- node.queue_free()
|
|
|
-
|
|
|
- await get_tree().process_frame # Ensure nodes are freed before adding new ones
|
|
|
-
|
|
|
- var id_to_node = {} # Map node IDs to new node instances
|
|
|
|
|
|
- # Recreate nodes and store them by ID
|
|
|
- for node_data in graph_data["nodes"]:
|
|
|
- var command_name = node_data.get("command", "")
|
|
|
- var template = Nodes.get_node_or_null(command_name)
|
|
|
- if not template:
|
|
|
- print("Template not found for command:", command_name)
|
|
|
- continue
|
|
|
-
|
|
|
- var new_node: GraphNode = template.duplicate()
|
|
|
- new_node.name = node_data["name"]
|
|
|
- new_node.position_offset = Vector2(node_data["offset"]["x"], node_data["offset"]["y"])
|
|
|
- new_node.set_meta("command", command_name)
|
|
|
- graph_edit.add_child(new_node)
|
|
|
- new_node.connect("open_help", Callable(open_help, "show_help_for_node"))
|
|
|
- _register_node_movement() # Track node movement changes
|
|
|
-
|
|
|
- id_to_node[node_data["id"]] = new_node
|
|
|
-
|
|
|
- # Restore sliders
|
|
|
- for slider_path_str in node_data["slider_values"]:
|
|
|
- var slider = new_node.get_node_or_null(slider_path_str)
|
|
|
- if slider and (slider is HSlider or slider is VSlider):
|
|
|
- var slider_info = node_data["slider_values"][slider_path_str]
|
|
|
- if typeof(slider_info) == TYPE_DICTIONARY:
|
|
|
- slider.value = slider_info.get("value", slider.value)
|
|
|
- if slider_info.has("editable"):
|
|
|
- slider.editable = slider_info["editable"]
|
|
|
- if slider_info.has("meta"):
|
|
|
- for key in slider_info["meta"]:
|
|
|
- var value = slider_info["meta"][key]
|
|
|
- if key == "brk_data" and typeof(value) == TYPE_ARRAY:
|
|
|
- var new_array: Array = []
|
|
|
- for item in value:
|
|
|
- if typeof(item) == TYPE_STRING:
|
|
|
- var numbers: PackedStringArray = item.strip_edges().trim_prefix("(").trim_suffix(")").split(",")
|
|
|
- if numbers.size() == 2:
|
|
|
- var x = float(numbers[0])
|
|
|
- var y = float(numbers[1])
|
|
|
- new_array.append(Vector2(x, y))
|
|
|
- value = new_array
|
|
|
- slider.set_meta(key, value)
|
|
|
- else:
|
|
|
- slider.value = slider_info
|
|
|
-
|
|
|
- # Restore notes
|
|
|
- for codeedit_name in node_data["notes"]:
|
|
|
- var codeedit = new_node.find_child(codeedit_name, true, false)
|
|
|
- if codeedit and (codeedit is CodeEdit):
|
|
|
- codeedit.text = node_data["notes"][codeedit_name]
|
|
|
-
|
|
|
- _register_inputs_in_node(new_node) # Track slider changes
|
|
|
-
|
|
|
- # Recreate connections by looking up nodes by ID
|
|
|
- for conn in graph_data["connections"]:
|
|
|
- var from_node = id_to_node.get(conn["from_node_id"], null)
|
|
|
- var to_node = id_to_node.get(conn["to_node_id"], null)
|
|
|
-
|
|
|
- if from_node != null and to_node != null:
|
|
|
- graph_edit.connect_node(
|
|
|
- from_node.name, conn["from_port"],
|
|
|
- to_node.name, conn["to_port"]
|
|
|
- )
|
|
|
- else:
|
|
|
- print("Warning: Connection references unknown node ID(s). Skipping connection.")
|
|
|
-
|
|
|
- link_output()
|
|
|
- print("Graph loaded.")
|
|
|
- get_window().title = "SoundThread - " + path.get_file().trim_suffix(".thd")
|
|
|
|
|
|
func _on_save_dialog_file_selected(path: String) -> void:
|
|
|
- save_graph_edit(path) #save file
|
|
|
+ save_load.save_graph_edit(path) #save file
|
|
|
#check what the user was trying to do before save and do that action
|
|
|
if savestate == "newfile":
|
|
|
new_patch()
|
|
|
@@ -859,7 +694,7 @@ func _on_save_dialog_file_selected(path: String) -> void:
|
|
|
$LoadDialog.popup_centered()
|
|
|
elif savestate == "helpfile":
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit(helpfile)
|
|
|
+ save_load.load_graph_edit(helpfile)
|
|
|
elif savestate == "quit":
|
|
|
await get_tree().create_timer(0.25).timeout #little pause so that it feels like it actually saved even though it did
|
|
|
get_tree().quit()
|
|
|
@@ -869,7 +704,7 @@ func _on_save_dialog_file_selected(path: String) -> void:
|
|
|
|
|
|
func _on_load_dialog_file_selected(path: String) -> void:
|
|
|
currentfile = path #tracking path here only means "save" only saves patches the user has loaded rather than overwriting help files
|
|
|
- load_graph_edit(path)
|
|
|
+ save_load.load_graph_edit(path)
|
|
|
|
|
|
func _on_help_button_index_pressed(index: int) -> void:
|
|
|
match index:
|
|
|
@@ -882,7 +717,7 @@ func _on_help_button_index_pressed(index: int) -> void:
|
|
|
$SaveChangesPopup.popup_centered()
|
|
|
else:
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit("res://examples/getting_started.thd")
|
|
|
+ save_load.load_graph_edit("res://examples/getting_started.thd")
|
|
|
2:
|
|
|
if changesmade == true:
|
|
|
savestate = "helpfile"
|
|
|
@@ -890,7 +725,7 @@ func _on_help_button_index_pressed(index: int) -> void:
|
|
|
$SaveChangesPopup.popup_centered()
|
|
|
else:
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit("res://examples/navigating.thd")
|
|
|
+ save_load.load_graph_edit("res://examples/navigating.thd")
|
|
|
3:
|
|
|
if changesmade == true:
|
|
|
savestate = "helpfile"
|
|
|
@@ -898,7 +733,7 @@ func _on_help_button_index_pressed(index: int) -> void:
|
|
|
$SaveChangesPopup.popup_centered()
|
|
|
else:
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit("res://examples/building_a_thread.thd")
|
|
|
+ save_load.load_graph_edit("res://examples/building_a_thread.thd")
|
|
|
4:
|
|
|
if changesmade == true:
|
|
|
savestate = "helpfile"
|
|
|
@@ -906,7 +741,7 @@ func _on_help_button_index_pressed(index: int) -> void:
|
|
|
$SaveChangesPopup.popup_centered()
|
|
|
else:
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit("res://examples/frequency_domain.thd")
|
|
|
+ save_load.load_graph_edit("res://examples/frequency_domain.thd")
|
|
|
5:
|
|
|
if changesmade == true:
|
|
|
savestate = "helpfile"
|
|
|
@@ -914,7 +749,7 @@ func _on_help_button_index_pressed(index: int) -> void:
|
|
|
$SaveChangesPopup.popup_centered()
|
|
|
else:
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit("res://examples/automation.thd")
|
|
|
+ save_load.load_graph_edit("res://examples/automation.thd")
|
|
|
6:
|
|
|
if changesmade == true:
|
|
|
savestate = "helpfile"
|
|
|
@@ -922,7 +757,7 @@ func _on_help_button_index_pressed(index: int) -> void:
|
|
|
$SaveChangesPopup.popup_centered()
|
|
|
else:
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit("res://examples/trimming.thd")
|
|
|
+ save_load.load_graph_edit("res://examples/trimming.thd")
|
|
|
7:
|
|
|
pass
|
|
|
8:
|
|
|
@@ -932,7 +767,7 @@ func _on_help_button_index_pressed(index: int) -> void:
|
|
|
$SaveChangesPopup.popup_centered()
|
|
|
else:
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit("res://examples/wetdry.thd")
|
|
|
+ save_load.load_graph_edit("res://examples/wetdry.thd")
|
|
|
9:
|
|
|
if changesmade == true:
|
|
|
savestate = "helpfile"
|
|
|
@@ -940,7 +775,7 @@ func _on_help_button_index_pressed(index: int) -> void:
|
|
|
$SaveChangesPopup.popup_centered()
|
|
|
else:
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit("res://examples/resonant_filters.thd")
|
|
|
+ save_load.load_graph_edit("res://examples/resonant_filters.thd")
|
|
|
10:
|
|
|
pass
|
|
|
11:
|
|
|
@@ -959,7 +794,7 @@ func _on_save_changes_button_down() -> void:
|
|
|
if currentfile == "none":
|
|
|
$SaveDialog.show()
|
|
|
else:
|
|
|
- save_graph_edit(currentfile)
|
|
|
+ save_load.save_graph_edit(currentfile)
|
|
|
if savestate == "newfile":
|
|
|
new_patch()
|
|
|
currentfile = "none" #reset current file to none for save tracking
|
|
|
@@ -967,7 +802,7 @@ func _on_save_changes_button_down() -> void:
|
|
|
$LoadDialog.popup_centered()
|
|
|
elif savestate == "helpfile":
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit(helpfile)
|
|
|
+ save_load.load_graph_edit(helpfile)
|
|
|
elif savestate == "quit":
|
|
|
await get_tree().create_timer(0.25).timeout #little pause so that it feels like it actually saved even though it did
|
|
|
get_tree().quit()
|
|
|
@@ -984,7 +819,7 @@ func _on_dont_save_changes_button_down() -> void:
|
|
|
$LoadDialog.popup_centered()
|
|
|
elif savestate == "helpfile":
|
|
|
currentfile = "none" #reset current file to none for save tracking so user cant save over help file
|
|
|
- load_graph_edit(helpfile)
|
|
|
+ save_load.load_graph_edit(helpfile)
|
|
|
elif savestate == "quit":
|
|
|
get_tree().quit()
|
|
|
|