state_treeview.gd 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. extends VBoxContainer
  2. signal on_select_change(avatar_type: String, index: int, state_code: String)
  3. @onready var button_0: Button = $MarginContainer/VBoxContainer/HBoxContainer2/Button0
  4. @onready var button_1: Button = $MarginContainer/VBoxContainer/HBoxContainer2/Button1
  5. @onready var button_2: Button = $MarginContainer/VBoxContainer/HBoxContainer2/Button2
  6. @onready var button_3: Button = $MarginContainer/VBoxContainer/HBoxContainer2/Button3
  7. @onready var button_collapse: Button = $MarginContainer/VBoxContainer/HBoxContainer2/ButtonCollapse
  8. @onready var button_expand: Button = $MarginContainer/VBoxContainer/HBoxContainer2/ButtonExpand
  9. @onready var state_name_label: Label = $MarginContainer/VBoxContainer/StateNameLabel
  10. @onready var state_treeview: Tree = $MarginContainer/VBoxContainer/StateTreeview
  11. var avatar_type: String = "Clothes"
  12. var current_avatar_part = null
  13. var current_avatar_index = 0
  14. var current_tree_item: TreeItem = null
  15. var current_state_code = ""
  16. var state_map = {}
  17. var icon_checked:Texture2D
  18. var icon_warning:Texture2D
  19. var filter_type = 0
  20. var tree_max_depth = 0
  21. var item_collection = {}
  22. func _ready() -> void:
  23. _init_gui()
  24. func _init_gui():
  25. icon_checked = load("res://Resources/UI/checked.png")
  26. icon_warning = load("res://Resources/UI/warning.png")
  27. state_treeview.columns = 3
  28. state_treeview.hide_root = true
  29. state_treeview.set_column_custom_minimum_width(1, 60)
  30. state_treeview.set_column_custom_minimum_width(2, 16)
  31. state_treeview.set_column_expand(0, true)
  32. state_treeview.set_column_expand(1, false)
  33. state_treeview.set_column_expand(2, false)
  34. state_treeview.item_selected.connect(_on_state_treeview_item_selected)
  35. state_treeview.item_activated.connect(_on_state_treeview_item_activated)
  36. state_treeview.create_item()
  37. var group = ButtonGroup.new()
  38. var buttons = [button_0, button_1, button_2, button_3]
  39. for i in range(buttons.size()):
  40. var button = buttons[i]
  41. button.button_group = group
  42. button.pressed.connect(_on_filter_button_pressed.bind(i))
  43. button_collapse.pressed.connect(_on_button_collapse_pressed)
  44. button_expand.pressed.connect(_on_button_expand_pressed)
  45. func set_avatar_type(index, rebuild_tree: bool):
  46. current_avatar_index = index
  47. if current_avatar_index >= 0 and AvatarDollDataMgr.avatar_doll_data[avatar_type].size() > index:
  48. current_avatar_part = AvatarDollDataMgr.avatar_doll_data[avatar_type][index]
  49. update_data(rebuild_tree)
  50. func set_state_code(state_code):
  51. var item = state_treeview.get_root()
  52. for c in state_code:
  53. var index = AvatarDollDataMgr.get_state_index(c)
  54. item = item.get_child(index)
  55. if item == null:
  56. return
  57. state_treeview.set_selected(item, 0)
  58. state_treeview.scroll_to_item(item)
  59. _on_state_treeview_item_selected()
  60. func update_data(rebuild_tree: bool = false):
  61. if not AvatarDollDataMgr.initialed or avatar_type not in AvatarDollDataMgr.avatar_doll_data:
  62. state_treeview.clear()
  63. state_treeview.create_item() # root
  64. return
  65. #var old_index = current_avatar_index
  66. #var old_state = current_state_code
  67. var states = AvatarDollDataMgr.avatar_part_state[avatar_type]
  68. var root
  69. if rebuild_tree:
  70. state_treeview.clear()
  71. root = state_treeview.create_item()
  72. item_collection = {}
  73. if current_avatar_index >= 0:
  74. tree_max_depth = states.size()
  75. for i in range(tree_max_depth):
  76. item_collection[i] = []
  77. _add_state_item(rebuild_tree, states, root)
  78. else:
  79. root = state_treeview.get_root()
  80. if current_avatar_index >= 0:
  81. _add_state_item(rebuild_tree, states, root)
  82. func _add_state_item(rebuild_tree, states: Array, parent: TreeItem, depth = 0, current_list = ["R"], state_code=""):
  83. if depth >= states.size():
  84. var state_name = "/".join(current_list)
  85. var setup = current_avatar_part["Elements"].get(state_code, []).size() > 0
  86. var requirment = current_list[0] == "R"
  87. if setup:
  88. parent.set_icon(2, icon_checked)
  89. elif requirment:
  90. parent.set_icon(2, icon_warning)
  91. else:
  92. parent.set_icon(2, null)
  93. if (filter_type == 1 and not setup) or \
  94. (filter_type == 2 and not requirment) or \
  95. (filter_type == 3 and not (requirment and not setup)):
  96. parent.visible = false
  97. else:
  98. parent.visible = true
  99. parent.set_metadata(0, state_name)
  100. parent.set_metadata(1, state_code)
  101. parent.set_metadata(2, Vector3i(1 if setup else 0, 1 if requirment else 0, 1))
  102. parent.set_custom_color(0, Color.WHITE)
  103. else:
  104. var state = states[depth]
  105. var state_count = state["Values"].size()
  106. var item
  107. for i in range(state_count):
  108. var value = state["Values"][i]
  109. if rebuild_tree:
  110. item = parent.create_child()
  111. item_collection[depth].append(item)
  112. else:
  113. item = parent.get_child(i)
  114. var c = AvatarDollDataMgr.get_state_char(i)
  115. item.set_text(0, "%s %s" % [c, value])
  116. item.set_cell_mode(2, TreeItem.CELL_MODE_ICON)
  117. var new_list = current_list + [value]
  118. var new_code = state_code + c
  119. if state["Required"][i] == false:
  120. new_list[0] = "N"
  121. _add_state_item(rebuild_tree, states, item, depth + 1, new_list, new_code)
  122. var parent_visible = false
  123. var total = Vector3i.ZERO
  124. var missing = false
  125. for child in parent.get_children():
  126. if child.visible == true:
  127. parent_visible = true
  128. if child.get_icon(2) == icon_warning:
  129. missing = true
  130. total += child.get_metadata(2)
  131. parent.visible = parent_visible
  132. parent.set_text(1, "%d/%d/%d" % [total.x, total.y, total.z])
  133. parent.set_text_alignment(1, HORIZONTAL_ALIGNMENT_RIGHT)
  134. parent.set_icon(2, icon_warning if missing else icon_checked)
  135. parent.set_metadata(2, total)
  136. parent.set_custom_color(0, Color(0.6, 0.6, 0.6))
  137. func _on_filter_button_pressed(index):
  138. filter_type = index
  139. update_data()
  140. func _on_state_treeview_item_selected():
  141. var item = state_treeview.get_selected()
  142. var state_name = item.get_metadata(0)
  143. var state_code = item.get_metadata(1)
  144. if state_code != null:
  145. var parent
  146. if current_tree_item != null:
  147. current_tree_item.clear_custom_bg_color(0)
  148. current_tree_item.clear_custom_bg_color(1)
  149. current_tree_item.clear_custom_bg_color(2)
  150. parent = current_tree_item.get_parent()
  151. while parent != state_treeview.get_root():
  152. parent.clear_custom_bg_color(0)
  153. parent.clear_custom_bg_color(1)
  154. parent.clear_custom_bg_color(2)
  155. parent = parent.get_parent()
  156. var color = Color(0.0, 0.6, 0.8, 1.0)
  157. item.set_custom_bg_color(0, color)
  158. item.set_custom_bg_color(1, color)
  159. item.set_custom_bg_color(2, color)
  160. color = Color(0.0, 0.3, 0.4, 1.0)
  161. parent = item.get_parent()
  162. while parent != state_treeview.get_root():
  163. parent.set_custom_bg_color(0, color)
  164. parent.set_custom_bg_color(1, color)
  165. parent.set_custom_bg_color(2, color)
  166. parent = parent.get_parent()
  167. current_tree_item = item
  168. current_state_code = state_code
  169. state_name_label.text = "%s %s" % [state_code, state_name.substr(2)]
  170. on_select_change.emit(avatar_type, current_avatar_index, state_code)
  171. print("State: ", state_name, " ", state_code)
  172. pass
  173. func _on_state_treeview_item_activated():
  174. var item = state_treeview.get_selected()
  175. var state_code = item.get_metadata(1)
  176. if state_code == null:
  177. item.collapsed = not item.collapsed
  178. func _on_button_collapse_pressed():
  179. if not AvatarDollDataMgr.initialed:
  180. return
  181. var result = _collect_tree_item_collapse_and_expand(state_treeview.get_root(), tree_max_depth - 1)
  182. var max_expand = result[1]
  183. while max_expand < tree_max_depth:
  184. for item in item_collection[max_expand - 1]:
  185. item.collapsed = true
  186. max_expand += 1
  187. func _on_button_expand_pressed():
  188. if not AvatarDollDataMgr.initialed:
  189. return
  190. var result = _collect_tree_item_collapse_and_expand(state_treeview.get_root(), tree_max_depth - 1)
  191. var min_collapse = result[0]
  192. while min_collapse > 0:
  193. for item in item_collection[min_collapse - 1]:
  194. item.collapsed = false
  195. min_collapse -= 1
  196. func _collect_tree_item_collapse_and_expand(parent: TreeItem, min_collapse:int = 9999, max_expand:int = 1, depth = 0):
  197. if parent.get_child_count() == 0:
  198. return [9999, 0]
  199. var all_collapsed = false
  200. for item in parent.get_children():
  201. if item.collapsed:
  202. min_collapse = min(min_collapse, depth + 1)
  203. else:
  204. all_collapsed = false
  205. var result = _collect_tree_item_collapse_and_expand(item, min_collapse, depth + 1, depth + 1)
  206. min_collapse = min(min_collapse, result[0])
  207. max_expand = max(max_expand, result[1])
  208. if all_collapsed:
  209. return [min_collapse, depth]
  210. else:
  211. return [min_collapse, max_expand]