=== WHAT'S BEEN DONE (Recent) === MCP Pipeline Factory: - 38 MCP servers tracked across 7 pipeline stages - 31 servers at Stage 16 (Website Built) — ready to deploy - All 30 production servers patched to 100/100 protocol compliance - Built complete testing infra: mcp-jest, mcp-validator, mcp-add, MCP Inspector - 702 auto-generated test cases ready for live API testing - Autonomous pipeline operator system w/ 7 Discord channels + cron jobs - Dashboard live at 192.168.0.25:8888 (drag-drop kanban) CloseBot MCP: - 119 tools, 4,656 lines TypeScript, compiles clean - 14 modules (8 tool groups + 6 UI apps) GHL MCP: - Stage 11 (Edge Case Testing) — 42 failing tests identified Sub-agent _meta Labels: - All 643 tools across 5 MCPs tagged (GHL, Google Ads, Meta Ads, Google Console, Twilio) OpenClaw Upwork Launch: - 15 graphics, 6 mockups, 2 PDFs, 90-sec Remotion video - 3-tier pricing: $2,499 / $7,499 / $24,999 - First $20k deal closed + $2k/mo retainer (hospice) Other: - Surya Blender animation scripts (7 tracks) - Clawdbot architecture deep dive doc - Pipeline state.json updates === TO-DO (Open Items) === BLOCKERS: - [ ] GHL MCP: Fix 42 failing edge case tests (Stage 11) - [ ] Expired Anthropic API key in localbosses-app .env.local - [ ] Testing strategy decision: structural vs live API vs hybrid NEEDS API KEYS (can't progress without): - [ ] Meta Ads MCP — needs META_ADS_API_KEY for Stage 8→9 - [ ] Twilio MCP — needs TWILIO_API_KEY for Stage 8→9 - [ ] CloseBot MCP — needs CLOSEBOT_API_KEY for live testing - [ ] 702 test cases across all servers need live API credentials PIPELINE ADVANCEMENT: - [ ] Stage 7→8: CloseBot + Google Console need design approval - [ ] Stage 6→7: 22 servers need UI apps built - [ ] Stage 5→6: 5 servers need core tools built (FreshBooks, Gusto, Jobber, Keap, Lightspeed) - [ ] Stage 1→5: 3 new MCPs need scaffolding (Compliance GRC, HR People Ops, Product Analytics) PENDING REVIEW: - [ ] Jake review OpenClaw video + gallery → finalize Upwork listing - [ ] LocalBosses UI redesign (Steve Jobs critique delivered, recs available) QUEUED PROJECTS: - [ ] SongSense AI music analysis product (architecture done, build not started) - [ ] 8-Week Agent Study Plan execution (curriculum posted, Week 1 not started)
165 lines
5.7 KiB
Python
165 lines
5.7 KiB
Python
"""
|
|
Track 09: WITH U - Two Orbiting Souls/Spheres with Stars (THE TURN!)
|
|
"""
|
|
|
|
import bpy
|
|
import math
|
|
import random
|
|
import sys
|
|
import os
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
from utils import *
|
|
|
|
|
|
def create_with_u_animation():
|
|
"""Create the full Track 09 animation - the emotional centerpiece."""
|
|
clear_scene()
|
|
setup_scene(background_color=(0.047, 0.039, 0.035, 1.0)) # Warm dark
|
|
|
|
# Create camera
|
|
camera = create_camera(location=(0, -12, 6), rotation=(1.1, 0, 0))
|
|
animate_camera_orbit(camera, center=(0, 0, 0), radius=12, height=5,
|
|
start_frame=1, end_frame=TOTAL_FRAMES, revolutions=0.35)
|
|
|
|
# Create Soul 1 (main gold)
|
|
soul1 = create_sphere(location=(2, 0, 0), radius=0.4, segments=24, rings=16, name="Soul1")
|
|
soul1_mat = create_emission_material("Soul1Mat", COLORS["with_u"], strength=4.0)
|
|
soul1.data.materials.append(soul1_mat)
|
|
|
|
# Create Soul 2 (lighter gold)
|
|
soul2 = create_sphere(location=(-2, 0, 0), radius=0.35, segments=24, rings=16, name="Soul2")
|
|
soul2_mat = create_emission_material("Soul2Mat", (0.988, 0.827, 0.302, 1.0), strength=4.0)
|
|
soul2.data.materials.append(soul2_mat)
|
|
|
|
# Entrance animation
|
|
keyframe_scale(soul1, 1, 0.01)
|
|
keyframe_scale(soul1, 60, 1.0)
|
|
keyframe_scale(soul2, 1, 0.01)
|
|
keyframe_scale(soul2, 60, 1.0)
|
|
|
|
# Orbital dance animation
|
|
orbit_start = 90
|
|
orbit_end = 550
|
|
|
|
for frame in range(orbit_start, orbit_end + 1, 3):
|
|
t = (frame - orbit_start) / (orbit_end - orbit_start)
|
|
angle = t * 2.5 * math.pi
|
|
|
|
# Elliptical orbits with vertical motion
|
|
r1 = 2 + 0.3 * math.sin(angle * 2)
|
|
r2 = 2 + 0.3 * math.sin(angle * 2 + math.pi)
|
|
|
|
pos1 = (
|
|
r1 * math.cos(angle),
|
|
r1 * math.sin(angle),
|
|
0.5 * math.sin(angle * 3)
|
|
)
|
|
pos2 = (
|
|
r2 * math.cos(angle + math.pi),
|
|
r2 * math.sin(angle + math.pi),
|
|
0.5 * math.sin(angle * 3 + math.pi)
|
|
)
|
|
|
|
keyframe_location(soul1, frame, pos1)
|
|
keyframe_location(soul2, frame, pos2)
|
|
|
|
# Create orbital trails using curves
|
|
trail1_points = []
|
|
trail2_points = []
|
|
|
|
for t in range(100):
|
|
angle = t / 100 * 2.5 * math.pi
|
|
r1 = 2 + 0.3 * math.sin(angle * 2)
|
|
r2 = 2 + 0.3 * math.sin(angle * 2 + math.pi)
|
|
|
|
trail1_points.append((
|
|
r1 * math.cos(angle),
|
|
r1 * math.sin(angle),
|
|
0.5 * math.sin(angle * 3)
|
|
))
|
|
trail2_points.append((
|
|
r2 * math.cos(angle + math.pi),
|
|
r2 * math.sin(angle + math.pi),
|
|
0.5 * math.sin(angle * 3 + math.pi)
|
|
))
|
|
|
|
trail1 = create_curve_from_points(trail1_points, name="Trail1", bevel_depth=0.015)
|
|
trail1_mat = create_emission_material("Trail1Mat", COLORS["with_u"], strength=1.5)
|
|
trail1.data.materials.append(trail1_mat)
|
|
|
|
trail2 = create_curve_from_points(trail2_points, name="Trail2", bevel_depth=0.015)
|
|
trail2_mat = create_emission_material("Trail2Mat", (0.988, 0.827, 0.302, 1.0), strength=1.5)
|
|
trail2.data.materials.append(trail2_mat)
|
|
|
|
# Animate trails appearing
|
|
trail1.data.bevel_factor_end = 0.0
|
|
trail1.data.keyframe_insert(data_path="bevel_factor_end", frame=orbit_start)
|
|
trail1.data.bevel_factor_end = 1.0
|
|
trail1.data.keyframe_insert(data_path="bevel_factor_end", frame=orbit_end)
|
|
|
|
trail2.data.bevel_factor_end = 0.0
|
|
trail2.data.keyframe_insert(data_path="bevel_factor_end", frame=orbit_start)
|
|
trail2.data.bevel_factor_end = 1.0
|
|
trail2.data.keyframe_insert(data_path="bevel_factor_end", frame=orbit_end)
|
|
|
|
# EPIC MOMENT - Stars appear!
|
|
stars_appear_frame = 480
|
|
stars = create_star_field(count=200, radius=15, min_size=0.02, max_size=0.06)
|
|
|
|
for i, star in enumerate(stars):
|
|
keyframe_scale(star, 1, 0.01)
|
|
keyframe_scale(star, stars_appear_frame + i // 5, 0.01)
|
|
keyframe_scale(star, stars_appear_frame + i // 5 + 30, 1.0)
|
|
|
|
# Souls come together
|
|
union_start = 580
|
|
union_end = 650
|
|
|
|
keyframe_location(soul1, union_start, soul1.location[:])
|
|
keyframe_location(soul2, union_start, soul2.location[:])
|
|
|
|
keyframe_location(soul1, union_end, (0.35, 0, 0))
|
|
keyframe_location(soul2, union_end, (-0.35, 0, 0))
|
|
|
|
# Glow brighter together
|
|
# (In Blender, we'd animate material emission strength, but for export compatibility
|
|
# we'll animate scale as a visual indicator)
|
|
keyframe_scale(soul1, union_end, 1.0)
|
|
keyframe_scale(soul1, union_end + 30, 1.5)
|
|
keyframe_scale(soul2, union_end, 1.0)
|
|
keyframe_scale(soul2, union_end + 30, 1.5)
|
|
|
|
# Dim stars when souls unite
|
|
for star in stars:
|
|
keyframe_scale(star, union_end, 1.0)
|
|
keyframe_scale(star, union_end + 30, 0.7)
|
|
|
|
# Exit animation
|
|
keyframe_scale(soul1, TOTAL_FRAMES - 30, 1.5)
|
|
keyframe_scale(soul1, TOTAL_FRAMES, 0.01)
|
|
keyframe_scale(soul2, TOTAL_FRAMES - 30, 1.5)
|
|
keyframe_scale(soul2, TOTAL_FRAMES, 0.01)
|
|
|
|
return soul1, soul2, trail1, trail2, stars
|
|
|
|
|
|
if __name__ == "__main__":
|
|
create_with_u_animation()
|
|
|
|
output_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(output_dir, "exports", "track09_with_u.blend"))
|
|
|
|
bpy.ops.export_scene.gltf(
|
|
filepath=os.path.join(output_dir, "exports", "track09_with_u.gltf"),
|
|
export_animations=True,
|
|
export_format='GLTF_SEPARATE'
|
|
)
|
|
|
|
bpy.ops.wm.alembic_export(
|
|
filepath=os.path.join(output_dir, "exports", "track09_with_u.abc"),
|
|
start=1, end=TOTAL_FRAMES
|
|
)
|
|
|
|
print("Track 09 - With U: Export complete!")
|