Files
Pr3tz/knot_animation/scene_setup.py
T
2026-05-31 17:35:06 -04:00

75 lines
3.4 KiB
Python

"""
scene_setup.py
--------------
One-shot scene initialisation: camera, area light, world background,
render engine, and default playlist.
Call ``setup_scene()`` once after ``register()`` (typically from
``__main__`` or a startup hook).
"""
from __future__ import annotations
import bpy
from .constants import (
CAMERA_LOCATION, CAMERA_ROTATION,
LIGHT_LOCATION, LIGHT_ENERGY,
)
from .materials import prewarm_materials_and_blends
def setup_scene() -> None:
"""Configure the Blender scene for knot animation playback."""
scene = bpy.context.scene
# ── Timeline ─────────────────────────────────────────────────────────────
scene.frame_start = 1
scene.frame_end = 600
scene.render.fps = 24
# ── Render engine ────────────────────────────────────────────────────────
scene.render.engine = 'CYCLES'
scene.cycles.samples = 64
# ── Remove default objects ───────────────────────────────────────────────
for name in ("Cube", "Light", "Camera"):
obj = bpy.data.objects.get(name)
if obj:
bpy.data.objects.remove(obj, do_unlink=True)
# ── Camera ───────────────────────────────────────────────────────────────
cam_data = bpy.data.cameras.new("KnotCamera")
cam_data.lens = 50
cam_obj = bpy.data.objects.new("KnotCamera", cam_data)
cam_obj.location = CAMERA_LOCATION
cam_obj.rotation_euler = CAMERA_ROTATION
scene.collection.objects.link(cam_obj)
scene.camera = cam_obj
# ── Area Light ───────────────────────────────────────────────────────────
light_data = bpy.data.lights.new("KnotLight", type='AREA')
light_data.energy = LIGHT_ENERGY
light_data.size = 3.0
light_obj = bpy.data.objects.new("KnotLight", light_data)
light_obj.location = LIGHT_LOCATION
scene.collection.objects.link(light_obj)
# ── World background: dark gradient ──────────────────────────────────────
world = scene.world
if world is None:
world = bpy.data.worlds.new("KnotWorld")
scene.world = world
bg_node = world.node_tree.nodes.get("Background")
if bg_node:
bg_node.inputs["Color"].default_value = (0.02, 0.02, 0.05, 1.0)
bg_node.inputs["Strength"].default_value = 0.2
# ── Default playlist ─────────────────────────────────────────────────────
# NOTE: An empty CollectionProperty is falsy in Python; use len() to test.
if len(scene.knot_list) == 0:
bpy.ops.knot.populate() # also calls prewarm_materials_and_blends()
else:
prewarm_materials_and_blends(scene) # ensure shaders exist for existing list
print("[KnotScript] Scene setup complete.")