@volter/blender-engine 0.1.148 → 0.1.149

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +4 -11
  3. package/browser/addons/vrm/LICENSE_(OPTION1)_MIT.txt +22 -0
  4. package/browser/addons/vrm/LICENSE_(OPTION2)_GPL-3_0.txt +674 -0
  5. package/browser/addons/vrm/LICENSE_MAIN.txt +1 -0
  6. package/browser/addons/vrm/README.txt +3 -0
  7. package/browser/addons/vrm/__init__.py +41 -0
  8. package/browser/addons/vrm/blender_manifest.toml +16 -0
  9. package/browser/addons/vrm/common/__init__.py +1 -0
  10. package/browser/addons/vrm/common/animation.py +58 -0
  11. package/browser/addons/vrm/common/blender_manifest.py +82 -0
  12. package/browser/addons/vrm/common/char.py +16 -0
  13. package/browser/addons/vrm/common/convert.py +287 -0
  14. package/browser/addons/vrm/common/convert_any.py +48 -0
  15. package/browser/addons/vrm/common/debug.py +40 -0
  16. package/browser/addons/vrm/common/deep.py +162 -0
  17. package/browser/addons/vrm/common/error_dialog.py +274 -0
  18. package/browser/addons/vrm/common/fs.py +71 -0
  19. package/browser/addons/vrm/common/gl.py +20 -0
  20. package/browser/addons/vrm/common/gltf.py +1149 -0
  21. package/browser/addons/vrm/common/human_bone_mapper/__init__.py +1 -0
  22. package/browser/addons/vrm/common/human_bone_mapper/biped_mapping.py +84 -0
  23. package/browser/addons/vrm/common/human_bone_mapper/cats_blender_plugin_fix_model_mapping.py +63 -0
  24. package/browser/addons/vrm/common/human_bone_mapper/human_bone_mapper.py +203 -0
  25. package/browser/addons/vrm/common/human_bone_mapper/microsoft_rocketbox_mapping.py +69 -0
  26. package/browser/addons/vrm/common/human_bone_mapper/mixamo_mapping.py +62 -0
  27. package/browser/addons/vrm/common/human_bone_mapper/mmd_mapping.py +115 -0
  28. package/browser/addons/vrm/common/human_bone_mapper/mpfb_mapping.py +120 -0
  29. package/browser/addons/vrm/common/human_bone_mapper/ready_player_me_mapping.py +65 -0
  30. package/browser/addons/vrm/common/human_bone_mapper/reallusion_mapping.py +94 -0
  31. package/browser/addons/vrm/common/human_bone_mapper/rigify_meta_rig_mapping.py +65 -0
  32. package/browser/addons/vrm/common/human_bone_mapper/structure_based_mapping.py +891 -0
  33. package/browser/addons/vrm/common/human_bone_mapper/unreal_mapping.py +62 -0
  34. package/browser/addons/vrm/common/human_bone_mapper/vrm_addon_mapping.py +112 -0
  35. package/browser/addons/vrm/common/human_bone_mapper/vroid_mapping.py +89 -0
  36. package/browser/addons/vrm/common/legacy_gltf.py +16 -0
  37. package/browser/addons/vrm/common/logger.py +84 -0
  38. package/browser/addons/vrm/common/mtoon0.blend +0 -0
  39. package/browser/addons/vrm/common/mtoon1.blend +0 -0
  40. package/browser/addons/vrm/common/mtoon1_outline.blend +0 -0
  41. package/browser/addons/vrm/common/mtoon_auto_setup.blend +0 -0
  42. package/browser/addons/vrm/common/mtoon_unversioned.py +62 -0
  43. package/browser/addons/vrm/common/ops/__init__.py +10 -0
  44. package/browser/addons/vrm/common/ops/export_scene.py +67 -0
  45. package/browser/addons/vrm/common/ops/icyp.py +53 -0
  46. package/browser/addons/vrm/common/ops/import_scene.py +57 -0
  47. package/browser/addons/vrm/common/ops/vrm.py +2380 -0
  48. package/browser/addons/vrm/common/ops/wm.py +167 -0
  49. package/browser/addons/vrm/common/preferences.py +362 -0
  50. package/browser/addons/vrm/common/progress.py +87 -0
  51. package/browser/addons/vrm/common/rotation.py +89 -0
  52. package/browser/addons/vrm/common/safe_removal.py +46 -0
  53. package/browser/addons/vrm/common/scene_watcher.py +230 -0
  54. package/browser/addons/vrm/common/shader.py +2243 -0
  55. package/browser/addons/vrm/common/shape_key_mapper/__init__.py +1 -0
  56. package/browser/addons/vrm/common/shape_key_mapper/arkit_mapping.py +168 -0
  57. package/browser/addons/vrm/common/shape_key_mapper/mmd_mapping.py +62 -0
  58. package/browser/addons/vrm/common/shape_key_mapper/ready_player_me_mapping.py +52 -0
  59. package/browser/addons/vrm/common/shape_key_mapper/vrchat_mapping.py +17 -0
  60. package/browser/addons/vrm/common/third_party_user_extension.py +214 -0
  61. package/browser/addons/vrm/common/transparent_z_write.blend +0 -0
  62. package/browser/addons/vrm/common/version.py +161 -0
  63. package/browser/addons/vrm/common/vrm0/__init__.py +1 -0
  64. package/browser/addons/vrm/common/vrm0/human_bone.py +662 -0
  65. package/browser/addons/vrm/common/vrm0/material_property.py +346 -0
  66. package/browser/addons/vrm/common/vrm1/__init__.py +1 -0
  67. package/browser/addons/vrm/common/vrm1/expression_preset.py +207 -0
  68. package/browser/addons/vrm/common/vrm1/human_bone.py +822 -0
  69. package/browser/addons/vrm/common/workspace.py +227 -0
  70. package/browser/addons/vrm/common/writable_context.py +77 -0
  71. package/browser/addons/vrm/documentation/en-us/animation/index.md +63 -0
  72. package/browser/addons/vrm/documentation/en-us/create-humanoid-vrm-from-scratch/index.md +131 -0
  73. package/browser/addons/vrm/documentation/en-us/create-simple-vrm-from-scratch/index.md +30 -0
  74. package/browser/addons/vrm/documentation/en-us/development/index.md +136 -0
  75. package/browser/addons/vrm/documentation/en-us/index.md +41 -0
  76. package/browser/addons/vrm/documentation/en-us/installation/index.md +152 -0
  77. package/browser/addons/vrm/documentation/en-us/material-mtoon/index.md +122 -0
  78. package/browser/addons/vrm/documentation/en-us/material-pbr/index.md +94 -0
  79. package/browser/addons/vrm/documentation/en-us/scripting-api/index.md +391 -0
  80. package/browser/addons/vrm/documentation/en-us/ui/export_scene.vrm/index.md +57 -0
  81. package/browser/addons/vrm/documentation/en-us/ui/export_scene.vrma/index.md +17 -0
  82. package/browser/addons/vrm/documentation/en-us/ui/import_scene.vrm/index.md +61 -0
  83. package/browser/addons/vrm/documentation/en-us/ui/import_scene.vrma/index.md +13 -0
  84. package/browser/addons/vrm/documentation/ja-jp/animation/index.md +57 -0
  85. package/browser/addons/vrm/documentation/ja-jp/create-humanoid-vrm-from-scratch/index.md +129 -0
  86. package/browser/addons/vrm/documentation/ja-jp/create-simple-vrm-from-scratch/index.md +29 -0
  87. package/browser/addons/vrm/documentation/ja-jp/development/index.md +137 -0
  88. package/browser/addons/vrm/documentation/ja-jp/index.md +37 -0
  89. package/browser/addons/vrm/documentation/ja-jp/installation/index.md +150 -0
  90. package/browser/addons/vrm/documentation/ja-jp/material-mtoon/index.md +113 -0
  91. package/browser/addons/vrm/documentation/ja-jp/material-pbr/index.md +90 -0
  92. package/browser/addons/vrm/documentation/ja-jp/scripting-api/index.md +389 -0
  93. package/browser/addons/vrm/documentation/ja-jp/ui/export_scene.vrm/index.md +55 -0
  94. package/browser/addons/vrm/documentation/ja-jp/ui/export_scene.vrma/index.md +19 -0
  95. package/browser/addons/vrm/documentation/ja-jp/ui/import_scene.vrm/index.md +56 -0
  96. package/browser/addons/vrm/documentation/ja-jp/ui/import_scene.vrma/index.md +14 -0
  97. package/browser/addons/vrm/editor/__init__.py +1 -0
  98. package/browser/addons/vrm/editor/extension.py +425 -0
  99. package/browser/addons/vrm/editor/extension_accessor.py +75 -0
  100. package/browser/addons/vrm/editor/handler.py +84 -0
  101. package/browser/addons/vrm/editor/khr_character/__init__.py +1 -0
  102. package/browser/addons/vrm/editor/khr_character/panel.py +69 -0
  103. package/browser/addons/vrm/editor/khr_character/property_group.py +27 -0
  104. package/browser/addons/vrm/editor/khr_xmp_json_ld/__init__.py +1 -0
  105. package/browser/addons/vrm/editor/khr_xmp_json_ld/ops.py +464 -0
  106. package/browser/addons/vrm/editor/khr_xmp_json_ld/panel.py +136 -0
  107. package/browser/addons/vrm/editor/khr_xmp_json_ld/property_group.py +83 -0
  108. package/browser/addons/vrm/editor/khr_xmp_json_ld/ui_list.py +198 -0
  109. package/browser/addons/vrm/editor/make_armature.py +709 -0
  110. package/browser/addons/vrm/editor/menu.py +147 -0
  111. package/browser/addons/vrm/editor/migration.py +297 -0
  112. package/browser/addons/vrm/editor/mtoon1/__init__.py +1 -0
  113. package/browser/addons/vrm/editor/mtoon1/handler.py +20 -0
  114. package/browser/addons/vrm/editor/mtoon1/migration.py +536 -0
  115. package/browser/addons/vrm/editor/mtoon1/ops.py +304 -0
  116. package/browser/addons/vrm/editor/mtoon1/panel.py +442 -0
  117. package/browser/addons/vrm/editor/mtoon1/property_group.py +4977 -0
  118. package/browser/addons/vrm/editor/mtoon1/scene_watcher.py +381 -0
  119. package/browser/addons/vrm/editor/node_constraint1/__init__.py +1 -0
  120. package/browser/addons/vrm/editor/node_constraint1/panel.py +317 -0
  121. package/browser/addons/vrm/editor/node_constraint1/property_group.py +25 -0
  122. package/browser/addons/vrm/editor/ops.py +471 -0
  123. package/browser/addons/vrm/editor/panel.py +315 -0
  124. package/browser/addons/vrm/editor/property_group.py +888 -0
  125. package/browser/addons/vrm/editor/search.py +682 -0
  126. package/browser/addons/vrm/editor/spring_bone1/__init__.py +1 -0
  127. package/browser/addons/vrm/editor/spring_bone1/handler.py +994 -0
  128. package/browser/addons/vrm/editor/spring_bone1/menu.py +246 -0
  129. package/browser/addons/vrm/editor/spring_bone1/migration.py +86 -0
  130. package/browser/addons/vrm/editor/spring_bone1/ops.py +1679 -0
  131. package/browser/addons/vrm/editor/spring_bone1/panel.py +605 -0
  132. package/browser/addons/vrm/editor/spring_bone1/property_group.py +1457 -0
  133. package/browser/addons/vrm/editor/spring_bone1/ui_list.py +408 -0
  134. package/browser/addons/vrm/editor/subscription.py +123 -0
  135. package/browser/addons/vrm/editor/t_pose.py +713 -0
  136. package/browser/addons/vrm/editor/validation.py +1271 -0
  137. package/browser/addons/vrm/editor/vrm0/__init__.py +1 -0
  138. package/browser/addons/vrm/editor/vrm0/gizmo_group.py +63 -0
  139. package/browser/addons/vrm/editor/vrm0/handler.py +23 -0
  140. package/browser/addons/vrm/editor/vrm0/menu.py +145 -0
  141. package/browser/addons/vrm/editor/vrm0/migration.py +761 -0
  142. package/browser/addons/vrm/editor/vrm0/ops.py +2145 -0
  143. package/browser/addons/vrm/editor/vrm0/panel.py +1333 -0
  144. package/browser/addons/vrm/editor/vrm0/property_group.py +1818 -0
  145. package/browser/addons/vrm/editor/vrm0/ui_list.py +688 -0
  146. package/browser/addons/vrm/editor/vrm1/__init__.py +1 -0
  147. package/browser/addons/vrm/editor/vrm1/handler.py +28 -0
  148. package/browser/addons/vrm/editor/vrm1/menu.py +76 -0
  149. package/browser/addons/vrm/editor/vrm1/migration.py +321 -0
  150. package/browser/addons/vrm/editor/vrm1/ops.py +2679 -0
  151. package/browser/addons/vrm/editor/vrm1/panel.py +1243 -0
  152. package/browser/addons/vrm/editor/vrm1/property_group.py +2087 -0
  153. package/browser/addons/vrm/editor/vrm1/scene_watcher.py +90 -0
  154. package/browser/addons/vrm/editor/vrm1/ui_list.py +533 -0
  155. package/browser/addons/vrm/exporter/__init__.py +1 -0
  156. package/browser/addons/vrm/exporter/abstract_base_vrm_exporter.py +628 -0
  157. package/browser/addons/vrm/exporter/export_scene.py +930 -0
  158. package/browser/addons/vrm/exporter/gltf2_export_user_extension.py +45 -0
  159. package/browser/addons/vrm/exporter/khr_character_exporter.py +34 -0
  160. package/browser/addons/vrm/exporter/vrm0_exporter.py +4020 -0
  161. package/browser/addons/vrm/exporter/vrm1_exporter.py +3682 -0
  162. package/browser/addons/vrm/exporter/vrm_animation_exporter.py +1035 -0
  163. package/browser/addons/vrm/external/__init__.py +1 -0
  164. package/browser/addons/vrm/external/auto_rig_pro_support.py +3 -0
  165. package/browser/addons/vrm/external/io_scene_gltf2_support.py +418 -0
  166. package/browser/addons/vrm/external/rigify_support.py +1 -0
  167. package/browser/addons/vrm/importer/__init__.py +1 -0
  168. package/browser/addons/vrm/importer/abstract_base_vrm_importer.py +1548 -0
  169. package/browser/addons/vrm/importer/file_handler.py +34 -0
  170. package/browser/addons/vrm/importer/gltf2_import_user_extension.py +268 -0
  171. package/browser/addons/vrm/importer/import_scene.py +646 -0
  172. package/browser/addons/vrm/importer/license_validation.py +198 -0
  173. package/browser/addons/vrm/importer/vrm0_importer.py +1723 -0
  174. package/browser/addons/vrm/importer/vrm1_importer.py +2014 -0
  175. package/browser/addons/vrm/importer/vrm_animation_importer.py +763 -0
  176. package/browser/addons/vrm/importer/vrm_diff.py +316 -0
  177. package/browser/addons/vrm/locale/__init__.py +1 -0
  178. package/browser/addons/vrm/locale/ja_jp.py +826 -0
  179. package/browser/addons/vrm/locale/ruff.toml +8 -0
  180. package/browser/addons/vrm/locale/translation_dictionary.py +10 -0
  181. package/browser/addons/vrm/locale/zh_hans.py +928 -0
  182. package/browser/addons/vrm/registration.py +670 -0
  183. package/browser/addons/vrm.json +18 -0
  184. package/browser/blender-emscripten-engine.mts +60 -128
  185. package/browser/blender-engine.mts +20 -186
  186. package/browser/blender-wali-engine.mts +35 -81
  187. package/browser/describe-thrown.mts +3 -6
  188. package/browser/document-chunks.mts +4 -16
  189. package/browser/gltf_export.py +3161 -0
  190. package/browser/heap-growth.mts +23 -0
  191. package/browser/index.ts +2 -0
  192. package/browser/protocol.ts +119 -35
  193. package/browser/pull-job.mts +2 -10
  194. package/browser/rna.ts +190 -73
  195. package/browser/runtime.ts +197 -82
  196. package/browser/session-addons.mts +33 -0
  197. package/browser/session-frame.mts +5 -24
  198. package/browser/session.py +1338 -1427
  199. package/browser/three/attach-presenter.ts +11 -39
  200. package/browser/three/blender-base64.ts +1 -36
  201. package/browser/three/blender-corner-normals.ts +1 -23
  202. package/browser/three/blender-display-shaders.json +1 -1
  203. package/browser/three/blender-display-shaders.lut +0 -0
  204. package/browser/three/blender-display-transform.ts +2 -1
  205. package/browser/three/blender-frame-columns.ts +5 -13
  206. package/browser/three/blender-graph-material.ts +18 -3
  207. package/browser/three/blender-node-graph.ts +10 -34
  208. package/browser/three/blender-physical-material.ts +2 -31
  209. package/browser/three/blender-runtime-armature.ts +7 -60
  210. package/browser/three/blender-runtime-frame.ts +9 -23
  211. package/browser/three/blender-runtime-geometry.ts +22 -26
  212. package/browser/three/blender-runtime-lighting.ts +48 -178
  213. package/browser/three/blender-runtime-shadows.ts +187 -1
  214. package/browser/three/blender-runtime-skeleton.ts +53 -1
  215. package/browser/three/blender-runtime-view.ts +505 -283
  216. package/browser/three/blender-runtime-weights.ts +9 -72
  217. package/browser/three/blender-sky.ts +13 -33
  218. package/browser/three/blender-triangulate.ts +7 -35
  219. package/browser/three/blender-viewport-sampling.ts +235 -0
  220. package/browser/three/blender-workbench-material.ts +25 -29
  221. package/browser/three/blender-workbench-outline.ts +199 -0
  222. package/browser/three/blender-world-volume.ts +62 -10
  223. package/browser/three/presenter.ts +10 -26
  224. package/browser/three/release.ts +5 -21
  225. package/browser/three/sky-precompute-worker.ts +1 -18
  226. package/browser/three/sky-worker.ts +5 -23
  227. package/browser/three/world-field-sampler.ts +12 -26
  228. package/browser/volter_three.py +9 -105
  229. package/browser/worker.ts +156 -151
  230. package/package.json +5 -2
  231. package/wasm/BUNDLE.json +17 -17
  232. package/wasm/DEPENDENCY-LICENSES.txt +14 -0
  233. package/wasm/blender_browser.data.br +0 -0
  234. package/wasm/blender_browser.js +1 -1
  235. package/wasm/blender_browser.wasm.br +0 -0
  236. package/browser/frame-transfer.mts +0 -19
  237. package/browser/three/agx-base-srgb.lut +0 -0
  238. package/browser/three/agx-look-medium-high-contrast.lut +0 -0
  239. package/browser/three/agx-look-punchy.lut +0 -0
  240. package/browser/three/blender-agx.ts +0 -235
  241. package/browser/three/blender-display-lut.ts +0 -145
  242. package/browser/three/blender-filmic.ts +0 -49
  243. package/browser/three/blender-standard.ts +0 -68
  244. package/browser/three/blender-world-visibility.ts +0 -278
  245. package/browser/three/filmic-srgb.lut +0 -0
