Kaynağa Gözat

automation points now save when saving a thread, limited rang of min/max sliders so they cant exceed each other, also added lohi filter

Jonathan Higgins 7 ay önce
ebeveyn
işleme
d7e0fd3604

+ 44 - 0
scenes/Nodes/min_max_sliders.gd

@@ -0,0 +1,44 @@
+extends GraphNode
+
+@export var min_gap: float = 0.5  # editable value in inspector for the minimum gap between min and max
+
+func _ready() -> void:
+	var sliders := _get_all_hsliders(self) #finds all sliders
+	#links sliders to this script
+	for slider in sliders:
+		slider.value_changed.connect(_on_slider_value_changed.bind(slider))
+
+func _get_all_hsliders(node: Node) -> Array:
+	#moves through all children recusively to find nested sliders
+	var result: Array = []
+	for child in node.get_children():
+		if child is HSlider:
+			result.append(child)
+		elif child.has_method("get_children"):
+			result += _get_all_hsliders(child)
+	return result
+
+func _on_slider_value_changed(value: float, changed_slider: HSlider) -> void:
+	#checks if the slider moved has min or max meta data
+	var is_min := changed_slider.has_meta("min")
+	var is_max := changed_slider.has_meta("max")
+	
+	#if not exits function
+	if not is_min and not is_max:
+		return
+
+	var sliders := _get_all_hsliders(self)
+
+	for other_slider in sliders:
+		if other_slider == changed_slider:
+			continue
+		
+		if is_min and other_slider.has_meta("max"):
+			var max_value: float = other_slider.value
+			if changed_slider.value > max_value - min_gap:
+				changed_slider.value = max_value - min_gap
+		
+		elif is_max and other_slider.has_meta("min"):
+			var min_value: float = other_slider.value
+			if changed_slider.value < min_value + min_gap:
+				changed_slider.value = min_value + min_gap

+ 1 - 0
scenes/Nodes/min_max_sliders.gd.uid

@@ -0,0 +1 @@
+uid://cdbx1dt3ohqte

+ 124 - 1
scenes/Nodes/nodes.tscn

@@ -1,7 +1,8 @@
-[gd_scene load_steps=3 format=3 uid="uid://duy5epq25pj8u"]
+[gd_scene load_steps=4 format=3 uid="uid://duy5epq25pj8u"]
 
 [ext_resource type="PackedScene" uid="uid://csapiqka522fh" path="res://scenes/Nodes/audioplayer.tscn" id="2_b6nw4"]
 [ext_resource type="PackedScene" uid="uid://dya5kxx132fgp" path="res://scenes/Nodes/valueslider.tscn" id="3_b6nw4"]
+[ext_resource type="Script" uid="uid://cdbx1dt3ohqte" path="res://scenes/Nodes/min_max_sliders.gd" id="3_uv17x"]
 
 [node name="Control" type="Control"]
 layout_mode = 3
@@ -1026,6 +1027,7 @@ slot/3/right_type = 0
 slot/3/right_color = Color(1, 1, 1, 1)
 slot/3/right_icon = null
 slot/3/draw_stylebox = true
+script = ExtResource("3_uv17x")
 metadata/command = "extend_scramble_1"
 metadata/stereo_input = true
 
@@ -1044,6 +1046,7 @@ min_value = 2.0
 step = 0.01
 value = 2.0
 metadata/time = true
+metadata/min = true
 
 [node name="VBoxContainer2" parent="extend_scramble_1" instance=ExtResource("3_b6nw4")]
 layout_mode = 2
@@ -1057,6 +1060,7 @@ min_value = 3.0
 step = 0.01
 value = 3.0
 metadata/time = true
+metadata/max = true
 
 [node name="VBoxContainer3" parent="extend_scramble_1" instance=ExtResource("3_b6nw4")]
 layout_mode = 2
@@ -1258,6 +1262,8 @@ slot/4/right_type = 0
 slot/4/right_color = Color(1, 1, 1, 1)
 slot/4/right_icon = null
 slot/4/draw_stylebox = true
+script = ExtResource("3_uv17x")
+min_gap = 1.0
 metadata/command = "extend_zigzag_1"
 metadata/stereo_input = true
 
@@ -1275,6 +1281,7 @@ text = "Start Point"
 step = 0.01
 value = 0.0
 metadata/time = true
