| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- extends Node
- class_name AvatarDollDataManager
- static var instance: AvatarDollDataManager
- var avatar_part_scope = {"Clothes": 0, "Bodies": 1, "Heads": 2, "Hairs": 3, "Faces": 4}
- var default_texture: Texture2D = preload("res://Resources/UI/missing_image.png")
- var blank_texture: Texture2D = preload("res://Resources/__blank__.png")
- var initialed = false
- var work_json_file = ""
- var avatar_part_state = {}
- var avatar_part_state_name_to_index = {}
- var avatar_part_state_index_to_name = {}
- var avatar_doll_data = null
- var avatar_asset_id_max = -1
- var avatar_asset = {}
- var avatar_asset_name = {}
- var char_to_index: Dictionary = {}
- var index_to_char: Dictionary = {}
- func _init():
- instance = self
-
- var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- for i in range(chars.length()):
- var c = chars[i]
- char_to_index[c] = i
- index_to_char[i] = str(c)
- func load_json(json_path) -> bool:
- var file = FileAccess.open(json_path, FileAccess.READ)
- var json_str = file.get_as_text()
- var json = JSON.new()
- var error = json.parse(json_str)
- if error != OK:
- push_error("load_avatar_doll_json ERROR!")
- initialed = false
- return false
-
- avatar_doll_data = _fix_avatar_dool_data(json.get_data())
- work_json_file = json_path
-
- # _load_setting
- reload_setting()
-
- # AssetMap
- reload_all_asset()
-
- initialed = true
- return true
- func save_json(json_path=""):
- if json_path == "":
- json_path = work_json_file
-
- if json_path == "" or initialed == false:
- return
-
- var data = _fix_avatar_dool_data(avatar_doll_data)
- var json_str = JSON.stringify(data)
-
- var file = FileAccess.open(json_path, FileAccess.WRITE)
- file.store_string(json_str)
- file.close()
- func reload_setting():
- avatar_part_state.clear()
- avatar_part_state_name_to_index.clear()
- avatar_part_state_index_to_name.clear()
-
- for part in avatar_part_scope:
- avatar_part_state[part] = []
-
- var scope_flag = avatar_part_scope[part]
- for state in avatar_doll_data["Settings"]["States"]:
- if 1 == 1 & (int(state["Scope"]) >> scope_flag):
- avatar_part_state[part].append(state)
-
- var result = {}
- _full_permutation_state(result, avatar_part_state[part])
- avatar_part_state_name_to_index[part] = result
- var swapped_dict = {}
- for key in result:
- var value = result[key]
- swapped_dict[value] = key
- avatar_part_state_index_to_name[part] = swapped_dict
- func _fix_avatar_dool_data(data):
- # fix data
- data["FormatVersion"] = int(data["FormatVersion"])
- data["Settings"]["MaxBodySlotCost"] = int(data["Settings"]["MaxBodySlotCost"])
- for i in range(data["Settings"]["States"].size()):
- data["Settings"]["States"][i]["Id"] = int(data["Settings"]["States"][i]["Id"])
- data["Settings"]["States"][i]["Scope"] = int(data["Settings"]["States"][i]["Scope"])
-
- var new_map = {}
- for key in data["AssetMap"]:
- if key is String and not key.is_valid_int():
- continue
- elif key is int and key <= 0:
- continue
-
- var asset_id = int(key)
- if asset_id > 0:
- new_map[asset_id] = [
- data["AssetMap"][key][0].simplify_path(),
- int(data["AssetMap"][key][1]),
- int(data["AssetMap"][key][2])
- ]
- data["AssetMap"] = new_map
-
- for p in avatar_part_scope.keys():
- if p not in data:
- continue
- for index in range(data[p].size()):
- #data[p][index]["Guid"] = data[p][index]["Guid"]
- data[p][index]["IconAssetId"] = int(data[p][index]["IconAssetId"])
- for i in range(data[p][index]["Palettes"].size()):
- #data[p][index]["Palettes"][i]["Guid"] = data[p][index]["Palettes"][i]["Guid"]
- for j in range(data[p][index]["Palettes"][i]["IconPaletteParam"].size()):
- data[p][index]["Palettes"][i]["IconPaletteParam"][j]["ElementIndex"] = int(data[p][index]["Palettes"][i]["IconPaletteParam"][j]["ElementIndex"])
- data[p][index]["Palettes"][i]["IconPaletteParam"][j]["BlendMode"] = int(data[p][index]["Palettes"][i]["IconPaletteParam"][j]["BlendMode"])
- for j in range(data[p][index]["Palettes"][i]["ElementPaletteParam"].size()):
- data[p][index]["Palettes"][i]["ElementPaletteParam"][j]["ElementIndex"] = int(data[p][index]["Palettes"][i]["ElementPaletteParam"][j]["ElementIndex"])
- data[p][index]["Palettes"][i]["ElementPaletteParam"][j]["BlendMode"] = int(data[p][index]["Palettes"][i]["ElementPaletteParam"][j]["BlendMode"])
-
- var elements = {}
- for key in data[p][index]["Elements"]:
- if data[p][index]["Elements"][key].size() > 0:
- elements[key] = data[p][index]["Elements"][key]
- for i in range(data[p][index]["Elements"][key].size()):
- data[p][index]["Elements"][key][i]["AssetId"] = int(data[p][index]["Elements"][key][i]["AssetId"])
- data[p][index]["Elements"][key][i]["Layer"] = int(data[p][index]["Elements"][key][i]["Layer"])
- data[p][index]["Elements"][key][i]["LayerOffset"] = int(data[p][index]["Elements"][key][i]["LayerOffset"])
- data[p][index]["Elements"] = elements
-
- if p == "Clothes":
- var ClothClasses = int(data[p][index]["ClothClasses"]["Hash"])
- data[p][index]["ClothClasses"] = { "Hash": ClothClasses }
-
- var BodySlotCost = {}
- for slot in data[p][index]["BodySlotCost"]:
- BodySlotCost[int(slot)] = int(data[p][index]["BodySlotCost"][slot])
- data[p][index]["BodySlotCost"] = BodySlotCost
- return data
-
- func _full_permutation_state(result: Dictionary, states: Array, depth = 0, current_list = ["R"], current_code=""):
- if states.size() == depth:
- result["/".join(current_list)] = current_code
- else:
- var state = states[depth]
- for i in range(state["Values"].size()):
- var new_list = current_list + [state["Values"][i]]
- var new_code = current_code + str(index_to_char.get(i, "#"))
- if state["Required"][i] == false:
- new_list[0] = "N"
- _full_permutation_state(result, states, depth + 1, new_list, new_code)
- func load_texture(texture_path: String) -> ImageTexture:
- var image = Image.new()
- var err = image.load(texture_path)
- if err != OK:
- #push_error("load image fail: %s" % texture_path)
- return null
-
- var image_texture = ImageTexture.new()
- image_texture.set_image(image)
- return image_texture
-
- func load_asset(texture_path: String):
- texture_path = texture_path.simplify_path()
- for asset_id in avatar_doll_data["AssetMap"]:
- if avatar_doll_data["AssetMap"][asset_id][0] == texture_path:
- return asset_id
-
- var texture = load_texture(texture_path)
- if texture != null:
- var asset_id = avatar_asset_id_max + 1
- avatar_asset[asset_id] = texture
- avatar_asset_name[asset_id] = texture_path.get_file()
- var asset = [texture_path, int(texture.get_size().x), int(texture.get_size().y)]
- avatar_doll_data["AssetMap"][asset_id] = asset
- avatar_asset_id_max += 1
- return asset_id
- return null
-
- func replace_asset(asset_id, texture_path):
- if asset_id not in avatar_doll_data["AssetMap"]:
- return false
-
- texture_path = texture_path.simplify_path()
-
- var texture = load_texture(texture_path)
- if texture == null:
- return false
-
- avatar_asset[asset_id] = texture
- avatar_asset_name[asset_id] = texture_path.get_file()
- var asset = [texture_path, int(texture.get_size().x), int(texture.get_size().y)]
- avatar_doll_data["AssetMap"][asset_id] = asset
- avatar_asset_id_max += 1
- return true
-
- func remove_asset(asset_id):
- if asset_id not in avatar_doll_data["AssetMap"]:
- return
-
- for scope in avatar_part_scope:
- if scope not in avatar_doll_data:
- continue
-
- for part_index in range(avatar_doll_data[scope].size()):
- var part = avatar_doll_data[scope][part_index]
- # icon
- if part["IconAssetId"] == asset_id:
- part["IconAssetId"] = 0
-
- # element
- for state_code in part["Elements"]:
- var new_elements = []
- for element_index in range(part["Elements"][state_code].size()):
- if part["Elements"][state_code][element_index]["AssetId"] != asset_id:
- new_elements.append(part["Elements"][state_code][element_index])
- part["Elements"][state_code] = new_elements
-
- avatar_doll_data["AssetMap"].erase(asset_id)
- avatar_asset.erase(asset_id)
- avatar_asset_name.erase(asset_id)
-
- func reload_all_asset():
- avatar_asset_id_max = 0
- avatar_asset.clear()
- for asset_id in avatar_doll_data["AssetMap"]:
- avatar_asset_id_max = max(asset_id, avatar_asset_id_max)
-
- var asset = avatar_doll_data["AssetMap"][asset_id]
- var asset_path = asset[0]
- var asset_name = asset_path.get_file().get_basename()
- var texture = load_texture(asset_path)
- if texture != null:
- avatar_doll_data["AssetMap"][asset_id] = [asset_path, int(texture.get_size().x), int(texture.get_size().y)]
- avatar_asset[asset_id] = texture
- avatar_asset_name[asset_id] = asset_name
- else:
- var image: Image = default_texture.get_image()
- image.resize(asset[1], asset[2], Image.INTERPOLATE_LANCZOS)
- avatar_asset[asset_id] = ImageTexture.create_from_image(image)
- avatar_asset_name[asset_id] = asset_name
-
- func get_asset(asset_id):
- if asset_id == 0:
- return blank_texture
- return avatar_asset[asset_id]
- func get_asset_name(asset_id):
- asset_id = int(asset_id)
- if asset_id == 0:
- return "__blank__"
- elif asset_id in avatar_asset_name:
- return avatar_asset_name[asset_id]
- else:
- return ""
-
- func get_asset_id(asset_name):
- if asset_name == "__blank__":
- return 0
- for asset_id in avatar_asset_name:
- if asset_name == avatar_asset_name[asset_id]:
- return asset_id
- return -1
-
- func get_asset_using(asset_id):
- if not initialed:
- return []
-
- var result = []
- for scope in avatar_part_scope:
- if scope not in avatar_doll_data:
- continue
-
- for part_index in range(avatar_doll_data[scope].size()):
- var part = avatar_doll_data[scope][part_index]
- # icon
- if part["IconAssetId"] == asset_id:
- result.append(["icon", scope, part_index])
-
- # element
- for state_code in part["Elements"]:
- for element_index in range(part["Elements"][state_code].size()):
- if part["Elements"][state_code][element_index]["AssetId"] == asset_id:
- result.append(["elem", scope, part_index, state_code, element_index])
-
- return result
-
- func get_avatar_part_scope_flag(avatar_part):
- return avatar_part_scope.get(avatar_part, -1)
-
- func get_states_hash_code(setting) -> int:
- var final_hash := 0
- for state in setting["States"]:
- var list_hash := 0
- for value in state["Required"]:
- var value_hash := 1 if value else 0
- list_hash = _combine_hashes(list_hash, value_hash)
- final_hash = _combine_hashes(final_hash, list_hash)
- return final_hash
- func _combine_hashes(h1: int, h2: int) -> int:
- var _hash: int = 2166136261
- _hash = (_hash ^ (h1 & 0xFF)) * 16777619
- _hash = (_hash ^ ((h1 >> 8) & 0xFF)) * 16777619
- _hash = (_hash ^ ((h1 >> 16) & 0xFF)) * 16777619
- _hash = (_hash ^ ((h1 >> 24) & 0xFF)) * 16777619
-
- _hash = (_hash ^ (h2 & 0xFF)) * 16777619
- _hash = (_hash ^ ((h2 >> 8) & 0xFF)) * 16777619
- _hash = (_hash ^ ((h2 >> 16) & 0xFF)) * 16777619
- _hash = (_hash ^ ((h2 >> 24) & 0xFF)) * 16777619
- return _hash & 0x7FFFFFFF
- func get_state_index(c: String) -> int:
- return char_to_index.get(c, -1)
-
- func get_state_char(index: int) -> String:
- return index_to_char.get(index, "#")
- func get_state_names(avatar_type, state_code):
- var state_names = []
- var state = avatar_part_state[avatar_type]
- for i in range(state_code.length()):
- var index = get_state_index(state_code[i])
- state_names.append(state[i]["Values"][index])
- return state_names
- func get_render_palettes(part: String, avatar_index: int, state_code: String, palette_id: int, is_icon: bool = false):
- var palettes = {}
- var target = avatar_doll_data[part][avatar_index]
- var elements = target["Elements"][state_code]
-
- var palette_setting
- if palette_id < 0:
- palette_setting = []
- elif is_icon:
- palette_setting = target["Palettes"][palette_id]["IconPaletteParam"]
- else:
- palette_setting = target["Palettes"][palette_id]["ElementPaletteParam"]
-
- for i in range(elements.size()):
- palettes[i] = []
-
- for setting in palette_setting:
- var element_index = setting["ElementIndex"]
- if element_index == -1:
- for i in palettes:
- palettes[i].append(setting)
- else:
- palettes[element_index].append(setting)
- return palettes
-
|