# anyscene

Adopt this skill: https://proskills.md/skills/other/apekshik-anyscene

Page: https://proskills.md/skills/other/apekshik-anyscene
This document is the public skill bundle for that page. It contains SKILL.md and every helper file the catalog carries. No login is required.

## File: SKILL.md
size: 18488
sha: f19099503a2cd3ade7306414a248b433e7990515
upstream: https://github.com/apekshik/anyscene/blob/HEAD/SKILL.md

````text
---
name: anyscene
description: Build a photoreal, film-style Blender scene from a one-paragraph brief. Generate concept images and every prop with image→3D models on fal, then script the layout, set dressing, grime, lighting, camera moves and grade. Use it when someone asks for a realistic 3D environment, a set or a cinematic shot of a place, whether starting fresh or extending an existing AnyScene scene.
---

# AnyScene

AnyScene turns a brief like "a 1 AM electronics repair shop in Tokyo, rain outside" into a dressed, lit Blender scene with
cinematic shots and a behind-the-scenes video. Agents built the two example scenes (`scenes/tokyo-electronics-repair`, `scenes/tokyo-ramen-shop`) with this process.
Each has 75–90 generated props, 8–9 shots, and about $150 of generation per round.

You are the art department, set dresser, gaffer and DP. Everything is a script you can re-run; the .blend is a build output.
Never hand-edit a .blend you can't regenerate.

## Requirements

| Tool | Notes |
|---|---|
| Blender 5.0+ | `$BLENDER`. Background mode (`-b`) for everything; the GUI is only for a human to look. |
| ffmpeg | `$FFMPEG`. Needs an h264 encoder (`libx264` or `h264_nvenc`), `curves`, `hue`, `vignette`, `noise`, `xfade`. |
| Node 20+ | for `generate/fal.mjs` |
| fal key | `FAL_KEY` env var. Never print or log it. |
| GPU | 12–16 GB is enough for one Cycles render at a time. Two at once runs out of memory: see GPU rules. |

## Layout of a scene

```
scenes/<scene>/
  brief.md            the brief + decisions (mood, time, lens style), kept up to date (new; the reference scenes keep this in NOTES.md)
  assets.json         room dims + every prop: id, prompt, height h, optional dims [x,y,z]
  picks.json          per prop: chosen model + one-line why; retired / debranded flags
  shots.json          camrig shots (see camera/README.md)
  NOTES.md            gotchas you hit, in one line each — read it before touching the scene
  props/<id>.blend    prepped props (output of prep)
  out/                renders, sheets, graded shots
  scripts/            the scene's build scripts: shell, dress, validate, grime, lights, post
refs/<scene>/         concept images, prop references, textures/decals
assets/gen/<model>/<id>/model.glb   raw generator output (never edited)
```