+metadata/min = true
 
 [node name="VBoxContainer2" parent="extend_zigzag_1" instance=ExtResource("3_b6nw4")]
 layout_mode = 2
@@ -1287,6 +1294,7 @@ text = "End Point"
 min_value = 1.0
 step = 0.01
 metadata/time = true
+metadata/max = true
 
 [node name="VBoxContainer3" parent="extend_zigzag_1" instance=ExtResource("3_b6nw4")]
 layout_mode = 2
@@ -1588,6 +1596,118 @@ step = 0.01
 value = 0.0
 metadata/flag = "-s"
 
+[node name="filter_lohi_1" type="GraphNode" parent="."]
+layout_mode = 0
+offset_left = 858.0
+offset_top = 2385.0
+offset_right = 1164.0
+offset_bottom = 2609.0
+tooltip_text = "Removes high/low frequencies - Stop > Pass = Low Pass, Stop < Pass = High Pass"
+title = "Filter: Low/High Pass"
+slot/0/left_enabled = true
+slot/0/left_type = 0
+slot/0/left_color = Color(1, 1, 1, 0.564706)
+slot/0/left_icon = null
+slot/0/right_enabled = true
+slot/0/right_type = 0
+slot/0/right_color = Color(1, 1, 1, 0.564706)
+slot/0/right_icon = null
+slot/0/draw_stylebox = true
+slot/1/left_enabled = false
+slot/1/left_type = 0
+slot/1/left_color = Color(1, 1, 1, 1)
+slot/1/left_icon = null
+slot/1/right_enabled = false
+slot/1/right_type = 0
+slot/1/right_color = Color(1, 1, 1, 1)
+slot/1/right_icon = null
+slot/1/draw_stylebox = true
+slot/2/left_enabled = false
+slot/2/left_type = 0
+slot/2/left_color = Color(1, 1, 1, 1)
+slot/2/left_icon = null
+slot/2/right_enabled = false
+slot/2/right_type = 0
+slot/2/right_color = Color(1, 1, 1, 1)
+slot/2/right_icon = null
+slot/2/draw_stylebox = true
+slot/3/left_enabled = false
+slot/3/left_type = 0
+slot/3/left_color = Color(1, 1, 1, 1)
+slot/3/left_icon = null
+slot/3/right_enabled = false
+slot/3/right_type = 0
+slot/3/right_color = Color(1, 1, 1, 1)
+slot/3/right_icon = null
+slot/3/draw_stylebox = true
+metadata/command = "filter_lohi_1"
+metadata/stereo_input = true
+
+[node name="Control" type="Control" parent="filter_lohi_1"]
+layout_mode = 2
+
+[node name="VBoxContainer" parent="filter_lohi_1" instance=ExtResource("3_b6nw4")]
+layout_mode = 2
+tooltip_text = "Steepness of the filter"
+
+[node name="Label" parent="filter_lohi_1/VBoxContainer" index="0"]
+text = "Rolloff"
+
+[node name="HSlider" parent="filter_lohi_1/VBoxContainer/HSplitContainer" index="0"]
+min_value = -96.0
+max_value = 0.0
+step = 0.01
+value = -60.0
+
+[node name="PopupMenu" parent="filter_lohi_1/VBoxContainer/HSplitContainer/HSlider" index="0"]
+auto_translate_mode = 1
+size = Vector2i(208, 100)
+
+[node name="BreakFileMaker" parent="filter_lohi_1/VBoxContainer" index="3"]
+auto_translate_mode = 1
+
+[node name="VBoxContainer2" parent="filter_lohi_1" instance=ExtResource("3_b6nw4")]
+layout_mode = 2
+tooltip_text = "Last pitch to be passed by the filter"
+
+[node name="Label" parent="filter_lohi_1/VBoxContainer2" index="0"]
+text = "Pass-band"
+
+[node name="HSlider" parent="filter_lohi_1/VBoxContainer2/HSplitContainer" index="0"]
+min_value = 20.0
+max_value = 20000.0
+step = 0.01
+value = 440.0
+exp_edit = true
+
+[node name="PopupMenu" parent="filter_lohi_1/VBoxContainer2/HSplitContainer/HSlider" index="0"]
+auto_translate_mode = 1
+size = Vector2i(208, 100)
+
+[node name="BreakFileMaker" parent="filter_lohi_1/VBoxContainer2" index="3"]
+auto_translate_mode = 1
+
+[node name="VBoxContainer3" parent="filter_lohi_1" instance=ExtResource("3_b6nw4")]
+layout_mode = 2
+tooltip_text = "First pitch to be stopped by the filter"
+
+[node name="Label" parent="filter_lohi_1/VBoxContainer3" index="0"]
+text = "Stop-band"
+
+[node name="HSlider" parent="filter_lohi_1/VBoxContainer3/HSplitContainer" index="0"]
+min_value = 20.0
+max_value = 20000.0
+step = 0.01
+value = 10000.0
+exp_edit = true
+
+[node name="PopupMenu" parent="filter_lohi_1/VBoxContainer3/HSplitContainer/HSlider" index="0"]
+auto_translate_mode = 1
+size = Vector2i(208, 100)
+
+[node name="BreakFileMaker" parent="filter_lohi_1/VBoxContainer3" index="3"]
+auto_translate_mode = 1
+
 [node name="filter_bank_5" type="GraphNode" parent="."]
 layout_mode = 0
 offset_left = 850.0
