711 lines
22 KiB
Python
711 lines
22 KiB
Python
# Copyright (C) 2021 Victor Soupday
|
|
# This file is part of CC/iC Blender Tools <https://github.com/soupday/cc_blender_tools>
|
|
#
|
|
# CC/iC Blender Tools is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# CC/iC Blender Tools is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with CC/iC Blender Tools. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
import json
|
|
import os
|
|
import bpy
|
|
import copy
|
|
|
|
from . import utils
|
|
|
|
|
|
JSON_CACHE = {}
|
|
|
|
|
|
def get_json_cache_copy(fbx_path):
|
|
if fbx_path in JSON_CACHE:
|
|
json_data = JSON_CACHE[fbx_path]
|
|
if json_data is not None:
|
|
return copy.deepcopy(json_data)
|
|
return None
|
|
|
|
|
|
def get_json_path(fbx_path):
|
|
json_path = None
|
|
if fbx_path:
|
|
fbx_file = os.path.basename(fbx_path)
|
|
fbx_folder = os.path.dirname(fbx_path)
|
|
fbx_name = os.path.splitext(fbx_file)[0]
|
|
json_path = os.path.join(fbx_folder, fbx_name + ".json")
|
|
return json_path
|
|
|
|
|
|
def read_json(fbx_path, errors, no_local=False):
|
|
json_file_exists = False
|
|
json_cache = get_json_cache_copy(fbx_path)
|
|
if json_cache:
|
|
return json_cache
|
|
try:
|
|
fbx_file = os.path.basename(fbx_path)
|
|
fbx_folder = os.path.dirname(fbx_path)
|
|
fbx_name = os.path.splitext(fbx_file)[0]
|
|
json_path = os.path.join(fbx_folder, fbx_name + ".json")
|
|
# if the json doesn't exist in the expected path, look for it in the blend file path
|
|
if not os.path.exists(json_path):
|
|
json_path = utils.local_path(fbx_name + ".json")
|
|
|
|
if json_path and os.path.exists(json_path):
|
|
json_file_exists = True
|
|
# json_local is a custom version of the json created by the update/replace operator
|
|
# to incorporate new & replaced objects and materials though the datalink
|
|
json_local_path = json_path + "_local"
|
|
if os.path.exists(json_local_path):
|
|
json_path = json_local_path
|
|
|
|
# determine start of json text data
|
|
file_bytes = open(json_path, "rb")
|
|
bytes = file_bytes.read(3)
|
|
file_bytes.close()
|
|
start = 0
|
|
# json files outputted from Visual Studio projects start with a byte mark order block (3 bytes EF BB BF)
|
|
if bytes[0] == 0xEF and bytes[1] == 0xBB and bytes[2] == 0xBF:
|
|
start = 3
|
|
|
|
# read json text
|
|
file = open(json_path, "rt")
|
|
file.seek(start)
|
|
text_data = file.read()
|
|
json_data = json.loads(text_data)
|
|
file.close()
|
|
JSON_CACHE[fbx_path] = json_data
|
|
utils.log_info("Json data successfully parsed: " + json_path)
|
|
return json_data
|
|
|
|
utils.log_info("No Json data to parse, using defaults...")
|
|
JSON_CACHE[fbx_path] = None
|
|
if errors:
|
|
errors.append("NO_JSON")
|
|
return None
|
|
except:
|
|
utils.log_warn("Failed to read Json data: " + json_path)
|
|
if errors:
|
|
if json_file_exists:
|
|
errors.append("CORRUPT")
|
|
else:
|
|
errors.append("PATH_FAILED")
|
|
return None
|
|
|
|
|
|
def write_json(json_data, path, is_fbx_path=False, is_json_local=False, update_cache=False):
|
|
if is_fbx_path:
|
|
if update_cache:
|
|
JSON_CACHE[path] = json_data
|
|
file = os.path.basename(path)
|
|
folder = os.path.dirname(path)
|
|
name = os.path.splitext(file)[0]
|
|
path = os.path.join(folder, name + ".json")
|
|
if is_json_local:
|
|
path += "_local"
|
|
json_object = json.dumps(json_data, indent = 4)
|
|
with open(path, "w") as write_file:
|
|
write_file.write(json_object)
|
|
|
|
|
|
def safe_name(o):
|
|
if type(o) is str:
|
|
return utils.strip_name(o).lower()
|
|
else:
|
|
return utils.strip_name(o.name).lower()
|
|
|
|
|
|
def get_all_object_keys(chr_json):
|
|
if chr_json:
|
|
meshes_json = chr_json["Meshes"]
|
|
return meshes_json.keys()
|
|
return []
|
|
|
|
|
|
def get_all_material_keys(chr_json):
|
|
if chr_json:
|
|
keys = []
|
|
meshes_json = chr_json["Meshes"]
|
|
for obj_json_name in meshes_json.keys():
|
|
obj_json = meshes_json[obj_json_name]
|
|
materials_json = obj_json["Materials"]
|
|
for mat_key in materials_json.keys():
|
|
keys.append(mat_key)
|
|
return keys
|
|
|
|
|
|
def get_character_generation_json(chr_json, character_id):
|
|
try:
|
|
return chr_json[character_id]["Object"][character_id]["Generation"]
|
|
except:
|
|
utils.log_warn("Failed to read character generation data!")
|
|
return None
|
|
|
|
|
|
def set_character_generation_json(chr_json, character_id, generation):
|
|
try:
|
|
chr_json[character_id]["Object"][character_id]["Generation"] = generation
|
|
return True
|
|
except:
|
|
utils.log_warn(f"Failed to set character generation to: {generation}")
|
|
return False
|
|
|
|
|
|
def get_character_root_json(json_data, character_id):
|
|
if not json_data:
|
|
return None
|
|
try:
|
|
return json_data[character_id]["Object"]
|
|
except:
|
|
utils.log_warn("Failed to get character root Json data!")
|
|
return None
|
|
|
|
def get_character_json(json_data, character_id):
|
|
if not json_data:
|
|
return None
|
|
try:
|
|
chr_json = json_data[character_id]["Object"][character_id]
|
|
utils.log_detail("Character Json data found for: " + character_id)
|
|
return chr_json
|
|
except:
|
|
utils.log_warn("Failed to get character Json data!")
|
|
return None
|
|
|
|
def get_object_info_json(json_data, character_id):
|
|
if not json_data:
|
|
return None
|
|
try:
|
|
info_json = json_data[character_id]["Object_Info"]
|
|
utils.log_detail("Character Object Info Json data found for: " + character_id)
|
|
return info_json
|
|
except:
|
|
utils.log_warn("Failed to get character object info Json data!")
|
|
return None
|
|
|
|
def get_facial_profile_json(json_data, character_id):
|
|
try:
|
|
return json_data[character_id]["Facial_Profile"]
|
|
except:
|
|
return None
|
|
|
|
|
|
def get_facial_profile_categories_json(json_data, character_id):
|
|
try:
|
|
return json_data[character_id]["Facial_Profile"]["Categories"]
|
|
except:
|
|
return None
|
|
|
|
|
|
def set_facial_profile_categories_json(json_data, character_id, categories_json):
|
|
try:
|
|
if "Facial_Profile" not in json_data[character_id].keys():
|
|
json_data[character_id]["Facial_Profile"] = {}
|
|
json_data[character_id]["Facial_Profile"]["Categories"] = categories_json
|
|
return True
|
|
except:
|
|
return False
|
|
|
|
|
|
def has_node_type(chr_json, node_type):
|
|
meshes_json = chr_json["Meshes"]
|
|
for obj_name, obj_json in meshes_json.items():
|
|
if obj_json and "Materials" in obj_json:
|
|
for mat_name, mat_json in obj_json["Materials"].items():
|
|
if "Node Type" in mat_json and mat_json["Node Type"] == node_type:
|
|
return True
|
|
return False
|
|
|
|
|
|
def get_object_json(chr_json, obj):
|
|
if not chr_json:
|
|
return None
|
|
try:
|
|
name = safe_name(obj)
|
|
meshes_json = chr_json["Meshes"]
|
|
for object_name in meshes_json.keys():
|
|
if object_name.lower() == name:
|
|
utils.log_detail("Object Json data found for: " + name)
|
|
return meshes_json[object_name]
|
|
except:
|
|
utils.log_warn("Failed to get object Json data!")
|
|
return None
|
|
|
|
|
|
def get_object_json_key(chr_json, obj_json):
|
|
if not chr_json:
|
|
return None
|
|
if obj_json is None:
|
|
return None
|
|
meshes_json: dict = chr_json["Meshes"]
|
|
for key, value in meshes_json.items():
|
|
if value == obj_json:
|
|
return key
|
|
return None
|
|
|
|
|
|
def get_physics_json(chr_json):
|
|
try:
|
|
return chr_json["Physics"]
|
|
except:
|
|
return None
|
|
|
|
|
|
def get_soft_physics_json(physics_json, obj, mat):
|
|
try:
|
|
obj_name = safe_name(obj)
|
|
mat_name = safe_name(mat)
|
|
soft_physics_mesh_json = physics_json["Soft Physics"]["Meshes"]
|
|
for object_name in soft_physics_mesh_json:
|
|
if object_name.lower() == obj_name:
|
|
materials_json = soft_physics_mesh_json[object_name]["Materials"]
|
|
for material_name in materials_json:
|
|
if material_name.lower() == mat_name:
|
|
return materials_json[material_name]
|
|
return None
|
|
except:
|
|
utils.log_warn("Failed to get soft physics material Json data!")
|
|
return None
|
|
|
|
|
|
def get_physics_mesh_json(soft_physics_json, obj):
|
|
if not soft_physics_json:
|
|
return None
|
|
try:
|
|
name = safe_name(obj)
|
|
for object_name in soft_physics_json.keys():
|
|
if object_name.lower() == name:
|
|
utils.log_detail("Physics Object Json data found for: " + name)
|
|
return soft_physics_json[object_name]
|
|
except:
|
|
utils.log_warn("Failed to get physics object Json data!")
|
|
return None
|
|
|
|
|
|
def get_physics_mesh_json_key(soft_physics_json, physics_mesh_json):
|
|
if not soft_physics_json:
|
|
return None
|
|
if physics_mesh_json is None:
|
|
return None
|
|
for key, value in soft_physics_json.items():
|
|
if value == physics_mesh_json:
|
|
return key
|
|
return None
|
|
|
|
|
|
def get_custom_shader(mat_json):
|
|
try:
|
|
return mat_json["Custom Shader"]["Shader Name"]
|
|
except:
|
|
try:
|
|
return mat_json["Material Type"]
|
|
except:
|
|
utils.log_warn("Failed to find material shader data!")
|
|
return "Pbr"
|
|
|
|
|
|
def get_material_json(obj_json, material):
|
|
if not obj_json:
|
|
return None
|
|
try:
|
|
name = safe_name(material)
|
|
materials_json = obj_json["Materials"]
|
|
for material_name in materials_json.keys():
|
|
if material_name.lower() == name:
|
|
utils.log_detail("Material Json data found for: " + name)
|
|
return materials_json[material_name]
|
|
except:
|
|
utils.log_warn("Failed to get material Json data!")
|
|
return None
|
|
|
|
|
|
def get_material_node_type(mat_json: dict):
|
|
return mat_json.get("Node Type", None)
|
|
|
|
|
|
def get_material_json_key(obj_json, mat_json):
|
|
if not obj_json:
|
|
return None
|
|
if mat_json is None:
|
|
return None
|
|
materials_json: dict = obj_json["Materials"]
|
|
for key, value in materials_json.items():
|
|
if value == mat_json:
|
|
return key
|
|
return None
|
|
|
|
|
|
def get_physics_material_json(physics_mesh_json, material):
|
|
if not physics_mesh_json:
|
|
return None
|
|
try:
|
|
name = safe_name(material)
|
|
materials_json = physics_mesh_json["Materials"]
|
|
for material_name in materials_json.keys():
|
|
if material_name.lower() == name:
|
|
utils.log_detail("Physics Material Json data found for: " + name)
|
|
return materials_json[material_name]
|
|
except:
|
|
utils.log_warn("Failed to get physics material Json data!")
|
|
return None
|
|
|
|
|
|
def get_physics_material_json_key(physics_mesh_json, physics_mat_json):
|
|
if not physics_mesh_json:
|
|
return None
|
|
if physics_mat_json is None:
|
|
return None
|
|
materials_json: dict = physics_mesh_json["Materials"]
|
|
for key, value in materials_json.items():
|
|
if value == physics_mat_json:
|
|
return key
|
|
return None
|
|
|
|
|
|
def get_texture_info(mat_json, texture_id):
|
|
tex_info = get_pbr_texture_info(mat_json, texture_id)
|
|
if tex_info is None:
|
|
tex_info = get_shader_texture_info(mat_json, texture_id)
|
|
if tex_info is None:
|
|
tex_info = get_wrinkle_texture_info(mat_json, texture_id)
|
|
return tex_info
|
|
|
|
def get_texture_channel_strength(mat_json, texture_id, default_value=None):
|
|
tex_info = get_texture_info(mat_json, texture_id)
|
|
if tex_info and "Strength" in tex_info:
|
|
return tex_info["Strength"] / 100
|
|
return default_value
|
|
|
|
def get_pbr_texture_info(mat_json, texture_id):
|
|
if not mat_json:
|
|
return None
|
|
try:
|
|
return mat_json["Textures"][texture_id]
|
|
except:
|
|
return None
|
|
|
|
def get_shader_texture_info(mat_json, texture_id):
|
|
if not mat_json:
|
|
return None
|
|
try:
|
|
return mat_json["Custom Shader"]["Image"][texture_id]
|
|
except:
|
|
return None
|
|
|
|
def get_wrinkle_texture_info(mat_json, texture_id):
|
|
if not mat_json:
|
|
return None
|
|
try:
|
|
return mat_json["Wrinkle"]["Textures"][texture_id]
|
|
except: ...
|
|
try:
|
|
return mat_json["Resource Textures"][texture_id]
|
|
except: ...
|
|
return None
|
|
|
|
def get_material_json_var(mat_json, var_path: str):
|
|
paths = var_path.split('/')
|
|
var_type = paths[0]
|
|
var_name = paths[1]
|
|
if var_type == "Custom":
|
|
return get_shader_var(mat_json, var_name)
|
|
elif var_type == "Reflection":
|
|
return get_direct_shader_var(mat_json, var_name)
|
|
elif var_type == "SSS":
|
|
return get_sss_var(mat_json, var_name)
|
|
elif var_type == "Pbr":
|
|
return get_pbr_var(mat_json, var_name, paths)
|
|
else: # var_type == "Base":
|
|
return get_material_var(mat_json, var_name)
|
|
|
|
|
|
def get_shader_var(mat_json, var_name):
|
|
if not mat_json:
|
|
return None
|
|
try:
|
|
return mat_json["Custom Shader"]["Variable"][var_name]
|
|
except:
|
|
return None
|
|
|
|
|
|
def get_direct_shader_var(mat_json, var_name):
|
|
if not mat_json:
|
|
return None
|
|
try:
|
|
return mat_json["Custom Shader"][var_name]
|
|
except:
|
|
return None
|
|
|
|
|
|
def get_pbr_var(mat_json, var_name, paths):
|
|
if not mat_json:
|
|
return None
|
|
try:
|
|
tex_json = mat_json["Textures"][var_name]
|
|
if len(paths) == 3:
|
|
return tex_json.get(paths[2], 1.0)
|
|
else:
|
|
return tex_json.get("Strength", 100.0) / 100.0
|
|
except:
|
|
return None
|
|
|
|
|
|
def get_material_var(mat_json, var_name):
|
|
if not mat_json:
|
|
return None
|
|
try:
|
|
return mat_json[var_name]
|
|
except:
|
|
return None
|
|
|
|
|
|
def get_sss_var(mat_json, var_name):
|
|
if not mat_json:
|
|
return None
|
|
try:
|
|
return mat_json["Subsurface Scatter"][var_name]
|
|
except:
|
|
return None
|
|
|
|
|
|
def set_material_json_var(mat_json, var_path: str, value):
|
|
paths = var_path.split('/')
|
|
var_type = paths[0]
|
|
var_name = paths[1]
|
|
if var_type == "Custom":
|
|
set_shader_var(mat_json, var_name, value)
|
|
elif var_type == "SSS":
|
|
set_sss_var(mat_json, var_name, value)
|
|
elif var_type == "Pbr":
|
|
set_pbr_var(mat_json, var_name, paths, value)
|
|
else: # var_type == "Base":
|
|
set_material_var(mat_json, var_name, value)
|
|
|
|
|
|
def set_shader_var(mat_json, var_name, value):
|
|
if mat_json:
|
|
try:
|
|
mat_json["Custom Shader"]["Variable"][var_name] = value
|
|
except:
|
|
return
|
|
|
|
|
|
def set_pbr_var(mat_json, var_name, paths, value):
|
|
if mat_json:
|
|
try:
|
|
if len(paths) == 3:
|
|
mat_json["Textures"][var_name][paths[2]] = value
|
|
else:
|
|
# metallic and roughness don't have controllable strength settings, so always set to max
|
|
if var_name == "Metallic" or var_name == "Roughness":
|
|
value = 1.0
|
|
mat_json["Textures"][var_name]["Strength"] = value * 100.0
|
|
except:
|
|
return
|
|
|
|
|
|
def set_material_var(mat_json, var_name, value):
|
|
if mat_json:
|
|
try:
|
|
mat_json[var_name] = value
|
|
except:
|
|
return
|
|
|
|
|
|
def set_sss_var(mat_json, var_name, value):
|
|
if mat_json:
|
|
try:
|
|
mat_json["Subsurface Scatter"][var_name] = value
|
|
except:
|
|
return
|
|
|
|
|
|
def convert_to_color(json_var):
|
|
if type(json_var) == list:
|
|
for i in range(0, len(json_var)):
|
|
json_var[i] /= 255.0
|
|
if len(json_var) == 3:
|
|
json_var.append(1)
|
|
return json_var
|
|
|
|
|
|
def convert_from_color(color):
|
|
try:
|
|
return [ int(color[0] * 255.0), int(color[1] * 255.0), int(color[2] * 255.0) ]
|
|
except:
|
|
return [255,255,255]
|
|
|
|
|
|
def get_shader_var_color(mat_json, var_name):
|
|
if not mat_json:
|
|
return None
|
|
try:
|
|
json_color = mat_json["Custom Shader"]["Variable"][var_name]
|
|
return convert_to_color(json_color)
|
|
except:
|
|
return None
|
|
|
|
|
|
def get_json(json_data, path: str, default=None):
|
|
if json_data:
|
|
keys = path.split("/")
|
|
for key in keys:
|
|
if key in json_data:
|
|
json_data = json_data[key]
|
|
else:
|
|
return default
|
|
return json_data
|
|
return default
|
|
|
|
|
|
def set_json(json_data, path: str, value):
|
|
if json_data:
|
|
json_key = None
|
|
keys = path.split("/")
|
|
for i, key in enumerate(keys):
|
|
if key in json_data:
|
|
if i == len(keys) - 1:
|
|
json_data[key] = value
|
|
return True
|
|
else:
|
|
json_data = json_data[key]
|
|
else:
|
|
break
|
|
return False
|
|
|
|
|
|
def generate_character_base_json_data(name):
|
|
json_data = {
|
|
name: {
|
|
"Version": "1.10.1822.1",
|
|
"Scene": {
|
|
"Name": True,
|
|
"SupportShaderSelect": True
|
|
},
|
|
"Object": {
|
|
name: {
|
|
"Generation": "",
|
|
"Meshes": {
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
return json_data
|
|
|
|
|
|
def add_json_path(json_data, path):
|
|
keys = path.split("/")
|
|
for key in keys:
|
|
if key not in json_data.keys():
|
|
json_data[key] = {}
|
|
json_data = json_data[key]
|
|
return json_data
|
|
|
|
|
|
def rename_json_key(json_data, old_name, new_name):
|
|
if old_name in json_data.keys():
|
|
json_data[new_name] = json_data.pop(old_name)
|
|
return True
|
|
return False
|
|
|
|
|
|
def add_physics_json(json_data, character_id, collider_source_json=None, collider_source_id=None):
|
|
phys_meshes = add_json_path(json_data, f"{character_id}/Object/{character_id}/Physics/Soft Physics/Meshes")
|
|
colliders = add_json_path(json_data, f"{character_id}/Object/{character_id}/Physics/Soft Physics/Collision Shapes")
|
|
if collider_source_json and collider_source_id:
|
|
collider_source = get_json(collider_source_json,
|
|
f"{collider_source_id}/Object/{collider_source_id}/Physics/Collision Shapes")
|
|
colliders = copy.deepcopy(collider_source)
|
|
set_json(json_data,
|
|
f"{character_id}/Object/{character_id}/Physics/Soft Physics/Collision Shapes",
|
|
colliders)
|
|
return phys_meshes, colliders
|
|
|
|
|
|
|
|
def get_character_meshes_json(json_data, character_id):
|
|
meshes_json: dict = None
|
|
phys_meshes_json: dict = None
|
|
try:
|
|
meshes_json = json_data[character_id]["Object"][character_id]["Meshes"]
|
|
except:
|
|
pass
|
|
try:
|
|
phys_meshes_json = json_data[character_id]["Object"][character_id]["Physics"]["Soft Physics"]["Meshes"]
|
|
except:
|
|
pass
|
|
return meshes_json, phys_meshes_json
|
|
|
|
|
|
def get_physics_collision_shapes_json(json_data, character_id) -> dict:
|
|
try:
|
|
return json_data[character_id]["Object"][character_id]["Physics"]["Collision Shapes"]
|
|
except:
|
|
pass
|
|
|
|
|
|
def remap_mesh_json_tex_paths(obj_json, phys_json, from_dir, to_dir):
|
|
if obj_json and "Materials" in obj_json:
|
|
for mat_name in obj_json["Materials"]:
|
|
mat_json = obj_json["Materials"][mat_name]
|
|
if "Textures" in mat_json:
|
|
for tex_channel in mat_json["Textures"]:
|
|
tex_info = mat_json["Textures"][tex_channel]
|
|
tex_path = tex_info["Texture Path"]
|
|
if tex_path:
|
|
full_path = os.path.normpath(os.path.join(from_dir, tex_path))
|
|
rel_path = os.path.relpath(full_path, to_dir).replace(r"\\","/")
|
|
tex_info["Texture Path"] = rel_path
|
|
if "Custom Shader" in mat_json:
|
|
for custom_channel in mat_json["Custom Shader"]["Image"]:
|
|
tex_info = mat_json["Custom Shader"]["Image"][custom_channel]
|
|
tex_path = tex_info["Texture Path"]
|
|
if tex_path:
|
|
full_path = os.path.normpath(os.path.join(from_dir, tex_path))
|
|
rel_path = os.path.relpath(full_path, to_dir).replace(r"\\","/")
|
|
tex_info["Texture Path"] = rel_path
|
|
if phys_json and "Materials" in phys_json:
|
|
for mat_name in phys_json["Materials"]:
|
|
mat_json = phys_json["Materials"][mat_name]
|
|
if "Weight Map Path" in mat_json:
|
|
tex_path = mat_json["Weight Map Path"]
|
|
if tex_path:
|
|
full_path = os.path.normpath(os.path.join(from_dir, tex_path))
|
|
rel_path = os.path.relpath(full_path, to_dir).replace(r"\\","/")
|
|
tex_info["Texture Path"] = rel_path
|
|
|
|
def get_meshes_images(meshes_json, filter=None):
|
|
images = set()
|
|
for mesh_name in meshes_json:
|
|
if filter and mesh_name not in filter: continue
|
|
mesh_json = meshes_json[mesh_name]
|
|
for mat_name in mesh_json["Materials"]:
|
|
mat_json = mesh_json["Materials"][mat_name]
|
|
if "Textures" in mat_json:
|
|
for tex_channel in mat_json["Textures"]:
|
|
tex_info = mat_json["Textures"][tex_channel]
|
|
tex_path = tex_info["Texture Path"]
|
|
if tex_path:
|
|
images.add(os.path.normpath(tex_path))
|
|
if "Custom Shader" in mat_json:
|
|
for custom_channel in mat_json["Custom Shader"]["Image"]:
|
|
tex_info = mat_json["Custom Shader"]["Image"][custom_channel]
|
|
tex_path = tex_info["Texture Path"]
|
|
if tex_path:
|
|
images.add(os.path.normpath(tex_path))
|
|
return images
|
|
|
|
|
|
def get_displacement_data(mat_json):
|
|
texture_path = get_json(mat_json, "Textures/Displacement/Texture Path", "")
|
|
strength = get_json(mat_json, "Textures/Displacement/Strength", 0.0) / 100.0
|
|
level = int(get_json(mat_json, "Textures/Displacement/Tessellation Level", 0))
|
|
multiplier = get_json(mat_json, "Textures/Displacement/Multiplier", 1.0)
|
|
base = get_json(mat_json, "Textures/Displacement/Gray-scale Base Value", 0.0)
|
|
return texture_path, strength, level, multiplier, base |