@volter/blender-engine 0.1.148 → 0.1.150
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 +22 -5
- 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 +66 -129
- package/browser/blender-engine.mts +20 -186
- package/browser/blender-wali-engine.mts +37 -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 +3 -0
- package/browser/protocol.ts +130 -43
- package/browser/pull-job.mts +2 -10
- package/browser/rna.ts +190 -73
- package/browser/runtime.ts +271 -106
- package/browser/session-addons.mts +33 -0
- package/browser/session-frame.mts +5 -24
- package/browser/session.py +1389 -1446
- 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 +492 -306
- 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 +195 -180
- 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,46 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
2
|
+
|
|
3
|
+
import bpy
|
|
4
|
+
from bpy.types import Context, Object
|
|
5
|
+
|
|
6
|
+
from .logger import get_logger
|
|
7
|
+
|
|
8
|
+
_logger = get_logger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def remove_object(context: Context, obj: Object) -> bool:
|
|
12
|
+
for child in tuple(obj.children):
|
|
13
|
+
if child.parent_type != obj.parent_type:
|
|
14
|
+
child.parent_type = obj.parent_type
|
|
15
|
+
if child.parent != obj.parent:
|
|
16
|
+
child.parent = obj.parent
|
|
17
|
+
if child.parent_bone != obj.parent_bone:
|
|
18
|
+
child.parent_bone = obj.parent_bone
|
|
19
|
+
|
|
20
|
+
for collection in tuple(obj.users_collection):
|
|
21
|
+
if obj.name in collection.objects:
|
|
22
|
+
collection.objects.unlink(obj)
|
|
23
|
+
|
|
24
|
+
if obj.parent_type != "OBJECT":
|
|
25
|
+
obj.parent_type = "OBJECT"
|
|
26
|
+
if obj.parent is not None:
|
|
27
|
+
obj.parent = None
|
|
28
|
+
|
|
29
|
+
if obj.users:
|
|
30
|
+
user_class_names = list[str]()
|
|
31
|
+
_logger.debug("Object %r is used by %d users:", obj.name, obj.users)
|
|
32
|
+
for users in context.blend_data.user_map(subset=(obj,)).values():
|
|
33
|
+
for user in users:
|
|
34
|
+
user_class_names.append(type(user).__name__)
|
|
35
|
+
_logger.debug(" %r", user)
|
|
36
|
+
|
|
37
|
+
# TODO: In Blender 5.2, Scene objects may remain as users.
|
|
38
|
+
# Until the cause is identified, forcibly remove with do_unlink=True.
|
|
39
|
+
if bpy.app.version >= (5, 2) and user_class_names == ["Scene"]:
|
|
40
|
+
context.blend_data.objects.remove(obj, do_unlink=True)
|
|
41
|
+
return True
|
|
42
|
+
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
context.blend_data.objects.remove(obj, do_unlink=True)
|
|
46
|
+
return True
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
2
|
+
import base64
|
|
3
|
+
import hashlib
|
|
4
|
+
import inspect
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Final, Optional, Protocol
|
|
10
|
+
|
|
11
|
+
import bpy
|
|
12
|
+
from bpy.app.handlers import persistent
|
|
13
|
+
from bpy.types import Context
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RunState(Enum):
|
|
17
|
+
PREEMPT = 1
|
|
18
|
+
FINISH = 2
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SceneWatcher(Protocol):
|
|
22
|
+
"""Protocol for detecting scene changes and performing some action when detected."""
|
|
23
|
+
|
|
24
|
+
def run(self, context: Context) -> RunState:
|
|
25
|
+
"""Detect scene changes and perform some action when detected.
|
|
26
|
+
|
|
27
|
+
If no changes that need to be detected have occurred in the scene, this method
|
|
28
|
+
must return in less than 100 microseconds. If there is not enough time, save
|
|
29
|
+
the current state to instance variables and interrupt the process.
|
|
30
|
+
|
|
31
|
+
This method is executed multiple times across Blender frames. Usually such
|
|
32
|
+
processing can be efficiently implemented using generators or async, but this
|
|
33
|
+
class does not do so.
|
|
34
|
+
|
|
35
|
+
The reason is that references to Blender's native objects cannot be held
|
|
36
|
+
across frames, but programming with generators and async is difficult when
|
|
37
|
+
considering this limitation.
|
|
38
|
+
|
|
39
|
+
:return FINISH if processing is complete. PREEMPT if not complete.
|
|
40
|
+
"""
|
|
41
|
+
raise NotImplementedError
|
|
42
|
+
|
|
43
|
+
def create_fast_path_performance_test_objects(self, context: Context) -> None:
|
|
44
|
+
"""Create objects for testing whether run() normally completes.
|
|
45
|
+
|
|
46
|
+
This tests whether the run() method normally completes in less than 100
|
|
47
|
+
microseconds.
|
|
48
|
+
"""
|
|
49
|
+
raise NotImplementedError
|
|
50
|
+
|
|
51
|
+
def reset_run_progress(self) -> None:
|
|
52
|
+
"""Reset the interrupted state of run()."""
|
|
53
|
+
raise NotImplementedError
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class SceneWatcherSchedule:
|
|
58
|
+
"""Holds SceneWatcher and its operation status."""
|
|
59
|
+
|
|
60
|
+
scene_watcher: Final[SceneWatcher]
|
|
61
|
+
requires_run_once_more: bool = False
|
|
62
|
+
finished: bool = False
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass
|
|
66
|
+
class SceneWatcherScheduler:
|
|
67
|
+
"""Periodically executes registered SceneWatchers in order.
|
|
68
|
+
|
|
69
|
+
This scheduler is careful not to block the UI while executing the
|
|
70
|
+
SceneWatcher instances.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
INTERVAL: Final[float] = 0.2
|
|
74
|
+
scene_watcher_schedule_index: int = 0
|
|
75
|
+
scene_watcher_type_to_schedule: Final[
|
|
76
|
+
dict[type[SceneWatcher], SceneWatcherSchedule]
|
|
77
|
+
] = field(default_factory=dict[type[SceneWatcher], SceneWatcherSchedule])
|
|
78
|
+
scene_watcher_schedules: Final[list[SceneWatcherSchedule]] = field(
|
|
79
|
+
default_factory=list[SceneWatcherSchedule]
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def trigger(self, scene_watcher_type: type[SceneWatcher]) -> None:
|
|
83
|
+
scene_watcher_schedule = self.scene_watcher_type_to_schedule.get(
|
|
84
|
+
scene_watcher_type
|
|
85
|
+
)
|
|
86
|
+
if scene_watcher_schedule:
|
|
87
|
+
# High-frequency fast path.
|
|
88
|
+
# Allow returning with minimal processing.
|
|
89
|
+
|
|
90
|
+
if scene_watcher_schedule.finished:
|
|
91
|
+
# If the task is finished, restart it
|
|
92
|
+
scene_watcher_schedule.finished = False
|
|
93
|
+
scene_watcher_schedule.scene_watcher.reset_run_progress()
|
|
94
|
+
else:
|
|
95
|
+
# If the task is running,
|
|
96
|
+
# set it to "run once more after completion"
|
|
97
|
+
scene_watcher_schedule.requires_run_once_more = True
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
# Low-frequency slow path.
|
|
101
|
+
# Heavy processing is okay.
|
|
102
|
+
|
|
103
|
+
# To prevent unregistered SceneWatchers from being missed in testing,
|
|
104
|
+
# throw an error if trying to instantiate an unregistered SceneWatcher.
|
|
105
|
+
if scene_watcher_type not in self.get_all_scene_watcher_types():
|
|
106
|
+
message = f"{scene_watcher_type} is not registered"
|
|
107
|
+
raise NotImplementedError(message)
|
|
108
|
+
|
|
109
|
+
new_scene_watcher = scene_watcher_type()
|
|
110
|
+
new_schedule = SceneWatcherSchedule(scene_watcher=new_scene_watcher)
|
|
111
|
+
self.scene_watcher_type_to_schedule[scene_watcher_type] = new_schedule
|
|
112
|
+
self.scene_watcher_schedules.append(new_schedule)
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def get_all_scene_watcher_types() -> Sequence[type[SceneWatcher]]:
|
|
116
|
+
from ..editor.mtoon1.scene_watcher import MToon1AutoSetup, OutlineUpdater
|
|
117
|
+
from ..editor.vrm1.scene_watcher import LookAtPreviewUpdater
|
|
118
|
+
|
|
119
|
+
return [OutlineUpdater, LookAtPreviewUpdater, MToon1AutoSetup]
|
|
120
|
+
|
|
121
|
+
def process(self, context: Context) -> bool:
|
|
122
|
+
"""Execute one SceneWatcher.
|
|
123
|
+
|
|
124
|
+
Use index values to reduce GC allocation.
|
|
125
|
+
"""
|
|
126
|
+
if not self.scene_watcher_schedules:
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
for _ in range(len(self.scene_watcher_schedules)):
|
|
130
|
+
self.scene_watcher_schedule_index += 1
|
|
131
|
+
self.scene_watcher_schedule_index %= len(self.scene_watcher_schedules)
|
|
132
|
+
|
|
133
|
+
# Skip tasks that are already completed
|
|
134
|
+
scene_watcher_schedule = self.scene_watcher_schedules[
|
|
135
|
+
self.scene_watcher_schedule_index
|
|
136
|
+
]
|
|
137
|
+
if scene_watcher_schedule.finished:
|
|
138
|
+
continue
|
|
139
|
+
|
|
140
|
+
# Execute the task
|
|
141
|
+
run_state = scene_watcher_schedule.scene_watcher.run(context)
|
|
142
|
+
if run_state == RunState.FINISH:
|
|
143
|
+
if scene_watcher_schedule.requires_run_once_more:
|
|
144
|
+
scene_watcher_schedule.requires_run_once_more = False
|
|
145
|
+
scene_watcher_schedule.scene_watcher.reset_run_progress()
|
|
146
|
+
else:
|
|
147
|
+
scene_watcher_schedule.finished = True
|
|
148
|
+
|
|
149
|
+
# Return if at least one task was executed
|
|
150
|
+
return True
|
|
151
|
+
return False
|
|
152
|
+
|
|
153
|
+
def flush(self, context: Context) -> None:
|
|
154
|
+
while self.process(context):
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
_scene_watcher_scheduler: Final = SceneWatcherScheduler()
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def process_scene_watcher_scheduler() -> Optional[float]:
|
|
162
|
+
context = bpy.context
|
|
163
|
+
|
|
164
|
+
_scene_watcher_scheduler.process(context)
|
|
165
|
+
return SceneWatcherScheduler.INTERVAL
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def create_fast_path_performance_test_scene(
|
|
169
|
+
context: Context, scene_watcher: SceneWatcher
|
|
170
|
+
) -> None:
|
|
171
|
+
class_file_path_str = inspect.getfile(type(scene_watcher))
|
|
172
|
+
if not class_file_path_str:
|
|
173
|
+
message = f"No path for class {type(scene_watcher)}"
|
|
174
|
+
raise ValueError(message)
|
|
175
|
+
class_file_path = Path(class_file_path_str)
|
|
176
|
+
if not class_file_path.exists():
|
|
177
|
+
message = f"No {class_file_path} found"
|
|
178
|
+
raise ValueError(message)
|
|
179
|
+
class_source_hash = (
|
|
180
|
+
base64.urlsafe_b64encode(
|
|
181
|
+
hashlib.sha3_224(class_file_path.read_bytes()).digest()
|
|
182
|
+
)
|
|
183
|
+
.rstrip(b"=")
|
|
184
|
+
.decode()
|
|
185
|
+
)
|
|
186
|
+
repository_root_path = (
|
|
187
|
+
Path(__file__).resolve(strict=True).parent.parent.parent.parent
|
|
188
|
+
)
|
|
189
|
+
expected_scene_watcher_source_path = (
|
|
190
|
+
repository_root_path / "src" / "io_scene_vrm" / "common" / "scene_watcher.py"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
if (
|
|
194
|
+
not expected_scene_watcher_source_path.exists()
|
|
195
|
+
or (
|
|
196
|
+
expected_scene_watcher_source_path.resolve(strict=True)
|
|
197
|
+
!= Path(__file__).resolve(strict=True)
|
|
198
|
+
)
|
|
199
|
+
or not (repository_root_path / ".git").exists()
|
|
200
|
+
or not (repository_root_path / "pyproject.toml").exists()
|
|
201
|
+
):
|
|
202
|
+
message = f"Repository root not found at {repository_root_path}"
|
|
203
|
+
raise AssertionError(message)
|
|
204
|
+
|
|
205
|
+
cache_folder_path = repository_root_path / ".local" / "var" / "cache"
|
|
206
|
+
cached_blend_path = cache_folder_path / (
|
|
207
|
+
type(scene_watcher).__name__
|
|
208
|
+
+ "-"
|
|
209
|
+
+ "_".join(map(str, bpy.app.version))
|
|
210
|
+
+ "-"
|
|
211
|
+
+ class_source_hash
|
|
212
|
+
+ ".blend"
|
|
213
|
+
)
|
|
214
|
+
if not cached_blend_path.exists():
|
|
215
|
+
bpy.ops.wm.read_homefile(use_empty=True)
|
|
216
|
+
scene_watcher.create_fast_path_performance_test_objects(context)
|
|
217
|
+
bpy.ops.wm.save_as_mainfile(filepath=str(cached_blend_path))
|
|
218
|
+
bpy.ops.wm.read_homefile(use_empty=True)
|
|
219
|
+
bpy.ops.wm.open_mainfile(filepath=str(cached_blend_path))
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def trigger_scene_watcher(scene_watcher_type: type[SceneWatcher]) -> None:
|
|
223
|
+
_scene_watcher_scheduler.trigger(scene_watcher_type)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@persistent
|
|
227
|
+
def save_pre(_unused: object) -> None:
|
|
228
|
+
context = bpy.context
|
|
229
|
+
|
|
230
|
+
_scene_watcher_scheduler.flush(context)
|