@volter/blender-engine 0.1.147 → 0.1.149
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +16 -0
- package/README.md +4 -11
- package/browser/addons/vrm/LICENSE_(OPTION1)_MIT.txt +22 -0
- package/browser/addons/vrm/LICENSE_(OPTION2)_GPL-3_0.txt +674 -0
- package/browser/addons/vrm/LICENSE_MAIN.txt +1 -0
- package/browser/addons/vrm/README.txt +3 -0
- package/browser/addons/vrm/__init__.py +41 -0
- package/browser/addons/vrm/blender_manifest.toml +16 -0
- package/browser/addons/vrm/common/__init__.py +1 -0
- package/browser/addons/vrm/common/animation.py +58 -0
- package/browser/addons/vrm/common/blender_manifest.py +82 -0
- package/browser/addons/vrm/common/char.py +16 -0
- package/browser/addons/vrm/common/convert.py +287 -0
- package/browser/addons/vrm/common/convert_any.py +48 -0
- package/browser/addons/vrm/common/debug.py +40 -0
- package/browser/addons/vrm/common/deep.py +162 -0
- package/browser/addons/vrm/common/error_dialog.py +274 -0
- package/browser/addons/vrm/common/fs.py +71 -0
- package/browser/addons/vrm/common/gl.py +20 -0
- package/browser/addons/vrm/common/gltf.py +1149 -0
- package/browser/addons/vrm/common/human_bone_mapper/__init__.py +1 -0
- package/browser/addons/vrm/common/human_bone_mapper/biped_mapping.py +84 -0
- package/browser/addons/vrm/common/human_bone_mapper/cats_blender_plugin_fix_model_mapping.py +63 -0
- package/browser/addons/vrm/common/human_bone_mapper/human_bone_mapper.py +203 -0
- package/browser/addons/vrm/common/human_bone_mapper/microsoft_rocketbox_mapping.py +69 -0
- package/browser/addons/vrm/common/human_bone_mapper/mixamo_mapping.py +62 -0
- package/browser/addons/vrm/common/human_bone_mapper/mmd_mapping.py +115 -0
- package/browser/addons/vrm/common/human_bone_mapper/mpfb_mapping.py +120 -0
- package/browser/addons/vrm/common/human_bone_mapper/ready_player_me_mapping.py +65 -0
- package/browser/addons/vrm/common/human_bone_mapper/reallusion_mapping.py +94 -0
- package/browser/addons/vrm/common/human_bone_mapper/rigify_meta_rig_mapping.py +65 -0
- package/browser/addons/vrm/common/human_bone_mapper/structure_based_mapping.py +891 -0
- package/browser/addons/vrm/common/human_bone_mapper/unreal_mapping.py +62 -0
- package/browser/addons/vrm/common/human_bone_mapper/vrm_addon_mapping.py +112 -0
- package/browser/addons/vrm/common/human_bone_mapper/vroid_mapping.py +89 -0
- package/browser/addons/vrm/common/legacy_gltf.py +16 -0
- package/browser/addons/vrm/common/logger.py +84 -0
- package/browser/addons/vrm/common/mtoon0.blend +0 -0
- package/browser/addons/vrm/common/mtoon1.blend +0 -0
- package/browser/addons/vrm/common/mtoon1_outline.blend +0 -0
- package/browser/addons/vrm/common/mtoon_auto_setup.blend +0 -0
- package/browser/addons/vrm/common/mtoon_unversioned.py +62 -0
- package/browser/addons/vrm/common/ops/__init__.py +10 -0
- package/browser/addons/vrm/common/ops/export_scene.py +67 -0
- package/browser/addons/vrm/common/ops/icyp.py +53 -0
- package/browser/addons/vrm/common/ops/import_scene.py +57 -0
- package/browser/addons/vrm/common/ops/vrm.py +2380 -0
- package/browser/addons/vrm/common/ops/wm.py +167 -0
- package/browser/addons/vrm/common/preferences.py +362 -0
- package/browser/addons/vrm/common/progress.py +87 -0
- package/browser/addons/vrm/common/rotation.py +89 -0
- package/browser/addons/vrm/common/safe_removal.py +46 -0
- package/browser/addons/vrm/common/scene_watcher.py +230 -0
- package/browser/addons/vrm/common/shader.py +2243 -0
- package/browser/addons/vrm/common/shape_key_mapper/__init__.py +1 -0
- package/browser/addons/vrm/common/shape_key_mapper/arkit_mapping.py +168 -0
- package/browser/addons/vrm/common/shape_key_mapper/mmd_mapping.py +62 -0
- package/browser/addons/vrm/common/shape_key_mapper/ready_player_me_mapping.py +52 -0
- package/browser/addons/vrm/common/shape_key_mapper/vrchat_mapping.py +17 -0
- package/browser/addons/vrm/common/third_party_user_extension.py +214 -0
- package/browser/addons/vrm/common/transparent_z_write.blend +0 -0
- package/browser/addons/vrm/common/version.py +161 -0
- package/browser/addons/vrm/common/vrm0/__init__.py +1 -0
- package/browser/addons/vrm/common/vrm0/human_bone.py +662 -0
- package/browser/addons/vrm/common/vrm0/material_property.py +346 -0
- package/browser/addons/vrm/common/vrm1/__init__.py +1 -0
- package/browser/addons/vrm/common/vrm1/expression_preset.py +207 -0
- package/browser/addons/vrm/common/vrm1/human_bone.py +822 -0
- package/browser/addons/vrm/common/workspace.py +227 -0
- package/browser/addons/vrm/common/writable_context.py +77 -0
- package/browser/addons/vrm/documentation/en-us/animation/index.md +63 -0
- package/browser/addons/vrm/documentation/en-us/create-humanoid-vrm-from-scratch/index.md +131 -0
- package/browser/addons/vrm/documentation/en-us/create-simple-vrm-from-scratch/index.md +30 -0
- package/browser/addons/vrm/documentation/en-us/development/index.md +136 -0
- package/browser/addons/vrm/documentation/en-us/index.md +41 -0
- package/browser/addons/vrm/documentation/en-us/installation/index.md +152 -0
- package/browser/addons/vrm/documentation/en-us/material-mtoon/index.md +122 -0
- package/browser/addons/vrm/documentation/en-us/material-pbr/index.md +94 -0
- package/browser/addons/vrm/documentation/en-us/scripting-api/index.md +391 -0
- package/browser/addons/vrm/documentation/en-us/ui/export_scene.vrm/index.md +57 -0
- package/browser/addons/vrm/documentation/en-us/ui/export_scene.vrma/index.md +17 -0
- package/browser/addons/vrm/documentation/en-us/ui/import_scene.vrm/index.md +61 -0
- package/browser/addons/vrm/documentation/en-us/ui/import_scene.vrma/index.md +13 -0
- package/browser/addons/vrm/documentation/ja-jp/animation/index.md +57 -0
- package/browser/addons/vrm/documentation/ja-jp/create-humanoid-vrm-from-scratch/index.md +129 -0
- package/browser/addons/vrm/documentation/ja-jp/create-simple-vrm-from-scratch/index.md +29 -0
- package/browser/addons/vrm/documentation/ja-jp/development/index.md +137 -0
- package/browser/addons/vrm/documentation/ja-jp/index.md +37 -0
- package/browser/addons/vrm/documentation/ja-jp/installation/index.md +150 -0
- package/browser/addons/vrm/documentation/ja-jp/material-mtoon/index.md +113 -0
- package/browser/addons/vrm/documentation/ja-jp/material-pbr/index.md +90 -0
- package/browser/addons/vrm/documentation/ja-jp/scripting-api/index.md +389 -0
- package/browser/addons/vrm/documentation/ja-jp/ui/export_scene.vrm/index.md +55 -0
- package/browser/addons/vrm/documentation/ja-jp/ui/export_scene.vrma/index.md +19 -0
- package/browser/addons/vrm/documentation/ja-jp/ui/import_scene.vrm/index.md +56 -0
- package/browser/addons/vrm/documentation/ja-jp/ui/import_scene.vrma/index.md +14 -0
- package/browser/addons/vrm/editor/__init__.py +1 -0
- package/browser/addons/vrm/editor/extension.py +425 -0
- package/browser/addons/vrm/editor/extension_accessor.py +75 -0
- package/browser/addons/vrm/editor/handler.py +84 -0
- package/browser/addons/vrm/editor/khr_character/__init__.py +1 -0
- package/browser/addons/vrm/editor/khr_character/panel.py +69 -0
- package/browser/addons/vrm/editor/khr_character/property_group.py +27 -0
- package/browser/addons/vrm/editor/khr_xmp_json_ld/__init__.py +1 -0
- package/browser/addons/vrm/editor/khr_xmp_json_ld/ops.py +464 -0
- package/browser/addons/vrm/editor/khr_xmp_json_ld/panel.py +136 -0
- package/browser/addons/vrm/editor/khr_xmp_json_ld/property_group.py +83 -0
- package/browser/addons/vrm/editor/khr_xmp_json_ld/ui_list.py +198 -0
- package/browser/addons/vrm/editor/make_armature.py +709 -0
- package/browser/addons/vrm/editor/menu.py +147 -0
- package/browser/addons/vrm/editor/migration.py +297 -0
- package/browser/addons/vrm/editor/mtoon1/__init__.py +1 -0
- package/browser/addons/vrm/editor/mtoon1/handler.py +20 -0
- package/browser/addons/vrm/editor/mtoon1/migration.py +536 -0
- package/browser/addons/vrm/editor/mtoon1/ops.py +304 -0
- package/browser/addons/vrm/editor/mtoon1/panel.py +442 -0
- package/browser/addons/vrm/editor/mtoon1/property_group.py +4977 -0
- package/browser/addons/vrm/editor/mtoon1/scene_watcher.py +381 -0
- package/browser/addons/vrm/editor/node_constraint1/__init__.py +1 -0
- package/browser/addons/vrm/editor/node_constraint1/panel.py +317 -0
- package/browser/addons/vrm/editor/node_constraint1/property_group.py +25 -0
- package/browser/addons/vrm/editor/ops.py +471 -0
- package/browser/addons/vrm/editor/panel.py +315 -0
- package/browser/addons/vrm/editor/property_group.py +888 -0
- package/browser/addons/vrm/editor/search.py +682 -0
- package/browser/addons/vrm/editor/spring_bone1/__init__.py +1 -0
- package/browser/addons/vrm/editor/spring_bone1/handler.py +994 -0
- package/browser/addons/vrm/editor/spring_bone1/menu.py +246 -0
- package/browser/addons/vrm/editor/spring_bone1/migration.py +86 -0
- package/browser/addons/vrm/editor/spring_bone1/ops.py +1679 -0
- package/browser/addons/vrm/editor/spring_bone1/panel.py +605 -0
- package/browser/addons/vrm/editor/spring_bone1/property_group.py +1457 -0
- package/browser/addons/vrm/editor/spring_bone1/ui_list.py +408 -0
- package/browser/addons/vrm/editor/subscription.py +123 -0
- package/browser/addons/vrm/editor/t_pose.py +713 -0
- package/browser/addons/vrm/editor/validation.py +1271 -0
- package/browser/addons/vrm/editor/vrm0/__init__.py +1 -0
- package/browser/addons/vrm/editor/vrm0/gizmo_group.py +63 -0
- package/browser/addons/vrm/editor/vrm0/handler.py +23 -0
- package/browser/addons/vrm/editor/vrm0/menu.py +145 -0
- package/browser/addons/vrm/editor/vrm0/migration.py +761 -0
- package/browser/addons/vrm/editor/vrm0/ops.py +2145 -0
- package/browser/addons/vrm/editor/vrm0/panel.py +1333 -0
- package/browser/addons/vrm/editor/vrm0/property_group.py +1818 -0
- package/browser/addons/vrm/editor/vrm0/ui_list.py +688 -0
- package/browser/addons/vrm/editor/vrm1/__init__.py +1 -0
- package/browser/addons/vrm/editor/vrm1/handler.py +28 -0
- package/browser/addons/vrm/editor/vrm1/menu.py +76 -0
- package/browser/addons/vrm/editor/vrm1/migration.py +321 -0
- package/browser/addons/vrm/editor/vrm1/ops.py +2679 -0
- package/browser/addons/vrm/editor/vrm1/panel.py +1243 -0
- package/browser/addons/vrm/editor/vrm1/property_group.py +2087 -0
- package/browser/addons/vrm/editor/vrm1/scene_watcher.py +90 -0
- package/browser/addons/vrm/editor/vrm1/ui_list.py +533 -0
- package/browser/addons/vrm/exporter/__init__.py +1 -0
- package/browser/addons/vrm/exporter/abstract_base_vrm_exporter.py +628 -0
- package/browser/addons/vrm/exporter/export_scene.py +930 -0
- package/browser/addons/vrm/exporter/gltf2_export_user_extension.py +45 -0
- package/browser/addons/vrm/exporter/khr_character_exporter.py +34 -0
- package/browser/addons/vrm/exporter/vrm0_exporter.py +4020 -0
- package/browser/addons/vrm/exporter/vrm1_exporter.py +3682 -0
- package/browser/addons/vrm/exporter/vrm_animation_exporter.py +1035 -0
- package/browser/addons/vrm/external/__init__.py +1 -0
- package/browser/addons/vrm/external/auto_rig_pro_support.py +3 -0
- package/browser/addons/vrm/external/io_scene_gltf2_support.py +418 -0
- package/browser/addons/vrm/external/rigify_support.py +1 -0
- package/browser/addons/vrm/importer/__init__.py +1 -0
- package/browser/addons/vrm/importer/abstract_base_vrm_importer.py +1548 -0
- package/browser/addons/vrm/importer/file_handler.py +34 -0
- package/browser/addons/vrm/importer/gltf2_import_user_extension.py +268 -0
- package/browser/addons/vrm/importer/import_scene.py +646 -0
- package/browser/addons/vrm/importer/license_validation.py +198 -0
- package/browser/addons/vrm/importer/vrm0_importer.py +1723 -0
- package/browser/addons/vrm/importer/vrm1_importer.py +2014 -0
- package/browser/addons/vrm/importer/vrm_animation_importer.py +763 -0
- package/browser/addons/vrm/importer/vrm_diff.py +316 -0
- package/browser/addons/vrm/locale/__init__.py +1 -0
- package/browser/addons/vrm/locale/ja_jp.py +826 -0
- package/browser/addons/vrm/locale/ruff.toml +8 -0
- package/browser/addons/vrm/locale/translation_dictionary.py +10 -0
- package/browser/addons/vrm/locale/zh_hans.py +928 -0
- package/browser/addons/vrm/registration.py +670 -0
- package/browser/addons/vrm.json +18 -0
- package/browser/blender-emscripten-engine.mts +60 -128
- package/browser/blender-engine.mts +20 -186
- package/browser/blender-wali-engine.mts +35 -81
- package/browser/describe-thrown.mts +3 -6
- package/browser/document-chunks.mts +4 -16
- package/browser/gltf_export.py +3161 -0
- package/browser/heap-growth.mts +23 -0
- package/browser/index.ts +2 -0
- package/browser/protocol.ts +119 -35
- package/browser/pull-job.mts +2 -10
- package/browser/rna.ts +190 -73
- package/browser/runtime.ts +197 -82
- package/browser/session-addons.mts +33 -0
- package/browser/session-frame.mts +5 -24
- package/browser/session.py +1338 -1427
- package/browser/three/attach-presenter.ts +11 -39
- package/browser/three/blender-base64.ts +1 -36
- package/browser/three/blender-corner-normals.ts +1 -23
- package/browser/three/blender-display-shaders.json +1 -1
- package/browser/three/blender-display-shaders.lut +0 -0
- package/browser/three/blender-display-transform.ts +2 -1
- package/browser/three/blender-frame-columns.ts +5 -13
- package/browser/three/blender-graph-material.ts +18 -3
- package/browser/three/blender-node-graph.ts +10 -34
- package/browser/three/blender-physical-material.ts +2 -31
- package/browser/three/blender-runtime-armature.ts +7 -60
- package/browser/three/blender-runtime-frame.ts +9 -23
- package/browser/three/blender-runtime-geometry.ts +22 -26
- package/browser/three/blender-runtime-lighting.ts +48 -178
- package/browser/three/blender-runtime-shadows.ts +187 -1
- package/browser/three/blender-runtime-skeleton.ts +53 -1
- package/browser/three/blender-runtime-view.ts +505 -283
- package/browser/three/blender-runtime-weights.ts +9 -72
- package/browser/three/blender-sky.ts +13 -33
- package/browser/three/blender-triangulate.ts +7 -35
- package/browser/three/blender-viewport-sampling.ts +235 -0
- package/browser/three/blender-workbench-material.ts +25 -29
- package/browser/three/blender-workbench-outline.ts +199 -0
- package/browser/three/blender-world-volume.ts +62 -10
- package/browser/three/presenter.ts +10 -26
- package/browser/three/release.ts +5 -21
- package/browser/three/sky-precompute-worker.ts +1 -18
- package/browser/three/sky-worker.ts +5 -23
- package/browser/three/world-field-sampler.ts +12 -26
- package/browser/volter_three.py +9 -105
- package/browser/worker.ts +156 -151
- package/package.json +5 -2
- package/wasm/BUNDLE.json +17 -17
- package/wasm/DEPENDENCY-LICENSES.txt +14 -0
- package/wasm/blender_browser.data.br +0 -0
- package/wasm/blender_browser.js +1 -1
- package/wasm/blender_browser.wasm.br +0 -0
- package/browser/frame-transfer.mts +0 -19
- package/browser/three/agx-base-srgb.lut +0 -0
- package/browser/three/agx-look-medium-high-contrast.lut +0 -0
- package/browser/three/agx-look-punchy.lut +0 -0
- package/browser/three/blender-agx.ts +0 -235
- package/browser/three/blender-display-lut.ts +0 -145
- package/browser/three/blender-filmic.ts +0 -49
- package/browser/three/blender-standard.ts +0 -68
- package/browser/three/blender-world-visibility.ts +0 -278
- package/browser/three/filmic-srgb.lut +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { HEAP_GROWTH_REFUSED } from './protocol';
|
|
2
|
+
|
|
3
|
+
/** Report WebAssembly.Memory.grow refusals from each thread before allocation aborts obscure the failed growth request. */
|
|
4
|
+
export function watchHeapGrowthSource(report: string): string {
|
|
5
|
+
return `(() => {
|
|
6
|
+
const grow = WebAssembly.Memory.prototype.grow;
|
|
7
|
+
if (grow.volterWatched) return;
|
|
8
|
+
const watched = function (pages) {
|
|
9
|
+
let before = 0;
|
|
10
|
+
try { before = this.buffer.byteLength; } catch (_) {}
|
|
11
|
+
try { return grow.call(this, pages); }
|
|
12
|
+
catch (error) {
|
|
13
|
+
const line = '${HEAP_GROWTH_REFUSED}: the browser refused ' + Math.round(pages * 65536 / 1048576) + ' MB more at ' +
|
|
14
|
+
Math.round(before / 1048576) + ' MB (' + String(error && error.message || error) + '); allocations fail from here.';
|
|
15
|
+
try { (${report})(line); } catch (_) {}
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
watched.volterWatched = true;
|
|
20
|
+
WebAssembly.Memory.prototype.grow = watched;
|
|
21
|
+
})();
|
|
22
|
+
`;
|
|
23
|
+
}
|
package/browser/index.ts
CHANGED
package/browser/protocol.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import type { FrameChunk } from './frame-stream.mts';
|
|
2
|
+
|
|
3
|
+
/** The start of the line a Blender thread prints when the browser refuses to grow the engine's heap
|
|
4
|
+
* (`blender-emscripten-engine.mts`, `watchHeapGrowthSource`); the tab keeps it (`runtime.ts`). */
|
|
5
|
+
export const HEAP_GROWTH_REFUSED = 'Blender heap could not grow';
|
|
2
6
|
/** Messages between the editor tab and its Blender worker. One session per
|
|
3
7
|
* worker; the model lives in the worker's Python and nowhere else. */
|
|
4
8
|
|
|
5
9
|
export type WorkerRequest =
|
|
6
10
|
| { id: number; op: 'load-next'; token: string }
|
|
7
11
|
| { id: number; op: 'flush-document' }
|
|
12
|
+
/** The document's bytes as a save would write them, for a backup: nothing is carried to the
|
|
13
|
+
* project and the document stays dirty. */
|
|
14
|
+
| { id: number; op: 'snapshot-document' }
|
|
15
|
+
/** Reopen the document from the project's file, discarding what it holds. */
|
|
16
|
+
| { id: number; op: 'revert-document' }
|
|
17
|
+
/** Reopen the document as `bytes` (a backup), which is then its unsaved state. */
|
|
18
|
+
| { id: number; op: 'restore-document'; bytes: Uint8Array }
|
|
8
19
|
| { id: number; op: 'history-begin' | 'history-end' }
|
|
9
20
|
| { id: number; op: 'history-step'; token: string; direction: 'undo' | 'redo' }
|
|
10
21
|
/** `document` is the session's `.blend`, PROJECT-RELATIVE (`models/model.blend`
|
|
@@ -19,10 +30,8 @@ export type WorkerRequest =
|
|
|
19
30
|
| { id: number; op: 'scene-info' }
|
|
20
31
|
| { id: number; op: 'object-info'; name: string }
|
|
21
32
|
| { id: number; op: 'screenshot-view'; maxSize: number }
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
* which `dispatch` has always answered; nothing sent it until the document
|
|
25
|
-
* did). Every mutation presents, so this is only ever the FIRST one. */
|
|
33
|
+
/** Present the engine's current document state without capture. Used for initial display and
|
|
34
|
+
* explicit refreshes of an already-open document (`session.py`'s `present` op). */
|
|
26
35
|
| { id: number; op: 'present' }
|
|
27
36
|
/** THE RNA DOOR (`./rna.ts` is its contract, `session.py`'s `rna_view`
|
|
28
37
|
* its answer): one datablock's `bl_rna.properties` as typed rows. `path` is
|
|
@@ -73,6 +82,21 @@ export type WorkerRequest =
|
|
|
73
82
|
* plus the scene's frame range/fps and the summary row's key columns.
|
|
74
83
|
* READ ONLY: keying, moving a key and setting a range are edits. */
|
|
75
84
|
| { id: number; op: 'action-clip'; object?: string; bake?: boolean; action?: string; summary?: boolean }
|
|
85
|
+
/** THE SCENE'S MOVIE (`session.py`'s `rna_scene_movie`): its range, markers and cameras, and every
|
|
86
|
+
* object's transform stack and curves, for Timeline playback and glTF export. READ ONLY. */
|
|
87
|
+
| { id: number; op: 'scene-movie' }
|
|
88
|
+
/** Scene sound strips and speakers over frames first to last. READ ONLY;
|
|
89
|
+
* speaker sampling restores the scene frame before returning. */
|
|
90
|
+
| { id: number; op: 'sound-scene'; first: number; last: number }
|
|
91
|
+
/** Export a component or level through Blender’s glTF exporter. Restore temporary state before
|
|
92
|
+
* answering; do not create history, save or present. */
|
|
93
|
+
| { id: number; op: 'gltf-export'; kind: GltfExportKind; force?: boolean; previous?: GltfExportPrevious; blendSha256?: string; luts?: Readonly<Record<string, string>> }
|
|
94
|
+
/** A SCRIPT RUN AS `blender -b <document> -P <script> -- <args>` runs one (`session.py`'s `_run_script`): its
|
|
95
|
+
* working directory a folder emptied for it, whose files the tab carries into the project. The script puts back
|
|
96
|
+
* what it changes: no history, save or present. */
|
|
97
|
+
| { id: number; op: 'run-script'; source: string; args: readonly string[]; dir: string }
|
|
98
|
+
/** AN ASSET LIBRARY IN BLENDER'S PREFERENCES (`session.py`'s `_asset_library`): a preference, not an edit. */
|
|
99
|
+
| { id: number; op: 'asset-library'; library: BlenderAssetLibrary }
|
|
76
100
|
/** ONE RESTRICTION COLUMN, written (`session.py`'s `outliner_set`). A column
|
|
77
101
|
* Blender draws on no row of that type is refused by name. */
|
|
78
102
|
| { id: number; op: 'outliner-set'; path: string; column: string; value: boolean }
|
|
@@ -81,7 +105,6 @@ export type WorkerRequest =
|
|
|
81
105
|
| { id: number; op: 'view-shading'; shading: 'WIREFRAME' | 'SOLID' | 'MATERIAL' | 'RENDERED' }
|
|
82
106
|
| { id: number; op: 'read-file'; path: string }
|
|
83
107
|
| { id: number; op: 'write-file'; path: string; bytes: Uint8Array }
|
|
84
|
-
| { id: number; op: 'list-files'; path: string }
|
|
85
108
|
/** The tab's answer to a `present` the worker asked for.
|
|
86
109
|
*
|
|
87
110
|
* `held` is the PRESENTER'S OWN report of what it held BEFORE this frame
|
|
@@ -99,6 +122,8 @@ export type WorkerRequest =
|
|
|
99
122
|
export type WorkerReply =
|
|
100
123
|
| { op: 'frame-stream'; id: number; chunk: FrameChunk }
|
|
101
124
|
| { op: 'document-dirty'; dirty: boolean }
|
|
125
|
+
/** A protected document is not being written; null follows a successful project save. */
|
|
126
|
+
| { op: 'document-saving'; document: string; note: string | null }
|
|
102
127
|
/** THE DOCUMENT FOLLOWED BLENDER: a script's `save_as_mainfile` (or `open_mainfile`) left
|
|
103
128
|
* another project `.blend` open, and the session's saves now go there
|
|
104
129
|
* (`session.py::follow_open_file`). Both paths are project-relative. Posted before the
|
|
@@ -119,21 +144,7 @@ export type WorkerReply =
|
|
|
119
144
|
* displayed-versus-submitted comparison otherwise does not have. */
|
|
120
145
|
| { op: 'present'; id: number; frame: unknown; description: unknown; capture?: CaptureRequest }
|
|
121
146
|
| { op: 'log'; level: 'log' | 'warn' | 'error'; text: string }
|
|
122
|
-
/**
|
|
123
|
-
* HOW BIG THE MODULE'S LINEAR MEMORY IS, posted after every call.
|
|
124
|
-
*
|
|
125
|
-
* The one number about the engine's memory that only the worker can read
|
|
126
|
-
* (`Module.HEAPU8.length`), and the one the tab's census had no field for:
|
|
127
|
-
* `heapUsedMB` is the PAGE's JS heap and says nothing about the wasm. wasm32
|
|
128
|
-
* memory never shrinks, so this value is also the session's high-water mark
|
|
129
|
-
* — a reader needs no separate peak.
|
|
130
|
-
*
|
|
131
|
-
* MEASURED 2026-09-18: 512 MB reserved at boot of which ~166 MB is ever
|
|
132
|
-
* touched (so the reservation itself costs no resident pages), growing to
|
|
133
|
-
* 1036 MB across `17-workshop-interior`. Every byte dlmalloc takes inside it
|
|
134
|
-
* stays taken: there is no `madvise` in wasm, so a scene's peak allocation is
|
|
135
|
-
* a permanent cost for the life of the tab.
|
|
136
|
-
*/
|
|
147
|
+
/** The worker’s current wasm linear-memory size, posted after each call. This differs from the page’s JS heap and also records the wasm high-water mark because wasm32 memory does not shrink. */
|
|
137
148
|
| { op: 'memory'; bytes: number };
|
|
138
149
|
|
|
139
150
|
export type NativeHistoryEntry = { reset: true } | {
|
|
@@ -193,15 +204,7 @@ export interface CaptureRequest {
|
|
|
193
204
|
render?: RenderRequest;
|
|
194
205
|
}
|
|
195
206
|
|
|
196
|
-
|
|
197
|
-
* `bpy.ops.render.render()` asking for the scene camera's own picture.
|
|
198
|
-
*
|
|
199
|
-
* three.js IS the renderer (ARCHITECTURE-CORE, "No second implementation of a
|
|
200
|
-
* substrate capability ships"), so a render is the Model document photographed
|
|
201
|
-
* through the scene's camera at `scene.render`'s exact resolution — and unlike
|
|
202
|
-
* a screenshot, whose view is only REMEMBERED for the transport to photograph
|
|
203
|
-
* later, the pixels come back to the caller inside the operator that asked.
|
|
204
|
-
*/
|
|
207
|
+
|
|
205
208
|
export interface RenderRequest {
|
|
206
209
|
/** Omit the visible world while retaining its illumination. */
|
|
207
210
|
transparent?: boolean;
|
|
@@ -218,7 +221,7 @@ export interface RenderRequest {
|
|
|
218
221
|
/** The scene's own view transform, as the three.js tone mapping of the same
|
|
219
222
|
* NAME (`bpy/_render_three.py`). A transform with no curve here never
|
|
220
223
|
* reaches this point: Python refuses it. */
|
|
221
|
-
toneMapping: 'none' | 'agx' | 'filmic' | 'neutral';
|
|
224
|
+
toneMapping: 'none' | 'agx' | 'filmic' | 'neutral' | 'aces13' | 'aces20';
|
|
222
225
|
/** The colour-management LOOK the scene asks for, as Blender names it.
|
|
223
226
|
* `'None'` means the base transform; anything else is a look the view holds
|
|
224
227
|
* a baked table for, because the renderer refuses the rest by name. */
|
|
@@ -241,6 +244,90 @@ export interface RenderRequest {
|
|
|
241
244
|
orthographic: boolean;
|
|
242
245
|
}
|
|
243
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Export a component .blend or a level that links components.
|
|
249
|
+
*/
|
|
250
|
+
export type GltfExportKind = 'component' | 'level';
|
|
251
|
+
|
|
252
|
+
/** The project's earlier export, as the tab holds it: its manifest and its file's SHA-256. */
|
|
253
|
+
export interface GltfExportPrevious {
|
|
254
|
+
readonly manifest: GltfExportManifest;
|
|
255
|
+
readonly sha256: string | null;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** One placement marker of a level (`extras.component`, `extras.action`, `extras.tint`, visibility). */
|
|
259
|
+
export interface GltfExportMarker {
|
|
260
|
+
readonly name: string;
|
|
261
|
+
readonly component: { readonly file: string; readonly collection: string };
|
|
262
|
+
readonly action: string | null;
|
|
263
|
+
readonly visible: boolean;
|
|
264
|
+
readonly tint: unknown;
|
|
265
|
+
readonly parent: string | null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** The manifest written beside each export (`<name>.json`): what made it, and what it holds. */
|
|
269
|
+
export interface GltfExportManifest {
|
|
270
|
+
readonly format: 1;
|
|
271
|
+
readonly kind: GltfExportKind;
|
|
272
|
+
/** The `.blend`, project-relative, and the SHA-256 of its bytes when it was exported. */
|
|
273
|
+
readonly blend: string;
|
|
274
|
+
readonly blendSha256: string;
|
|
275
|
+
/** Blender's version, its glTF add-on's, and the first 16 hex digits of `gltf_export.py`'s SHA-256. */
|
|
276
|
+
readonly exporter: { readonly blender: string; readonly gltf: string; readonly script: string };
|
|
277
|
+
readonly settings: Readonly<Record<string, string | boolean>>;
|
|
278
|
+
readonly file: string;
|
|
279
|
+
readonly sha256: string;
|
|
280
|
+
readonly bytes: number;
|
|
281
|
+
readonly nodes: number;
|
|
282
|
+
readonly meshes: number;
|
|
283
|
+
readonly skins: number;
|
|
284
|
+
readonly animations: readonly string[];
|
|
285
|
+
readonly extensionsUsed: readonly string[];
|
|
286
|
+
readonly hiddenNodes: number;
|
|
287
|
+
readonly warnings: readonly string[];
|
|
288
|
+
/**
|
|
289
|
+
* A component’s collections, named after the component.
|
|
290
|
+
*/
|
|
291
|
+
readonly collections?: readonly string[];
|
|
292
|
+
/** A level's placements, the components they name, and the override edits no marker carries. */
|
|
293
|
+
readonly markers?: readonly GltfExportMarker[];
|
|
294
|
+
readonly components?: readonly { readonly file: string; readonly collection: string }[];
|
|
295
|
+
readonly unsupported?: readonly { readonly placement: string; readonly edit: string }[];
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** What `gltf-export` answers. `files` are the module-filesystem paths of the written `.glb`
|
|
299
|
+
* and manifest (none when the earlier export is `current`), for the tab to carry out. */
|
|
300
|
+
export interface GltfExportAnswer {
|
|
301
|
+
readonly kind: GltfExportKind;
|
|
302
|
+
readonly name: string;
|
|
303
|
+
readonly document: string;
|
|
304
|
+
readonly current: boolean;
|
|
305
|
+
readonly ms: number;
|
|
306
|
+
readonly manifest: GltfExportManifest;
|
|
307
|
+
readonly files: readonly string[];
|
|
308
|
+
/** What this Blender writes for either kind: the exporter's version and each kind's settings. */
|
|
309
|
+
readonly exporter: GltfExportManifest['exporter'];
|
|
310
|
+
readonly settings: Readonly<Record<GltfExportKind, GltfExportManifest['settings']>>;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/** What `run-script` answers: the script's printed output and its raise (`error`, null when it ran to its end), and
|
|
314
|
+
* each file it wrote under its own working directory (the run's `dir`), by its path from there, with its bytes.
|
|
315
|
+
* `unstaged` names the project files that could not be copied into Blender before it ran. */
|
|
316
|
+
export interface ScriptRunAnswer {
|
|
317
|
+
readonly output: string;
|
|
318
|
+
readonly error: string | null;
|
|
319
|
+
readonly files: readonly { readonly path: string; readonly bytes: Uint8Array }[];
|
|
320
|
+
readonly unstaged: readonly string[];
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** An asset library as Preferences > File Paths > Asset Libraries lists one: its name, its folder by its path from the
|
|
324
|
+
* project, and how an asset dragged from it is imported. */
|
|
325
|
+
export interface BlenderAssetLibrary {
|
|
326
|
+
readonly name: string;
|
|
327
|
+
readonly directory: string;
|
|
328
|
+
readonly importMethod: 'LINK' | 'APPEND' | 'APPEND_REUSE' | 'PACK';
|
|
329
|
+
}
|
|
330
|
+
|
|
244
331
|
export interface FileEntry {
|
|
245
332
|
path: string;
|
|
246
333
|
size: number;
|
|
@@ -251,11 +338,8 @@ export interface FileEntry {
|
|
|
251
338
|
export interface RuntimeStart {
|
|
252
339
|
session: string;
|
|
253
340
|
python: string;
|
|
254
|
-
/**
|
|
255
|
-
|
|
256
|
-
* a board that cannot name the skew it measured cannot call a difference
|
|
257
|
-
* between them a defect in either. */
|
|
258
|
-
skew?: 'emscripten' | 'wali';
|
|
341
|
+
/** The engine implementation that answered: standalone Emscripten or WALI on browser-substrate. */
|
|
342
|
+
skew: 'emscripten' | 'wali';
|
|
259
343
|
/** The session's document, project-relative, when one was named. */
|
|
260
344
|
document?: string;
|
|
261
345
|
/** True when the project already held that `.blend` and it was OPENED —
|
package/browser/pull-job.mts
CHANGED
|
@@ -10,15 +10,7 @@ export class PullJob<T> {
|
|
|
10
10
|
private expected: string | null = null;
|
|
11
11
|
private resume: (() => void) | null = null;
|
|
12
12
|
private waiter: { resolve: (value: PullResult<T>) => void; reject: (error: unknown) => void } | null = null;
|
|
13
|
-
/**
|
|
14
|
-
* How the work ended, when it ended while nobody was waiting on a step. Work normally ends only
|
|
15
|
-
* while a step waits, but work that races something against a checkpoint (an engine compiling
|
|
16
|
-
* beside an import) can fail in the gap after a `continue` was handed out. The outcome is kept
|
|
17
|
-
* for the step that comes next, so the caller is told what actually happened. Before this, the
|
|
18
|
-
* failure was thrown at nobody and the next step answered "Invalid or replayed load
|
|
19
|
-
* continuation", which named the protocol instead of the fault (measured 2026-10-08: a Blender
|
|
20
|
-
* start refused by a content security policy showed only that message, on every retry).
|
|
21
|
-
*/
|
|
13
|
+
/** Keep a terminal result that arrives between cooperative steps so the next step reports the original failure. */
|
|
22
14
|
private ended: { readonly value: T } | { readonly error: unknown } | null = null;
|
|
23
15
|
constructor(private readonly work: (checkpoint: (phase: string) => Promise<void>) => Promise<T>) {}
|
|
24
16
|
step(token?: string): Promise<PullResult<T>> {
|
|
@@ -48,7 +40,7 @@ export class PullJob<T> {
|
|
|
48
40
|
if (waiter) waiter.reject(error);
|
|
49
41
|
else {
|
|
50
42
|
this.ended = { error };
|
|
51
|
-
//
|
|
43
|
+
// Report the failure now while retaining it for the next step.
|
|
52
44
|
console.warn('A Blender load failed between steps; the next step reports it:', error);
|
|
53
45
|
}
|
|
54
46
|
});
|
package/browser/rna.ts
CHANGED
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* THE RNA DOOR'S CONTRACT — what `session.py`'s `rna_view`, `rna_context` and
|
|
3
|
-
* `rna_set` answer, as types. TYPES ONLY, no imports and no values: the
|
|
4
|
-
* Properties sections (`../contributions/blender-properties-*`) read these
|
|
5
|
-
* shapes, and a type-only module costs their closure nothing.
|
|
6
|
-
*
|
|
7
|
-
* Everything here is Blender's own introspection of Blender's own data
|
|
8
|
-
* (`bl_rna.properties`) — the ruling's "everything Blender SHOWS about a
|
|
9
|
-
* datablock, we show, in OUR panels, read from the engine through bpy and RNA"
|
|
10
|
-
* (ARCHITECTURE-CORE §Blender north star, "Inspection parity, not editing
|
|
11
|
-
* parity"). Nothing in this file is a volter invention over RNA: every field is
|
|
12
|
-
* a `PropertyRNA` member, a `bpy.types` name, or an address `path_from_id()`
|
|
13
|
-
* produced.
|
|
14
|
-
*/
|
|
1
|
+
|
|
15
2
|
|
|
16
3
|
/** `PropertyRNA.type` — Blender's own property-type enum. */
|
|
17
4
|
export type BlenderRnaType =
|
|
@@ -71,9 +58,7 @@ export interface BlenderRnaRow {
|
|
|
71
58
|
* swatch instead of three numbers. */
|
|
72
59
|
readonly subtype: string;
|
|
73
60
|
readonly description: string;
|
|
74
|
-
/** The RNA
|
|
75
|
-
* the only grouping RNA exposes, and the one the generic view groups by.
|
|
76
|
-
* Blender's panel layout is not this and is not read (the ruling). */
|
|
61
|
+
/** The declaring RNA struct (Object, ID, Mesh), used to group properties independently of Blender’s panel layout. */
|
|
77
62
|
readonly group: string;
|
|
78
63
|
readonly groupName: string;
|
|
79
64
|
readonly arrayLength: number;
|
|
@@ -86,7 +71,7 @@ export interface BlenderRnaRow {
|
|
|
86
71
|
* `ViewLayer.depsgraph` (`rna_layer.cc:733`), the NLA tweak storage
|
|
87
72
|
* (`rna_animation.cc:1701,1713`). The door reports it; the generic view
|
|
88
73
|
* OMITS it, and no curated list names one. */
|
|
89
|
-
readonly hidden
|
|
74
|
+
readonly hidden: boolean;
|
|
90
75
|
/** UNDRAWN STATE — RNA never gave this property UI text, so
|
|
91
76
|
* `rna_define.cc:1311-1312`'s defaults still stand: `name` is the
|
|
92
77
|
* identifier and `description` is empty. The modifier panel-open booleans
|
|
@@ -238,8 +223,7 @@ export interface BlenderRnaWrite {
|
|
|
238
223
|
// ---- the outliner tree -----------------------------------------------------
|
|
239
224
|
//
|
|
240
225
|
// WHAT `session.py`'s `rna_outliner` ANSWERS: Blender's VIEW LAYER tree for the
|
|
241
|
-
// session's scene, as rows
|
|
242
|
-
// "Inspection parity", I3). Every field below is Blender's own — a `TSE_*`
|
|
226
|
+
// session's scene, as rows. Every field below is Blender's own — a `TSE_*`
|
|
243
227
|
// element type, an `ICON_*` name `tree_element_get_icon` picks, a restriction
|
|
244
228
|
// column `outliner_draw_restrictbuts` draws — and nothing here is a volter
|
|
245
229
|
// invention over the Outliner.
|
|
@@ -303,7 +287,7 @@ export interface BlenderOutlinerRow {
|
|
|
303
287
|
readonly object?: string;
|
|
304
288
|
/** A layer collection row's COLLECTION address. The row itself is addressed
|
|
305
289
|
* by its POSITION in the view layer, because a `LayerCollection` has no
|
|
306
|
-
* `path_from_id()
|
|
290
|
+
* `path_from_id()`; this is the collection datablock it
|
|
307
291
|
* shows. */
|
|
308
292
|
readonly data?: string;
|
|
309
293
|
readonly selected?: boolean;
|
|
@@ -408,7 +392,7 @@ export interface BlenderNode {
|
|
|
408
392
|
readonly colorTag: BlenderNodeColorTag;
|
|
409
393
|
/** Tree-space `[x, y]`: the node's top-left corner, which is where
|
|
410
394
|
* `node_update_basis` starts laying out (`node_draw.cc:1295-1300`). */
|
|
411
|
-
readonly location: readonly number
|
|
395
|
+
readonly location: readonly [number, number];
|
|
412
396
|
readonly width: number;
|
|
413
397
|
/** `Node.hide` — Blender's COLLAPSED node, drawn as a short rounded bar
|
|
414
398
|
* (`node_update_collapsed`, `node_draw.cc:1326-1390`). */
|
|
@@ -416,23 +400,12 @@ export interface BlenderNode {
|
|
|
416
400
|
readonly muted: boolean;
|
|
417
401
|
readonly selected: boolean;
|
|
418
402
|
readonly useCustomColor: boolean;
|
|
419
|
-
readonly color: readonly number
|
|
403
|
+
readonly color: readonly [number, number, number];
|
|
420
404
|
/** The frame node this one sits inside, by name, or null. */
|
|
421
405
|
readonly parent: string | null;
|
|
422
406
|
/** `NODE_DO_OUTPUT` through its one RNA spelling. */
|
|
423
407
|
readonly activeOutput: boolean;
|
|
424
|
-
/**
|
|
425
|
-
* HOW MANY SOCKET PANELS THE NODE DECLARES (`Node.panel_states`). A panel
|
|
426
|
-
* state carries a `persistent_uid` and `is_collapsed` and nothing else
|
|
427
|
-
* (`rna_nodetree.cc:9289-9299`, `:9430-9434`); which SOCKETS belong to a
|
|
428
|
-
* panel, and what a panel is CALLED, live in the node's C++ declaration
|
|
429
|
-
* that `node_update_basis_from_declaration` (`node_draw.cc:1086-1218`)
|
|
430
|
-
* walks, and bpy exposes neither — so that half is TRACED from Blender's
|
|
431
|
-
* source (ruled 2026-09-19) and this door owes only the live half. The
|
|
432
|
-
* trace and its table belong to the CONSUMER, `@volter/editor-blender`, because they
|
|
433
|
-
* read a Blender checkout rather than the running engine; this package
|
|
434
|
-
* answers what the engine knows and nothing else.
|
|
435
|
-
*/
|
|
408
|
+
/** Live Node.panel_states values. Socket-panel labels and membership come from Blender’s C++ declarations and belong to the editor-blender consumer’s source table. */
|
|
436
409
|
readonly panelCount: number;
|
|
437
410
|
/**
|
|
438
411
|
* The states themselves, IN DECLARATION ORDER — Blender indexes
|
|
@@ -473,39 +446,14 @@ export interface BlenderNodeTree {
|
|
|
473
446
|
readonly links: readonly BlenderNodeLink[];
|
|
474
447
|
}
|
|
475
448
|
|
|
476
|
-
/**
|
|
477
|
-
* What `rna_uv_layout` answers — ONE MESH'S UV LAYOUT, as Blender's UV editor
|
|
478
|
-
* would draw it.
|
|
479
|
-
*
|
|
480
|
-
* THE PER-CORNER ARRAYS CROSS AS BASE64 typed-array bytes, for the reason
|
|
481
|
-
* I4's weights do: a layout is `loops` two-float corners plus a
|
|
482
|
-
* triangulation, and the generic RNA door answers a struct at a time.
|
|
483
|
-
* `uvBase64` is `Float32Array` of `loops * 2` (u, v per corner, in corner
|
|
484
|
-
* order); `triangleBase64` is `Uint32Array` of `triangles * 3` CORNER indices
|
|
485
|
-
* into that array — Blender's own `calc_loop_triangles` fan, never one of
|
|
486
|
-
* ours; `loopStartBase64` / `loopTotalBase64` are `Uint32Array` of
|
|
487
|
-
* `polygons`, which is what makes a face's UV outline a contiguous walk;
|
|
488
|
-
* `pinBase64` is `Uint8Array` of `loops` and is null when nothing is pinned.
|
|
489
|
-
*
|
|
490
|
-
* `active` null with a non-empty `layers` cannot happen (a mesh with UV maps
|
|
491
|
-
* has an active one); `active` null with `layers` empty is a mesh that has no
|
|
492
|
-
* UV map at all, which is a STATE — `arena-vanguard.blend`'s 17,778-vertex
|
|
493
|
-
* body is exactly that, measured 2026-09-19 — and the door answers the header
|
|
494
|
-
* alone.
|
|
495
|
-
*
|
|
496
|
-
* `selection` is null at this pin and says so rather than being absent: UV
|
|
497
|
-
* selection lives in the BMesh an edit-mode session holds, and
|
|
498
|
-
* `MeshUVLoopLayer` (`rna_mesh.cc:2380-2456`) declares `uv`, `pin`, `name`,
|
|
499
|
-
* `active`, `active_render` and `active_clone` and no selection of any kind.
|
|
500
|
-
*/
|
|
449
|
+
/** One mesh’s UV layout. uvBase64 contains Float32 corner pairs; triangleBase64 contains Uint32 corner indices; loopStartBase64 and loopTotalBase64 delimit polygon corners; pinBase64 is Uint8 or null. A mesh with no UV layers has no active layer. Selection is null because MeshUVLoopLayer exposes no selection field outside edit-mode BMesh. */
|
|
501
450
|
export interface BlenderUvLayout {
|
|
502
451
|
readonly object: string | null;
|
|
503
452
|
readonly mesh: string | null;
|
|
504
453
|
readonly path?: string;
|
|
505
454
|
readonly layers: readonly string[];
|
|
506
455
|
readonly active: string | null;
|
|
507
|
-
/**
|
|
508
|
-
* 2026-09-19: inspection is not mode-gated). */
|
|
456
|
+
/** bpy.context.mode, reported without gating inspection on the current mode. */
|
|
509
457
|
readonly mode: string;
|
|
510
458
|
readonly loops: number;
|
|
511
459
|
readonly polygons: number;
|
|
@@ -538,6 +486,23 @@ export interface BlenderClipTrack extends BlenderClipCurve {
|
|
|
538
486
|
readonly index: number;
|
|
539
487
|
}
|
|
540
488
|
|
|
489
|
+
/** One sampled column of a {@link BlenderClipBone}: `count` samples (one when it never changes),
|
|
490
|
+
* base64 Float32. */
|
|
491
|
+
export interface BlenderClipColumn {
|
|
492
|
+
readonly count: number;
|
|
493
|
+
readonly base64: string;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/** One bone of an action as three.js plays it: its local position, quaternion (x, y, z, w) and
|
|
497
|
+
* scale per integer frame of the clip's range, and the frames it is keyed on. */
|
|
498
|
+
export interface BlenderClipBone {
|
|
499
|
+
readonly bone: string;
|
|
500
|
+
readonly keys: readonly number[];
|
|
501
|
+
readonly position: BlenderClipColumn;
|
|
502
|
+
readonly quaternion: BlenderClipColumn;
|
|
503
|
+
readonly scale: BlenderClipColumn;
|
|
504
|
+
}
|
|
505
|
+
|
|
541
506
|
/** An F-Curve's body: everything Blender evaluates it from, wherever it lives. */
|
|
542
507
|
export interface BlenderClipCurve {
|
|
543
508
|
/** `FCurve.extrapolation`: `CONSTANT` or `LINEAR`. */
|
|
@@ -604,13 +569,9 @@ export interface BlenderActionClip {
|
|
|
604
569
|
readonly slot: string | null;
|
|
605
570
|
/** The action's object slots: at most one means every armature reads the same curves. */
|
|
606
571
|
readonly objectSlots?: number;
|
|
607
|
-
/** `layered` at this pin — an `Action` has no `.fcurves`; they live at
|
|
608
|
-
* `layers[0].strips[0].channelbags[0].fcurves`. `legacy` is the branch for
|
|
609
|
-
* a build where the old attribute is still there. */
|
|
610
|
-
readonly channels?: string;
|
|
611
572
|
/** The scene's own name — the Timeline's one write addresses
|
|
612
573
|
* `bpy.data.scenes["<name>"]`, because an RNA path starts at `bpy.data.`. */
|
|
613
|
-
readonly scene
|
|
574
|
+
readonly scene: string;
|
|
614
575
|
readonly frameCurrent: number;
|
|
615
576
|
readonly frameStart: number;
|
|
616
577
|
readonly frameEnd: number;
|
|
@@ -621,7 +582,7 @@ export interface BlenderActionClip {
|
|
|
621
582
|
readonly keyframes: readonly BlenderClipKeyColumn[];
|
|
622
583
|
/** Every animated object in the view layer, for the summary row's
|
|
623
584
|
* selection filter. Always present; empty for a file with no animation. */
|
|
624
|
-
readonly summary
|
|
585
|
+
readonly summary: readonly BlenderClipSummaryObject[];
|
|
625
586
|
readonly tracks: readonly BlenderClipTrack[];
|
|
626
587
|
readonly clipStart?: number;
|
|
627
588
|
readonly clipEnd?: number;
|
|
@@ -629,14 +590,170 @@ export interface BlenderActionClip {
|
|
|
629
590
|
* modifier repeats into. */
|
|
630
591
|
readonly keysStart?: number | null;
|
|
631
592
|
readonly keysEnd?: number | null;
|
|
632
|
-
/** Blender repeats it past its range (Cycles modifiers on its curves, or `use_cyclic`). */
|
|
633
|
-
readonly cyclic?: boolean;
|
|
634
593
|
readonly duration?: number;
|
|
635
|
-
readonly sampled?: number;
|
|
636
594
|
/** Bones the action names that the armature does not have. */
|
|
637
595
|
readonly unplayedBones?: readonly string[];
|
|
638
|
-
/**
|
|
639
|
-
*
|
|
596
|
+
/** THE ACTION AS THREE.JS PLAYS IT (`session.py`'s `_three_bones`): per bone it keys, the bone's
|
|
597
|
+
* local transform at every integer frame from `clipStart` to `clipEnd`, sampled by Blender. */
|
|
598
|
+
readonly bones?: readonly BlenderClipBone[];
|
|
599
|
+
/** Keyed channels the three.js animation preview does not play (a custom property or delta
|
|
600
|
+
* transform). Object transforms are handled by {@link BlenderSceneMovie}. */
|
|
640
601
|
readonly unsupported?: readonly string[];
|
|
641
602
|
readonly reason?: string;
|
|
642
603
|
}
|
|
604
|
+
|
|
605
|
+
/** One object the scene's movie moves or looks through. */
|
|
606
|
+
export interface BlenderMovieObject {
|
|
607
|
+
readonly name: string;
|
|
608
|
+
readonly type: string;
|
|
609
|
+
readonly parent: string | null;
|
|
610
|
+
/** `Object.rotation_mode`. */
|
|
611
|
+
readonly rotationMode: string;
|
|
612
|
+
/** Its own channels as the file holds them, which a component no action keys keeps. */
|
|
613
|
+
readonly channels: {
|
|
614
|
+
readonly location: readonly number[];
|
|
615
|
+
readonly rotation_quaternion: readonly number[];
|
|
616
|
+
readonly rotation_euler: readonly number[];
|
|
617
|
+
readonly rotation_axis_angle: readonly number[];
|
|
618
|
+
readonly scale: readonly number[];
|
|
619
|
+
};
|
|
620
|
+
/** Its delta transform (the rotation as a quaternion w, x, y, z), applied as `BKE_object_to_mat4`. */
|
|
621
|
+
readonly delta: { readonly location: readonly number[]; readonly rotation: readonly number[]; readonly scale: readonly number[] };
|
|
622
|
+
/** What places its basis in its parent's space: `matrix_parent_inverse` (identity without a parent). */
|
|
623
|
+
readonly pre: readonly (readonly number[])[];
|
|
624
|
+
readonly constraints: readonly {
|
|
625
|
+
readonly name: string;
|
|
626
|
+
readonly type: string;
|
|
627
|
+
readonly enabled: boolean;
|
|
628
|
+
readonly influence: number;
|
|
629
|
+
readonly target?: string;
|
|
630
|
+
readonly trackAxis?: string;
|
|
631
|
+
readonly upAxis?: string;
|
|
632
|
+
readonly useTargetZ?: boolean;
|
|
633
|
+
}[];
|
|
634
|
+
/** A camera's projection as held by the file, with sampled columns when keyed. */
|
|
635
|
+
readonly camera?: {
|
|
636
|
+
readonly type: string;
|
|
637
|
+
readonly lens: number;
|
|
638
|
+
readonly sensor_width: number;
|
|
639
|
+
readonly sensor_height: number;
|
|
640
|
+
readonly sensor_fit: string;
|
|
641
|
+
readonly ortho_scale: number;
|
|
642
|
+
readonly clip_start: number;
|
|
643
|
+
readonly clip_end: number;
|
|
644
|
+
readonly shift_x: number;
|
|
645
|
+
readonly shift_y: number;
|
|
646
|
+
/** Disabled in renders: Blender's marker cuts skip it. */
|
|
647
|
+
readonly renderHidden: boolean;
|
|
648
|
+
/** Its projection at every scene frame, sampled by Blender (present when keyed). */
|
|
649
|
+
readonly sampled?: { readonly start: number; readonly end: number } & Readonly<Record<
|
|
650
|
+
'lens' | 'sensor_width' | 'sensor_height' | 'ortho_scale' | 'shift_x' | 'shift_y' | 'clip_start' | 'clip_end', BlenderClipColumn>>;
|
|
651
|
+
};
|
|
652
|
+
/** Its local transform at every scene frame, sampled by Blender (`session.py`'s `_sample_object`):
|
|
653
|
+
* `hidden` (1 hidden) when its render visibility is keyed. Present when it is animated. */
|
|
654
|
+
readonly sampled?: {
|
|
655
|
+
readonly start: number;
|
|
656
|
+
readonly end: number;
|
|
657
|
+
readonly position: BlenderClipColumn;
|
|
658
|
+
readonly quaternion: BlenderClipColumn;
|
|
659
|
+
readonly scale: BlenderClipColumn;
|
|
660
|
+
readonly hidden?: BlenderClipColumn;
|
|
661
|
+
};
|
|
662
|
+
/** Animation behavior the three.js preview does not play. */
|
|
663
|
+
readonly unsupported?: readonly string[];
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/** A sound's file: a path Blender holds it at (the project's, absolute), or a packed sound's copy
|
|
667
|
+
* beside the session, read back through the session's files. */
|
|
668
|
+
export type BlenderSoundFile = { readonly path: string } | { readonly packed: string };
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* THE SCENE'S SOUND, DESCRIBED FOR THE PAGE TO MIX (`session.py`'s `rna_sound_scene`), over the
|
|
672
|
+
* movie's frames `first` to `last`. Every per-frame column holds `count` values (stride 1, or 3 for a
|
|
673
|
+
* point), or one when it never changes.
|
|
674
|
+
*/
|
|
675
|
+
export interface BlenderSoundScene {
|
|
676
|
+
readonly fps: number;
|
|
677
|
+
readonly first: number;
|
|
678
|
+
readonly last: number;
|
|
679
|
+
readonly count: number;
|
|
680
|
+
/** The scene's own volume, and whether its sequencer sound is muted (`Scene.use_audio`). */
|
|
681
|
+
readonly volume: number;
|
|
682
|
+
readonly muted: boolean;
|
|
683
|
+
/** `Scene.audio_distance_model`: `NONE`, `INVERSE`, `INVERSE_CLAMPED`, `LINEAR`, `LINEAR_CLAMPED`, `EXPONENT`, `EXPONENT_CLAMPED`. */
|
|
684
|
+
readonly distanceModel: string;
|
|
685
|
+
readonly strips: readonly {
|
|
686
|
+
readonly name: string;
|
|
687
|
+
readonly file: BlenderSoundFile | null;
|
|
688
|
+
readonly mono: boolean;
|
|
689
|
+
readonly muted: boolean;
|
|
690
|
+
/** The frame the sound's own start sits at, and the frames the strip is cut to (end exclusive). */
|
|
691
|
+
readonly start: number;
|
|
692
|
+
readonly finalStart: number;
|
|
693
|
+
readonly finalEnd: number;
|
|
694
|
+
readonly speed: number;
|
|
695
|
+
readonly volume: BlenderClipColumn;
|
|
696
|
+
readonly pan: BlenderClipColumn;
|
|
697
|
+
}[];
|
|
698
|
+
readonly speakers: readonly {
|
|
699
|
+
readonly name: string;
|
|
700
|
+
readonly file: BlenderSoundFile | null;
|
|
701
|
+
readonly muted: boolean;
|
|
702
|
+
/** The frames its NLA sound strips start on. */
|
|
703
|
+
readonly starts: readonly number[];
|
|
704
|
+
readonly volume: BlenderClipColumn;
|
|
705
|
+
readonly volumeMin: number;
|
|
706
|
+
readonly volumeMax: number;
|
|
707
|
+
readonly attenuation: number;
|
|
708
|
+
readonly distanceReference: number;
|
|
709
|
+
readonly distanceMax: number;
|
|
710
|
+
/** Radians. */
|
|
711
|
+
readonly coneInner: number;
|
|
712
|
+
readonly coneOuter: number;
|
|
713
|
+
readonly coneOuterVolume: number;
|
|
714
|
+
/** Blender world space, per frame (stride 3); facing is the speaker's -Z. */
|
|
715
|
+
readonly position: BlenderClipColumn;
|
|
716
|
+
readonly facing: BlenderClipColumn;
|
|
717
|
+
}[];
|
|
718
|
+
/** The scene camera's place and axes per frame (stride 3), the speakers' listener; null without speakers. */
|
|
719
|
+
readonly listener: { readonly position: BlenderClipColumn; readonly forward: BlenderClipColumn; readonly up: BlenderClipColumn } | null;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* The scene animation from `session.py`'s `rna_scene_movie`, consumed by the Timeline preview
|
|
724
|
+
* and glTF export.
|
|
725
|
+
*/
|
|
726
|
+
export interface BlenderSceneMovie {
|
|
727
|
+
readonly scene: {
|
|
728
|
+
readonly name: string;
|
|
729
|
+
readonly start: number;
|
|
730
|
+
readonly end: number;
|
|
731
|
+
readonly fps: number;
|
|
732
|
+
readonly current: number;
|
|
733
|
+
readonly camera: string | null;
|
|
734
|
+
};
|
|
735
|
+
/** The Timeline's markers by frame, each with the camera it cuts to (`TimelineMarker.camera`). */
|
|
736
|
+
readonly markers: readonly { readonly name: string; readonly frame: number; readonly camera: string | null }[];
|
|
737
|
+
readonly objects: readonly BlenderMovieObject[];
|
|
738
|
+
/** MATERIALS whose Principled inputs a curve keys (`_sample_material`): base colour, emission (colour times strength) and alpha at every scene frame, each
|
|
739
|
+
* present only when keyed. */
|
|
740
|
+
readonly materials: readonly {
|
|
741
|
+
readonly name: string;
|
|
742
|
+
readonly start: number;
|
|
743
|
+
readonly end: number;
|
|
744
|
+
readonly color?: BlenderClipColumn;
|
|
745
|
+
readonly emissive?: BlenderClipColumn;
|
|
746
|
+
readonly opacity?: BlenderClipColumn;
|
|
747
|
+
}[];
|
|
748
|
+
/** MESHES whose shape keys a curve keys (`_sample_shapes`): each keyed key's offset at
|
|
749
|
+
* every vertex (from the key it is relative to), its value at every scene frame and the value the
|
|
750
|
+
* presented geometry already holds; `mapped` false when modifiers change the mesh's vertices. */
|
|
751
|
+
readonly shapes: readonly {
|
|
752
|
+
readonly object: string;
|
|
753
|
+
readonly start: number;
|
|
754
|
+
readonly end: number;
|
|
755
|
+
readonly vertices: number;
|
|
756
|
+
readonly mapped: boolean;
|
|
757
|
+
readonly keys: readonly { readonly name: string; readonly delta: BlenderClipColumn; readonly values: BlenderClipColumn; readonly current: number }[];
|
|
758
|
+
}[];
|
|
759
|
+
}
|