main_work_window.gd 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. extends PanelContainer
  2. @onready var avatar_type_combo: OptionButton = $VBoxContainer/MarginContainer/ToolBar/AvatarTypeCombo
  3. @onready var avatar_part_combo: OptionButton = $VBoxContainer/MarginContainer/ToolBar/AvatarPartCombo
  4. @onready var palette_combo: OptionButton = $VBoxContainer/MarginContainer/ToolBar/PaletteCombo
  5. @onready var state_panel: VBoxContainer = $VBoxContainer/HSplitContainer/StatePanel
  6. @onready var canvas_2d: Node2D = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer/PanelContainer/SubViewportContainer/SubViewport/Canvas2d
  7. @onready var sub_viewport_container: SubViewportContainer = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer/PanelContainer/SubViewportContainer
  8. @onready var asset_panel: PanelContainer = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer/PanelContainer2/AssetPanel
  9. @onready var panel_container: PanelContainer = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer/PanelContainer
  10. @onready var asset_line_edit: LineEdit = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/AssetLineEdit
  11. @onready var layer_line_edit: LineEdit = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/HBoxContainer/LayerLineEdit
  12. @onready var layer_button: Button = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/HBoxContainer/LayerButton
  13. @onready var layer_offset_spin_box: SpinBox = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/LayerOffsetSpinBox
  14. @onready var position_x_spin_box: SpinBox = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/HBoxContainer2/PositionXSpinBox
  15. @onready var position_y_spin_box: SpinBox = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/HBoxContainer2/PositionYSpinBox
  16. @onready var rotation_spin_box: SpinBox = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/RotationSpinBox
  17. @onready var scale_x_spin_box: SpinBox = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/HBoxContainer4/ScaleXSpinBox
  18. @onready var scale_y_spin_box: SpinBox = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/HBoxContainer4/ScaleYSpinBox
  19. @onready var popup_panel: PopupPanel = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/HBoxContainer/LayerButton/PopupPanel
  20. @onready var layer_selecter: Panel = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer2/MarginContainer/VBoxContainer/GridContainer/HBoxContainer/LayerButton/PopupPanel/LayerSelecter
  21. @onready var palette_property_rich_text_label: RichTextLabel = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer/MarginContainer/VBoxContainer/PalettePropertyRichTextLabel
  22. @onready var guid_line_edit: LineEdit = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer/MarginContainer/VBoxContainer/GridContainer/GuidLineEdit
  23. @onready var name_line_edit: LineEdit = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer/MarginContainer/VBoxContainer/GridContainer/NameLineEdit
  24. @onready var intro_text_edit: TextEdit = $VBoxContainer/HSplitContainer/HSplitContainer/VBoxContainer2/PanelContainer/MarginContainer/VBoxContainer/GridContainer/IntroTextEdit
  25. var avatar_type: String = "Clothes"
  26. var _current_part = null
  27. var _current_part_index = null
  28. var _current_state_code = null
  29. var _current_palette_index = -1
  30. var _current_elements = null
  31. var _current_element_index = -1
  32. var _current_element = null
  33. func _ready() -> void:
  34. state_panel.avatar_type = avatar_type
  35. _init_gui()
  36. func _init_gui():
  37. get_tree().get_root().files_dropped.connect(_on_files_dropped)
  38. visibility_changed.connect(_on_visibility_changed)
  39. avatar_type_combo.item_selected.connect(_on_avatar_type_combo_item_selected)
  40. sub_viewport_container.mouse_entered.connect(_on_canvas_mouse_entered)
  41. sub_viewport_container.mouse_exited.connect(_on_canvas_mouse_exited)
  42. canvas_2d.element_property_changed.connect(_on_canvas_element_property_changed)
  43. canvas_2d.element_selected.connect(_on_canvas_element_selected)
  44. canvas_2d.element_action.connect(_on_canvas_element_action, ConnectFlags.CONNECT_DEFERRED)
  45. canvas_2d.asset_drop.connect(_on_asset_dropped)
  46. asset_panel.asset_updated.connect(_on_asset_updated)
  47. avatar_part_combo.item_selected.connect(_on_avatar_part_combo_item_selected)
  48. state_panel.on_select_change.connect(_on_state_treeview_select_change)
  49. palette_combo.item_selected.connect(_on_palette_combo_item_selected)
  50. position_x_spin_box.value_changed.connect(_on_property_changed.bind("PositionX"))
  51. position_y_spin_box.value_changed.connect(_on_property_changed.bind("PositionY"))
  52. rotation_spin_box.value_changed.connect(_on_property_changed.bind("Rotation"))
  53. scale_x_spin_box.value_changed.connect(_on_property_changed.bind("ScaleX"))
  54. scale_y_spin_box.value_changed.connect(_on_property_changed.bind("ScaleY"))
  55. layer_button.pressed.connect(_on_layer_button_pressed)
  56. layer_selecter.pressed.connect(_on_layer_selecter_pressed)
  57. name_line_edit.text_changed.connect(_on_name_line_edit_text_submitted)
  58. intro_text_edit.text_changed.connect(_on_intro_text_edit_text_submitted)
  59. func _on_visibility_changed() -> void:
  60. if is_visible_in_tree() == true:
  61. set_select(avatar_type, _current_part_index, _current_state_code, _current_element_index)
  62. canvas_2d.sync_background()
  63. else:
  64. canvas_2d.cancle_free_transform()
  65. func load_data():
  66. if AvatarDollDataMgr.initialed == false or avatar_type not in AvatarDollDataMgr.avatar_doll_data:
  67. avatar_part_combo.clear()
  68. return
  69. avatar_part_combo.clear()
  70. var parts = AvatarDollDataMgr.avatar_doll_data[avatar_type]
  71. for part in parts:
  72. avatar_part_combo.add_item(part["Name"])
  73. if parts.size() > 0:
  74. avatar_part_combo.selected = 0
  75. _current_part = AvatarDollDataMgr.avatar_doll_data[avatar_type][0]
  76. palette_combo.clear()
  77. palette_combo.add_item("Default")
  78. for i in range(_current_part["Palettes"].size()):
  79. var palette = _current_part["Palettes"][i]
  80. palette_combo.add_item(palette["Name"])
  81. else:
  82. _current_part = null
  83. state_panel.set_avatar_type(0, true)
  84. update_data()
  85. pass
  86. func update_data():
  87. if _current_part != null:
  88. _current_part_index = avatar_part_combo.selected
  89. _current_state_code = state_panel.current_state_code
  90. _current_part = AvatarDollDataMgr.avatar_doll_data[avatar_type][_current_part_index]
  91. _current_element = null
  92. _current_element_index = -1
  93. state_panel.set_avatar_type(_current_part_index, false)
  94. if _current_state_code in _current_part["Elements"]:
  95. _current_elements = _current_part["Elements"][_current_state_code]
  96. canvas_2d.set_editable(true)
  97. canvas_2d.load_elements(_current_elements)
  98. elif _current_state_code != "":
  99. _current_elements = []
  100. _current_part["Elements"][_current_state_code] = _current_elements
  101. canvas_2d.set_editable(true)
  102. canvas_2d.load_elements(_current_elements)
  103. else:
  104. _current_elements = null
  105. canvas_2d.set_editable(false)
  106. canvas_2d.load_elements([])
  107. canvas_2d.zoom_fit()
  108. # palette
  109. palette_combo.clear()
  110. palette_combo.add_item("Default")
  111. for i in range(_current_part["Palettes"].size()):
  112. var palette = _current_part["Palettes"][i]
  113. palette_combo.add_item(palette["Name"])
  114. asset_panel.update_data()
  115. else:
  116. canvas_2d.load_elements([])
  117. canvas_2d.set_editable(false)
  118. update_property()
  119. update_asset_property()
  120. pass
  121. func update_property():
  122. if AvatarDollDataMgr.initialed == false or _current_part == null:
  123. name_line_edit.editable = false
  124. intro_text_edit.editable = false
  125. guid_line_edit.text = ""
  126. name_line_edit.text = ""
  127. intro_text_edit.text = ""
  128. palette_property_rich_text_label.text = "[font_size=20][b]Property[/b][/font_size]"
  129. return
  130. name_line_edit.editable = true
  131. intro_text_edit.editable = true
  132. if _current_palette_index < 0:
  133. palette_property_rich_text_label.text = "[font_size=20][b]Property [Default][/b][/font_size]"
  134. guid_line_edit.text = str(_current_palette_index)
  135. name_line_edit.text = _current_part["Name"]
  136. intro_text_edit.text = _current_part["Introduction"]
  137. else:
  138. palette_property_rich_text_label.text = "[font_size=20][b]Property [Palette %d][/b][/font_size]" % _current_palette_index
  139. guid_line_edit.text = str(_current_palette_index)
  140. name_line_edit.text = _current_part["Palettes"][_current_palette_index]["Name"]
  141. intro_text_edit.text = _current_part["Palettes"][_current_palette_index]["Introduction"]
  142. func update_asset_property():
  143. if _current_element != null:
  144. asset_line_edit.text = AvatarDollDataMgr.get_asset_name(_current_element["AssetId"])
  145. layer_line_edit.text = str(_current_element["Layer"])
  146. layer_offset_spin_box.set_value_no_signal(_current_element["LayerOffset"])
  147. position_x_spin_box.set_value_no_signal(_current_element["PositionX"])
  148. position_y_spin_box.set_value_no_signal(_current_element["PositionY"])
  149. rotation_spin_box.set_value_no_signal(_current_element["Rotation"])
  150. scale_x_spin_box.set_value_no_signal(_current_element["ScaleX"])
  151. scale_y_spin_box.set_value_no_signal(_current_element["ScaleY"])
  152. layer_button.disabled = false
  153. layer_offset_spin_box.editable = true
  154. position_x_spin_box.editable = true
  155. position_y_spin_box.editable = true
  156. rotation_spin_box.editable = true
  157. scale_x_spin_box.editable = true
  158. scale_y_spin_box.editable = true
  159. else:
  160. asset_line_edit.text = "-1"
  161. layer_line_edit.text = "0"
  162. layer_offset_spin_box.set_value_no_signal(0)
  163. position_x_spin_box.set_value_no_signal(0)
  164. position_y_spin_box.set_value_no_signal(0)
  165. rotation_spin_box.set_value_no_signal(0)
  166. scale_x_spin_box.set_value_no_signal(0)
  167. scale_y_spin_box.set_value_no_signal(0)
  168. layer_button.disabled = true
  169. layer_offset_spin_box.editable = false
  170. position_x_spin_box.editable = false
  171. position_y_spin_box.editable = false
  172. rotation_spin_box.editable = false
  173. scale_x_spin_box.editable = false
  174. scale_y_spin_box.editable = false
  175. func set_select(new_type, part_index, state_code, element_index):
  176. if AvatarDollDataMgr.initialed == false or new_type not in AvatarDollDataMgr.avatar_doll_data:
  177. return
  178. avatar_type_combo.set_block_signals(true)
  179. avatar_type_combo.selected = AvatarDollDataMgr.avatar_part_scope.keys().find(new_type)
  180. avatar_type_combo.set_block_signals(false)
  181. state_panel.avatar_type = new_type
  182. avatar_type = new_type
  183. load_data()
  184. if part_index < AvatarDollDataMgr.avatar_doll_data[avatar_type].size():
  185. _current_part_index = part_index
  186. avatar_part_combo.selected = part_index
  187. _current_part = AvatarDollDataMgr.avatar_doll_data[avatar_type][part_index]
  188. if state_code in _current_part["Elements"]:
  189. state_panel.set_state_code(state_code)
  190. _current_state_code = state_code
  191. if element_index >= 0 and element_index < _current_part["Elements"][state_code].size():
  192. _current_elements = _current_part["Elements"][state_code]
  193. _current_element_index = element_index
  194. _current_element = _current_elements[element_index]
  195. canvas_2d.load_elements(_current_elements, element_index)
  196. #update_asset_property()
  197. func set_palette(index):
  198. _current_palette_index = index
  199. update_property()
  200. var state_code = state_panel.current_state_code
  201. if state_code not in _current_part["Elements"]:
  202. _current_state_code = null
  203. return
  204. var palettes = AvatarDollDataMgr.get_render_palettes(avatar_type, avatar_part_combo.selected, state_code, index, false)
  205. for asset_name in palettes:
  206. canvas_2d.update_palette(asset_name, palettes[asset_name])
  207. func _on_avatar_type_combo_item_selected(index):
  208. avatar_type = avatar_type_combo.get_item_text(index)
  209. state_panel.avatar_type = avatar_type
  210. load_data()
  211. func _on_avatar_part_combo_item_selected(index):
  212. _current_part = AvatarDollDataMgr.avatar_doll_data[avatar_type][index]
  213. _current_palette_index = -1
  214. update_data()
  215. canvas_2d.zoom_fit()
  216. func _on_palette_combo_item_selected(index):
  217. set_palette(index - 1)
  218. func _on_state_treeview_select_change(_avatar_type, _index, _state_code):
  219. update_data()
  220. set_palette(_current_palette_index)
  221. canvas_2d.zoom_fit()
  222. func _on_canvas_mouse_entered():
  223. canvas_2d.update_mouse_in_canvas(true)
  224. func _on_canvas_mouse_exited():
  225. canvas_2d.update_mouse_in_canvas(false)
  226. func _on_canvas_element_selected(index: int):
  227. _current_element_index = index
  228. _current_element = _current_elements[index] if index != -1 else null
  229. update_asset_property()
  230. func _on_canvas_element_property_changed(_index: int, _position: Vector2, _rotation: float, _scale: Vector2, _skew: float):
  231. if _current_part == null or _current_state_code == null:
  232. return
  233. _current_element["PositionX"] = _position.x
  234. _current_element["PositionY"] = _position.y
  235. _current_element["Rotation"] = _rotation
  236. _current_element["ScaleX"] = _scale.x
  237. _current_element["ScaleY"] = _scale.y
  238. _current_element["Skew"] = _skew
  239. update_asset_property()
  240. func _on_canvas_element_action(index: int, action: String, data: Dictionary):
  241. if action == "UP" and index > 0:
  242. var temp = _current_elements[index - 1]
  243. _current_elements[index - 1] = _current_elements[index]
  244. _current_elements[index] = temp
  245. canvas_2d.load_elements(_current_elements, index - 1)
  246. elif action == "DOWN" and index < _current_elements.size() - 1:
  247. var temp = _current_elements[index + 1]
  248. _current_elements[index + 1] = _current_elements[index]
  249. _current_elements[index] = temp
  250. canvas_2d.load_elements(_current_elements, index + 1)
  251. elif action == "REMOVE":
  252. var msg = "确定删除 %s 吗?" % AvatarDollDataMgr.get_asset_name(_current_elements[index]["AssetId"])
  253. var msg_box = MessageBox.warning(self,
  254. "警告", msg,
  255. MessageBox.StandardButton.YES | MessageBox.StandardButton.NO)
  256. msg_box.accepted.connect(func():
  257. _current_elements.remove_at(index)
  258. canvas_2d.load_elements(_current_elements)
  259. state_panel.update_data()
  260. )
  261. pass
  262. func _on_property_changed(value, property: String):
  263. _current_element[property] = value
  264. update_asset_property()
  265. canvas_2d.update_element(_current_element_index, _current_element)
  266. func _on_name_line_edit_text_submitted(new_text):
  267. if not AvatarDollDataMgr.initialed or _current_part == null:
  268. return
  269. var new_name = name_line_edit.text
  270. if _current_palette_index < 0:
  271. _current_part["Name"] = new_name
  272. avatar_part_combo.set_item_text(_current_part_index, new_name)
  273. else:
  274. _current_part["Palettes"][_current_palette_index]["Name"] = new_name
  275. palette_combo.set_item_text(_current_palette_index, new_name)
  276. func _on_intro_text_edit_text_submitted():
  277. if not AvatarDollDataMgr.initialed or _current_part == null:
  278. return
  279. if _current_palette_index < 0:
  280. _current_part["Introduction"] = intro_text_edit.text
  281. else:
  282. _current_part["Palettes"][_current_palette_index]["Introduction"] = intro_text_edit.text
  283. func _on_layer_button_pressed():
  284. var pos = layer_button.global_position + layer_button.get_rect().size
  285. pos.x -= popup_panel.size.x
  286. popup_panel.position = pos
  287. popup_panel.show()
  288. func _on_layer_selecter_pressed(index):
  289. popup_panel.hide()
  290. _current_element["Layer"] = index
  291. update_asset_property()
  292. func _on_files_dropped(files):
  293. if not AvatarDollDataMgr.initialed:
  294. return
  295. if mouse_over_control(sub_viewport_container):
  296. if _current_state_code:
  297. for file_path in files:
  298. var asset_id = AvatarDollDataMgr.load_asset(file_path)
  299. if _current_elements != null:
  300. var element = {}
  301. element["AssetId"] = asset_id
  302. element["LayerOffset"] = 0
  303. element["PositionX"] = 0.0
  304. element["PositionY"] = 0.0
  305. element["Rotation"] = 0.0
  306. element["ScaleX"] = 1.0
  307. element["ScaleY"] = 1.0
  308. element["Skew"] = 0.0
  309. match avatar_type:
  310. "Bodies": element["Layer"] = 0
  311. "Heads": element["Layer"] = 9
  312. "Hairs": element["Layer"] = 10
  313. "Faces": element["Layer"] = 14
  314. "Clothes": element["Layer"] = 7
  315. _current_elements.append(element)
  316. update_data()
  317. canvas_2d.set_selected(_current_elements.size() - 1)
  318. else:
  319. for file_path in files:
  320. var asset_id = AvatarDollDataMgr.load_asset(file_path)
  321. update_data()
  322. elif mouse_over_control(asset_panel):
  323. for file_path in files:
  324. var asset_id = AvatarDollDataMgr.load_asset(file_path)
  325. update_data()
  326. func _on_asset_dropped(asset_name, pos):
  327. if _current_elements == null:
  328. return
  329. var element = {}
  330. element["AssetId"] = AvatarDollDataMgr.get_asset_id(asset_name)
  331. element["LayerOffset"] = 0
  332. element["PositionX"] = pos.x
  333. element["PositionY"] = pos.y
  334. element["Rotation"] = 0.0
  335. element["ScaleX"] = 1.0
  336. element["ScaleY"] = 1.0
  337. element["Skew"] = 0.0
  338. match avatar_type:
  339. "Bodies": element["Layer"] = 0
  340. "Heads": element["Layer"] = 9
  341. "Hairs": element["Layer"] = 10
  342. "Faces": element["Layer"] = 14
  343. "Clothes": element["Layer"] = 7
  344. _current_elements.append(element)
  345. update_data()
  346. canvas_2d.set_selected(_current_elements.size() - 1)
  347. func _on_asset_updated():
  348. update_data()
  349. func mouse_over_control(node: Control):
  350. var rect = node.get_global_transform() * node.get_rect()
  351. var mouse = get_global_mouse_position()
  352. return rect.has_point(mouse)