@@ -3429,6 +3549,9 @@ wrap_mode = 1
 [editable path="filter_bank_2/VBoxContainer3"]
 [editable path="filter_bank_2/VBoxContainer4"]
 [editable path="filter_bank_2/VBoxContainer6"]
+[editable path="filter_lohi_1/VBoxContainer"]
+[editable path="filter_lohi_1/VBoxContainer2"]
+[editable path="filter_lohi_1/VBoxContainer3"]
 [editable path="filter_bank_5/VBoxContainer"]
 [editable path="filter_bank_5/VBoxContainer2"]
 [editable path="filter_bank_5/VBoxContainer3"]

+ 18 - 5
scenes/Nodes/valueslider.gd

@@ -2,6 +2,7 @@ extends VBoxContainer
 
 @onready var window := $BreakFileMaker
 @onready var editor := window.get_node("AutomationEditor")
+signal meta_changed
 
 
 #Called when the node enters the scene tree for the first time.
@@ -15,9 +16,10 @@ func _ready() -> void:
 func _on_h_slider_value_changed(value: float) -> void:
 	#$HSplitContainer/ValueLabel.text = str(value)
 	$HSplitContainer/LineEdit.text = str(value)
+
 	
 func _on_line_edit_text_submitted(new_text: String) -> void:
-	#check if input from text box is a valid number for the slider if not choose and appropriate value and set that
+	#check if input from text box is a valid number for the slider if not choose an appropriate value and set that
 	if new_text.is_valid_float():
 		var new_val = new_text.to_float()
 		if new_val > $HSplitContainer/HSlider.max_value:
@@ -28,6 +30,8 @@ func _on_line_edit_text_submitted(new_text: String) -> void:
 			$HSplitContainer/HSlider.set_value_no_signal(new_val)
 	else:
 		$HSplitContainer/LineEdit.text = str($HSplitContainer/HSlider.value)
+		
+
 
 func _on_line_edit_focus_exited() -> void:
 	#check if input from text box is a valid number for the slider if not choose and appropriate value and set that
@@ -43,16 +47,21 @@ func _on_line_edit_focus_exited() -> void:
 		$HSplitContainer/LineEdit.text = str($HSplitContainer/HSlider.value)
 		
 
+		
+
 
 
 		
 
 #check for right click
 func _on_h_slider_gui_input(event: InputEvent) -> void:
-	if $HSplitContainer/HSlider.has_meta("brk"):
+	if $HSplitContainer/HSlider.has_meta("brk"): #check if slider can take a break file
+		if $HSplitContainer/HSlider.has_meta("brk_data"): #check if it already has break data and set menu correctly (used when loading files)
+			$HSplitContainer/HSlider/PopupMenu.set_item_text(0, "Edit Automation")
+			if $HSplitContainer/HSlider/PopupMenu.get_item_count() <= 1: #if it has automation data but no remove button, add it
+				$HSplitContainer/HSlider/PopupMenu.add_item("Remove Automation", 1)
 		$HSplitContainer/HSlider/PopupMenu.set_item_disabled(0, false)