Reusable pieces (don't fork them per scene unless you need to change them):
- `generate/fal.mjs`: image and 3D generation, with an append-only spend log.
- `pipeline/gpu_run.sh`: a FIFO GPU queue.
- `pipeline/render_compare.py`: same-light comparison renders.
- `camera/`: camera rig and shot renderer.
- `breakdown/assemble.py`: the behind-the-scenes video.
- `pipeline/build_scenes_page.mjs`: the gallery page.

## The pipeline

Work in this order. Each step ends with a **gate**: a contact sheet or check you look at before moving on. Look at the
images yourself. A script that ran without errors proves nothing about how the scene looks.

### 1. Brief → scene spec

Write `brief.md`:
- the place, the time of day and the weather;
- 3–5 mood words;
- the room size in metres;
- where the street/door is (put it at y=0 and make the room deep along +Y);
- zones (counter, bench, kitchen, racks);
- 2–3 hero spots the camera will live on;
- the light sources that would really exist there (practicals).

Real places are small: the repair shop is about 3.5 × 6 m. Keep it tight. Density sells realism more than size does.

### 2. Concept images

Run `node generate/fal.mjs image --variant sunburst --out refs/<scene>/concept_wide --prompt "..."`, and again for a
detail shot. GPT Image 2.5 Sunburst beat Flare on legible signage text and natural grade. These set palette, clutter level
and the prop list; you don't match them shot for shot.

**Gate:** the user (or you, if running solo) agrees on the look.

### 3. Prop manifest

List every object in `assets.json`. Sort them into four tiers:
- **furniture** (scripted);
- **hero props** (generated);
- **mid props** (generated);
- **clutter and decals** (generated or direct-modelled).

Decide per object whether to generate it or direct-model it:
- **Direct-model** anything architectural or simple-and-exact: walls, counters, shelving, boxes, cables, paper, glass panes, signage text (real font text objects).
- **Generate** anything with character: appliances, tools, electronics, crockery, food, bins.

Give every generated prop:
- `h`: its real height in metres;
- `dims`: for boxy things, because generators invent depth (fridges, ticket machines, ranges);
- a prompt describing one object, its condition and its materials. **No brand names.**

### 4. References → 3D, both models

For each prop:
1. Generate a reference with the scan template appended. This is the exact text the reference scenes used:
   > No real-world brand names or logos. Product reference photograph for 3D scanning. The entire object fully visible and centered, three-quarter front view from slightly above, plain seamless light-grey background, soft even diffuse studio lighting, no harsh shadows, no other objects, no hands, realistic used and worn condition, sharp focus, true-to-life materials.
2. Send the same reference to **both** Tripo H3.1 (`--model tripo-h31`) and Meshy 7.1 (`--model meshy`).

Notes:
- Run about 12 jobs concurrently. About 10–20% fail transiently (504, ECONNRESET, Meshy timeouts after about 10 min); re-run the same ids. The script skips GLBs that already exist.
- **Never run two generation passes at once.** Existence is checked at start, so in-flight jobs get double-submitted.
- References often come back with real brands even when told not to. Check every reference and regenerate those that carry one as `<id>_nb`, with a fictional brand.

**Gate:** a reference sheet with no real brands.

### 5. Compare and pick

Render reference | Tripo | Meshy, front, back and clay, under the same light (`render_compare.py`), then sheet them. Pick per prop and
record the choice and a one-line why in `picks.json`.

What the reference scenes found across ~150 props:
- **Meshy 7.1** wins about 70% of the time: small consumer items, sharper printed labels.
- **Tripo H3.1** wins big hard-surface heroes, where real geometry matters (knobs, bezels, dents). It's about 2M tris, so it needs decimating.
- **Both** produce opaque glass, so fix glass by script.
- Meshy speckles flat panels. Look at the clay render, not just the beauty render: it shows which details are real geometry.

**Gate:** the picks sheet. Every prop has a winner or is retired.

### 6. Prep

Turn every pick into `props/<id>.blend`:
- **Front faces −Y.** Tripo's front faces +X, so rotate it −90°; Meshy's already faces −Y. Rotate the mesh data, not the object. Tripo H3.1 with `orientation: align_image` also bakes a ±20–30° Z rotation into the glTF node (to match the reference photo's three-quarter view): clear that node rotation before the −90° turn, and frame by vertex bounds, not `bound_box`.
- **Real scale** from `h`/`dims`.
- **Bottom-centre origin.**
- **Decimate** heroes to about 150k tris.
- **Textures** at 2K or less.

Gotchas:
- glTF imports use QUATERNION rotation mode, so `rotation_euler` is silently ignored. Set `rotation_mode = "XYZ"` first.
- glTF images arrive packed. Calling `pack()` again on an unmodified image drops its data and the prop renders magenta. Repack only the images you resized.
- Pass absolute paths to Blender, or relative paths resolve against the wrong directory.

### 7. Shell and layout

Script the room: floor, walls, ceiling, storefront and glass, counters, shelving and fixed furniture. Name objects clearly; shots and
lights reference them by name. Gotchas:
- A smooth-shaded box without a bevel acts as a lens when it's glass.
- `matrix_world` on objects created in the same script is stale until `view_layer.update()`.

**Gate:** a clay sheet from the hero camera positions.

### 8. Dressing, big → small

Place furniture props, then heroes, then mid props, then clutter. Each pass drops props onto surfaces with raycasts.

- **Start drop rays below anything overhead** (shelf above, hood, conduit), or the prop lands on top of it.
- **Vary instances** with `ob.color` multiplied into albedo (Object Info › Color), so repeated meshes don't read as copies.
- **Run the validator after every pass.** Check each prop for:
  - a BVH mesh overlap against fixed furniture (lift the prop 3 mm before testing);
  - prop–prop clashes;
  - floating more than 1 cm. Start the float ray *above* the support's top face, or a thin bench top reports its own thickness.

  Clashing small props get spiral-searched to a clear spot. Validator reports are noisy, so read them: a plinth or pots on a burner can be legitimate.
- **Re-drop after every move.** Anything a clash resolver or a later pass moves sideways must be dropped onto the
  surface under its new position. Skipping this left two stools hovering at table height in the dai pai dong.
- **Run the grounding check** after the last dressing pass and again before final renders:
  `blender -b scene.blend --python pipeline/grounding.py -- --prefix <scene prefix> --max-gap 2`, then with `--all`.
  It casts rays down from each object's lowest vertices (feet, legs, base rings) and skips volumes. Checking from the
  bounding box misses floaters whenever the box bottom isn't where the object touches down. Fix floaters in the
  dressing scripts, not only in the saved file, so a rebuild stays grounded. Hanging items (signs, AC units, lamps,
  posters) are skipped unless you pass `--all`; check that each one it lists really is meant to hang.

**Gate:**
- The validator and the grounding check show 0 unexplained issues: no prop more than 1 cm off its support.
- A dressed clay sheet and a textured flat-lit sheet.
- **A contact sheet of low-angle stills** (camera ~30 cm off the floor) along the main furniture: chairs, stools,
  tables, bins. A floating chair is obvious from there and nearly invisible in a wide shot.

### 9. Script fixes, grime and de-branding

- **Screens:** CRT screens become emissive with a scanline glow, and scopes get a graticule and trace. Fix lamp lenses, display glass and bottles to real glass.
- **Grime:** a shared node group with AO-driven dirt, edge wear and per-instance tint. Add decals (stains, flyers, stickers) generated on flat backgrounds, alpha-keyed and stuck on with raycasts.
- **De-branding without regenerating:** render ortho views and mark the brand rectangles. Raycast the rectangles to texels, fill each with the label's ground colour plus grain, and flatten the same texels in the normal map, or embossed text survives.

### 9b. Build the scene as a rig of dials

The scene must expose the ten dials in `docs/ENDPOINT.md` (density, tidiness, wear, wetness, time_of_day, weather,
atmosphere, power, warmth, look) as real controls, so they can be changed after the build without rebuilding:
- **wear:** one strength input on the shared grime group, plus decal counts and label fading, all driven by one value;
- **wetness:** a wetness mask feeding roughness, puddle masks and drips;
- **atmosphere:** the density of every haze, dust, smoke and steam volume, scaled together;
- **power:** lights and emitters in named groups (practicals, screens, fires and flames, machines), each switched or
  dimmed by one value;
- **time_of_day, weather:** sky/world and sun setups plus weather objects (rain, mist) selected by name;
- **warmth, look:** light colour temperatures and the grade preset;
- **density, tidiness:** recorded as the values the dressing passes used; changing them reruns those passes.

Write `dials.json` (each dial's value plus what it means in this scene) and `scripts/apply_dials.py`, which reads
`dials.json` and sets every control. Apply the dials once at the end of the build, so the rig is what produced the
finals.

### 10. Lighting (night)

1. Start with practicals: the light fixtures a real place would have (lamps, pendants, tubes, signage, screens, the fridge, the street spill).
2. Add fills last and keep them weak. A 45 W bounce at exposure 1.0 made the room look like the overhead lights were on. Let the practicals make the contrast.

Gotchas:
- **Lamp shades:** generated shades are closed meshes, so put spots just under the rim, not inside.
- **Light direction:** area lights shine along local −Z.
- **Glass:** hide fills from camera, glossy *and* transmission rays, or they show through glass as bright discs.
- **Emissive meshes:** on dense generated meshes, texture-driven emission turns every triangle into a light. Set `material.cycles.emission_sampling = "NONE"` on those.
- **Exposure:** re-check it after every new practical.

**Gate:** Cycles stills of each hero spot at 32–64 spp.

### 11. Atmosphere and FX

- **Volumetric haze:** cheap and worth it.
- **Steam (Mantaflow):** set `surface_distance` around 1.0 (it is measured in cells), and keep emitters well inside the domain.
- **Bake cache:** use negative cache frames so plumes are developed at frame 1. Clear the cache folder with `rmtree`: `fluid.free_all()` is async in background mode and deletes the new bake.
- **Motion blur:** turn object motion blur **off** on volume domains, or each frame costs about 290 s.
- **Rain:** particles with `rotation_mode = "VEL"` and drop geometry along +X.

### 12. Shots

Write `shots.json` for `camera/shoot.py`. Its README is the contract: moves, rack focus, lens FX and the handheld profiles.

1. **Block:** start with `--framing` (3 stamped stills per shot), then `--preview` (Eevee, stamped).
2. **Design:** mix 2–3 cinematic moves (push-ins, a dolly zoom, a 100–135 mm rack) with 1–2 long **handheld walkthroughs**: `"handheld": {"profile": "walk"}`, a 4–6 key `path` at walking pace. People respond most to the walkthroughs. Keep them as long, uncut takes.
3. **Path check:** check the camera against the scene before rendering, keeping more than 0.45 m from every solid surface on every frame (walls, furniture, props: not dust motes, particles, haze volumes or decals, which a real camera moves through). Load the scene once and test every frame in one Blender session.
4. **Focus:**
   - A focus target must never be one the camera passes through, or the distance collapses to 0 and the frame goes soft. Rack to something past it first.
   - Focus `obj` uses the bounding-box centre. For deep objects, put a `pos` on the face you want sharp.

**Gate:** previews reviewed. Each shot's framing, move and focus are approved before any final render.

### 13. Final renders

- **GPU prefs:** `blender -b file.blend` renders Cycles on the **CPU** unless a pre-script sets the GPU compute device (`--python scenes/<scene>/scripts/gpu_prefs.py`, before any other `--python`). Device prefs are user prefs and aren't saved in the .blend. This cost the reference scenes hours.
- **Chunks:** render in 24-frame chunks through `pipeline/gpu_run.sh`. Existing frames are skipped, so runs resume.
- **Settings:** 2.39:1 at 1280–1920 px wide, 48–64 spp with the denoiser. That runs about 4–12 s per frame on a 5070 Ti.
- **Encode:** with NVENC. Check every graded output's duration and frame count. A grade run over a frame folder with a gap silently produces a short clip.

### 14. Post

Grade in ffmpeg, not the Blender compositor. The 5.0 colour-balance and mask nodes misbehave. Keep only Glare and Lens
Distortion in Blender. Grade with `curves` (lift blacks to about 0.03, teal shadows, warm highlights), `hue=s=0.88`, a slight
`rgbashift`, `vignette` and temporal `noise`.

Deliver:
- graded shots;
- a reel (concat with stream copy);
- a compressed copy under 30 MB for chat.

### 15. Behind the scenes (optional)

`breakdown/SPEC.md` + `breakdown/assemble.py` make a one-minute video: concept, layout, props, dressing, materials, lighting, post and final shot.
The scene supplies four "dollhouse" clips, one 120° orbit with the ceiling and near walls hidden:
- clay layout;
- props popping in;
- clay to textures to grime;
- lights coming on in order.

## Running several scenes or agents at once

- **Ownership:** each agent owns its scene's folders and asset ids. Shared tools are read-only; copy one into your scene to change it.
- **One Blender on the GPU at a time:** previews included, everything through `pipeline/gpu_run.sh`. Keep each locked call under about 10 minutes.
- **Waiting on a condition:** wait on the actual condition, not a guess. A "GPU busy" check must not match its own command line, and killing a waiting shell does not kill its child processes. Both of these caused duplicate renders that overwrote finished work. After a pause or crash, list every `blender` process before starting anything.
- **Cross-scene ordering:** marker files only, e.g. `.gpu.<scene>_done`, and create one only when the work is actually done.
- **Other GPU apps:** another GPU-heavy app (Houdini, Unreal) running alongside can slow Cycles 8×. Tell the user rather than closing their apps.

## Budget and time (fal, Oct 2026)

| Item | Cost |
|---|---|
| Reference image | ~$0.25 |
| Tripo H3.1 | ~$0.60 |
| Meshy 7.1 | ~$0.80 |
| Per prop, both models | **~$1.65** |
| ~90-prop scene | ~$150 |

Every call is logged to `generate/spend.jsonl`; `node generate/fal.mjs spend` totals it.

Time on one 16 GB GPU: a scene is roughly a day of agent work, and the final shots are about 1–2 GPU-hours.

## Generalising to a new scene

1. Start from the closer example scene: copy its `assets.json`, `shots.json` and `scripts/` into `scenes/<your-scene>/`
   (name the folder after the place, e.g. `lisbon-tram-depot`), then rewrite `brief.md` and `assets.json` for it.
2. Reuse the shared tools as they are. Reuse an example scene's `scripts/` as a starting point, but the
   shell and the dressing passes are always scene-specific. That's where your judgement goes.
3. Keep `NOTES.md` as you go. Anything that cost you more than 10 minutes gets one line. The next agent reads it first.

## Definition of done

- [ ] Every placed prop is in `picks.json` with a reason, and no real brands are visible in any shot.
- [ ] The validator is clean, or every remaining report is explained.
- [ ] `pipeline/grounding.py` reports 0 unintended floaters on the file the finals are rendered from.
- [ ] Each hero spot has a final still, and every shot is rendered, graded and has the right duration.
- [ ] There's a reel and a compressed copy; an optional BTS video.
- [ ] `NOTES.md` is updated, and the spend is totalled.
````

## File: blender_addon/README.md
size: 10209
sha: 55d82c7e95690b00bae8322cfb891c1b8d60deb5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/README.md

````text
# fal Render Farm (Blender add-on)

Render the open scene on the AnyScene render farm (fal Serverless, RTX PRO 6000 GPUs) instead of your local GPU.
Direct a downloaded scene in your own Blender (cameras, lights, edits), then press **Render animation on fal**. Frames
come back into the scene's own output path with the same names a local render would give them.

```
blender_addon/
  fal_render_farm/            the add-on (an extension folder: blender_manifest.toml + bl_info, works either way)
    __init__.py               panel, operators, preferences, status bar, UI timer
    job.py                    planning (main thread) and the job runner (background thread)
    fal_api.py                fal queue API + fal storage upload over plain urllib
    pack_copy.py              runs in a separate Blender on a temp copy: make local, pack_all, refuse on externals
    farm_gpu.py               shipped in every bundle, run with --python on the farm: OptiX/CUDA + GPU on every scene
  fal_render_farm-1.0.0.zip   installable build
  tests/                      make_test_scene.py, test_farm.py (headless end-to-end test against the real farm)
```

## Install

Blender 4.2 or newer (built and tested on 5.0.1).

1. **Edit > Preferences > Get Extensions**, then the drop-down at the top right > **Install from Disk...**, and pick
   `blender_addon/fal_render_farm-1.0.0.zip`. Dragging the zip onto the Blender window also works.
2. Enable **fal Render Farm** if it isn't enabled already.

For development, symlink or copy `blender_addon/fal_render_farm/` into an extensions repo (or a legacy
`scripts/addons/` folder) instead.

## Set the key

Open the add-on's preferences (Preferences > Add-ons > fal Render Farm):

- **fal key**: the key of the account that owns the farm app (the Serverless key the farm is deployed under,
  `FAL_SERVERLESS_KEY` in this repo, not a generation-only `FAL_KEY`). It's a password field, stored in Blender's user preferences (`userpref.blend`), and the
  add-on never prints or logs it. Press **Check key** to make sure fal accepts it.
- **Farm app**: empty by default; set it to your own deployment of `farm/app.py`, e.g.
  `<your-fal-username>/blender-farm-2` (see "Farm change" below). The add-on refuses to render until it's set. A farm
  deployed from the older build as `blender-farm` returns **PNG frames only**; `blender-farm-2` is the same farm with
  one backward-compatible addition (an `outputs` field), so it also returns EXR, multilayer EXR, JPEG, TIFF and so on.
  The panel warns when the output format isn't PNG and the app is a `.../blender-farm`.
- **Frames per chunk** (24) and **Concurrent chunks** (20): one chunk is one farm request on one GPU.
- **Chunk timeout**, **Encode MP4 when done**, and the **ffmpeg** path (empty means use the one on PATH).

Remember to save preferences (or keep auto-save on).

## Render

**Properties > Render > fal Render Farm**:

- **Render animation on fal** renders the scene's frame range (and frame step).
- **Render this frame on fal** renders the current frame and saves it to the output path as frame N. If an Image
  Editor is open, the frame is shown there when it arrives.
- **Cancel** cancels in-flight chunks on fal. Frames that already arrived stay on disk.
- **Retry failed chunks** re-submits failed chunks against the bundle that's already uploaded.

What happens when you press render:

1. The open file, unsaved edits included, is written to a temp folder with `save_as_mainfile(copy=True)`. Your
   working file isn't modified or re-saved, and it doesn't get marked dirty.
2. A separate background Blender opens that copy, makes linked data local, runs `pack_all` and saves `scene.blend`.
   If something still points outside the file (unpackable images or movies, Alembic/USD caches, libraries), the
   render stops and the panel lists those paths.
3. `scene.blend` and `farm_gpu.py` are zipped, the `bundle_id` is set to the first 16 hex characters of the zip's
   sha256, and the zip is uploaded to fal storage. An unchanged bundle is uploaded only once per session.
4. Frames that already exist at their output path are **skipped** (that's how resume works). The remaining frames
   are cut into chunks. Each chunk goes to the queue API as
   `{bundle}/scene.blend -S <scene> --python {bundle}/farm_gpu.py -o {out}/frames/<filename pattern> -s A -e B -j STEP -a`,
   and at most *Concurrent chunks* are in flight at once.
5. Each finished chunk's zip is downloaded and its files are written to the paths that `scene.render.frame_path()`
   gives locally. That covers `#` padding, relative `//` paths and the file extension setting.

The scene renders with its own settings: engine, samples, resolution and percentage, file format and colour depth,
view layers, compositor, color management and camera. The only thing the farm changes is the device: `farm_gpu.py`
selects OptiX (or CUDA) and sets `cycles.device = 'GPU'`, the same way `builder/blender_gpu.py` does for the builder.

Progress appears in the panel (phase, chunks queued/rendering/done/failed, frames, elapsed time, GPU-seconds and their
cost) and in the status bar. Everything runs on a background thread, and a timer redraws the UI every 0.5 s, so
Blender stays responsive. Each failed chunk shows its error. A chunk is retried once automatically before it's marked
failed.

When an animation finishes with PNG/JPEG/TIFF/... frames and ffmpeg is available, the add-on writes an H.264 MP4
(`<name>_<first>-<last>.mp4`, CRF 16) next to the frames. EXR frames are skipped, because they're linear and belong
in your grade.

## What the estimate means

The estimate scales a measured reference to your scene. Mission control rendered at **5 to 7 s per frame at
1920x804 and 48 spp** on an RTX PRO 6000. That figure is multiplied by `(your pixels / 1920x804) x (your samples / 48)`,
using Cycles samples or EEVEE render samples. Each chunk also adds about 20 s of overhead (Blender start, scene load,
returning the frames). GPU time is priced at **$4.00 per GPU-hour**. Wall time assumes chunks run *Concurrent chunks*
at a time, plus about 90 s of cold start if the app has scaled to zero.

Treat the estimate as an order-of-magnitude figure, not a quote. Scene complexity, volumes, adaptive sampling,
denoising, light paths and EEVEE versus Cycles can each move the real number by 2x or more. Once a job is running,
the panel shows the real GPU-seconds the farm reports (render time plus bundle fetch per chunk). That figure leaves
out cold starts and idle keep-alive, which fal also bills.

## Troubleshooting

- **"Set your fal key"** or **HTTP 401/403**: the key is missing, or it belongs to an account that can't see the farm
  app. Use the farm owner's Serverless key and press **Check key**.
- **"the file references data that can't be packed"**: these are the listed images/movies/caches. Fix their paths or
  make them local. Fluid and other disk simulation caches aren't shipped (you get a warning, not an error), so bake
  them into the mesh or render those shots locally.
- **"output path is relative (//) but this file has never been saved"**: save the file once, or set an absolute
  output path.
- **"Output is a video format"**: the farm renders frame sequences in chunks. Pick PNG/EXR/... and turn on *Encode
  MP4*.
- **A chunk fails with "the farm returned no OPEN_EXR files"**: you're on a `blender-farm` deployment, which only returns
  PNG. Deploy and switch to `<your-fal-username>/blender-farm-2`.
- **Chunks sit in "queued"**: the farm is busy or scaling up (it allows at most 20 workers, shared with other jobs on
  the same app). They start once workers free up.
- **A chunk timed out**: lower *Frames per chunk*, or raise *Chunk timeout* (the farm's hard cap is 3600 s per request).
- **Frames look different from a local render**: the farm runs Blender **5.0.1** on Linux. Scenes that depend on
  add-ons (custom nodes, drivers that call add-on Python, Python-scripted drivers in general) only render correctly if
  the farm has them, and it has no add-ons. Disk caches and file-output nodes with absolute paths aren't shipped
  either.
- **Nothing comes back for a stereo/multiview scene**: per-view files (`_L`/`_R`) are written next to the frames,
  but resume doesn't know about them yet.
- The **System Console** (Window > Toggle System Console) shows one `fal render farm:` line per step and per chunk.

## Tests

```
"C:/Program Files/Blender Foundation/Blender 5.0/blender.exe" -b --factory-startup --python-exit-code 1 \
    --python blender_addon/tests/test_farm.py -- <workdir> --app <your-fal-username>/blender-farm-2 [--chunk 12] [--ffmpeg <path>]

BLENDER_USER_RESOURCES=<empty temp dir> "C:/Program Files/Blender Foundation/Blender 5.0/blender.exe" -b \
    --factory-startup --python-exit-code 1 --python blender_addon/tests/test_zip_install.py -- blender_addon/fal_render_farm-1.0.0.zip
```

Rebuild the zip with `blender --factory-startup --command extension build --source-dir blender_addon/fal_render_farm --output-dir blender_addon`.

The test builds a 48-frame 640x360 Cycles scene with an external texture and enables the add-on from its folder. It
reads `FAL_SERVERLESS_KEY` from the Windows user environment, for that process only, then draws the panel and polls
the operators. It renders the animation through the operator and checks every frame name. It also confirms the
working .blend is untouched, tests resume (it deletes 2 frames and re-renders), compares frame 1 against a local GPU
render (PSNR), and renders one EXR frame. It ends with a `TEST-SUMMARY` JSON line.

## Farm change (blender-farm-2)

`farm/app.py` gained one optional request field, `outputs` (glob patterns relative to `{out}`). It defaults to
`["**/*.png"]`, which is exactly the old behaviour, so existing clients (`farm/farm.py`, AnyShot's `farm_render`) are
unaffected. The add-on always sends `["frames/**/*"]`, and an older `blender-farm` deployment ignores the unknown field.
The changed app is deployed as `blender-farm-2` on your own account:

```
fal deploy farm/app.py::BlenderFarm --app-name blender-farm-2 --auth private
```

An existing `blender-farm` deployment doesn't need to be redeployed.
````

## File: camera/README.md
size: 13268
sha: 29f39c6c135481243d55916e6301bd9d3a2d47f7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/camera/README.md

````text
<!-- synced from github.com/apekshik/anyshot camera/README.md -->
# camrig: cinematic camera rig and shot renderer

`camera/shoot.py` adds one camera rig per shot to a scene .blend, then renders:
- preview blocking passes,
- framing checks,
- lens charts,
- final Cycles frames and mp4s.

Shots are described in a JSON file: an AnyShot order writes its own as `out/shots/<job>/shots.json`, and an AnyScene
build keeps its scouting cameras in `out/shots.json`. Examples live in `camera/examples/`.

The contract is stable. New fields may be added, but existing ones will not change meaning.

## CLI

```bash
. pipeline/env.sh   # sets $B (Blender) and $ROOT_ABS (absolute repo root)
# always through the shared GPU queue
pipeline/gpu_run.sh "$B" -b scenes/my-set/set.blend --python camera/shoot.py -- \
  --shots $ROOT_ABS/scenes/my-set/shots.json \
  --out   $ROOT_ABS/scenes/my-set/out/shots \
  [--only a,b] [--preview | --framing | --lenschart NAME] [--frames 1-24] [--still 12] [--save rigged.blend] [--no-encode] \
  [--engine eevee|cycles|workbench] [--step N]
```

| Mode | What it does | Output (`<out>/<shot>/…`) |
|---|---|---|
| *(default)* final | Renders with Cycles. Scene settings stay unless a shot field overrides them. Frames that already exist are skipped, so a run can be resumed. Encodes `<shot>.mp4` and a contact sheet once every frame exists. | `frames/####.png`, `<shot>.mp4`, `contact.png` |
| `--preview` | Renders with Eevee at 50% resolution, every frame (`--step N` renders every Nth), 16 TAA samples, no motion blur. The stamp is burned in per frame: shot name, frame, lens mm, f-stop, focus distance. `--engine cycles` gives a 16 spp denoised preview with the real lighting. | `preview/####.png`, `preview.mp4` |
| `--framing` | Renders a stamped low-res still of each shot at t = 0, 0.5 and 1 with Eevee, plus one 3×3 sheet for all shots. | `framing/t0.png`, `framing/t5.png`, `framing/t10.png`, `<out>/_framing.png` |
| `--lenschart NAME` | Renders shot NAME's t=0 position and aim at 18/24/35/50/85/135 mm with Eevee. | `lenschart/<mm>.png`, `<out>/<NAME>_lenschart.png` |
| `--frames a-b` | Renders only frames a..b of the shot (1-based). Use it to keep each `gpu_run` call short (aim for under about 10 minutes). | |
| `--still N` | Renders a single final-quality frame N. | `still_####.png` |
| `--save path.blend` | Writes the rigged scene so a human can open and tweak it in the UI. It never overwrites the input file. | |
| `--no-encode` | Skips mp4 and contact-sheet encoding. | |

The script never saves the input .blend. Every shot's rig is built fresh on each run.

## shots.json

```jsonc
{
  "defaults": { "fps": 24, "res": [1920, 1080], "aspect": "16:9", "samples": 256,
                "shutter": 180, "sensor": "s35", "fstop": 2.8, "ease": "inout", "handheld": 0.0 },
  "shots": [
    {
      "name": "counter_push",                 // [a-z0-9_], used for folders and the rig name
      "frames": 120,                          // length in frames
      "fps": 24,
      "res": [1920, 1080],
      "aspect": "2.39",                       // "16:9" | "1.85" | "2.39" — output is cropped to the aspect (res height recomputed from width)
      "samples": 256,                         // Cycles samples for final
      "shutter": 180,                         // motion blur shutter in degrees (0 = off)
      "sensor": "s35",                        // "s35" (24.89 mm) | "ff" (36 mm) | number in mm (sensor width)
      "move": "push_in",                      // see Moves
      "ease": "inout",                        // linear | in | out | inout — position/aim: one ease over the whole shot (passes through middle keys without stopping); lens/roll/focus/f-stop keys: eased per segment (hold + pull)
      "keys": [
        { "t": 0.0, "pos": [x,y,z], "aim": [x,y,z], "lens": 35, "roll": 0 },
        { "t": 1.0, "pos": [x,y,z], "aim_obj": "ramen_bowl_unfinished", "lens": 35 }
      ],
      "focus": { "mode": "rack", "keys": [ { "t": 0.0, "obj": "water_glass" }, { "t": 0.6, "pos": [x,y,z] } ] },
      "fstop": 2.0,                           // or "fstop_keys": [{ "t":0, "v":4 }, { "t":1, "v":1.4 }]
      "blades": 0, "ratio": 1.0,              // aperture blades (0 = round) and anamorphic ratio (>1 = oval bokeh)
      "handheld": 0.35,                       // 0..1, shake layered on top of the move
      "breathing": 0.5,                       // 0..1, slow drift (default = handheld)
      "lens_fx": { "distortion": 0.01, "dispersion": 0.01, "glare": "fog" }   // optional, see notes
    }
  ]
}
```

Units are metres and Blender world axes (Z up). Wherever the contract takes a position, an object name works too.
- `aim_obj` and `focus.obj` resolve to the **centre of that object's world bounding box**.
- `obj` matches the object name exactly. If nothing matches exactly, it uses the first object whose name starts with the given string, then the first case-insensitive substring match. Bounds include all mesh children, so a GLB import root works.
- `"aim_obj": "name", "aim_offset": [dx,dy,dz]` nudges the aim point from that centre. Keys also take `pos_obj` + `pos_offset`. A key that omits `pos` or `aim` holds the previous one.
- Optional `"exposure": EV` offsets the scene exposure for the shot. The scenes' old keyed exposure drift is removed and frozen at its frame-1 value, so it can't leak into new shots.

### Moves

All moves interpolate between `keys`; `move` sets defaults and validation:

| move | keys needed | notes |
|---|---|---|
| `static` | 1 | Locked off. Add `handheld` for life. |
| `dolly`, `truck`, `pedestal`, `push_in`, `crane` | 2 or more | Each key has a position and an aim. The names describe intent; they all interpolate the same way. |
| `pan`, `tilt` | 2 or more | Keep `pos` the same and change `aim`. |
| `orbit` | none (or 1 for lens and roll) | `"orbit": {"center":[x,y,z] or "center_obj":"name", "radius":1.2, "start_deg":-30, "end_deg":30, "height":1.3}`. Aims at the centre. Angles are measured from +X, counter-clockwise from above. |
| `dolly_zoom` | 2 (start and end `pos`; aim and lens at t=0) | Lens is solved per frame to hold the subject size: `lens(t) = lens0 · dist(t) / dist0`. Distance is measured to `"subject"` (pos or obj, defaults to the aim). |
| `path` | 3 or more | Smooth path through every key: Catmull-Rom on position, eased in time. |

### Focus

- `{"mode":"track","obj":"name"}`: the focus empty is parented to and follows that object's bounds centre.
- `{"mode":"point","pos":[x,y,z]}`
- `{"mode":"rack","keys":[{"t":0,"obj":"a"},{"t":0.6,"pos":[...]}]}`: the focus empty moves between points with the same ease. The pull happens between successive keys, so to hold and then pull, repeat a key: `t 0 → a`, `t 0.4 → a`, `t 0.6 → b`.
- `{"mode":"none"}`: depth of field off.
- `fstop` (or `fstop_keys`), `blades` and `ratio` are optional.

### Handheld

- **Shake (`handheld`):** two Noise layers per channel on `CR_<shot>_shake` (between aim and camera, so it moves in camera space).
  - Hand bob: period about 11 frames, 4 mm and 0.27° × intensity.
  - Fine jitter: period about 3.5 frames, 1.2 mm and 0.07° × intensity.
  - Roll runs at about 60% of pan and tilt.
- **Breathing:** body sway with a period of about 2 s, 14 mm and 0.4° × breathing.
- **Lens length:** the shift scales with focal length the way real handheld does. At 85 mm, handheld 0.4 already reads clearly; at 24 mm, 0.3–0.5 feels like a steady operator.

### Handheld walk profile (opt-in)

`"handheld": {"profile": "walk", "amount": 1.0}` replaces the noise shake with a baked operator-walking motion. Shots that keep a number for `handheld` are unchanged.

- **Footsteps:** a bob of about 1 cm, once per step at 1.8 Hz (`step_hz`), and a 0.3° roll that alternates left and right with each step.
  Both scale with the speed of the move's path: full at or above `walk_speed` (default 0.55 m/s), zero when standing.
  Walking intensity is smoothed over about 0.4 s, so steps fade in and out with the move's ease.
- **Body sway:** 0.17–0.57 Hz. Position moves ±2–3 cm and pan/tilt ±0.7°. When the operator stands still this drops to about 45%.
- **Aim lag:** the aim follows a spring (`aim_lag_hz` 0.9, `aim_damping` 0.62). Pans trail behind the keyed aim and overshoot slightly when they settle.
  Focus that follows the aim (the default focus mode) uses the lagged aim as well.
- **Reframes:** `corrections` (default 2) small reframes. Each drifts off by 0.6° and is quickly corrected back.
- **Frequency ceiling:** nothing is above about 1.9 Hz, so there is no jitter. Motion blur sees smooth curves.
- **Baking:** everything is baked per frame onto `CR_<shot>_shake` (location in metres, rotation in radians, in the camera's local axes).
  It is deterministic per shot index.
- **Setting it up:** use `move: "path"` with 4–6 keys at a walking pace (about 0.3–0.6 m/s) and `ease: "inout"`, so the operator starts and stops gently.
  Check the camera path against the scene before rendering: load the scene once, build a BVH of its meshes, and report the closest mesh and its frame for every frame of the move.

## Rig hierarchy (in the saved .blend)

```
CR_<shot>_base     (location baked one LINEAR key per frame)
 └ CR_<shot>_aim   (rotation: Track To an animated aim empty CR_<shot>_target)
    └ CR_<shot>_shake   (noise only)
       └ CR_<shot>_cam  (camera data: lens/sensor/DOF; lens animated)
CR_<shot>_target   (aim point, animated)
CR_<shot>_focus    (DOF focus object, animated or parented)
```

Moves are evaluated in Python and **baked one key per frame**, so every move type behaves the same and Cycles motion blur sees smooth subframes.

The real way to change a move is to edit shots.json and rerun. In a `--save`d file you can still:
- turn the shake empty's Noise modifiers up or down (Graph Editor → Modifiers),
- move the focus empty,
- change lens and f-stop keys on the camera data.

Each shot's rig lives in its own collection `camrig/CamRig_<shot>`. Rerunning a shot deletes and rebuilds that rig.

## Lens FX / grading (Blender 5.0)

- `lens_fx.distortion` and `lens_fx.dispersion` use the **Lens Distortion** compositor node. `lens_fx.glare` (`"fog"`, `"bloom"`, `"streaks"`) uses the **Glare** node.
- **Vignette, colour balance and grain are not done here.** The 5.0 mask and colour-balance nodes misbehave, so finish those in your own ffmpeg grade pass on the rendered frames.
- **Existing compositor:** if the scene already has one, it is kept unless the shot sets `lens_fx`. In that case camrig copies the scene's tree to `camrig_fx` and splices its nodes in just before the Group Output. (Wrapping the old tree in a group node renders **black** in 5.0, because Render Layers inside a nested group yields nothing.)

## Encoding

- ffmpeg comes from `$FFMPEG` (default `ffmpeg` on PATH). camrig encodes with `h264_nvenc` (CQ 18, yuv420p, faststart), which is fast and barely touches the GPU.
- If NVENC fails, it falls back to `h264_mf`.
- Frames are fed through an ffmpeg concat list, so no glob is needed and stepped previews work. 16-bit PNG frames encode fine.

## Helpers (python, inside Blender)

```python
import sys; sys.path.append("<repo>/camera")
import camrig
camrig.bounds("ticket_machine")      # -> (min Vector, max Vector, center Vector)
camrig.find("ramen_bowl")            # exact name or prefix match
```

`--list "pattern"` prints the matching objects with their bounds centre and size, then exits:

```bash
"$B" -b scene.blend --python camera/shoot.py -- --list bowl
```

## Measured (RTX 5070 Ti, Blender 5.0.1, on two of AnyScene's reference sets)

| Pass | Scene | Time |
|---|---|---|
| `--framing`, 4 shots → 12 Eevee stills at 640 px | either | 30–50 s, including the file load |
| `--preview`, 960×402 Eevee | ramen | ~0.25 s/frame |
| `--preview`, 960×402 Eevee | repair | ~0.35 s/frame |
| `--lenschart` | either | ~12 s |
| Final Cycles, 960×402, 32 spp, motion blur, glare + lens distortion | repair | ~10 s/frame |
| Final Cycles, 640×360, 16 spp | repair | ~3.3 s/frame |

Scale final times by pixels × samples before you pick a `--frames` chunk size.

## Robust vs flaky (Blender 5.0)

**Robust:**
- every move type, including dolly_zoom lens solving and Catmull-Rom paths
- Track To aim
- rack, track and point focus
- f-stop keys and blades/ratio
- Noise-modifier handheld
- per-frame stamps (a `frame_change_post` handler updates the note)
- Eevee previews
- resume via `use_overwrite=False`
- NVENC encode
- Glare and Lens Distortion spliced into the scene's compositor

**Avoid:**
- compositor mask, ellipse and colour-balance nodes (grade in ffmpeg)
- nesting the scene's compositor group (renders black)
- Track To flips when the aim is exactly vertical, so keep aim points off the camera's plumb line

**Eevee previews differ from Cycles:**
- Glass reads as dark.
- Light falloff is flatter.
- Previews are for framing, move and focus, not for look.

## Examples
- `camera/examples/ramen_shots.json` and `camera/examples/repair_shots.json`: 35 mm push-in with a foreground->subject
  rack, 85 mm static handheld at f/1.8, 24 mm orbit, and a dolly zoom, written for two of AnyScene's reference sets
  (the object names are from those scenes).
````

## File: README.md
size: 8961
sha: f4bec83b346af1c05f5bf6e3b65344220b1b18e2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/README.md

````text
# AnyScene

Give it reference images of a place (or a one-paragraph brief) and it builds a dressed, lit Blender scene: a real room
with every prop as its own model, practical lights, grime, haze, cinematic camera moves and graded renders.

The work is done by an AI agent (Claude, in Claude Code) following [`SKILL.md`](SKILL.md). No prop is modelled by hand:
each one is generated as an image, turned into 3D with two image-to-3D models on [fal](https://fal.ai), and the better
result is picked by comparing same-light renders.

![Five AnyScene scenes](docs/media/strip.jpg)

## Five places, one process

| | Scene | |
|---|---|---|
| ![](docs/media/repair.jpg) | **Electronics repair shop**, Tokyo, 1 AM, rain outside | [`scenes/tokyo-electronics-repair`](scenes/tokyo-electronics-repair) · 86 generated props |
| ![](docs/media/ramen.jpg) | **Ramen shop**, Tokyo, last orders, steam and rain | [`scenes/tokyo-ramen-shop`](scenes/tokyo-ramen-shop) · 74 generated props |
| ![](docs/media/hk.jpg) | **Dai pai dong**, Hong Kong, an open-air street kitchen just after rain | [`scenes/hk-dai-pai-dong`](scenes/hk-dai-pai-dong) · 78 generated props |
| ![](docs/media/mc.jpg) | **Mission control**, 1970s, a night shift during an orbital flight | [`scenes/mission-control-1970s`](scenes/mission-control-1970s) |
| ![](docs/media/bakery.jpg) | **Maison Roussel**, a Paris bakery. Built by the hosted endpoint from [one reference image](docs/media/bakery_reference.jpg), with no human input, in under two hours | (endpoint run) |

The first four were built by an agent working through `SKILL.md`, with a person checking its gates. The bakery was built
end to end by the same process running unattended on a fal GPU worker.

This repo is the process and the code. The finished scenes (.blend files, generated models, textures, renders) add up
to tens of gigabytes and are not in git. Each scene folder keeps what's needed to rebuild it: its prop list
(`assets.json`), model picks with reasons (`picks.json`), shots (`shots.json`), notes and build scripts.

## Quick start

You need:
- [Blender](https://www.blender.org/) 5.0 or newer. Set `BLENDER` if it isn't on your PATH or in the default install location.
- [Node](https://nodejs.org/) 20 or newer, then `npm install` in the repo root.
- A [fal API key](https://fal.ai/dashboard/keys) in `FAL_KEY`. Generation is billed to your fal account: roughly $1.65
  per prop (an image plus two 3D models), so about $150 for a 90-prop scene.
- ffmpeg with an H.264 encoder (`FFMPEG`, default `ffmpeg`). The example scenes were built on Windows with an NVIDIA GPU
  and use `h264_nvenc`; on other machines, swap in `libx264`.
- [uv](https://docs.astral.sh/uv/) for the Python helper scripts.
- [Claude Code](https://claude.com/claude-code).
- A GPU with 12–16 GB of memory for Cycles.

Then open the repo in Claude Code and ask for a scene:

> Use SKILL.md to build a new scene: a Lisbon tram depot at dawn, one tram half-stripped for repair.

Or start from your own references: put a few images (and, optionally, a floor plan) in `refs/<scene>/` and say so:

> Use SKILL.md to build a scene from the reference images in refs/lisbon-tram-depot/. Treat them as the approved concept.

Check the agent's work at each gate: concept, prop picks, clay layout, lit stills, shot previews. Expect most of a day
of agent time and 1–2 GPU-hours of final renders per scene.

## How the agent works

[`SKILL.md`](SKILL.md) is the whole process, step by step, with every gotcha the example scenes hit:

1. brief → scene spec (room size, zones, hero spots, real light sources);
2. concept images, or your references;
3. a prop manifest, then a reference image for every prop;
4. each prop through both Tripo H3.1 and Meshy 7.1, picked by looking at same-light renders;
5. a scripted room shell, dressing from big furniture down to small clutter, with collision and floating checks;
6. grime, de-branding, decals, practical lighting, haze, steam and rain;
7. cinematic and long handheld walkthrough shots, rendered in Cycles and graded;
8. optionally, a behind-the-scenes video.

Every step ends with a gate: a contact sheet the agent has to look at before moving on. Everything is a script, so the
.blend is a build output that can be regenerated.

[`builder/CRAFT.md`](builder/CRAFT.md) is the short version of what made the good scenes good: render it and look, name
the problem precisely, fix it in code, check the fix from a view that shows it, and get an independent critic.

## Layout

```
SKILL.md          the process; agents start here
builder/CRAFT.md  the review loop that separates good scenes from first drafts
generate/         fal client: images and image→3D (Tripo H3.1, Meshy 7.1), with a local spend log
pipeline/         Blender/ffmpeg discovery, a FIFO GPU queue, comparison renders, gallery pages, floating-prop check
camera/           camera rig and shot renderer: moves, rack focus, handheld walk, lens effects (synced from AnyShot)
breakdown/        behind-the-scenes videos, promo cuts and the launch supercut
scenes/<name>/    one folder per scene: assets.json, picks.json, shots.json, NOTES.md, brief.md, scripts/
farm/             a fal Serverless render farm for Cycles (app.py, synced from AnyShot), and a client that renders a scene's shots on it
blender_addon/    the fal Render Farm add-on for Blender
builder/          the same process packaged as a fal Serverless app (the hosted endpoint)
docs/             endpoint and API notes, README images
scripts/          sync_from_anyshot.py: refresh the files shared with AnyShot from a sibling ../anyshot checkout
```

## Hosted endpoint (optional)

If you'd rather not set up Blender, a GPU and the toolchain, the hosted endpoint runs the whole build on fal: send one
to four reference images (and an optional prompt), and get back the scene package (`scene.blend` with every prop as
its own object, a `scene.glb`, stills and panoramas; walkthroughs render on the farm). The bakery above was built this way, from a single image.

<!-- TODO(apek): link the public endpoint page / model id here once it's listed. -->

The endpoint's code is in [`builder/`](builder) if you want to deploy your own copy to your fal account
(`fal deploy builder/app.py::SceneBuilderApp --app-name anyscene-builder`). It needs `FAL_KEY` and `OPENROUTER_API_KEY` set
as secrets on the app, and the `endpoint/` folder alongside it (the builder imports its planner and schema).

## Shooting builds: AnyShot

Stills and camera moves of a finished build are made by [AnyShot](https://github.com/apekshik/anyshot), an AI
cinematographer that lives in its own repo and runs as its own fal app. Deploy it on the same fal account and set
`fal secrets set ANYSHOT_APP=<your-fal-username>/anyshot`: the builder's `/scene2image`, `/scene2video` and `/shots`
routes (and the optional `shots` order on `/ref2scene`) forward to it over the fal API and relay its live log, and
AnyShot reads the build straight from the account's `/data` storage by `build_id`. AnyShot also takes any uploaded
`.blend`, so you can call it directly.

The code both repos use (`camera/`, `builder/blender_gpu.py`, `farm/app.py`, `pipeline/env.sh`, `pipeline/gpu_run.sh`)
lives in AnyShot; the copies here carry a "synced from" header. Edit them there, then run
`python scripts/sync_from_anyshot.py` with AnyShot checked out next to this repo.

## Kits: AnyKit

For props rather than whole sets, use [AnyKit](https://github.com/apekshik/anykit): give it one to four style
reference images and a Claude agent builds a cohesive kit of production-ready props in that style, at real-world
scale (per-item GLB + LOD1, a `kit.blend` asset library, a lineup render), in about 25-40 minutes for about $25. It
uses the same generators, agent harness and container as the scene builder, lives in its own repo and runs as its own
fal app; deployed on the same account it shares this repo's `/data/anyscene/` storage and OptiX cache. AnyKit keeps
synced copies of the code it shares with this repo (`builder/gallery.py`, `builder/blender_gpu.py`,
`generate/fal.mjs`, `pipeline/env.sh`, `pipeline/gpu_run.sh`), so edit those here first. The web UI's kit gallery
calls it over the fal API (`NEXT_PUBLIC_ANYKIT_APP`).

## Render farm add-on

[`blender_addon/`](blender_addon) is a Blender add-on that renders the open scene on fal GPUs instead of your own:
direct a scene in Blender, press **Render animation on fal**, and the frames come back into the scene's output path
with the same names a local render would give them. See [`blender_addon/README.md`](blender_addon/README.md) for
install and settings. The farm itself is [`farm/app.py`](farm/app.py) (its home is AnyShot's `farm/app.py`); you can deploy your own and point the add-on's
**Farm app** preference at it.

## Licence

Code is MIT, see [LICENSE](LICENSE). Generated assets are not in this repo; where they're published, they come with
their own licence.
````

## File: unreal_fal/README.md
size: 5690
sha: 60c4e75f1004e3c745bef35f51c0fd8dae9c365e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/README.md

````text
# unreal_fal: the Blender -> Unreal export stage on fal Serverless

`app.py` is the fal app **`apek/blend2unreal`** (private). It runs `export_blend.py` headless on RTX 5090 workers. The
slow texture bake is sharded across workers, and finished assets are cached by content hash on `/data`.

```bash
cd unreal_fal
fal deploy app.py::Blend2Unreal --app-name blend2unreal --auth private --reset-scale
python client.py upload hk_scene.zip                 # .blend or .zip (a .blend + grade.sh); pack images/fonts first
python client.py export <scene_url> --options '{"frame": 60, "dof": {"cam_street": [9.5, 2.8]}}' --out result.json
```

## API

`POST /export`
```json
{"scene_url": "https://.../hk_scene.zip",
 "options": {"frame": 60, "density": 1024, "max_res": 4096, "dof": {"cam_street": [9.5, 2.8]},
             "grade_sh": "grade.sh", "blend": null, "device": "gpu", "shards": 0, "procs": 0},
 "use_cache": true, "fresh": false, "inline_scene_json": true}
```
Response:
```json
{"job_id": "x_...", "zip_url": "...zip", "scene_json_url": "...scene.json", "scene_json": {...},
 "report": {"counts": {...}, "cache": {...}, "not_baked": [], "not_converted": [...], "warnings": [...],
            "timings": {...}, "worker_seconds": {...}, "shards": [...]},
 "minutes": 5.4}
```
- `device`, `shards` and `procs` don't change the result, so they are left out of the retry fingerprint.
- The app scales to zero (`min_concurrency = 0`), so a cold `/export` first waits ~1-2 min for a worker to boot. Set it to 1 to keep a warm worker ($2.50/h).
- Repeating an identical request returns the finished result, or attaches to a live attempt (heartbeat), or resumes
  a dead one and re-attaches to its shard requests. `fresh: true` exports again.
- `use_cache: false` re-bakes everything into a job-private cache, deleted afterwards. The shared cache is never
  read or changed.

`POST /shard` is internal: `/export` calls it on other workers. Benches call it with `use_cache: false`.

## Pipeline

1. **Plan** (`--plan-out`, ~25 s for HK): names every unique mesh, hashes it and estimates its bake cost.
   - The hash covers: evaluated mesh, material node trees (recursively, with packed image bytes), world-space
     scale, bake settings, the Blender version and the exporter file itself.
   - Materials that read their object (Object Info, object coordinates, object attributes) also hash that object.
2. **Shards**:
   - Cache misses are dealt longest-first into N shards: ~2 min of estimated work per Blender process, at most 32.
   - Shard 0 runs on the `/export` worker; the others are `/shard` requests, submitted and polled (not
     `subscribe()`).
   - Each worker runs 2 Blender processes x 3 threads with OptiX. Each process is resumed up to 6 times after a
     Blender bake crash.
   - Every finished asset is written to `/data/blend2unreal/cache/<h[:2]>/<h>/` (written to a temp dir, then
     renamed into place).
   - Assets still missing after round 1 are re-dealt in a second round.
3. **Merge** (`--plan --cache --link-cache --no-bake`): pulls every asset from the cache by symlink, then writes
   volumes, lights, cameras, world, grade LUT and `scene.json`.
4. **Package**: copies off `/data` with 16 parallel readers, zips (PNG/EXR stored, the rest deflated) and uploads
   to fal storage.

## Machine notes (measured)

- An RTX 5090 worker is **6 cores / 60 GB** (`os.cpu_count()` says 512: the host's). Probed:
  - L: 4 cores / 15 GB
  - XL: 8 / 30 GB
  - RTX PRO 6000: 6
  - H100: 12 / 112 GB
- Per-asset time is mostly CPU: unwrap, Cycles sync, PNG encode.
- 36-asset HK bench on one worker:

  | Setup | Wall time |
  |---|---|
  | GPU, 2 procs x 3 threads | 122 s |
  | GPU, 1 proc x 6 threads | 196 s |
  | CPU, 2 procs | 785 s (road alone 354 s) |

  **GPU (OptiX) is ~6x faster**: it is the default.
- OptiX compiles its "shader raytrace" kernels (AO and Bevel nodes) on the first such bake: ~230 s per process on a
  fresh worker. The warm-up in `setup()` now bakes an AO+Bevel material, and the kernel cache is shared on `/data`
  with the render farm (`/data/anyscene-farm/optix/<gpu>`).

## Changes to merge back into `unreal/`

`export_blend.py` (copied from `unreal/` at 21:15 on Nov 1, after its last edit at 20:25):
1. New flags: `--plan-out FILE`, `--plan FILE`, `--keys FILE`, `--cache DIR`, `--link-cache` (see the docstring).
   Without them the exporter behaves as before, apart from items 2-4.
2. **Asset names are computed over the whole sorted key list before any filtering by `--keys`.**
   - Without `--only`/`--limit` the names are the same as before.
   - With them, the collision suffix `_NNN` now uses the index in the full list. Before, it was the index in the
     filtered list.
3. `scene.json` assets gain `"hash"` when `--cache` is used. Shard mode writes `out/shard_<keys file>`, not
   `scene.json`.
4. With `--gpu`, the bake scene selects OptiX devices itself (a factory-startup Blender would otherwise bake on the
   CPU). Locally, `gpu_prefs.py` via `EXPORT_PRE` keeps working.

`build_level.py`, `render_shots.py`, `side_by_side.py`, `agx_view.py`, `make_copy.py`: unchanged copies.

New: `app.py`, `client.py`, this README.

## Known limits / follow-ups

- The cache on `/data` has no eviction (HK is ~4.6 GB). Job-private caches are deleted after the job.
- `smart_project` UV layouts of converted text (fascia_text_*, neon_*) differ between Linux and Windows Blender.
  Each export's textures match its own GLB UVs, but the PNGs are not byte-comparable across platforms.
- `scene.json` paths use `/` (relpaths on Linux). The local Windows export used `\`. `build_level.py` joins them
  with `os.path.join`, which works on both.
````

## File: unreal_fal_ue/README.md
size: 5614
sha: ecd9f8cf65dbc69f7280159ec71a45211fe6036c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/README.md

````text
# unreal_fal_ue: UE 5.8 headless on fal Serverless (`apek/unreal-build`)

Status (2026-11-02): **working end to end.** HK builds on fal and renders with MRQ. Against the local Windows MRQ
frames the result is near-identical: PSNR 47–50 dB and a mean difference of 0.25–0.36 out of 255.

## Endpoints (private app `apek/unreal-build`, GPU-RTX5090)
| route | in | out |
|---|---|---|
| `/smoke` | `{"render": true}` | engine version, GPU, Vulkan, and a lit-cube PNG rendered offscreen |
| `/build` | `{"export_url", "scene": "HK", "level", "stages", "nanite_tris", "exposure_offset"}` | `content_url` (zip of `Content/AnyScene/<scene>`, Config, uproject), `log_url`, `report` |
| `/render` | `{"content_url", "scene", "cameras": [...], "config": "MRQ_Still", "resolution": [1920,804], "frames": 1, "temporal_samples": 8, "warmup_frames": 64}` | per camera: PNG/EXR URLs, an MP4 when frames > 1, logs |

```
# PowerShell 5.1 strips quotes from arguments, so pass the args as @file.json. FAL_KEY comes from FAL_SERVERLESS_KEY.
python -I tools/call.py apek/unreal-build build  @build_args.json  build.json
python -I tools/call.py apek/unreal-build render @render_args.json render.json
python -I tools/fetch.py apek/unreal-build <request_id> out.json --wait   # re-attach to a request after a local crash
```

## Measured on HK (2026-11-02)
- `/build`: 1514 s end to end, broken down as:
  - fetch and unzip of the 4.7 GB export: 163 s
  - UE commandlet: 1054 s (textures 263 s, meshes 629 s, materials 135 s)
  - zip: 230 s
  - upload: 47 s

  The content zip is 4.15 GB.
- `/render`, three cameras at 1920x804, 8 temporal samples and 64 warm-up frames: 1352 s, broken down as:
  - content fetch: 96 s
  - MRQ config: 17 s
  - `cam_street`: 1103 s, the first render, which compiles shaders into a cold DDC
  - `cam_table`: 64 s
  - `cam_wok`: 61 s
- Cold start, measured from zero runners to a new runner answering `/smoke {"render": false}`: 10.8 s. That node
  already had the image cached. A pull onto a node without the image couldn't be forced, so it is not measured;
  expect minutes for 24 GB.
- The shared DDC on `/data` persists across runners, so later renders on any runner skip most shader compiles.
- Cost: an RTX 5090 is $0.000694/s, about $2.50/h. A warm runner (`min_concurrency=1`) costs about $60 a day.
  The app is now scaled to `min_concurrency=0` and `keep_alive=300`. To warm it again:
  `fal apps scale unreal-build --min-concurrency 1 --keep-alive 3600`.

## Container
- The base image is `ghcr.io/epicgames/unreal-engine:dev-slim-5.8.4`: 24 GB compressed, with the engine at
  `/home/ue4/UnrealEngine` and user `ue4`.
  - Pulling it needs a GitHub account linked to Epic and in the EpicGames org, plus a classic PAT with `read:packages`.
    The PAT goes in the user env vars `GHCR_USER`/`GHCR_TOKEN` and is passed as `ContainerImage(registries=...)`;
    the Depot builder is the only thing that uses it.
- On top of the base image:
  - Python 3.13 via uv (it must match the deploying Python);
  - ffmpeg, the Vulkan loader and tools, and the NVIDIA ICD JSON;
  - `NVIDIA_DRIVER_CAPABILITIES=all`.
- The first image build took 644 s. Redeploys with an unchanged image take about 20 s.

```
$env:UE_SOURCE = "ghcr:dev-slim-5.8.4"; $env:GHCR_USER = "apekshik"   # GHCR_TOKEN from the user env var
uv run --python 3.13 --with fal==1.84.0 --with pydantic --with fal-client fal deploy app.py::UnrealBuild --app-name unreal-build --auth private --reset-scale
```
`UE_SOURCE=url:<linux engine zip>` builds from an Epic Linux binary zip instead. `none` builds a probe image with no engine.

## Linux specifics, now verified
- UnrealEditor refuses to run as root, so every engine process runs as `ue4` via `setpriv`.
- Rendering uses `-vulkan -RenderOffscreen` with `SDL_VIDEODRIVER=offscreen`; MRQ runs in `-game` mode with `-LevelSequence`.
- Engine processes run in their own process group:
  - Shutdown is detected from log markers, and the group is killed EXIT_GRACE seconds later; `pkill -u ue4` follows.
    ShaderCompileWorker children otherwise keep stdout open after the engine has exited.
  - Commandlets never log `LogExit`: their last line is `Execution of commandlet took`.
- `skip_retry_conditions=["timeout"]`. Without it, fal re-ran a timed-out build on a new runner every 2 h for 14 h.
- Exports written on Windows hold backslash paths in scene.json. `build_level.py` converts them on Linux; see `_posix_paths`.

## Files (all new; nothing in `unreal/` changed)
- `app.py`: the fal app.
- `mrq_config.py`: makes a per-request MRQ config. It sets the output dir, resolution, frame range, samples and
  warm-up, and `use_camera_cut_for_warm_up=False`.
- `smoke_shot.py`: an offscreen SceneCapture render of a lit cube.
- `template/`: `AnySceneUE.uproject` and Config. `make_project()` swaps the startup map and adds Linux `SF_VULKAN_SM6`.
- `tools/upload_export.py`, `tools/call.py`, `tools/fetch.py`: upload, submit-and-poll, and re-attach.
- `build_level.py`: `unreal/build_level.py` as of 2026-11-01 20:25, plus `_posix_paths` (merge that upstream).
  `app.py` ships whichever `build_level.py` is in this folder.
- `render_mrq.ps1`, `render_shots.py`, `TOGGLE.md`: unchanged copies.

## fal facts learned
- `keep_alive` is capped at 3600 s without a support request.
- Scaling settings persist across deploys; pass `--reset-scale` to apply the values in code.
- A timeout makes the queue retry on a fresh runner unless `skip_retry_conditions` includes `"timeout"`.
- `fal runners list --state terminated --since 6h` and `fal runners logs <id>` recover a dead runner's full log.
````

## File: web/README.md
size: 11222
sha: db9c4bad0d880541712f3d9cfc0d6be9600759db
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/README.md

````text
# AnyScene web

The showcase UI for AnyScene. The default product is the agent builder (`builder/`, e.g. the public `apek/anyscene`): drop a reference
image and one request builds the whole scene on a fal GPU worker (up to fal's 2 h cap), with a Claude agent looping
against an independent critic. The UI shows the agent's production log, its milestones as a schedule, the newest
render live, the critic's score sheet round by round, and the result (stills, 360, package, cost). The older
plan + build pipeline (`endpoint/`) is still there at `?mode=pipeline`. Styled as a film call sheet.

Next.js (App Router, TypeScript), three.js, `@fal-ai/client` in the browser through `@fal-ai/server-proxy` on the
server. The fal key never reaches the browser.

## Run

```
npm install
cp .env.example .env.local   # then fill in FAL_KEY and the app ids
npm run env:local     # (Windows) writes FAL_KEY into .env.local from the user env var FAL_SERVERLESS_KEY (never printed)
npm run dev           # http://localhost:3210
```

The fal apps come from `NEXT_PUBLIC_*` variables in `.env.local`, as `<your-fal-username>/<app>` (see `.env.example`):
`NEXT_PUBLIC_ANYSCENE_APP` (the builder), `NEXT_PUBLIC_ANYKIT_APP` (AnyKit, for the kit gallery), and optionally
`NEXT_PUBLIC_ANYSCENE_PIPELINE_APP` (the older pipeline; defaults to the builder's id) and
`NEXT_PUBLIC_ANYSCENE_TEST_APP` (a second builder the gallery shows with `?gallery_app=<id>`). There are no defaults:
a live call to an unset app fails with a message naming the variable. `DEV_ORIGINS` (comma-separated) adds LAN hosts
allowed to open the dev server.

`npm run dev` and `npm run build` first copy `fixtures/` into `public/replay/` (`npm run fixtures`).

## Builder (default)

- Live: **Build the scene** uploads the reference to fal storage and calls `<NEXT_PUBLIC_ANYSCENE_APP>/ref2scene` with
  `{reference_image_urls, prompt, effort, scene: "scene"}`. Stage events come from the queue logs (prefix
  `ANYSCENE_STAGE `, polled every 2 s, deduped by message).
- Schedule: the milestones the agent reports (plan, props, layout, dressing, screens, materials, lighting, atmosphere,
  cameras, finals, plus any it invents), with ROLLING on the current one, WRAPPED and a duration once it moves on, and
  "take 2" when it returns to one after a critique. Then the critic's state and the package.
- Production log (bottom): every `log` event (tool label and what it did), the agent's `thinking` notes, milestones
  with a thumbnail, critic lines; filter by notes, tools or milestones. The caption under the frame is the agent's
  latest note.
- Frame: Live (newest `preview_url`, with a strip of recent frames you can hold), Compare (the plate against the
  critic's reference-angle still, then the first final), Contact sheet (every reported frame), Stills and 360 after
  the wrap.
- Critic's report (right): the eight scores per round side by side with the change from the round before, lines under
  7 marked, the verdict stamp, the summary and the ranked fixes; earlier rounds' fixes fold away.
- Result: stills, package, scene.blend and scene.glb, agent cost, minutes, critic rounds, anything `missing`.

### Builder replay

`/?replay=builder` plays `fixtures/builder/` (`events.jsonl` timed by each event's own `t`, `build.json` as the
response); speeds 1x to 64x in the toolbar, `&auto=1` starts it. That fixture is **synthetic**
(`npm run fixture:builder`): it follows the real schema, reuses the pipeline run's images, and its package link is
the earlier pipeline package. To drop in a real run:

```
npm run import:builder -- <run dir>                                               # -> fixtures/builder/
npm run import:builder -- <run dir> fal_mc_1                                            # or keep both: ?replay=fal_mc_1
```

It copies `events.jsonl`, `build.json` and any `still_*.png` (served locally in place of the remote stills), plus a
reference image. A run without `build.json` yet replays up to its last event and stops there.

## Password, who's building, and limits

The proxy checks a shared password, verified on the server: set `ANYSCENE_ACCESS_KEY` in the server environment and every proxied request must
carry it as `x-anyscene-key`. With the variable unset the proxy is open in `next dev` and **closed** in production,
so a fresh deployment can't start builds on the account. `ANYSCENE_ADMIN_KEY`, given in place of the password, also
skips the limits below.

The page asks once for the password and an email or username (**Sign in** in the toolbar; kept in that browser's
localStorage) and sends them to our own proxy only (`x-anyscene-key`, `x-anyscene-user`, `x-anyscene-name`). The proxy
tags each `/ref2scene` build with `owner` (the email or username) (stored by `builder/app.py`, listed by `/builds`, left out of
the retry fingerprint), so the gallery's **My builds** shows your own and **Everyone** shows all. A build's page is
shareable as `/?open=<build id>` (**Copy link**). It is self-declared behind the shared password: a label, not
authentication (see Google sign-in below).

Limits, all server only:

| variable | default | |
|---|---|---|
| `ANYSCENE_BUILDS_PER_DAY` | 3 | builds per email per UTC day; counted in a private Vercel Blob store when `BLOB_READ_WRITE_TOKEN` is set (else in memory) |
| `ANYSCENE_JOBS_PER_HOUR` | 6 | new jobs (builds and shots) per IP per hour, in memory per instance: a backstop |
| `ANYSCENE_OWNER_DOMAIN` | none | only emails at this domain may build, e.g. `fal.ai` (usernames are always allowed) |

The build button notes the cost (about $60-100 a build) and what's left today, and asks before starting.
`app/api/me` answers the page's "is my key right, who am I, what's left" check.

### Google sign-in (later)

To replace the self-declared name with real accounts restricted to one Google Workspace domain:

1. Google Cloud console, the owner's project: **APIs & Services > OAuth consent screen**, user type **Internal** (only
   the Workspace's accounts can sign in). Then **Credentials > Create credentials > OAuth client ID**, type **Web
   application**, authorized redirect URI `https://studio.anyscene.org/api/auth/callback/google` (and
   `http://localhost:3210/api/auth/callback/google` for dev).
2. `npm install next-auth@5` and add `auth.ts` with the Google provider, `authorization: { params: { hd: "fal.ai" } }`,
   and a `signIn` callback that returns `profile.email_verified && profile.email.endsWith("@fal.ai")` (`hd` alone is
   only a hint); export `handlers` from `app/api/auth/[...nextauth]/route.ts`.
3. Vercel env: `AUTH_SECRET` (`npx auth secret`), `AUTH_GOOGLE_ID`, `AUTH_GOOGLE_SECRET`, `AUTH_TRUST_HOST=true`.
4. In `lib/guard.ts`, take the owner from `await auth()` (session email and name) instead of the `x-anyscene-*`
   headers, and treat a session as the access key (keep `ANYSCENE_ADMIN_KEY` for the owner). In the page, replace the
   sign-in card with `signIn("google")`.

## Replay mode (pipeline)

`/?replay=demo` plays the recorded pipeline run in `fixtures/` with its original timing. Click **Plan the scene**, then
**Approve and build**.

| param | |
|---|---|
| `replay=<name>` | `demo` is `fixtures/` itself; any subfolder `fixtures/<name>/` is another recording |
| `speed=<n>` | 1 (real time) to 64; also switchable in the toolbar (1x to 16x) |
| `auto=1` | plans on load and approves the build 3.5 s after the plan lands, for hands-off screen recordings |

A recording is: `plan_events.jsonl` and `build_events.jsonl` (one `{"t": seconds, ...stage event}` per line, as written
by `endpoint/client.py --events`), `plan.json`, `build.json` (the BuildResponse), `reference.png`, `floor_plan.png`,
`blockout_reference.png`, `blockout_overview.png`, `comparison.png` and `still_*.png`. Recorded `preview_url`s that
match a local file (floor plan, comparison, stills in `build.json` order) are served locally; the rest (layout and
dressing previews, prop references, GLBs) still load from fal's CDN. Without `build_events.jsonl` the replay
synthesizes a build from `plan.json`. The last two lines of `fixtures/plan_events.jsonl` are marked `"synthetic"`:
the recorded plan run lost its final events when the client crashed, so `blockout done` and `done` were added.

## Live mode

Without `?replay`, **Plan the scene** uploads the reference to fal storage and calls `<pipeline app>/plan` through
`/api/fal/proxy`; **Approve and build** calls `<pipeline app>/build` with the plan id and tier. Stage events are read
from the queue logs (lines prefixed `ANYSCENE_STAGE `, deduped by message). The proxy only forwards to
the configured `NEXT_PUBLIC_*_APP` apps (`<app>/**`) and fal storage uploads, so a deployment's key can't be used for
other endpoints. On Vercel, set `FAL_KEY`, `ANYSCENE_ACCESS_KEY` and the `NEXT_PUBLIC_*_APP` ids in the project
environment.

## 360 and scene lighting (ahead of the endpoint)

The UI already reads these optional fields, from events or the BuildResponse:

| field | where | |
|---|---|---|
| `panorama_url` (+ `viewpoint`) | `rendering` event, one per viewpoint | equirectangular Cycles render, 2:1 |
| `panorama_urls` | BuildResponse | the same, first = reference camera |
| `scene_glb_url` | `packaging` event / BuildResponse | decimated scene glTF with KHR_lights_punctual |
| `environment_url` | any event / BuildResponse | equirect .hdr or PNG of the scene's light for the prop viewer (else the first panorama) |

Until real ones exist, `scripts/make-placeholders.mjs` builds `fixtures/panorama_ref.png`, `panorama_mid.png`
(a ray-cast grey room from `plan.json`) and `fixtures/scene.glb` (the plan as boxes with its lights), and replay
injects them where the endpoint will emit them, labelled "placeholder".

## Screens

- Left: reference plate, direction (prompt, the ten dials, planning effort, build tier), the schedule.
- Centre: the camera-report frame with Floor plan (drawing, or the prop map that fills in as meshes land), Grey-box,
  Live (newest `preview_url`), Compare (slider between the reference and the matching render), 3D (the selected
  prop's GLB at the plan's real size, with dashed bounds and a ground shadow, lit by the scene's environment map once
  there is one, studio light until then), 360 (drag-to-look panoramas per viewpoint, plus the scene glTF as a
  free-orbit set model lit by the reference-camera panorama; hidden unless the build provides them), and Dailies
  after the wrap (stills, timings, package). **Follow** moves the frame to whatever just arrived; picking a
  view turns it off.
- Bottom: the prop manifest, one card per `prop.id`: IN SHOP while meshing, TRIPO or MESHY with a turntable once the
  mesh lands, FAILED, or STAND-IN if it never arrives. Click a card for the 3D view.
- Right: the breakdown (room, setting, counts, lights, palette, dials), notes for a revision, Approve and build.

Prop GLBs are 10-60 MB, so each card's turntable is rendered once into a sprite strip on a shared offscreen renderer
and the model is freed; only the 3D view keeps a live model.

`npm run screenshots` (pipeline) and `npm run screenshots:builder` (builder), with the dev server running, capture the
main states into `screenshots/` with the installed Edge or Chrome.
````

## File: scripts/sync_from_anyshot.py
size: 1931
sha: fadfc47a37323dcf5aad02ac76595f0b7a675f48
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scripts/sync_from_anyshot.py

```text
"""Copy the code AnyScene shares with AnyShot from a sibling AnyShot checkout (github.com/apekshik/anyshot).

    python scripts/sync_from_anyshot.py [path/to/anyshot]      (default: ../anyshot next to this repo)

AnyShot is the home of these files; edit them there, then run this. Each copy gets a one-line header naming its source.
"""

import os
import sys

REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# anyscene path: anyshot path
FILES = {
    "builder/blender_gpu.py": "agent/blender_gpu.py",
    "camera/camrig.py": "camera/camrig.py",
    "camera/shoot.py": "camera/shoot.py",
    "camera/README.md": "camera/README.md",
    "farm/app.py": "farm/app.py",
    "pipeline/env.sh": "pipeline/env.sh",
    "pipeline/gpu_run.sh": "pipeline/gpu_run.sh",
}

def header(src_rel):
    text = f"synced from github.com/apekshik/anyshot {src_rel}"
    return f"<!-- {text} -->" if src_rel.endswith(".md") else f"# {text}"

def main():
    src_root = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else os.path.join(REPO, "..", "anyshot"))
    if not os.path.exists(os.path.join(src_root, "agent", "director.py")):
        sys.exit(f"not an AnyShot checkout: {src_root}")
    for dst_rel, src_rel in FILES.items():
        lines = open(os.path.join(src_root, src_rel), encoding="utf-8").read().splitlines(keepends=True)
        at = 1 if lines and lines[0].startswith("#!") else 0  # keep a shebang first
        lines.insert(at, header(src_rel) + "\n")
        dst = os.path.join(REPO, dst_rel)
        os.makedirs(os.path.dirname(dst), exist_ok=True)
        old = open(dst, encoding="utf-8").read() if os.path.exists(dst) else None
        new = "".join(lines)
        if new != old:
            with open(dst, "w", encoding="utf-8", newline="\n") as f:
                f.write(new)
        print(f"{'updated' if new != old else 'same   '} {dst_rel}  <-  {src_rel}")

if __name__ == "__main__":
    main()
```

## File: .gitattributes
size: 19
sha: 6313b56c57848efce05faa7aa7e901ccfc2886ea
upstream: https://github.com/apekshik/anyscene/blob/HEAD/.gitattributes

```text
* text=auto eol=lf
```

## File: .gitignore
size: 1191
sha: f7ac1973425c6d4ca9061dc8d08715eda4237f09
upstream: https://github.com/apekshik/anyscene/blob/HEAD/.gitignore

```text
# Build outputs and generated assets: large, downloaded separately
*.blend
*.blend1
*.glb
*.vdb
*.exr
*.mp4
*.png
*.jpg
assets/
refs/
out/
cache/
scenes/*/props/
scenes/*/props_prebrand/
scenes/*/compare/
scenes/*/debrand/
scenes/*/out/
scenes/*/cache/
breakdown/*/
!breakdown/*.py
!breakdown/*.md
# other heavy formats that should never be committed
*.mov
*.webm
*.fbx
*.obj
*.usd
*.usdz
*.hdr
*.blend@
# small README images are the exception to *.png / *.jpg above
!docs/media/
!docs/media/*.jpg
!docs/media/*.png
!docs/media/*.gif

# Local state
generate/spend.jsonl
**/spend.jsonl
logs/
*.log
.gpu.queue/
.gpu.*_done
__pycache__/
node_modules/
.env*
!.env.example
pipeline/env.local.sh
*.pem
*.key
.secrets*
credentials*.json
.venv/

# Blender writes this into the working directory
waveletNoiseTile.bin

# Client output folders (responses, downloaded stills/videos, event logs)
anyshot_out/
builder_out/
# Generation records (refs/**/*.json) hold local output paths; refs/ above already excludes them, this is explicit
refs/**/*.json
*.tsbuildinfo

# Unreal build logs
*.out
unreal_fx/work/
# sample reference plates for the Studio picker
!web/public/samples/
!web/public/samples/*.jpg
```

## File: blender_addon/fal_render_farm-1.0.0.zip
size: 16383
sha: bd0fa4ba18f190a30569f2c05e6806083c9d17bb
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/fal_render_farm-1.0.0.zip

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/fal_render_farm-1.0.0.zip

## File: blender_addon/fal_render_farm/__init__.py
size: 14311
sha: bb72ed2b6643856e7d61d6e4e86ab7ac7f010a40
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/fal_render_farm/__init__.py

```text
"""fal Render Farm: render the open scene on a fal Serverless Blender farm (farm/app.py, deployed on your own fal account) instead of the local GPU.

Properties > Render > fal Render Farm. The open file is copied (never re-saved), packed in a separate Blender, zipped
with a GPU script, uploaded to fal storage and rendered in chunks on up to N GPUs. Frames come back into the scene's
own output path with the names a local render would give them. Talks to fal over plain HTTPS (urllib) only.
"""

bl_info = {
    "name": "fal Render Farm",
    "author": "AnyScene contributors",
    "version": (1, 0, 0),
    "blender": (4, 2, 0),
    "location": "Properties > Render > fal Render Farm",
    "description": "Render the open scene on a fal Serverless GPU render farm",
    "category": "Render",
}

import os
import time

import bpy
from bpy.props import BoolProperty, IntProperty, StringProperty

from . import fal_api, job as farm_job

PKG = __package__

def prefs():
    return bpy.context.preferences.addons[PKG].preferences

class FALRF_Preferences(bpy.types.AddonPreferences):
    bl_idname = PKG

    fal_key: StringProperty(
        name="fal key", subtype="PASSWORD", default="",
        description="fal API key of the account that owns the farm app (key_id:key_secret). Stored in Blender's "
                    "preferences; never printed or logged")
    app_id: StringProperty(
        name="Farm app", default="",
        description="fal app id of your render farm, <your-fal-username>/blender-farm-2 (farm/app.py deployed on your "
                    "account). An app deployed as blender-farm (the older build) returns PNG frames only; "
                    "blender-farm-2 also returns EXR, JPEG, TIFF and other image formats")
    chunk_size: IntProperty(name="Frames per chunk", default=24, min=1, max=1000,
                            description="Frames rendered by one farm request (one GPU)")
    concurrency: IntProperty(name="Concurrent chunks", default=100, min=1, max=200,
                             description="Requests in flight at once (the farm caps at its own max workers)")
    timeout_s: IntProperty(name="Chunk timeout (s)", default=3000, min=60, max=3500,
                           description="The farm kills Blender after this long on one chunk")
    encode_mp4: BoolProperty(name="Encode MP4 when done", default=True,
                             description="After an animation finishes, encode the frames to an H.264 MP4 next to "
                                         "them if ffmpeg is found (PNG/JPEG/TIFF/... frames only)")
    ffmpeg_path: StringProperty(name="ffmpeg", subtype="FILE_PATH", default="",
                                description="Path to ffmpeg; empty = look it up on PATH")

    def draw(self, context):
        col = self.layout.column()
        col.prop(self, "fal_key")
        col.prop(self, "app_id")
        row = col.row()
        row.prop(self, "chunk_size")
        row.prop(self, "concurrency")
        col.prop(self, "timeout_s")
        row = col.row()
        row.prop(self, "encode_mp4")
        row.prop(self, "ffmpeg_path", text="")
        col.operator(FALRF_OT_check_key.bl_idname, icon="KEY_HLT")

# -- operators --------------------------------------------------------------------------------------------------

def _busy():
    j = farm_job.CURRENT
    return j is not None and j.running

class FALRF_OT_render(bpy.types.Operator):
    """Render on the fal render farm instead of the local GPU"""

    bl_idname = "fal_render_farm.render"
    bl_label = "Render on fal"
    bl_options = {"REGISTER"}

    mode: bpy.props.EnumProperty(items=[("ANIMATION", "Animation", "The scene's frame range"),
                                        ("FRAME", "Frame", "The current frame")], default="ANIMATION")

    @classmethod
    def poll(cls, context):
        if _busy():
            cls.poll_message_set("A farm render is already running")
            return False
        if context.scene is None:
            return False
        return True

    @classmethod
    def description(cls, context, props):
        if props.mode == "FRAME":
            return "Render the current frame on the fal render farm; it is saved to the output path"
        return "Render the scene's frame range on the fal render farm, into the output path"

    def execute(self, context):
        try:
            p = farm_job.plan(context, self.mode, prefs())
            farm_job.save_copy(p)
        except farm_job.PlanError as e:
            self.report({"ERROR"}, str(e))
            return {"CANCELLED"}
        farm_job.CURRENT = farm_job.Job(p).start()
        _start_ui_timer()
        self.report({"INFO"}, f"fal render farm: {len(p.frames)} frame(s) of '{p.scene_name}' on {p.app}")
        return {"FINISHED"}

class FALRF_OT_cancel(bpy.types.Operator):
    """Cancel the running farm render (in-flight chunks are cancelled on fal; finished frames stay on disk)"""

    bl_idname = "fal_render_farm.cancel"
    bl_label = "Cancel"

    @classmethod
    def poll(cls, context):
        return _busy()

    def execute(self, context):
        farm_job.CURRENT.cancel()
        return {"FINISHED"}

class FALRF_OT_retry(bpy.types.Operator):
    """Re-submit the chunks that failed, reusing the uploaded bundle"""

    bl_idname = "fal_render_farm.retry"
    bl_label = "Retry failed chunks"

    @classmethod
    def poll(cls, context):
        j = farm_job.CURRENT
        return j is not None and not j.running and j.bundle_url and any(
            c.status in ("failed", "cancelled") for c in j.chunks)

    def execute(self, context):
        if farm_job.CURRENT.retry_failed():
            _start_ui_timer()
        return {"FINISHED"}

class FALRF_OT_check_key(bpy.types.Operator):
    """Check that fal accepts the key (a status read on the farm app; nothing is rendered)"""

    bl_idname = "fal_render_farm.check_key"
    bl_label = "Check key"

    def execute(self, context):
        pr = prefs()
        if not pr.fal_key.strip():
            self.report({"ERROR"}, "No key set")
            return {"CANCELLED"}
        if not pr.app_id.strip().strip("/"):
            self.report({"ERROR"}, farm_job.NO_APP_MSG)
            return {"CANCELLED"}
        ok, msg = fal_api.check_key(pr.fal_key.strip(), pr.app_id)
        self.report({"INFO"} if ok else {"ERROR"}, msg)
        return {"FINISHED"} if ok else {"CANCELLED"}

class FALRF_OT_open_output(bpy.types.Operator):
    """Open the folder the frames are written to"""

    bl_idname = "fal_render_farm.open_output"
    bl_label = "Open output folder"

    def execute(self, context):
        path = bpy.path.abspath(context.scene.render.frame_path(frame=context.scene.frame_start))
        folder = os.path.dirname(os.path.abspath(path))
        os.makedirs(folder, exist_ok=True)
        bpy.ops.wm.path_open(filepath=folder)
        return {"FINISHED"}

# -- panel ------------------------------------------------------------------------------------------------------

def _progress_text(s):
    c = s["counts"]
    done = c.get("done", 0)
    parts = [f"{done}/{s['n_chunks']} chunks", f"{s['frames_done']}/{s['frames_total']} frames",
             farm_job.fmt_s(s["elapsed"])]
    if s["gpu_s"]:
        parts.append(f"{s['gpu_s']:.0f} GPU-s (~${s['gpu_s'] / 3600 * farm_job.GPU_RATE_PER_HOUR:.2f})")
    return " · ".join(parts)

class FALRF_PT_panel(bpy.types.Panel):
    bl_label = "fal Render Farm"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "render"

    def draw_header(self, context):
        self.layout.label(icon="WORLD")

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        pr = prefs()

        frames = farm_job.frame_list(scene, "ANIMATION")
        est = farm_job.estimate(scene, len(frames), pr.chunk_size, pr.concurrency)
        samples, unit = farm_job.samples_of(scene)
        r = scene.render
        w = int(r.resolution_x * r.resolution_percentage / 100)
        h = int(r.resolution_y * r.resolution_percentage / 100)

        box = layout.box()
        col = box.column(align=True)
        col.label(text=f"Frames {scene.frame_start}-{scene.frame_end}"
                       + (f" step {scene.frame_step}" if scene.frame_step > 1 else "")
                       + f": {len(frames)} · {est['chunks']} chunks of {pr.chunk_size}", icon="RENDER_ANIMATION")
        col.label(text=f"{w}x{h}" + (f" · {samples} {unit}" if samples else "")
                       + f" · {r.engine.replace('BLENDER_', '').title()} · {r.image_settings.file_format}")
        lo, hi = est["cost"], est["wall"]
        col.label(text=f"Estimate: ${lo[0]:.2f}-{lo[1]:.2f} · {farm_job.fmt_s(est['gpu_s'][0])}-"
                       f"{farm_job.fmt_s(est['gpu_s'][1])} of GPU time", icon="INFO")
        col.label(text=f"   ~{farm_job.fmt_s(hi[0])}-{farm_job.fmt_s(hi[1])} wall at {pr.concurrency} GPUs, "
                       f"+ ~{farm_job.fmt_s(est['cold_start'])} cold start")
        col.label(text=f"   {est['sec_per_frame'][0]:.1f}-{est['sec_per_frame'][1]:.1f} s/frame, "
                       f"${farm_job.GPU_RATE_PER_HOUR:.2f}/GPU-h (RTX PRO 6000); an estimate")

        if not pr.fal_key.strip():
            layout.label(text="Set your fal key in the add-on preferences", icon="ERROR")
        if not pr.app_id.strip().strip("/"):
            layout.label(text="Set the farm app (<your-fal-username>/blender-farm-2) below", icon="ERROR")
        if r.image_settings.file_format != "PNG" and pr.app_id.strip().strip("/").endswith("/blender-farm"):
            layout.label(text=f"{pr.app_id} returns PNG only; use a blender-farm-2 deployment for "
                              f"{r.image_settings.file_format}", icon="ERROR")
        if r.image_settings.file_format == "FFMPEG":
            layout.label(text="Video output: pick an image format (MP4 is encoded after)", icon="ERROR")

        row = layout.row(align=True)
        row.scale_y = 1.4
        row.operator(FALRF_OT_render.bl_idname, text="Render animation on fal", icon="RENDER_ANIMATION").mode = "ANIMATION"
        row = layout.row(align=True)
        row.operator(FALRF_OT_render.bl_idname, text="Render this frame on fal", icon="RENDER_STILL").mode = "FRAME"
        row.operator(FALRF_OT_cancel.bl_idname, text="Cancel", icon="CANCEL")

        sub = layout.column(align=True)
        sub.prop(pr, "app_id")
        row = sub.row(align=True)
        row.prop(pr, "chunk_size", text="Chunk")
        row.prop(pr, "concurrency", text="GPUs")
        sub.prop(pr, "encode_mp4")
        layout.label(text="Output: " + (r.filepath or "(blend file folder)"), icon="FILE_FOLDER")

        j = farm_job.CURRENT
        if j is None:
            return
        s = j.snapshot()
        box = layout.box()
        icon = {"done": "CHECKMARK", "failed": "ERROR", "cancelled": "CANCEL"}.get(s["phase"], "SORTTIME")
        box.label(text=f"{s['phase'].title()} · {s['app']}", icon=icon)
        if s["n_chunks"]:
            box.progress(factor=s["frames_done"] / max(1, s["frames_total"]), text=_progress_text(s))
            c = s["counts"]
            box.label(text=f"queued {c.get('queued', 0) + c.get('pending', 0)} · rendering {c.get('rendering', 0)} "
                           f"· downloading {c.get('downloading', 0)} · done {c.get('done', 0)} "
                           f"· failed {c.get('failed', 0)}" + (f" · {s['skipped']} frames already on disk"
                                                                if s["skipped"] else ""))
        if s["message"]:
            box.label(text=s["message"][:160])
        for label, err in s["failed"][:8]:
            box.label(text=f"chunk {label}: {err[:140]}", icon="ERROR")
        if s["mp4"]:
            box.label(text=f"MP4: {s['mp4']}", icon="FILE_MOVIE")
        row = box.row()
        row.operator(FALRF_OT_retry.bl_idname, icon="FILE_REFRESH")
        row.operator(FALRF_OT_open_output.bl_idname, icon="FILE_FOLDER")

def draw_status(self, context):
    j = farm_job.CURRENT
    if j is None or (not j.running and j.finished_seen and time.time() - (j.t_end or 0) > 30):
        return
    s = j.snapshot()
    text = f"fal farm: {s['phase']}"
    if s["n_chunks"]:
        text += " · " + _progress_text(s)
    self.layout.separator()
    self.layout.label(text=text, icon="WORLD")

# -- UI timer: redraws while a job runs, then reacts once to its end --------------------------------------------

def _redraw():
    wm = bpy.context.window_manager
    if wm is None:
        return
    for win in wm.windows:
        for area in win.screen.areas:
            if area.type in ("PROPERTIES", "STATUSBAR"):
                area.tag_redraw()

def _tick():
    j = farm_job.CURRENT
    if j is None:
        return None
    try:
        _redraw()
    except Exception:  # noqa: BLE001 - never let a redraw problem kill the timer
        pass
    if j.running:
        return 0.5
    if not j.finished_seen:
        j.finished_seen = True
        if j.p.mode == "FRAME" and j.phase == "done":
            _show_frame(j)
    return None

def _show_frame(j):
    path = j.p.targets[j.p.frames[0]]
    if not os.path.exists(path):
        return
    img = bpy.data.images.load(path, check_existing=True)
    img.reload()
    for win in bpy.context.window_manager.windows:
        for area in win.screen.areas:
            if area.type == "IMAGE_EDITOR":
                area.spaces.active.image = img
                area.tag_redraw()
                return

def _start_ui_timer():
    if not bpy.app.timers.is_registered(_tick):
        bpy.app.timers.register(_tick, first_interval=0.5, persistent=True)

classes = (FALRF_Preferences, FALRF_OT_render, FALRF_OT_cancel, FALRF_OT_retry, FALRF_OT_check_key,
           FALRF_OT_open_output, FALRF_PT_panel)

def register():
    for c in classes:
        bpy.utils.register_class(c)
    bpy.types.STATUSBAR_HT_header.append(draw_status)

def unregister():
    if farm_job.CURRENT is not None and farm_job.CURRENT.running:
        farm_job.CURRENT.cancel()
    if bpy.app.timers.is_registered(_tick):
        bpy.app.timers.unregister(_tick)
    bpy.types.STATUSBAR_HT_header.remove(draw_status)
    for c in reversed(classes):
        bpy.utils.unregister_class(c)
```

## File: blender_addon/fal_render_farm/blender_manifest.toml
size: 531
sha: 6bbcfbeecef716b8034c45c27bc318093c8561a1
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/fal_render_farm/blender_manifest.toml

```text
schema_version = "1.0.0"

id = "fal_render_farm"
version = "1.0.0"
name = "fal Render Farm"
tagline = "Render the open scene on a fal Serverless GPU render farm"
maintainer = "AnyScene contributors"
type = "add-on"

blender_version_min = "4.2.0"

license = ["SPDX:GPL-3.0-or-later"]
tags = ["Render"]

[permissions]
network = "Upload the scene to fal storage and render it on fal Serverless"
files = "Save a packed temp copy and write frames to the output path"

[build]
paths_exclude_pattern = ["__pycache__/", "*.pyc", "/.git/"]
```

## File: blender_addon/fal_render_farm/fal_api.py
size: 6622
sha: 55f94edebdbeea63bc219c160cabee06689818f9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/fal_render_farm/fal_api.py

```text
"""fal over plain HTTPS (urllib only, nothing Blender doesn't ship): the queue API and CDN storage uploads.

Queue:   POST https://queue.fal.run/<app>  -> {request_id, status_url, response_url, cancel_url}
         GET  status_url                  -> {status: IN_QUEUE | IN_PROGRESS | COMPLETED, queue_position?}
         GET  response_url                -> the app's result (or an HTTP error with the app's exception)
         PUT  cancel_url
Storage: the same CDN v3 flow fal_client uses: a short-lived upload token from rest.fal.ai, then a single POST
         (small files) or a multipart upload (big ones) to the token's base URL. Returns a public access URL.

The key is only ever put in an Authorization header; it never appears in an error message or a log line.
"""

import json
import os
import time
import urllib.error
import urllib.request

QUEUE_URL = "https://queue.fal.run"
REST_URL = "https://rest.fal.ai"
USER_AGENT = "fal-render-farm-blender/1.0"
MULTIPART_THRESHOLD = 90 * 1024 * 1024
PART_SIZE = 10 * 1024 * 1024
TRANSIENT = {408, 409, 425, 429, 500, 502, 503, 504}

class FalError(RuntimeError):
    def __init__(self, msg, status=None):
        super().__init__(msg)
        self.status = status

def _scrub(text, key):
    text = text or ""
    if key:
        text = text.replace(key, "[key]")
    return text

def _request(method, url, *, key=None, auth=None, body=None, headers=None, timeout=60, retries=3, raw=False):
    """One HTTP call with retries on transient failures. `auth` is a full Authorization header value."""
    hdrs = {"User-Agent": USER_AGENT, "Accept": "application/json"}
    if key:
        hdrs["Authorization"] = f"Key {key}"
    if auth:
        hdrs["Authorization"] = auth
    if isinstance(body, (dict, list)):
        body = json.dumps(body).encode()
        hdrs["Content-Type"] = "application/json"
    hdrs.update(headers or {})
    last = None
    for attempt in range(retries):
        req = urllib.request.Request(url, data=body, method=method, headers=hdrs)
        try:
            with urllib.request.urlopen(req, timeout=timeout) as r:
                data = r.read()
                if raw:
                    return data, dict(r.headers)
                return json.loads(data) if data else {}
        except urllib.error.HTTPError as e:
            detail = _scrub(e.read().decode("utf-8", "replace"), key)
            last = FalError(f"HTTP {e.code} from {method} {url.split('?')[0]}: {detail[:2000]}", e.code)
            if e.code not in TRANSIENT:
                raise last from None
        except (urllib.error.URLError, TimeoutError, ConnectionError, OSError) as e:
            last = FalError(f"{method} {url.split('?')[0]} failed: {_scrub(str(e), key)}")
        time.sleep(1.5 * (attempt + 1))
    raise last

# -- storage ----------------------------------------------------------------------------------------------------

def _cdn_token(key):
    data = _request("POST", f"{REST_URL}/storage/auth/token?storage_type=fal-cdn-v3", key=key, body={})
    return f"{data['token_type']} {data['token']}", data["base_url"]

def upload_file(key, path, content_type="application/zip", expires_s=7 * 86400, progress=None):
    """Upload a local file to fal storage and return its public URL. progress(bytes_sent, total) is optional."""
    size = os.path.getsize(path)
    name = os.path.basename(path)
    auth, base = _cdn_token(key)
    lifecycle = json.dumps({"expiration_duration_seconds": int(expires_s)})
    if size <= MULTIPART_THRESHOLD:
        with open(path, "rb") as f:
            data = f.read()
        res = _request("POST", f"{base}/files/upload", auth=auth, body=data, timeout=600, headers={
            "Content-Type": content_type, "X-Fal-File-Name": name, "X-Fal-Object-Lifecycle": lifecycle})
        if progress:
            progress(size, size)
        return res["access_url"]

    res = _request("POST", f"{base}/files/upload/multipart", auth=auth, headers={
        "Content-Type": content_type, "X-Fal-File-Name": name, "X-Fal-Object-Lifecycle": lifecycle})
    access, upload_id = res["access_url"], res["uploadId"]
    parts, sent = [], 0
    with open(path, "rb") as f:
        n = 1
        while chunk := f.read(PART_SIZE):
            _, hdrs = _request("PUT", f"{access}/multipart/{upload_id}/{n}", auth=auth, body=chunk, timeout=600,
                               raw=True, headers={"Content-Type": content_type, "Accept-Encoding": "identity"})
            etag = {k.lower(): v for k, v in hdrs.items()}.get("etag")
            parts.append({"partNumber": n, "etag": etag})
            sent += len(chunk)
            if progress:
                progress(sent, size)
            n += 1
    _request("POST", f"{access}/multipart/{upload_id}/complete", auth=auth, body={"parts": parts})
    return access

def download(url, dest, timeout=600):
    """Stream a URL to a file (written to dest.part, then renamed)."""
    tmp = dest + ".part"
    for attempt in range(3):
        try:
            req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT})
            with urllib.request.urlopen(req, timeout=timeout) as r, open(tmp, "wb") as f:
                while chunk := r.read(4 << 20):
                    f.write(chunk)
            os.replace(tmp, dest)
            return dest
        except (urllib.error.URLError, TimeoutError, ConnectionError, OSError) as e:
            err = e
            time.sleep(2 * (attempt + 1))
    raise FalError(f"download failed: {err}")

# -- queue ------------------------------------------------------------------------------------------------------

def submit(key, app, payload):
    return _request("POST", f"{QUEUE_URL}/{app.strip('/')}", key=key, body=payload)

def status(key, handle):
    return _request("GET", handle["status_url"], key=key)

def result(key, handle):
    return _request("GET", handle["response_url"], key=key, timeout=120)

def cancel(key, handle):
    try:
        _request("PUT", handle["cancel_url"], key=key, retries=1, timeout=15)
    except FalError:
        pass  # already finished, or never started: nothing to cancel

def check_key(key, app):
    """Cheap auth probe: a status read of a request id that doesn't exist. 401/403 means a bad key."""
    try:
        _request("GET", f"{QUEUE_URL}/{app.strip('/')}/requests/00000000-0000-0000-0000-000000000000/status",
                 key=key, retries=1, timeout=15)
    except FalError as e:
        if e.status in (401, 403):
            return False, "fal rejected the key (HTTP %s)" % e.status
        return True, "key accepted"
    return True, "key accepted"
```

## File: blender_addon/fal_render_farm/farm_gpu.py
size: 1161
sha: 07c94187b21468b51b9a7e00e397df3e3fdd368b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/fal_render_farm/farm_gpu.py

```text
"""Shipped in every bundle and run with --python before the render: headless Blender on the farm would otherwise
render Cycles on the CPU. Picks OptiX (else CUDA), enables only those devices, and puts every scene on the GPU now,
on file load and at render start. Nothing else about the scene is touched. (Same idea as builder/blender_gpu.py.)"""

import bpy
from bpy.app.handlers import persistent

def _devices():
    try:
        prefs = bpy.context.preferences.addons["cycles"].preferences
    except (KeyError, AttributeError):
        return "no cycles"
    for kind in ("OPTIX", "CUDA"):
        try:
            prefs.compute_device_type = kind
            prefs.get_devices()
        except TypeError:
            continue
        if any(d.type == kind for d in prefs.devices):
            for d in prefs.devices:
                d.use = d.type == kind
            return kind
    return "none"

@persistent
def _gpu_scenes(*_):
    for sc in bpy.data.scenes:
        sc.cycles.device = "GPU"

print("fal-farm: compute device", _devices())
_gpu_scenes()
bpy.app.handlers.load_post.append(_gpu_scenes)
bpy.app.handlers.render_init.append(_gpu_scenes)
```

## File: blender_addon/fal_render_farm/job.py
size: 21644
sha: b9ae39b99024ae904cdedd022b8ff673858442d3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/fal_render_farm/job.py

```text
"""A farm render job: everything that touches bpy happens in plan() on the main thread; Job.run() is pure Python on a
background thread (pack in a separate Blender, zip, upload, fan chunks out to the queue, download frames), so the UI
never blocks. The UI reads Job.snapshot() from a timer."""

import concurrent.futures as cf
import hashlib
import math
import os
import re
import shutil
import subprocess
import sys
import tempfile
import threading
import time
import traceback
import zipfile
from collections import deque
from dataclasses import dataclass, field

from . import fal_api

HERE = os.path.dirname(os.path.abspath(__file__))
GPU_RATE_PER_HOUR = 4.00  # RTX PRO 6000 on fal
REF_PIXELS = 1920 * 804
REF_SAMPLES = 48
REF_SEC_PER_FRAME = (5.0, 7.0)  # measured on mission control at 1920x804 / 48 spp
CHUNK_OVERHEAD_S = 20.0  # Blender start + scene load + zip/upload of the frames, per request
COLD_START_S = 90.0  # first workers when the app has scaled to zero
VIDEO_SAFE = {"PNG", "JPEG", "TIFF", "TARGA", "TARGA_RAW", "BMP", "WEBP"}
NO_WINDOW = 0x08000000 if sys.platform == "win32" else 0  # CREATE_NO_WINDOW: no console flashing up per subprocess

_uploads = {}  # bundle sha256 -> fal storage URL, so a retry or re-render of an unchanged file skips the upload
CURRENT = None  # the job the panel shows

class PlanError(Exception):
    pass

NO_APP_MSG = ("Set the farm app in Preferences > Add-ons > fal Render Farm: the fal app id of your render farm, "
              "<your-fal-username>/blender-farm-2 (deploy farm/app.py on your own fal account)")

# -- estimate ---------------------------------------------------------------------------------------------------

def samples_of(scene):
    eng = scene.render.engine
    if eng == "CYCLES":
        return scene.cycles.samples, "spp"
    if eng.startswith("BLENDER_EEVEE"):
        return scene.eevee.taa_render_samples, "samples"
    return None, ""

def frame_list(scene, mode):
    if mode == "FRAME":
        return [scene.frame_current]
    return list(range(scene.frame_start, scene.frame_end + 1, max(1, scene.frame_step)))

def estimate(scene, n_frames, chunk, concurrency):
    """Rough cost/time from the reference rate, scaled by pixels x samples. An estimate, not a quote."""
    r = scene.render
    pixels = r.resolution_x * r.resolution_y * (r.resolution_percentage / 100.0) ** 2
    samples, _ = samples_of(scene)
    scale = pixels / REF_PIXELS * ((samples or REF_SAMPLES * 0.05) / REF_SAMPLES)
    spf = [max(0.3, s * scale) for s in REF_SEC_PER_FRAME]
    n_chunks = max(1, math.ceil(n_frames / max(1, chunk))) if n_frames else 0
    gpu_s = [n_frames * s + n_chunks * CHUNK_OVERHEAD_S for s in spf]
    waves = math.ceil(n_chunks / max(1, min(concurrency, n_chunks or 1))) if n_chunks else 0
    per = min(chunk, n_frames)
    wall = [waves * (per * s + CHUNK_OVERHEAD_S) for s in spf]
    return {
        "sec_per_frame": spf, "chunks": n_chunks, "gpu_s": gpu_s, "cost": [g / 3600 * GPU_RATE_PER_HOUR for g in gpu_s],
        "wall": wall, "cold_start": COLD_START_S, "pixels": int(pixels), "samples": samples,
    }

def fmt_s(s):
    s = int(round(s))
    if s < 60:
        return f"{s}s"
    if s < 3600:
        return f"{s // 60}m{s % 60:02d}s"
    return f"{s // 3600}h{(s % 3600) // 60:02d}m"

# -- plan (main thread) -----------------------------------------------------------------------------------------

@dataclass
class Plan:
    mode: str
    scene_name: str
    frames: list
    step: int
    targets: dict  # frame -> absolute local path, exactly as a local render names it
    farm_pattern: str  # the filename part of render.filepath, with its # padding
    file_format: str
    fps: float
    key: str
    app: str
    chunk_size: int
    concurrency: int
    timeout_s: int
    encode_mp4: bool
    ffmpeg: str
    blender_bin: str
    workdir: str = ""
    copy_path: str = ""
    skipped: list = field(default_factory=list)

def plan(context, mode, prefs):
    import bpy

    scene = context.scene
    r = scene.render
    if not prefs.fal_key.strip():
        raise PlanError("Set your fal key in Preferences > Add-ons > fal Render Farm")
    if not prefs.app_id.strip().strip("/"):
        raise PlanError(NO_APP_MSG)
    if r.image_settings.file_format == "FFMPEG" or getattr(r.image_settings, "media_type", "") == "VIDEO":
        raise PlanError("Output is a video format; the farm renders frame sequences in chunks. Pick an image format "
                        "(PNG, EXR...) and enable 'Encode MP4' in the add-on preferences instead")
    if scene.camera is None:
        raise PlanError("The scene has no active camera")
    if r.filepath.startswith("//") and not bpy.data.filepath:
        raise PlanError("The output path is relative (//) but this file has never been saved; save it first "
                        "or set an absolute output path")
    frames = frame_list(scene, mode)
    if not frames:
        raise PlanError("The frame range is empty")
    targets = {f: os.path.abspath(bpy.path.abspath(r.frame_path(frame=f))) for f in frames}
    pattern = re.split(r"[\\/]", r.filepath)[-1]
    if pattern in ("", ".", ".."):
        pattern = ""
    ffmpeg = prefs.ffmpeg_path.strip() or shutil.which("ffmpeg") or ""
    return Plan(
        mode=mode, scene_name=scene.name, frames=frames, step=max(1, scene.frame_step) if mode == "ANIMATION" else 1,
        targets=targets, farm_pattern=pattern, file_format=r.image_settings.file_format,
        fps=r.fps / (r.fps_base or 1.0), key=prefs.fal_key.strip(), app=prefs.app_id.strip().strip("/"),
        chunk_size=max(1, prefs.chunk_size), concurrency=max(1, prefs.concurrency), timeout_s=prefs.timeout_s,
        encode_mp4=prefs.encode_mp4 and mode == "ANIMATION", ffmpeg=ffmpeg, blender_bin=bpy.app.binary_path,
    )

def save_copy(p):
    """Write the open file, unsaved edits included, to a temp dir. copy=True leaves the user's file, its path and its
    dirty state alone; relative_remap keeps // paths pointing at the same files from the new location."""
    import bpy

    p.workdir = tempfile.mkdtemp(prefix="fal_farm_")
    p.copy_path = os.path.join(p.workdir, "copy.blend")
    bpy.ops.wm.save_as_mainfile(filepath=p.copy_path, copy=True, relative_remap=True, compress=False,
                                check_existing=False)
    if not os.path.exists(p.copy_path):
        raise PlanError("Could not save a temporary copy of the file")

# -- job (background thread) ------------------------------------------------------------------------------------

@dataclass
class Chunk:
    frames: list
    step: int
    status: str = "pending"  # pending queued rendering downloading done failed cancelled
    error: str = ""
    attempts: int = 0
    render_s: float = 0.0
    gpu_s: float = 0.0
    device: str = ""
    handle: dict = None

    @property
    def label(self):
        a, b = self.frames[0], self.frames[-1]
        return f"{a}" if a == b else f"{a}-{b}"

class Job:
    def __init__(self, p: Plan):
        self.p = p
        self.lock = threading.Lock()
        self.cancel_ev = threading.Event()
        self.phase = "starting"  # packing uploading rendering encoding done failed cancelled
        self.message = ""
        self.log = deque(maxlen=200)
        self.chunks = []
        self.bundle_url = self.bundle_id = None
        self.t0 = time.time()
        self.t_end = None
        self.mp4 = None
        self.thread = None
        self.finished_seen = False  # set by the UI once it has reacted to the end of the job

    # ---- public ----
    def start(self):
        self.thread = threading.Thread(target=self._run, name="fal-render-farm", daemon=True)
        self.thread.start()
        return self

    def cancel(self):
        self.cancel_ev.set()
        self._say("cancelling...")
        with self.lock:
            handles = [c.handle for c in self.chunks if c.handle and c.status in ("queued", "rendering")]
        for h in handles:
            threading.Thread(target=fal_api.cancel, args=(self.p.key, h), daemon=True).start()

    def retry_failed(self):
        if self.running:
            return False
        with self.lock:
            failed = [c for c in self.chunks if c.status in ("failed", "cancelled")]
            for c in failed:
                c.status, c.error, c.attempts, c.handle = "pending", "", 0, None
        if not failed:
            return False
        self.cancel_ev.clear()
        self.t0, self.t_end, self.phase = time.time(), None, "starting"
        self.finished_seen = False
        self.thread = threading.Thread(target=self._run, name="fal-render-farm", daemon=True)
        self.thread.start()
        return True

    @property
    def running(self):
        return self.thread is not None and self.thread.is_alive()

    def wait(self, timeout=None):
        if self.thread:
            self.thread.join(timeout)
        return not self.running

    def snapshot(self):
        with self.lock:
            counts = {}
            for c in self.chunks:
                counts[c.status] = counts.get(c.status, 0) + 1
            frames_done = sum(len(c.frames) for c in self.chunks if c.status == "done")
            return {
                "phase": self.phase, "message": self.message, "counts": counts, "n_chunks": len(self.chunks),
                "frames_done": frames_done + len(self.p.skipped), "frames_total": len(self.p.frames),
                "skipped": len(self.p.skipped), "elapsed": (self.t_end or time.time()) - self.t0,
                "gpu_s": sum(c.gpu_s for c in self.chunks), "render_s": sum(c.render_s for c in self.chunks),
                "failed": [(c.label, c.error) for c in self.chunks if c.status == "failed"],
                "mp4": self.mp4, "mode": self.p.mode, "app": self.p.app,
            }

    # ---- internals ----
    def _say(self, msg):
        with self.lock:
            self.message = msg
        self.log.append(f"[{time.strftime('%H:%M:%S')}] {msg}")
        print("fal render farm:", msg)

    def _set_phase(self, phase, msg=None):
        with self.lock:
            self.phase = phase
        if msg:
            self._say(msg)

    def _run(self):
        try:
            if not self.chunks:
                missing = [f for f in self.p.frames if not os.path.exists(self.p.targets[f])]
                self.p.skipped = [f for f in self.p.frames if f not in set(missing)]
                if self.p.skipped:
                    self._say(f"{len(self.p.skipped)} frames already on disk, skipped")
                self.chunks = self._split(missing)
                if not self.chunks:
                    self._finish()
                    return
            if not self.bundle_url:
                self._bundle()
            self._render()
            self._finish()
        except Exception as e:  # noqa: BLE001 - any failure lands in the panel, not a stack trace on stderr only
            if self.cancel_ev.is_set():
                self._set_phase("cancelled", "cancelled")
            else:
                self._set_phase("failed", f"failed: {fal_api._scrub(str(e), self.p.key)}")
                self.log.append(fal_api._scrub(traceback.format_exc(), self.p.key))
            self.t_end = time.time()
        finally:
            if self.p.workdir and not self.running_chunks():
                shutil.rmtree(self.p.workdir, ignore_errors=True)

    def running_chunks(self):
        return any(c.status in ("queued", "rendering", "downloading") for c in self.chunks)

    def _split(self, missing):
        """Contiguous runs (in steps of frame_step) of missing frames, cut into chunks of at most chunk_size."""
        step, out, run = self.p.step, [], []
        for f in missing:
            if run and (f != run[-1] + step or len(run) >= self.p.chunk_size):
                out.append(Chunk(run, step))
                run = []
            run.append(f)
        if run:
            out.append(Chunk(run, step))
        return out

    def _bundle(self):
        p = self.p
        self._set_phase("packing", "packing a copy of the file (textures, fonts, linked data)...")
        packed = os.path.join(p.workdir, "scene.blend")
        proc = subprocess.run(
            [p.blender_bin, "-b", "--factory-startup", p.copy_path, "--python", os.path.join(HERE, "pack_copy.py"),
             "--", packed],
            capture_output=True, text=True, encoding="utf-8", errors="replace", creationflags=NO_WINDOW)
        out = proc.stdout + proc.stderr
        for line in out.splitlines():
            if line.startswith(("PACK-WARNING:", "PACK-INFO:")):
                self.log.append(line)
        problems = [l[len("PACK-PROBLEM:"):].strip() for l in out.splitlines() if l.startswith("PACK-PROBLEM:")]
        if problems:
            raise RuntimeError("the file references data that can't be packed: " + "; ".join(problems[:6]))
        if proc.returncode != 0 or not os.path.exists(packed):
            raise RuntimeError(f"packing failed (Blender exited {proc.returncode}): {out[-800:]}")
        os.remove(p.copy_path)
        if self.cancel_ev.is_set():
            raise RuntimeError("cancelled")

        zpath = os.path.join(p.workdir, "bundle.zip")
        with zipfile.ZipFile(zpath, "w", zipfile.ZIP_STORED) as z:  # the .blend is saved compressed already
            z.write(packed, "scene.blend")
            z.write(os.path.join(HERE, "farm_gpu.py"), "farm_gpu.py")
        os.remove(packed)
        sha = hashlib.sha256()
        with open(zpath, "rb") as f:
            while b := f.read(8 << 20):
                sha.update(b)
        digest = sha.hexdigest()
        self.bundle_id = digest[:16]
        size = os.path.getsize(zpath)
        if digest in _uploads:
            self.bundle_url = _uploads[digest]
            self._say(f"bundle {self.bundle_id} ({size / 1e6:.1f} MB) already uploaded")
        else:
            self._set_phase("uploading", f"uploading bundle {self.bundle_id} ({size / 1e6:.1f} MB)...")

            def prog(sent, total):
                with self.lock:
                    self.message = f"uploading bundle {self.bundle_id}: {sent / 1e6:.0f}/{total / 1e6:.0f} MB"

            self.bundle_url = fal_api.upload_file(p.key, zpath, progress=prog)
            _uploads[digest] = self.bundle_url
            self._say(f"bundle {self.bundle_id} uploaded")
        os.remove(zpath)

    def _args(self, c):
        p = self.p
        return ["{bundle}/scene.blend", "-S", p.scene_name, "--python", "{bundle}/farm_gpu.py",
                "-o", "{out}/frames/" + p.farm_pattern,
                "-s", str(c.frames[0]), "-e", str(c.frames[-1]), "-j", str(c.step), "-a"]

    def _render(self):
        pending = [c for c in self.chunks if c.status == "pending"]
        n = len(pending)
        self._set_phase("rendering", f"rendering {sum(len(c.frames) for c in pending)} frames in {n} chunks "
                                     f"on {self.p.app} ({min(n, self.p.concurrency)} at a time)")
        with cf.ThreadPoolExecutor(max_workers=min(n, self.p.concurrency), thread_name_prefix="fal-chunk") as pool:
            list(pool.map(self._chunk, pending))

    def _chunk(self, c):
        p = self.p
        while not self.cancel_ev.is_set():
            c.attempts += 1
            try:
                self._chunk_once(c)
                return
            except Exception as e:  # noqa: BLE001
                err = fal_api._scrub(str(e), p.key)
                if "with 0 frames" in err and p.file_format != "PNG":
                    err = (f"the farm returned no {p.file_format} files. {p.app} may only return PNGs; "
                           f"set the farm app to your blender-farm-2 deployment. Blender said: {err[-600:]}")
                if c.handle and c.status in ("queued", "rendering"):
                    fal_api.cancel(p.key, c.handle)  # e.g. a status poll gave up: don't leave a twin rendering
                with self.lock:
                    c.error, c.handle = err, None
                if self.cancel_ev.is_set():
                    break
                if c.attempts >= 2:
                    with self.lock:
                        c.status = "failed"
                    self._say(f"chunk {c.label} failed: {err[:300]}")
                    return
                self._say(f"chunk {c.label} attempt {c.attempts} failed, retrying: {err[:200]}")
                time.sleep(3)
        with self.lock:
            c.status = "cancelled"

    def _chunk_once(self, c):
        p = self.p
        payload = {"bundle_url": self.bundle_url, "bundle_id": self.bundle_id, "blender_args": self._args(c),
                   "timeout_s": int(p.timeout_s), "outputs": ["frames/**/*"]}
        with self.lock:
            c.status = "queued"
        handle = fal_api.submit(p.key, p.app, payload)
        with self.lock:
            c.handle = handle
        delay = 1.0
        while True:
            if self.cancel_ev.is_set():
                fal_api.cancel(p.key, handle)
                raise RuntimeError("cancelled")
            st = fal_api.status(p.key, handle).get("status")
            if st == "IN_PROGRESS":
                with self.lock:
                    c.status = "rendering"
            elif st == "COMPLETED":
                break
            time.sleep(delay)
            delay = min(delay * 1.5, 4.0)
        res = fal_api.result(p.key, handle)
        if "frames_url" not in res:
            raise RuntimeError(f"unexpected farm response: {str(res)[:500]}")
        with self.lock:
            c.status = "downloading"
        zpath = os.path.join(tempfile.gettempdir(), f"fal_farm_{self.bundle_id}_{c.frames[0]}_{c.frames[-1]}.zip")
        fal_api.download(res["frames_url"], zpath)
        try:
            self._extract(zpath, c)
        finally:
            os.remove(zpath)
        with self.lock:
            c.status, c.error, c.handle = "done", "", None
            c.render_s = float(res.get("render_seconds", 0))
            c.gpu_s = c.render_s + float(res.get("bundle_seconds", 0))
            c.device = res.get("device", "")
        self._say(f"chunk {c.label}: {res.get('frame_count')} frames, render {c.render_s:.0f}s on "
                  f"{c.device.split(',')[0]}")

    def _extract(self, zpath, c):
        p = self.p
        by_name = {os.path.basename(p.targets[f]): p.targets[f] for f in c.frames}
        by_lower = {k.lower(): v for k, v in by_name.items()}
        fallback_dir = os.path.dirname(p.targets[c.frames[0]])
        with zipfile.ZipFile(zpath) as z:
            for info in z.infolist():
                if info.is_dir():
                    continue
                name = info.filename.rsplit("/", 1)[-1]
                dest = by_name.get(name) or by_lower.get(name.lower()) or os.path.join(fallback_dir, name)
                os.makedirs(os.path.dirname(dest), exist_ok=True)
                with z.open(info) as src, open(dest + ".part", "wb") as dst:
                    shutil.copyfileobj(src, dst, 4 << 20)
                os.replace(dest + ".part", dest)
        missing = [f for f in c.frames if not os.path.exists(p.targets[f])]
        if missing:
            got = ", ".join(n.rsplit("/", 1)[-1] for n in zipfile.ZipFile(zpath).namelist()[:4])
            raise RuntimeError(f"farm output is missing frames {missing[:8]} (got {got})")

    def _finish(self):
        if self.cancel_ev.is_set():
            self._set_phase("cancelled", "cancelled")
        elif any(c.status == "failed" for c in self.chunks):
            n = sum(c.status == "failed" for c in self.chunks)
            self._set_phase("failed", f"{n} chunk(s) failed; fix and press Retry failed chunks")
        else:
            if self.p.encode_mp4:
                self._encode()
            self._set_phase("done", f"done: {len(self.p.frames)} frames in "
                                    f"{os.path.dirname(self.p.targets[self.p.frames[0]])}")
        self.t_end = time.time()

    def _encode(self):
        p = self.p
        if not p.ffmpeg:
            self._say("ffmpeg not found; skipping the MP4 (set its path in the add-on preferences)")
            return
        if p.file_format not in VIDEO_SAFE:
            self._say(f"skipping the MP4: {p.file_format} frames are linear/HDR, encode them in your grade instead")
            return
        self._set_phase("encoding", "encoding MP4...")
        first, last = p.frames[0], p.frames[-1]
        stem = os.path.splitext(os.path.basename(p.targets[first]))[0]
        stem = re.sub(r"\d+$", "", stem).rstrip("_.- ") or "render"
        out = os.path.join(os.path.dirname(p.targets[first]), f"{stem}_{first:04d}-{last:04d}.mp4")
        listing = os.path.join(tempfile.gettempdir(), f"fal_farm_concat_{os.getpid()}.txt")
        with open(listing, "w", encoding="utf-8") as f:
            for fr in p.frames:
                f.write("file '%s'\nduration %.6f\n" % (p.targets[fr].replace("\\", "/").replace("'", r"'\''"), 1 / p.fps))
            f.write("file '%s'\n" % p.targets[last].replace("\\", "/").replace("'", r"'\''"))
        cmd = [p.ffmpeg, "-y", "-loglevel", "error", "-f", "concat", "-safe", "0", "-i", listing,
               "-vf", "pad=ceil(iw/2)*2:ceil(ih/2)*2", "-r", f"{p.fps:g}", "-c:v", "libx264", "-pix_fmt", "yuv420p",
               "-crf", "16", "-preset", "slow", out]
        proc = subprocess.run(cmd, capture_output=True, text=True, errors="replace", creationflags=NO_WINDOW)
        os.remove(listing)
        if proc.returncode == 0:
            self.mp4 = out
            self._say(f"MP4: {out}")
        else:
            self._say(f"ffmpeg failed: {proc.stderr[-400:]}")
```

## File: blender_addon/fal_render_farm/pack_copy.py
size: 2085
sha: 633803d1475e83913590ea066a32c524e80b4c53
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/fal_render_farm/pack_copy.py

```text
"""Run by the add-on in a separate background Blender, on a temporary copy of the user's file (never the file itself):

    blender -b --factory-startup <copy.blend> --python pack_copy.py -- <out.blend>

Makes linked library data local, packs images/fonts/sounds/volumes, and refuses (exit 2) if anything the render
needs still points outside the file, listing each path on a "PACK-PROBLEM:" line.
"""

import os
import sys

import bpy

out = sys.argv[sys.argv.index("--") + 1]

if bpy.data.libraries:
    print("PACK-INFO: making linked data local:", ", ".join(l.filepath for l in bpy.data.libraries))
    try:
        bpy.ops.object.make_local(type="ALL")
    except RuntimeError as e:
        print("PACK-INFO: make_local:", e)

try:
    bpy.ops.file.pack_all()
except RuntimeError as e:  # missing files: reported below as problems
    print("PACK-INFO: pack_all:", str(e).strip())

problems, warnings = [], []
for img in bpy.data.images:
    if img.users and img.source in {"FILE", "SEQUENCE", "TILED", "MOVIE"} and not img.packed_file and img.filepath:
        problems.append(f"image not packed ({img.source.lower()}): {img.name} -> {img.filepath}")
for v in bpy.data.volumes:
    if v.users and not v.packed_file and v.filepath:
        problems.append(f"volume not packed: {v.name} -> {v.filepath}")
for c in bpy.data.cache_files:
    if c.users:
        problems.append(f"cache file (Alembic/USD) can't be packed: {c.name} -> {c.filepath}")
for lib in bpy.data.libraries:
    problems.append(f"library still linked: {lib.filepath}")
for ob in bpy.data.objects:
    for m in ob.modifiers:
        if m.type == "FLUID" and m.fluid_type == "DOMAIN":
            warnings.append(f"fluid domain {ob.name}: its disk cache is not shipped "
                            f"({bpy.path.abspath(m.domain_settings.cache_directory)})")

for w in warnings:
    print("PACK-WARNING:", w)
for p in problems:
    print("PACK-PROBLEM:", p)
if problems:
    sys.exit(2)

bpy.ops.wm.save_as_mainfile(filepath=os.path.abspath(out), copy=True, compress=True)
print("PACK-OK:", os.path.getsize(out))
```

## File: blender_addon/tests/make_test_scene.py
size: 4232
sha: cb97ea8fd861ffcd6e19e178d80e4e60ba45618b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/tests/make_test_scene.py

```text
"""Build the add-on's test scene: a few animated objects, an external image texture (to exercise packing), a sun and
an area light, a moving camera, 48 frames at 640x360, Cycles at 32 spp with a fixed seed and no denoiser.

    blender -b --factory-startup --python make_test_scene.py -- <dir>

Writes <dir>/test_scene.blend and <dir>/tex/checker.png; output path is //renders/test_#### (relative on purpose).
"""

import math
import os
import sys

import bpy

out_dir = os.path.abspath(sys.argv[sys.argv.index("--") + 1])
os.makedirs(os.path.join(out_dir, "tex"), exist_ok=True)

bpy.ops.wm.read_factory_settings(use_empty=True)
scene = bpy.context.scene
scene.name = "FarmTest"

# external texture, saved next to the .blend and referenced relatively -> must be packed for the farm
tex_path = os.path.join(out_dir, "tex", "checker.png")
img = bpy.data.images.new("checker", 256, 256)
px = []
for y in range(256):
    for x in range(256):
        c = 0.9 if ((x // 32) + (y // 32)) % 2 else 0.1
        px += [c, 0.35 + 0.5 * (x / 255), 1.0 - c * 0.6, 1.0]
img.pixels = px
img.filepath_raw = tex_path
img.file_format = "PNG"
img.save()

def material(name, color=None, image=None):
    m = bpy.data.materials.new(name)
    m.use_nodes = True
    bsdf = m.node_tree.nodes["Principled BSDF"]
    if image:
        t = m.node_tree.nodes.new("ShaderNodeTexImage")
        t.image = bpy.data.images.load(tex_path)
        m.node_tree.links.new(t.outputs["Color"], bsdf.inputs["Base Color"])
    else:
        bsdf.inputs["Base Color"].default_value = (*color, 1)
    bsdf.inputs["Roughness"].default_value = 0.35
    return m

bpy.data.images.remove(img)  # the material loads it back from disk, as a normal external image

bpy.ops.mesh.primitive_plane_add(size=20)
bpy.context.object.data.materials.append(material("floor", image=True))

bpy.ops.mesh.primitive_cube_add(size=1.5, location=(-2, 0, 0.75))
cube = bpy.context.object
cube.data.materials.append(material("red", (0.8, 0.1, 0.08)))
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.9, location=(0.5, 1.5, 0.9))
sphere = bpy.context.object
bpy.ops.object.shade_smooth()
sphere.data.materials.append(material("blue", (0.1, 0.3, 0.9)))
bpy.ops.mesh.primitive_monkey_add(size=1.4, location=(2.2, -0.8, 1.0))
monkey = bpy.context.object
bpy.ops.object.shade_smooth()
monkey.data.materials.append(material("gold", (0.9, 0.65, 0.2)))

for f, z_rot, sz in ((1, 0, 0.9), (48, 2 * math.pi, 2.6)):
    scene.frame_set(f)
    cube.rotation_euler.z = z_rot
    cube.keyframe_insert("rotation_euler", index=2)
    sphere.location.z = sz
    sphere.keyframe_insert("location", index=2)
    monkey.rotation_euler.z = -z_rot / 2
    monkey.keyframe_insert("rotation_euler", index=2)

bpy.ops.object.light_add(type="SUN", rotation=(math.radians(50), 0, math.radians(30)))
bpy.context.object.data.energy = 3
bpy.ops.object.light_add(type="AREA", location=(-3, -4, 4))
bpy.context.object.data.energy = 400
bpy.context.object.data.size = 3

bpy.ops.object.camera_add(location=(0, -9, 4))
cam = bpy.context.object
scene.camera = cam
for f, x in ((1, -2.0), (48, 2.0)):
    cam.location.x = x
    cam.keyframe_insert("location", index=0, frame=f)
con = cam.constraints.new("TRACK_TO")
bpy.ops.object.empty_add(location=(0, 0, 0.8))
con.target = bpy.context.object

world = bpy.data.worlds.new("World")
world.use_nodes = True
world.node_tree.nodes["Background"].inputs[0].default_value = (0.05, 0.07, 0.1, 1)
world.node_tree.nodes["Background"].inputs[1].default_value = 1.0
scene.world = world

r = scene.render
r.engine = "CYCLES"
scene.cycles.samples = 32
scene.cycles.use_adaptive_sampling = False
scene.cycles.use_denoising = False
scene.cycles.seed = 0
r.resolution_x, r.resolution_y, r.resolution_percentage = 640, 360, 100
r.fps = 24
scene.frame_start, scene.frame_end = 1, 48
r.image_settings.file_format = "PNG"
r.image_settings.color_mode = "RGBA"
r.filepath = "//renders/test_####"
scene.frame_set(1)

bpy.ops.wm.save_as_mainfile(filepath=os.path.join(out_dir, "test_scene.blend"), relative_remap=True)
bpy.ops.file.make_paths_relative()  # the texture becomes //tex/checker.png, like a real project
bpy.ops.wm.save_mainfile()
print("TEST-SCENE:", os.path.join(out_dir, "test_scene.blend"))
```

## File: blender_addon/tests/test_farm.py
size: 12422
sha: 4131624fc17095359b4ceb5df10342e137d51d60
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/tests/test_farm.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/tests/test_farm.py

## File: blender_addon/tests/test_zip_install.py
size: 1475
sha: 9bb1d8b8bac8126537d312fc209c661565583553
upstream: https://github.com/apekshik/anyscene/blob/HEAD/blender_addon/tests/test_zip_install.py

```text
"""Install the built extension zip the way a user would, into a throwaway user profile, and check it registers.

    BLENDER_USER_RESOURCES=<empty temp dir> blender -b --factory-startup --python-exit-code 1 \
        --python test_zip_install.py -- blender_addon/fal_render_farm-1.0.0.zip
"""

import os
import sys

import bpy

zip_path = os.path.abspath(sys.argv[sys.argv.index("--") + 1])
ext_dir = bpy.utils.user_resource("EXTENSIONS")
assert os.environ.get("BLENDER_USER_RESOURCES") and os.path.normcase(os.path.abspath(ext_dir)).startswith(os.path.normcase(os.path.abspath(os.environ["BLENDER_USER_RESOURCES"]))), \
    f"refusing to install into the real profile ({ext_dir})"
print("ZIP-TEST extensions dir:", ext_dir)

res = bpy.ops.extensions.package_install_files(repo="user_default", filepath=zip_path, enable_on_install=True)
print("ZIP-TEST install:", res)
name = "bl_ext.user_default.fal_render_farm"
assert name in bpy.context.preferences.addons, list(bpy.context.preferences.addons.keys())
prefs = bpy.context.preferences.addons[name].preferences
assert prefs.app_id == "" and prefs.chunk_size == 24 and prefs.concurrency == 100, "defaults"
assert hasattr(bpy.types, "FALRF_PT_panel"), "panel not registered"
assert bpy.ops.fal_render_farm.render.poll(), "render op poll"
assert not bpy.ops.fal_render_farm.cancel.poll(), "cancel op poll"
print("ZIP-TEST OK: installed and enabled as", name, "with defaults", prefs.app_id, prefs.chunk_size, prefs.concurrency)
```

## File: breakdown/anyshot_supercut.py
size: 10576
sha: bd0c0f748fc03c2b1299f8983e5702fe003a0af7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/anyshot_supercut.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/anyshot_supercut.py

## File: breakdown/assemble.py
size: 15424
sha: a2d83059537732b8dee87e3f2f7eff392ccbc929
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/assemble.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/assemble.py

## File: breakdown/builder_reel.py
size: 11674
sha: 3be469e174660a47cfdcb59f1b1aba9b1ff6566f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/builder_reel.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/builder_reel.py

## File: breakdown/kit_motion.py
size: 12040
sha: e3a9114509a490006dabc7da9864068799a4e170
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/kit_motion.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/kit_motion.py

## File: breakdown/kit_supercut.py
size: 15274
sha: 11100d456e8d884653eaf73265d5c533c2e6712e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/kit_supercut.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/kit_supercut.py

## File: breakdown/promo.py
size: 6365
sha: ced67aa13f62d9e2ad603d4059505af536c1d538
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/promo.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/promo.py

## File: breakdown/site_rec.mjs
size: 7730
sha: 2c77885a13a073d11bdd47642ebc00b5770def13
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/site_rec.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/site_rec.mjs

## File: breakdown/SPEC.md
size: 3869
sha: e061e8715af632b9774f318f9c24f0a8459233f3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/SPEC.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/SPEC.md

## File: breakdown/supercut.py
size: 17220
sha: f294fa8179e0ec2aeabd40a95de6949c86e4e2a2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/supercut.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/supercut.py

## File: breakdown/trailer.py
size: 19719
sha: 715bf20f58fbf2c02dfe51f983a3ffb941aadd63
upstream: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/trailer.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/breakdown/trailer.py

## File: builder/app.py
size: 36047
sha: 88267603c127fbee00f5cfc87184638678c619ee
upstream: https://github.com/apekshik/anyscene/blob/HEAD/builder/app.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/builder/app.py

## File: builder/blender_gpu.py
size: 1144
sha: 6279f1bedad9381aef92fd67744c0b39ec4c16e2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/builder/blender_gpu.py

```text
# synced from github.com/apekshik/anyshot agent/blender_gpu.py
"""Every Blender the agent starts renders Cycles on the GPU, even with --factory-startup and no GPU prefs script.
On the fal worker `blender` is a wrapper that runs this first (`blender.real --python blender_gpu.py "$@"`): headless
Blender otherwise renders on the CPU, which an agent forgot once and lost most of a two-hour job to."""

import bpy
from bpy.app.handlers import persistent

def _devices():
    try:
        prefs = bpy.context.preferences.addons["cycles"].preferences
    except (KeyError, AttributeError):
        return
    for kind in ("OPTIX", "CUDA"):
        try:
            prefs.compute_device_type = kind
            prefs.get_devices()
        except TypeError:
            continue
        if any(d.type == kind for d in prefs.devices):
            for d in prefs.devices:
                d.use = d.type == kind
            return

@persistent
def _gpu_scenes(*_):
    for sc in bpy.data.scenes:
        sc.cycles.device = "GPU"

_devices()
_gpu_scenes()
bpy.app.handlers.load_post.append(_gpu_scenes)
bpy.app.handlers.render_init.append(_gpu_scenes)
```

## File: builder/client.py
size: 4403
sha: 42bb423d1ea03edccec114a8a875ea1420283406
upstream: https://github.com/apekshik/anyscene/blob/HEAD/builder/client.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/builder/client.py

## File: builder/CRAFT.md
size: 3871
sha: 1ce00e10dad79e5b35db89ec2005ae696450a129
upstream: https://github.com/apekshik/anyscene/blob/HEAD/builder/CRAFT.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/builder/CRAFT.md

## File: builder/gallery.py
size: 17576
sha: 6c71a3b3d91e5197dab221a2758673fe7a10f11e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/builder/gallery.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/builder/gallery.py

## File: builder/PROMPT.md
size: 8110
sha: 2496cfacafb6f00da64cfe9a0625a51fa537fbf3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/builder/PROMPT.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/builder/PROMPT.md

## File: builder/scene_builder.py
size: 24359
sha: 40ff760645ba70dd096739cb8fb02d09afb25cff
upstream: https://github.com/apekshik/anyscene/blob/HEAD/builder/scene_builder.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/builder/scene_builder.py

## File: builder/sources.py
size: 10147
sha: 8235a55a433a69f23df0297aa721906b29e24d56
upstream: https://github.com/apekshik/anyscene/blob/HEAD/builder/sources.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/builder/sources.py

## File: camera/camrig.py
size: 23631
sha: 4564e727a1f6d628d18c1e3afee2f4516b5699d4
upstream: https://github.com/apekshik/anyscene/blob/HEAD/camera/camrig.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/camera/camrig.py

## File: camera/examples/ramen_shots.json
size: 1550
sha: 5e4cc09fbf46bd4c06009be128bd10de480c641e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/camera/examples/ramen_shots.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/camera/examples/ramen_shots.json

## File: camera/examples/repair_shots.json
size: 1474
sha: 6272d73ede97655890f9d2de23c6c32274f49e1d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/camera/examples/repair_shots.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/camera/examples/repair_shots.json

## File: camera/shoot.py
size: 8042
sha: 796033ffd7b6274de27858d08a47ae8e2a1d0e00
upstream: https://github.com/apekshik/anyscene/blob/HEAD/camera/shoot.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/camera/shoot.py

## File: docs/endpoint-map.html
size: 20245
sha: 7db9bffd12e3eb3199bd7a4b56f4ca5813c9c147
upstream: https://github.com/apekshik/anyscene/blob/HEAD/docs/endpoint-map.html

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/docs/endpoint-map.html

## File: docs/ENDPOINT.md
size: 8798
sha: 4289f8dd31347c62727372f98db6ad1339776f26
upstream: https://github.com/apekshik/anyscene/blob/HEAD/docs/ENDPOINT.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/docs/ENDPOINT.md

## File: docs/media/bakery.jpg
size: 69123
sha: 4ab5ca875b042f51102f21b6fd4ba9ad981b64e2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/bakery.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/bakery.jpg

## File: docs/media/bakery_reference.jpg
size: 67918
sha: 10a87ab936e08e8173987bb78ba4a07f6609b824
upstream: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/bakery_reference.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/bakery_reference.jpg

## File: docs/media/hk.jpg
size: 42283
sha: 7734536ea5b6c775191b0b377734b801bead15dd
upstream: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/hk.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/hk.jpg

## File: docs/media/mc.jpg
size: 47251
sha: 97207e792f1dbfc861c2d920f830326776f9eb5d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/mc.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/mc.jpg

## File: docs/media/ramen.jpg
size: 34511
sha: caf2e187d1f5a95d4412cd5c770d16e30684fc05
upstream: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/ramen.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/ramen.jpg

## File: docs/media/repair.jpg
size: 22626
sha: 09c0dec46e7dc73a993adc25af9d4eb0e19c3708
upstream: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/repair.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/repair.jpg

## File: docs/media/strip.jpg
size: 69249
sha: 30d4d828100c2060b7266a9b366fee972959954c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/strip.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/docs/media/strip.jpg

## File: endpoint/app.py
size: 22566
sha: d4f72c69dd057e0067d98c78c6b6d4acf91d453a
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/app.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/app.py

## File: endpoint/assemble.py
size: 14668
sha: f04075ddc720917451b3765243436e4fd386b7c3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/assemble.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/assemble.py

## File: endpoint/blockout.py
size: 6384
sha: 9a91e42fbb4a644bfe787a9b8aa04b460aedc5d5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/blockout.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/blockout.py

## File: endpoint/client.py
size: 4674
sha: 71831b31fb5b8c5d347fa7e713b2c31f0089934c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/client.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/client.py

## File: endpoint/floorplan.py
size: 5429
sha: 86cd64c8966e335cecafca7bc8e271789fd9a135
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/floorplan.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/floorplan.py

## File: endpoint/planner.py
size: 7317
sha: 1895d60b358accc73299f47a2a3936e5d83de341
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/planner.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/planner.py

## File: endpoint/props.py
size: 9520
sha: 80abd15313a24acc74023f178c2a66e0626f3868
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/props.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/props.py

## File: endpoint/refine.py
size: 7324
sha: a06b57d6c2b57ae2b487b726bf4da27c59ac4202
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/refine.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/refine.py

## File: endpoint/refine_blender.py
size: 14657
sha: 70a49a315599600f532b91c653d837b722ca17b5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/refine_blender.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/refine_blender.py

## File: endpoint/schema.py
size: 4490
sha: 48e47ae02431c0c1bdc7d4a94df8e19ad459b4b1
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/schema.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/schema.py

## File: endpoint/stages.py
size: 1190
sha: c00afe04df644f2d38e2e3a51746c91b4738ae95
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/stages.py

```text
"""Stage events: one JSON object per line on stdout, prefixed so clients can pick them out of the fal queue logs."""

import json
import sys
import time

PREFIX = "ANYSCENE_STAGE "

class Stages:
    def __init__(self, request_id: str = ""):
        self.request_id = request_id
        self.t0 = time.time()
        self.current = None

    def emit(self, stage: str, status: str = "running", message: str = "", progress: float | None = None,
             preview_url: str | None = None, **extra):
        event = {"stage": stage, "status": status, "message": message, "elapsed_s": round(time.time() - self.t0, 1)}
        if progress is not None:
            event["progress"] = round(progress, 3)
        if preview_url:
            event["preview_url"] = preview_url
        event.update(extra)
        print(PREFIX + json.dumps(event), flush=True)
        sys.stdout.flush()
        self.current = stage

    def start(self, stage, message=""):
        self.emit(stage, "running", message)

    def done(self, stage, message="", **extra):
        self.emit(stage, "done", message, **extra)

    def fail(self, message):
        self.emit(self.current or "unknown", "failed", message)
```

## File: endpoint/test/plan_sample.json
size: 4453
sha: 0cbcde9f3bdd95533f1db2819d956886cbf7723a
upstream: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/test/plan_sample.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/endpoint/test/plan_sample.json

## File: farm/.bundles.json
size: 304
sha: a7403cd3c379df264dbf23bc198a7b4e7960516c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/farm/.bundles.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/farm/.bundles.json

## File: farm/app.py
size: 11565
sha: 51daea0f693cbca1d9ef5b9400efdb1633b58768
upstream: https://github.com/apekshik/anyscene/blob/HEAD/farm/app.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/farm/app.py

## File: farm/farm.py
size: 8002
sha: ab598457cbd435a8f03288ab2d14c63d0729dff7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/farm/farm.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/farm/farm.py

## File: farm/jobs/hk-dai-pai-dong.json
size: 65
sha: 6156b5840de5031089b1db5f30795394ea915d58
upstream: https://github.com/apekshik/anyscene/blob/HEAD/farm/jobs/hk-dai-pai-dong.json

```text
{
  "blend": "hk.blend",
  "scripts": ["scripts/gpu_prefs.py"]
}
```

## File: farm/jobs/mission-control-1970s.json
size: 144
sha: 9cff564f43f2a6321240b29cbef5b046938bef34
upstream: https://github.com/apekshik/anyscene/blob/HEAD/farm/jobs/mission-control-1970s.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/farm/jobs/mission-control-1970s.json

## File: farm/pack.py
size: 1816
sha: 0dae6db76198c3bf99e02b82660a0627815fe4dd
upstream: https://github.com/apekshik/anyscene/blob/HEAD/farm/pack.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/farm/pack.py

## File: generate/concepts.sh
size: 2925
sha: 2d25cb59e2117808f35ef2a54a92208f9b930715
upstream: https://github.com/apekshik/anyscene/blob/HEAD/generate/concepts.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/generate/concepts.sh

## File: generate/fal.mjs
size: 9756
sha: 8a6ea546416f01a8887f366e8c19a6859dfd4746
upstream: https://github.com/apekshik/anyscene/blob/HEAD/generate/fal.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/generate/fal.mjs

## File: generate/gen3d.sh
size: 459
sha: cde8765fb6d0d227ed845a3e5b28ff1e533e8133
upstream: https://github.com/apekshik/anyscene/blob/HEAD/generate/gen3d.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/generate/gen3d.sh

## File: generate/models.mjs
size: 540
sha: c6e74464ba36da802ea4373f70131bb0898e6f77
upstream: https://github.com/apekshik/anyscene/blob/HEAD/generate/models.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/generate/models.mjs

## File: generate/props.sh
size: 2484
sha: a8cfa67b82f7f5a135097a78c332b8fbaa34f69d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/generate/props.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/generate/props.sh

## File: generate/samples.sh
size: 3311
sha: 28eb341598f97f1b37c46e54a389f19741c914dd
upstream: https://github.com/apekshik/anyscene/blob/HEAD/generate/samples.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/generate/samples.sh

## File: generate/schema.mjs
size: 1224
sha: 69e39238b6bc02e8366cfb89a21c929a16e3ad7f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/generate/schema.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/generate/schema.mjs

## File: LICENSE
size: 1075
sha: 197f55410b49744956cb69236d4d2c586973c7aa
upstream: https://github.com/apekshik/anyscene/blob/HEAD/LICENSE

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/LICENSE

## File: package-lock.json
size: 21129
sha: d87fabd7f21560c4d6e28e8b6456ed000c81efe4
upstream: https://github.com/apekshik/anyscene/blob/HEAD/package-lock.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/package-lock.json

## File: package.json
size: 674
sha: 0cc6b5352ee7083c4753de5c5577cf8f13faee0b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/package.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/package.json

## File: pipeline/build_compare_page.mjs
size: 11439
sha: f4917682a086917348582bc2926332068167740a
upstream: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/build_compare_page.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/build_compare_page.mjs

## File: pipeline/build_scenes_page.mjs
size: 31327
sha: ded8363808eff24acdeea9b0a7d115841691325c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/build_scenes_page.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/build_scenes_page.mjs

## File: pipeline/env.sh
size: 1198
sha: 79b7fd49df41308ef797bc5ccda048e5dfb63ceb
upstream: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/env.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/env.sh

## File: pipeline/gpu_run.sh
size: 1022
sha: a86c987f2bf62c9d93d5c97a54b27d30ac6d70be
upstream: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/gpu_run.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/gpu_run.sh

## File: pipeline/grounding.py
size: 5787
sha: c41d5a2652d52664d3dc9dd60f5fa437e8527817
upstream: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/grounding.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/grounding.py

## File: pipeline/lan_gallery.py
size: 6065
sha: d5c5f9685b9f6c50fb088e95833d5d751e5c8290
upstream: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/lan_gallery.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/lan_gallery.py

## File: pipeline/r2.mjs
size: 3946
sha: 77d6c7fec93dbff997ed84ba06db7686b537256c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/r2.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/r2.mjs

## File: pipeline/render_compare.py
size: 8215
sha: 6f94fc338129e576fd6add803e96efb54821dca7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/render_compare.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/pipeline/render_compare.py

## File: scenes/hk-dai-pai-dong/assets.json
size: 22288
sha: c7cae3696cf2f6361910f06fe70554ae5d5c04d0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/assets.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/assets.json

## File: scenes/hk-dai-pai-dong/brief.md
size: 3784
sha: 60e5edba9a91d6fcc07e42b09aa0698b4428747e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/brief.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/brief.md

## File: scenes/hk-dai-pai-dong/NOTES.md
size: 10853
sha: 9c700c9845d7acc5b92cbc0439141ff5983ab523
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/NOTES.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/NOTES.md

## File: scenes/hk-dai-pai-dong/picks.json
size: 10688
sha: 7db1776ded59ec46b1e6f591d744e43d62568022
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/picks.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/picks.json

## File: scenes/hk-dai-pai-dong/scripts/bake_steam.py
size: 1534
sha: 88896769eea9fd8bac3fe812e9c4f03c8f18a604
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/bake_steam.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/bake_steam.py

## File: scenes/hk-dai-pai-dong/scripts/blend.sh
size: 649
sha: 7ba629cc40a51bcc3be2652f4f731a83daec5075
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/blend.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/blend.sh

## File: scenes/hk-dai-pai-dong/scripts/bts.py
size: 12930
sha: 67bb5b45dae16b34414182d9e1569ba51c796046
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/bts.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/bts.py

## File: scenes/hk-dai-pai-dong/scripts/bts_clay_redo.sh
size: 715
sha: f856c1ff54e2a140961637cc8bd2c256dfbdc71a
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/bts_clay_redo.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/bts_clay_redo.sh

## File: scenes/hk-dai-pai-dong/scripts/bts_encode.sh
size: 1309
sha: f5b114578fe5ea941eec5f877cbf22d4567e5a83
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/bts_encode.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/bts_encode.sh

## File: scenes/hk-dai-pai-dong/scripts/build.py
size: 5912
sha: bcded739831c3afca5918c2d9732e44901191b32
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/build.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/build.py

## File: scenes/hk-dai-pai-dong/scripts/check_path.py
size: 1969
sha: 0bf38204ce3718da531ea8f84b1892e5a0773ded
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/check_path.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/check_path.py

## File: scenes/hk-dai-pai-dong/scripts/compare.py
size: 8081
sha: 4853f3e33e8415e0348e65519067a8dc8bfad655
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/compare.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/compare.py

## File: scenes/hk-dai-pai-dong/scripts/compare.sh
size: 1551
sha: f1ae0d268f395795824e51e5c75522b4fbb0744f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/compare.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/compare.sh

## File: scenes/hk-dai-pai-dong/scripts/dress.py
size: 23352
sha: 5e5d690c81040e155c4163194f2094c673fa54e6
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/dress.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/dress.py

## File: scenes/hk-dai-pai-dong/scripts/emitters.py
size: 1857
sha: d56e3e3c2fcb54fbe60f3131762f6b755d64cd36
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/emitters.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/emitters.py

## File: scenes/hk-dai-pai-dong/scripts/flame_try.py
size: 1688
sha: 4835e04336a84b71d73dacb68a063cbeed73e2f3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/flame_try.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/flame_try.py

## File: scenes/hk-dai-pai-dong/scripts/fx.py
size: 8104
sha: 9295ce51daf90b1f57f2d1c10b140693fbd5a5ac
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/fx.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/fx.py

## File: scenes/hk-dai-pai-dong/scripts/gen.mjs
size: 3223
sha: 0a2c9aeeef1cb14b95b0f950314e1d06e13a6a81
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/gen.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/gen.mjs

## File: scenes/hk-dai-pai-dong/scripts/gpu_prefs.py
size: 508
sha: 855f62858438336f66c1bada64a9459d7d5c8b9d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/gpu_prefs.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/gpu_prefs.py

## File: scenes/hk-dai-pai-dong/scripts/grade.sh
size: 1428
sha: 55d34a6cd53f53bcf4af249b87b2c995cd343ba3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/grade.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/grade.sh

## File: scenes/hk-dai-pai-dong/scripts/grime.py
size: 6094
sha: c30afd14e47079c7aa5e7ebc98fb8f69ecd297ab
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/grime.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/grime.py

## File: scenes/hk-dai-pai-dong/scripts/ground_stills.py
size: 2054
sha: 3b92d9d86c09902b9da18df45ec28aaa5a9a226d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/ground_stills.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/ground_stills.py

## File: scenes/hk-dai-pai-dong/scripts/lib.py
size: 17401
sha: 5cc580eaf763564a78d2983cc8ea44aea1a0bd14
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/lib.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/lib.py

## File: scenes/hk-dai-pai-dong/scripts/lights.py
size: 11255
sha: a291c89a55618872add76620b036944724dd5192
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/lights.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/lights.py

## File: scenes/hk-dai-pai-dong/scripts/manifest.py
size: 19134
sha: 7a1611d6c25504eb5e6525aa959377de23e95f63
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/manifest.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/manifest.py

## File: scenes/hk-dai-pai-dong/scripts/pick.mjs
size: 507
sha: db6bb58c581bb53946c24abd33858a4636a14921
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/pick.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/pick.mjs

## File: scenes/hk-dai-pai-dong/scripts/post.py
size: 1546
sha: aa8a025536c2859ef936282e4d589066c25cbbd6
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/post.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/post.py

## File: scenes/hk-dai-pai-dong/scripts/prep.py
size: 12523
sha: 181a1903afc9060eee9efc6ad2e401fd34c609af
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/prep.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/prep.py

## File: scenes/hk-dai-pai-dong/scripts/reel.sh
size: 1047
sha: f251a47d8e284a6f25cf5554a93e43cf750efda0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/reel.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/reel.sh

## File: scenes/hk-dai-pai-dong/scripts/render_bts.sh
size: 2517
sha: aa528c0b3c0a46142ee8a8b6b43f2404c05c57c9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/render_bts.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/render_bts.sh

## File: scenes/hk-dai-pai-dong/scripts/render_finals.sh
size: 1255
sha: 18df539e3897c46a7078d8d6f556ad929163a80d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/render_finals.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/render_finals.sh

## File: scenes/hk-dai-pai-dong/scripts/review.sh
size: 1062
sha: c1f2a70dd004ef37c967b873f04acc193b86311a
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/review.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/review.sh

## File: scenes/hk-dai-pai-dong/scripts/sheet.py
size: 1664
sha: abb7b695ca5a8504ba619b891d8c94f82d2dde30
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/sheet.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/sheet.py

## File: scenes/hk-dai-pai-dong/scripts/shell.py
size: 30423
sha: a56da1977914e82d3821239dbece3069500ec1a3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/shell.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/shell.py

## File: scenes/hk-dai-pai-dong/scripts/shoot.sh
size: 477
sha: bffa69a50e7189969d81f6ee64834a7e12b64047
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/shoot.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/shoot.sh

## File: scenes/hk-dai-pai-dong/scripts/steam.py
size: 7744
sha: a85cc1cbc08e886461b34995efcfb370c3aba866
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/steam.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/steam.py

## File: scenes/hk-dai-pai-dong/scripts/stills.py
size: 1077
sha: 031618a692ea977322dd334c1b959787976f58f5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/stills.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/stills.py

## File: scenes/hk-dai-pai-dong/scripts/validate.py
size: 7136
sha: 8c24f2724ff966ddb971e1d22e82a62e5da1da41
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/validate.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/scripts/validate.py

## File: scenes/hk-dai-pai-dong/shots.json
size: 6482
sha: 1b0df1ce39f5a19b782799d3a297b49e199e50a8
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/shots.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/hk-dai-pai-dong/shots.json

## File: scenes/mission-control-1970s/assets.json
size: 22493
sha: ab3d39aaefbeafb9dad0e3dfe8a50c9252adb8ce
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/assets.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/assets.json

## File: scenes/mission-control-1970s/brief.md
size: 3199
sha: 5083d9395b7d913eec7bdc112c4f7b09bf0e6083
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/brief.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/brief.md

## File: scenes/mission-control-1970s/NOTES.md
size: 9998
sha: 2a939dbabe3fa239ee59e529a831c27f302ebafc
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/NOTES.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/NOTES.md

## File: scenes/mission-control-1970s/picks.json
size: 9133
sha: 4e0d13568a8e60de3ee0920ae09f99c91ab311d2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/picks.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/picks.json

## File: scenes/mission-control-1970s/scripts/bts.py
size: 13206
sha: 1fd1f2378f286c3b439a7e22759233da7076c3c4
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/bts.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/bts.py

## File: scenes/mission-control-1970s/scripts/bts_render.sh
size: 1711
sha: 6143e5efabbdad5e8305aed80602aac1fce86c72
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/bts_render.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/bts_render.sh

## File: scenes/mission-control-1970s/scripts/build.py
size: 1883
sha: 2c66a3996db03b9d72f81395b7375b2affa3119f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/build.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/build.py

## File: scenes/mission-control-1970s/scripts/check_path.py
size: 1972
sha: 12504549faa165e30356ce5ac24a9aa83eb14eb4
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/check_path.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/check_path.py

## File: scenes/mission-control-1970s/scripts/compare.py
size: 8105
sha: 8b91487b4bcda6db7ed9ec45377d9447aa0a565b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/compare.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/compare.py

## File: scenes/mission-control-1970s/scripts/compare_batch.sh
size: 1003
sha: ad2e363c818b704d5df062650351168b32a8b7e8
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/compare_batch.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/compare_batch.sh

## File: scenes/mission-control-1970s/scripts/dress.py
size: 20779
sha: cfdac12445a2e66fd7c1c7ee290c8f7f25e718be
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/dress.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/dress.py

## File: scenes/mission-control-1970s/scripts/fixes.py
size: 9325
sha: 9ab22410497433e496eb9f8352d513500f022153
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/fixes.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/fixes.py

## File: scenes/mission-control-1970s/scripts/fixscreens.py
size: 6517
sha: d1f523c84d3d89e096e330d04d75b7db402ef2a0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/fixscreens.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/fixscreens.py

## File: scenes/mission-control-1970s/scripts/gen3d.mjs
size: 1528
sha: 2eb15046f5c62a23d322b2e6caa76fa909829605
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/gen3d.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/gen3d.mjs

## File: scenes/mission-control-1970s/scripts/gpu_prefs.py
size: 430
sha: 806545e7cc22c17d7da04b2276ef1da0de3cb815
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/gpu_prefs.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/gpu_prefs.py

## File: scenes/mission-control-1970s/scripts/grade.sh
size: 1003
sha: 97b3bcb52da05fa9e04af76a74f3508ca094076f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/grade.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/grade.sh

## File: scenes/mission-control-1970s/scripts/grime.py
size: 11356
sha: a4da73fc43387177bea98538d3ae4353c197ae27
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/grime.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/grime.py

## File: scenes/mission-control-1970s/scripts/haze.py
size: 4608
sha: 70042ff4e53d51e7d9aced72494034af022f7488
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/haze.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/haze.py

## File: scenes/mission-control-1970s/scripts/layout.py
size: 2033
sha: 7f9ea4c2e3a1e0d02b6c7a859cb7dc3cc4075ddd
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/layout.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/layout.py

## File: scenes/mission-control-1970s/scripts/lib.py
size: 14093
sha: 38b6bd8fe28d11b95cc32b3b3e9c01ce4d2506b2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/lib.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/lib.py

## File: scenes/mission-control-1970s/scripts/lights.py
size: 5182
sha: 4b9cf8f1350cae61ceefb975a58976070170e5b0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/lights.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/lights.py

## File: scenes/mission-control-1970s/scripts/lowcams.py
size: 1265
sha: 9337e269be634b86d5341449df841d37ac029572
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/lowcams.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/lowcams.py

## File: scenes/mission-control-1970s/scripts/nocurl.py
size: 333
sha: ad5032722719f4617916b9f0444e29eef7d92261
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/nocurl.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/nocurl.py

## File: scenes/mission-control-1970s/scripts/post.py
size: 2726
sha: f9fae59749ead75d716999519f1f23bb02b611a7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/post.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/post.py

## File: scenes/mission-control-1970s/scripts/prep.py
size: 5542
sha: 767681dd9d48d522fefb7e6b07e7553a7c5a96b5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/prep.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/prep.py

## File: scenes/mission-control-1970s/scripts/preview.py
size: 1848
sha: 08f1bcba0cbd4aecb57aeaccc027531bd0051772
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/preview.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/preview.py

## File: scenes/mission-control-1970s/scripts/prevsheet.sh
size: 771
sha: 333e0091ca7219f3468d48bd03fece5b9502ed7f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/prevsheet.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/prevsheet.sh

## File: scenes/mission-control-1970s/scripts/refs.mjs
size: 1965
sha: e6f66f88193778a665ef707e841e7517d6413097
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/refs.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/refs.mjs

## File: scenes/mission-control-1970s/scripts/refsheet.sh
size: 870
sha: c03837ffaaea9791e450db3ac5ee4389a2a9d38b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/refsheet.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/refsheet.sh

## File: scenes/mission-control-1970s/scripts/render_finals.sh
size: 1390
sha: e43415319c12f4d33db7d69edf906d647ffabf43
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/render_finals.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/render_finals.sh

## File: scenes/mission-control-1970s/scripts/screens.py
size: 17331
sha: 214ac2ec52faaf0d0cd79c51161d66180c9e0ec9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/screens.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/screens.py

## File: scenes/mission-control-1970s/scripts/sheet.sh
size: 1160
sha: 2ec52d120e0cbd09865703653486e7e831664a5f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/sheet.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/sheet.sh

## File: scenes/mission-control-1970s/scripts/shell.py
size: 12797
sha: e0b35305813a6464ad5b2fe6072c374e7bbe48c7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/shell.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/shell.py

## File: scenes/mission-control-1970s/scripts/shoot.sh
size: 550
sha: 6896c1dcd438202a8182a1a79d49a362c4f0ad95
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/shoot.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/shoot.sh

## File: scenes/mission-control-1970s/scripts/validate.py
size: 10148
sha: 051080e27723ef9e0f071f60bdf54620c0f2d38b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/validate.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/scripts/validate.py

## File: scenes/mission-control-1970s/shots.json
size: 6725
sha: bea9e3d7a91b988d1e551643977e7c3eb858113c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/shots.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/mission-control-1970s/shots.json

## File: scenes/tokyo-electronics-repair/assets.json
size: 33601
sha: 2a61585f403a560d49eee7355a342c8701860500
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/assets.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/assets.json

## File: scenes/tokyo-electronics-repair/nb_swap.json
size: 760
sha: 5014c1c08f68979eb9fdc6812e1d086fb213644d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/nb_swap.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/nb_swap.json

## File: scenes/tokyo-electronics-repair/NOTES.md
size: 7957
sha: fdb85d72de86166112f42191cb849fcc961bd103
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/NOTES.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/NOTES.md

## File: scenes/tokyo-electronics-repair/picks.json
size: 12690
sha: 244a7fa786d1441a1dd70e8a4b406e348d6d7645
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/picks.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/picks.json

## File: scenes/tokyo-electronics-repair/scripts/bts.py
size: 16567
sha: a6300fb37fdfa9f1fef884904fce8853bf3471ed
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/bts.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/bts.py

## File: scenes/tokyo-electronics-repair/scripts/bts_render.sh
size: 1702
sha: 92da2e8f066ec826752ba3bbc715e899fedb3d07
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/bts_render.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/bts_render.sh

## File: scenes/tokyo-electronics-repair/scripts/build_shell.py
size: 15157
sha: 8661875f62e2fa05ff62f3a043152d780f8c9086
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/build_shell.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/build_shell.py

## File: scenes/tokyo-electronics-repair/scripts/cameras.py
size: 3569
sha: 17a04847af51fd3bda155b630e2aefb6f905d5bd
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/cameras.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/cameras.py

## File: scenes/tokyo-electronics-repair/scripts/check_path.py
size: 1945
sha: 09db36f506ae6b7629cd269e2607bf47baa85ee2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/check_path.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/check_path.py

## File: scenes/tokyo-electronics-repair/scripts/compare.py
size: 8422
sha: 358791f197345ed83407d1de65f27bc9de77802c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/compare.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/compare.py

## File: scenes/tokyo-electronics-repair/scripts/compare_ready.sh
size: 536
sha: 7d1c0f5e176ea3a6e37d2e55f61a1d05f19f5a5d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/compare_ready.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/compare_ready.sh

## File: scenes/tokyo-electronics-repair/scripts/debrand.py
size: 10218
sha: 2a0b9bc23647c4cf972898ca1bd0ac9107595794
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/debrand.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/debrand.py

## File: scenes/tokyo-electronics-repair/scripts/dress.py
size: 11873
sha: f22d4ea7900d059047668dda7872dc3987ef17b2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/dress.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/dress.py

## File: scenes/tokyo-electronics-repair/scripts/dress2.py
size: 62243
sha: 54e3ffa39b50c898e55919e2103d9296d7992796
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/dress2.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/dress2.py

## File: scenes/tokyo-electronics-repair/scripts/fixes.py
size: 11010
sha: d07b010e39141f45ac4146f9bb9e826894f68977
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/fixes.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/fixes.py

## File: scenes/tokyo-electronics-repair/scripts/gen3d.mjs
size: 1485
sha: 327417211ff9bb3796afd08d57b2ffd920be33e8
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/gen3d.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/gen3d.mjs

## File: scenes/tokyo-electronics-repair/scripts/gpu_prefs.py
size: 430
sha: 806545e7cc22c17d7da04b2276ef1da0de3cb815
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/gpu_prefs.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/gpu_prefs.py

## File: scenes/tokyo-electronics-repair/scripts/grade.sh
size: 987
sha: 71c0cbb2e428ca08a4619e8a5b82a7d6a176c146
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/grade.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/grade.sh

## File: scenes/tokyo-electronics-repair/scripts/grime.py
size: 13875
sha: 3854959bb3638262fa213a408430725f2c01afc8
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/grime.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/grime.py

## File: scenes/tokyo-electronics-repair/scripts/lib.py
size: 14093
sha: 38b6bd8fe28d11b95cc32b3b3e9c01ce4d2506b2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/lib.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/lib.py

## File: scenes/tokyo-electronics-repair/scripts/lights.py
size: 9770
sha: a043e8ddfa0938a92dfcb17bef2832a3afc74e2e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/lights.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/lights.py

## File: scenes/tokyo-electronics-repair/scripts/prep.py
size: 4568
sha: e9d43e17a5e9ea34b1d241c3671bf0129a5ee4d9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/prep.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/prep.py

## File: scenes/tokyo-electronics-repair/scripts/preview.py
size: 2226
sha: 4ff88293dc729262a3fe3e3efc41f2c6cfeb8845
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/preview.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/preview.py

## File: scenes/tokyo-electronics-repair/scripts/rebuild.sh
size: 1080
sha: 295f96d66209990a1b4b58e0534a47ab31d32d50
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/rebuild.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/rebuild.sh

## File: scenes/tokyo-electronics-repair/scripts/rebuild2.sh
size: 1910
sha: 4264a07258ad3cbbe55ae4b2606a7991ea717bcd
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/rebuild2.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/rebuild2.sh

## File: scenes/tokyo-electronics-repair/scripts/refs.mjs
size: 1563
sha: 2c100b326f8a5fae6958f3a7892ccc6930513063
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/refs.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/refs.mjs

## File: scenes/tokyo-electronics-repair/scripts/render_clip.sh
size: 748
sha: c9369456849818f1ae505fbeb59d9e4439450c18
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/render_clip.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/render_clip.sh

## File: scenes/tokyo-electronics-repair/scripts/render_finals.sh
size: 1445
sha: 196ff5d987f58301898ed763956ce72d0753a4fe
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/render_finals.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/render_finals.sh

## File: scenes/tokyo-electronics-repair/scripts/render_frames.py
size: 1380
sha: 713a1733db72b2db86c0dcbb3b4be5b6b262175d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/render_frames.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/render_frames.py

## File: scenes/tokyo-electronics-repair/scripts/render_round2.sh
size: 2150
sha: a9e450651e3df6f12e26b5b9630cd303eebcac09
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/render_round2.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/render_round2.sh

## File: scenes/tokyo-electronics-repair/scripts/round2_manifest.mjs
size: 9758
sha: 4ca8a3a90d398fc7e12b20c9d32118d326e49205
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/round2_manifest.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/round2_manifest.mjs

## File: scenes/tokyo-electronics-repair/scripts/sheet.sh
size: 1419
sha: c5e4053c791b3bc7c1be3b0969998eafaf3691c7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/sheet.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/sheet.sh

## File: scenes/tokyo-electronics-repair/scripts/shoot.sh
size: 508
sha: fe086f87d4a3dd4bdd522a4d976033c087a9c4a1
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/shoot.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/shoot.sh

## File: scenes/tokyo-electronics-repair/scripts/validate.py
size: 4814
sha: c498c4c47631729f38d95674bde3a7ae6047f532
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/validate.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/validate.py

## File: scenes/tokyo-electronics-repair/scripts/views.py
size: 2963
sha: e596c45494af841cb4439c1106ced73962eadf1f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/views.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/scripts/views.py

## File: scenes/tokyo-electronics-repair/shots.json
size: 8863
sha: 09a987479af79926e3c5f7a4889cb4868899550a
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/shots.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-electronics-repair/shots.json

## File: scenes/tokyo-ramen-shop/assets.json
size: 31113
sha: 0a1c86bb80e81c29d90714c4deaec3cf386948b9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/assets.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/assets.json

## File: scenes/tokyo-ramen-shop/NOTES.md
size: 7925
sha: 0d77a8727b7b170b4864a58bb65ec2c7cc760bd1
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/NOTES.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/NOTES.md

## File: scenes/tokyo-ramen-shop/picks.json
size: 10522
sha: 3b6d21599ade5986c8b6a52af0d26e307869311d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/picks.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/picks.json

## File: scenes/tokyo-ramen-shop/round2.json
size: 13057
sha: f67a44aaa4ffae36e23ccd3a305cd843f12723c5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/round2.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/round2.json

## File: scenes/tokyo-ramen-shop/scripts/add_nb.mjs
size: 4339
sha: 8fa8a63c4b4b99670cd7495efd64b4f6e49a1164
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/add_nb.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/add_nb.mjs

## File: scenes/tokyo-ramen-shop/scripts/bake_steam.py
size: 1534
sha: 88896769eea9fd8bac3fe812e9c4f03c8f18a604
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/bake_steam.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/bake_steam.py

## File: scenes/tokyo-ramen-shop/scripts/bts.py
size: 15164
sha: 1b6df84f18564b666312c9b9f2eed9e3f592e9fc
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/bts.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/bts.py

## File: scenes/tokyo-ramen-shop/scripts/build.py
size: 8481
sha: 11b611df85f0a5127ec97425d8be892b3b456792
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/build.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/build.py

## File: scenes/tokyo-ramen-shop/scripts/camcheck.py
size: 2535
sha: c5ddbb93576c817509beccc7b5453cb36eee5154
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/camcheck.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/camcheck.py

## File: scenes/tokyo-ramen-shop/scripts/camera.py
size: 2240
sha: 4df6f7f7458b464f1c739ad8d94d3d44b869a221
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/camera.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/camera.py

## File: scenes/tokyo-ramen-shop/scripts/clutter.py
size: 23695
sha: da865ccfd14e5a388adf76ae31abfae6ecd6433b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/clutter.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/clutter.py

## File: scenes/tokyo-ramen-shop/scripts/compare.py
size: 8425
sha: 322696f2091dbd8ce84648e3cf98a221286b375f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/compare.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/compare.py

## File: scenes/tokyo-ramen-shop/scripts/compare_rest.sh
size: 978
sha: 31c7bb6dc7637ebad3036ed14ae4a596604865b8
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/compare_rest.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/compare_rest.sh

## File: scenes/tokyo-ramen-shop/scripts/dress.py
size: 17943
sha: 8d3d4d6e1db926e011cefc2ffb2573a6ffbb4244
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/dress.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/dress.py

## File: scenes/tokyo-ramen-shop/scripts/emitters.py
size: 1857
sha: d56e3e3c2fcb54fbe60f3131762f6b755d64cd36
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/emitters.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/emitters.py

## File: scenes/tokyo-ramen-shop/scripts/exterior.py
size: 9964
sha: 88b765c8ebab744dc9bf8dbda32a6a35172dc484
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/exterior.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/exterior.py

## File: scenes/tokyo-ramen-shop/scripts/finals_gen.sh
size: 1646
sha: 669880932b298abd65a1c95bce9234704d569a07
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/finals_gen.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/finals_gen.sh

## File: scenes/tokyo-ramen-shop/scripts/finals_r2.sh
size: 548
sha: 8d99d66f24c90775889143eea67907ba56a918bc
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/finals_r2.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/finals_r2.sh

## File: scenes/tokyo-ramen-shop/scripts/finish.sh
size: 875
sha: 9b2f64802794a99eed262c6e46b9f1f62cad60cc
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/finish.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/finish.sh

## File: scenes/tokyo-ramen-shop/scripts/finish_r2.sh
size: 1571
sha: 1db549de4bbfbc570cdf3d91a278e0ea03568082
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/finish_r2.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/finish_r2.sh

## File: scenes/tokyo-ramen-shop/scripts/gen.mjs
size: 3070
sha: 51cd531939dea5f3baaa3cb8d3b9ea8b40b0bde1
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/gen.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/gen.mjs

## File: scenes/tokyo-ramen-shop/scripts/gpu_prefs.py
size: 508
sha: 855f62858438336f66c1bada64a9459d7d5c8b9d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/gpu_prefs.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/gpu_prefs.py

## File: scenes/tokyo-ramen-shop/scripts/grime.py
size: 8336
sha: 340f1cdcd47554ac1cb804e8a3c502641337677b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/grime.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/grime.py

## File: scenes/tokyo-ramen-shop/scripts/heroes_r2.sh
size: 517
sha: 5bc5a35438ba370f869cfb2d70ddc42de9263382
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/heroes_r2.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/heroes_r2.sh

## File: scenes/tokyo-ramen-shop/scripts/lib.py
size: 17403
sha: 86c49d178739c6c1e62ad5cb1f944a45654cbd9b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/lib.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/lib.py

## File: scenes/tokyo-ramen-shop/scripts/lighting.py
size: 4987
sha: d914f0014139cdfe9eec6f51b8617b03c736dea5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/lighting.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/lighting.py

## File: scenes/tokyo-ramen-shop/scripts/pick.mjs
size: 508
sha: d98e3df85ae1c3af514de613adf987e8e6bdb1f3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/pick.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/pick.mjs

## File: scenes/tokyo-ramen-shop/scripts/post.py
size: 1372
sha: 49e1caa770b5e3d9548e582c6d5791d18a0daa2d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/post.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/post.py

## File: scenes/tokyo-ramen-shop/scripts/prep.py
size: 11718
sha: 609244e273f8ae9632af835d7d9de92be37286ed
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/prep.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/prep.py

## File: scenes/tokyo-ramen-shop/scripts/process_r2.sh
size: 914
sha: 3ed03b90b03c724e982066d09508808c3416add6
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/process_r2.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/process_r2.sh

## File: scenes/tokyo-ramen-shop/scripts/r2gen.py
size: 12660
sha: 0064d7a41463a98dc97606903eca0f2c6d1523d3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/r2gen.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/r2gen.py

## File: scenes/tokyo-ramen-shop/scripts/rebuild.sh
size: 872
sha: 2b66b952b9145bb2b4720e3b32627380dbdb5148
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/rebuild.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/rebuild.sh

## File: scenes/tokyo-ramen-shop/scripts/render.py
size: 2287
sha: baa5a518bdcee4f6a1a717f195c0b0aa6d47be16
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/render.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/render.py

## File: scenes/tokyo-ramen-shop/scripts/render_bts.sh
size: 2644
sha: bc49a4cb7b6b889c5b56d161a7ebe658b20c574d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/render_bts.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/render_bts.sh

## File: scenes/tokyo-ramen-shop/scripts/render_clip.sh
size: 616
sha: 113e761a7a92d2059274754c169e1c2260e66e76
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/render_clip.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/render_clip.sh

## File: scenes/tokyo-ramen-shop/scripts/review.sh
size: 994
sha: 09e391a4cca3aa2dd9e50c10a01c8d10be9c7def
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/review.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/review.sh

## File: scenes/tokyo-ramen-shop/scripts/shell.py
size: 13938
sha: 1db096afeb8f5292c23cb38dbb62172cf878d139
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/shell.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/shell.py

## File: scenes/tokyo-ramen-shop/scripts/shots_r2.sh
size: 990
sha: b8ba736ff2dfa7772d1a5a8bf3c3336e153755a5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/shots_r2.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/shots_r2.sh

## File: scenes/tokyo-ramen-shop/scripts/steam.py
size: 7744
sha: a85cc1cbc08e886461b34995efcfb370c3aba866
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/steam.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/steam.py

## File: scenes/tokyo-ramen-shop/scripts/validate.py
size: 3700
sha: 4a65aa3b936f80ec58444a02da2aaca57fd5558d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/validate.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/scripts/validate.py

## File: scenes/tokyo-ramen-shop/shots.json
size: 10709
sha: e41322390f30b039a8f04414afbcf3a7b2c954c2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/shots.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/scenes/tokyo-ramen-shop/shots.json

## File: unreal/agx_view.py
size: 745
sha: 870bf9e98dc33cc0a5024d7a0c96e84985ac6615
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/agx_view.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/agx_view.py

## File: unreal/build_level.py
size: 83363
sha: 03dc2d04ff43938bdc735232868d41027817424d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/build_level.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/build_level.py

## File: unreal/CHANGELOG.md
size: 11457
sha: a150fa6e6672c832912d6b0d07f15a398f2e732e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/CHANGELOG.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/CHANGELOG.md

## File: unreal/csv_summary.sh
size: 1015
sha: 1a3f187328c07c2b083d8a1cfda5e12c5faaef4e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/csv_summary.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/csv_summary.sh

## File: unreal/export.sh
size: 1696
sha: e8e814d7b39d906d3a5028c5bfa8b23596cbbddb
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/export.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/export.sh

## File: unreal/export_blend.py
size: 78369
sha: 680f5e6848575a73264d663ae93ae7eee4b88512
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/export_blend.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/export_blend.py

## File: unreal/FX_AGENT.md
size: 7100
sha: aa0e595018ec03526b6b5eb74ae198da140216ea
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/FX_AGENT.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/FX_AGENT.md

## File: unreal/fx_export.py
size: 37628
sha: 5335d032482f9b2b25427440bfd43738e079dcb9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_export.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_export.py

## File: unreal/fx_pack.py
size: 33393
sha: 74d14d19478ab10906df2e1c48aad4b4bd494516
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_pack.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_pack.py

## File: unreal/fx_recipes/NS_Drips.json
size: 694
sha: 372a30714138f5aa99ff2148e2398fc0049cc0ce
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Drips.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Drips.json

## File: unreal/fx_recipes/NS_DustMotes.json
size: 633
sha: 25f0a2bf724247d752ac468233fc3e1792828200
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_DustMotes.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_DustMotes.json

## File: unreal/fx_recipes/NS_Fire.json
size: 5261
sha: 0b3f18fcb9465806e86b4361f949cee3b96aec20
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Fire.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Fire.json

## File: unreal/fx_recipes/NS_FountainJet.json
size: 769
sha: 6cf641829330a8178bcd98eaa229ba1a07bb3d49
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_FountainJet.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_FountainJet.json

## File: unreal/fx_recipes/NS_Rain.json
size: 708
sha: 6d1b850124e03ea6df93912a764945e326ebe3a8
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Rain.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Rain.json

## File: unreal/fx_recipes/NS_Smoke.json
size: 686
sha: 6fd6c6f4371443c11e275fc0be72d6254fac2aff
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Smoke.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Smoke.json

## File: unreal/fx_recipes/NS_Sparks.json
size: 1157
sha: 176d6d6bb75de7673839e63091823313ee14bd2b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Sparks.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Sparks.json

## File: unreal/fx_recipes/NS_Steam.json
size: 702
sha: 37501e58c53ccf3a2bd44b9edee03241795bb12c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Steam.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fx_recipes/NS_Steam.json

## File: unreal/fxlib.py
size: 1450
sha: b2c744ce4c28de4a28ae77fae23a08bfa3194f62
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fxlib.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/fxlib.py

## File: unreal/make_copy.py
size: 641
sha: 0a0063e9b916754ac2d99641a350a0415d3375d7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/make_copy.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/make_copy.py

## File: unreal/NIAGARA.md
size: 54723
sha: 72bd5cb705faadde7c5e6e826130a071ef902d00
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/NIAGARA.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/NIAGARA.md

## File: unreal/perf.ps1
size: 3002
sha: 75216fc4b78f2a4d8fbdf7a764c3bd44ef080803
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/perf.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/perf.ps1

## File: unreal/render_mrq.ps1
size: 1751
sha: 322b5b43f8d1f3a046097b1288dbd098a59a26d4
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/render_mrq.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/render_mrq.ps1

## File: unreal/render_shots.py
size: 9337
sha: 0d38457918ddc9d191824b9c50b7db9903f2692b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/render_shots.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/render_shots.py

## File: unreal/side_by_side.py
size: 2245
sha: 21ba7e3909b4c0276f7aee5d08180cfe8415668d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/side_by_side.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/side_by_side.py

## File: unreal/templates.json
size: 6207
sha: f2472655fcdef57105d5a8612fc6eab52d007545
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/templates.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/templates.json

## File: unreal/templates_report.json
size: 18880
sha: 4258677bc65fcb32c9311aa0a1fb414ae381711d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/templates_report.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/templates_report.json

## File: unreal/TOGGLE.md
size: 10997
sha: ccde40090d9a8933ea1e8148628b7b39baad9812
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal/TOGGLE.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal/TOGGLE.md

## File: unreal_bakery/_orig/agx_view.py
size: 745
sha: 870bf9e98dc33cc0a5024d7a0c96e84985ac6615
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/agx_view.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/agx_view.py

## File: unreal_bakery/_orig/build_level.py
size: 33429
sha: 66897bb9bfe15606177d6a417b256fd3a802bd12
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/build_level.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/build_level.py

## File: unreal_bakery/_orig/csv_summary.sh
size: 1015
sha: 1a3f187328c07c2b083d8a1cfda5e12c5faaef4e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/csv_summary.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/csv_summary.sh

## File: unreal_bakery/_orig/export.sh
size: 1377
sha: 92e1f3fa66fbe1014a64be3d162b560effb8698d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/export.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/export.sh

## File: unreal_bakery/_orig/export_blend.py
size: 44264
sha: 89ff833e78773422c560e714f9661ff6e80b36ac
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/export_blend.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/export_blend.py

## File: unreal_bakery/_orig/make_copy.py
size: 641
sha: 0a0063e9b916754ac2d99641a350a0415d3375d7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/make_copy.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/make_copy.py

## File: unreal_bakery/_orig/perf.ps1
size: 2745
sha: a601daf811a2a809b406eabe44656e510510e037
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/perf.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/perf.ps1

## File: unreal_bakery/_orig/render_mrq.ps1
size: 1099
sha: 841229aee3a69454c9070b2ceb39850cc1edc8b9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/render_mrq.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/render_mrq.ps1

## File: unreal_bakery/_orig/render_shots.py
size: 9337
sha: 0d38457918ddc9d191824b9c50b7db9903f2692b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/render_shots.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/render_shots.py

## File: unreal_bakery/_orig/side_by_side.py
size: 1832
sha: e55eddd506c31032358af5afb7a2838f8dfbf823
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/side_by_side.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/_orig/side_by_side.py

## File: unreal_bakery/agx_view.py
size: 745
sha: 870bf9e98dc33cc0a5024d7a0c96e84985ac6615
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/agx_view.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/agx_view.py

## File: unreal_bakery/build_level.py
size: 35010
sha: e9e810556ee02d9043dedc3c2904e5f53c829889
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/build_level.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/build_level.py

## File: unreal_bakery/csv_summary.sh
size: 1015
sha: 1a3f187328c07c2b083d8a1cfda5e12c5faaef4e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/csv_summary.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/csv_summary.sh

## File: unreal_bakery/export.sh
size: 1377
sha: 92e1f3fa66fbe1014a64be3d162b560effb8698d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/export.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/export.sh

## File: unreal_bakery/export_blend.py
size: 44480
sha: afb8c1c7d9101cbb03f3abc23e43f439940da99e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/export_blend.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/export_blend.py

## File: unreal_bakery/make_copy.py
size: 641
sha: 0a0063e9b916754ac2d99641a350a0415d3375d7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/make_copy.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/make_copy.py

## File: unreal_bakery/NIAGARA.md
size: 54723
sha: 72bd5cb705faadde7c5e6e826130a071ef902d00
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/NIAGARA.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/NIAGARA.md

## File: unreal_bakery/perf.ps1
size: 2992
sha: 4aeb4b4c6b3a4547ca052bf9d350c88eba062bba
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/perf.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/perf.ps1

## File: unreal_bakery/render_mrq.ps1
size: 1215
sha: caa346af4d88408e4ae43b8a4c65a4a3ff4d584b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/render_mrq.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/render_mrq.ps1

## File: unreal_bakery/render_shots.py
size: 9337
sha: 0d38457918ddc9d191824b9c50b7db9903f2692b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/render_shots.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/render_shots.py

## File: unreal_bakery/side_by_side.py
size: 2206
sha: eba72156e3d47b9fb93cdb40a04d4b31f685c7f4
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/side_by_side.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/side_by_side.py

## File: unreal_bakery/TOGGLE.md
size: 10997
sha: ccde40090d9a8933ea1e8148628b7b39baad9812
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/TOGGLE.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_bakery/TOGGLE.md

## File: unreal_caustic/agx_view.py
size: 745
sha: 870bf9e98dc33cc0a5024d7a0c96e84985ac6615
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/agx_view.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/agx_view.py

## File: unreal_caustic/build_level.py
size: 58169
sha: 7668193409abed5c61f8bf54533cb3b1fcd2dd5f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/build_level.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/build_level.py

## File: unreal_caustic/csv_summary.sh
size: 1015
sha: 1a3f187328c07c2b083d8a1cfda5e12c5faaef4e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/csv_summary.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/csv_summary.sh

## File: unreal_caustic/export.sh
size: 1492
sha: 990ac5293ac2c1ca87ee83601044400c04fced20
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/export.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/export.sh

## File: unreal_caustic/export_blend.py
size: 57970
sha: 41fb36bed0f93da7f4dd3b20e9dd8d57cf8fda19
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/export_blend.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/export_blend.py

## File: unreal_caustic/make_copy.py
size: 641
sha: 0a0063e9b916754ac2d99641a350a0415d3375d7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/make_copy.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/make_copy.py

## File: unreal_caustic/MERGE_BACK.patch
size: 56074
sha: 7868bc0d399c6725724204a1a209a311e7943488
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/MERGE_BACK.patch

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/MERGE_BACK.patch

## File: unreal_caustic/NIAGARA.md
size: 54723
sha: 72bd5cb705faadde7c5e6e826130a071ef902d00
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/NIAGARA.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/NIAGARA.md

## File: unreal_caustic/perf.ps1
size: 2881
sha: 35d417afae423c304e6dea1244b2e9de955f8ef4
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/perf.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/perf.ps1

## File: unreal_caustic/render_cycles_refs.py
size: 2869
sha: 38c9425e6d4a1ff8db93a77f975dd3a826658740
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/render_cycles_refs.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/render_cycles_refs.py

## File: unreal_caustic/render_mrq.ps1
size: 1505
sha: f7b961aee9ed6a6bb9ff2ec7c966e52f2387fb11
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/render_mrq.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/render_mrq.ps1

## File: unreal_caustic/render_shots.py
size: 9337
sha: 0d38457918ddc9d191824b9c50b7db9903f2692b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/render_shots.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/render_shots.py

## File: unreal_caustic/run_chamber.sh
size: 2189
sha: ab3a46d1b4dafbd3e988459e2b2a33e84d34a67e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/run_chamber.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/run_chamber.sh

## File: unreal_caustic/scene_defaults.patch
size: 4728
sha: b4de3e24b25e0393458c5ca104b2c386af16e5c6
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/scene_defaults.patch

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/scene_defaults.patch

## File: unreal_caustic/side_by_side.py
size: 2222
sha: 00cb893a779f9ec14ced22deb263826a4c26e1d2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/side_by_side.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/side_by_side.py

## File: unreal_caustic/TOGGLE.md
size: 10997
sha: ccde40090d9a8933ea1e8148628b7b39baad9812
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/TOGGLE.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_caustic/TOGGLE.md

## File: unreal_demo/bake_cams.py
size: 3625
sha: 90c0787421d5d9e0731d5a4f776260aa1724a510
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/bake_cams.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/bake_cams.py

## File: unreal_demo/cams/h1_walk_in_to_wok.json
size: 310783
sha: 1205f1e9774370672683339c0bb97a5665e3af14
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/h1_walk_in_to_wok.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/h1_walk_in_to_wok.json

## File: unreal_demo/cams/h2_walk_tables_neon.json
size: 257953
sha: acd347c89170a88abb9320a69c3703d9cdd63925
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/h2_walk_tables_neon.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/h2_walk_tables_neon.json

## File: unreal_demo/cams/s1_street_crane.json
size: 75581
sha: fd6c9f2285704abab7aa768778a6a072ce178615
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/s1_street_crane.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/s1_street_crane.json

## File: unreal_demo/cams/s2_teapot_wok_rack.json
size: 89833
sha: 9f4400a9585d5947d9d32533288f6f3d2e60d986
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/s2_teapot_wok_rack.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/s2_teapot_wok_rack.json

## File: unreal_demo/cams/s3_wok_push.json
size: 60437
sha: d74d00622dfc83e246cbbe5a03c7e41f524aea3e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/s3_wok_push.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/s3_wok_push.json

## File: unreal_demo/cams/s4_neon_tilt.json
size: 76441
sha: aa3880c15ace7e105bcac66afdb424fbf211d5c7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/s4_neon_tilt.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/cams/s4_neon_tilt.json

## File: unreal_demo/check_match.py
size: 3339
sha: ccd2ddf30f625e05eaf4d9b6da4e4628a7e9b027
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/check_match.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/check_match.py

## File: unreal_demo/demo_cut.py
size: 9863
sha: f7588d620d9caff3bd3818436c648fdcfd4bc63f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/demo_cut.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/demo_cut.py

## File: unreal_demo/make_seqs.py
size: 8695
sha: 91db9a339d2a14365e8e5dc2d82a32e2577ead69
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/make_seqs.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/make_seqs.py

## File: unreal_demo/render.sh
size: 1386
sha: 3f969714a9c572c14a37c41ca418d19d5afbc2ec
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/render.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_demo/render.sh

## File: unreal_fal/agx_view.py
size: 745
sha: 870bf9e98dc33cc0a5024d7a0c96e84985ac6615
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/agx_view.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/agx_view.py

## File: unreal_fal/app.py
size: 37894
sha: 8e8c8753c6d643833e5932556f3bc44ae174c784
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/app.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/app.py

## File: unreal_fal/build_level.py
size: 33640
sha: 7b0892dff205f48c762a3085f3e6dbb13186c698
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/build_level.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/build_level.py

## File: unreal_fal/client.py
size: 2946
sha: 386186328e0f4b2a1eaad72136081e33d698ddab
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/client.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/client.py

## File: unreal_fal/export_blend.py
size: 61003
sha: 9bbd45e684a51f6b794f5a874b8f5fbd679a3e39
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/export_blend.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/export_blend.py

## File: unreal_fal/make_copy.py
size: 641
sha: 0a0063e9b916754ac2d99641a350a0415d3375d7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/make_copy.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/make_copy.py

## File: unreal_fal/render_shots.py
size: 9337
sha: 0d38457918ddc9d191824b9c50b7db9903f2692b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/render_shots.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/render_shots.py

## File: unreal_fal/side_by_side.py
size: 1832
sha: e55eddd506c31032358af5afb7a2838f8dfbf823
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/side_by_side.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal/side_by_side.py

## File: unreal_fal_ue/app.py
size: 22954
sha: 79ca3fe38b458dbcc8dd51b96622e787b18010eb
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/app.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/app.py

## File: unreal_fal_ue/build_level.py
size: 34052
sha: d43da05117b5265c4418a7d3d9d2da0bc8370260
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/build_level.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/build_level.py

## File: unreal_fal_ue/mrq_config.py
size: 2879
sha: ebe79abdbb866130979a339abc9ad5d225a595b1
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/mrq_config.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/mrq_config.py

## File: unreal_fal_ue/render_mrq.ps1
size: 1099
sha: 841229aee3a69454c9070b2ceb39850cc1edc8b9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/render_mrq.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/render_mrq.ps1

## File: unreal_fal_ue/render_shots.py
size: 9337
sha: 0d38457918ddc9d191824b9c50b7db9903f2692b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/render_shots.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/render_shots.py

## File: unreal_fal_ue/smoke_shot.py
size: 2281
sha: ef39acfc2ee41e445648d57be0febc5e3a0914a0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/smoke_shot.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/smoke_shot.py

## File: unreal_fal_ue/template/AnySceneUE.uproject
size: 364
sha: 01b7dc2ad8a0eeada5be8fe1c2c19503bcc1bf3c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/template/AnySceneUE.uproject

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/template/AnySceneUE.uproject

## File: unreal_fal_ue/template/Config/DefaultEngine.ini
size: 1155
sha: 8f5848d1288b2bb151bfa13be0e220bd55b24b3f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/template/Config/DefaultEngine.ini

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/template/Config/DefaultEngine.ini

## File: unreal_fal_ue/template/Config/DefaultGame.ini
size: 71
sha: b33dbf3c1ebe16c4e0a69f57116181fa6946ac24
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/template/Config/DefaultGame.ini

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/template/Config/DefaultGame.ini

## File: unreal_fal_ue/TOGGLE.md
size: 10997
sha: ccde40090d9a8933ea1e8148628b7b39baad9812
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/TOGGLE.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/TOGGLE.md

## File: unreal_fal_ue/tools/call.py
size: 1608
sha: 86591ad23ff44ad235dc62dc20696210a7788b2f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/tools/call.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/tools/call.py

## File: unreal_fal_ue/tools/fetch.py
size: 1164
sha: 9ef22c13088bcd2bb5a841b0b6b275c14c9c590b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/tools/fetch.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/tools/fetch.py

## File: unreal_fal_ue/tools/upload_export.py
size: 971
sha: 3055094e7031c51bb8a382bdeb867c360222f9ac
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/tools/upload_export.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fal_ue/tools/upload_export.py

## File: unreal_fx/agx_view.py
size: 745
sha: 870bf9e98dc33cc0a5024d7a0c96e84985ac6615
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/agx_view.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/agx_view.py

## File: unreal_fx/build_level.py
size: 40570
sha: 176a9e9eb9d404ef882f06c09e1a1f7a02a47cbc
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/build_level.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/build_level.py

## File: unreal_fx/CHANGES.md
size: 6449
sha: 6e4521fb88e60dfe729ea85e025c71ea7d134a80
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/CHANGES.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/CHANGES.md

## File: unreal_fx/export_blend.py
size: 44264
sha: 89ff833e78773422c560e714f9661ff6e80b36ac
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/export_blend.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/export_blend.py

## File: unreal_fx/FX_AGENT.md
size: 7100
sha: aa0e595018ec03526b6b5eb74ae198da140216ea
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/FX_AGENT.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/FX_AGENT.md

## File: unreal_fx/fx_export.py
size: 37628
sha: 5335d032482f9b2b25427440bfd43738e079dcb9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_export.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_export.py

## File: unreal_fx/fx_pack.py
size: 33393
sha: 74d14d19478ab10906df2e1c48aad4b4bd494516
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_pack.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_pack.py

## File: unreal_fx/fx_recipes/NS_Drips.json
size: 694
sha: 372a30714138f5aa99ff2148e2398fc0049cc0ce
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Drips.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Drips.json

## File: unreal_fx/fx_recipes/NS_DustMotes.json
size: 633
sha: 25f0a2bf724247d752ac468233fc3e1792828200
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_DustMotes.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_DustMotes.json

## File: unreal_fx/fx_recipes/NS_Fire.json
size: 5261
sha: 0b3f18fcb9465806e86b4361f949cee3b96aec20
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Fire.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Fire.json

## File: unreal_fx/fx_recipes/NS_FountainJet.json
size: 769
sha: 6cf641829330a8178bcd98eaa229ba1a07bb3d49
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_FountainJet.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_FountainJet.json

## File: unreal_fx/fx_recipes/NS_Rain.json
size: 708
sha: 6d1b850124e03ea6df93912a764945e326ebe3a8
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Rain.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Rain.json

## File: unreal_fx/fx_recipes/NS_Smoke.json
size: 686
sha: 6fd6c6f4371443c11e275fc0be72d6254fac2aff
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Smoke.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Smoke.json

## File: unreal_fx/fx_recipes/NS_Sparks.json
size: 1157
sha: 176d6d6bb75de7673839e63091823313ee14bd2b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Sparks.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Sparks.json

## File: unreal_fx/fx_recipes/NS_Steam.json
size: 702
sha: 37501e58c53ccf3a2bd44b9edee03241795bb12c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Steam.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fx_recipes/NS_Steam.json

## File: unreal_fx/fxlib.py
size: 1450
sha: b2c744ce4c28de4a28ae77fae23a08bfa3194f62
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fxlib.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/fxlib.py

## File: unreal_fx/make_copy.py
size: 641
sha: 0a0063e9b916754ac2d99641a350a0415d3375d7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/make_copy.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/make_copy.py

## File: unreal_fx/NIAGARA.md
size: 54723
sha: 72bd5cb705faadde7c5e6e826130a071ef902d00
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/NIAGARA.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/NIAGARA.md

## File: unreal_fx/ORIG.md5
size: 99
sha: ca9cfa978be331278e2e75185352bc9cfd44a08d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/ORIG.md5

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/ORIG.md5

## File: unreal_fx/perf.ps1
size: 2745
sha: a601daf811a2a809b406eabe44656e510510e037
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/perf.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/perf.ps1

## File: unreal_fx/render_mrq.ps1
size: 1099
sha: 841229aee3a69454c9070b2ceb39850cc1edc8b9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/render_mrq.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/render_mrq.ps1

## File: unreal_fx/render_shots.py
size: 9337
sha: 0d38457918ddc9d191824b9c50b7db9903f2692b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/render_shots.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/render_shots.py

## File: unreal_fx/side_by_side.py
size: 1832
sha: e55eddd506c31032358af5afb7a2838f8dfbf823
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/side_by_side.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/side_by_side.py

## File: unreal_fx/templates.json
size: 6207
sha: f2472655fcdef57105d5a8612fc6eab52d007545
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/templates.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/templates.json

## File: unreal_fx/templates_report.json
size: 18880
sha: 4258677bc65fcb32c9311aa0a1fb414ae381711d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/templates_report.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_fx/templates_report.json

## File: unreal_ramen/_orig/agx_view.py
size: 745
sha: 870bf9e98dc33cc0a5024d7a0c96e84985ac6615
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/agx_view.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/agx_view.py

## File: unreal_ramen/_orig/build_level.py
size: 33429
sha: 66897bb9bfe15606177d6a417b256fd3a802bd12
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/build_level.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/build_level.py

## File: unreal_ramen/_orig/csv_summary.sh
size: 1015
sha: 1a3f187328c07c2b083d8a1cfda5e12c5faaef4e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/csv_summary.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/csv_summary.sh

## File: unreal_ramen/_orig/export.sh
size: 1377
sha: 92e1f3fa66fbe1014a64be3d162b560effb8698d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/export.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/export.sh

## File: unreal_ramen/_orig/export_blend.py
size: 44264
sha: 89ff833e78773422c560e714f9661ff6e80b36ac
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/export_blend.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/export_blend.py

## File: unreal_ramen/_orig/make_copy.py
size: 641
sha: 0a0063e9b916754ac2d99641a350a0415d3375d7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/make_copy.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/make_copy.py

## File: unreal_ramen/_orig/perf.ps1
size: 2745
sha: a601daf811a2a809b406eabe44656e510510e037
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/perf.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/perf.ps1

## File: unreal_ramen/_orig/render_mrq.ps1
size: 1099
sha: 841229aee3a69454c9070b2ceb39850cc1edc8b9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/render_mrq.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/render_mrq.ps1

## File: unreal_ramen/_orig/render_shots.py
size: 9337
sha: 0d38457918ddc9d191824b9c50b7db9903f2692b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/render_shots.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/render_shots.py

## File: unreal_ramen/_orig/side_by_side.py
size: 1832
sha: e55eddd506c31032358af5afb7a2838f8dfbf823
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/side_by_side.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/_orig/side_by_side.py

## File: unreal_ramen/agx_view.py
size: 745
sha: 870bf9e98dc33cc0a5024d7a0c96e84985ac6615
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/agx_view.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/agx_view.py

## File: unreal_ramen/build_level.py
size: 34496
sha: 1f012ed7e5bb48aaf556be0cab462e0a9d626474
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/build_level.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/build_level.py

## File: unreal_ramen/csv_summary.sh
size: 1015
sha: 1a3f187328c07c2b083d8a1cfda5e12c5faaef4e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/csv_summary.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/csv_summary.sh

## File: unreal_ramen/export.sh
size: 1636
sha: e626c78add6cc07c4a0d08d83ce427e118e7e3ed
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/export.sh

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/export.sh

## File: unreal_ramen/export_blend.py
size: 46461
sha: 64ecb453b1da3690033d7e5c97914e25cae2a01f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/export_blend.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/export_blend.py

## File: unreal_ramen/FIXLOG.md
size: 8252
sha: f620a67210f77ace5313a2533a91766e20778ee5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/FIXLOG.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/FIXLOG.md

## File: unreal_ramen/make_copy.py
size: 641
sha: 0a0063e9b916754ac2d99641a350a0415d3375d7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/make_copy.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/make_copy.py

## File: unreal_ramen/NIAGARA.md
size: 54723
sha: 72bd5cb705faadde7c5e6e826130a071ef902d00
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/NIAGARA.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/NIAGARA.md

## File: unreal_ramen/perf.ps1
size: 2887
sha: cf962b294c57c29e3d0e9a42c144d0161662987e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/perf.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/perf.ps1

## File: unreal_ramen/ramen_fixes.patch
size: 13082
sha: 52ed4b55460249097ca21106e11792c5f063b011
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/ramen_fixes.patch

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/ramen_fixes.patch

## File: unreal_ramen/render_mrq.ps1
size: 1215
sha: caa346af4d88408e4ae43b8a4c65a4a3ff4d584b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/render_mrq.ps1

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/render_mrq.ps1

## File: unreal_ramen/render_shots.py
size: 9337
sha: 0d38457918ddc9d191824b9c50b7db9903f2692b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/render_shots.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/render_shots.py

## File: unreal_ramen/side_by_side.py
size: 1832
sha: e55eddd506c31032358af5afb7a2838f8dfbf823
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/side_by_side.py

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/side_by_side.py

## File: unreal_ramen/TOGGLE.md
size: 10997
sha: ccde40090d9a8933ea1e8148628b7b39baad9812
upstream: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/TOGGLE.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/unreal_ramen/TOGGLE.md

## File: web/.env.example
size: 1596
sha: 7213c8bf67624755f8e47a3b5698cd2ed2221e32
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/.env.example

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/.env.example

## File: web/.gitignore
size: 387
sha: bc93f3baf340325f06620becd06ff9d6681e5116
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/.gitignore

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/.gitignore

## File: web/.vercelignore
size: 118
sha: 03bf369d62ef8a75a0cd29baf1222926b6d26da3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/.vercelignore

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/.vercelignore

## File: web/AGENTS.md
size: 679
sha: af3b7c84114bafeee578bf1adff2ef74af2cc6a2
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/AGENTS.md

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/AGENTS.md

## File: web/app/api/fal/proxy/route.ts
size: 3724
sha: abd7eb385b393d258115821f57422cfde8034a49
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/app/api/fal/proxy/route.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/app/api/fal/proxy/route.ts

## File: web/app/api/me/route.ts
size: 852
sha: 8f9e6d38519344e33d7799287b8e3c14d3bc9e27
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/app/api/me/route.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/app/api/me/route.ts

## File: web/app/globals.css
size: 50193
sha: eac7ebd27866e2c4a1a173e0020127660e32407d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/app/globals.css

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/app/globals.css

## File: web/app/layout.tsx
size: 749
sha: 07ee57061ed6fae0cce9bc1f36c99ab7d5206e61
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/app/layout.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/app/layout.tsx

## File: web/app/page.tsx
size: 173
sha: b564ae38f1d34d574ba41eef370e862f8940ac90
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/app/page.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/app/page.tsx

## File: web/components/BuilderInputs.tsx
size: 5546
sha: a4dceae012f36c39c3923f2d859688835bcabb16
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderInputs.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderInputs.tsx

## File: web/components/BuilderResult.tsx
size: 4738
sha: 5699b367c94025afaa6b298c032bcd76cda15656
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderResult.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderResult.tsx

## File: web/components/BuilderSchedule.tsx
size: 4275
sha: 6f9885161c265420a248a89127c27a4b0b1f1d38
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderSchedule.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderSchedule.tsx

## File: web/components/BuilderStudio.tsx
size: 19845
sha: d7e879c97b8c21039205027e8fe0928ea5626a44
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderStudio.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderStudio.tsx

## File: web/components/BuilderViewport.tsx
size: 11707
sha: 635b9762b5221dfae814558c554a462e903d4b12
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderViewport.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/BuilderViewport.tsx

## File: web/components/Compare.tsx
size: 2087
sha: 14bf1da679b9f3ef3ff9457c5b3d00c9d8f72c22
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Compare.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Compare.tsx

## File: web/components/CriticPanel.tsx
size: 5024
sha: 9bab599375e39b2ba08d15fa83791ea72ee7bd7e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/CriticPanel.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/CriticPanel.tsx

## File: web/components/Dials.tsx
size: 3283
sha: 16eae55d2e635c92be02060240cebf9361e9d9cb
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Dials.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Dials.tsx

## File: web/components/Fade.tsx
size: 1090
sha: 8bef5d6490ba641cf3ebce980d7f1a19685a83ab
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Fade.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Fade.tsx

## File: web/components/Gallery.tsx
size: 10312
sha: e7ba8b35a78059c5193243a17e5ff1ce9f76343c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Gallery.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Gallery.tsx

## File: web/components/InfoTip.tsx
size: 3133
sha: 256f1c9b3a1bf369ab23426944b55900c6a72589
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/InfoTip.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/InfoTip.tsx

## File: web/components/Inputs.tsx
size: 4190
sha: 48f1f308fe214f74bb56b93f2ea9b2c059ef13d7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Inputs.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Inputs.tsx

## File: web/components/Lightbox.tsx
size: 3602
sha: 8d611b8901dee13c77f4231111072418aced2971
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Lightbox.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Lightbox.tsx

## File: web/components/LiveMap.tsx
size: 4356
sha: 942ab68c1fbd404ede3d49027e4474698db45ea3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/LiveMap.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/LiveMap.tsx

## File: web/components/Pano360.tsx
size: 4335
sha: 3c182fa45d73b362b3bb0ef69140ebb30e3f33b3
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Pano360.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Pano360.tsx

## File: web/components/PlanPanel.tsx
size: 6306
sha: 69a492c51bd189a2b03188301cdbdf404a613684
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/PlanPanel.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/PlanPanel.tsx

## File: web/components/ProductionLog.tsx
size: 4227
sha: 0416b73e5a8696044b861806ee95b178f3743904
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/ProductionLog.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/ProductionLog.tsx

## File: web/components/ProductSwitch.tsx
size: 942
sha: 2a68f2e03fd8af88d8dfc3dc87cc18a07e05a5c0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/ProductSwitch.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/ProductSwitch.tsx

## File: web/components/PropShelf.tsx
size: 5284
sha: da16d314a670a670bb0b673aa8531ddd5f848238
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/PropShelf.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/PropShelf.tsx

## File: web/components/Result.tsx
size: 3460
sha: 4466b235a7686f0b0651aed9cb97d8642a16e5ce
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Result.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Result.tsx

## File: web/components/SamplePicker.tsx
size: 4515
sha: acab4b0b040bc3e7ce688141048a805f127f295d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/SamplePicker.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/SamplePicker.tsx

## File: web/components/SceneView.tsx
size: 5341
sha: f8979f3cc19fb35f3a0966887c3a4968fbfbebe0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/SceneView.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/SceneView.tsx

## File: web/components/Shell.tsx
size: 1375
sha: b375d07d86df75ce75e32048e6ebe761f627b420
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Shell.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Shell.tsx

## File: web/components/ShotsOrder.tsx
size: 6976
sha: 248daeaa30d04357c81c6e2423af3a6a77f15b8d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/ShotsOrder.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/ShotsOrder.tsx

## File: web/components/Stages.tsx
size: 3324
sha: 89bf90eba1f43a03660e3b2ddbb0e62c5c12148b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Stages.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Stages.tsx

## File: web/components/Stamp.tsx
size: 428
sha: 40db81c9096efec2276f18f23a83bcece2d7287e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Stamp.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Stamp.tsx

## File: web/components/Studio.tsx
size: 12155
sha: 6ed393718c58f14647a23b03d764e4c3bc83c2ef
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Studio.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Studio.tsx

## File: web/components/Viewer3D.tsx
size: 7941
sha: 70029a25bd832a90f063daa78db11584895090e7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Viewer3D.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Viewer3D.tsx

## File: web/components/Viewport.tsx
size: 11146
sha: ef550e886be537213c59bb6415791c48ad86df50
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Viewport.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/Viewport.tsx

## File: web/components/WhoAmI.tsx
size: 4022
sha: 07c4fe2bf638e21a810401543947b3527c4c58a7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/components/WhoAmI.tsx

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/components/WhoAmI.tsx

## File: web/lib/apps.ts
size: 1917
sha: 9e51e500f449d534334dc34fbe6c2c9abcf28ca0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/apps.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/apps.ts

## File: web/lib/builder.ts
size: 10493
sha: 20fd156966e82579ac4987b07083ea51cca40c9c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/builder.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/builder.ts

## File: web/lib/gallery.ts
size: 6097
sha: 2bc3c83bca7765a1734e27ecfce7e9fed4921d7b
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/gallery.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/gallery.ts

## File: web/lib/guard.ts
size: 5688
sha: e64aef59fe2d6978c18818f583612fd2e38476fc
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/guard.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/guard.ts

## File: web/lib/run.ts
size: 8701
sha: 527d63de31bc69d3a8b293800f9e2ba37b8e5d24
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/run.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/run.ts

## File: web/lib/samples.ts
size: 1416
sha: fed008342bb06d0448fde6ccadf96dde77c4e9f0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/samples.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/samples.ts

## File: web/lib/sources.ts
size: 20815
sha: ba3e1c832538f29d5ba6b23f9e2e6ed16ee634cb
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/sources.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/sources.ts

## File: web/lib/three-util.ts
size: 5913
sha: 36741e80fd0b8ea0ceb99b64afe02cffd527d27e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/three-util.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/three-util.ts

## File: web/lib/types.ts
size: 5428
sha: 75052e3a1cccffc9ed0ca61fe3b79e75486a0423
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/types.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/lib/types.ts

## File: web/next.config.ts
size: 502
sha: 5b316aa5420d0fab7e2e6dacb4715ee0d5cdf729
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/next.config.ts

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/next.config.ts

## File: web/package-lock.json
size: 52400
sha: 0ee1078d1e2c5e9ea8cc90acd1bed88eda57812d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/package-lock.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/package-lock.json

## File: web/package.json
size: 1067
sha: 41a931a8b7dd401c9e650798f86b6d084fee6707
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/package.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/package.json

## File: web/public/samples/apothecary.jpg
size: 323521
sha: 71009d460dae0d22c89d4fe32181ef55e7c7b585
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/apothecary.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/apothecary.jpg

## File: web/public/samples/apothecary_thumb.jpg
size: 130086
sha: 51e11af241fed769beaf8eaf85b71cf54c907f0d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/apothecary_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/apothecary_thumb.jpg

## File: web/public/samples/arcade.jpg
size: 229297
sha: ee0881b808d7b9525da1c1a255e795d9896bfa9e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/arcade.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/arcade.jpg

## File: web/public/samples/arcade_thumb.jpg
size: 92383
sha: dce9f9ef1599a6bc29dde0ac921e5ff7da00eb64
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/arcade_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/arcade_thumb.jpg

## File: web/public/samples/cabin.jpg
size: 235984
sha: 233a4a583551ce2b16101ed8d560263b92d8f3f6
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/cabin.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/cabin.jpg

## File: web/public/samples/cabin_thumb.jpg
size: 90098
sha: ae0448f82450a446c41a65afe85733f2cf056b02
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/cabin_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/cabin_thumb.jpg

## File: web/public/samples/cargo.jpg
size: 250339
sha: 350deeaca2e29324e79ae3e0bbd0b3a0684e8905
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/cargo.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/cargo.jpg

## File: web/public/samples/cargo_thumb.jpg
size: 93499
sha: 02e66fb4c5afe52fc3bf42bc717c879fae331a7a
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/cargo_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/cargo_thumb.jpg

## File: web/public/samples/diner.jpg
size: 209302
sha: c9c793fcf2b44b35a4d63233db659d5a2bbe4926
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/diner.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/diner.jpg

## File: web/public/samples/diner_thumb.jpg
size: 87089
sha: ec0ca30e295157a667e56fb4d6f5d7b5f95f68f4
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/diner_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/diner_thumb.jpg

## File: web/public/samples/forge.jpg
size: 277862
sha: 45f998b9d434c7fca95689a40a7bd2c0d87e4115
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/forge.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/forge.jpg

## File: web/public/samples/forge_thumb.jpg
size: 105981
sha: d59ed5d4b2821c73bb452001a573bd2ad41aee48
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/forge_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/forge_thumb.jpg

## File: web/public/samples/garage.jpg
size: 282354
sha: e081350ccbd983b86a274f7fdd064be9669a40de
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/garage.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/garage.jpg

## File: web/public/samples/garage_thumb.jpg
size: 110617
sha: 6a3ef896e03467b143545765df7e4fc9cebdad04
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/garage_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/garage_thumb.jpg

## File: web/public/samples/greenhouse.jpg
size: 437565
sha: 6ced06ea545a13d61abd016ecfcf20c5ee4cba22
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/greenhouse.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/greenhouse.jpg

## File: web/public/samples/greenhouse_thumb.jpg
size: 163250
sha: a6cc529fb96c1854f7920148ed7d2b91cfc341d9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/greenhouse_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/greenhouse_thumb.jpg

## File: web/public/samples/jazz.jpg
size: 181846
sha: 4827fb0dc45bd78e14d303432bdc6e1e6ad89ea6
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/jazz.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/jazz.jpg

## File: web/public/samples/jazz_thumb.jpg
size: 72512
sha: 8eb1638cc8d1401994b565a395d3ebf8c386da50
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/jazz_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/jazz_thumb.jpg

## File: web/public/samples/library.jpg
size: 258026
sha: 7e8073d89dc37c9ad769813a690d8ef05c888e53
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/library.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/library.jpg

## File: web/public/samples/library_thumb.jpg
size: 96066
sha: 85c0434b37f3eeb7488fda7903c63ddda7df58dd
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/library_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/library_thumb.jpg

## File: web/public/samples/noir.jpg
size: 165302
sha: 3990441f9e93d035b3875729330cbcdb001af097
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/noir.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/noir.jpg

## File: web/public/samples/noir_thumb.jpg
size: 63628
sha: 178dab930cfb7bba5304f627e45c13a759fe49ab
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/noir_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/noir_thumb.jpg

## File: web/public/samples/subway.jpg
size: 200731
sha: 1b827131d977f749c9b1f99b0e10f6f6de746b5c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/subway.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/subway.jpg

## File: web/public/samples/subway_thumb.jpg
size: 75498
sha: 6c82f4d20feacbfcee679e463b042ed62821f2e5
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/subway_thumb.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/public/samples/subway_thumb.jpg

## File: web/screenshots/01-idle.png
size: 194610
sha: 23c8243845d2b204bf50fbea4e2ee726edbb8321
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/01-idle.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/01-idle.png

## File: web/screenshots/02-planning.png
size: 203134
sha: 8d85699c120871212f6812467c72db209bb7c82a
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/02-planning.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/02-planning.png

## File: web/screenshots/03-plan-ready-greybox.png
size: 485343
sha: 9565703f090a064bd73320d7e58bb0dff710713c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/03-plan-ready-greybox.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/03-plan-ready-greybox.png

## File: web/screenshots/04-floor-plan.png
size: 293258
sha: 69ad1774c8bc845fbfc62beff66baa3521742ca7
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/04-floor-plan.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/04-floor-plan.png

## File: web/screenshots/05-compare-greybox.png
size: 718001
sha: 036a2be65029e006aff8206d5bd41776986301aa
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/05-compare-greybox.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/05-compare-greybox.png

## File: web/screenshots/06-build-references.png
size: 373816
sha: 1d7bf58aab0a092a03528ed05b418f9bd49ad33d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/06-build-references.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/06-build-references.png

## File: web/screenshots/07-build-meshes-prop-map.png
size: 429774
sha: 62b5c2de9cdcdfe56f84a9ce0b7e7d08fea8af1e
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/07-build-meshes-prop-map.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/07-build-meshes-prop-map.png

## File: web/screenshots/08-live-layout.png
size: 634165
sha: ff5c24042635d6c62385ae54fa8e66a49abec7d0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/08-live-layout.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/08-live-layout.png

## File: web/screenshots/09-prop-3d.png
size: 517245
sha: ee004a7a9189ce06fecd528ed191a61f6280ba67
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/09-prop-3d.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/09-prop-3d.png

## File: web/screenshots/10-wrapped-result.png
size: 556155
sha: 6bce4ed385f9cb476accf0eee325fd984689bd17
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/10-wrapped-result.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/10-wrapped-result.png

## File: web/screenshots/11-compare-final.png
size: 809483
sha: e3c5562f65d58a4623169e5a7252b478b97733d9
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/11-compare-final.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/11-compare-final.png

## File: web/screenshots/12-360-plate.png
size: 432265
sha: c03de21c7d2bc0a83f23f01b30b0df5b9d821161
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/12-360-plate.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/12-360-plate.png

## File: web/screenshots/13-360-set-model.png
size: 488194
sha: 2b401bb28c2c27a605595f614b352444a09b1d67
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/13-360-set-model.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/13-360-set-model.png

## File: web/screenshots/14-prop-3d-scene-light.png
size: 522429
sha: 3a6e65f68fc72751d6c1fce8b114331c3df6e2c6
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/14-prop-3d-scene-light.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/14-prop-3d-scene-light.png

## File: web/screenshots/15-mobile.png
size: 184744
sha: 7b1552c5fff5b6f60dff35350ea10bba15468790
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/15-mobile.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/15-mobile.png

## File: web/screenshots/builder-01-idle.png
size: 197215
sha: 546249a0a6bada8e86e36165e04a0c125b10ccbc
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-01-idle.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-01-idle.png

## File: web/screenshots/builder-02-plan-milestone.png
size: 306847
sha: ed820c1235016c70361eebed2941aa0a4200923c
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-02-plan-milestone.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-02-plan-milestone.png

## File: web/screenshots/builder-03-props-dressing.png
size: 583544
sha: 44a261c76b3711707156ec2acda6374c4bea79b0
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-03-props-dressing.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-03-props-dressing.png

## File: web/screenshots/builder-04-critic-round-1.png
size: 640889
sha: 637853d2b795e863b40cea29ea9ce016f4e58a64
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-04-critic-round-1.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-04-critic-round-1.png

## File: web/screenshots/builder-05-contact-sheet-round-2.png
size: 480250
sha: fe3735384801f1a8d7e0fd05360f01b8570075ad
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-05-contact-sheet-round-2.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-05-contact-sheet-round-2.png

## File: web/screenshots/builder-06-log-notes-filter.png
size: 498642
sha: 6405d7eb55cdc4aef805a25bc59112e87aa66deb
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-06-log-notes-filter.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-06-log-notes-filter.png

## File: web/screenshots/builder-07-wrapped-stills.png
size: 503173
sha: 24dd4cb665f7d3c0648dcc6e8544a03f6122e6ce
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-07-wrapped-stills.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-07-wrapped-stills.png

## File: web/screenshots/builder-08-compare.png
size: 753236
sha: e9039d79998aa55fd5d651f10e3509e22e088cd4
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-08-compare.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-08-compare.png

## File: web/screenshots/builder-09-360-plate.png
size: 398108
sha: 168c6b65cce400166459bcb2c1ec51b299c3744f
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-09-360-plate.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-09-360-plate.png

## File: web/screenshots/builder-10-360-set-model.png
size: 444968
sha: 5fae401a37082fefc244183d176a90b9aa33ac8d
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-10-360-set-model.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-10-360-set-model.png

## File: web/screenshots/builder-11-mobile.png
size: 182076
sha: 28ef6932538a7839155fa01e6f4e406e86e91efb
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-11-mobile.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-11-mobile.png

## File: web/screenshots/builder-12-pipeline-toggle.png
size: 114324
sha: 9f974d542029ace2bb88623e72284e3add8bc7de
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-12-pipeline-toggle.png

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/screenshots/builder-12-pipeline-toggle.png

## File: web/scripts/import-builder-run.mjs
size: 1617
sha: 8da09e18498ab9c7d34cd2f5c427826b9d1f0400
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/import-builder-run.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/import-builder-run.mjs

## File: web/scripts/make-builder-fixture.mjs
size: 12253
sha: 0a8b3649b6a29079fb16508ad65f91aef3385193
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/make-builder-fixture.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/make-builder-fixture.mjs

## File: web/scripts/make-placeholders.mjs
size: 10598
sha: c6b4d5a4a248d7af139f57c2ab8feb601f0d3671
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/make-placeholders.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/make-placeholders.mjs

## File: web/scripts/screenshots-builder.mjs
size: 3061
sha: 074f16ee4c7272613052d134d4d1065685cb1102
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/screenshots-builder.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/screenshots-builder.mjs

## File: web/scripts/screenshots.mjs
size: 3706
sha: 51e4b15084f1953f4ef6fb3638fa69381a895447
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/screenshots.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/screenshots.mjs

## File: web/scripts/sync-fixtures.mjs
size: 2863
sha: 6c4a58e03c5b6b900acbd00025be76c4bfffa758
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/sync-fixtures.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/sync-fixtures.mjs

## File: web/scripts/write-env-local.mjs
size: 1184
sha: 03917041c0e3eed9f9f67c3b24bda830fe1d8435
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/write-env-local.mjs

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/scripts/write-env-local.mjs

## File: web/tsconfig.json
size: 714
sha: 469c29726bbd78386b5450777515c8c3dd2f4f3a
upstream: https://github.com/apekshik/anyscene/blob/HEAD/web/tsconfig.json

Content is not inlined in the catalog. Read the upstream file: https://github.com/apekshik/anyscene/blob/HEAD/web/tsconfig.json
