@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,162 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
2
|
+
import difflib
|
|
3
|
+
import math
|
|
4
|
+
from collections.abc import Mapping
|
|
5
|
+
from json import dumps as json_dumps
|
|
6
|
+
from types import MappingProxyType
|
|
7
|
+
|
|
8
|
+
from . import convert
|
|
9
|
+
from .convert import Json, JsonView
|
|
10
|
+
from .logger import get_logger
|
|
11
|
+
|
|
12
|
+
_logger = get_logger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def make_json(v: object) -> Json:
|
|
16
|
+
if v is None:
|
|
17
|
+
return None
|
|
18
|
+
if isinstance(v, int):
|
|
19
|
+
return v
|
|
20
|
+
if isinstance(v, float):
|
|
21
|
+
if not math.isfinite(v):
|
|
22
|
+
_logger.warning("%s %s is non-finite value", v, type(v))
|
|
23
|
+
return 0.0
|
|
24
|
+
return v
|
|
25
|
+
if isinstance(v, bool):
|
|
26
|
+
return v
|
|
27
|
+
if isinstance(v, str):
|
|
28
|
+
return v
|
|
29
|
+
|
|
30
|
+
mapping = convert.mapping_or_none(v)
|
|
31
|
+
if mapping is not None:
|
|
32
|
+
dict_result: dict[str, Json] = {}
|
|
33
|
+
for key, value in mapping.items():
|
|
34
|
+
if isinstance(key, str):
|
|
35
|
+
dict_result[key] = make_json(value)
|
|
36
|
+
continue
|
|
37
|
+
_logger.warning("%s %s is unrecognized type for dict key", key, type(key))
|
|
38
|
+
return dict_result
|
|
39
|
+
|
|
40
|
+
iterator = convert.iterator_or_none(v)
|
|
41
|
+
if iterator is not None:
|
|
42
|
+
return [make_json(x) for x in iterator]
|
|
43
|
+
|
|
44
|
+
_logger.warning("%s %s is unrecognized type", v, type(v))
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def make_json_view(v: object) -> JsonView:
|
|
49
|
+
json = make_json(v)
|
|
50
|
+
if isinstance(json, dict):
|
|
51
|
+
return MappingProxyType(
|
|
52
|
+
{key: make_json_view(value) for key, value in json.items()}
|
|
53
|
+
)
|
|
54
|
+
if isinstance(json, list):
|
|
55
|
+
return tuple(make_json_view(x) for x in json)
|
|
56
|
+
return json
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def make_json_dict(v: Mapping[str, object]) -> dict[str, Json]:
|
|
60
|
+
return {key: make_json(value) for key, value in v.items()}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def diff(
|
|
64
|
+
left: Json,
|
|
65
|
+
right: Json,
|
|
66
|
+
float_tolerance: float = 0,
|
|
67
|
+
path: str = "",
|
|
68
|
+
) -> list[str]:
|
|
69
|
+
if isinstance(left, list):
|
|
70
|
+
if not isinstance(right, list):
|
|
71
|
+
return [f"{path}: left is list but right is {type(right)}"]
|
|
72
|
+
if len(left) != len(right):
|
|
73
|
+
result = [
|
|
74
|
+
f"{path}: left length is {len(left)} but right length is {len(right)}"
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
right_json_str = json_dumps(right, indent=4, sort_keys=True)
|
|
78
|
+
right_json_lines = right_json_str.splitlines(keepends=True)
|
|
79
|
+
left_json_str = json_dumps(left, indent=4, sort_keys=True)
|
|
80
|
+
left_json_lines = left_json_str.splitlines(keepends=True)
|
|
81
|
+
|
|
82
|
+
if len(right_json_lines) > 1000 or len(left_json_lines) > 1000:
|
|
83
|
+
return result
|
|
84
|
+
|
|
85
|
+
unified_diff = [
|
|
86
|
+
line.rstrip()
|
|
87
|
+
for line in difflib.unified_diff(
|
|
88
|
+
right_json_lines,
|
|
89
|
+
left_json_lines,
|
|
90
|
+
f"{path}/right",
|
|
91
|
+
f"{path}/left",
|
|
92
|
+
)
|
|
93
|
+
]
|
|
94
|
+
if len(unified_diff) > 1000:
|
|
95
|
+
return result
|
|
96
|
+
return result + unified_diff
|
|
97
|
+
diffs: list[str] = []
|
|
98
|
+
for i, (left_child, right_child) in enumerate(zip(left, right)):
|
|
99
|
+
diffs.extend(diff(left_child, right_child, float_tolerance, f"{path}[{i}]"))
|
|
100
|
+
return diffs
|
|
101
|
+
|
|
102
|
+
if isinstance(left, dict):
|
|
103
|
+
if not isinstance(right, dict):
|
|
104
|
+
return [f"{path}: left is dict but right is {type(right)}"]
|
|
105
|
+
diffs = []
|
|
106
|
+
for key in sorted(left.keys() | right.keys()):
|
|
107
|
+
if key not in left:
|
|
108
|
+
diffs.append(f'{path}: {key} not in left. right["{key}"]={right[key]}')
|
|
109
|
+
continue
|
|
110
|
+
if key not in right:
|
|
111
|
+
diffs.append(f'{path}: {key} not in right, left["{key}"]={left[key]}')
|
|
112
|
+
continue
|
|
113
|
+
diffs.extend(
|
|
114
|
+
diff(left[key], right[key], float_tolerance, f'{path}["{key}"]')
|
|
115
|
+
)
|
|
116
|
+
return diffs
|
|
117
|
+
|
|
118
|
+
if isinstance(left, bool):
|
|
119
|
+
if not isinstance(right, bool):
|
|
120
|
+
return [f"{path}: left is bool but right is {type(right)}"]
|
|
121
|
+
if left != right:
|
|
122
|
+
return [f"{path}: left is {left} but right is {right}"]
|
|
123
|
+
return []
|
|
124
|
+
|
|
125
|
+
if isinstance(left, str):
|
|
126
|
+
if not isinstance(right, str):
|
|
127
|
+
return [f"{path}: left is str but right is {type(right)}"]
|
|
128
|
+
if left != right:
|
|
129
|
+
return [f'{path}: left is "{left}" but right is "{right}"']
|
|
130
|
+
return []
|
|
131
|
+
|
|
132
|
+
if isinstance(left, int) and isinstance(right, int):
|
|
133
|
+
if left != right:
|
|
134
|
+
return [f"{path}: left is {left} but right is {right}"]
|
|
135
|
+
return []
|
|
136
|
+
|
|
137
|
+
if isinstance(left, (int, float)) and isinstance(right, (int, float)):
|
|
138
|
+
if (isinstance(left, float) and not math.isfinite(left)) or (
|
|
139
|
+
isinstance(right, float) and not math.isfinite(right)
|
|
140
|
+
):
|
|
141
|
+
return [
|
|
142
|
+
f"{path}: left is {left}"
|
|
143
|
+
+ f" but right is {right}, They are not comparable numbers"
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
error = math.fabs(float(left) - float(right))
|
|
147
|
+
if error > float_tolerance:
|
|
148
|
+
return [
|
|
149
|
+
f"{path}: left is {float(left):20.17f}"
|
|
150
|
+
+ f" but right is {float(right):20.17f}, error={error:19.17f}"
|
|
151
|
+
]
|
|
152
|
+
return []
|
|
153
|
+
|
|
154
|
+
if left is None:
|
|
155
|
+
if right is None:
|
|
156
|
+
return []
|
|
157
|
+
return [f"{path}: left is None but right is {type(right)}"]
|
|
158
|
+
if right is None:
|
|
159
|
+
return [f"{path}: left is {type(left)} but right is None"]
|
|
160
|
+
|
|
161
|
+
message = f"{path}: unexpected type left={type(left)} right={type(right)}"
|
|
162
|
+
raise ValueError(message)
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import datetime as dt
|
|
5
|
+
import getpass
|
|
6
|
+
import platform
|
|
7
|
+
import sys
|
|
8
|
+
import sysconfig
|
|
9
|
+
from collections.abc import Sequence
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import TYPE_CHECKING, ClassVar, Union
|
|
12
|
+
|
|
13
|
+
import bpy
|
|
14
|
+
from bpy.props import CollectionProperty, IntProperty, StringProperty
|
|
15
|
+
from bpy.types import (
|
|
16
|
+
Context,
|
|
17
|
+
Event,
|
|
18
|
+
Operator,
|
|
19
|
+
PropertyGroup,
|
|
20
|
+
UILayout,
|
|
21
|
+
UIList,
|
|
22
|
+
)
|
|
23
|
+
from bpy_extras.io_utils import ExportHelper
|
|
24
|
+
|
|
25
|
+
from ..common import convert, ops
|
|
26
|
+
from ..common.logger import get_logger
|
|
27
|
+
from ..common.version import get_addon_version
|
|
28
|
+
from ..editor.ops import VRM_OT_open_url_in_web_browser, layout_operator
|
|
29
|
+
from ..editor.property_group import CollectionPropertyProtocol
|
|
30
|
+
from ..external import io_scene_gltf2_support
|
|
31
|
+
|
|
32
|
+
_logger = get_logger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def show_error_dialog(
|
|
36
|
+
title: str,
|
|
37
|
+
lines: Union[str, Sequence[str]],
|
|
38
|
+
*,
|
|
39
|
+
append_environment: bool = True,
|
|
40
|
+
) -> set[str]:
|
|
41
|
+
if isinstance(lines, str):
|
|
42
|
+
lines = [line.rstrip() for line in lines.splitlines()]
|
|
43
|
+
while lines and not lines[0].strip():
|
|
44
|
+
del lines[0]
|
|
45
|
+
while lines and not lines[-1].strip():
|
|
46
|
+
del lines[-1]
|
|
47
|
+
else:
|
|
48
|
+
lines = list(lines)
|
|
49
|
+
if not lines:
|
|
50
|
+
return {"CANCELLED"}
|
|
51
|
+
if append_environment:
|
|
52
|
+
if lines:
|
|
53
|
+
lines[0] = f"Python: {lines[0]}"
|
|
54
|
+
lines = io_scene_gltf2_support.read_addon_diagnostics() + lines
|
|
55
|
+
|
|
56
|
+
os_name = None
|
|
57
|
+
platform_system, _, _ = platform.system_alias(
|
|
58
|
+
platform.system(), platform.release(), platform.version()
|
|
59
|
+
)
|
|
60
|
+
if sys.version_info >= (3, 10) and platform_system not in {"Windows", "Darwin"}:
|
|
61
|
+
# https://github.com/python/cpython/blob/v3.10.18/Doc/library/platform.rst?plain=1#L271-L272
|
|
62
|
+
with contextlib.suppress(OSError):
|
|
63
|
+
os_name = platform.freedesktop_os_release().get("PRETTY_NAME")
|
|
64
|
+
|
|
65
|
+
if not os_name:
|
|
66
|
+
os_name = platform_system
|
|
67
|
+
|
|
68
|
+
python_version = (
|
|
69
|
+
platform.python_implementation()
|
|
70
|
+
+ " "
|
|
71
|
+
+ ".".join(map(str, sys.version_info[:3]))
|
|
72
|
+
)
|
|
73
|
+
runtime_platform = os_name + " " + platform.machine()
|
|
74
|
+
build_platform = sysconfig.get_platform()
|
|
75
|
+
lines.insert(
|
|
76
|
+
0,
|
|
77
|
+
"Environment: Blender {} / VRM Add-on {} / {} / {} ({})".format(
|
|
78
|
+
bpy.app.version_string,
|
|
79
|
+
".".join(map(str, get_addon_version())),
|
|
80
|
+
python_version,
|
|
81
|
+
runtime_platform,
|
|
82
|
+
build_platform,
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
return ops.wm.vrm_error_dialog(
|
|
86
|
+
"INVOKE_DEFAULT",
|
|
87
|
+
title=title,
|
|
88
|
+
lines=[
|
|
89
|
+
{
|
|
90
|
+
"name": f"error_line_{i}",
|
|
91
|
+
"line": _mask_private_string(line),
|
|
92
|
+
}
|
|
93
|
+
for i, line in enumerate(lines)
|
|
94
|
+
],
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _mask_private_string(message: str) -> str:
|
|
99
|
+
script_path = Path(__file__).parent.parent.parent.parent.parent
|
|
100
|
+
if len(script_path.parts) > 3:
|
|
101
|
+
message = message.replace(str(script_path), "<script path>")
|
|
102
|
+
|
|
103
|
+
message = message.replace(str(Path.home()), "<home path>")
|
|
104
|
+
message = message.replace(getpass.getuser(), "<user name>")
|
|
105
|
+
binary_path = bpy.app.binary_path
|
|
106
|
+
if binary_path:
|
|
107
|
+
binary_folder_path = Path(binary_path).parent
|
|
108
|
+
message = message.replace(str(binary_folder_path), "<bin folder path>")
|
|
109
|
+
return message
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class VrmErrorDialogMessageLine(PropertyGroup):
|
|
113
|
+
line: StringProperty() # type: ignore[valid-type]
|
|
114
|
+
|
|
115
|
+
if TYPE_CHECKING:
|
|
116
|
+
# This code is auto generated.
|
|
117
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
118
|
+
line: str # type: ignore[no-redef]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class VRM_UL_vrm_error_dialog_message(UIList):
|
|
122
|
+
bl_idname = "VRM_UL_vrm_error_dialog_message"
|
|
123
|
+
|
|
124
|
+
def filter_items(
|
|
125
|
+
self,
|
|
126
|
+
_context: Context,
|
|
127
|
+
data: object,
|
|
128
|
+
propname: str,
|
|
129
|
+
) -> tuple[list[int], list[int]]:
|
|
130
|
+
items = convert.sequence_or_none(getattr(data, propname, None))
|
|
131
|
+
if items is None:
|
|
132
|
+
return ([], [])
|
|
133
|
+
|
|
134
|
+
flt_flags: list[int] = [self.bitflag_filter_item] * len(items)
|
|
135
|
+
flt_neworder: list[int] = []
|
|
136
|
+
|
|
137
|
+
filter_name: str = self.filter_name.casefold()
|
|
138
|
+
if not filter_name:
|
|
139
|
+
return (flt_flags, flt_neworder)
|
|
140
|
+
|
|
141
|
+
for index, item in enumerate(items):
|
|
142
|
+
if (
|
|
143
|
+
isinstance(item, VrmErrorDialogMessageLine)
|
|
144
|
+
and filter_name in item.line.casefold()
|
|
145
|
+
):
|
|
146
|
+
continue
|
|
147
|
+
flt_flags[index] = 0
|
|
148
|
+
|
|
149
|
+
return (flt_flags, flt_neworder)
|
|
150
|
+
|
|
151
|
+
def draw_item(
|
|
152
|
+
self,
|
|
153
|
+
_context: Context,
|
|
154
|
+
layout: UILayout,
|
|
155
|
+
_data: object,
|
|
156
|
+
line: object,
|
|
157
|
+
_icon: int,
|
|
158
|
+
_active_data: object,
|
|
159
|
+
_active_prop_name: str,
|
|
160
|
+
_index: int,
|
|
161
|
+
_flt_flag: int,
|
|
162
|
+
) -> None:
|
|
163
|
+
if not isinstance(line, VrmErrorDialogMessageLine):
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
column = layout.column(align=True)
|
|
167
|
+
column.label(text=line.line, translate=False)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class VRM_OT_save_error_dialog_message(Operator, ExportHelper):
|
|
171
|
+
bl_idname = "vrm.save_error_dialog_message"
|
|
172
|
+
bl_label = "Save Error Message"
|
|
173
|
+
bl_description = "Save Error Message"
|
|
174
|
+
bl_options: ClassVar = {"REGISTER"}
|
|
175
|
+
|
|
176
|
+
filename_ext = ".txt"
|
|
177
|
+
filter_glob: StringProperty( # type: ignore[valid-type]
|
|
178
|
+
default="*.txt",
|
|
179
|
+
options={"HIDDEN"},
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
title: StringProperty(options={"HIDDEN"}) # type: ignore[valid-type]
|
|
183
|
+
lines: CollectionProperty( # type: ignore[valid-type]
|
|
184
|
+
type=VrmErrorDialogMessageLine, options={"HIDDEN"}
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def _restore_error_dialog(self) -> set[str]:
|
|
188
|
+
if bpy.app.version >= (4, 1):
|
|
189
|
+
return {"FINISHED"}
|
|
190
|
+
|
|
191
|
+
return show_error_dialog(
|
|
192
|
+
self.title,
|
|
193
|
+
[output.line for output in self.lines],
|
|
194
|
+
append_environment=False,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
def cancel(self, _context: Context) -> None:
|
|
198
|
+
self._restore_error_dialog()
|
|
199
|
+
|
|
200
|
+
def execute(self, _context: Context) -> set[str]:
|
|
201
|
+
message = "\n".join(output.line for output in self.lines)
|
|
202
|
+
Path(self.filepath).write_bytes(message.encode())
|
|
203
|
+
return self._restore_error_dialog()
|
|
204
|
+
|
|
205
|
+
def invoke(self, context: Context, event: Event) -> set[str]:
|
|
206
|
+
if not self.filepath:
|
|
207
|
+
local_now = dt.datetime.now(tz=None) # Get local time # noqa: DTZ005
|
|
208
|
+
formatted_time = local_now.strftime("%Y%m%d_%H%M%S")
|
|
209
|
+
self.filepath = f"vrm_error_message_{formatted_time}.txt"
|
|
210
|
+
return ExportHelper.invoke(self, context, event)
|
|
211
|
+
|
|
212
|
+
if TYPE_CHECKING:
|
|
213
|
+
# This code is auto generated.
|
|
214
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
215
|
+
filter_glob: str # type: ignore[no-redef]
|
|
216
|
+
title: str # type: ignore[no-redef]
|
|
217
|
+
lines: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
218
|
+
VrmErrorDialogMessageLine
|
|
219
|
+
]
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class WM_OT_vrm_error_dialog(Operator):
|
|
223
|
+
bl_label = "Error"
|
|
224
|
+
bl_idname = "wm.vrm_error_dialog"
|
|
225
|
+
bl_options: ClassVar = {"REGISTER"}
|
|
226
|
+
|
|
227
|
+
title: StringProperty(options={"HIDDEN"}) # type: ignore[valid-type]
|
|
228
|
+
lines: CollectionProperty( # type: ignore[valid-type]
|
|
229
|
+
type=VrmErrorDialogMessageLine, options={"HIDDEN"}
|
|
230
|
+
)
|
|
231
|
+
active_line_index: IntProperty(options={"HIDDEN"}) # type: ignore[valid-type]
|
|
232
|
+
|
|
233
|
+
def execute(self, _context: Context) -> set[str]:
|
|
234
|
+
return {"FINISHED"}
|
|
235
|
+
|
|
236
|
+
def invoke(self, context: Context, _event: Event) -> set[str]:
|
|
237
|
+
self.active_line_index = len(self.lines) - 1
|
|
238
|
+
return context.window_manager.invoke_props_dialog(self, width=700)
|
|
239
|
+
|
|
240
|
+
def draw(self, _context: Context) -> None:
|
|
241
|
+
layout = self.layout.column()
|
|
242
|
+
layout.emboss = "NONE"
|
|
243
|
+
box = layout.box()
|
|
244
|
+
box.emboss = "NORMAL"
|
|
245
|
+
row = box.split(factor=0.5, align=True)
|
|
246
|
+
row.label(text=self.title, icon="ERROR")
|
|
247
|
+
save_op = layout_operator(row, VRM_OT_save_error_dialog_message, icon="FILE")
|
|
248
|
+
save_op.title = self.title
|
|
249
|
+
for process_output_line in self.lines:
|
|
250
|
+
output = save_op.lines.add()
|
|
251
|
+
output.line = process_output_line.line
|
|
252
|
+
open_url_op = layout_operator(
|
|
253
|
+
row, VRM_OT_open_url_in_web_browser, icon="URL", text="Open Support Site"
|
|
254
|
+
)
|
|
255
|
+
open_url_op.url = "https://github.com/saturday06/VRM-Addon-for-Blender/issues"
|
|
256
|
+
box.template_list(
|
|
257
|
+
VRM_UL_vrm_error_dialog_message.bl_idname,
|
|
258
|
+
"",
|
|
259
|
+
self,
|
|
260
|
+
"lines",
|
|
261
|
+
self,
|
|
262
|
+
"active_line_index",
|
|
263
|
+
rows=20,
|
|
264
|
+
sort_lock=True,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
if TYPE_CHECKING:
|
|
268
|
+
# This code is auto generated.
|
|
269
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
270
|
+
title: str # type: ignore[no-redef]
|
|
271
|
+
lines: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
272
|
+
VrmErrorDialogMessageLine
|
|
273
|
+
]
|
|
274
|
+
active_line_index: int # type: ignore[no-redef]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_unique_indexed_directory_path(path: Path) -> Path:
|
|
7
|
+
name = path.name
|
|
8
|
+
max_retry_count = 100_000
|
|
9
|
+
for count in range(max_retry_count):
|
|
10
|
+
count_str = f".{count}" if count else ""
|
|
11
|
+
path = path.with_name(name + count_str)
|
|
12
|
+
try:
|
|
13
|
+
path.mkdir(parents=True)
|
|
14
|
+
except FileExistsError:
|
|
15
|
+
continue
|
|
16
|
+
except OSError as exception:
|
|
17
|
+
message = f"Failed to create unique directory path: {path}"
|
|
18
|
+
raise RuntimeError(message) from exception
|
|
19
|
+
return path
|
|
20
|
+
message = (
|
|
21
|
+
"Failed to create unique directory path "
|
|
22
|
+
+ f"(max retries: {max_retry_count} exceeded): {path}"
|
|
23
|
+
)
|
|
24
|
+
raise RuntimeError(message)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def create_unique_indexed_file_path(path: Path, binary: Optional[bytes] = None) -> Path:
|
|
28
|
+
suffix = path.suffix
|
|
29
|
+
stem = path.stem
|
|
30
|
+
max_retry_count = 100_000
|
|
31
|
+
|
|
32
|
+
folder_path = path.parent
|
|
33
|
+
try:
|
|
34
|
+
folder_path.mkdir(parents=True, exist_ok=True)
|
|
35
|
+
except OSError as exception:
|
|
36
|
+
message = f"Failed to create parent directory for unique file path: {path}"
|
|
37
|
+
raise RuntimeError(message) from exception
|
|
38
|
+
|
|
39
|
+
for count in range(max_retry_count):
|
|
40
|
+
count_str = f".{count}" if count else ""
|
|
41
|
+
path = path.with_name(stem + count_str + suffix)
|
|
42
|
+
|
|
43
|
+
if binary is None:
|
|
44
|
+
try:
|
|
45
|
+
if not path.exists():
|
|
46
|
+
return path
|
|
47
|
+
except OSError as exception:
|
|
48
|
+
message = f"Failed to create unique file path: {path}"
|
|
49
|
+
raise RuntimeError(message) from exception
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
path.touch(exist_ok=False)
|
|
54
|
+
except FileExistsError:
|
|
55
|
+
continue
|
|
56
|
+
except OSError as exception:
|
|
57
|
+
message = f"Failed to create unique file path: {path}"
|
|
58
|
+
raise RuntimeError(message) from exception
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
path.write_bytes(binary)
|
|
62
|
+
except OSError as exception:
|
|
63
|
+
message = f"Failed to write data to unique file path: {path}"
|
|
64
|
+
raise RuntimeError(message) from exception
|
|
65
|
+
return path
|
|
66
|
+
|
|
67
|
+
message = (
|
|
68
|
+
"Failed to create unique file path "
|
|
69
|
+
+ f"(max retries: {max_retry_count} exceeded): {path}"
|
|
70
|
+
)
|
|
71
|
+
raise RuntimeError(message)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
2
|
+
from typing import Final
|
|
3
|
+
|
|
4
|
+
GL_TRIANGLES: Final = 0x0004
|
|
5
|
+
GL_BYTE: Final = 0x1400
|
|
6
|
+
GL_UNSIGNED_BYTE: Final = 0x1401
|
|
7
|
+
GL_SHORT: Final = 0x1402
|
|
8
|
+
GL_UNSIGNED_SHORT: Final = 0x1403
|
|
9
|
+
GL_INT: Final = 0x1404
|
|
10
|
+
GL_UNSIGNED_INT: Final = 0x1405
|
|
11
|
+
GL_FLOAT: Final = 0x1406
|
|
12
|
+
GL_NEAREST: Final = 0x2600
|
|
13
|
+
GL_LINEAR: Final = 0x2601
|
|
14
|
+
GL_REPEAT: Final = 0x2901
|
|
15
|
+
GL_CLAMP_TO_EDGE: Final = 0x812F
|
|
16
|
+
GL_MIRRORED_REPEAT: Final = 0x8370
|
|
17
|
+
GL_NEAREST_MIPMAP_NEAREST: Final = 0x2700
|
|
18
|
+
GL_LINEAR_MIPMAP_NEAREST: Final = 0x2701
|
|
19
|
+
GL_NEAREST_MIPMAP_LINEAR: Final = 0x2702
|
|
20
|
+
GL_LINEAR_MIPMAP_LINEAR: Final = 0x2703
|