Big update
This commit is contained in:
+100
-21
@@ -139,33 +139,33 @@ def knot_frame_handler(scene, depsgraph=None) -> None:
|
||||
config[key] = val_b
|
||||
|
||||
# Animated spin phase
|
||||
sP_a = item.torus_sP + effective_f * item.spin_phase_rate * reactivity
|
||||
sP_b = next_item.torus_sP + effective_f * next_item.spin_phase_rate * reactivity
|
||||
sP_a = item.torus_sP + effective_f * item.spin_phase_rate
|
||||
sP_b = next_item.torus_sP + effective_f * next_item.spin_phase_rate
|
||||
config["torus_sP"] = sP_a + (sP_b - sP_a) * t
|
||||
|
||||
# Animated revolution phase
|
||||
rP_a = item.torus_rP + effective_f * item.rev_phase_rate * reactivity
|
||||
rP_b = next_item.torus_rP + effective_f * next_item.rev_phase_rate * reactivity
|
||||
rP_a = item.torus_rP + effective_f * item.rev_phase_rate
|
||||
rP_b = next_item.torus_rP + effective_f * next_item.rev_phase_rate
|
||||
config["torus_rP"] = rP_a + (rP_b - rP_a) * t
|
||||
|
||||
# Animated height pulse
|
||||
h_a = item.torus_h + (
|
||||
math.sin(effective_f * item.height_rate * reactivity) * abs(item.height_rate) * 5.0
|
||||
math.sin(effective_f * item.height_rate) * abs(item.height_rate) * 5.0 * reactivity
|
||||
if item.height_rate != 0.0 else 0.0
|
||||
)
|
||||
h_b = next_item.torus_h + (
|
||||
math.sin(effective_f * next_item.height_rate * reactivity) * abs(next_item.height_rate) * 5.0
|
||||
math.sin(effective_f * next_item.height_rate) * abs(next_item.height_rate) * 5.0 * reactivity
|
||||
if next_item.height_rate != 0.0 else 0.0
|
||||
)
|
||||
config["torus_h"] = h_a + (h_b - h_a) * t
|
||||
|
||||
# Animated scale oscillation
|
||||
sc_a = (
|
||||
1.0 + item.scale_amplitude * math.sin(effective_f * item.scale_rate * reactivity)
|
||||
1.0 + item.scale_amplitude * math.sin(effective_f * item.scale_rate) * reactivity
|
||||
if item.scale_amplitude > 0.0 and item.scale_rate != 0.0 else None
|
||||
)
|
||||
sc_b = (
|
||||
1.0 + next_item.scale_amplitude * math.sin(effective_f * next_item.scale_rate * reactivity)
|
||||
1.0 + next_item.scale_amplitude * math.sin(effective_f * next_item.scale_rate) * reactivity
|
||||
if next_item.scale_amplitude > 0.0 and next_item.scale_rate != 0.0 else None
|
||||
)
|
||||
if sc_a is not None or sc_b is not None:
|
||||
@@ -176,21 +176,39 @@ def knot_frame_handler(scene, depsgraph=None) -> None:
|
||||
else:
|
||||
# Apply animated rates with reactivity (no transition)
|
||||
if item.spin_phase_rate != 0.0:
|
||||
config["torus_sP"] += effective_f * item.spin_phase_rate * reactivity
|
||||
config["torus_sP"] += effective_f * item.spin_phase_rate
|
||||
|
||||
if item.rev_phase_rate != 0.0:
|
||||
config["torus_rP"] += effective_f * item.rev_phase_rate * reactivity
|
||||
config["torus_rP"] += effective_f * item.rev_phase_rate
|
||||
|
||||
if item.height_rate != 0.0:
|
||||
config["torus_h"] += (
|
||||
math.sin(effective_f * item.height_rate * reactivity) * abs(item.height_rate) * 5.0
|
||||
math.sin(effective_f * item.height_rate) * abs(item.height_rate) * 5.0 * reactivity
|
||||
)
|
||||
|
||||
if item.scale_amplitude > 0.0 and item.scale_rate != 0.0:
|
||||
config["_scale_override"] = (
|
||||
1.0 + item.scale_amplitude * math.sin(effective_f * item.scale_rate * reactivity)
|
||||
1.0 + item.scale_amplitude * math.sin(effective_f * item.scale_rate) * reactivity
|
||||
)
|
||||
|
||||
# ── Apply Attenuverter Modulations ───────────────────────────────────────
|
||||
# Float mods
|
||||
for key in [
|
||||
"torus_R", "torus_r", "torus_eR", "torus_iR", "torus_h",
|
||||
"mobius_width", "liss_amp", "spiral_R",
|
||||
"geo_extrude", "geo_offset", "geo_bDepth"
|
||||
]:
|
||||
if f"mod_{key}" in config and config[f"mod_{key}"] != 0.0:
|
||||
config[key] += config[f"mod_{key}"] * reactivity
|
||||
|
||||
# Integer mods (clamp to minimum 1 for topology safety)
|
||||
for key in [
|
||||
"torus_p", "torus_q", "mobius_twists",
|
||||
"liss_kx", "liss_ky", "liss_kz", "spiral_turns"
|
||||
]:
|
||||
if f"mod_{key}" in config and config[f"mod_{key}"] != 0.0:
|
||||
config[key] = max(1, config[key] + int(config[f"mod_{key}"] * reactivity))
|
||||
|
||||
# ── Cross-material blend ─────────────────────────────────────────────────
|
||||
cross_material = False
|
||||
if transition_active:
|
||||
@@ -200,26 +218,87 @@ def knot_frame_handler(scene, depsgraph=None) -> None:
|
||||
if cross_material:
|
||||
config["_skip_material"] = True
|
||||
|
||||
# ── Apply Global Settings & Overrides ────────────────────────────────────
|
||||
is_render = False
|
||||
if depsgraph is not None and getattr(depsgraph, "mode", 'VIEWPORT') == 'RENDER':
|
||||
is_render = True
|
||||
|
||||
res = glob.render_resolution if is_render else glob.preview_resolution
|
||||
bevel_res = glob.render_bevel_resolution if is_render else glob.preview_bevel_resolution
|
||||
|
||||
if "geo_bDepth" in config:
|
||||
config["geo_bDepth"] *= glob.global_master_thickness
|
||||
|
||||
if "preset_emission_strength" in config:
|
||||
config["preset_emission_strength"] *= glob.global_emission_multiplier
|
||||
|
||||
if "preset_color" in config and glob.global_hue_shift != 0.0:
|
||||
import colorsys
|
||||
color_val = config["preset_color"]
|
||||
if len(color_val) == 4:
|
||||
r, g, b, a = color_val
|
||||
else:
|
||||
r, g, b = color_val
|
||||
a = 1.0
|
||||
|
||||
h_hsv, s, v = colorsys.rgb_to_hsv(r, g, b)
|
||||
h_hsv = (h_hsv + glob.global_hue_shift) % 1.0
|
||||
nr, ng, nb = colorsys.hsv_to_rgb(h_hsv, s, v)
|
||||
|
||||
if len(color_val) == 4:
|
||||
config["preset_color"] = (nr, ng, nb, a)
|
||||
else:
|
||||
config["preset_color"] = (nr, ng, nb)
|
||||
|
||||
# Resolve globals once and pass explicitly — no bpy.context inside geometry
|
||||
_make_torus_knot(
|
||||
config,
|
||||
resolution=glob.resolution,
|
||||
bevel_resolution=glob.bevel_resolution,
|
||||
resolution=res,
|
||||
bevel_resolution=bevel_res,
|
||||
knot_scale=glob.knot_scale,
|
||||
scene=scene,
|
||||
turbulence=glob.global_turbulence,
|
||||
smooth_shading=glob.smooth_shading,
|
||||
)
|
||||
|
||||
if cross_material:
|
||||
blend_name = f"KnotBlend_Item_{idx}"
|
||||
blend_mat = bpy.data.materials.get(blend_name)
|
||||
if blend_mat:
|
||||
mix_node = blend_mat.node_tree.nodes.get("_KnotBlendMix")
|
||||
if mix_node:
|
||||
mix_node.inputs["Fac"].default_value = float(t)
|
||||
|
||||
blend_obj = bpy.data.objects.get(KNOT_OBJ_NAME)
|
||||
if blend_obj:
|
||||
blend_obj = bpy.data.objects.get(KNOT_OBJ_NAME)
|
||||
if blend_obj:
|
||||
if blend_mat:
|
||||
mix_node = blend_mat.node_tree.nodes.get("_KnotBlendMix")
|
||||
if mix_node:
|
||||
mix_node.inputs["Fac"].default_value = float(t)
|
||||
if len(blend_obj.data.materials) == 0:
|
||||
blend_obj.data.materials.append(blend_mat)
|
||||
else:
|
||||
blend_obj.data.materials[0] = blend_mat
|
||||
elif mat_a:
|
||||
# Fallback if blend material wasn't generated
|
||||
if len(blend_obj.data.materials) == 0:
|
||||
blend_obj.data.materials.append(mat_a)
|
||||
else:
|
||||
blend_obj.data.materials[0] = mat_a
|
||||
|
||||
# ── Post-Geometry Object Overrides ───────────────────────────────────────
|
||||
knot_obj = bpy.data.objects.get(KNOT_OBJ_NAME)
|
||||
if knot_obj:
|
||||
knot_obj.display_type = 'WIRE' if glob.viewport_wireframe else 'TEXTURED'
|
||||
knot_obj.rotation_euler[2] = effective_f * glob.auto_turntable_speed
|
||||
|
||||
# ── Camera Shake ─────────────────────────────────────────────────────────
|
||||
cam = scene.camera
|
||||
if cam:
|
||||
shake = glob.camera_shake_amplitude
|
||||
if shake > 0.0:
|
||||
import random
|
||||
# Deterministic noise based on frame for stable rendering
|
||||
random.seed(int(f * 1000))
|
||||
cam.delta_location = (
|
||||
random.uniform(-shake, shake),
|
||||
random.uniform(-shake, shake),
|
||||
random.uniform(-shake, shake)
|
||||
)
|
||||
else:
|
||||
cam.delta_location = (0.0, 0.0, 0.0)
|
||||
|
||||
Reference in New Issue
Block a user