node_logic.gd 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. extends GraphNode
  2. @export var min_gap: float = 0.5 # editable value in inspector for the minimum gap between min and max
  3. var undo_redo: UndoRedo
  4. var button_states = {}
  5. signal open_help
  6. signal inlet_removed
  7. signal node_moved
  8. func _ready() -> void:
  9. var sliders := _get_all_hsliders(self) #finds all sliders
  10. #links sliders to this script
  11. for slider in sliders:
  12. slider.value_changed.connect(_on_slider_value_changed.bind(slider))
  13. #link all buttons for undo redo
  14. get_all_buttons()
  15. #add button to title bar
  16. var titlebar = self.get_titlebar_hbox()
  17. #add randomise button
  18. if sliders.size() > 0:
  19. var rnd_btn = Button.new()
  20. rnd_btn.text = "!"
  21. rnd_btn.tooltip_text = "Randomise Slider Values"
  22. rnd_btn.connect("pressed", Callable(self, "_randomise_sliders")) #pass key (process name) when button is pressed
  23. titlebar.add_child(rnd_btn)
  24. #add help button
  25. var btn = Button.new()
  26. btn.text = "?"
  27. btn.tooltip_text = "Open help for " + self.title
  28. btn.connect("pressed", Callable(self, "_open_help")) #pass key (process name) when button is pressed
  29. titlebar.add_child(btn)
  30. await get_tree().process_frame
  31. #reset_size()
  32. self.position_offset_changed.connect(_on_position_offset_changed)
  33. if self.has_node("addremoveinlets"):
  34. var addremove = self.get_node("addremoveinlets")
  35. addremove.add_inlet.connect(add_inlet_to_node)
  36. addremove.remove_inlet.connect(remove_inlet_from_node)
  37. func _get_all_hsliders(node: Node) -> Array:
  38. #moves through all children recusively to find nested sliders
  39. var result: Array = []
  40. for child in node.get_children():
  41. if child is HSlider:
  42. result.append(child)
  43. elif child.has_method("get_children"):
  44. result += _get_all_hsliders(child)
  45. return result
  46. func get_all_buttons() -> void:
  47. for child in get_children():
  48. if child is OptionButton:
  49. button_states[child] = child.selected
  50. child.item_selected.connect(button_changed.bind(child))
  51. elif child is CheckButton:
  52. button_states[child] = child.button_pressed
  53. child.toggled.connect(button_changed.bind(child))
  54. func _on_slider_value_changed(value: float, changed_slider: HSlider) -> void:
  55. #checks if the slider moved has min or max meta data
  56. var is_min = changed_slider.get_meta("min")
  57. var is_max = changed_slider.get_meta("max")
  58. var is_outputduration = false
  59. if changed_slider.has_meta("outputduration"):
  60. is_outputduration = changed_slider.get_meta("outputduration")
  61. #if not exits function
  62. if not is_min and not is_max:
  63. return
  64. var sliders := _get_all_hsliders(self)
  65. for other_slider in sliders:
  66. if other_slider == changed_slider:
  67. continue
  68. if is_min and other_slider.get_meta("max"):
  69. var max_value: float = other_slider.value
  70. if changed_slider.value > max_value - min_gap:
  71. changed_slider.value = max_value - min_gap
  72. elif is_max and other_slider.get_meta("min"):
  73. var min_value: float = other_slider.value
  74. if changed_slider.value < min_value + min_gap:
  75. changed_slider.value = min_value + min_gap
  76. #set output duration meta if this is the output duration slider
  77. if is_outputduration:
  78. set_meta("outputduration", value)
  79. func _open_help():
  80. open_help.emit(self.get_meta("command"), self.title)
  81. func add_inlet_to_node():
  82. #called when the + button is pressed on an addremoveinlets node in the graphnode
  83. var inlet_count = self.get_input_port_count()
  84. var child_count = self.get_child_count()
  85. #check if the number of children is less than the new inlet count
  86. if child_count < inlet_count + 1:
  87. #if so add a new control node for the inlet to connect to
  88. var control = Control.new()
  89. control.custom_minimum_size.y = 57
  90. #give it this meta so it can be found and removed later if needed
  91. control.set_meta("dummynode", true)
  92. add_child(control)
  93. #move the ui for adding/removing inlets to the bottom of the node
  94. move_child(get_node("addremoveinlets"), get_child_count() - 1)
  95. #add the inlet using the same parameters as the first inlet
  96. set_slot(inlet_count, true, get_input_port_type(0), get_input_port_color(0), false, 0, get_input_port_color(0))
  97. func remove_inlet_from_node():
  98. var inlet_count = self.get_input_port_count()
  99. var child_count = self.get_child_count()
  100. #emit a signal to the graphedit script to remove any connections to this inlet
  101. inlet_removed.emit(self.get_name(), inlet_count - 1)
  102. #remove the inlet note inlet idx starts at 0 hence inlet_count -1
  103. set_slot(inlet_count - 1, false, get_input_port_type(0), get_input_port_color(0), false, 0, get_input_port_color(0))
  104. #check if a dummy control node has been added to make this inlet -2 because bottom node is the ui for adding removing inlets and idx starts at 0
  105. if get_child(child_count - 2).has_meta("dummynode"):
  106. #remove the dummy node
  107. get_child(child_count - 2).queue_free()
  108. #wait a frame for it to be removed
  109. await get_tree().process_frame
  110. #update the size of the graphnode to shrink to fit smaller ui
  111. update_minimum_size()
  112. size.y = get_combined_minimum_size().y
  113. func _on_position_offset_changed():
  114. node_moved.emit(self, Rect2(position, size))
  115. func _randomise_sliders():
  116. undo_redo.create_action("Randomise Sliders")
  117. var sliders := _get_all_hsliders(self) #finds all sliders
  118. #links sliders to this script
  119. for slider in sliders:
  120. var minimum = slider.min_value
  121. var maximum = slider.max_value
  122. var expo = slider.exp_edit
  123. var rnd = randf()
  124. var rnd_value
  125. if expo:
  126. rnd_value = minimum * pow(maximum / minimum, rnd)
  127. else:
  128. rnd_value = (rnd * (maximum - minimum)) + minimum
  129. undo_redo.add_do_method(set_slider_value.bind(slider, rnd_value))
  130. undo_redo.add_undo_method(set_slider_value.bind(slider, slider.value))
  131. undo_redo.commit_action()
  132. func set_slider_value(slider: HSlider, value: float) -> void:
  133. slider.value = value
  134. func button_changed(value, button) -> void:
  135. if button_states[button] != value:
  136. undo_redo.create_action("Change Button Value")
  137. undo_redo.add_do_method(set_button_value.bind(value, button))
  138. undo_redo.add_undo_method(set_button_value.bind(button_states[button], button))
  139. undo_redo.commit_action()
  140. func set_button_value(value, button) -> void:
  141. if button is OptionButton:
  142. button.selected = value
  143. elif button is CheckButton:
  144. button.set_pressed_no_signal(value)
  145. button_states[button] = value