-		#$HSplitContainer/HSlider/PopupMenu.set_item_text(0, "Add Automation")
-	else:
+	else: #if it can't take automation data updata menu to let user know
 		$HSplitContainer/HSlider/PopupMenu.set_item_disabled(0, true)
 		$HSplitContainer/HSlider/PopupMenu.set_item_text(0, "Automation is not available for this parameter")
 	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
@@ -78,14 +87,15 @@ func _on_popup_menu_index_pressed(index: int) -> void:
 			$HSplitContainer/HSlider.editable = true
 			$HSplitContainer/HSlider/PopupMenu.set_item_text(0, "Add Automation")
 			$HSplitContainer/HSlider/PopupMenu.remove_item(1)
+			_on_meta_changed()
 
 func _on_automation_data_received(data):
 	$HSplitContainer/HSlider.set_meta("brk_data", data)
-	print($HSplitContainer/HSlider.get_meta("brk_data"))
 	$HSplitContainer/HSlider.editable = false
 	$HSplitContainer/HSlider/PopupMenu.set_item_text(0, "Edit Automation")
 	if $HSplitContainer/HSlider/PopupMenu.get_item_count() <= 1:
 		$HSplitContainer/HSlider/PopupMenu.add_item("Remove Automation", 1)
+	_on_meta_changed()
 
 
 
@@ -99,3 +109,6 @@ func _on_save_automation_2_button_down() -> void:
 
 func _on_break_file_maker_close_requested() -> void:
 	$BreakFileMaker.hide()
+
+func _on_meta_changed():
+	emit_signal("meta_changed")

+ 59 - 4
scenes/main/control.gd

@@ -448,13 +448,24 @@ func _register_inputs_in_node(node: Node):
 		# Check if it's already connected, and connect if not
 		if not slider.is_connected("value_changed", callable):
 			slider.connect("value_changed", callable)
+	
+	for slider in node.find_children("*", "VBoxContainer", true, false):
+		# Also connect to meta_changed if the slider has that signal
+		if slider.has_signal("meta_changed"):
+			var meta_callable = Callable(self, "_on_any_slider_meta_changed")
+			if not slider.is_connected("meta_changed", meta_callable):
+				slider.connect("meta_changed", meta_callable)
 		
-	# Track CodeEdits (if necessary)
+	# Track CodeEdits
 	for editor in node.find_children("*", "CodeEdit", true, false):
 		var callable = Callable(self, "_on_any_input_changed")
 		if not editor.is_connected("text_changed", callable):
 			editor.connect("text_changed", callable)
 			
+func _on_any_slider_meta_changed():
+	changesmade = true
+	print("Meta changed in slider")
+	
 func _register_node_movement():
 	for graphnode in graph_edit.get_children():
 		if graphnode is GraphNode:
@@ -1029,8 +1040,11 @@ func make_process(node: Node, process_count: int, current_infile: String, slider
 					#var new_y = infile_length * (remap(point.y, 255, 0, min_slider, max_slider) / 100) #slider value scaled as a percentage of infile time
 					#calculated_brk.append(Vector2(new_x, new_y))
 			#else:
-			for point in sorted_brk_data:
+			for i in range(sorted_brk_data.size()):
+				var point = sorted_brk_data[i]
 				var new_x = infile_length * (point.x / 700) #time
+				if i == sorted_brk_data.size() - 1: #check if this is last automation point
+					new_x = infile_length + 0.1  # force last point's x to infile_length + 100ms to make sure the file is defo over
 				var new_y = remap(point.y, 255, 0, min_slider, max_slider) #slider value
 				calculated_brk.append(Vector2(new_x, new_y))
 				
@@ -1254,7 +1268,18 @@ func save_graph_edit(path: String):
 
 			for child in node.find_children("*", "Slider", true, false):
 				var relative_path = node.get_path_to(child)
-				node_data["slider_values"][str(relative_path)] = child.value
+				var path_str = str(relative_path)
+
+				# Save slider value
+				node_data["slider_values"][path_str] = {
+					"value": child.value,
+					"editable": child.editable,
+					"meta": {}
+				}
+
+				# Save all metadata
+				for key in child.get_meta_list():
+					node_data["slider_values"][path_str]["meta"][str(key)] = child.get_meta(key)
 				
 			for child in node.find_children("*", "CodeEdit", true, false):
 				node_data["notes"][child.name] = child.text
@@ -1324,7 +1349,37 @@ func load_graph_edit(path: String):
 		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):
