"""JANCTION Render example 27: kinetic typography, letters popping up one by one with an overshoot (48 frames, EEVEE, MP4).

Reproduce: render_final(scene_url="https://render.janction.jp/samples/ex27_kinetic_type.py",
                        frame_start=1, frame_end=48, width=1280, height=720, engine="eevee", output="mp4",
                        environment="studio")
Each letter is its own extruded text object; it scales 0 -> 1.25 -> 1 and rises from the floor, three frames
after the one before. Change TEXT (capital letters and spaces) for your own title.
"""
import math

import bpy

for ob in list(bpy.data.objects):
    bpy.data.objects.remove(ob, do_unlink=True)
scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = 48
scene.render.fps = 24
TEXT = "MAKE IT MOVE"
ADVANCE = 0.78          # 1 文字の幅（大文字の目安）
STAGGER = 3             # 次の文字までのコマ数
COLORS = [(0.95, 0.35, 0.25), (0.98, 0.72, 0.2), (0.25, 0.7, 0.55), (0.25, 0.5, 0.95)]


def material(name, color, roughness=0.35, metallic=0.0):
    mat = bpy.data.materials.new(name)
    bsdf = mat.node_tree.nodes["Principled BSDF"]
    bsdf.inputs["Base Color"].default_value = (*color, 1.0)
    bsdf.inputs["Roughness"].default_value = roughness
    bsdf.inputs["Metallic"].default_value = metallic
    return mat


mats = [material(f"Letter{i}", c) for i, c in enumerate(COLORS)]
width = ADVANCE * (len(TEXT) - 1)
k = 0
for i, ch in enumerate(TEXT):
    if ch == " ":
        continue
    curve = bpy.data.curves.new(f"Glyph{i}", type="FONT")
    curve.body = ch
    curve.align_x = "CENTER"
    curve.align_y = "BOTTOM_BASELINE"
    curve.extrude = 0.12
    curve.bevel_depth = 0.015
    curve.size = 1.1
    letter = bpy.data.objects.new(f"Letter_{i}_{ch}", curve)
    scene.collection.objects.link(letter)
    letter.location = (i * ADVANCE - width / 2, 0, 0)
    letter.rotation_euler = (math.radians(90), 0, 0)
    letter.data.materials.append(mats[k % len(mats)])
    start = 1 + k * STAGGER
    # 0 → 1.25（行き過ぎ）→ 1。床の下から少し持ち上がる
    for frame, s, z in ((start, 0.0, -0.4), (start + 6, 1.25, 0.12), (start + 10, 1.0, 0.0)):
        letter.scale = (s, s, s)
        letter.location.z = z
        letter.keyframe_insert("scale", frame=frame)
        letter.keyframe_insert("location", index=2, frame=frame)
    k += 1

bpy.ops.mesh.primitive_plane_add(size=40, location=(0, 0, 0))
floor = bpy.context.active_object
floor.data.materials.append(material("Floor", (0.06, 0.065, 0.08), roughness=0.25))

bpy.ops.object.light_add(type="AREA", location=(0, -4, 5))
key = bpy.context.active_object
key.data.energy = 800
key.data.size = 6
key.rotation_euler = (math.radians(40), 0, 0)

# 12 文字の幅（約 8.6 m）が 50 mm で収まる距離。文字の中ほど（高さ 0.45 m）を見る
bpy.ops.object.camera_add(location=(0, -15.5, 1.6), rotation=(math.radians(85.8), 0, 0))
cam = bpy.context.active_object
cam.data.lens = 50
# ゆっくり寄る（48 コマで 1.2 m）
cam.keyframe_insert("location", frame=1)
cam.location.y += 1.2
cam.keyframe_insert("location", frame=48)
scene.camera = cam
