Land Explorer in HomeCamp with boot loading, journal UI, and CDN publish tooling.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import time
|
||||
import json
|
||||
from pathlib import Path
|
||||
import requests
|
||||
|
||||
BASE = "http://127.0.0.1:8008"
|
||||
JOB_ID = "25f0f3ce2d124e748bc3e8415e7289c7"
|
||||
OUTPUT_DIR = Path("Tools/output/explorer_3d")
|
||||
|
||||
session = requests.Session()
|
||||
|
||||
def wait_job(timeout=600, interval=2):
|
||||
deadline = time.monotonic() + timeout
|
||||
while time.monotonic() < deadline:
|
||||
r = session.get(f"{BASE}/api/jobs/{JOB_ID}", timeout=30)
|
||||
r.raise_for_status()
|
||||
job = r.json()
|
||||
status = job.get("status")
|
||||
stage = job.get("stage", "")
|
||||
progress = job.get("progress", 0)
|
||||
print(f"[{status}] stage={stage} progress={progress}%", flush=True)
|
||||
if status in ("completed", "failed"):
|
||||
if status != "completed" or job.get("error"):
|
||||
raise RuntimeError(f"Animation failed: {job.get('error') or job}")
|
||||
return job
|
||||
time.sleep(interval)
|
||||
raise TimeoutError("Animation timeout")
|
||||
|
||||
def download(url, out_path):
|
||||
r = session.get(f"{BASE}{url}", timeout=300)
|
||||
r.raise_for_status()
|
||||
out = Path(out_path)
|
||||
if r.content[:4] == b"PK\x03\x04":
|
||||
out = out.with_suffix(".zip")
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
out.write_bytes(r.content)
|
||||
print(f"Downloaded: {out} ({len(r.content)} bytes)")
|
||||
return out
|
||||
|
||||
# 1. Walk Animation
|
||||
print("\n=== Generating Walk Animation ===")
|
||||
r = session.post(f"{BASE}/api/jobs/{JOB_ID}/animate", data={
|
||||
"motion_prompt": "A person walks forward at a steady pace.",
|
||||
"seed": 42,
|
||||
"cfg_scale": 5,
|
||||
"in_place": "true"
|
||||
})
|
||||
print("Walk trigger:", r.status_code, r.text[:200])
|
||||
walk_job = wait_job()
|
||||
walk_dir = OUTPUT_DIR / "walk"
|
||||
walk_dir.mkdir(parents=True, exist_ok=True)
|
||||
for k, u in walk_job.get("downloads", {}).items():
|
||||
if "anim" in k:
|
||||
download(u, walk_dir / (k + (".fbx" if "fbx" in k else ".glb")))
|
||||
|
||||
# 2. Idle Animation
|
||||
print("\n=== Generating Idle Animation ===")
|
||||
r = session.post(f"{BASE}/api/jobs/{JOB_ID}/animate", data={
|
||||
"motion_prompt": "A person stands calmly in an idle breathing pose.",
|
||||
"seed": 100,
|
||||
"cfg_scale": 5,
|
||||
"in_place": "true"
|
||||
})
|
||||
print("Idle trigger:", r.status_code, r.text[:200])
|
||||
idle_job = wait_job()
|
||||
idle_dir = OUTPUT_DIR / "idle"
|
||||
idle_dir.mkdir(parents=True, exist_ok=True)
|
||||
for k, u in idle_job.get("downloads", {}).items():
|
||||
if "anim" in k:
|
||||
download(u, idle_dir / (k + (".fbx" if "fbx" in k else ".glb")))
|
||||
|
||||
print("\nBoth animations generated and downloaded successfully!")
|
||||
|
||||
Reference in New Issue
Block a user