explore_menu.gd 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. extends Window
  2. var node_data = {} #stores node data for each node to display in help popup
  3. signal make_node(command)
  4. signal open_help(command)
  5. @onready var fav_button_logic = preload("res://scenes/menu/fav_button.gd")
  6. func _ready() -> void:
  7. $"Control/select_effect/Time Domain".show()
  8. $"Control/select_effect/Time Domain/Distort".show()
  9. $"Control/select_effect/Frequency Domain/Convert".show()
  10. #parse json
  11. var file = FileAccess.open("res://scenes/main/process_help.json", FileAccess.READ)
  12. if file:
  13. var result = JSON.parse_string(file.get_as_text())
  14. if typeof(result) == TYPE_DICTIONARY:
  15. node_data = result
  16. else:
  17. push_error("Invalid JSON")
  18. fill_menu()
  19. load_search()
  20. #chec user prefs fr favourites and load them
  21. var interface_settings = ConfigHandler.load_interface_settings()
  22. var favourites = interface_settings.favourites
  23. _load_favourites(favourites)
  24. func fill_menu():
  25. var interface_settings = ConfigHandler.load_interface_settings()
  26. var favourites = interface_settings.favourites
  27. for key in node_data.keys():
  28. var item = node_data[key]
  29. var title = item.get("title", "")
  30. #filter out output nodes
  31. if title == "Output File":
  32. continue
  33. var category = item.get("category", "")
  34. var subcategory = item.get("subcategory", "")
  35. var short_desc = item.get("short_description", "")
  36. var container
  37. if category == "time":
  38. if subcategory == "distort":
  39. container = $"Control/select_effect/Time Domain/Distort/MarginContainer/ScrollContainer/DistortContainer"
  40. elif subcategory == "extend":
  41. container = $"Control/select_effect/Time Domain/Extend/MarginContainer/ScrollContainer/ExtendContainer"
  42. elif subcategory == "filter":
  43. container = $"Control/select_effect/Time Domain/Filter/MarginContainer/ScrollContainer/FilterContainer"
  44. elif subcategory == "granulate":
  45. container = $"Control/select_effect/Time Domain/Granulate/MarginContainer/ScrollContainer/GranulateContainer"
  46. elif subcategory == "misc":
  47. container = $"Control/select_effect/Time Domain/Misc/MarginContainer/ScrollContainer/MiscContainer"
  48. elif subcategory == "reverb":
  49. container = $"Control/select_effect/Time Domain/Reverb and Delay/MarginContainer/ScrollContainer/ReverbContainer"
  50. elif subcategory == "synthesis":
  51. container = $"Control/select_effect/Time Domain/Synthesis/MarginContainer/ScrollContainer/SynthesisContainer"
  52. else:
  53. continue
  54. elif category == "pvoc":
  55. if subcategory == "convert":
  56. container = $"Control/select_effect/Frequency Domain/Convert/MarginContainer/ScrollContainer/PVOCConvertContainer"
  57. elif subcategory == "amplitude" or subcategory == "pitch":
  58. container = $"Control/select_effect/Frequency Domain/Amplitude and Pitch/MarginContainer/ScrollContainer/PVOCAmplitudePitchContainer"
  59. elif subcategory == "combine":
  60. container = $"Control/select_effect/Frequency Domain/Combine/MarginContainer/ScrollContainer/PVOCCombineContainer"
  61. elif subcategory == "formants":
  62. container = $"Control/select_effect/Frequency Domain/Formants/MarginContainer/ScrollContainer/PVOCFormantsContainer"
  63. elif subcategory == "time":
  64. container = $"Control/select_effect/Frequency Domain/Time/MarginContainer/ScrollContainer/PVOCTimeContainer"
  65. elif subcategory == "spectrum":
  66. container = $"Control/select_effect/Frequency Domain/Spectrum/MarginContainer/ScrollContainer/PVOCSpectrumContainer"
  67. else:
  68. continue
  69. elif category == "utility":
  70. container = $Control/select_effect/Utilities/SoundThread/MarginContainer/ScrollContainer/UtilityContainer
  71. else:
  72. continue
  73. var hbox = HBoxContainer.new()
  74. var label = RichTextLabel.new()
  75. var favbtn = Button.new()
  76. var helpbtn = Button.new()
  77. var makebtn = Button.new()
  78. var margin = MarginContainer.new()
  79. hbox.size.x = container.size.x
  80. label.bbcode_enabled = true
  81. label.text = "[b]%s[/b]\n%s" % [title, short_desc]
  82. label.set_h_size_flags(Control.SIZE_EXPAND_FILL)
  83. label.set_v_size_flags(Control.SIZE_EXPAND_FILL)
  84. label.fit_content = true
  85. favbtn.name = "fav_" + key
  86. favbtn.add_theme_font_size_override("font_size", 20)
  87. favbtn.tooltip_text = "Favourite " + title
  88. favbtn.custom_minimum_size = Vector2(40, 40)
  89. favbtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  90. favbtn.toggle_mode = true
  91. if favourites.has(key):
  92. favbtn.text = "★"
  93. favbtn.set_pressed_no_signal(true)
  94. else:
  95. favbtn.text = "☆"
  96. favbtn.set_script(fav_button_logic)
  97. favbtn.connect("toggled", Callable(self, "_favourite_process").bind(key, favourites)) #pass key (process name) when button is pressed
  98. helpbtn.text = "?"
  99. helpbtn.tooltip_text = "Open help for " + title
  100. helpbtn.custom_minimum_size = Vector2(40, 40)
  101. helpbtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  102. helpbtn.connect("pressed", Callable(self, "_open_help").bind(key, title)) #pass key (process name) when button is pressed
  103. makebtn.text = "+"
  104. makebtn.tooltip_text = "Add " + title + " to thread"
  105. makebtn.custom_minimum_size = Vector2(40, 40)
  106. makebtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  107. makebtn.connect("pressed", Callable(self, "_make_node").bind(key)) #pass key (process name) when button is pressed
  108. margin.add_theme_constant_override("margin_bottom", 3)
  109. container.add_child(hbox)
  110. hbox.add_child(label)
  111. hbox.add_child(favbtn)
  112. hbox.add_child(helpbtn)
  113. hbox.add_child(makebtn)
  114. container.add_child(margin)
  115. func _on_about_to_popup() -> void:
  116. #fill_search("")
  117. $"Control/select_effect/Search/Search for a process in SoundThread/MarginContainer/VBoxContainer/SearchBar".clear()
  118. if $Control/select_effect.current_tab == 3:
  119. $"Control/select_effect/Search/Search for a process in SoundThread/MarginContainer/VBoxContainer/SearchBar".grab_focus()
  120. func fill_search(filter: String):
  121. var interface_settings = ConfigHandler.load_interface_settings()
  122. var favourites = interface_settings.favourites
  123. # Remove all existing items from the VBoxContainer
  124. var container = $"Control/select_effect/Search/Search for a process in SoundThread/MarginContainer/VBoxContainer/ScrollContainer/ItemContainer"
  125. #for child in container.get_children():
  126. #child.queue_free()
  127. var filters = filter.to_lower().split(" ", false)
  128. for key in node_data.keys():
  129. var item = node_data[key]
  130. var search_element = container.find_child("search_" + key, true, false)
  131. var search_margin = container.find_child("search_margin_" + key, true, false)
  132. var title = item.get("title", "")
  133. if search_element == null:
  134. continue
  135. if filters.has("*"):
  136. if favourites.has(key) == false:
  137. search_element.hide()
  138. search_margin.hide()
  139. continue
  140. var category = item.get("category", "")
  141. var subcategory = item.get("subcategory", "")
  142. var short_desc = item.get("short_description", "")
  143. var command = key.replace("_", " ")
  144. # Combine all searchable text into one lowercase string
  145. var searchable_text = "%s %s %s %s %s" % [title, short_desc, category, subcategory, key]
  146. searchable_text = searchable_text.to_lower()
  147. # If filter is not empty, skip non-matches populate all other buttons
  148. if filter != "":
  149. var match_all_words = true
  150. for word in filters:
  151. if word == "*":
  152. continue
  153. if word != "" and not searchable_text.findn(word) != -1:
  154. match_all_words = false
  155. search_element.hide()
  156. search_margin.hide()
  157. break
  158. if not match_all_words:
  159. continue
  160. search_element.show()
  161. search_margin.show()
  162. func load_search():
  163. var interface_settings = ConfigHandler.load_interface_settings()
  164. var favourites = interface_settings.favourites
  165. # Remove all existing items from the VBoxContainer
  166. var container = $"Control/select_effect/Search/Search for a process in SoundThread/MarginContainer/VBoxContainer/ScrollContainer/ItemContainer"
  167. for child in container.get_children():
  168. child.queue_free()
  169. for key in node_data.keys():
  170. var item = node_data[key]
  171. var title = item.get("title", "")
  172. #filter out output node
  173. if title == "Output File":
  174. continue
  175. var category = item.get("category", "")
  176. var subcategory = item.get("subcategory", "")
  177. var short_desc = item.get("short_description", "")
  178. var command = key.replace("_", " ")
  179. # Combine all searchable text into one lowercase string
  180. var searchable_text = "%s %s %s %s %s" % [title, short_desc, category, subcategory, key]
  181. searchable_text = searchable_text.to_lower()
  182. var hbox = HBoxContainer.new()
  183. var label = RichTextLabel.new()
  184. var favbtn = Button.new()
  185. var helpbtn = Button.new()
  186. var makebtn = Button.new()
  187. var margin = MarginContainer.new()
  188. hbox.size.x = container.size.x
  189. hbox.name = "search_" + key
  190. margin.name = "search_margin_" + key
  191. label.bbcode_enabled = true
  192. label.text = "[b]%s[/b]\n%s" % [title, short_desc]
  193. label.set_h_size_flags(Control.SIZE_EXPAND_FILL)
  194. label.set_v_size_flags(Control.SIZE_EXPAND_FILL)
  195. label.fit_content = true
  196. favbtn.name = "search_fav_" + key
  197. favbtn.add_theme_font_size_override("font_size", 20)
  198. favbtn.tooltip_text = "Favourite " + title
  199. favbtn.custom_minimum_size = Vector2(40, 40)
  200. favbtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  201. favbtn.toggle_mode = true
  202. if favourites.has(key):
  203. favbtn.text = "★"
  204. favbtn.set_pressed_no_signal(true)
  205. else:
  206. favbtn.text = "☆"
  207. favbtn.set_script(fav_button_logic)
  208. favbtn.connect("toggled", Callable(self, "_favourite_process").bind(key, favourites)) #pass key (process name) when button is pressed
  209. helpbtn.text = "?"
  210. helpbtn.tooltip_text = "Open help for " + title
  211. helpbtn.custom_minimum_size = Vector2(40, 40)
  212. helpbtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  213. helpbtn.connect("pressed", Callable(self, "_open_help").bind(key, title)) #pass key (process name) when button is pressed
  214. makebtn.text = "+"
  215. makebtn.tooltip_text = "Add " + title + " to thread"
  216. makebtn.custom_minimum_size = Vector2(40, 40)
  217. makebtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  218. makebtn.connect("pressed", Callable(self, "_make_node").bind(key)) #pass key (process name) when button is pressed
  219. margin.add_theme_constant_override("margin_bottom", 3)
  220. container.add_child(hbox)
  221. hbox.add_child(label)
  222. hbox.add_child(favbtn)
  223. hbox.add_child(helpbtn)
  224. hbox.add_child(makebtn)
  225. container.add_child(margin)
  226. func _on_search_bar_text_changed(new_text: String) -> void:
  227. fill_search(new_text)
  228. pass
  229. func _make_node(key: String):
  230. make_node.emit(key) # send out signal to main patch
  231. self.hide()
  232. func _open_help(key: String, title: String):
  233. open_help.emit(key, title) # send out signal to main patch
  234. self.hide()
  235. func _on_select_effect_tab_changed(tab: int) -> void:
  236. if tab == 4:
  237. $"Control/select_effect/Search/Search for a process in SoundThread/MarginContainer/VBoxContainer/SearchBar".grab_focus()
  238. func _favourite_process(toggled_on: bool, key: String, favourites: Array):
  239. if toggled_on:
  240. favourites.append(key)
  241. else:
  242. favourites.erase(key)
  243. ConfigHandler.save_interface_settings("favourites", favourites)
  244. #find all favourite buttons for this effect and set to the correct state if in serach of favourites window
  245. if $Control/select_effect.current_tab == 3 or $Control/select_effect.current_tab == 4:
  246. var button = $Control/select_effect.find_child("fav_" + key, true, false)
  247. if button != null:
  248. button.set_pressed_no_signal(toggled_on)
  249. if toggled_on:
  250. button.text = "★"
  251. else:
  252. button.text = "☆"
  253. if $Control/select_effect.current_tab != 4:
  254. var button = $Control/select_effect.find_child("search_fav_" + key, true, false)
  255. if button != null:
  256. button.set_pressed_no_signal(toggled_on)
  257. if toggled_on:
  258. button.text = "★"
  259. else:
  260. button.text = "☆"
  261. _load_favourites(favourites)
  262. func refresh_menu():
  263. pass
  264. func _load_favourites(favourites: Array):
  265. var container = $"Control/select_effect/Favourites/Browse Favourites/MarginContainer/VBoxContainer/ScrollContainer/ItemContainer"
  266. for child in container.get_children():
  267. child.queue_free()
  268. if favourites.size() > 0:
  269. for key in node_data.keys():
  270. var item = node_data[key]
  271. var title = item.get("title", "")
  272. if favourites.has(key) == false:
  273. continue
  274. var short_desc = item.get("short_description", "")
  275. var command = key.replace("_", " ")
  276. var hbox = HBoxContainer.new()
  277. var label = RichTextLabel.new()
  278. var favbtn = Button.new()
  279. var helpbtn = Button.new()
  280. var makebtn = Button.new()
  281. var margin = MarginContainer.new()
  282. hbox.size.x = container.size.x
  283. label.bbcode_enabled = true
  284. label.text = "[b]%s[/b]\n%s" % [title, short_desc]
  285. label.set_h_size_flags(Control.SIZE_EXPAND_FILL)
  286. label.set_v_size_flags(Control.SIZE_EXPAND_FILL)
  287. label.fit_content = true
  288. favbtn.add_theme_font_size_override("font_size", 20)
  289. favbtn.tooltip_text = "Favourite " + title
  290. favbtn.custom_minimum_size = Vector2(40, 40)
  291. favbtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  292. favbtn.toggle_mode = true
  293. if favourites.has(key):
  294. favbtn.text = "★"
  295. favbtn.set_pressed_no_signal(true)
  296. else:
  297. favbtn.text = "☆"
  298. favbtn.set_script(fav_button_logic)
  299. favbtn.connect("toggled", Callable(self, "_favourite_process").bind(key, favourites)) #pass key (process name) when button is pressed
  300. helpbtn.text = "?"
  301. helpbtn.tooltip_text = "Open help for " + title
  302. helpbtn.custom_minimum_size = Vector2(40, 40)
  303. helpbtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  304. helpbtn.connect("pressed", Callable(self, "_open_help").bind(key, title)) #pass key (process name) when button is pressed
  305. makebtn.text = "+"
  306. makebtn.tooltip_text = "Add " + title + " to thread"
  307. makebtn.custom_minimum_size = Vector2(40, 40)
  308. makebtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  309. makebtn.connect("pressed", Callable(self, "_make_node").bind(key)) #pass key (process name) when button is pressed
  310. margin.add_theme_constant_override("margin_bottom", 3)
  311. container.add_child(hbox)
  312. hbox.add_child(label)
  313. hbox.add_child(favbtn)
  314. hbox.add_child(helpbtn)
  315. hbox.add_child(makebtn)
  316. container.add_child(margin)
  317. else:
  318. var label = RichTextLabel.new()
  319. label.text = "Press the star next to a process in the explore menu to add a favourite."
  320. label.fit_content = true
  321. container.add_child(label)