json_editor.gd 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. extends Control
  2. var node_data = {} #stores json file
  3. @onready var parameter_container = $HBoxContainer/VBoxContainer2/ScrollContainer/parameter_container
  4. var json = "res://scenes/main/process_help.json"
  5. func _ready() -> void:
  6. load_json()
  7. hidpi_adjustment()
  8. func hidpi_adjustment():
  9. #checks if display is hidpi and scales ui accordingly hidpi - 144
  10. if DisplayServer.screen_get_dpi(0) >= 144:
  11. get_window().content_scale_factor = 2.0
  12. func load_json():
  13. var file = FileAccess.open(json, FileAccess.READ)
  14. if file:
  15. node_data = JSON.parse_string(file.get_as_text())
  16. fill_search("")
  17. func fill_search(filter: String):
  18. # Remove all existing items from the VBoxContainer
  19. var container = $HBoxContainer/VBoxContainer/search/MarginContainer/VBoxContainer/ScrollContainer/ItemContainer
  20. for child in container.get_children():
  21. child.queue_free()
  22. for key in node_data.keys():
  23. var item = node_data[key]
  24. var title = item.get("title", "")
  25. var category = item.get("category", "")
  26. var subcategory = item.get("subcategory", "")
  27. var short_desc = item.get("short_description", "")
  28. # If filter is not empty, skip non-matches populate all other buttons
  29. if filter != "":
  30. var filter_lc = filter.to_lower()
  31. if not (filter_lc in title.to_lower() or filter_lc in short_desc.to_lower() or filter_lc in category.to_lower() or filter_lc in subcategory.to_lower()):
  32. continue
  33. var hbox = HBoxContainer.new()
  34. var label = RichTextLabel.new()
  35. var editbtn = Button.new()
  36. var margin = MarginContainer.new()
  37. hbox.size.x = container.size.x
  38. label.bbcode_enabled = true
  39. label.text = "[b]%s[/b]\n%s" % [title, short_desc]
  40. label.set_h_size_flags(Control.SIZE_EXPAND_FILL)
  41. label.set_v_size_flags(Control.SIZE_EXPAND_FILL)
  42. label.fit_content = true
  43. editbtn.text = "Edit"
  44. editbtn.custom_minimum_size = Vector2(80, 40)
  45. editbtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
  46. editbtn.connect("pressed", Callable(self, "edit_node").bind(key)) #pass key (process name) when button is pressed
  47. margin.add_theme_constant_override("margin_bottom", 3)
  48. container.add_child(hbox)
  49. hbox.add_child(label)
  50. hbox.add_child(editbtn)
  51. container.add_child(margin)
  52. func _on_search_bar_text_changed(new_text: String) -> void:
  53. fill_search(new_text)
  54. func edit_node(key: String):
  55. if node_data.has(key):
  56. #looks up the help data from the json and stores it in info
  57. var info = node_data[key]
  58. var parameters = info.get("parameters", {})
  59. $HBoxContainer/VBoxContainer2/HBoxContainer/key.text = key
  60. $HBoxContainer/VBoxContainer2/HBoxContainer2/category.text = info.get("category", "")
  61. $HBoxContainer/VBoxContainer2/HBoxContainer3/subcategory.text = info.get("subcategory", "")
  62. $HBoxContainer/VBoxContainer2/HBoxContainer4/title.text = info.get("title", "")
  63. $HBoxContainer/VBoxContainer2/HBoxContainer5/shortdescription.text = info.get("short_description", "")
  64. $HBoxContainer/VBoxContainer2/HBoxContainer7/longdescription.text = info.get("description", "")
  65. $HBoxContainer/VBoxContainer2/HBoxContainer6/stereo.button_pressed = bool(info.get("stereo"))
  66. $HBoxContainer/VBoxContainer2/HBoxContainer8/outputisstereo.button_pressed = bool(info.get("outputisstereo"))
  67. $HBoxContainer/VBoxContainer2/HBoxContainer9/inputtype.text = str(info.get("inputtype", ""))
  68. $HBoxContainer/VBoxContainer2/HBoxContainer11/outputtype.text = str(info.get("outputtype", ""))
  69. $HBoxContainer/VBoxContainer2/HBoxContainer10/allowbypass.button_pressed = bool(info.get("allowbypass"))
  70. for child in parameter_container.get_children():
  71. child.queue_free()
  72. var count = 1
  73. for param_key in parameters.keys():
  74. var param_box = VBoxContainer.new()
  75. param_box.set_h_size_flags(Control.SIZE_EXPAND_FILL)
  76. parameter_container.add_child(param_box)
  77. var label = Label.new()
  78. label.text = "Parameter " + str(count)
  79. param_box.add_child(label)
  80. var param_data = parameters[param_key]
  81. for field_key in param_data.keys():
  82. var field_value = param_data[field_key]
  83. var hbox = HBoxContainer.new()
  84. var namelabel = RichTextLabel.new()
  85. var namefield
  86. namelabel.text = field_key
  87. namelabel.custom_minimum_size.x = 250
  88. if field_value is bool:
  89. namefield = CheckBox.new()
  90. namefield.button_pressed = field_value
  91. else:
  92. namefield = LineEdit.new()
  93. namefield.text = str(field_value)
  94. namefield.set_h_size_flags(Control.SIZE_EXPAND_FILL)
  95. hbox.add_child(namelabel)
  96. hbox.add_child(namefield)
  97. param_box.add_child(hbox)
  98. var delete_button = Button.new()
  99. delete_button.text = "Delete " + param_data.get("paramname", "")
  100. delete_button.set_h_size_flags(Control.SIZE_EXPAND)
  101. delete_button.connect("pressed", Callable(self, "delete_param").bind(param_box))
  102. param_box.add_child(delete_button)
  103. var margin = MarginContainer.new()
  104. margin.add_theme_constant_override("margin_bottom", 5)
  105. param_box.add_child(margin)
  106. count += 1
  107. func delete_param(container: VBoxContainer):
  108. container.queue_free()
  109. func _on_button_button_down() -> void:
  110. var info = node_data["distort_replace"]
  111. var parameters = info.get("parameters", {})
  112. var parameter = parameters.get("param1", {})
  113. var param_box = VBoxContainer.new()
  114. param_box.set_h_size_flags(Control.SIZE_EXPAND_FILL)
  115. parameter_container.add_child(param_box)
  116. var label = Label.new()
  117. label.text = "New Parameter"
  118. param_box.add_child(label)
  119. for field_key in parameter.keys():
  120. var field_value = parameter[field_key]
  121. var hbox = HBoxContainer.new()
  122. var namelabel = RichTextLabel.new()
  123. var namefield
  124. namelabel.text = field_key
  125. namelabel.custom_minimum_size.x = 250
  126. if field_value is bool:
  127. namefield = CheckBox.new()
  128. else:
  129. namefield = LineEdit.new()
  130. namefield.set_h_size_flags(Control.SIZE_EXPAND_FILL)
  131. hbox.add_child(namelabel)
  132. hbox.add_child(namefield)
  133. param_box.add_child(hbox)
  134. var delete_button = Button.new()
  135. delete_button.text = "Delete"
  136. delete_button.set_h_size_flags(Control.SIZE_EXPAND)
  137. delete_button.connect("pressed", Callable(self, "delete_param").bind(param_box))
  138. param_box.add_child(delete_button)
  139. var margin = MarginContainer.new()
  140. margin.add_theme_constant_override("margin_bottom", 5)
  141. param_box.add_child(margin)
  142. func save_node(is_new: bool) -> void:
  143. var key = $HBoxContainer/VBoxContainer2/HBoxContainer/key.text.strip_edges()
  144. if key == "":
  145. printerr("Key is empty, cannot save")
  146. return
  147. var info = {
  148. "category": $HBoxContainer/VBoxContainer2/HBoxContainer2/category.text,
  149. "subcategory": $HBoxContainer/VBoxContainer2/HBoxContainer3/subcategory.text,
  150. "title": $HBoxContainer/VBoxContainer2/HBoxContainer4/title.text,
  151. "short_description": $HBoxContainer/VBoxContainer2/HBoxContainer5/shortdescription.text,
  152. "description": $HBoxContainer/VBoxContainer2/HBoxContainer7/longdescription.text,
  153. "stereo": $HBoxContainer/VBoxContainer2/HBoxContainer6/stereo.button_pressed,
  154. "outputisstereo": $HBoxContainer/VBoxContainer2/HBoxContainer8/outputisstereo.button_pressed,
  155. "inputtype": $HBoxContainer/VBoxContainer2/HBoxContainer9/inputtype.text,
  156. "outputtype": $HBoxContainer/VBoxContainer2/HBoxContainer11/outputtype.text,
  157. "allowbypass": $HBoxContainer/VBoxContainer2/HBoxContainer10/allowbypass.button_pressed,
  158. "parameters": {}
  159. }
  160. for param_box in parameter_container.get_children():
  161. var children = param_box.get_children()
  162. if children.size() < 2:
  163. continue
  164. var param_data = {}
  165. var param_label = children[0] as Label
  166. var param_id = "param" + str(parameter_container.get_children().find(param_box) + 1)
  167. for i in range(1, children.size()):
  168. var node = children[i]
  169. if node is HBoxContainer and node.get_child_count() >= 2:
  170. var field_name = node.get_child(0).text
  171. var input_field = node.get_child(1)
  172. var field_value
  173. if input_field is CheckBox:
  174. field_value = input_field.button_pressed
  175. else:
  176. var raw_text = input_field.text
  177. if raw_text.is_valid_float():
  178. field_value = raw_text.to_float()
  179. elif raw_text.is_valid_int():
  180. field_value = raw_text.to_int()
  181. elif raw_text.to_lower() == "true":
  182. field_value = true
  183. elif raw_text.to_lower() == "false":
  184. field_value = false
  185. else:
  186. field_value = raw_text
  187. param_data[field_name] = field_value
  188. if param_data.size() > 0:
  189. info["parameters"][param_id] = param_data
  190. # Save or update entry
  191. node_data[key] = info
  192. # Write to file
  193. var file = FileAccess.open(json, FileAccess.WRITE)
  194. if file:
  195. file.store_string(JSON.stringify(node_data, "\t")) # pretty print with tab indent
  196. file.close()
  197. fill_search("") # refresh list
  198. $HBoxContainer/VBoxContainer/search/MarginContainer/VBoxContainer/SearchBar.text = ""
  199. func _on_save_changes_button_down() -> void:
  200. save_node(false)
  201. func _on_save_new_button_down() -> void:
  202. save_node(true)
  203. func _on_delete_process_button_down() -> void:
  204. var key = $HBoxContainer/VBoxContainer2/HBoxContainer/key.text.strip_edges()
  205. if key == "":
  206. printerr("No key entered – cannot delete.")
  207. return
  208. if not node_data.has(key):
  209. printerr("Key '%s' not found in JSON." % key)
  210. return
  211. # Remove entry from the dictionary
  212. node_data.erase(key)
  213. # Save updated JSON to file
  214. var file = FileAccess.open(json, FileAccess.WRITE)
  215. if file:
  216. file.store_string(JSON.stringify(node_data, "\t")) # pretty print
  217. file.close()
  218. print("Deleted entry: ", key)
  219. # refresh the list
  220. fill_search("")
  221. $HBoxContainer/VBoxContainer/search/MarginContainer/VBoxContainer/SearchBar.text = ""
  222. _on_new_process_button_down()
  223. func _on_new_process_button_down() -> void:
  224. $HBoxContainer/VBoxContainer2/HBoxContainer/key.text = ""
  225. $HBoxContainer/VBoxContainer2/HBoxContainer2/category.text = ""
  226. $HBoxContainer/VBoxContainer2/HBoxContainer3/subcategory.text = ""
  227. $HBoxContainer/VBoxContainer2/HBoxContainer4/title.text = ""
  228. $HBoxContainer/VBoxContainer2/HBoxContainer5/shortdescription.text = ""
  229. $HBoxContainer/VBoxContainer2/HBoxContainer7/longdescription.text = ""
  230. $HBoxContainer/VBoxContainer2/HBoxContainer6/stereo.button_pressed = false
  231. for child in parameter_container.get_children():
  232. child.queue_free()
  233. func _on_sort_json_button_down() -> void:
  234. var is_windows = OS.get_name() == "Windows"
  235. var json_to_sort = ProjectSettings.globalize_path(json)
  236. var python_script = ProjectSettings.globalize_path("res://dev_tools/helpers/sort_json.py")
  237. print(json_to_sort)
  238. print(python_script)
  239. # Run the Python script with the JSON path as an argument
  240. var output = []
  241. var exit_code
  242. if is_windows:
  243. exit_code = OS.execute("cmd.exe", ["/c", python_script, json_to_sort], output, true)
  244. else:
  245. exit_code = OS.execute("python3", [python_script, json_to_sort], output, true)
  246. # Optionally print the output or check the result
  247. print("Exit code: ", exit_code)
  248. print("Output:\n", output)
  249. fill_search("") # refresh list
  250. $HBoxContainer/VBoxContainer/search/MarginContainer/VBoxContainer/SearchBar.text = ""
  251. load_json()