-				slider.value = node_data["slider_values"][slider_path_str]
+				var slider_info = node_data["slider_values"][slider_path_str]
+				
+				if typeof(slider_info) == TYPE_DICTIONARY:
+					slider.value = slider_info.get("value", slider.value)
+					
+					# Restore enabled/disabled
+					if slider_info.has("editable"):
+						slider.editable = slider_info["editable"]
+					
+					# Restore metadata
+					if slider_info.has("meta"):
+						for key in slider_info["meta"]:
+							var value = slider_info["meta"][key]
+
+							# Convert arrays of stringified Vector2s back to real Vector2s
+							if key == "brk_data" and typeof(value) == TYPE_ARRAY:
+								var new_array: Array = []
+								for item in value:
+									if typeof(item) == TYPE_STRING:
+										# Extract values from "(x, y)"
+										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:
+					# Legacy support: just value
+					slider.value = slider_info
 			
 	
 				

+ 28 - 2
scenes/menu/menu.tscn

@@ -25,7 +25,7 @@ current_tab = 0
 
 [node name="Time Domain" type="TabContainer" parent="select_effect"]
 layout_mode = 2
-current_tab = 3
+current_tab = 2
 metadata/_tab_index = 0
 
 [node name="Distort" type="VBoxContainer" parent="select_effect/Time Domain"]
@@ -411,7 +411,6 @@ layout_mode = 2
 text = "+"
 
 [node name="Filter" type="VBoxContainer" parent="select_effect/Time Domain"]
-visible = false
 layout_mode = 2
 metadata/_tab_index = 2
 
@@ -473,6 +472,28 @@ text = "+"
 layout_mode = 2
 theme_override_constants/margin_bottom = 3
 
+[node name="HSplitContainer10" type="HSplitContainer" parent="select_effect/Time Domain/Filter/MarginContainer2/ScrollContainer/VBoxContainer"]
+custom_minimum_size = Vector2(565, 0)
+layout_mode = 2
+split_offset = 505
+dragging_enabled = false
+
+[node name="RichTextLabel" type="RichTextLabel" parent="select_effect/Time Domain/Filter/MarginContainer2/ScrollContainer/VBoxContainer/HSplitContainer10"]
+layout_mode = 2
+bbcode_enabled = true
+text = "[b]Low Pass/High Pass[/b]
+Filter for removing low or high frequencies"
+fit_content = true
+scroll_active = false
+
+[node name="filter_lohi_1" type="Button" parent="select_effect/Time Domain/Filter/MarginContainer2/ScrollContainer/VBoxContainer/HSplitContainer10" groups=["make_node_buttons"]]
+layout_mode = 2
+text = "+"
+
+[node name="MarginContainer4" type="MarginContainer" parent="select_effect/Time Domain/Filter/MarginContainer2/ScrollContainer/VBoxContainer"]
+layout_mode = 2
+theme_override_constants/margin_bottom = 3
+
 [node name="HSplitContainer2" type="HSplitContainer" parent="select_effect/Time Domain/Filter/MarginContainer2/ScrollContainer/VBoxContainer"]
 custom_minimum_size = Vector2(565, 0)
 layout_mode = 2
@@ -537,6 +558,7 @@ layout_mode = 2
 text = "+"
 
 [node name="Granulate" type="VBoxContainer" parent="select_effect/Time Domain"]
+visible = false
 layout_mode = 2
 metadata/_tab_index = 3
 
@@ -573,6 +595,10 @@ scroll_active = false
 layout_mode = 2
 text = "+"
 
+[node name="MarginContainer5" type="MarginContainer" parent="select_effect/Time Domain/Granulate/MarginContainer2/ScrollContainer/VBoxContainer"]
+layout_mode = 2
+theme_override_constants/margin_bottom = 3
+
 [node name="HSplitContainer5" type="HSplitContainer" parent="select_effect/Time Domain/Granulate/MarginContainer2/ScrollContainer/VBoxContainer"]
 custom_minimum_size = Vector2(565, 0)
 layout_mode = 2