@@ -0,0 +1,713 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
2
+ import math
3
+ from collections.abc import Generator, Mapping
4
+ from contextlib import contextmanager
5
+ from dataclasses import dataclass
6
+ from sys import float_info
7
+ from typing import Optional, Union
8
+
9
+ import bpy
10
+ from bpy.types import (
11
+ Armature,
12
+ Context,
13
+ Object,
14
+ Pose,
15
+ PoseBone,
16
+ )
17
+ from mathutils import Euler, Matrix, Quaternion, Vector
18
+
19
+ from ..common.logger import get_logger
20
+ from ..common.rotation import (
21
+ get_rotation_as_quaternion,
22
+ set_rotation_without_mode_change,
23
+ )
24
+ from ..common.vrm0.human_bone import HumanBoneName as Vrm0HumanBoneName
25
+ from ..common.vrm1.human_bone import HumanBoneName as Vrm1HumanBoneName
26
+ from ..common.workspace import save_workspace
27
+ from .extension import VrmAddonArmatureExtensionPropertyGroup
28
+ from .extension_accessor import get_armature_extension
29
+ from .vrm0.property_group import Vrm0HumanoidPropertyGroup
30
+ from .vrm1.property_group import Vrm1HumanoidPropertyGroup
31
+
32
+ _logger = get_logger(__name__)
33
+
34
+
35
+ def _set_bone_direction_to_align_child_bone(
36
+ context: Context,
37
+ armature: Object,
38
+ direction: Vector,
39
+ bone: PoseBone,
40
+ child_bone: PoseBone,
41
+ ) -> None:
42
+ world_bone_matrix = armature.matrix_world @ bone.matrix
43
+ world_child_bone_matrix = armature.matrix_world @ child_bone.matrix
44
+
45
+ world_bone_length = (
46
+ world_child_bone_matrix.translation - world_bone_matrix.translation
47
+ ).length
48
+
49
+ world_child_bone_from_translation = world_child_bone_matrix.translation
50
+ world_child_bone_to_translation = (
51
+ world_bone_matrix.translation + direction * world_bone_length
52
+ )
53
+
54
+ bone_local_child_bone_from_translation = (
55
+ armature.matrix_world @ bone.matrix
56
+ ).inverted_safe() @ world_child_bone_from_translation
57
+ bone_local_child_bone_to_translation = (
58
+ armature.matrix_world @ bone.matrix
59
+ ).inverted_safe() @ world_child_bone_to_translation
60
+
61
+ if bone_local_child_bone_from_translation.length_squared < float_info.epsilon:
62
+ return
63
+ if bone_local_child_bone_to_translation.length_squared < float_info.epsilon:
64
+ return
65
+
66
+ rotation = bone_local_child_bone_from_translation.rotation_difference(
67
+ bone_local_child_bone_to_translation
68
+ )
69
+
70
+ set_rotation_without_mode_change(bone, rotation @ get_rotation_as_quaternion(bone))
71
+
72
+ context.view_layer.update()
73
+
74
+
75
+ def _set_bone_direction_to_align_z_world_location(
76
+ context: Context,
77
+ armature: Object,
78
+ direction: Vector,
79
+ bone: PoseBone,
80
+ from_world_location: Vector,
81
+ ) -> None:
82
+ world_bone_translation = (armature.matrix_world @ bone.matrix).to_translation()
83
+ aligned_from_world_location = Vector(
84
+ (
85
+ from_world_location.x,
86
+ world_bone_translation.y,
87
+ from_world_location.z,
88
+ )
89
+ )
90
+ aligned_to_world_location = world_bone_translation + direction
91
+
92
+ bone_local_aligned_from_world_location = (
93
+ armature.matrix_world @ bone.matrix
94
+ ).inverted_safe() @ aligned_from_world_location
95
+ bone_local_aligned_to_world_location = (
96
+ armature.matrix_world @ bone.matrix
97
+ ).inverted_safe() @ aligned_to_world_location
98
+
99
+ if bone_local_aligned_from_world_location.length_squared < float_info.epsilon:
100
+ return
101
+ if bone_local_aligned_to_world_location.length_squared < float_info.epsilon:
102
+ return
103
+
104
+ rotation = bone_local_aligned_from_world_location.rotation_difference(
105
+ bone_local_aligned_to_world_location
106
+ )
107
+
108
+ set_rotation_without_mode_change(bone, rotation @ get_rotation_as_quaternion(bone))
109
+
110
+ context.view_layer.update()
111
+
112
+
113
+ @dataclass(frozen=True)
114
+ class ChainSingleChild:
115
+ direction: Vector
116
+ vrm0_human_bone_names: tuple[Vrm0HumanBoneName, ...]
117
+ vrm1_human_bone_names: tuple[Vrm1HumanBoneName, ...]
118
+
119
+ def execute(self, context: Context, armature: Object) -> None:
120
+ armature_data = armature.data
121
+ if not isinstance(armature_data, Armature):
122
+ raise TypeError
123
+
124
+ ext = get_armature_extension(armature_data)
125
+ if ext.is_vrm0():
126
+ humanoid = ext.vrm0.humanoid
127
+ bones: list[PoseBone] = []
128
+ for human_bone in humanoid.human_bones:
129
+ human_bone_name = Vrm0HumanBoneName.from_str(human_bone.bone)
130
+ if not human_bone_name:
131
+ continue
132
+ if human_bone_name not in self.vrm0_human_bone_names:
133
+ continue
134
+ bone = armature.pose.bones.get(human_bone.node.bone_name)
135
+ if not bone:
136
+ continue
137
+ bones.append(bone)
138
+ else:
139
+ human_bones = ext.vrm1.humanoid.human_bones
140
+ human_bone_name_to_human_bone = human_bones.human_bone_name_to_human_bone()
141
+ bones = [
142
+ bone
143
+ for bone in (
144
+ armature.pose.bones.get(human_bone.node.bone_name)
145
+ for human_bone in (
146
+ human_bone_name_to_human_bone.get(human_bone_name)
147
+ for human_bone_name in self.vrm1_human_bone_names
148
+ )
149
+ if human_bone
150
+ )
151
+ if bone
152
+ ]
153
+
154
+ if len(bones) < 2:
155
+ return
156
+
157
+ root_bone = bones[0]
158
+ tip_bone = bones[-1]
159
+
160
+ chained_bones: list[PoseBone] = []
161
+ searching_bone: Optional[PoseBone] = tip_bone
162
+ while True:
163
+ if not searching_bone:
164
+ return
165
+ chained_bones.insert(0, searching_bone)
166
+ if searching_bone == root_bone:
167
+ break
168
+ searching_bone = searching_bone.parent
169
+
170
+ for bone, child_bone in zip(chained_bones, chained_bones[1:]):
171
+ _set_bone_direction_to_align_child_bone(
172
+ context, armature, self.direction, bone, child_bone
173
+ )
174
+
175
+
176
+ @dataclass(frozen=True)
177
+ class ChainHorizontalMultipleChildren:
178
+ direction: Vector
179
+ vrm0_parent_human_bone_name: Vrm0HumanBoneName
180
+ vrm0_human_bone_names: tuple[Vrm0HumanBoneName, ...]
181
+ vrm1_parent_human_bone_name: Vrm1HumanBoneName
182
+ vrm1_human_bone_names: tuple[Vrm1HumanBoneName, ...]
183
+
184
+ def execute(self, context: Context, armature: Object) -> None:
185
+ armature_data = armature.data
186
+ if not isinstance(armature_data, Armature):
187
+ raise TypeError
188
+
189
+ ext = get_armature_extension(armature_data)
190
+ if ext.is_vrm0():
191
+ humanoid = ext.vrm0.humanoid
192
+ bones: list[PoseBone] = []
193
+ parent_bone: Optional[PoseBone] = None
194
+ for human_bone in humanoid.human_bones:
195
+ human_bone_name = Vrm0HumanBoneName.from_str(human_bone.bone)
196
+ if not human_bone_name:
197
+ continue
198
+ if human_bone_name == self.vrm0_parent_human_bone_name:
199
+ parent_bone = armature.pose.bones.get(human_bone.node.bone_name)
200
+ elif human_bone_name in self.vrm0_human_bone_names:
201
+ bone = armature.pose.bones.get(human_bone.node.bone_name)
202
+ if bone:
203
+ bones.append(bone)
204
+ else:
205
+ human_bones = ext.vrm1.humanoid.human_bones
206
+ human_bone_name_to_human_bone = human_bones.human_bone_name_to_human_bone()
207
+ bones = [
208
+ bone
209
+ for bone in (
210
+ armature.pose.bones.get(human_bone.node.bone_name)
211
+ for human_bone in (
212
+ human_bone_name_to_human_bone.get(human_bone_name)
213
+ for human_bone_name in self.vrm1_human_bone_names
214
+ )
215
+ if human_bone
216
+ )
217
+ if bone
218
+ ]
219
+ parent_human_bone = human_bone_name_to_human_bone.get(
220
+ self.vrm1_parent_human_bone_name
221
+ )
222
+ parent_bone = None
223
+ if parent_human_bone:
224
+ parent_bone = armature.pose.bones.get(parent_human_bone.node.bone_name)
225
+ if not bones:
226
+ return
227
+ world_location = Vector((0, 0, 0))
228
+ for bone in bones:
229
+ world_location += (armature.matrix_world @ bone.matrix).to_translation()
230
+ world_location /= len(bones)
231
+
232
+ if not parent_bone:
233
+ return
234
+
235
+ _set_bone_direction_to_align_z_world_location(
236
+ context, armature, self.direction, parent_bone, world_location
237
+ )
238
+
239
+
240
+ def _reset_root_to_human_bone_translation(
241
+ pose: Pose, ext: VrmAddonArmatureExtensionPropertyGroup
242
+ ) -> None:
243
+ # Reset positions from root bone to any Human bone
244
+ # No particular reason for not resetting all bones, just intuition
245
+ bones: list[PoseBone] = [bone for bone in pose.bones if not bone.parent]
246
+ while bones:
247
+ bone = bones.pop()
248
+ bone.location = Vector((0, 0, 0))
249
+
250
+ if ext.is_vrm1():
251
+ human_bone_name_to_human_bones = (
252
+ ext.vrm1.humanoid.human_bones.human_bone_name_to_human_bone()
253
+ )
254
+ if any(
255
+ True
256
+ for human_bone in human_bone_name_to_human_bones.values()
257
+ if human_bone.node.bone_name == bone.name
258
+ ):
259
+ continue
260
+
261
+ if ext.is_vrm0() and any(
262
+ True
263
+ for human_bone in ext.vrm0.humanoid.human_bones
264
+ if human_bone.node.bone_name == bone.name
265
+ ):
266
+ continue
267
+
268
+ bones.extend(bone.children)
269
+
270
+
271
+ def set_estimated_humanoid_t_pose(context: Context, armature: Object) -> bool:
272
+ armature_data = armature.data
273
+ if not isinstance(armature_data, Armature):
274
+ return False
275
+
276
+ ext = get_armature_extension(armature_data)
277
+ if ext.is_vrm0():
278
+ if not ext.vrm0.humanoid.bones_are_correctly_assigned():
279
+ return False
280
+ else:
281
+ human_bones = ext.vrm1.humanoid.human_bones
282
+ if not human_bones.bones_are_correctly_assigned():
283
+ return False
284
+
285
+ for bone in armature.pose.bones:
286
+ set_rotation_without_mode_change(bone, Quaternion())
287
+
288
+ _reset_root_to_human_bone_translation(armature.pose, ext)
289
+
290
+ context.view_layer.update()
291
+
292
+ # https://github.com/vrm-c/vrm-specification/blob/73855bb77d431a3374212551a4fa48e043be3ced/specification/VRMC_vrm-1.0/tpose.md
293
+ chains: tuple[Union[ChainSingleChild, ChainHorizontalMultipleChildren], ...] = (
294
+ ChainSingleChild(
295
+ Vector((-1, 0, 0)),
296
+ (
297
+ Vrm0HumanBoneName.RIGHT_UPPER_ARM,
298
+ Vrm0HumanBoneName.RIGHT_LOWER_ARM,
299
+ Vrm0HumanBoneName.RIGHT_HAND,
300
+ ),
301
+ (
302
+ Vrm1HumanBoneName.RIGHT_UPPER_ARM,
303
+ Vrm1HumanBoneName.RIGHT_LOWER_ARM,
304
+ Vrm1HumanBoneName.RIGHT_HAND,
305
+ ),
306
+ ),
307
+ ChainHorizontalMultipleChildren(
308
+ Vector((-1, 0, 0)),
309
+ Vrm0HumanBoneName.RIGHT_HAND,
310
+ (
311
+ Vrm0HumanBoneName.RIGHT_INDEX_PROXIMAL,
312
+ Vrm0HumanBoneName.RIGHT_MIDDLE_PROXIMAL,
313
+ Vrm0HumanBoneName.RIGHT_RING_PROXIMAL,
314
+ Vrm0HumanBoneName.RIGHT_LITTLE_PROXIMAL,
315
+ ),
316
+ Vrm1HumanBoneName.RIGHT_HAND,
317
+ (
318
+ Vrm1HumanBoneName.RIGHT_INDEX_PROXIMAL,
319
+ Vrm1HumanBoneName.RIGHT_MIDDLE_PROXIMAL,
320
+ Vrm1HumanBoneName.RIGHT_RING_PROXIMAL,
321
+ Vrm1HumanBoneName.RIGHT_LITTLE_PROXIMAL,
322
+ ),
323
+ ),
324
+ ChainSingleChild(
325
+ Vector((-math.sqrt(0.5), -math.sqrt(0.5), 0)),
326
+ (
327
+ Vrm0HumanBoneName.RIGHT_THUMB_PROXIMAL,
328
+ Vrm0HumanBoneName.RIGHT_THUMB_INTERMEDIATE,
329
+ Vrm0HumanBoneName.RIGHT_THUMB_DISTAL,
330
+ ),
331
+ (
332
+ Vrm1HumanBoneName.RIGHT_THUMB_METACARPAL,
333
+ Vrm1HumanBoneName.RIGHT_THUMB_PROXIMAL,
334
+ Vrm1HumanBoneName.RIGHT_THUMB_DISTAL,
335
+ ),
336
+ ),
337
+ ChainSingleChild(
338
+ Vector((-1, 0, 0)),
339
+ (
340
+ Vrm0HumanBoneName.RIGHT_INDEX_PROXIMAL,
341
+ Vrm0HumanBoneName.RIGHT_INDEX_INTERMEDIATE,
342
+ Vrm0HumanBoneName.RIGHT_INDEX_DISTAL,
343
+ ),
344
+ (
345
+ Vrm1HumanBoneName.RIGHT_INDEX_PROXIMAL,
346
+ Vrm1HumanBoneName.RIGHT_INDEX_INTERMEDIATE,
347
+ Vrm1HumanBoneName.RIGHT_INDEX_DISTAL,
348
+ ),
349
+ ),
350
+ ChainSingleChild(
351
+ Vector((-1, 0, 0)),
352
+ (
353
+ Vrm0HumanBoneName.RIGHT_MIDDLE_PROXIMAL,
354
+ Vrm0HumanBoneName.RIGHT_MIDDLE_INTERMEDIATE,
355
+ Vrm0HumanBoneName.RIGHT_MIDDLE_DISTAL,
356
+ ),
357
+ (
358
+ Vrm1HumanBoneName.RIGHT_MIDDLE_PROXIMAL,
359
+ Vrm1HumanBoneName.RIGHT_MIDDLE_INTERMEDIATE,
360
+ Vrm1HumanBoneName.RIGHT_MIDDLE_DISTAL,
361
+ ),
362
+ ),
363
+ ChainSingleChild(
364
+ Vector((-1, 0, 0)),
365
+ (
366
+ Vrm0HumanBoneName.RIGHT_RING_PROXIMAL,
367
+ Vrm0HumanBoneName.RIGHT_RING_INTERMEDIATE,
368
+ Vrm0HumanBoneName.RIGHT_RING_DISTAL,
369
+ ),
370
+ (
371
+ Vrm1HumanBoneName.RIGHT_RING_PROXIMAL,
372
+ Vrm1HumanBoneName.RIGHT_RING_INTERMEDIATE,
373
+ Vrm1HumanBoneName.RIGHT_RING_DISTAL,
374
+ ),
375
+ ),
376
+ ChainSingleChild(
377
+ Vector((-1, 0, 0)),
378
+ (
379
+ Vrm0HumanBoneName.RIGHT_LITTLE_PROXIMAL,
380
+ Vrm0HumanBoneName.RIGHT_LITTLE_INTERMEDIATE,
381
+ Vrm0HumanBoneName.RIGHT_LITTLE_DISTAL,
382
+ ),
383
+ (
384
+ Vrm1HumanBoneName.RIGHT_LITTLE_PROXIMAL,
385
+ Vrm1HumanBoneName.RIGHT_LITTLE_INTERMEDIATE,
386
+ Vrm1HumanBoneName.RIGHT_LITTLE_DISTAL,
387
+ ),
388
+ ),
389
+ ChainSingleChild(
390
+ Vector((0, 0, -1)),
391
+ (
392
+ Vrm0HumanBoneName.RIGHT_UPPER_LEG,
393
+ Vrm0HumanBoneName.RIGHT_LOWER_LEG,
394
+ Vrm0HumanBoneName.RIGHT_FOOT,
395
+ ),
396
+ (
397
+ Vrm1HumanBoneName.RIGHT_UPPER_LEG,
398
+ Vrm1HumanBoneName.RIGHT_LOWER_LEG,
399
+ Vrm1HumanBoneName.RIGHT_FOOT,
400
+ ),
401
+ ),
402
+ ChainSingleChild(
403
+ Vector((1, 0, 0)),
404
+ (
405
+ Vrm0HumanBoneName.LEFT_UPPER_ARM,
406
+ Vrm0HumanBoneName.LEFT_LOWER_ARM,
407
+ Vrm0HumanBoneName.LEFT_HAND,
408
+ ),
409
+ (
410
+ Vrm1HumanBoneName.LEFT_UPPER_ARM,
411
+ Vrm1HumanBoneName.LEFT_LOWER_ARM,
412
+ Vrm1HumanBoneName.LEFT_HAND,
413
+ ),
414
+ ),
415
+ ChainHorizontalMultipleChildren(
416
+ Vector((1, 0, 0)),
417
+ Vrm0HumanBoneName.LEFT_HAND,
418
+ (
419
+ Vrm0HumanBoneName.LEFT_INDEX_PROXIMAL,
420
+ Vrm0HumanBoneName.LEFT_MIDDLE_PROXIMAL,
421
+ Vrm0HumanBoneName.LEFT_RING_PROXIMAL,
422
+ Vrm0HumanBoneName.LEFT_LITTLE_PROXIMAL,
423
+ ),
424
+ Vrm1HumanBoneName.LEFT_HAND,
425
+ (
426
+ Vrm1HumanBoneName.LEFT_INDEX_PROXIMAL,
427
+ Vrm1HumanBoneName.LEFT_MIDDLE_PROXIMAL,
428
+ Vrm1HumanBoneName.LEFT_RING_PROXIMAL,
429
+ Vrm1HumanBoneName.LEFT_LITTLE_PROXIMAL,
430
+ ),
431
+ ),
432
+ ChainSingleChild(
433
+ Vector((math.sqrt(0.5), -math.sqrt(0.5), 0)),
434
+ (
435
+ Vrm0HumanBoneName.LEFT_THUMB_PROXIMAL,
436
+ Vrm0HumanBoneName.LEFT_THUMB_INTERMEDIATE,
437
+ Vrm0HumanBoneName.LEFT_THUMB_DISTAL,
438
+ ),
439
+ (
440
+ Vrm1HumanBoneName.LEFT_THUMB_METACARPAL,
441
+ Vrm1HumanBoneName.LEFT_THUMB_PROXIMAL,
442
+ Vrm1HumanBoneName.LEFT_THUMB_DISTAL,
443
+ ),
444
+ ),
445
+ ChainSingleChild(
446
+ Vector((1, 0, 0)),
447
+ (
448
+ Vrm0HumanBoneName.LEFT_INDEX_PROXIMAL,
449
+ Vrm0HumanBoneName.LEFT_INDEX_INTERMEDIATE,
450
+ Vrm0HumanBoneName.LEFT_INDEX_DISTAL,
451
+ ),
452
+ (
453
+ Vrm1HumanBoneName.LEFT_INDEX_PROXIMAL,
454
+ Vrm1HumanBoneName.LEFT_INDEX_INTERMEDIATE,
455
+ Vrm1HumanBoneName.LEFT_INDEX_DISTAL,
456
+ ),
457
+ ),
458
+ ChainSingleChild(
459
+ Vector((1, 0, 0)),
460
+ (
461
+ Vrm0HumanBoneName.LEFT_MIDDLE_PROXIMAL,
462
+ Vrm0HumanBoneName.LEFT_MIDDLE_INTERMEDIATE,
463
+ Vrm0HumanBoneName.LEFT_MIDDLE_DISTAL,
464
+ ),
465
+ (
466
+ Vrm1HumanBoneName.LEFT_MIDDLE_PROXIMAL,
467
+ Vrm1HumanBoneName.LEFT_MIDDLE_INTERMEDIATE,
468
+ Vrm1HumanBoneName.LEFT_MIDDLE_DISTAL,
469
+ ),
470
+ ),
471
+ ChainSingleChild(
472
+ Vector((1, 0, 0)),
473
+ (
474
+ Vrm0HumanBoneName.LEFT_RING_PROXIMAL,
475
+ Vrm0HumanBoneName.LEFT_RING_INTERMEDIATE,
476
+ Vrm0HumanBoneName.LEFT_RING_DISTAL,
477
+ ),
478
+ (
479
+ Vrm1HumanBoneName.LEFT_RING_PROXIMAL,
480
+ Vrm1HumanBoneName.LEFT_RING_INTERMEDIATE,
481
+ Vrm1HumanBoneName.LEFT_RING_DISTAL,
482
+ ),
483
+ ),
484
+ ChainSingleChild(
485
+ Vector((1, 0, 0)),
486
+ (
487
+ Vrm0HumanBoneName.LEFT_LITTLE_PROXIMAL,
488
+ Vrm0HumanBoneName.LEFT_LITTLE_INTERMEDIATE,
489
+ Vrm0HumanBoneName.LEFT_LITTLE_DISTAL,
490
+ ),
491
+ (
492
+ Vrm1HumanBoneName.LEFT_LITTLE_PROXIMAL,
493
+ Vrm1HumanBoneName.LEFT_LITTLE_INTERMEDIATE,
494
+ Vrm1HumanBoneName.LEFT_LITTLE_DISTAL,
495
+ ),
496
+ ),
497
+ ChainSingleChild(
498
+ Vector((0, 0, -1)),
499
+ (
500
+ Vrm0HumanBoneName.LEFT_UPPER_LEG,
501
+ Vrm0HumanBoneName.LEFT_LOWER_LEG,
502
+ Vrm0HumanBoneName.LEFT_FOOT,
503
+ ),
504
+ (
505
+ Vrm1HumanBoneName.LEFT_UPPER_LEG,
506
+ Vrm1HumanBoneName.LEFT_LOWER_LEG,
507
+ Vrm1HumanBoneName.LEFT_FOOT,
508
+ ),
509
+ ),
510
+ )
511
+ for chain in chains:
512
+ chain.execute(context, armature)
513
+
514
+ return True
515
+
516
+
517
+ @dataclass(frozen=True)
518
+ class PoseBonePose:
519
+ matrix_basis: Matrix
520
+ rotation_mode: str
521
+ rotation_quaternion: Quaternion
522
+ rotation_axis_angle: tuple[float, float, float, float]
523
+ rotation_euler: Euler
524
+ scale: Vector
525
+ location: Vector
526
+ bone_select: bool
527
+
528
+ @staticmethod
529
+ def save(pose: Pose) -> Mapping[str, "PoseBonePose"]:
530
+ return {
531
+ bone.name: PoseBonePose(
532
+ matrix_basis=bone.matrix_basis.copy(),
533
+ rotation_mode=bone.rotation_mode,
534
+ rotation_quaternion=bone.rotation_quaternion.copy(),
535
+ rotation_axis_angle=(
536
+ bone.rotation_axis_angle[0],
537
+ bone.rotation_axis_angle[1],
538
+ bone.rotation_axis_angle[2],
539
+ bone.rotation_axis_angle[3],
540
+ ),
541
+ rotation_euler=bone.rotation_euler.copy(),
542
+ scale=bone.scale.copy(),
543
+ location=bone.location.copy(),
544
+ bone_select=(bone.bone.select if bpy.app.version < (5, 0) else False),
545
+ )
546
+ for bone in pose.bones
547
+ }
548
+
549
+ @staticmethod
550
+ def load(
551
+ context: Context,
552
+ pose: Pose,
553
+ bone_name_to_pose_bone_pose: Mapping[str, "PoseBonePose"],
554
+ ) -> None:
555
+ context.view_layer.update()
556
+
557
+ bones = [bone for bone in pose.bones if not bone.parent]
558
+ while bones:
559
+ bone = bones.pop()
560
+ pose_bone_pose = bone_name_to_pose_bone_pose.get(bone.name)
561
+ if pose_bone_pose:
562
+ bone.matrix_basis = pose_bone_pose.matrix_basis.copy()
563
+ # Directly restoring bone.matrix seems more efficient, but doing so
564
+ # can cause problems when constraints are attached
565
+ # https://github.com/saturday06/VRM-Addon-for-Blender/issues/671
566
+ bone.rotation_mode = pose_bone_pose.rotation_mode
567
+ bone.rotation_axis_angle = list(pose_bone_pose.rotation_axis_angle)
568
+ bone.rotation_quaternion = pose_bone_pose.rotation_quaternion.copy()
569
+ bone.rotation_euler = pose_bone_pose.rotation_euler.copy()
570
+ bone.scale = pose_bone_pose.scale.copy()
571
+ bone.location = pose_bone_pose.location.copy()
572
+ if bpy.app.version < (5, 0):
573
+ bone.bone.select = pose_bone_pose.bone_select
574
+ bones.extend(bone.children)
575
+
576
+ context.view_layer.update()
577
+
578
+
579
+ def _leave_setup_humanoid_t_pose(
580
+ context: Context,
581
+ armature: Object,
582
+ saved_pose_bone_pose: Mapping[str, PoseBonePose],
583
+ saved_pose_position: str,
584
+ *,
585
+ saved_vrm1_look_at_preview: bool,
586
+ ) -> None:
587
+ with save_workspace(context, armature):
588
+ bpy.ops.object.select_all(action="DESELECT")
589
+ bpy.ops.object.mode_set(mode="POSE")
590
+ PoseBonePose.load(context, armature.pose, saved_pose_bone_pose)
591
+ bpy.ops.object.mode_set(mode="OBJECT")
592
+
593
+ armature_data = armature.data
594
+ if not isinstance(armature_data, Armature):
595
+ return
596
+ armature_data.pose_position = saved_pose_position
597
+ ext = get_armature_extension(armature_data)
598
+ if (
599
+ ext.is_vrm1()
600
+ and ext.vrm1.look_at.enable_preview != saved_vrm1_look_at_preview
601
+ ):
602
+ ext.vrm1.look_at.enable_preview = saved_vrm1_look_at_preview
603
+
604
+
605
+ @contextmanager
606
+ def setup_humanoid_t_pose(
607
+ context: Context,
608
+ armature: Object,
609
+ ) -> Generator[None]:
610
+ armature_data = armature.data
611
+ if not isinstance(armature_data, Armature):
612
+ raise TypeError
613
+ ext = get_armature_extension(armature_data)
614
+ if ext.is_vrm0():
615
+ humanoid: Union[Vrm0HumanoidPropertyGroup, Vrm1HumanoidPropertyGroup] = (
616
+ ext.vrm0.humanoid
617
+ )
618
+ else:
619
+ humanoid = ext.vrm1.humanoid
620
+ pose = humanoid.pose
621
+ action = humanoid.pose_library
622
+ pose_marker_name = humanoid.pose_marker_name
623
+
624
+ if pose != humanoid.POSE_CUSTOM_POSE.identifier:
625
+ action = None
626
+ pose_marker_name = ""
627
+
628
+ if (
629
+ pose == humanoid.POSE_CURRENT_POSE.identifier
630
+ and armature_data.pose_position == "REST"
631
+ ):
632
+ yield
633
+ return
634
+
635
+ if pose == humanoid.POSE_REST_POSITION_POSE.identifier or (
636
+ pose == humanoid.POSE_CUSTOM_POSE.identifier
637
+ and not (action and action.name in context.blend_data.actions)
638
+ ):
639
+ saved_pose_position = armature_data.pose_position
640
+ armature_data.pose_position = "REST"
641
+ try:
642
+ yield
643
+ finally:
644
+ armature_data.pose_position = saved_pose_position
645
+ return
646
+
647
+ with save_workspace(context, armature):
648
+ bpy.ops.object.select_all(action="DESELECT")
649
+ bpy.ops.object.mode_set(mode="POSE")
650
+
651
+ saved_pose_position = armature_data.pose_position
652
+ if armature_data.pose_position != "POSE":
653
+ armature_data.pose_position = "POSE"
654
+
655
+ context.view_layer.update()
656
+
657
+ saved_pose_bone_pose = PoseBonePose.save(armature.pose)
658
+
659
+ if bpy.app.version < (5, 0):
660
+ for bone in armature.pose.bones:
661
+ bone.bone.select = False
662
+
663
+ ext = get_armature_extension(armature_data)
664
+ saved_vrm1_look_at_preview = ext.vrm1.look_at.enable_preview
665
+ if ext.is_vrm1() and ext.vrm1.look_at.enable_preview:
666
+ _logger.warning(
667
+ "The Look At preview is enabled. It will be temporarily disabled."
668
+ )
669
+ ext.vrm1.look_at.enable_preview = False
670
+ if ext.vrm1.look_at.type == ext.vrm1.look_at.TYPE_BONE.identifier:
671
+ human_bones = ext.vrm1.humanoid.human_bones
672
+
673
+ left_eye_bone_name = human_bones.left_eye.node.bone_name
674
+ left_eye_bone = armature.pose.bones.get(left_eye_bone_name)
675
+ if left_eye_bone:
676
+ set_rotation_without_mode_change(left_eye_bone, Quaternion())
677
+
678
+ right_eye_bone_name = human_bones.right_eye.node.bone_name
679
+ right_eye_bone = armature.pose.bones.get(right_eye_bone_name)
680
+ if right_eye_bone:
681
+ set_rotation_without_mode_change(right_eye_bone, Quaternion())
682
+
683
+ if pose == humanoid.POSE_AUTO_POSE.identifier:
684
+ set_estimated_humanoid_t_pose(context, armature)
685
+ elif pose == humanoid.POSE_CUSTOM_POSE.identifier:
686
+ if action and action.name in context.blend_data.actions:
687
+ pose_marker_frame = 0
688
+ if pose_marker_name:
689
+ for search_pose_marker in action.pose_markers.values():
690
+ if search_pose_marker.name == pose_marker_name:
691
+ pose_marker_frame = search_pose_marker.frame
692
+ break
693
+ armature.pose.apply_pose_from_action(
694
+ action, evaluation_time=pose_marker_frame
695
+ )
696
+ else:
697
+ set_estimated_humanoid_t_pose(context, armature)
698
+
699
+ context.view_layer.update()
700
+
701
+ try:
702
+ yield
703
+ # After yield, bpy native objects may be deleted or frames may advance
704
+ # making them invalid. Accessing them in this state can cause crashes,
705
+ # so be careful not to access potentially invalid native objects after yield
706
+ finally:
707
+ _leave_setup_humanoid_t_pose(
708
+ context,
709
+ armature,
710
+ saved_pose_bone_pose,
711
+ saved_pose_position,
712
+ saved_vrm1_look_at_preview=saved_vrm1_look_at_preview,
713
+ )