avatar_doll_data_manager.gd 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. extends Node
  2. class_name AvatarDollDataManager
  3. static var instance: AvatarDollDataManager
  4. var avatar_part_scope = {"Clothes": 0, "Bodies": 1, "Heads": 2, "Hairs": 3, "Faces": 4}
  5. var default_texture: Texture2D = preload("res://Resources/UI/missing_image.png")
  6. var blank_texture: Texture2D = preload("res://Resources/__blank__.png")
  7. var initialed = false
  8. var work_json_file = ""
  9. var avatar_part_state = {}
  10. var avatar_part_state_name_to_index = {}
  11. var avatar_part_state_index_to_name = {}
  12. var avatar_doll_data = null
  13. var avatar_asset_id_max = -1
  14. var avatar_asset = {}
  15. var avatar_asset_name = {}
  16. var char_to_index: Dictionary = {}
  17. var index_to_char: Dictionary = {}
  18. func _init():
  19. instance = self
  20. var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  21. for i in range(chars.length()):
  22. var c = chars[i]
  23. char_to_index[c] = i
  24. index_to_char[i] = str(c)
  25. func load_json(json_path) -> bool:
  26. var file = FileAccess.open(json_path, FileAccess.READ)
  27. var json_str = file.get_as_text()
  28. var json = JSON.new()
  29. var error = json.parse(json_str)
  30. if error != OK:
  31. push_error("load_avatar_doll_json ERROR!")
  32. initialed = false
  33. return false
  34. avatar_doll_data = _fix_avatar_dool_data(json.get_data())
  35. work_json_file = json_path
  36. # _load_setting
  37. reload_setting()
  38. # AssetMap
  39. reload_all_asset()
  40. initialed = true
  41. return true
  42. func save_json(json_path=""):
  43. if json_path == "":
  44. json_path = work_json_file
  45. if json_path == "" or initialed == false:
  46. return
  47. var data = _fix_avatar_dool_data(avatar_doll_data)
  48. var json_str = JSON.stringify(data)
  49. var file = FileAccess.open(json_path, FileAccess.WRITE)
  50. file.store_string(json_str)
  51. file.close()
  52. func reload_setting():
  53. avatar_part_state.clear()
  54. avatar_part_state_name_to_index.clear()
  55. avatar_part_state_index_to_name.clear()
  56. for part in avatar_part_scope:
  57. avatar_part_state[part] = []
  58. var scope_flag = avatar_part_scope[part]
  59. for state in avatar_doll_data["Settings"]["States"]:
  60. if 1 == 1 & (int(state["Scope"]) >> scope_flag):
  61. avatar_part_state[part].append(state)
  62. var result = {}
  63. _full_permutation_state(result, avatar_part_state[part])
  64. avatar_part_state_name_to_index[part] = result
  65. var swapped_dict = {}
  66. for key in result:
  67. var value = result[key]
  68. swapped_dict[value] = key
  69. avatar_part_state_index_to_name[part] = swapped_dict
  70. func _fix_avatar_dool_data(data):
  71. # fix data
  72. data["FormatVersion"] = int(data["FormatVersion"])
  73. data["Settings"]["MaxBodySlotCost"] = int(data["Settings"]["MaxBodySlotCost"])
  74. for i in range(data["Settings"]["States"].size()):
  75. data["Settings"]["States"][i]["Id"] = int(data["Settings"]["States"][i]["Id"])
  76. data["Settings"]["States"][i]["Scope"] = int(data["Settings"]["States"][i]["Scope"])
  77. var new_map = {}
  78. for key in data["AssetMap"]:
  79. if key is String and not key.is_valid_int():
  80. continue
  81. elif key is int and key <= 0:
  82. continue
  83. var asset_id = int(key)
  84. if asset_id > 0:
  85. new_map[asset_id] = [
  86. data["AssetMap"][key][0].simplify_path(),
  87. int(data["AssetMap"][key][1]),
  88. int(data["AssetMap"][key][2])
  89. ]
  90. data["AssetMap"] = new_map
  91. for p in avatar_part_scope.keys():
  92. if p not in data:
  93. continue
  94. for index in range(data[p].size()):
  95. #data[p][index]["Guid"] = data[p][index]["Guid"]
  96. data[p][index]["IconAssetId"] = int(data[p][index]["IconAssetId"])
  97. for i in range(data[p][index]["Palettes"].size()):
  98. #data[p][index]["Palettes"][i]["Guid"] = data[p][index]["Palettes"][i]["Guid"]
  99. for j in range(data[p][index]["Palettes"][i]["IconPaletteParam"].size()):
  100. data[p][index]["Palettes"][i]["IconPaletteParam"][j]["ElementIndex"] = int(data[p][index]["Palettes"][i]["IconPaletteParam"][j]["ElementIndex"])
  101. data[p][index]["Palettes"][i]["IconPaletteParam"][j]["BlendMode"] = int(data[p][index]["Palettes"][i]["IconPaletteParam"][j]["BlendMode"])
  102. for j in range(data[p][index]["Palettes"][i]["ElementPaletteParam"].size()):
  103. data[p][index]["Palettes"][i]["ElementPaletteParam"][j]["ElementIndex"] = int(data[p][index]["Palettes"][i]["ElementPaletteParam"][j]["ElementIndex"])
  104. data[p][index]["Palettes"][i]["ElementPaletteParam"][j]["BlendMode"] = int(data[p][index]["Palettes"][i]["ElementPaletteParam"][j]["BlendMode"])
  105. var elements = {}
  106. for key in data[p][index]["Elements"]:
  107. if data[p][index]["Elements"][key].size() > 0:
  108. elements[key] = data[p][index]["Elements"][key]
  109. for i in range(data[p][index]["Elements"][key].size()):
  110. data[p][index]["Elements"][key][i]["AssetId"] = int(data[p][index]["Elements"][key][i]["AssetId"])
  111. data[p][index]["Elements"][key][i]["Layer"] = int(data[p][index]["Elements"][key][i]["Layer"])
  112. data[p][index]["Elements"][key][i]["LayerOffset"] = int(data[p][index]["Elements"][key][i]["LayerOffset"])
  113. data[p][index]["Elements"] = elements
  114. if p == "Clothes":
  115. var ClothClasses = int(data[p][index]["ClothClasses"]["Hash"])
  116. data[p][index]["ClothClasses"] = { "Hash": ClothClasses }
  117. var BodySlotCost = {}
  118. for slot in data[p][index]["BodySlotCost"]:
  119. BodySlotCost[int(slot)] = int(data[p][index]["BodySlotCost"][slot])
  120. data[p][index]["BodySlotCost"] = BodySlotCost
  121. return data
  122. func _full_permutation_state(result: Dictionary, states: Array, depth = 0, current_list = ["R"], current_code=""):
  123. if states.size() == depth:
  124. result["/".join(current_list)] = current_code
  125. else:
  126. var state = states[depth]
  127. for i in range(state["Values"].size()):
  128. var new_list = current_list + [state["Values"][i]]
  129. var new_code = current_code + str(index_to_char.get(i, "#"))
  130. if state["Required"][i] == false:
  131. new_list[0] = "N"
  132. _full_permutation_state(result, states, depth + 1, new_list, new_code)
  133. func load_texture(texture_path: String) -> ImageTexture:
  134. var image = Image.new()
  135. var err = image.load(texture_path)
  136. if err != OK:
  137. #push_error("load image fail: %s" % texture_path)
  138. return null
  139. var image_texture = ImageTexture.new()
  140. image_texture.set_image(image)
  141. return image_texture
  142. func load_asset(texture_path: String):
  143. texture_path = texture_path.simplify_path()
  144. for asset_id in avatar_doll_data["AssetMap"]:
  145. if avatar_doll_data["AssetMap"][asset_id][0] == texture_path:
  146. return asset_id
  147. var texture = load_texture(texture_path)
  148. if texture != null:
  149. var asset_id = avatar_asset_id_max + 1
  150. avatar_asset[asset_id] = texture
  151. avatar_asset_name[asset_id] = texture_path.get_file()
  152. var asset = [texture_path, int(texture.get_size().x), int(texture.get_size().y)]
  153. avatar_doll_data["AssetMap"][asset_id] = asset
  154. avatar_asset_id_max += 1
  155. return asset_id
  156. return null
  157. func replace_asset(asset_id, texture_path):
  158. if asset_id not in avatar_doll_data["AssetMap"]:
  159. return false
  160. texture_path = texture_path.simplify_path()
  161. var texture = load_texture(texture_path)
  162. if texture == null:
  163. return false
  164. avatar_asset[asset_id] = texture
  165. avatar_asset_name[asset_id] = texture_path.get_file()
  166. var asset = [texture_path, int(texture.get_size().x), int(texture.get_size().y)]
  167. avatar_doll_data["AssetMap"][asset_id] = asset
  168. avatar_asset_id_max += 1
  169. return true
  170. func remove_asset(asset_id):
  171. if asset_id not in avatar_doll_data["AssetMap"]:
  172. return
  173. for scope in avatar_part_scope:
  174. if scope not in avatar_doll_data:
  175. continue
  176. for part_index in range(avatar_doll_data[scope].size()):
  177. var part = avatar_doll_data[scope][part_index]
  178. # icon
  179. if part["IconAssetId"] == asset_id:
  180. part["IconAssetId"] = 0
  181. # element
  182. for state_code in part["Elements"]:
  183. var new_elements = []
  184. for element_index in range(part["Elements"][state_code].size()):
  185. if part["Elements"][state_code][element_index]["AssetId"] != asset_id:
  186. new_elements.append(part["Elements"][state_code][element_index])
  187. part["Elements"][state_code] = new_elements
  188. avatar_doll_data["AssetMap"].erase(asset_id)
  189. avatar_asset.erase(asset_id)
  190. avatar_asset_name.erase(asset_id)
  191. func reload_all_asset():
  192. avatar_asset_id_max = 0
  193. avatar_asset.clear()
  194. for asset_id in avatar_doll_data["AssetMap"]:
  195. avatar_asset_id_max = max(asset_id, avatar_asset_id_max)
  196. var asset = avatar_doll_data["AssetMap"][asset_id]
  197. var asset_path = asset[0]
  198. var asset_name = asset_path.get_file().get_basename()
  199. var texture = load_texture(asset_path)
  200. if texture != null:
  201. avatar_doll_data["AssetMap"][asset_id] = [asset_path, int(texture.get_size().x), int(texture.get_size().y)]
  202. avatar_asset[asset_id] = texture
  203. avatar_asset_name[asset_id] = asset_name
  204. else:
  205. var image: Image = default_texture.get_image()
  206. image.resize(asset[1], asset[2], Image.INTERPOLATE_LANCZOS)
  207. avatar_asset[asset_id] = ImageTexture.create_from_image(image)
  208. avatar_asset_name[asset_id] = asset_name
  209. func get_asset(asset_id):
  210. if asset_id == 0:
  211. return blank_texture
  212. return avatar_asset[asset_id]
  213. func get_asset_name(asset_id):
  214. asset_id = int(asset_id)
  215. if asset_id == 0:
  216. return "__blank__"
  217. elif asset_id in avatar_asset_name:
  218. return avatar_asset_name[asset_id]
  219. else:
  220. return ""
  221. func get_asset_id(asset_name):
  222. if asset_name == "__blank__":
  223. return 0
  224. for asset_id in avatar_asset_name:
  225. if asset_name == avatar_asset_name[asset_id]:
  226. return asset_id
  227. return -1
  228. func get_asset_using(asset_id):
  229. if not initialed:
  230. return []
  231. var result = []
  232. for scope in avatar_part_scope:
  233. if scope not in avatar_doll_data:
  234. continue
  235. for part_index in range(avatar_doll_data[scope].size()):
  236. var part = avatar_doll_data[scope][part_index]
  237. # icon
  238. if part["IconAssetId"] == asset_id:
  239. result.append(["icon", scope, part_index])
  240. # element
  241. for state_code in part["Elements"]:
  242. for element_index in range(part["Elements"][state_code].size()):
  243. if part["Elements"][state_code][element_index]["AssetId"] == asset_id:
  244. result.append(["elem", scope, part_index, state_code, element_index])
  245. return result
  246. func get_avatar_part_scope_flag(avatar_part):
  247. return avatar_part_scope.get(avatar_part, -1)
  248. func get_states_hash_code(setting) -> int:
  249. var final_hash := 0
  250. for state in setting["States"]:
  251. var list_hash := 0
  252. for value in state["Required"]:
  253. var value_hash := 1 if value else 0
  254. list_hash = _combine_hashes(list_hash, value_hash)
  255. final_hash = _combine_hashes(final_hash, list_hash)
  256. return final_hash
  257. func _combine_hashes(h1: int, h2: int) -> int:
  258. var _hash: int = 2166136261
  259. _hash = (_hash ^ (h1 & 0xFF)) * 16777619
  260. _hash = (_hash ^ ((h1 >> 8) & 0xFF)) * 16777619
  261. _hash = (_hash ^ ((h1 >> 16) & 0xFF)) * 16777619
  262. _hash = (_hash ^ ((h1 >> 24) & 0xFF)) * 16777619
  263. _hash = (_hash ^ (h2 & 0xFF)) * 16777619
  264. _hash = (_hash ^ ((h2 >> 8) & 0xFF)) * 16777619
  265. _hash = (_hash ^ ((h2 >> 16) & 0xFF)) * 16777619
  266. _hash = (_hash ^ ((h2 >> 24) & 0xFF)) * 16777619
  267. return _hash & 0x7FFFFFFF
  268. func get_state_index(c: String) -> int:
  269. return char_to_index.get(c, -1)
  270. func get_state_char(index: int) -> String:
  271. return index_to_char.get(index, "#")
  272. func get_state_names(avatar_type, state_code):
  273. var state_names = []
  274. var state = avatar_part_state[avatar_type]
  275. for i in range(state_code.length()):
  276. var index = get_state_index(state_code[i])
  277. state_names.append(state[i]["Values"][index])
  278. return state_names
  279. func get_render_palettes(part: String, avatar_index: int, state_code: String, palette_id: int, is_icon: bool = false):
  280. var palettes = {}
  281. var target = avatar_doll_data[part][avatar_index]
  282. var elements = target["Elements"][state_code]
  283. var palette_setting
  284. if palette_id < 0:
  285. palette_setting = []
  286. elif is_icon:
  287. palette_setting = target["Palettes"][palette_id]["IconPaletteParam"]
  288. else:
  289. palette_setting = target["Palettes"][palette_id]["ElementPaletteParam"]
  290. for i in range(elements.size()):
  291. palettes[i] = []
  292. for setting in palette_setting:
  293. var element_index = setting["ElementIndex"]
  294. if element_index == -1:
  295. for i in palettes:
  296. palettes[i].append(setting)
  297. else:
  298. palettes[element_index].append(setting)
  299. return palettes