@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,1818 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
|
2
|
+
import uuid
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from sys import float_info
|
|
5
|
+
from typing import TYPE_CHECKING, ClassVar, Optional
|
|
6
|
+
|
|
7
|
+
import bpy
|
|
8
|
+
from bpy.app.translations import pgettext
|
|
9
|
+
from bpy.props import (
|
|
10
|
+
BoolProperty,
|
|
11
|
+
CollectionProperty,
|
|
12
|
+
EnumProperty,
|
|
13
|
+
FloatProperty,
|
|
14
|
+
FloatVectorProperty,
|
|
15
|
+
IntProperty,
|
|
16
|
+
PointerProperty,
|
|
17
|
+
StringProperty,
|
|
18
|
+
)
|
|
19
|
+
from bpy.types import (
|
|
20
|
+
Action,
|
|
21
|
+
Armature,
|
|
22
|
+
Context,
|
|
23
|
+
Image,
|
|
24
|
+
Material,
|
|
25
|
+
Mesh,
|
|
26
|
+
Object,
|
|
27
|
+
PropertyGroup,
|
|
28
|
+
)
|
|
29
|
+
from mathutils import Vector
|
|
30
|
+
|
|
31
|
+
from ...common import convert, shader
|
|
32
|
+
from ...common.animation import defer_shape_key_update
|
|
33
|
+
from ...common.logger import get_logger
|
|
34
|
+
from ...common.shader import LegacyAddonMaterial
|
|
35
|
+
from ...common.vrm0.human_bone import (
|
|
36
|
+
HumanBoneName,
|
|
37
|
+
HumanBoneSpecification,
|
|
38
|
+
HumanBoneSpecifications,
|
|
39
|
+
)
|
|
40
|
+
from ...common.vrm0.material_property import (
|
|
41
|
+
GLTF_PROPERTIES,
|
|
42
|
+
MTOON0_PROPERTIES,
|
|
43
|
+
MaterialPropertyTarget,
|
|
44
|
+
MaterialPropertyType,
|
|
45
|
+
)
|
|
46
|
+
from ...common.vrm1.expression_preset import (
|
|
47
|
+
VRM0_PRESET_UNKNOWN,
|
|
48
|
+
ExpressionPresets,
|
|
49
|
+
)
|
|
50
|
+
from ..extension_accessor import get_armature_extension, get_material_extension
|
|
51
|
+
from ..mtoon1.property_group import (
|
|
52
|
+
Mtoon1MaterialPropertyGroup,
|
|
53
|
+
Mtoon1TextureInfoPropertyGroup,
|
|
54
|
+
)
|
|
55
|
+
from ..property_group import (
|
|
56
|
+
BonePropertyGroup,
|
|
57
|
+
FloatPropertyGroup,
|
|
58
|
+
HumanoidStructureBonePropertyGroup,
|
|
59
|
+
MeshObjectPropertyGroup,
|
|
60
|
+
clear_expression_material_binds,
|
|
61
|
+
property_group_enum,
|
|
62
|
+
)
|
|
63
|
+
from ..vrm1.property_group import Vrm1HumanoidPropertyGroup
|
|
64
|
+
|
|
65
|
+
if TYPE_CHECKING:
|
|
66
|
+
from ..property_group import CollectionPropertyProtocol
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
_logger = get_logger(__name__)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Vrm0HumanoidBoneNodePropertyGroup(HumanoidStructureBonePropertyGroup):
|
|
73
|
+
def update_bone_name_candidates(
|
|
74
|
+
self,
|
|
75
|
+
armature_data: Armature,
|
|
76
|
+
target: HumanBoneSpecification,
|
|
77
|
+
bpy_bone_name_to_human_bone_specification: dict[str, HumanBoneSpecification],
|
|
78
|
+
error_bpy_bone_names: Sequence[str],
|
|
79
|
+
) -> bool:
|
|
80
|
+
new_candidates = HumanoidStructureBonePropertyGroup.find_bone_candidates(
|
|
81
|
+
armature_data,
|
|
82
|
+
target,
|
|
83
|
+
bpy_bone_name_to_human_bone_specification,
|
|
84
|
+
error_bpy_bone_names,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
bone_name_candidates = self.bone_name_candidates
|
|
88
|
+
if bone_name_candidates == new_candidates:
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
bone_name_candidates.clear()
|
|
92
|
+
bone_name_candidates.update(new_candidates)
|
|
93
|
+
return True
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_Humanoid.cs#L70-L164
|
|
97
|
+
class Vrm0HumanoidBonePropertyGroup(PropertyGroup):
|
|
98
|
+
bone: StringProperty( # type: ignore[valid-type]
|
|
99
|
+
name="VRM Humanoid Bone Name"
|
|
100
|
+
)
|
|
101
|
+
node: PointerProperty( # type: ignore[valid-type]
|
|
102
|
+
name="Bone Name",
|
|
103
|
+
type=Vrm0HumanoidBoneNodePropertyGroup,
|
|
104
|
+
)
|
|
105
|
+
use_default_values: BoolProperty( # type: ignore[valid-type]
|
|
106
|
+
name="Unity's HumanLimit.useDefaultValues",
|
|
107
|
+
default=True,
|
|
108
|
+
)
|
|
109
|
+
min: FloatVectorProperty( # type: ignore[valid-type]
|
|
110
|
+
size=3,
|
|
111
|
+
name="Unity's HumanLimit.min",
|
|
112
|
+
)
|
|
113
|
+
max: FloatVectorProperty( # type: ignore[valid-type]
|
|
114
|
+
size=3,
|
|
115
|
+
name="Unity's HumanLimit.max",
|
|
116
|
+
)
|
|
117
|
+
center: FloatVectorProperty( # type: ignore[valid-type]
|
|
118
|
+
size=3,
|
|
119
|
+
name="Unity's HumanLimit.center",
|
|
120
|
+
)
|
|
121
|
+
axis_length: FloatProperty( # type: ignore[valid-type]
|
|
122
|
+
name="Unity's HumanLimit.axisLength"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
def specification(self) -> HumanBoneSpecification:
|
|
126
|
+
name = HumanBoneName.from_str(self.bone)
|
|
127
|
+
if name is None:
|
|
128
|
+
message = f'HumanBone "{self.bone}" is invalid'
|
|
129
|
+
raise ValueError(message)
|
|
130
|
+
return HumanBoneSpecifications.get(name)
|
|
131
|
+
|
|
132
|
+
if TYPE_CHECKING:
|
|
133
|
+
# This code is auto generated.
|
|
134
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
135
|
+
bone: str # type: ignore[no-redef]
|
|
136
|
+
node: Vrm0HumanoidBoneNodePropertyGroup # type: ignore[no-redef]
|
|
137
|
+
use_default_values: bool # type: ignore[no-redef]
|
|
138
|
+
min: Sequence[float] # type: ignore[no-redef]
|
|
139
|
+
max: Sequence[float] # type: ignore[no-redef]
|
|
140
|
+
center: Sequence[float] # type: ignore[no-redef]
|
|
141
|
+
axis_length: float # type: ignore[no-redef]
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_Humanoid.cs#L166-L195
|
|
145
|
+
class Vrm0HumanoidPropertyGroup(PropertyGroup):
|
|
146
|
+
human_bones: CollectionProperty( # type: ignore[valid-type]
|
|
147
|
+
name="Human Bones",
|
|
148
|
+
type=Vrm0HumanoidBonePropertyGroup,
|
|
149
|
+
)
|
|
150
|
+
arm_stretch: FloatProperty( # type: ignore[valid-type]
|
|
151
|
+
name="Arm Stretch",
|
|
152
|
+
default=0.05,
|
|
153
|
+
)
|
|
154
|
+
leg_stretch: FloatProperty( # type: ignore[valid-type]
|
|
155
|
+
name="Leg Stretch",
|
|
156
|
+
default=0.05,
|
|
157
|
+
)
|
|
158
|
+
upper_arm_twist: FloatProperty( # type: ignore[valid-type]
|
|
159
|
+
name="Upper Arm Twist",
|
|
160
|
+
default=0.5,
|
|
161
|
+
)
|
|
162
|
+
lower_arm_twist: FloatProperty( # type: ignore[valid-type]
|
|
163
|
+
name="Lower Arm Twist",
|
|
164
|
+
default=0.5,
|
|
165
|
+
)
|
|
166
|
+
upper_leg_twist: FloatProperty( # type: ignore[valid-type]
|
|
167
|
+
name="Upper Leg Twist",
|
|
168
|
+
default=0.5,
|
|
169
|
+
)
|
|
170
|
+
lower_leg_twist: FloatProperty( # type: ignore[valid-type]
|
|
171
|
+
name="Lower Leg Twist",
|
|
172
|
+
default=0.5,
|
|
173
|
+
)
|
|
174
|
+
feet_spacing: FloatProperty( # type: ignore[valid-type]
|
|
175
|
+
name="Feet Spacing",
|
|
176
|
+
default=0,
|
|
177
|
+
)
|
|
178
|
+
has_translation_dof: BoolProperty( # type: ignore[valid-type]
|
|
179
|
+
name="Has Translation DoF",
|
|
180
|
+
default=False,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
POSE_AUTO_POSE = Vrm1HumanoidPropertyGroup.POSE_AUTO_POSE
|
|
184
|
+
POSE_REST_POSITION_POSE = Vrm1HumanoidPropertyGroup.POSE_REST_POSITION_POSE
|
|
185
|
+
POSE_CURRENT_POSE = Vrm1HumanoidPropertyGroup.POSE_CURRENT_POSE
|
|
186
|
+
POSE_CUSTOM_POSE = Vrm1HumanoidPropertyGroup.POSE_CUSTOM_POSE
|
|
187
|
+
|
|
188
|
+
pose: bpy.props.EnumProperty( # type: ignore[valid-type]
|
|
189
|
+
items=Vrm1HumanoidPropertyGroup.pose_enum.items(),
|
|
190
|
+
name="T-Pose",
|
|
191
|
+
description="T-Pose",
|
|
192
|
+
default=POSE_AUTO_POSE.identifier,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# for T-Pose
|
|
196
|
+
def _update_pose_library(self, _context: Context) -> None:
|
|
197
|
+
self.pose_marker_name = ""
|
|
198
|
+
|
|
199
|
+
pose_library: PointerProperty( # type: ignore[valid-type]
|
|
200
|
+
type=Action,
|
|
201
|
+
name="Pose Library",
|
|
202
|
+
description="Pose library for T Pose",
|
|
203
|
+
update=_update_pose_library,
|
|
204
|
+
)
|
|
205
|
+
pose_marker_name: StringProperty() # type: ignore[valid-type]
|
|
206
|
+
|
|
207
|
+
# for UI
|
|
208
|
+
pointer_to_last_bone_names_str: ClassVar[dict[int, str]] = {}
|
|
209
|
+
initial_automatic_bone_assignment: BoolProperty( # type: ignore[valid-type]
|
|
210
|
+
default=True
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
def _update_filter_by_human_bone_hierarchy(self, _context: Context) -> None:
|
|
214
|
+
if not isinstance(armature_data := self.id_data, Armature):
|
|
215
|
+
return
|
|
216
|
+
HumanoidStructureBonePropertyGroup.clear_bone_name_candidates_cache(
|
|
217
|
+
human_bone.node for human_bone in self.human_bones
|
|
218
|
+
)
|
|
219
|
+
HumanoidStructureBonePropertyGroup.update_all_vrm0_bone_name_candidates(
|
|
220
|
+
armature_data
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
filter_by_human_bone_hierarchy: BoolProperty( # type: ignore[valid-type]
|
|
224
|
+
name="Filter by VRM Human Bone Hierarchy",
|
|
225
|
+
description="Restrict selectable bones by VRM humanoid hierarchy",
|
|
226
|
+
default=True,
|
|
227
|
+
update=_update_filter_by_human_bone_hierarchy,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
def human_bone_duplication_error_messages(self) -> list[tuple[str, str]]:
|
|
231
|
+
messages: list[tuple[str, str]] = []
|
|
232
|
+
bone_name_to_human_bone_names: dict[str, list[str]] = {}
|
|
233
|
+
for human_bone in self.human_bones:
|
|
234
|
+
bone_name = human_bone.node.bone_name
|
|
235
|
+
if not bone_name:
|
|
236
|
+
continue
|
|
237
|
+
|
|
238
|
+
human_bone_names = bone_name_to_human_bone_names.get(bone_name)
|
|
239
|
+
if human_bone_names is None:
|
|
240
|
+
human_bone_names = []
|
|
241
|
+
bone_name_to_human_bone_names[bone_name] = human_bone_names
|
|
242
|
+
|
|
243
|
+
human_bone_name = HumanBoneName.from_str(human_bone.bone)
|
|
244
|
+
if human_bone_name is None:
|
|
245
|
+
human_bone_names.append(human_bone.bone)
|
|
246
|
+
continue
|
|
247
|
+
human_bone_names.append(HumanBoneSpecifications.get(human_bone_name).title)
|
|
248
|
+
|
|
249
|
+
for bone_name, human_bone_names in bone_name_to_human_bone_names.items():
|
|
250
|
+
if len(human_bone_names) < 2:
|
|
251
|
+
continue
|
|
252
|
+
messages.append(
|
|
253
|
+
(
|
|
254
|
+
bone_name,
|
|
255
|
+
pgettext(
|
|
256
|
+
'Bone "{bone_name}" is assigned to multiple VRM Human Bones:'
|
|
257
|
+
+ " {human_bone_names}."
|
|
258
|
+
).format(
|
|
259
|
+
bone_name=bone_name,
|
|
260
|
+
human_bone_names=", ".join(human_bone_names),
|
|
261
|
+
),
|
|
262
|
+
)
|
|
263
|
+
)
|
|
264
|
+
return messages
|
|
265
|
+
|
|
266
|
+
def error_messages(self) -> Sequence[str]:
|
|
267
|
+
messages = [
|
|
268
|
+
message for _, message in self.human_bone_duplication_error_messages()
|
|
269
|
+
]
|
|
270
|
+
|
|
271
|
+
for human_bone_name, human_bone in (
|
|
272
|
+
(human_bone_name, human_bone)
|
|
273
|
+
for human_bone in self.human_bones
|
|
274
|
+
for name in HumanBoneSpecifications.required_names
|
|
275
|
+
if human_bone.bone == name
|
|
276
|
+
and (human_bone_name := HumanBoneName.from_str(name))
|
|
277
|
+
):
|
|
278
|
+
specification = HumanBoneSpecifications.get(human_bone_name)
|
|
279
|
+
bone_name = human_bone.node.bone_name
|
|
280
|
+
if not bone_name:
|
|
281
|
+
if specification.requirement:
|
|
282
|
+
messages.append(
|
|
283
|
+
pgettext(
|
|
284
|
+
'Please assign Required VRM Human Bone "{human_bone_name}".'
|
|
285
|
+
).format(human_bone_name=specification.title)
|
|
286
|
+
)
|
|
287
|
+
continue
|
|
288
|
+
if (
|
|
289
|
+
self.filter_by_human_bone_hierarchy
|
|
290
|
+
and bone_name not in human_bone.node.bone_name_candidates
|
|
291
|
+
):
|
|
292
|
+
messages.append(
|
|
293
|
+
pgettext(
|
|
294
|
+
'Couldn\'t assign "{bone_name}" bone'
|
|
295
|
+
+ ' to VRM Human Bone "{human_bone_name}". '
|
|
296
|
+
).format(bone_name=bone_name, human_bone_name=specification.title)
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
return messages
|
|
300
|
+
|
|
301
|
+
def bones_are_correctly_assigned(self) -> bool:
|
|
302
|
+
return len(self.error_messages()) == 0
|
|
303
|
+
|
|
304
|
+
@staticmethod
|
|
305
|
+
def update_all_bone_name_candidates(
|
|
306
|
+
context: Context,
|
|
307
|
+
armature_data_name: str,
|
|
308
|
+
*,
|
|
309
|
+
force: bool = False,
|
|
310
|
+
) -> None:
|
|
311
|
+
armature_data = context.blend_data.armatures.get(armature_data_name)
|
|
312
|
+
if not armature_data:
|
|
313
|
+
return
|
|
314
|
+
|
|
315
|
+
ext = get_armature_extension(armature_data)
|
|
316
|
+
if not ext.is_vrm0():
|
|
317
|
+
return
|
|
318
|
+
|
|
319
|
+
bone_names_str = "\n".join(
|
|
320
|
+
sorted(
|
|
321
|
+
bone.name + "\n" + (parent.name if (parent := bone.parent) else "")
|
|
322
|
+
for bone in armature_data.bones.values()
|
|
323
|
+
)
|
|
324
|
+
)
|
|
325
|
+
humanoid = ext.vrm0.humanoid
|
|
326
|
+
pointer_key = humanoid.as_pointer()
|
|
327
|
+
pointer_to_last_bone_names_str = humanoid.pointer_to_last_bone_names_str
|
|
328
|
+
last_bone_names_str = pointer_to_last_bone_names_str.get(pointer_key)
|
|
329
|
+
if not force and last_bone_names_str == bone_names_str:
|
|
330
|
+
return
|
|
331
|
+
pointer_to_last_bone_names_str[pointer_key] = bone_names_str
|
|
332
|
+
|
|
333
|
+
HumanoidStructureBonePropertyGroup.update_all_vrm0_bone_name_candidates(
|
|
334
|
+
armature_data
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
@staticmethod
|
|
338
|
+
def fixup_human_bones(obj: Object) -> None:
|
|
339
|
+
armature_data = obj.data
|
|
340
|
+
if not isinstance(armature_data, Armature):
|
|
341
|
+
return
|
|
342
|
+
|
|
343
|
+
humanoid = get_armature_extension(armature_data).vrm0.humanoid
|
|
344
|
+
|
|
345
|
+
# Add bone maps that don't exist
|
|
346
|
+
refresh = False
|
|
347
|
+
for human_bone_name in HumanBoneSpecifications.all_names:
|
|
348
|
+
if any(
|
|
349
|
+
human_bone.bone == human_bone_name
|
|
350
|
+
for human_bone in humanoid.human_bones
|
|
351
|
+
):
|
|
352
|
+
continue
|
|
353
|
+
human_bone = humanoid.human_bones.add()
|
|
354
|
+
human_bone.bone = human_bone_name
|
|
355
|
+
refresh = True
|
|
356
|
+
|
|
357
|
+
# Remove duplicate bone maps
|
|
358
|
+
fixup = True
|
|
359
|
+
while fixup:
|
|
360
|
+
fixup = False
|
|
361
|
+
found_bones: list[str] = []
|
|
362
|
+
for i, human_bone in enumerate(list(humanoid.human_bones)):
|
|
363
|
+
if (
|
|
364
|
+
human_bone.bone in HumanBoneSpecifications.all_names
|
|
365
|
+
and human_bone.bone not in found_bones
|
|
366
|
+
):
|
|
367
|
+
found_bones.append(human_bone.bone)
|
|
368
|
+
continue
|
|
369
|
+
humanoid.human_bones.remove(i)
|
|
370
|
+
refresh = True
|
|
371
|
+
fixup = True
|
|
372
|
+
break
|
|
373
|
+
|
|
374
|
+
# If multiple bone maps have the same Blender bone assigned, remove one of them
|
|
375
|
+
fixup = True
|
|
376
|
+
while fixup:
|
|
377
|
+
fixup = False
|
|
378
|
+
found_node_bone_names: list[str] = []
|
|
379
|
+
for human_bone in humanoid.human_bones:
|
|
380
|
+
if not human_bone.node.bone_name:
|
|
381
|
+
continue
|
|
382
|
+
if human_bone.node.bone_name not in found_node_bone_names:
|
|
383
|
+
found_node_bone_names.append(human_bone.node.bone_name)
|
|
384
|
+
continue
|
|
385
|
+
human_bone.node.bone_name = ""
|
|
386
|
+
refresh = True
|
|
387
|
+
fixup = True
|
|
388
|
+
break
|
|
389
|
+
|
|
390
|
+
if not refresh:
|
|
391
|
+
return
|
|
392
|
+
|
|
393
|
+
secondary_animation = get_armature_extension(
|
|
394
|
+
armature_data
|
|
395
|
+
).vrm0.secondary_animation
|
|
396
|
+
secondary_animation.fixup(obj)
|
|
397
|
+
|
|
398
|
+
if TYPE_CHECKING:
|
|
399
|
+
# This code is auto generated.
|
|
400
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
401
|
+
human_bones: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
402
|
+
Vrm0HumanoidBonePropertyGroup
|
|
403
|
+
]
|
|
404
|
+
arm_stretch: float # type: ignore[no-redef]
|
|
405
|
+
leg_stretch: float # type: ignore[no-redef]
|
|
406
|
+
upper_arm_twist: float # type: ignore[no-redef]
|
|
407
|
+
lower_arm_twist: float # type: ignore[no-redef]
|
|
408
|
+
upper_leg_twist: float # type: ignore[no-redef]
|
|
409
|
+
lower_leg_twist: float # type: ignore[no-redef]
|
|
410
|
+
feet_spacing: float # type: ignore[no-redef]
|
|
411
|
+
has_translation_dof: bool # type: ignore[no-redef]
|
|
412
|
+
pose: str # type: ignore[no-redef]
|
|
413
|
+
pose_library: Optional[Action] # type: ignore[no-redef]
|
|
414
|
+
pose_marker_name: str # type: ignore[no-redef]
|
|
415
|
+
initial_automatic_bone_assignment: bool # type: ignore[no-redef]
|
|
416
|
+
filter_by_human_bone_hierarchy: bool # type: ignore[no-redef]
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_FirstPerson.cs#L10-L22
|
|
420
|
+
class Vrm0DegreeMapPropertyGroup(PropertyGroup):
|
|
421
|
+
curve: FloatVectorProperty( # type: ignore[valid-type]
|
|
422
|
+
size=8,
|
|
423
|
+
name="Curve",
|
|
424
|
+
default=(0, 0, 0, 1, 1, 1, 1, 0),
|
|
425
|
+
)
|
|
426
|
+
x_range: FloatProperty( # type: ignore[valid-type]
|
|
427
|
+
name="X Range",
|
|
428
|
+
default=90,
|
|
429
|
+
)
|
|
430
|
+
y_range: FloatProperty( # type: ignore[valid-type]
|
|
431
|
+
name="Y Range",
|
|
432
|
+
default=10,
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
if TYPE_CHECKING:
|
|
436
|
+
# This code is auto generated.
|
|
437
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
438
|
+
curve: Sequence[float] # type: ignore[no-redef]
|
|
439
|
+
x_range: float # type: ignore[no-redef]
|
|
440
|
+
y_range: float # type: ignore[no-redef]
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_FirstPerson.cs#L32-L41
|
|
444
|
+
class Vrm0MeshAnnotationPropertyGroup(PropertyGroup):
|
|
445
|
+
mesh: PointerProperty( # type: ignore[valid-type]
|
|
446
|
+
name="Mesh",
|
|
447
|
+
type=MeshObjectPropertyGroup,
|
|
448
|
+
description="Mesh on restrict render in the first person camera",
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
first_person_flag_enum, *__first_person_flags = property_group_enum(
|
|
452
|
+
("Auto", "Auto", "Auto restrict render", "NONE", 0),
|
|
453
|
+
(
|
|
454
|
+
"FirstPersonOnly",
|
|
455
|
+
"First-Person Only",
|
|
456
|
+
"(Maybe needless) Restrict render in the third person camera",
|
|
457
|
+
"NONE",
|
|
458
|
+
1,
|
|
459
|
+
),
|
|
460
|
+
(
|
|
461
|
+
"ThirdPersonOnly",
|
|
462
|
+
"Third-Person Only",
|
|
463
|
+
"Restrict render in the first person camera for face, hairs or hat",
|
|
464
|
+
"NONE",
|
|
465
|
+
2,
|
|
466
|
+
),
|
|
467
|
+
("Both", "Both", "No restrict render for body, arms or legs", "NONE", 3),
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
first_person_flag: EnumProperty( # type: ignore[valid-type]
|
|
471
|
+
items=first_person_flag_enum.items(),
|
|
472
|
+
name="First Person Flag",
|
|
473
|
+
description="Restrict render in the first person camera",
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
if TYPE_CHECKING:
|
|
477
|
+
# This code is auto generated.
|
|
478
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
479
|
+
mesh: MeshObjectPropertyGroup # type: ignore[no-redef]
|
|
480
|
+
first_person_flag: str # type: ignore[no-redef]
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_FirstPerson.cs#L50-L91
|
|
484
|
+
class Vrm0FirstPersonPropertyGroup(PropertyGroup):
|
|
485
|
+
first_person_bone: PointerProperty( # type: ignore[valid-type]
|
|
486
|
+
name="Bone",
|
|
487
|
+
type=BonePropertyGroup,
|
|
488
|
+
description="Bone to follow the first person camera",
|
|
489
|
+
)
|
|
490
|
+
first_person_bone_offset: FloatVectorProperty( # type: ignore[valid-type]
|
|
491
|
+
size=3,
|
|
492
|
+
name="Bone Offset",
|
|
493
|
+
description=(
|
|
494
|
+
"Offset from the first person bone to follow the first person camera"
|
|
495
|
+
),
|
|
496
|
+
subtype="TRANSLATION",
|
|
497
|
+
unit="LENGTH",
|
|
498
|
+
default=(0, 0, 0),
|
|
499
|
+
)
|
|
500
|
+
mesh_annotations: CollectionProperty( # type: ignore[valid-type]
|
|
501
|
+
name="Mesh Annotations",
|
|
502
|
+
type=Vrm0MeshAnnotationPropertyGroup,
|
|
503
|
+
)
|
|
504
|
+
look_at_type_name_enum, *__look_at_types = property_group_enum(
|
|
505
|
+
("Bone", "Bone", "Use bones to eye movement", "BONE_DATA", 0),
|
|
506
|
+
(
|
|
507
|
+
"BlendShape",
|
|
508
|
+
"Blend Shape",
|
|
509
|
+
"Use blend Shapes of VRM Blend Shape Proxy to eye movement.",
|
|
510
|
+
"SHAPEKEY_DATA",
|
|
511
|
+
1,
|
|
512
|
+
),
|
|
513
|
+
)
|
|
514
|
+
look_at_type_name: EnumProperty( # type: ignore[valid-type]
|
|
515
|
+
items=look_at_type_name_enum.items(),
|
|
516
|
+
name="Look At Type",
|
|
517
|
+
description="How to eye movement",
|
|
518
|
+
)
|
|
519
|
+
look_at_horizontal_inner: PointerProperty( # type: ignore[valid-type]
|
|
520
|
+
type=Vrm0DegreeMapPropertyGroup,
|
|
521
|
+
name="Look At Horizontal Inner",
|
|
522
|
+
)
|
|
523
|
+
look_at_horizontal_outer: PointerProperty( # type: ignore[valid-type]
|
|
524
|
+
type=Vrm0DegreeMapPropertyGroup,
|
|
525
|
+
name="Look At Horizontal Outer",
|
|
526
|
+
)
|
|
527
|
+
look_at_vertical_down: PointerProperty( # type: ignore[valid-type]
|
|
528
|
+
type=Vrm0DegreeMapPropertyGroup,
|
|
529
|
+
name="Look At Vertical Down",
|
|
530
|
+
)
|
|
531
|
+
look_at_vertical_up: PointerProperty( # type: ignore[valid-type]
|
|
532
|
+
type=Vrm0DegreeMapPropertyGroup,
|
|
533
|
+
name="lookAt Vertical Up",
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
# for UI
|
|
537
|
+
active_mesh_annotation_index: IntProperty(min=0) # type: ignore[valid-type]
|
|
538
|
+
|
|
539
|
+
if TYPE_CHECKING:
|
|
540
|
+
# This code is auto generated.
|
|
541
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
542
|
+
first_person_bone: BonePropertyGroup # type: ignore[no-redef]
|
|
543
|
+
first_person_bone_offset: Sequence[float] # type: ignore[no-redef]
|
|
544
|
+
mesh_annotations: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
545
|
+
Vrm0MeshAnnotationPropertyGroup
|
|
546
|
+
]
|
|
547
|
+
look_at_type_name: str # type: ignore[no-redef]
|
|
548
|
+
look_at_horizontal_inner: Vrm0DegreeMapPropertyGroup # type: ignore[no-redef]
|
|
549
|
+
look_at_horizontal_outer: Vrm0DegreeMapPropertyGroup # type: ignore[no-redef]
|
|
550
|
+
look_at_vertical_down: Vrm0DegreeMapPropertyGroup # type: ignore[no-redef]
|
|
551
|
+
look_at_vertical_up: Vrm0DegreeMapPropertyGroup # type: ignore[no-redef]
|
|
552
|
+
active_mesh_annotation_index: int # type: ignore[no-redef]
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_BlendShape.cs#L18-L30
|
|
556
|
+
class Vrm0BlendShapeBindPropertyGroup(PropertyGroup):
|
|
557
|
+
def _update_preview(self, context: Context) -> None:
|
|
558
|
+
if not isinstance(armature_data := self.id_data, Armature):
|
|
559
|
+
return
|
|
560
|
+
Vrm0BlendShapeGroupPropertyGroup.apply_previews(context, armature_data)
|
|
561
|
+
|
|
562
|
+
mesh: PointerProperty( # type: ignore[valid-type]
|
|
563
|
+
name="Mesh",
|
|
564
|
+
type=MeshObjectPropertyGroup,
|
|
565
|
+
update=_update_preview,
|
|
566
|
+
)
|
|
567
|
+
index: StringProperty( # type: ignore[valid-type]
|
|
568
|
+
name="Index",
|
|
569
|
+
update=_update_preview,
|
|
570
|
+
)
|
|
571
|
+
weight: FloatProperty( # type: ignore[valid-type]
|
|
572
|
+
name="Weight",
|
|
573
|
+
min=0,
|
|
574
|
+
default=1,
|
|
575
|
+
max=1,
|
|
576
|
+
subtype="FACTOR",
|
|
577
|
+
update=_update_preview,
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
if TYPE_CHECKING:
|
|
581
|
+
# This code is auto generated.
|
|
582
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
583
|
+
mesh: MeshObjectPropertyGroup # type: ignore[no-redef]
|
|
584
|
+
index: str # type: ignore[no-redef]
|
|
585
|
+
weight: float # type: ignore[no-redef]
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
def reset_blend_shape_material_value_binds(context: Context) -> None:
|
|
589
|
+
clear_expression_material_binds(context)
|
|
590
|
+
for armature_data in context.blend_data.armatures:
|
|
591
|
+
Vrm0BlendShapeGroupPropertyGroup.apply_previews(context, armature_data)
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_BlendShape.cs#L9-L16
|
|
595
|
+
class Vrm0MaterialValueBindPropertyGroup(PropertyGroup):
|
|
596
|
+
material: PointerProperty( # type: ignore[valid-type]
|
|
597
|
+
name="Material",
|
|
598
|
+
type=Material,
|
|
599
|
+
update=lambda _, context: reset_blend_shape_material_value_binds(context),
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
# Use StringProperty instead of EnumProperty for property_name.
|
|
603
|
+
# This is necessary to allow arbitrary values to be entered.
|
|
604
|
+
property_name: StringProperty( # type: ignore[valid-type]
|
|
605
|
+
name="Property Name",
|
|
606
|
+
update=lambda _, context: reset_blend_shape_material_value_binds(context),
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
target_value: CollectionProperty( # type: ignore[valid-type]
|
|
610
|
+
name="Target Value",
|
|
611
|
+
type=FloatPropertyGroup,
|
|
612
|
+
)
|
|
613
|
+
|
|
614
|
+
def _get_target_value_as_rgb(self) -> tuple[float, float, float]:
|
|
615
|
+
r, g, b, _a = self.read_target_value_as_float4()
|
|
616
|
+
return (
|
|
617
|
+
r,
|
|
618
|
+
g,
|
|
619
|
+
b,
|
|
620
|
+
)
|
|
621
|
+
|
|
622
|
+
def _set_target_value_as_rgb(self, value: Sequence[float]) -> None:
|
|
623
|
+
if len(value) < 3:
|
|
624
|
+
return
|
|
625
|
+
r, g, b = value[:3]
|
|
626
|
+
while len(self.target_value) < 4:
|
|
627
|
+
self.target_value.add()
|
|
628
|
+
while len(self.target_value) > 4:
|
|
629
|
+
self.target_value.remove(len(self.target_value) - 1)
|
|
630
|
+
self.target_value[0].value = r
|
|
631
|
+
self.target_value[1].value = g
|
|
632
|
+
self.target_value[2].value = b
|
|
633
|
+
self.target_value[3].value = 1.0
|
|
634
|
+
|
|
635
|
+
target_value_as_rgb: FloatVectorProperty( # type: ignore[valid-type]
|
|
636
|
+
name="Color",
|
|
637
|
+
size=3,
|
|
638
|
+
subtype="COLOR",
|
|
639
|
+
get=_get_target_value_as_rgb,
|
|
640
|
+
set=_set_target_value_as_rgb,
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
def _get_target_value_as_rgba(self) -> tuple[float, float, float, float]:
|
|
644
|
+
return self.read_target_value_as_float4()
|
|
645
|
+
|
|
646
|
+
def _set_target_value_as_rgba(self, value: Sequence[float]) -> None:
|
|
647
|
+
if len(value) < 4:
|
|
648
|
+
return
|
|
649
|
+
r, g, b, a = value[:4]
|
|
650
|
+
while len(self.target_value) < 4:
|
|
651
|
+
self.target_value.add()
|
|
652
|
+
while len(self.target_value) > 4:
|
|
653
|
+
self.target_value.remove(len(self.target_value) - 1)
|
|
654
|
+
self.target_value[0].value = r
|
|
655
|
+
self.target_value[1].value = g
|
|
656
|
+
self.target_value[2].value = b
|
|
657
|
+
self.target_value[3].value = a
|
|
658
|
+
|
|
659
|
+
target_value_as_rgba: FloatVectorProperty( # type: ignore[valid-type]
|
|
660
|
+
name="Color",
|
|
661
|
+
size=4,
|
|
662
|
+
subtype="COLOR",
|
|
663
|
+
get=_get_target_value_as_rgba,
|
|
664
|
+
set=_set_target_value_as_rgba,
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
def _set_target_value_uv(self, index: int, value: float) -> None:
|
|
668
|
+
u_scale, v_scale, u_offset, v_offset = self.read_target_value_as_float4()
|
|
669
|
+
values = [u_scale, v_scale, u_offset, v_offset]
|
|
670
|
+
values[index] = value
|
|
671
|
+
while len(self.target_value) < 4:
|
|
672
|
+
self.target_value.add()
|
|
673
|
+
while len(self.target_value) > 4:
|
|
674
|
+
self.target_value.remove(len(self.target_value) - 1)
|
|
675
|
+
for i, v in enumerate(values):
|
|
676
|
+
self.target_value[i].value = v
|
|
677
|
+
|
|
678
|
+
def _get_target_value_tiling_s(self) -> float:
|
|
679
|
+
return self.read_target_value_as_float4()[0]
|
|
680
|
+
|
|
681
|
+
def _set_target_value_tiling_s(self, value: float) -> None:
|
|
682
|
+
self._set_target_value_uv(0, value)
|
|
683
|
+
|
|
684
|
+
target_value_tiling_s: FloatProperty( # type: ignore[valid-type]
|
|
685
|
+
name="Tiling X",
|
|
686
|
+
get=_get_target_value_tiling_s,
|
|
687
|
+
set=_set_target_value_tiling_s,
|
|
688
|
+
)
|
|
689
|
+
|
|
690
|
+
def _get_target_value_tiling_t(self) -> float:
|
|
691
|
+
return self.read_target_value_as_float4()[1]
|
|
692
|
+
|
|
693
|
+
def _set_target_value_tiling_t(self, value: float) -> None:
|
|
694
|
+
self._set_target_value_uv(1, value)
|
|
695
|
+
|
|
696
|
+
target_value_tiling_t: FloatProperty( # type: ignore[valid-type]
|
|
697
|
+
name="Tiling Y",
|
|
698
|
+
get=_get_target_value_tiling_t,
|
|
699
|
+
set=_set_target_value_tiling_t,
|
|
700
|
+
)
|
|
701
|
+
|
|
702
|
+
def _get_target_value_offset_s(self) -> float:
|
|
703
|
+
return self.read_target_value_as_float4()[2]
|
|
704
|
+
|
|
705
|
+
def _set_target_value_offset_s(self, value: float) -> None:
|
|
706
|
+
self._set_target_value_uv(2, value)
|
|
707
|
+
|
|
708
|
+
target_value_offset_s: FloatProperty( # type: ignore[valid-type]
|
|
709
|
+
name="Offset X",
|
|
710
|
+
get=_get_target_value_offset_s,
|
|
711
|
+
set=_set_target_value_offset_s,
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
def _get_target_value_offset_t(self) -> float:
|
|
715
|
+
return self.read_target_value_as_float4()[3]
|
|
716
|
+
|
|
717
|
+
def _set_target_value_offset_t(self, value: float) -> None:
|
|
718
|
+
self._set_target_value_uv(3, value)
|
|
719
|
+
|
|
720
|
+
target_value_offset_t: FloatProperty( # type: ignore[valid-type]
|
|
721
|
+
name="Offset Y",
|
|
722
|
+
get=_get_target_value_offset_t,
|
|
723
|
+
set=_set_target_value_offset_t,
|
|
724
|
+
)
|
|
725
|
+
|
|
726
|
+
def read_default_target_value(self) -> Optional[tuple[float, float, float, float]]:
|
|
727
|
+
material = self.material
|
|
728
|
+
is_mtoon = material and (
|
|
729
|
+
get_material_extension(material).mtoon1.enabled
|
|
730
|
+
or (
|
|
731
|
+
(legacy_addon_material := LegacyAddonMaterial.try_parse(material))
|
|
732
|
+
and legacy_addon_material.shader_name == "MToon_unversioned"
|
|
733
|
+
)
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
for material_property in (
|
|
737
|
+
list(MTOON0_PROPERTIES.values()) + list(GLTF_PROPERTIES.values())
|
|
738
|
+
if is_mtoon
|
|
739
|
+
else list(GLTF_PROPERTIES.values()) + list(MTOON0_PROPERTIES.values())
|
|
740
|
+
):
|
|
741
|
+
if material_property.name != self.property_name:
|
|
742
|
+
continue
|
|
743
|
+
if material_property.type in {
|
|
744
|
+
MaterialPropertyType.RGB,
|
|
745
|
+
MaterialPropertyType.RGBA,
|
|
746
|
+
}:
|
|
747
|
+
return (1.0, 1.0, 1.0, 1.0)
|
|
748
|
+
if material_property.type in {
|
|
749
|
+
MaterialPropertyType.UV,
|
|
750
|
+
MaterialPropertyType.UV_S,
|
|
751
|
+
MaterialPropertyType.UV_T,
|
|
752
|
+
}:
|
|
753
|
+
return (1.0, 1.0, 0.0, 0.0)
|
|
754
|
+
return None
|
|
755
|
+
|
|
756
|
+
def read_target_value_as_float4(self) -> tuple[float, float, float, float]:
|
|
757
|
+
default_target_value = self.read_default_target_value()
|
|
758
|
+
if default_target_value is None:
|
|
759
|
+
default_target_value = (0.0, 0.0, 0.0, 0.0)
|
|
760
|
+
target_value = self.target_value
|
|
761
|
+
return (
|
|
762
|
+
target_value[0].value if len(target_value) > 0 else default_target_value[0],
|
|
763
|
+
target_value[1].value if len(target_value) > 1 else default_target_value[1],
|
|
764
|
+
target_value[2].value if len(target_value) > 2 else default_target_value[2],
|
|
765
|
+
target_value[3].value if len(target_value) > 3 else default_target_value[3],
|
|
766
|
+
)
|
|
767
|
+
|
|
768
|
+
def read_target_value_as_float_list(self) -> list[float]:
|
|
769
|
+
target_value = self.target_value
|
|
770
|
+
default_target_value = self.read_default_target_value()
|
|
771
|
+
if default_target_value is None:
|
|
772
|
+
return [value.value for value in target_value]
|
|
773
|
+
return [
|
|
774
|
+
target_value[i].value if i < len(target_value) else default_target_value[i]
|
|
775
|
+
for i in range(len(default_target_value))
|
|
776
|
+
]
|
|
777
|
+
|
|
778
|
+
if TYPE_CHECKING:
|
|
779
|
+
# This code is auto generated.
|
|
780
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
781
|
+
material: Optional[Material] # type: ignore[no-redef]
|
|
782
|
+
property_name: str # type: ignore[no-redef]
|
|
783
|
+
target_value: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
784
|
+
FloatPropertyGroup
|
|
785
|
+
]
|
|
786
|
+
target_value_as_rgb: Sequence[float] # type: ignore[no-redef]
|
|
787
|
+
target_value_as_rgba: Sequence[float] # type: ignore[no-redef]
|
|
788
|
+
target_value_tiling_s: float # type: ignore[no-redef]
|
|
789
|
+
target_value_tiling_t: float # type: ignore[no-redef]
|
|
790
|
+
target_value_offset_s: float # type: ignore[no-redef]
|
|
791
|
+
target_value_offset_t: float # type: ignore[no-redef]
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_BlendShape.cs#L62-L99
|
|
795
|
+
class Vrm0BlendShapeGroupPropertyGroup(PropertyGroup):
|
|
796
|
+
name: StringProperty( # type: ignore[valid-type]
|
|
797
|
+
name="Name",
|
|
798
|
+
description="Name of the blendshape group",
|
|
799
|
+
)
|
|
800
|
+
|
|
801
|
+
preset_name_enum, (PRESET_NAME_UNKNOWN, *__preset_names) = property_group_enum(
|
|
802
|
+
(VRM0_PRESET_UNKNOWN, "Unknown", "", "SHAPEKEY_DATA", 0),
|
|
803
|
+
(ExpressionPresets.NEUTRAL.vrm0_preset, "Neutral", "", "VIEW_ORTHO", 1),
|
|
804
|
+
(ExpressionPresets.AA.vrm0_preset, "A", "", "EVENT_A", 2),
|
|
805
|
+
(ExpressionPresets.IH.vrm0_preset, "I", "", "EVENT_I", 3),
|
|
806
|
+
(ExpressionPresets.OU.vrm0_preset, "U", "", "EVENT_U", 4),
|
|
807
|
+
(ExpressionPresets.EE.vrm0_preset, "E", "", "EVENT_E", 5),
|
|
808
|
+
(ExpressionPresets.OH.vrm0_preset, "O", "", "EVENT_O", 6),
|
|
809
|
+
(ExpressionPresets.BLINK.vrm0_preset, "Blink", "", "HIDE_ON", 7),
|
|
810
|
+
(ExpressionPresets.HAPPY.vrm0_preset, "Joy", "", "HEART", 8),
|
|
811
|
+
(ExpressionPresets.ANGRY.vrm0_preset, "Angry", "", "ORPHAN_DATA", 9),
|
|
812
|
+
(ExpressionPresets.SAD.vrm0_preset, "Sorrow", "", "MOD_FLUIDSIM", 10),
|
|
813
|
+
(ExpressionPresets.RELAXED.vrm0_preset, "Fun", "", "LIGHT_SUN", 11),
|
|
814
|
+
(ExpressionPresets.LOOK_UP.vrm0_preset, "Look Up", "", "ANCHOR_TOP", 12),
|
|
815
|
+
(ExpressionPresets.LOOK_DOWN.vrm0_preset, "Look Down", "", "ANCHOR_BOTTOM", 13),
|
|
816
|
+
(ExpressionPresets.LOOK_LEFT.vrm0_preset, "Look Left", "", "ANCHOR_RIGHT", 14),
|
|
817
|
+
(ExpressionPresets.LOOK_RIGHT.vrm0_preset, "Look Right", "", "ANCHOR_LEFT", 15),
|
|
818
|
+
(ExpressionPresets.BLINK_LEFT.vrm0_preset, "Blink_L", "", "HIDE_ON", 16),
|
|
819
|
+
(ExpressionPresets.BLINK_RIGHT.vrm0_preset, "Blink_R", "", "HIDE_ON", 17),
|
|
820
|
+
)
|
|
821
|
+
|
|
822
|
+
preset_name: EnumProperty( # type: ignore[valid-type]
|
|
823
|
+
items=preset_name_enum.items(),
|
|
824
|
+
name="Preset",
|
|
825
|
+
description="Preset name in VRM avatar",
|
|
826
|
+
)
|
|
827
|
+
binds: CollectionProperty( # type: ignore[valid-type]
|
|
828
|
+
type=Vrm0BlendShapeBindPropertyGroup,
|
|
829
|
+
name="Binds",
|
|
830
|
+
)
|
|
831
|
+
material_values: CollectionProperty( # type: ignore[valid-type]
|
|
832
|
+
type=Vrm0MaterialValueBindPropertyGroup,
|
|
833
|
+
name="Material Values",
|
|
834
|
+
)
|
|
835
|
+
|
|
836
|
+
# for UI
|
|
837
|
+
active_bind_index: IntProperty(min=0) # type: ignore[valid-type]
|
|
838
|
+
active_material_value_index: IntProperty(min=0) # type: ignore[valid-type]
|
|
839
|
+
|
|
840
|
+
def _get_preview(self) -> float:
|
|
841
|
+
value = self.get("preview")
|
|
842
|
+
if isinstance(value, (float, int)):
|
|
843
|
+
return float(value)
|
|
844
|
+
return 0.0
|
|
845
|
+
|
|
846
|
+
def _set_preview(self, value_obj: object) -> None:
|
|
847
|
+
context = bpy.context
|
|
848
|
+
|
|
849
|
+
value = convert.float_or_none(value_obj)
|
|
850
|
+
if value is None:
|
|
851
|
+
return
|
|
852
|
+
|
|
853
|
+
current_value = convert.float_or_none(self.get("preview"))
|
|
854
|
+
if (
|
|
855
|
+
current_value is not None
|
|
856
|
+
and abs(current_value - value) < float_info.epsilon
|
|
857
|
+
):
|
|
858
|
+
return
|
|
859
|
+
|
|
860
|
+
self["preview"] = value
|
|
861
|
+
|
|
862
|
+
self._update_preview(context)
|
|
863
|
+
|
|
864
|
+
pending_preview_update_armature_data_names: ClassVar[list[str]] = []
|
|
865
|
+
|
|
866
|
+
def _update_preview(self, context: Context) -> None:
|
|
867
|
+
armature_data = self.id_data
|
|
868
|
+
if not isinstance(armature_data, Armature):
|
|
869
|
+
return
|
|
870
|
+
|
|
871
|
+
if defer_shape_key_update(context):
|
|
872
|
+
if (
|
|
873
|
+
armature_data.name
|
|
874
|
+
not in self.pending_preview_update_armature_data_names
|
|
875
|
+
):
|
|
876
|
+
self.pending_preview_update_armature_data_names.append(
|
|
877
|
+
armature_data.name
|
|
878
|
+
)
|
|
879
|
+
return
|
|
880
|
+
|
|
881
|
+
self.apply_previews(context, armature_data)
|
|
882
|
+
|
|
883
|
+
@classmethod
|
|
884
|
+
def apply_pending_preview_update_to_armatures(cls, context: Context) -> None:
|
|
885
|
+
for armature_data_name in cls.pending_preview_update_armature_data_names:
|
|
886
|
+
armature_data = context.blend_data.armatures.get(armature_data_name)
|
|
887
|
+
if not armature_data:
|
|
888
|
+
continue
|
|
889
|
+
cls.apply_previews(context, armature_data)
|
|
890
|
+
cls.pending_preview_update_armature_data_names.clear()
|
|
891
|
+
|
|
892
|
+
@classmethod
|
|
893
|
+
def get_texture_info(
|
|
894
|
+
cls,
|
|
895
|
+
gltf: Mtoon1MaterialPropertyGroup,
|
|
896
|
+
target: MaterialPropertyTarget,
|
|
897
|
+
) -> Optional[Mtoon1TextureInfoPropertyGroup]:
|
|
898
|
+
mtoon = gltf.extensions.vrmc_materials_mtoon
|
|
899
|
+
if target == MaterialPropertyTarget.MAIN_TEX:
|
|
900
|
+
return gltf.pbr_metallic_roughness.base_color_texture
|
|
901
|
+
if target == MaterialPropertyTarget.SHADE_TEXTURE:
|
|
902
|
+
return mtoon.shade_multiply_texture
|
|
903
|
+
if target == MaterialPropertyTarget.BUMP_MAP:
|
|
904
|
+
return gltf.normal_texture
|
|
905
|
+
if target == MaterialPropertyTarget.RIM_TEXTURE:
|
|
906
|
+
return mtoon.rim_multiply_texture
|
|
907
|
+
if target == MaterialPropertyTarget.SPHERE_ADD:
|
|
908
|
+
return mtoon.matcap_texture
|
|
909
|
+
if target == MaterialPropertyTarget.EMISSION_MAP:
|
|
910
|
+
return gltf.emissive_texture
|
|
911
|
+
if target == MaterialPropertyTarget.OUTLINE_WIDTH_TEXTURE:
|
|
912
|
+
return mtoon.outline_width_multiply_texture
|
|
913
|
+
if target == MaterialPropertyTarget.UV_ANIM_MASK_TEXTURE:
|
|
914
|
+
return mtoon.uv_animation_mask_texture
|
|
915
|
+
return None
|
|
916
|
+
|
|
917
|
+
@classmethod
|
|
918
|
+
def get_material_property_vector(
|
|
919
|
+
cls, material: Material, material_value: Vrm0MaterialValueBindPropertyGroup
|
|
920
|
+
) -> Optional[
|
|
921
|
+
tuple[tuple[float, float, float, float], tuple[float, float, float, float]]
|
|
922
|
+
]:
|
|
923
|
+
gltf = get_material_extension(material).mtoon1
|
|
924
|
+
if not gltf.enabled:
|
|
925
|
+
return None
|
|
926
|
+
mtoon = gltf.extensions.vrmc_materials_mtoon
|
|
927
|
+
target_vector = material_value.read_target_value_as_float_list()
|
|
928
|
+
property_name = material_value.property_name
|
|
929
|
+
if not property_name:
|
|
930
|
+
return None
|
|
931
|
+
material_property = MTOON0_PROPERTIES.get(property_name)
|
|
932
|
+
if not material_property:
|
|
933
|
+
return None
|
|
934
|
+
|
|
935
|
+
if len(target_vector) != 4:
|
|
936
|
+
return None
|
|
937
|
+
target_vector = (
|
|
938
|
+
target_vector[0],
|
|
939
|
+
target_vector[1],
|
|
940
|
+
target_vector[2],
|
|
941
|
+
target_vector[3],
|
|
942
|
+
)
|
|
943
|
+
|
|
944
|
+
target = material_property.target
|
|
945
|
+
if target is None:
|
|
946
|
+
return None
|
|
947
|
+
|
|
948
|
+
if target == MaterialPropertyTarget.COLOR:
|
|
949
|
+
default_vector = convert.float4_or(
|
|
950
|
+
gltf.pbr_metallic_roughness.base_color_factor,
|
|
951
|
+
(
|
|
952
|
+
*shader.OUTPUT_GROUP_BASE_COLOR_FACTOR_COLOR_DEFAULT,
|
|
953
|
+
shader.OUTPUT_GROUP_BASE_COLOR_FACTOR_ALPHA_DEFAULT,
|
|
954
|
+
),
|
|
955
|
+
)
|
|
956
|
+
return (target_vector, default_vector)
|
|
957
|
+
if target == MaterialPropertyTarget.SHADE_COLOR:
|
|
958
|
+
default_vector = (
|
|
959
|
+
*convert.float3_or(
|
|
960
|
+
mtoon.shade_color_factor,
|
|
961
|
+
shader.OUTPUT_GROUP_SHADE_COLOR_FACTOR_DEFAULT,
|
|
962
|
+
),
|
|
963
|
+
1.0,
|
|
964
|
+
)
|
|
965
|
+
return (target_vector, default_vector)
|
|
966
|
+
if target == MaterialPropertyTarget.RIM_COLOR:
|
|
967
|
+
default_vector = (
|
|
968
|
+
*convert.float3_or(
|
|
969
|
+
mtoon.parametric_rim_color_factor,
|
|
970
|
+
shader.OUTPUT_GROUP_PARAMETRIC_RIM_COLOR_FACTOR_DEFAULT,
|
|
971
|
+
),
|
|
972
|
+
1.0,
|
|
973
|
+
)
|
|
974
|
+
return (target_vector, default_vector)
|
|
975
|
+
if target == MaterialPropertyTarget.EMISSION_COLOR:
|
|
976
|
+
default_vector = (
|
|
977
|
+
*convert.float3_or(
|
|
978
|
+
gltf.emissive_factor,
|
|
979
|
+
shader.OUTPUT_GROUP_EMISSIVE_FACTOR_DEFAULT,
|
|
980
|
+
),
|
|
981
|
+
1.0,
|
|
982
|
+
)
|
|
983
|
+
return (target_vector, default_vector)
|
|
984
|
+
if target == MaterialPropertyTarget.OUTLINE_COLOR:
|
|
985
|
+
default_vector = (
|
|
986
|
+
*convert.float3_or(
|
|
987
|
+
mtoon.outline_color_factor,
|
|
988
|
+
shader.OUTPUT_GROUP_OUTLINE_COLOR_FACTOR_DEFAULT,
|
|
989
|
+
),
|
|
990
|
+
1.0,
|
|
991
|
+
)
|
|
992
|
+
return (target_vector, default_vector)
|
|
993
|
+
|
|
994
|
+
texture_info = cls.get_texture_info(gltf, target)
|
|
995
|
+
if not texture_info:
|
|
996
|
+
return None
|
|
997
|
+
khr_texture_transform = texture_info.extensions.khr_texture_transform
|
|
998
|
+
khr_scale_u = khr_texture_transform.scale[0]
|
|
999
|
+
khr_scale_v = khr_texture_transform.scale[1]
|
|
1000
|
+
khr_offset_u = khr_texture_transform.offset[0]
|
|
1001
|
+
khr_offset_v = khr_texture_transform.offset[1]
|
|
1002
|
+
if material_property.type == MaterialPropertyType.UV:
|
|
1003
|
+
unity_scale_u, unity_scale_v, unity_offset_u, unity_offset_v = target_vector
|
|
1004
|
+
target_vector = (
|
|
1005
|
+
unity_scale_u,
|
|
1006
|
+
unity_scale_v,
|
|
1007
|
+
unity_offset_u,
|
|
1008
|
+
# https://github.com/vrm-c/UniVRM/issues/930
|
|
1009
|
+
1 - unity_offset_v - unity_scale_v,
|
|
1010
|
+
)
|
|
1011
|
+
elif material_property.type == MaterialPropertyType.UV_S:
|
|
1012
|
+
unity_scale_u, _, unity_offset_u, _ = target_vector
|
|
1013
|
+
target_vector = (
|
|
1014
|
+
unity_scale_u,
|
|
1015
|
+
khr_scale_v,
|
|
1016
|
+
unity_offset_u,
|
|
1017
|
+
khr_offset_v, # No need to change offset
|
|
1018
|
+
)
|
|
1019
|
+
elif material_property.type == MaterialPropertyType.UV_T:
|
|
1020
|
+
_, unity_scale_v, _, unity_offset_v = target_vector
|
|
1021
|
+
target_vector = (
|
|
1022
|
+
khr_scale_u,
|
|
1023
|
+
unity_scale_v,
|
|
1024
|
+
khr_offset_u,
|
|
1025
|
+
# https://github.com/vrm-c/UniVRM/issues/930
|
|
1026
|
+
1 - unity_offset_v - unity_scale_v,
|
|
1027
|
+
)
|
|
1028
|
+
else:
|
|
1029
|
+
return None
|
|
1030
|
+
|
|
1031
|
+
return (
|
|
1032
|
+
target_vector,
|
|
1033
|
+
(
|
|
1034
|
+
khr_scale_u,
|
|
1035
|
+
khr_scale_v,
|
|
1036
|
+
khr_offset_u,
|
|
1037
|
+
khr_offset_v,
|
|
1038
|
+
),
|
|
1039
|
+
)
|
|
1040
|
+
|
|
1041
|
+
@classmethod
|
|
1042
|
+
def set_material_property_vector_to_expression(
|
|
1043
|
+
cls,
|
|
1044
|
+
material: Material,
|
|
1045
|
+
target: MaterialPropertyTarget,
|
|
1046
|
+
vector: Vector,
|
|
1047
|
+
) -> None:
|
|
1048
|
+
mtoon1 = get_material_extension(material).mtoon1
|
|
1049
|
+
|
|
1050
|
+
if target == MaterialPropertyTarget.COLOR:
|
|
1051
|
+
mtoon1.set_vector3(
|
|
1052
|
+
shader.OUTPUT_GROUP_NAME,
|
|
1053
|
+
shader.OUTPUT_GROUP_EXPRESSION_COLOR_BIND_LABEL,
|
|
1054
|
+
vector.xyz,
|
|
1055
|
+
)
|
|
1056
|
+
mtoon1.set_value(
|
|
1057
|
+
shader.OUTPUT_GROUP_NAME,
|
|
1058
|
+
shader.OUTPUT_GROUP_EXPRESSION_COLOR_ALPHA_BIND_LABEL,
|
|
1059
|
+
vector.w,
|
|
1060
|
+
)
|
|
1061
|
+
return
|
|
1062
|
+
if target == MaterialPropertyTarget.SHADE_COLOR:
|
|
1063
|
+
mtoon1.set_vector3(
|
|
1064
|
+
shader.OUTPUT_GROUP_NAME,
|
|
1065
|
+
shader.OUTPUT_GROUP_EXPRESSION_SHADE_COLOR_BIND_LABEL,
|
|
1066
|
+
vector.xyz,
|
|
1067
|
+
)
|
|
1068
|
+
return
|
|
1069
|
+
if target == MaterialPropertyTarget.RIM_COLOR:
|
|
1070
|
+
mtoon1.set_vector3(
|
|
1071
|
+
shader.OUTPUT_GROUP_NAME,
|
|
1072
|
+
shader.OUTPUT_GROUP_EXPRESSION_RIM_COLOR_BIND_LABEL,
|
|
1073
|
+
vector.xyz,
|
|
1074
|
+
)
|
|
1075
|
+
return
|
|
1076
|
+
if target == MaterialPropertyTarget.EMISSION_COLOR:
|
|
1077
|
+
mtoon1.set_vector3(
|
|
1078
|
+
shader.OUTPUT_GROUP_NAME,
|
|
1079
|
+
shader.OUTPUT_GROUP_EXPRESSION_EMISSION_COLOR_BIND_LABEL,
|
|
1080
|
+
vector.xyz,
|
|
1081
|
+
)
|
|
1082
|
+
return
|
|
1083
|
+
if target == MaterialPropertyTarget.OUTLINE_COLOR:
|
|
1084
|
+
mtoon1.set_vector3(
|
|
1085
|
+
shader.OUTPUT_GROUP_NAME,
|
|
1086
|
+
shader.OUTPUT_GROUP_EXPRESSION_OUTLINE_COLOR_BIND_LABEL,
|
|
1087
|
+
vector.xyz,
|
|
1088
|
+
)
|
|
1089
|
+
return
|
|
1090
|
+
|
|
1091
|
+
texture_info = cls.get_texture_info(mtoon1, target)
|
|
1092
|
+
if not texture_info:
|
|
1093
|
+
return
|
|
1094
|
+
khr_texture_transform = texture_info.extensions.khr_texture_transform
|
|
1095
|
+
khr_texture_transform.set_texture_uv(
|
|
1096
|
+
shader.UV_GROUP_EXPRESSION_UV_SCALE_BIND_LABEL,
|
|
1097
|
+
vector.xy,
|
|
1098
|
+
)
|
|
1099
|
+
khr_texture_transform.set_texture_uv(
|
|
1100
|
+
shader.UV_GROUP_EXPRESSION_UV_OFFSET_BIND_LABEL,
|
|
1101
|
+
vector.zw,
|
|
1102
|
+
)
|
|
1103
|
+
|
|
1104
|
+
@classmethod
|
|
1105
|
+
def apply_previews(cls, context: Context, armature_data: Armature) -> None:
|
|
1106
|
+
mesh_object_name_to_key_block_name_to_value: dict[str, dict[str, float]] = {}
|
|
1107
|
+
blend_shape_groups = get_armature_extension(
|
|
1108
|
+
armature_data
|
|
1109
|
+
).vrm0.blend_shape_master.blend_shape_groups
|
|
1110
|
+
material_name_to_target_to_vector: dict[
|
|
1111
|
+
str, dict[MaterialPropertyTarget, Vector]
|
|
1112
|
+
] = {}
|
|
1113
|
+
for blend_shape_group in blend_shape_groups:
|
|
1114
|
+
if blend_shape_group.is_binary:
|
|
1115
|
+
# https://github.com/vrm-c/UniVRM/blob/a4711bbf8c4d10659d3e5568c2e3d7d595005e51/Packages/VRM/Runtime/BlendShape/BlendShapeMerger.cs#L89-L92
|
|
1116
|
+
# https://docs.unity3d.com/6000.3/Documentation/ScriptReference/Mathf.Round.html
|
|
1117
|
+
preview = round(blend_shape_group.preview)
|
|
1118
|
+
else:
|
|
1119
|
+
preview = blend_shape_group.preview
|
|
1120
|
+
|
|
1121
|
+
for material_value in blend_shape_group.material_values:
|
|
1122
|
+
material = material_value.material
|
|
1123
|
+
if not material:
|
|
1124
|
+
continue
|
|
1125
|
+
vectors = cls.get_material_property_vector(material, material_value)
|
|
1126
|
+
if not vectors:
|
|
1127
|
+
continue
|
|
1128
|
+
property_name = material_value.property_name
|
|
1129
|
+
if not property_name:
|
|
1130
|
+
continue
|
|
1131
|
+
material_property = MTOON0_PROPERTIES.get(property_name)
|
|
1132
|
+
if not material_property:
|
|
1133
|
+
continue
|
|
1134
|
+
target = material_property.target
|
|
1135
|
+
if not target:
|
|
1136
|
+
continue
|
|
1137
|
+
target_vector, default_vector = vectors
|
|
1138
|
+
target_to_vector = material_name_to_target_to_vector.get(material.name)
|
|
1139
|
+
if target_to_vector is None:
|
|
1140
|
+
target_to_vector = {}
|
|
1141
|
+
material_name_to_target_to_vector[material.name] = target_to_vector
|
|
1142
|
+
current_vector = target_to_vector.get(target)
|
|
1143
|
+
if current_vector is None:
|
|
1144
|
+
current_vector = (
|
|
1145
|
+
Vector(target_vector) - Vector(default_vector)
|
|
1146
|
+
) * preview
|
|
1147
|
+
else:
|
|
1148
|
+
current_vector = (
|
|
1149
|
+
current_vector
|
|
1150
|
+
+ (Vector(target_vector) - Vector(default_vector)) * preview
|
|
1151
|
+
)
|
|
1152
|
+
target_to_vector[target] = current_vector
|
|
1153
|
+
|
|
1154
|
+
for bind in blend_shape_group.binds:
|
|
1155
|
+
mesh_object_name = bind.mesh.mesh_object_name
|
|
1156
|
+
key_block_name = bind.index
|
|
1157
|
+
value = bind.weight * preview # Lerp 0.0 * (1 - a) + weight * a
|
|
1158
|
+
key_block_name_to_value = (
|
|
1159
|
+
mesh_object_name_to_key_block_name_to_value.get(mesh_object_name)
|
|
1160
|
+
)
|
|
1161
|
+
if not key_block_name_to_value:
|
|
1162
|
+
mesh_object_name_to_key_block_name_to_value[mesh_object_name] = {
|
|
1163
|
+
key_block_name: value
|
|
1164
|
+
}
|
|
1165
|
+
continue
|
|
1166
|
+
key_block_name_to_value[key_block_name] = (
|
|
1167
|
+
key_block_name_to_value.get(key_block_name, 0) + value
|
|
1168
|
+
)
|
|
1169
|
+
|
|
1170
|
+
for (
|
|
1171
|
+
material_name,
|
|
1172
|
+
target_to_vector,
|
|
1173
|
+
) in material_name_to_target_to_vector.items():
|
|
1174
|
+
material = context.blend_data.materials.get(material_name)
|
|
1175
|
+
if not material:
|
|
1176
|
+
continue
|
|
1177
|
+
for target, vector in target_to_vector.items():
|
|
1178
|
+
cls.set_material_property_vector_to_expression(material, target, vector)
|
|
1179
|
+
|
|
1180
|
+
mesh_data_name_to_key_block_name_to_total_value: dict[
|
|
1181
|
+
str, dict[str, float]
|
|
1182
|
+
] = {}
|
|
1183
|
+
for (
|
|
1184
|
+
mesh_object_name,
|
|
1185
|
+
key_block_name_to_value,
|
|
1186
|
+
) in mesh_object_name_to_key_block_name_to_value.items():
|
|
1187
|
+
mesh_object = context.blend_data.objects.get(mesh_object_name)
|
|
1188
|
+
if not mesh_object:
|
|
1189
|
+
continue
|
|
1190
|
+
mesh_data = mesh_object.data
|
|
1191
|
+
if not isinstance(mesh_data, Mesh):
|
|
1192
|
+
continue
|
|
1193
|
+
key_block_name_to_total_value = (
|
|
1194
|
+
mesh_data_name_to_key_block_name_to_total_value.get(mesh_data.name)
|
|
1195
|
+
)
|
|
1196
|
+
if not key_block_name_to_total_value:
|
|
1197
|
+
mesh_data_name_to_key_block_name_to_total_value[mesh_data.name] = (
|
|
1198
|
+
key_block_name_to_value
|
|
1199
|
+
)
|
|
1200
|
+
continue
|
|
1201
|
+
for key_block_name, value in key_block_name_to_value.items():
|
|
1202
|
+
key_block_name_to_total_value[key_block_name] = (
|
|
1203
|
+
key_block_name_to_total_value.get(key_block_name, 0) + value
|
|
1204
|
+
)
|
|
1205
|
+
|
|
1206
|
+
for (
|
|
1207
|
+
mesh_data_name,
|
|
1208
|
+
key_block_name_to_value,
|
|
1209
|
+
) in mesh_data_name_to_key_block_name_to_total_value.items():
|
|
1210
|
+
mesh_data = context.blend_data.meshes.get(mesh_data_name)
|
|
1211
|
+
if not mesh_data:
|
|
1212
|
+
continue
|
|
1213
|
+
shape_keys = mesh_data.shape_keys
|
|
1214
|
+
if not shape_keys:
|
|
1215
|
+
continue
|
|
1216
|
+
key_blocks = shape_keys.key_blocks
|
|
1217
|
+
if not key_blocks:
|
|
1218
|
+
continue
|
|
1219
|
+
for key_block_name, value in key_block_name_to_value.items():
|
|
1220
|
+
key_block = key_blocks.get(key_block_name)
|
|
1221
|
+
if not key_block:
|
|
1222
|
+
continue
|
|
1223
|
+
if abs(key_block.value - value) < float_info.epsilon:
|
|
1224
|
+
continue
|
|
1225
|
+
key_block.value = value
|
|
1226
|
+
|
|
1227
|
+
preview: FloatProperty( # type: ignore[valid-type]
|
|
1228
|
+
name="Blend Shape Proxy",
|
|
1229
|
+
min=0,
|
|
1230
|
+
max=1,
|
|
1231
|
+
subtype="FACTOR",
|
|
1232
|
+
get=_get_preview,
|
|
1233
|
+
set=_set_preview,
|
|
1234
|
+
)
|
|
1235
|
+
|
|
1236
|
+
is_binary: BoolProperty( # type: ignore[valid-type]
|
|
1237
|
+
name="Is Binary",
|
|
1238
|
+
description="Use binary change in the blendshape group",
|
|
1239
|
+
update=_update_preview,
|
|
1240
|
+
)
|
|
1241
|
+
|
|
1242
|
+
if TYPE_CHECKING:
|
|
1243
|
+
# This code is auto generated.
|
|
1244
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
1245
|
+
name: str # type: ignore[no-redef]
|
|
1246
|
+
preset_name: str # type: ignore[no-redef]
|
|
1247
|
+
binds: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
1248
|
+
Vrm0BlendShapeBindPropertyGroup
|
|
1249
|
+
]
|
|
1250
|
+
material_values: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
1251
|
+
Vrm0MaterialValueBindPropertyGroup
|
|
1252
|
+
]
|
|
1253
|
+
active_bind_index: int # type: ignore[no-redef]
|
|
1254
|
+
active_material_value_index: int # type: ignore[no-redef]
|
|
1255
|
+
preview: float # type: ignore[no-redef]
|
|
1256
|
+
is_binary: bool # type: ignore[no-redef]
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_SecondaryAnimation.cs#L10-L18
|
|
1260
|
+
class Vrm0SecondaryAnimationColliderPropertyGroup(PropertyGroup):
|
|
1261
|
+
bpy_object: PointerProperty( # type: ignore[valid-type]
|
|
1262
|
+
type=Object
|
|
1263
|
+
)
|
|
1264
|
+
|
|
1265
|
+
def fixup(self, armature: Optional[Object], bone_name: str) -> None:
|
|
1266
|
+
bpy_object = self.bpy_object
|
|
1267
|
+
if not bpy_object or not bpy_object.name:
|
|
1268
|
+
return
|
|
1269
|
+
|
|
1270
|
+
if armature and bpy_object.parent != armature:
|
|
1271
|
+
_logger.warning(
|
|
1272
|
+
"Collider %s is not parented to the armature."
|
|
1273
|
+
" Parenting to the armature %s.",
|
|
1274
|
+
self.path_from_id(),
|
|
1275
|
+
armature.name,
|
|
1276
|
+
)
|
|
1277
|
+
bpy_object.parent = armature
|
|
1278
|
+
|
|
1279
|
+
if bpy_object.empty_display_type != "SPHERE":
|
|
1280
|
+
_logger.warning(
|
|
1281
|
+
"Collider %s has empty display type %s. Setting to SPHERE.",
|
|
1282
|
+
self.path_from_id(),
|
|
1283
|
+
bpy_object.empty_display_type,
|
|
1284
|
+
)
|
|
1285
|
+
bpy_object.empty_display_type = "SPHERE"
|
|
1286
|
+
|
|
1287
|
+
parent_obj = bpy_object.parent
|
|
1288
|
+
if not parent_obj:
|
|
1289
|
+
return
|
|
1290
|
+
|
|
1291
|
+
if parent_obj.type != "ARMATURE" or not bone_name:
|
|
1292
|
+
if bpy_object.parent_type != "OBJECT":
|
|
1293
|
+
_logger.warning(
|
|
1294
|
+
"Collider %s is parented to a bone but no bone is assigned."
|
|
1295
|
+
" Changing to object parenting.",
|
|
1296
|
+
self.path_from_id(),
|
|
1297
|
+
)
|
|
1298
|
+
bpy_object.parent_type = "OBJECT"
|
|
1299
|
+
if bpy_object.parent_bone:
|
|
1300
|
+
_logger.warning(
|
|
1301
|
+
"Collider %s has a stale parent bone %s while using object"
|
|
1302
|
+
" parenting. Clearing the parent bone.",
|
|
1303
|
+
self.path_from_id(),
|
|
1304
|
+
bpy_object.parent_bone,
|
|
1305
|
+
)
|
|
1306
|
+
bpy_object.parent_bone = ""
|
|
1307
|
+
return
|
|
1308
|
+
|
|
1309
|
+
if bpy_object.parent_type != "BONE":
|
|
1310
|
+
_logger.warning(
|
|
1311
|
+
"Collider %s is not parented to a bone. Parenting to the bone %s.",
|
|
1312
|
+
self.path_from_id(),
|
|
1313
|
+
bone_name,
|
|
1314
|
+
)
|
|
1315
|
+
bpy_object.parent_type = "BONE"
|
|
1316
|
+
|
|
1317
|
+
if bpy_object.parent_bone != bone_name:
|
|
1318
|
+
_logger.warning(
|
|
1319
|
+
"Collider %s is parented to a different bone %s."
|
|
1320
|
+
" Changing to the bone %s.",
|
|
1321
|
+
self.path_from_id(),
|
|
1322
|
+
bpy_object.parent_bone,
|
|
1323
|
+
bone_name,
|
|
1324
|
+
)
|
|
1325
|
+
bpy_object.parent_bone = bone_name
|
|
1326
|
+
|
|
1327
|
+
if TYPE_CHECKING:
|
|
1328
|
+
# This code is auto generated.
|
|
1329
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
1330
|
+
bpy_object: Optional[Object] # type: ignore[no-redef]
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
# https://github.com/vrm-c/vrm-specification/blob/f2d8f158297fc883aef9c3071ca68fbe46b03f45/specification/0.0/schema/vrm.secondaryanimation.collidergroup.schema.json
|
|
1334
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_SecondaryAnimation.cs#L21-L29
|
|
1335
|
+
class Vrm0SecondaryAnimationColliderGroupPropertyGroup(PropertyGroup):
|
|
1336
|
+
node: PointerProperty( # type: ignore[valid-type]
|
|
1337
|
+
name="Bone",
|
|
1338
|
+
type=BonePropertyGroup,
|
|
1339
|
+
)
|
|
1340
|
+
# Use the collider's own data for offset and radius
|
|
1341
|
+
colliders: CollectionProperty( # type: ignore[valid-type]
|
|
1342
|
+
name="Colliders",
|
|
1343
|
+
type=Vrm0SecondaryAnimationColliderPropertyGroup,
|
|
1344
|
+
)
|
|
1345
|
+
|
|
1346
|
+
@property
|
|
1347
|
+
def display_name(self) -> str:
|
|
1348
|
+
if not self.uuid:
|
|
1349
|
+
return ""
|
|
1350
|
+
return f"{self.node.bone_name}#{self.uuid}"
|
|
1351
|
+
|
|
1352
|
+
def fixup(self, armature: Optional[Object]) -> None:
|
|
1353
|
+
if not self.uuid:
|
|
1354
|
+
new_uuid = uuid.uuid4().hex
|
|
1355
|
+
_logger.error(
|
|
1356
|
+
"Collider group %s has no UUID. Assigning a new UUID %s.",
|
|
1357
|
+
self.path_from_id(),
|
|
1358
|
+
new_uuid,
|
|
1359
|
+
)
|
|
1360
|
+
self.uuid = new_uuid
|
|
1361
|
+
|
|
1362
|
+
for index, collider in reversed(
|
|
1363
|
+
tuple((index, collider) for index, collider in enumerate(self.colliders))
|
|
1364
|
+
):
|
|
1365
|
+
if not collider.bpy_object or not collider.bpy_object.name:
|
|
1366
|
+
_logger.warning(
|
|
1367
|
+
"Collider %s in group %s has no valid object. Removing.",
|
|
1368
|
+
collider.path_from_id(),
|
|
1369
|
+
self.display_name,
|
|
1370
|
+
)
|
|
1371
|
+
self.colliders.remove(index)
|
|
1372
|
+
else:
|
|
1373
|
+
collider.fixup(armature, self.node.bone_name)
|
|
1374
|
+
|
|
1375
|
+
armature_data = self.id_data
|
|
1376
|
+
if not isinstance(armature_data, Armature):
|
|
1377
|
+
return
|
|
1378
|
+
|
|
1379
|
+
vrm0 = get_armature_extension(armature_data).vrm0
|
|
1380
|
+
for bone_group in vrm0.secondary_animation.bone_groups:
|
|
1381
|
+
bone_group.fixup()
|
|
1382
|
+
|
|
1383
|
+
# for UI
|
|
1384
|
+
show_expanded: BoolProperty() # type: ignore[valid-type]
|
|
1385
|
+
|
|
1386
|
+
active_collider_index: IntProperty(min=0) # type: ignore[valid-type]
|
|
1387
|
+
|
|
1388
|
+
# for reference from Vrm0SecondaryAnimationGroupPropertyGroup
|
|
1389
|
+
uuid: StringProperty() # type: ignore[valid-type]
|
|
1390
|
+
|
|
1391
|
+
if TYPE_CHECKING:
|
|
1392
|
+
# This code is auto generated.
|
|
1393
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
1394
|
+
node: BonePropertyGroup # type: ignore[no-redef]
|
|
1395
|
+
colliders: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
1396
|
+
Vrm0SecondaryAnimationColliderPropertyGroup
|
|
1397
|
+
]
|
|
1398
|
+
show_expanded: bool # type: ignore[no-redef]
|
|
1399
|
+
active_collider_index: int # type: ignore[no-redef]
|
|
1400
|
+
uuid: str # type: ignore[no-redef]
|
|
1401
|
+
|
|
1402
|
+
|
|
1403
|
+
class Vrm0SecondaryAnimationColliderGroupReferencePropertyGroup(PropertyGroup):
|
|
1404
|
+
@property
|
|
1405
|
+
def collider_group_display_name(self) -> str:
|
|
1406
|
+
armature_data = self.id_data
|
|
1407
|
+
if not isinstance(armature_data, Armature):
|
|
1408
|
+
return ""
|
|
1409
|
+
if not self.collider_group_uuid:
|
|
1410
|
+
return ""
|
|
1411
|
+
|
|
1412
|
+
secondary_animation = get_armature_extension(
|
|
1413
|
+
armature_data
|
|
1414
|
+
).vrm0.secondary_animation
|
|
1415
|
+
for collider_group in secondary_animation.collider_groups:
|
|
1416
|
+
if collider_group.uuid == self.collider_group_uuid:
|
|
1417
|
+
return collider_group.display_name
|
|
1418
|
+
return ""
|
|
1419
|
+
|
|
1420
|
+
def _update_collider_group_uuid(self, _context: Context) -> None:
|
|
1421
|
+
if not self.collider_group_uuid:
|
|
1422
|
+
return
|
|
1423
|
+
|
|
1424
|
+
armature_data = self.id_data
|
|
1425
|
+
if not isinstance(armature_data, Armature):
|
|
1426
|
+
return
|
|
1427
|
+
|
|
1428
|
+
vrm0 = get_armature_extension(armature_data).vrm0
|
|
1429
|
+
secondary_animation = vrm0.secondary_animation
|
|
1430
|
+
for collider_group in secondary_animation.collider_groups:
|
|
1431
|
+
if self.collider_group_uuid == collider_group.uuid:
|
|
1432
|
+
return
|
|
1433
|
+
|
|
1434
|
+
self.collider_group_uuid = ""
|
|
1435
|
+
|
|
1436
|
+
collider_group_uuid: StringProperty(update=_update_collider_group_uuid) # type: ignore[valid-type]
|
|
1437
|
+
|
|
1438
|
+
if TYPE_CHECKING:
|
|
1439
|
+
# This code is auto generated.
|
|
1440
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
1441
|
+
collider_group_uuid: str # type: ignore[no-redef]
|
|
1442
|
+
|
|
1443
|
+
|
|
1444
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_SecondaryAnimation.cs#L32-L67
|
|
1445
|
+
class Vrm0SecondaryAnimationGroupPropertyGroup(PropertyGroup):
|
|
1446
|
+
comment: StringProperty( # type: ignore[valid-type]
|
|
1447
|
+
name="Comment",
|
|
1448
|
+
description="Comment about the purpose of springs",
|
|
1449
|
+
)
|
|
1450
|
+
|
|
1451
|
+
# typo in VRM 0.0 specification
|
|
1452
|
+
# https://github.com/vrm-c/vrm-specification/blob/1723a45abfb4f12ac5d3635a3f66dc45e2f93c83/specification/0.0/schema/vrm.secondaryanimation.spring.schema.json#L9-L12
|
|
1453
|
+
stiffiness: FloatProperty( # type: ignore[valid-type]
|
|
1454
|
+
name="Stiffness",
|
|
1455
|
+
min=0.0,
|
|
1456
|
+
soft_max=4.0,
|
|
1457
|
+
subtype="FACTOR",
|
|
1458
|
+
description="Stiffness of springs",
|
|
1459
|
+
)
|
|
1460
|
+
|
|
1461
|
+
gravity_power: FloatProperty( # type: ignore[valid-type]
|
|
1462
|
+
name="Gravity Power",
|
|
1463
|
+
min=0.0,
|
|
1464
|
+
soft_max=2.0,
|
|
1465
|
+
subtype="FACTOR",
|
|
1466
|
+
description="Gravity power of springs",
|
|
1467
|
+
)
|
|
1468
|
+
|
|
1469
|
+
def _update_gravity_dir(self, _context: Context) -> None:
|
|
1470
|
+
gravity_dir = Vector(self.gravity_dir)
|
|
1471
|
+
normalized_gravity_dir = gravity_dir.normalized()
|
|
1472
|
+
if (gravity_dir - normalized_gravity_dir).length > 0.0001:
|
|
1473
|
+
self.gravity_dir = normalized_gravity_dir
|
|
1474
|
+
|
|
1475
|
+
gravity_dir: FloatVectorProperty( # type: ignore[valid-type]
|
|
1476
|
+
size=3,
|
|
1477
|
+
min=-1,
|
|
1478
|
+
max=1,
|
|
1479
|
+
subtype="XYZ",
|
|
1480
|
+
name="Gravity Direction",
|
|
1481
|
+
description="Gravity direction of springs",
|
|
1482
|
+
update=_update_gravity_dir,
|
|
1483
|
+
)
|
|
1484
|
+
drag_force: FloatProperty( # type: ignore[valid-type]
|
|
1485
|
+
name="Drag Force",
|
|
1486
|
+
min=0.0,
|
|
1487
|
+
max=1.0,
|
|
1488
|
+
subtype="FACTOR",
|
|
1489
|
+
description="Drag Force of springs",
|
|
1490
|
+
)
|
|
1491
|
+
center: PointerProperty( # type: ignore[valid-type]
|
|
1492
|
+
name="Center",
|
|
1493
|
+
type=BonePropertyGroup,
|
|
1494
|
+
description="Origin of Physics simulation to stop springs on moving",
|
|
1495
|
+
)
|
|
1496
|
+
hit_radius: FloatProperty( # type: ignore[valid-type]
|
|
1497
|
+
name="Hit Radius",
|
|
1498
|
+
min=0.0,
|
|
1499
|
+
soft_max=0.5,
|
|
1500
|
+
subtype="DISTANCE",
|
|
1501
|
+
description="Hit Radius of springs",
|
|
1502
|
+
)
|
|
1503
|
+
bones: CollectionProperty( # type: ignore[valid-type]
|
|
1504
|
+
name="Bones",
|
|
1505
|
+
type=BonePropertyGroup,
|
|
1506
|
+
description="Bones of the spring roots",
|
|
1507
|
+
)
|
|
1508
|
+
collider_groups: CollectionProperty( # type: ignore[valid-type]
|
|
1509
|
+
name="Collider Group",
|
|
1510
|
+
type=Vrm0SecondaryAnimationColliderGroupReferencePropertyGroup,
|
|
1511
|
+
description="Enabled collider Groups of springs",
|
|
1512
|
+
)
|
|
1513
|
+
|
|
1514
|
+
# for UI
|
|
1515
|
+
show_expanded: BoolProperty() # type: ignore[valid-type]
|
|
1516
|
+
show_expanded_bones: BoolProperty( # type: ignore[valid-type]
|
|
1517
|
+
name="Bones"
|
|
1518
|
+
)
|
|
1519
|
+
show_expanded_collider_groups: BoolProperty( # type: ignore[valid-type]
|
|
1520
|
+
name="Collider Groups"
|
|
1521
|
+
)
|
|
1522
|
+
|
|
1523
|
+
active_bone_index: IntProperty(min=0) # type: ignore[valid-type]
|
|
1524
|
+
active_collider_group_index: IntProperty(min=0) # type: ignore[valid-type]
|
|
1525
|
+
|
|
1526
|
+
def fixup(self) -> None:
|
|
1527
|
+
armature_data = self.id_data
|
|
1528
|
+
if not isinstance(armature_data, Armature):
|
|
1529
|
+
return
|
|
1530
|
+
ext = get_armature_extension(armature_data)
|
|
1531
|
+
collider_group_uuids = {
|
|
1532
|
+
collider_group.uuid
|
|
1533
|
+
for collider_group in ext.vrm0.secondary_animation.collider_groups
|
|
1534
|
+
}
|
|
1535
|
+
for collider_group_reference in self.collider_groups:
|
|
1536
|
+
collider_group_uuid = collider_group_reference.collider_group_uuid
|
|
1537
|
+
if not collider_group_uuid:
|
|
1538
|
+
continue
|
|
1539
|
+
if collider_group_uuid in collider_group_uuids:
|
|
1540
|
+
collider_group_uuids.remove(collider_group_uuid)
|
|
1541
|
+
continue
|
|
1542
|
+
_logger.error(
|
|
1543
|
+
'Collider group with uuid "%s" not found or duplicated for'
|
|
1544
|
+
' "%s". Clearing UUID.',
|
|
1545
|
+
collider_group_uuid,
|
|
1546
|
+
collider_group_reference.path_from_id(),
|
|
1547
|
+
)
|
|
1548
|
+
collider_group_reference.collider_group_uuid = ""
|
|
1549
|
+
|
|
1550
|
+
if TYPE_CHECKING:
|
|
1551
|
+
# This code is auto generated.
|
|
1552
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
1553
|
+
comment: str # type: ignore[no-redef]
|
|
1554
|
+
stiffiness: float # type: ignore[no-redef]
|
|
1555
|
+
gravity_power: float # type: ignore[no-redef]
|
|
1556
|
+
gravity_dir: Sequence[float] # type: ignore[no-redef]
|
|
1557
|
+
drag_force: float # type: ignore[no-redef]
|
|
1558
|
+
center: BonePropertyGroup # type: ignore[no-redef]
|
|
1559
|
+
hit_radius: float # type: ignore[no-redef]
|
|
1560
|
+
bones: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
1561
|
+
BonePropertyGroup
|
|
1562
|
+
]
|
|
1563
|
+
collider_groups: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
1564
|
+
Vrm0SecondaryAnimationColliderGroupReferencePropertyGroup
|
|
1565
|
+
]
|
|
1566
|
+
show_expanded: bool # type: ignore[no-redef]
|
|
1567
|
+
show_expanded_bones: bool # type: ignore[no-redef]
|
|
1568
|
+
show_expanded_collider_groups: bool # type: ignore[no-redef]
|
|
1569
|
+
active_bone_index: int # type: ignore[no-redef]
|
|
1570
|
+
active_collider_group_index: int # type: ignore[no-redef]
|
|
1571
|
+
|
|
1572
|
+
|
|
1573
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_Meta.cs#L33-L149
|
|
1574
|
+
class Vrm0MetaPropertyGroup(PropertyGroup):
|
|
1575
|
+
allowed_user_name_enum, __allowed_user_names = property_group_enum(
|
|
1576
|
+
("OnlyAuthor", "Only Author", "", "NONE", 0),
|
|
1577
|
+
("ExplicitlyLicensedPerson", "Explicitly Licensed Person", "", "NONE", 1),
|
|
1578
|
+
("Everyone", "Everyone", "", "NONE", 2),
|
|
1579
|
+
)
|
|
1580
|
+
|
|
1581
|
+
violent_ussage_name_enum, __violent_ussage_names = property_group_enum(
|
|
1582
|
+
("Disallow", "Disallow", "", "NONE", 0),
|
|
1583
|
+
("Allow", "Allow", "", "NONE", 1),
|
|
1584
|
+
)
|
|
1585
|
+
|
|
1586
|
+
sexual_ussage_name_enum, __sexual_ussage_names = property_group_enum(
|
|
1587
|
+
("Disallow", "Disallow", "", "NONE", 0),
|
|
1588
|
+
("Allow", "Allow", "", "NONE", 1),
|
|
1589
|
+
)
|
|
1590
|
+
|
|
1591
|
+
commercial_ussage_name_enum, __commercial_ussage_names = property_group_enum(
|
|
1592
|
+
("Disallow", "Disallow", "", "NONE", 0),
|
|
1593
|
+
("Allow", "Allow", "", "NONE", 1),
|
|
1594
|
+
)
|
|
1595
|
+
|
|
1596
|
+
(
|
|
1597
|
+
license_name_enum,
|
|
1598
|
+
(
|
|
1599
|
+
LICENSE_NAME_REDISTRIBUTION_PROHIBITED,
|
|
1600
|
+
LICENSE_NAME_CC0,
|
|
1601
|
+
LICENSE_NAME_CC_BY,
|
|
1602
|
+
LICENSE_NAME_CC_BY_NC,
|
|
1603
|
+
LICENSE_NAME_CC_BY_SA,
|
|
1604
|
+
LICENSE_NAME_CC_BY_NC_SA,
|
|
1605
|
+
LICENSE_NAME_CC_BY_ND,
|
|
1606
|
+
LICENSE_NAME_CC_BY_NC_ND,
|
|
1607
|
+
LICENSE_NAME_OTHER,
|
|
1608
|
+
),
|
|
1609
|
+
) = property_group_enum(
|
|
1610
|
+
("Redistribution_Prohibited", "Redistribution Prohibited", "", "NONE", 0),
|
|
1611
|
+
("CC0", "CC0", "", "NONE", 1),
|
|
1612
|
+
("CC_BY", "CC BY", "", "NONE", 2),
|
|
1613
|
+
("CC_BY_NC", "CC BY NC", "", "NONE", 3),
|
|
1614
|
+
("CC_BY_SA", "CC BY SA", "", "NONE", 4),
|
|
1615
|
+
("CC_BY_NC_SA", "CC BY NC SA", "", "NONE", 5),
|
|
1616
|
+
("CC_BY_ND", "CC BY ND", "", "NONE", 6), # codespell:ignore nd
|
|
1617
|
+
("CC_BY_NC_ND", "CC BY NC ND", "", "NONE", 7), # codespell:ignore nd
|
|
1618
|
+
("Other", "Other", "", "NONE", 8),
|
|
1619
|
+
)
|
|
1620
|
+
|
|
1621
|
+
title: StringProperty( # type: ignore[valid-type]
|
|
1622
|
+
name="Title",
|
|
1623
|
+
description="Title of the avatar",
|
|
1624
|
+
)
|
|
1625
|
+
version: StringProperty( # type: ignore[valid-type]
|
|
1626
|
+
name="Version",
|
|
1627
|
+
description="Version of the avatar",
|
|
1628
|
+
)
|
|
1629
|
+
author: StringProperty( # type: ignore[valid-type]
|
|
1630
|
+
name="Author",
|
|
1631
|
+
description="Author of the avatar",
|
|
1632
|
+
)
|
|
1633
|
+
contact_information: StringProperty( # type: ignore[valid-type]
|
|
1634
|
+
name="Contact Information",
|
|
1635
|
+
description="Contact Information about the avatar",
|
|
1636
|
+
)
|
|
1637
|
+
reference: StringProperty( # type: ignore[valid-type]
|
|
1638
|
+
name="Reference",
|
|
1639
|
+
description="Referenced works about the avatar",
|
|
1640
|
+
)
|
|
1641
|
+
allowed_user_name: EnumProperty( # type: ignore[valid-type]
|
|
1642
|
+
items=allowed_user_name_enum.items(),
|
|
1643
|
+
name="Allowed User",
|
|
1644
|
+
description="Allowed user of the avatar",
|
|
1645
|
+
)
|
|
1646
|
+
violent_ussage_name: EnumProperty( # type: ignore[valid-type]
|
|
1647
|
+
items=violent_ussage_name_enum.items(),
|
|
1648
|
+
name="Violent Usage",
|
|
1649
|
+
description="Violent usage of the avatar",
|
|
1650
|
+
)
|
|
1651
|
+
sexual_ussage_name: EnumProperty( # type: ignore[valid-type]
|
|
1652
|
+
items=sexual_ussage_name_enum.items(),
|
|
1653
|
+
name="Sexual Usage",
|
|
1654
|
+
description="Sexual Usage of the avatar",
|
|
1655
|
+
)
|
|
1656
|
+
commercial_ussage_name: EnumProperty( # type: ignore[valid-type]
|
|
1657
|
+
items=commercial_ussage_name_enum.items(),
|
|
1658
|
+
name="Commercial Usage",
|
|
1659
|
+
description="Commercial Usage of the avatar",
|
|
1660
|
+
)
|
|
1661
|
+
other_permission_url: StringProperty( # type: ignore[valid-type]
|
|
1662
|
+
name="Other Permission URL",
|
|
1663
|
+
description="URL about other permissions of the avatar",
|
|
1664
|
+
)
|
|
1665
|
+
license_name: EnumProperty( # type: ignore[valid-type]
|
|
1666
|
+
items=license_name_enum.items(),
|
|
1667
|
+
name="License",
|
|
1668
|
+
description="License of the avatar",
|
|
1669
|
+
)
|
|
1670
|
+
other_license_url: StringProperty( # type: ignore[valid-type]
|
|
1671
|
+
name="Other License URL",
|
|
1672
|
+
description="URL about other License of the avatar",
|
|
1673
|
+
)
|
|
1674
|
+
texture: PointerProperty( # type: ignore[valid-type]
|
|
1675
|
+
name="Thumbnail",
|
|
1676
|
+
type=Image,
|
|
1677
|
+
description="Thumbnail of the avatar",
|
|
1678
|
+
)
|
|
1679
|
+
|
|
1680
|
+
if TYPE_CHECKING:
|
|
1681
|
+
# This code is auto generated.
|
|
1682
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
1683
|
+
title: str # type: ignore[no-redef]
|
|
1684
|
+
version: str # type: ignore[no-redef]
|
|
1685
|
+
author: str # type: ignore[no-redef]
|
|
1686
|
+
contact_information: str # type: ignore[no-redef]
|
|
1687
|
+
reference: str # type: ignore[no-redef]
|
|
1688
|
+
allowed_user_name: str # type: ignore[no-redef]
|
|
1689
|
+
violent_ussage_name: str # type: ignore[no-redef]
|
|
1690
|
+
sexual_ussage_name: str # type: ignore[no-redef]
|
|
1691
|
+
commercial_ussage_name: str # type: ignore[no-redef]
|
|
1692
|
+
other_permission_url: str # type: ignore[no-redef]
|
|
1693
|
+
license_name: str # type: ignore[no-redef]
|
|
1694
|
+
other_license_url: str # type: ignore[no-redef]
|
|
1695
|
+
texture: Optional[Image] # type: ignore[no-redef]
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_BlendShape.cs#L101-L106
|
|
1699
|
+
class Vrm0BlendShapeMasterPropertyGroup(PropertyGroup):
|
|
1700
|
+
blend_shape_groups: CollectionProperty( # type: ignore[valid-type]
|
|
1701
|
+
name="Blend Shape Group",
|
|
1702
|
+
type=Vrm0BlendShapeGroupPropertyGroup,
|
|
1703
|
+
)
|
|
1704
|
+
|
|
1705
|
+
def restore_blend_shape_group_bind_object_assignments(
|
|
1706
|
+
self, context: Context
|
|
1707
|
+
) -> None:
|
|
1708
|
+
for blend_shape_group in self.blend_shape_groups:
|
|
1709
|
+
for bind in blend_shape_group.binds:
|
|
1710
|
+
bind.mesh.restore_object_assignment(context)
|
|
1711
|
+
|
|
1712
|
+
# for UI
|
|
1713
|
+
active_blend_shape_group_index: IntProperty(min=0) # type: ignore[valid-type]
|
|
1714
|
+
|
|
1715
|
+
if TYPE_CHECKING:
|
|
1716
|
+
# This code is auto generated.
|
|
1717
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
1718
|
+
blend_shape_groups: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
1719
|
+
Vrm0BlendShapeGroupPropertyGroup
|
|
1720
|
+
]
|
|
1721
|
+
active_blend_shape_group_index: int # type: ignore[no-redef]
|
|
1722
|
+
|
|
1723
|
+
|
|
1724
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_SecondaryAnimation.cs#L69-L78
|
|
1725
|
+
class Vrm0SecondaryAnimationPropertyGroup(PropertyGroup):
|
|
1726
|
+
bone_groups: CollectionProperty( # type: ignore[valid-type]
|
|
1727
|
+
name="Secondary Animation Groups",
|
|
1728
|
+
type=Vrm0SecondaryAnimationGroupPropertyGroup,
|
|
1729
|
+
)
|
|
1730
|
+
collider_groups: CollectionProperty( # type: ignore[valid-type]
|
|
1731
|
+
name="Collider Groups",
|
|
1732
|
+
type=Vrm0SecondaryAnimationColliderGroupPropertyGroup,
|
|
1733
|
+
)
|
|
1734
|
+
|
|
1735
|
+
# for UI
|
|
1736
|
+
show_expanded_bone_groups: BoolProperty( # type: ignore[valid-type]
|
|
1737
|
+
name="Spring Bone Groups",
|
|
1738
|
+
)
|
|
1739
|
+
show_expanded_collider_groups: BoolProperty( # type: ignore[valid-type]
|
|
1740
|
+
name="Collider Groups",
|
|
1741
|
+
)
|
|
1742
|
+
|
|
1743
|
+
active_bone_group_index: IntProperty(min=0) # type: ignore[valid-type]
|
|
1744
|
+
active_collider_group_index: IntProperty(min=0) # type: ignore[valid-type]
|
|
1745
|
+
|
|
1746
|
+
def fixup(self, armature_object: Optional[Object]) -> None:
|
|
1747
|
+
found_uuids = set[str]()
|
|
1748
|
+
for collider_group in self.collider_groups:
|
|
1749
|
+
if collider_group.uuid and collider_group.uuid not in found_uuids:
|
|
1750
|
+
found_uuids.add(collider_group.uuid)
|
|
1751
|
+
continue
|
|
1752
|
+
new_uuid = uuid.uuid4().hex
|
|
1753
|
+
_logger.error(
|
|
1754
|
+
"Collider group %s in secondary animation has no UUID or duplicated"
|
|
1755
|
+
" UUID. Assigning a new UUID %s.",
|
|
1756
|
+
collider_group.path_from_id(),
|
|
1757
|
+
new_uuid,
|
|
1758
|
+
)
|
|
1759
|
+
collider_group.uuid = new_uuid
|
|
1760
|
+
|
|
1761
|
+
for collider_group in self.collider_groups:
|
|
1762
|
+
collider_group.fixup(armature_object)
|
|
1763
|
+
|
|
1764
|
+
for bone_group in self.bone_groups:
|
|
1765
|
+
bone_group.fixup()
|
|
1766
|
+
|
|
1767
|
+
if TYPE_CHECKING:
|
|
1768
|
+
# This code is auto generated.
|
|
1769
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
1770
|
+
bone_groups: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
1771
|
+
Vrm0SecondaryAnimationGroupPropertyGroup
|
|
1772
|
+
]
|
|
1773
|
+
collider_groups: CollectionPropertyProtocol[ # type: ignore[no-redef]
|
|
1774
|
+
Vrm0SecondaryAnimationColliderGroupPropertyGroup
|
|
1775
|
+
]
|
|
1776
|
+
show_expanded_bone_groups: bool # type: ignore[no-redef]
|
|
1777
|
+
show_expanded_collider_groups: bool # type: ignore[no-redef]
|
|
1778
|
+
active_bone_group_index: int # type: ignore[no-redef]
|
|
1779
|
+
active_collider_group_index: int # type: ignore[no-redef]
|
|
1780
|
+
|
|
1781
|
+
|
|
1782
|
+
# https://github.com/vrm-c/UniVRM/blob/v0.91.1/Assets/VRM/Runtime/Format/glTF_VRM_extensions.cs#L8-L48
|
|
1783
|
+
class Vrm0PropertyGroup(PropertyGroup):
|
|
1784
|
+
meta: PointerProperty( # type: ignore[valid-type]
|
|
1785
|
+
name="VRM Meta",
|
|
1786
|
+
type=Vrm0MetaPropertyGroup,
|
|
1787
|
+
)
|
|
1788
|
+
humanoid: PointerProperty( # type: ignore[valid-type]
|
|
1789
|
+
name="VRM Humanoid",
|
|
1790
|
+
type=Vrm0HumanoidPropertyGroup,
|
|
1791
|
+
)
|
|
1792
|
+
first_person: PointerProperty( # type: ignore[valid-type]
|
|
1793
|
+
name="VRM First Person",
|
|
1794
|
+
type=Vrm0FirstPersonPropertyGroup,
|
|
1795
|
+
)
|
|
1796
|
+
blend_shape_master: PointerProperty( # type: ignore[valid-type]
|
|
1797
|
+
name="VRM Blend Shape Master",
|
|
1798
|
+
type=Vrm0BlendShapeMasterPropertyGroup,
|
|
1799
|
+
)
|
|
1800
|
+
secondary_animation: PointerProperty( # type: ignore[valid-type]
|
|
1801
|
+
name="VRM Secondary Animation",
|
|
1802
|
+
type=Vrm0SecondaryAnimationPropertyGroup,
|
|
1803
|
+
)
|
|
1804
|
+
if TYPE_CHECKING:
|
|
1805
|
+
# This code is auto generated.
|
|
1806
|
+
# To regenerate, run the `uv run tools/property_typing.py` command.
|
|
1807
|
+
meta: Vrm0MetaPropertyGroup # type: ignore[no-redef]
|
|
1808
|
+
humanoid: Vrm0HumanoidPropertyGroup # type: ignore[no-redef]
|
|
1809
|
+
first_person: Vrm0FirstPersonPropertyGroup # type: ignore[no-redef]
|
|
1810
|
+
blend_shape_master: Vrm0BlendShapeMasterPropertyGroup # type: ignore[no-redef]
|
|
1811
|
+
secondary_animation: ( # type: ignore[no-redef]
|
|
1812
|
+
Vrm0SecondaryAnimationPropertyGroup
|
|
1813
|
+
)
|
|
1814
|
+
|
|
1815
|
+
|
|
1816
|
+
def clear_global_variables() -> None:
|
|
1817
|
+
Vrm0HumanoidPropertyGroup.pointer_to_last_bone_names_str.clear()
|
|
1818
|
+
Vrm0BlendShapeGroupPropertyGroup.pending_preview_update_armature_data_names.clear()
|