2026-02-16
This commit is contained in:
Binary file not shown.
+4
-4
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"last_check": "2025-12-30 14:52:43.839129",
|
||||
"backup_date": "December-15-2025",
|
||||
"last_check": "2026-01-09 16:23:22.382598",
|
||||
"backup_date": "December-30-2025",
|
||||
"update_ready": true,
|
||||
"ignore": false,
|
||||
"just_restored": false,
|
||||
"just_updated": false,
|
||||
"version_text": {
|
||||
"link": "https://api.github.com/repos/soupday/cc_blender_tools/zipball/refs/tags/2_3_4_p0",
|
||||
"link": "https://api.github.com/repos/soupday/cc_blender_tools/zipball/refs/tags/2_3_4_p1",
|
||||
"version": [
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
0
|
||||
1
|
||||
]
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"last_check": "2025-12-30 14:52:43.839129",
|
||||
"backup_date": "December-30-2025",
|
||||
"last_check": "2026-01-09 16:23:22.382598",
|
||||
"backup_date": "January-9-2026",
|
||||
"update_ready": false,
|
||||
"ignore": false,
|
||||
"just_restored": false,
|
||||
|
||||
BIN
Binary file not shown.
@@ -1720,12 +1720,15 @@ class CC3Import(bpy.types.Operator):
|
||||
elif self.param == "BUILD" or self.param == "BUILD_REBUILD":
|
||||
chr_cache = props.get_context_character_cache(context)
|
||||
if chr_cache:
|
||||
bm = props.build_mode
|
||||
props.build_mode = "IMPORTED"
|
||||
mode_selection = utils.store_mode_selection_state()
|
||||
utils.object_mode()
|
||||
self.build_materials(context)
|
||||
self.build_drivers(context)
|
||||
self.do_import_report(context, stage = 1)
|
||||
utils.restore_mode_selection_state(mode_selection)
|
||||
props.build_mode = bm
|
||||
|
||||
elif self.param == "BUILD_DRIVERS":
|
||||
chr_cache = props.get_context_character_cache(context)
|
||||
@@ -1764,32 +1767,41 @@ class CC3Import(bpy.types.Operator):
|
||||
if chr_cache:
|
||||
utils.object_mode()
|
||||
if chr_cache.get_render_target() != "EEVEE":
|
||||
bm = props.build_mode
|
||||
props.build_mode = "IMPORTED"
|
||||
prefs.refractive_eyes = "PARALLAX"
|
||||
utils.log_info("Character is currently build for Cycles Rendering.")
|
||||
utils.log_info("Rebuilding Character for Eevee Rendering...")
|
||||
self.build_materials(context, render_target="EEVEE")
|
||||
self.build_drivers(context)
|
||||
props.build_mode = bm
|
||||
|
||||
elif self.param == "REBUILD_BAKE":
|
||||
chr_cache = props.get_context_character_cache(context)
|
||||
if chr_cache:
|
||||
utils.object_mode()
|
||||
props.wrinkle_mode = False
|
||||
bm = props.build_mode
|
||||
props.build_mode = "IMPORTED"
|
||||
prefs.refractive_eyes = "PARALLAX"
|
||||
utils.log_info("Rebuilding Character for Eevee Bake...")
|
||||
self.build_materials(context, render_target="EEVEE")
|
||||
self.build_drivers(context)
|
||||
props.build_mode = bm
|
||||
|
||||
elif self.param == "REBUILD_CYCLES":
|
||||
chr_cache = props.get_context_character_cache(context)
|
||||
if chr_cache:
|
||||
utils.object_mode()
|
||||
prefs.refractive_eyes = "SSR"
|
||||
if chr_cache.get_render_target() != "CYCLES":
|
||||
bm = props.build_mode
|
||||
props.build_mode = "IMPORTED"
|
||||
prefs.refractive_eyes = "SSR"
|
||||
utils.log_info("Character is currently build for Eevee Rendering.")
|
||||
utils.log_info("Rebuilding Character for Cycles Rendering...")
|
||||
self.build_materials(context, render_target="CYCLES")
|
||||
self.build_drivers(context)
|
||||
props.build_mode = bm
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -3869,7 +3869,9 @@ class LinkService():
|
||||
# generate new action set data
|
||||
set_id, set_generation = rigutils.generate_motion_set(actor_rig, motion_id, LINK_DATA.motion_prefix)
|
||||
remove_actions = []
|
||||
action_pairs = []
|
||||
if actor_rig:
|
||||
|
||||
if actor.get_type() == "PROP":
|
||||
# if it's a prop retarget the animation (or copy the rest pose):
|
||||
# props have no bind pose so the rest pose is the first frame of
|
||||
@@ -3888,6 +3890,7 @@ class LinkService():
|
||||
rigutils.copy_rest_pose(motion_rig, actor_rig)
|
||||
utils.safe_set_action(actor_rig, motion_rig_action)
|
||||
rigutils.update_prop_rig(actor_rig)
|
||||
|
||||
else: # Avatar
|
||||
if chr_cache.rigified:
|
||||
update_link_status(f"Retargeting Motion...")
|
||||
@@ -3897,11 +3900,14 @@ class LinkService():
|
||||
rigutils.set_armature_action_name(armature_action, actor_rig_id, motion_id, LINK_DATA.motion_prefix)
|
||||
remove_actions.append(motion_rig_action)
|
||||
else:
|
||||
actor_rig_action = utils.safe_get_action(actor_rig)
|
||||
rigutils.add_motion_set_data(motion_rig_action, set_id, set_generation, rl_arm_id=rl_arm_id)
|
||||
rigutils.set_armature_action_name(motion_rig_action, actor_rig_id, motion_id, LINK_DATA.motion_prefix)
|
||||
motion_rig_action.use_fake_user = LINK_DATA.use_fake_user
|
||||
utils.safe_set_action(actor_rig, motion_rig_action)
|
||||
action_pairs.append((actor_rig_action, motion_rig_action))
|
||||
rigutils.update_avatar_rig(actor_rig)
|
||||
|
||||
# assign motion object shape key actions:
|
||||
key_actions = rigutils.apply_source_key_actions(actor_rig,
|
||||
source_actions, copy=True,
|
||||
@@ -3909,11 +3915,12 @@ class LinkService():
|
||||
motion_prefix=LINK_DATA.motion_prefix,
|
||||
all_matching=True,
|
||||
set_id=set_id, set_generation=set_generation)
|
||||
for action in key_actions.values():
|
||||
actions = [ p[0] for p in key_actions.values() ]
|
||||
for action in actions:
|
||||
action.use_fake_user = LINK_DATA.use_fake_user
|
||||
# remove unused motion key actions
|
||||
for obj_action in source_actions["keys"].values():
|
||||
if obj_action not in key_actions.values():
|
||||
if obj_action not in actions:
|
||||
remove_actions.append(obj_action)
|
||||
# delete imported motion rig and objects
|
||||
for obj in motion_objects:
|
||||
|
||||
@@ -21,7 +21,7 @@ import bpy
|
||||
from . import imageutils, jsonutils, nodeutils, utils, params, vars
|
||||
|
||||
|
||||
def detect_skin_material(mat):
|
||||
def detect_skin_material_name(mat):
|
||||
name = mat.name.lower()
|
||||
if "std_skin_" in name or "ga_skin_" in name:
|
||||
return True
|
||||
@@ -67,7 +67,7 @@ def detect_key_words(hints, text):
|
||||
return "False"
|
||||
|
||||
|
||||
def detect_scalp_material(mat):
|
||||
def detect_scalp_material_name(mat):
|
||||
prefs = vars.prefs()
|
||||
material_name = mat.name.lower()
|
||||
hints = prefs.hair_scalp_hint.split(",")
|
||||
@@ -79,14 +79,14 @@ def detect_scalp_material(mat):
|
||||
return detect
|
||||
|
||||
|
||||
def detect_eyelash_material(mat):
|
||||
def detect_eyelash_material_name(mat):
|
||||
name = mat.name.lower()
|
||||
if "std_eyelash" in name or "ga_eyelash" in name:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def detect_teeth_material(mat):
|
||||
def detect_teeth_material_name(mat):
|
||||
name = mat.name.lower()
|
||||
if "std_upper_teeth" in name:
|
||||
return True
|
||||
@@ -95,21 +95,21 @@ def detect_teeth_material(mat):
|
||||
return False
|
||||
|
||||
|
||||
def detect_tongue_material(mat):
|
||||
def detect_tongue_material_name(mat):
|
||||
name = mat.name.lower()
|
||||
if "std_tongue" in name or "ga_tongue" in name:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def detect_nails_material(mat):
|
||||
def detect_nails_material_name(mat):
|
||||
name = mat.name.lower()
|
||||
if "std_nails" in name or "ga_nails" in name:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def detect_body_object(chr_cache, obj):
|
||||
def detect_body_object_name(obj):
|
||||
name = obj.name.lower()
|
||||
if "base_body" in name or "game_body" in name:
|
||||
return True
|
||||
@@ -282,16 +282,16 @@ def detect_materials_by_name(chr_cache, obj, mat):
|
||||
|
||||
if detect_hair_object(obj, tex_dirs, chr_cache.get_import_dir()) == "True":
|
||||
object_type = "HAIR"
|
||||
if detect_scalp_material(mat) == "True":
|
||||
if detect_scalp_material_name(mat) == "True":
|
||||
material_type = "SCALP"
|
||||
elif detect_hair_material(obj, mat, tex_dirs, chr_cache.get_import_dir()) == "Deny":
|
||||
material_type = "DEFAULT"
|
||||
else:
|
||||
material_type = "HAIR"
|
||||
|
||||
elif detect_body_object(chr_cache, obj):
|
||||
elif detect_body_object_name(obj):
|
||||
object_type = "BODY"
|
||||
if detect_skin_material(mat):
|
||||
if detect_skin_material_name(mat):
|
||||
if "head" in mat_name:
|
||||
material_type = "SKIN_HEAD"
|
||||
elif "body" in mat_name:
|
||||
@@ -300,9 +300,9 @@ def detect_materials_by_name(chr_cache, obj, mat):
|
||||
material_type = "SKIN_ARM"
|
||||
elif "leg" in mat_name:
|
||||
material_type = "SKIN_LEG"
|
||||
elif detect_nails_material(mat):
|
||||
elif detect_nails_material_name(mat):
|
||||
material_type = "NAILS"
|
||||
elif detect_eyelash_material(mat):
|
||||
elif detect_eyelash_material_name(mat):
|
||||
material_type = "EYELASH"
|
||||
|
||||
elif detect_cornea_material(mat):
|
||||
@@ -333,14 +333,14 @@ def detect_materials_by_name(chr_cache, obj, mat):
|
||||
else:
|
||||
material_type = "TEARLINE_RIGHT"
|
||||
|
||||
elif detect_teeth_material(mat):
|
||||
elif detect_teeth_material_name(mat):
|
||||
object_type = "TEETH"
|
||||
if detect_material_side(mat, "UPPER"):
|
||||
material_type = "TEETH_UPPER"
|
||||
else:
|
||||
material_type = "TEETH_LOWER"
|
||||
|
||||
elif detect_tongue_material(mat):
|
||||
elif detect_tongue_material_name(mat):
|
||||
object_type = "TONGUE"
|
||||
material_type = "TONGUE"
|
||||
|
||||
@@ -368,12 +368,12 @@ def detect_materials_from_json(chr_cache, obj, mat, obj_json, mat_json):
|
||||
object_type = "HAIR"
|
||||
if detect_hair_material(obj, mat, tex_dirs, chr_cache.get_import_dir(), mat_json) == "True":
|
||||
material_type = "HAIR"
|
||||
elif detect_scalp_material(mat) == "True":
|
||||
elif detect_scalp_material_name(mat) == "True":
|
||||
material_type = "SCALP"
|
||||
else:
|
||||
material_type = "DEFAULT"
|
||||
|
||||
elif detect_eyelash_material(mat):
|
||||
elif detect_eyelash_material_name(mat):
|
||||
object_type = "BODY"
|
||||
material_type = "EYELASH"
|
||||
|
||||
@@ -402,7 +402,7 @@ def detect_materials_from_json(chr_cache, obj, mat, obj_json, mat_json):
|
||||
material_type = "SKIN_ARM"
|
||||
elif "leg" in mat_name:
|
||||
material_type = "SKIN_LEG"
|
||||
elif detect_nails_material(mat):
|
||||
elif detect_nails_material_name(mat):
|
||||
material_type = "NAILS"
|
||||
|
||||
elif shader == "RLHead":
|
||||
@@ -459,7 +459,12 @@ def detect_materials_from_json(chr_cache, obj, mat, obj_json, mat_json):
|
||||
object_type = "DEFAULT"
|
||||
material_type = "DEFAULT"
|
||||
|
||||
utils.log_info(f"Material: {mat_name} detected from Json data as: {material_type}")
|
||||
# final check for body
|
||||
if object_type == "DEFAULT" and material_type == "DEFAULT":
|
||||
if detect_body_object_name(obj) and detect_skin_material_name(mat):
|
||||
object_type = "BODY"
|
||||
|
||||
utils.log_info(f"Material: {obj.name}/{mat_name} detected from Json data as: {object_type}/{material_type}")
|
||||
return object_type, material_type
|
||||
|
||||
|
||||
|
||||
@@ -1364,9 +1364,9 @@ SHADER_MATRIX = [
|
||||
# modifier properties:
|
||||
# [prop_name, material_type, modifier_type, modifier_id, expression]
|
||||
"modifiers": [
|
||||
[ "eye_iris_depth", "EYE_RIGHT", "DISPLACE", "Eye_Displace_R", "mod.strength = 1.5 * parameters.eye_iris_depth"],
|
||||
[ "eye_iris_depth", "EYE_RIGHT", "DISPLACE", "Eye_Displace_R", "mod.strength = 1.0 * parameters.eye_iris_depth"],
|
||||
[ "eye_pupil_scale", "EYE_RIGHT", "UV_WARP", "Eye_UV_Warp_R", "mod.scale = (1.0 / parameters.eye_pupil_scale, 1.0 / parameters.eye_pupil_scale)" ],
|
||||
[ "eye_iris_depth", "EYE_LEFT", "DISPLACE", "Eye_Displace_L", "mod.strength = 1.5 * parameters.eye_iris_depth"],
|
||||
[ "eye_iris_depth", "EYE_LEFT", "DISPLACE", "Eye_Displace_L", "mod.strength = 1.0 * parameters.eye_iris_depth"],
|
||||
[ "eye_pupil_scale", "EYE_LEFT", "UV_WARP", "Eye_UV_Warp_L", "mod.scale = (1.0 / parameters.eye_pupil_scale, 1.0 / parameters.eye_pupil_scale)" ],
|
||||
],
|
||||
# material setting properties:
|
||||
@@ -1391,7 +1391,7 @@ SHADER_MATRIX = [
|
||||
"mapping": [
|
||||
["DIFFUSE", "Sclera Scale", "", "eye_sclera_scale"],
|
||||
["DIFFUSE", "Iris Radius", "", "eye_iris_radius"],
|
||||
["DIFFUSE", "Pupil Scale", "", "eye_pupil_scale"],
|
||||
["DIFFUSE", "Pupil Scale", "func_set_parallax_pupil_scale", "eye_pupil_scale"],
|
||||
["DIFFUSE", "Depth", "func_set_parallax_iris_depth", "eye_iris_depth"],
|
||||
["DIFFUSE", "IOR", "", "eye_ior"],
|
||||
["SCLERA", "Invert", "func_eye_invert", "eye_is_left_eye"],
|
||||
|
||||
@@ -552,7 +552,7 @@ class CC3ToolsAddonPreferences(bpy.types.AddonPreferences):
|
||||
("LOCAL","Local Machine","Connect to a DataLink server running on the local machine"),
|
||||
("REMOTE","Remote Host","Connect to a DataLink server running on a remote machine"),
|
||||
], default="LOCAL", name = "DataLink Target")
|
||||
datalink_auto_lighting: bpy.props.BoolProperty(default=True,
|
||||
datalink_auto_lighting: bpy.props.BoolProperty(default=False,
|
||||
description="Use automatic lighting from CC/iC Go-B")
|
||||
|
||||
|
||||
|
||||
@@ -2778,7 +2778,7 @@ def full_retarget_source_rig_action(op, chr_cache, src_rig=None, src_action=None
|
||||
rigutils.add_motion_set_data(armature_action, set_id, set_generation, rl_arm_id=rl_arm_id)
|
||||
armature_action.use_fake_user = props.rigify_retarget_use_fake_user if use_ui_options else True
|
||||
utils.log_info(f"Renaming armature action to: {armature_action.name}")
|
||||
for obj_id, key_action in key_actions.items():
|
||||
for obj_id, (key_action, old_key_action) in key_actions.items():
|
||||
rigutils.set_key_action_name(key_action, rig_id, motion_id, obj_id, motion_prefix)
|
||||
rigutils.add_motion_set_data(key_action, set_id, set_generation, obj_id=obj_id)
|
||||
utils.log_info(f"Renaming key action ({obj_id}) to: {key_action.name}")
|
||||
|
||||
@@ -428,6 +428,7 @@ def apply_source_key_actions(dst_rig, source_actions, all_matching=False, copy=F
|
||||
if obj.type == "MESH":
|
||||
if utils.object_has_shape_keys(obj):
|
||||
obj_id = get_action_obj_id(obj)
|
||||
old_action = utils.safe_get_action(obj.data.shape_keys)
|
||||
if (obj_id in source_actions["keys"] and
|
||||
obj_has_action_shape_keys(obj, source_actions["keys"][obj_id])):
|
||||
action = source_actions["keys"][obj_id]
|
||||
@@ -440,7 +441,7 @@ def apply_source_key_actions(dst_rig, source_actions, all_matching=False, copy=F
|
||||
utils.log_info(f" - Applying action: {action.name} to {obj_id}")
|
||||
utils.safe_set_action(obj.data.shape_keys, action)
|
||||
obj_used.append(obj)
|
||||
key_actions[obj_id] = action
|
||||
key_actions[obj_id] = (action, old_action)
|
||||
else:
|
||||
utils.safe_set_action(obj.data.shape_keys, None)
|
||||
|
||||
@@ -452,6 +453,7 @@ def apply_source_key_actions(dst_rig, source_actions, all_matching=False, copy=F
|
||||
if filter and obj not in filter: continue
|
||||
if obj not in obj_used and utils.object_has_shape_keys(obj):
|
||||
obj_id = get_action_obj_id(obj)
|
||||
old_action = utils.safe_get_action(obj.data.shape_keys)
|
||||
if body_action:
|
||||
if obj_has_action_shape_keys(obj, body_action):
|
||||
action = body_action
|
||||
@@ -464,7 +466,7 @@ def apply_source_key_actions(dst_rig, source_actions, all_matching=False, copy=F
|
||||
utils.log_info(f" - Applying action: {action.name} to {obj_id}")
|
||||
utils.safe_set_action(obj.data.shape_keys, action)
|
||||
obj_used.append(obj)
|
||||
key_actions[obj_id] = action
|
||||
key_actions[obj_id] = (action, old_action)
|
||||
return key_actions
|
||||
|
||||
|
||||
|
||||
@@ -210,13 +210,13 @@ def import_rlx_light(data: BinaryData, data_folder):
|
||||
cutoff_distance_cache = frame_cache(num_frames)
|
||||
spot_blend_cache = frame_cache(num_frames)
|
||||
spot_size_cache = frame_cache(num_frames)
|
||||
visible_cache = frame_cache(num_frames)
|
||||
render_cache = frame_cache(num_frames)
|
||||
|
||||
frame = 0
|
||||
start = None
|
||||
while not frames.eof():
|
||||
frame += 1
|
||||
time = frames.time()
|
||||
frame = frames.int()
|
||||
frame = frames.int() + 1
|
||||
if start is None:
|
||||
start = frame
|
||||
active = frames.bool()
|
||||
@@ -230,8 +230,6 @@ def import_rlx_light(data: BinaryData, data_folder):
|
||||
falloff = frames.float() / 100
|
||||
attenuation = frames.float() / 100
|
||||
darkness = frames.float()
|
||||
if not active:
|
||||
multiplier = 0.0
|
||||
cutoff_distance = range
|
||||
store_frame(light, loc_cache, frame, start, loc)
|
||||
store_frame(light, rot_cache, frame, start, rot)
|
||||
@@ -254,6 +252,9 @@ def import_rlx_light(data: BinaryData, data_folder):
|
||||
elif light_type == "POINT":
|
||||
energy = ENERGY_SCALE * multiplier
|
||||
store_frame(light, energy_cache, frame, start, energy)
|
||||
store_frame(light, visible_cache, frame, start, 0.0 if active else 1.0)
|
||||
store_frame(light, render_cache, frame, start, 0.0 if active else 1.0)
|
||||
|
||||
|
||||
ob_action, light_action, ob_slot, light_slot = prep_rlx_actions(light, name, "Export",
|
||||
reuse_existing=False,
|
||||
@@ -261,6 +262,8 @@ def import_rlx_light(data: BinaryData, data_folder):
|
||||
add_cache_fcurves(ob_action, light.path_from_id("location"), loc_cache, num_frames, "Location", slot=ob_slot)
|
||||
add_cache_rotation_fcurves(light, ob_action, rot_cache, num_frames, slot=ob_slot)
|
||||
add_cache_fcurves(ob_action, light.path_from_id("scale"), sca_cache, num_frames, "Scale", slot=ob_slot)
|
||||
add_cache_fcurves(light_action, light.path_from_id("hide_viewport"), visible_cache, num_frames, "Hide Viewport", slot=ob_slot, interpolation="CONSTANT")
|
||||
add_cache_fcurves(light_action, light.path_from_id("hide_render"), render_cache, num_frames, "Hide Render", slot=ob_slot, interpolation="CONSTANT")
|
||||
add_cache_fcurves(light_action, light.data.path_from_id("color"), color_cache, num_frames, "Color", slot=light_slot)
|
||||
add_cache_fcurves(light_action, light.data.path_from_id("energy"), energy_cache, num_frames, "Energy", slot=light_slot)
|
||||
add_cache_fcurves(light_action, light.data.path_from_id("cutoff_distance"), cutoff_distance_cache, num_frames, "Cutoff Distance", slot=light_slot)
|
||||
@@ -298,12 +301,10 @@ def import_rlx_camera(data: BinaryData, data_folder):
|
||||
f_stop_cache = frame_cache(num_frames)
|
||||
active_cache = []
|
||||
|
||||
frame = 0
|
||||
start = None
|
||||
while not frames.eof():
|
||||
frame += 1
|
||||
time = frames.time()
|
||||
frame = frames.int()
|
||||
frame = frames.int() + 1
|
||||
if start is None:
|
||||
start = frame
|
||||
loc = frames.vector() / 100
|
||||
@@ -427,7 +428,7 @@ def add_cache_rotation_fcurves(obj, action: bpy.types.Action, cache, num_frames,
|
||||
add_cache_fcurves(action, data_path, cache, num_frames, group_name=group_name, slot=slot)
|
||||
|
||||
|
||||
def add_cache_fcurves(action: bpy.types.Action, data_path, cache, num_frames, group_name=None, slot=None):
|
||||
def add_cache_fcurves(action: bpy.types.Action, data_path, cache, num_frames, group_name=None, slot=None, interpolation="LINEAR"):
|
||||
channels = utils.get_action_channels(action, slot)
|
||||
num_curves = len(cache)
|
||||
if channels:
|
||||
@@ -436,9 +437,51 @@ def add_cache_fcurves(action: bpy.types.Action, data_path, cache, num_frames, gr
|
||||
channels.groups.new(group_name)
|
||||
for i in range(0, num_curves):
|
||||
fcurve = channels.fcurves.new(data_path, index=i)
|
||||
fcurve.auto_smoothing = "NONE"
|
||||
fcurve.group = channels.groups[group_name]
|
||||
fcurve.keyframe_points.add(num_frames)
|
||||
fcurve.keyframe_points.foreach_set('co', cache[i])
|
||||
reduced = reduce_cache(cache[i], interpolation)
|
||||
num_reduced = int(len(reduced) / 2)
|
||||
fcurve.keyframe_points.add(num_reduced)
|
||||
fcurve.keyframe_points.foreach_set('co', reduced)
|
||||
if interpolation != "BEZIER":
|
||||
for keyframe in fcurve.keyframe_points:
|
||||
keyframe.interpolation = interpolation
|
||||
else:
|
||||
L = len(fcurve.keyframe_points)
|
||||
for i, keyframe in enumerate(fcurve.keyframe_points):
|
||||
prev = fcurve.keyframe_points[i-1] if i > 0 else keyframe
|
||||
next = fcurve.keyframe_points[i+1] if i < L-1 else keyframe
|
||||
keyframe.handle_left_type = "AUTO"
|
||||
keyframe.handle_left[0] = keyframe.co.x - 0.5
|
||||
keyframe.handle_left[1] = (keyframe.co.y + prev.co.y) * 0.5
|
||||
keyframe.handle_right_type = "AUTO"
|
||||
keyframe.handle_right[0] = keyframe.co.x + 0.5
|
||||
keyframe.handle_right[1] = (keyframe.co.y + next.co.y) * 0.5
|
||||
|
||||
def reduce_cache(cache, interpolation):
|
||||
if not cache or len(cache) <= 4:
|
||||
return cache
|
||||
reduced = []
|
||||
L = len(cache)
|
||||
Lm2 = L - 2
|
||||
# add first frame
|
||||
reduced.append(cache[0])
|
||||
reduced.append(cache[1])
|
||||
use_next = interpolation != "CONSTANT"
|
||||
for i in range(2, L, 2):
|
||||
frame = cache[i]
|
||||
value = cache[i+1]
|
||||
value_last = cache[i-1]
|
||||
value_next = cache[i+3] if i < Lm2 else value
|
||||
last_changed = abs(value - value_last) > 0.0001
|
||||
next_changed = abs(value - value_next) > 0.0001
|
||||
if last_changed or (use_next and next_changed):
|
||||
reduced.append(frame)
|
||||
reduced.append(value)
|
||||
# add last frame
|
||||
#reduced.append(cache[-2])
|
||||
#reduced.append(cache[-1])
|
||||
return reduced
|
||||
|
||||
|
||||
def add_camera_markers(camera, cache, num_frames, start):
|
||||
@@ -567,8 +610,10 @@ def decode_rlx_light(light_data, light: bpy.types.Object=None, container=None):
|
||||
light.data.contact_shadow_distance = 0.1
|
||||
light.data.contact_shadow_bias = 0.03
|
||||
light.data.contact_shadow_thickness = 0.001
|
||||
if not active:
|
||||
utils.hide(light)
|
||||
|
||||
light.hide_viewport = not active
|
||||
light.hide_render = not active
|
||||
|
||||
return light
|
||||
|
||||
|
||||
|
||||
@@ -2641,7 +2641,7 @@ def cycles_setup(context):
|
||||
pass
|
||||
|
||||
try:
|
||||
context.scene.cycles.preview_denoiser = 'OPTIX'
|
||||
context.scene.cycles.preview_denoiser = 'OPENIMAGEDENOISE'
|
||||
context.scene.cycles.denoiser = 'OPTIX'
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -67,7 +67,12 @@ def apply_multi_res_shape(body):
|
||||
mod = modifiers.get_object_modifier(body, modifiers.MOD_MULTIRES, modifiers.MOD_MULTIRES_NAME)
|
||||
if mod and utils.set_only_active_object(body):
|
||||
utils.log_info("Applying base shape")
|
||||
bpy.ops.object.multires_base_apply(modifier=mod.name)
|
||||
if utils.B500():
|
||||
# apply_heuristic=True applies base assuming it will be used subdivided
|
||||
# apply_heuristic=False applies base to level 0
|
||||
bpy.ops.object.multires_base_apply(modifier=mod.name, apply_heuristic=False)
|
||||
else:
|
||||
bpy.ops.object.multires_base_apply(modifier=mod.name)
|
||||
|
||||
|
||||
def displacement_map_func(value):
|
||||
@@ -209,20 +214,22 @@ def do_multires_bake(context, chr_cache, multires_mesh, layer_target, apply_shap
|
||||
utils.log_recess()
|
||||
utils.log_info("Baking complete!")
|
||||
|
||||
utils.delete_mesh_object(norm_body)
|
||||
|
||||
if layer_target == LAYER_TARGET_SCULPT and apply_shape and source_body:
|
||||
|
||||
utils.log_info("Transfering sculpt base shape to source body...")
|
||||
|
||||
utils.unhide(multires_mesh)
|
||||
utils.unhide(source_body)
|
||||
copy_base_shape(multires_mesh, source_body, layer_target, True)
|
||||
if norm_body and source_body:
|
||||
copy_base_shape(norm_body, source_body, layer_target, True)
|
||||
|
||||
# if there is a detail sculpt body, update that with the new base shape too
|
||||
detail_body = chr_cache.get_detail_body(context_object=source_body)
|
||||
if detail_body:
|
||||
copy_base_shape(multires_mesh, detail_body, layer_target, True)
|
||||
# if there is a detail sculpt body, update that with the new base shape too
|
||||
detail_body = chr_cache.get_detail_body(context_object=source_body)
|
||||
if detail_body:
|
||||
# the base shape has only been applied to the norm_body so far ...
|
||||
copy_base_shape(norm_body, detail_body, layer_target, True)
|
||||
|
||||
utils.delete_mesh_object(norm_body)
|
||||
|
||||
# restore render engine
|
||||
bake.post_bake(context, bake_state)
|
||||
|
||||
@@ -607,10 +607,13 @@ def func_export_eye_depth(cc, depth):
|
||||
return (depth) * 3.0
|
||||
|
||||
def func_set_eye_depth(cc, depth):
|
||||
return depth * 1.5
|
||||
return depth * 1.0
|
||||
|
||||
def func_set_parallax_iris_depth(cc, depth):
|
||||
return depth * 1.5 + 0.1
|
||||
return depth * 1.0
|
||||
|
||||
def func_set_parallax_pupil_scale(cc, scale):
|
||||
return scale * 0.6666
|
||||
|
||||
def func_index_f0(cc, v: list):
|
||||
return v[0]
|
||||
|
||||
@@ -1499,6 +1499,10 @@ def hide_tree(obj, hide=True, render=False):
|
||||
except: ...
|
||||
|
||||
|
||||
def show(obj: bpy.types.Object, show=True, render=False):
|
||||
hide(obj, hide=not show, render=render)
|
||||
|
||||
|
||||
def hide(obj: bpy.types.Object, hide=True, render=False):
|
||||
try:
|
||||
obj.hide_set(hide)
|
||||
|
||||
Reference in New Issue
Block a user