state_treeview.gd 8.3 KB

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