@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.
Files changed (245) hide show
  1. package/LICENSE +22 -5
  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 +66 -129
  185. package/browser/blender-engine.mts +20 -186
  186. package/browser/blender-wali-engine.mts +37 -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 +3 -0
  192. package/browser/protocol.ts +130 -43
  193. package/browser/pull-job.mts +2 -10
  194. package/browser/rna.ts +190 -73
  195. package/browser/runtime.ts +271 -106
  196. package/browser/session-addons.mts +33 -0
  197. package/browser/session-frame.mts +5 -24
  198. package/browser/session.py +1389 -1446
  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 +492 -306
  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 +195 -180
  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,1243 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
2
+
3
+ from typing import ClassVar
4
+
5
+ import bpy
6
+ from bpy.app.translations import pgettext
7
+ from bpy.types import Armature, Context, Mesh, Object, Panel, UILayout
8
+
9
+ from ...common.logger import get_logger
10
+ from ...common.vrm1.human_bone import HumanBoneSpecifications
11
+ from .. import ops, search
12
+ from ..extension_accessor import get_armature_extension, get_bone_extension
13
+ from ..migration import defer_migrate
14
+ from ..ops import layout_operator
15
+ from ..panel import (
16
+ VRM_PT_vrm_armature_object_property,
17
+ draw_template_list,
18
+ draw_url_warning,
19
+ )
20
+ from ..search import active_object_is_vrm1_armature
21
+ from . import ops as vrm1_ops
22
+ from .menu import VRM_MT_vrm1_expression
23
+ from .ops import draw_bone_prop_search
24
+ from .property_group import (
25
+ Vrm1ExpressionsPropertyGroup,
26
+ Vrm1FirstPersonPropertyGroup,
27
+ Vrm1HumanBonesPropertyGroup,
28
+ Vrm1HumanoidPropertyGroup,
29
+ Vrm1LookAtPropertyGroup,
30
+ Vrm1MaterialColorBindPropertyGroup,
31
+ Vrm1MetaPropertyGroup,
32
+ Vrm1MorphTargetBindPropertyGroup,
33
+ Vrm1TextureTransformBindPropertyGroup,
34
+ )
35
+ from .ui_list import (
36
+ VRM_UL_vrm1_expression,
37
+ VRM_UL_vrm1_first_person_mesh_annotation,
38
+ VRM_UL_vrm1_material_color_bind,
39
+ VRM_UL_vrm1_meta_author,
40
+ VRM_UL_vrm1_meta_reference,
41
+ VRM_UL_vrm1_morph_target_bind,
42
+ VRM_UL_vrm1_texture_transform_bind,
43
+ )
44
+
45
+ _logger = get_logger(__name__)
46
+
47
+
48
+ def draw_vrm1_humanoid_required_bones_layout(
49
+ armature: Object,
50
+ layout: UILayout,
51
+ ) -> None:
52
+ split_factor = 0.2
53
+
54
+ layout.label(text="Required VRM Human Bones", icon="ARMATURE_DATA")
55
+
56
+ row = layout.row(align=True).split(factor=split_factor, align=True)
57
+ label_column = row.column(align=True)
58
+ label_column.label(text=HumanBoneSpecifications.HEAD.label)
59
+ label_column.label(text=HumanBoneSpecifications.SPINE.label)
60
+ label_column.label(text=HumanBoneSpecifications.HIPS.label)
61
+
62
+ search_column = row.column(align=True)
63
+ draw_bone_prop_search(search_column, HumanBoneSpecifications.HEAD, armature)
64
+ draw_bone_prop_search(search_column, HumanBoneSpecifications.SPINE, armature)
65
+ draw_bone_prop_search(search_column, HumanBoneSpecifications.HIPS, armature)
66
+
67
+ row = layout.row(align=True).split(factor=split_factor, align=True)
68
+ label_column = row.column(align=True)
69
+ label_column.label(text="")
70
+ label_column.label(text=HumanBoneSpecifications.LEFT_UPPER_ARM.label_no_left_right)
71
+ label_column.label(text=HumanBoneSpecifications.LEFT_LOWER_ARM.label_no_left_right)
72
+ label_column.label(text=HumanBoneSpecifications.LEFT_HAND.label_no_left_right)
73
+ label_column.separator()
74
+ label_column.label(text=HumanBoneSpecifications.LEFT_UPPER_LEG.label_no_left_right)
75
+ label_column.label(text=HumanBoneSpecifications.LEFT_LOWER_LEG.label_no_left_right)
76
+ label_column.label(text=HumanBoneSpecifications.LEFT_FOOT.label_no_left_right)
77
+
78
+ search_column = row.column(align=True)
79
+ right_left_row = search_column.row(align=True)
80
+ right_left_row.label(text="Right")
81
+ right_left_row.label(text="Left")
82
+
83
+ right_left_row = search_column.row(align=True)
84
+ draw_bone_prop_search(
85
+ right_left_row, HumanBoneSpecifications.RIGHT_UPPER_ARM, armature
86
+ )
87
+ draw_bone_prop_search(
88
+ right_left_row, HumanBoneSpecifications.LEFT_UPPER_ARM, armature
89
+ )
90
+
91
+ right_left_row = search_column.row(align=True)
92
+ draw_bone_prop_search(
93
+ right_left_row, HumanBoneSpecifications.RIGHT_LOWER_ARM, armature
94
+ )
95
+ draw_bone_prop_search(
96
+ right_left_row, HumanBoneSpecifications.LEFT_LOWER_ARM, armature
97
+ )
98
+
99
+ right_left_row = search_column.row(align=True)
100
+ draw_bone_prop_search(right_left_row, HumanBoneSpecifications.RIGHT_HAND, armature)
101
+ draw_bone_prop_search(right_left_row, HumanBoneSpecifications.LEFT_HAND, armature)
102
+
103
+ search_column.separator()
104
+
105
+ right_left_row = search_column.row(align=True)
106
+ draw_bone_prop_search(
107
+ right_left_row, HumanBoneSpecifications.RIGHT_UPPER_LEG, armature
108
+ )
109
+ draw_bone_prop_search(
110
+ right_left_row, HumanBoneSpecifications.LEFT_UPPER_LEG, armature
111
+ )
112
+
113
+ right_left_row = search_column.row(align=True)
114
+ draw_bone_prop_search(
115
+ right_left_row, HumanBoneSpecifications.RIGHT_LOWER_LEG, armature
116
+ )
117
+ draw_bone_prop_search(
118
+ right_left_row, HumanBoneSpecifications.LEFT_LOWER_LEG, armature
119
+ )
120
+
121
+ right_left_row = search_column.row(align=True)
122
+ draw_bone_prop_search(right_left_row, HumanBoneSpecifications.RIGHT_FOOT, armature)
123
+ draw_bone_prop_search(right_left_row, HumanBoneSpecifications.LEFT_FOOT, armature)
124
+
125
+
126
+ def draw_vrm1_humanoid_optional_bones_layout(
127
+ armature: Object,
128
+ layout: UILayout,
129
+ ) -> None:
130
+ split_factor = 0.2
131
+
132
+ layout.label(text="Optional VRM Human Bones", icon="BONE_DATA")
133
+
134
+ row = layout.row(align=True).split(factor=split_factor, align=True)
135
+ label_column = row.column(align=True)
136
+ label_column.label(text="")
137
+ label_column.label(text=HumanBoneSpecifications.LEFT_EYE.label_no_left_right)
138
+ label_column.label(text=HumanBoneSpecifications.JAW.label)
139
+ label_column.label(text=HumanBoneSpecifications.NECK.label)
140
+ label_column.label(text=HumanBoneSpecifications.RIGHT_SHOULDER.label_no_left_right)
141
+ label_column.label(text=HumanBoneSpecifications.UPPER_CHEST.label)
142
+ label_column.label(text=HumanBoneSpecifications.CHEST.label)
143
+ label_column.label(text=HumanBoneSpecifications.RIGHT_TOES.label_no_left_right)
144
+
145
+ search_column = row.column(align=True)
146
+
147
+ right_left_row = search_column.row(align=True)
148
+ right_left_row.label(text="Right")
149
+ right_left_row.label(text="Left")
150
+
151
+ right_left_row = search_column.row(align=True)
152
+ draw_bone_prop_search(right_left_row, HumanBoneSpecifications.RIGHT_EYE, armature)
153
+ draw_bone_prop_search(right_left_row, HumanBoneSpecifications.LEFT_EYE, armature)
154
+
155
+ draw_bone_prop_search(search_column, HumanBoneSpecifications.JAW, armature)
156
+ draw_bone_prop_search(search_column, HumanBoneSpecifications.NECK, armature)
157
+
158
+ right_left_row = search_column.row(align=True)
159
+ draw_bone_prop_search(
160
+ right_left_row, HumanBoneSpecifications.RIGHT_SHOULDER, armature
161
+ )
162
+ draw_bone_prop_search(
163
+ right_left_row, HumanBoneSpecifications.LEFT_SHOULDER, armature
164
+ )
165
+
166
+ draw_bone_prop_search(search_column, HumanBoneSpecifications.UPPER_CHEST, armature)
167
+ draw_bone_prop_search(search_column, HumanBoneSpecifications.CHEST, armature)
168
+
169
+ right_left_row = search_column.row(align=True)
170
+ draw_bone_prop_search(right_left_row, HumanBoneSpecifications.RIGHT_TOES, armature)
171
+ draw_bone_prop_search(right_left_row, HumanBoneSpecifications.LEFT_TOES, armature)
172
+
173
+ row = layout.row(align=True).split(factor=split_factor, align=True)
174
+ label_column = row.column(align=True)
175
+ label_column.label(text="", translate=False)
176
+ label_column.label(text="Left Thumb:")
177
+ label_column.label(text="Left Index:")
178
+ label_column.label(text="Left Middle:")
179
+ label_column.label(text="Left Ring:")
180
+ label_column.label(text="Left Little:")
181
+ label_column.separator()
182
+ label_column.label(text="Right Thumb:")
183
+ label_column.label(text="Right Index:")
184
+ label_column.label(text="Right Middle:")
185
+ label_column.label(text="Right Ring:")
186
+ label_column.label(text="Right Little:")
187
+
188
+ search_column = row.column(align=True)
189
+
190
+ finger_row = search_column.row(align=True)
191
+ finger_row.label(text="Root")
192
+ finger_row.label(text="", translate=False)
193
+ finger_row.label(text="Tip")
194
+
195
+ finger_row = search_column.row(align=True)
196
+ draw_bone_prop_search(
197
+ finger_row, HumanBoneSpecifications.LEFT_THUMB_METACARPAL, armature
198
+ )
199
+ draw_bone_prop_search(
200
+ finger_row, HumanBoneSpecifications.LEFT_THUMB_PROXIMAL, armature
201
+ )
202
+ draw_bone_prop_search(
203
+ finger_row, HumanBoneSpecifications.LEFT_THUMB_DISTAL, armature
204
+ )
205
+
206
+ finger_row = search_column.row(align=True)
207
+ draw_bone_prop_search(
208
+ finger_row, HumanBoneSpecifications.LEFT_INDEX_PROXIMAL, armature
209
+ )
210
+ draw_bone_prop_search(
211
+ finger_row, HumanBoneSpecifications.LEFT_INDEX_INTERMEDIATE, armature
212
+ )
213
+ draw_bone_prop_search(
214
+ finger_row, HumanBoneSpecifications.LEFT_INDEX_DISTAL, armature
215
+ )
216
+
217
+ finger_row = search_column.row(align=True)
218
+ draw_bone_prop_search(
219
+ finger_row, HumanBoneSpecifications.LEFT_MIDDLE_PROXIMAL, armature
220
+ )
221
+ draw_bone_prop_search(
222
+ finger_row, HumanBoneSpecifications.LEFT_MIDDLE_INTERMEDIATE, armature
223
+ )
224
+ draw_bone_prop_search(
225
+ finger_row, HumanBoneSpecifications.LEFT_MIDDLE_DISTAL, armature
226
+ )
227
+
228
+ finger_row = search_column.row(align=True)
229
+ draw_bone_prop_search(
230
+ finger_row, HumanBoneSpecifications.LEFT_RING_PROXIMAL, armature
231
+ )
232
+ draw_bone_prop_search(
233
+ finger_row, HumanBoneSpecifications.LEFT_RING_INTERMEDIATE, armature
234
+ )
235
+ draw_bone_prop_search(
236
+ finger_row, HumanBoneSpecifications.LEFT_RING_DISTAL, armature
237
+ )
238
+
239
+ finger_row = search_column.row(align=True)
240
+ draw_bone_prop_search(
241
+ finger_row, HumanBoneSpecifications.LEFT_LITTLE_PROXIMAL, armature
242
+ )
243
+ draw_bone_prop_search(
244
+ finger_row, HumanBoneSpecifications.LEFT_LITTLE_INTERMEDIATE, armature
245
+ )
246
+ draw_bone_prop_search(
247
+ finger_row, HumanBoneSpecifications.LEFT_LITTLE_DISTAL, armature
248
+ )
249
+
250
+ finger_row = search_column.row(align=True)
251
+ draw_bone_prop_search(
252
+ finger_row, HumanBoneSpecifications.RIGHT_THUMB_METACARPAL, armature
253
+ )
254
+ draw_bone_prop_search(
255
+ finger_row, HumanBoneSpecifications.RIGHT_THUMB_PROXIMAL, armature
256
+ )
257
+ draw_bone_prop_search(
258
+ finger_row, HumanBoneSpecifications.RIGHT_THUMB_DISTAL, armature
259
+ )
260
+
261
+ finger_row = search_column.row(align=True)
262
+ draw_bone_prop_search(
263
+ finger_row, HumanBoneSpecifications.RIGHT_INDEX_PROXIMAL, armature
264
+ )
265
+ draw_bone_prop_search(
266
+ finger_row, HumanBoneSpecifications.RIGHT_INDEX_INTERMEDIATE, armature
267
+ )
268
+ draw_bone_prop_search(
269
+ finger_row, HumanBoneSpecifications.RIGHT_INDEX_DISTAL, armature
270
+ )
271
+
272
+ finger_row = search_column.row(align=True)
273
+ draw_bone_prop_search(
274
+ finger_row, HumanBoneSpecifications.RIGHT_MIDDLE_PROXIMAL, armature
275
+ )
276
+ draw_bone_prop_search(
277
+ finger_row, HumanBoneSpecifications.RIGHT_MIDDLE_INTERMEDIATE, armature
278
+ )
279
+ draw_bone_prop_search(
280
+ finger_row, HumanBoneSpecifications.RIGHT_MIDDLE_DISTAL, armature
281
+ )
282
+
283
+ finger_row = search_column.row(align=True)
284
+ draw_bone_prop_search(
285
+ finger_row, HumanBoneSpecifications.RIGHT_RING_PROXIMAL, armature
286
+ )
287
+ draw_bone_prop_search(
288
+ finger_row, HumanBoneSpecifications.RIGHT_RING_INTERMEDIATE, armature
289
+ )
290
+ draw_bone_prop_search(
291
+ finger_row, HumanBoneSpecifications.RIGHT_RING_DISTAL, armature
292
+ )
293
+
294
+ finger_row = search_column.row(align=True)
295
+ draw_bone_prop_search(
296
+ finger_row, HumanBoneSpecifications.RIGHT_LITTLE_PROXIMAL, armature
297
+ )
298
+ draw_bone_prop_search(
299
+ finger_row, HumanBoneSpecifications.RIGHT_LITTLE_INTERMEDIATE, armature
300
+ )
301
+ draw_bone_prop_search(
302
+ finger_row, HumanBoneSpecifications.RIGHT_LITTLE_DISTAL, armature
303
+ )
304
+
305
+
306
+ def _draw_vrm1_humanoid_layout(
307
+ context: Context,
308
+ armature: Object,
309
+ layout: UILayout,
310
+ humanoid: Vrm1HumanoidPropertyGroup,
311
+ ) -> None:
312
+ if defer_migrate(armature.name, heavy_migration=True):
313
+ data = armature.data
314
+ if not isinstance(data, Armature):
315
+ return
316
+ Vrm1HumanBonesPropertyGroup.update_all_bone_name_candidates(context, data.name)
317
+
318
+ data = armature.data
319
+ if not isinstance(data, Armature):
320
+ return
321
+ human_bones = humanoid.human_bones
322
+
323
+ armature_box = layout
324
+
325
+ if not human_bones.allow_non_humanoid_rig:
326
+ t_pose_box = armature_box.box()
327
+ column = t_pose_box.row().column()
328
+ column.label(text="VRM T-Pose", icon="OUTLINER_OB_ARMATURE")
329
+ row = column.split(factor=0.8, align=True)
330
+ row.prop(humanoid, "pose")
331
+ apply_row = row.row(align=True)
332
+ apply_row.enabled = humanoid.pose != humanoid.POSE_CURRENT_POSE.identifier and (
333
+ humanoid.pose != humanoid.POSE_CUSTOM_POSE.identifier
334
+ or humanoid.pose_library is not None
335
+ )
336
+ layout_operator(
337
+ apply_row, ops.VRM_OT_apply_humanoid_t_pose
338
+ ).armature_object_name = armature.name
339
+ if humanoid.pose == humanoid.POSE_CUSTOM_POSE.identifier:
340
+ label = "Pose Library" if bpy.app.version < (3, 0) else "Pose Asset"
341
+ column.prop_search(
342
+ humanoid,
343
+ "pose_library",
344
+ context.blend_data,
345
+ "actions",
346
+ text=label,
347
+ translate=False,
348
+ )
349
+ pose_library = humanoid.pose_library
350
+ if pose_library and pose_library.pose_markers:
351
+ column.prop_search(
352
+ humanoid,
353
+ "pose_marker_name",
354
+ pose_library,
355
+ "pose_markers",
356
+ text="Pose",
357
+ translate=False,
358
+ )
359
+
360
+ bone_operator_column = layout.column()
361
+ layout_operator(
362
+ bone_operator_column,
363
+ vrm1_ops.VRM_OT_assign_vrm1_humanoid_human_bones_automatically,
364
+ icon="ARMATURE_DATA",
365
+ ).armature_object_name = armature.name
366
+
367
+ if ops.VRM_OT_simplify_vroid_bones.vroid_bones_exist(data):
368
+ simplify_vroid_bones_op = layout_operator(
369
+ armature_box,
370
+ ops.VRM_OT_simplify_vroid_bones,
371
+ text=pgettext(ops.VRM_OT_simplify_vroid_bones.bl_label),
372
+ icon="GREASEPENCIL",
373
+ )
374
+ simplify_vroid_bones_op.armature_object_name = armature.name
375
+
376
+ if not human_bones.allow_non_humanoid_rig:
377
+ layout.prop(human_bones, "filter_by_human_bone_hierarchy")
378
+ draw_vrm1_humanoid_required_bones_layout(armature, armature_box.box())
379
+ draw_vrm1_humanoid_optional_bones_layout(armature, armature_box.box())
380
+
381
+ layout.prop(human_bones, "allow_non_humanoid_rig")
382
+ if human_bones.allow_non_humanoid_rig:
383
+ non_humanoid_warnings_box = layout.box()
384
+ non_humanoid_warnings_column = non_humanoid_warnings_box.column(align=True)
385
+ text = pgettext(
386
+ "VRMs exported as Non-Humanoid\n"
387
+ + "Rigs can not have animations applied\n"
388
+ + "for humanoid avatars."
389
+ )
390
+ for index, message in enumerate(text.splitlines()):
391
+ non_humanoid_warnings_column.label(
392
+ text=message,
393
+ translate=False,
394
+ icon="ERROR" if index == 0 else "NONE",
395
+ )
396
+
397
+
398
+ class VRM_PT_vrm1_humanoid_armature_object_property(Panel):
399
+ bl_idname = "VRM_PT_vrm1_humanoid_armature_object_property"
400
+ bl_label = "Humanoid"
401
+ bl_translation_context = "VRM"
402
+ bl_space_type = "PROPERTIES"
403
+ bl_region_type = "WINDOW"
404
+ bl_context = "object"
405
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
406
+ bl_parent_id = VRM_PT_vrm_armature_object_property.bl_idname
407
+
408
+ @classmethod
409
+ def poll(cls, context: Context) -> bool:
410
+ return active_object_is_vrm1_armature(context)
411
+
412
+ def draw_header(self, _context: Context) -> None:
413
+ self.layout.label(icon="ARMATURE_DATA")
414
+
415
+ def draw(self, context: Context) -> None:
416
+ active_object = context.active_object
417
+ if not active_object:
418
+ return
419
+ if active_object.type != "ARMATURE":
420
+ return
421
+ armature_data = active_object.data
422
+ if not isinstance(armature_data, Armature):
423
+ return
424
+ _draw_vrm1_humanoid_layout(
425
+ context,
426
+ active_object,
427
+ self.layout,
428
+ get_armature_extension(armature_data).vrm1.humanoid,
429
+ )
430
+
431
+
432
+ class VRM_PT_vrm1_humanoid_ui(Panel):
433
+ bl_idname = "VRM_PT_vrm1_humanoid_ui"
434
+ bl_label = "Humanoid"
435
+ bl_translation_context = "VRM"
436
+ bl_space_type = "VIEW_3D"
437
+ bl_region_type = "UI"
438
+ bl_category = "VRM"
439
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
440
+
441
+ @classmethod
442
+ def poll(cls, context: Context) -> bool:
443
+ return search.current_armature_is_vrm1(context)
444
+
445
+ def draw_header(self, _context: Context) -> None:
446
+ self.layout.label(icon="ARMATURE_DATA")
447
+
448
+ def draw(self, context: Context) -> None:
449
+ armature = search.current_armature(context)
450
+ if not armature:
451
+ return
452
+ armature_data = armature.data
453
+ if not isinstance(armature_data, Armature):
454
+ return
455
+ _draw_vrm1_humanoid_layout(
456
+ context,
457
+ armature,
458
+ self.layout,
459
+ get_armature_extension(armature_data).vrm1.humanoid,
460
+ )
461
+
462
+
463
+ def _draw_vrm1_first_person_layout(
464
+ armature: Object,
465
+ _context: Context,
466
+ layout: UILayout,
467
+ first_person: Vrm1FirstPersonPropertyGroup,
468
+ ) -> None:
469
+ defer_migrate(armature.name, heavy_migration=False)
470
+ column = layout.column()
471
+ column.label(text="Mesh Annotations", icon="FULLSCREEN_EXIT")
472
+
473
+ (
474
+ mesh_annotation_collection_ops,
475
+ mesh_annotation_collection_item_ops,
476
+ mesh_annotation_index,
477
+ _,
478
+ _,
479
+ ) = draw_template_list(
480
+ column,
481
+ VRM_UL_vrm1_first_person_mesh_annotation,
482
+ first_person,
483
+ "mesh_annotations",
484
+ "active_mesh_annotation_index",
485
+ vrm1_ops.VRM_OT_add_vrm1_first_person_mesh_annotation,
486
+ vrm1_ops.VRM_OT_remove_vrm1_first_person_mesh_annotation,
487
+ vrm1_ops.VRM_OT_move_up_vrm1_first_person_mesh_annotation,
488
+ vrm1_ops.VRM_OT_move_down_vrm1_first_person_mesh_annotation,
489
+ )
490
+
491
+ for mesh_annotation_collection_op in mesh_annotation_collection_ops:
492
+ mesh_annotation_collection_op.armature_object_name = armature.name
493
+
494
+ for mesh_annotation_collection_item_op in mesh_annotation_collection_item_ops:
495
+ mesh_annotation_collection_item_op.mesh_annotation_index = mesh_annotation_index
496
+
497
+
498
+ class VRM_PT_vrm1_first_person_armature_object_property(Panel):
499
+ bl_idname = "VRM_PT_vrm1_first_person_armature_object_property"
500
+ bl_label = "First Person"
501
+ bl_translation_context = "VRM"
502
+ bl_space_type = "PROPERTIES"
503
+ bl_region_type = "WINDOW"
504
+ bl_context = "object"
505
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
506
+ bl_parent_id = VRM_PT_vrm_armature_object_property.bl_idname
507
+
508
+ @classmethod
509
+ def poll(cls, context: Context) -> bool:
510
+ return active_object_is_vrm1_armature(context)
511
+
512
+ def draw_header(self, _context: Context) -> None:
513
+ self.layout.label(icon="HIDE_OFF")
514
+
515
+ def draw(self, context: Context) -> None:
516
+ active_object = context.active_object
517
+ if not active_object:
518
+ return
519
+ if active_object.type != "ARMATURE":
520
+ return
521
+ armature_data = active_object.data
522
+ if not isinstance(armature_data, Armature):
523
+ return
524
+ _draw_vrm1_first_person_layout(
525
+ active_object,
526
+ context,
527
+ self.layout,
528
+ get_armature_extension(armature_data).vrm1.first_person,
529
+ )
530
+
531
+
532
+ class VRM_PT_vrm1_first_person_ui(Panel):
533
+ bl_idname = "VRM_PT_vrm1_first_person_ui"
534
+ bl_label = "First Person"
535
+ bl_translation_context = "VRM"
536
+ bl_space_type = "VIEW_3D"
537
+ bl_region_type = "UI"
538
+ bl_category = "VRM"
539
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
540
+
541
+ @classmethod
542
+ def poll(cls, context: Context) -> bool:
543
+ return search.current_armature_is_vrm1(context)
544
+
545
+ def draw_header(self, _context: Context) -> None:
546
+ self.layout.label(icon="USER")
547
+
548
+ def draw(self, context: Context) -> None:
549
+ armature = search.current_armature(context)
550
+ if not armature:
551
+ return
552
+ armature_data = armature.data
553
+ if not isinstance(armature_data, Armature):
554
+ return
555
+ _draw_vrm1_first_person_layout(
556
+ armature,
557
+ context,
558
+ self.layout,
559
+ get_armature_extension(armature_data).vrm1.first_person,
560
+ )
561
+
562
+
563
+ def _draw_vrm1_look_at_layout(
564
+ armature: Object,
565
+ _context: Context,
566
+ layout: UILayout,
567
+ look_at: Vrm1LookAtPropertyGroup,
568
+ ) -> None:
569
+ defer_migrate(armature.name, heavy_migration=False)
570
+
571
+ layout.prop(look_at, "enable_preview")
572
+
573
+ label_input_split = layout.split(factor=0.4)
574
+ label_column = label_input_split.column()
575
+ label_column.label(text="Preview Target:")
576
+ label_column.label(text="Type:")
577
+ input_column = label_input_split.column()
578
+ input_column.prop(look_at, "preview_target_bpy_object", text="", translate=False)
579
+ input_column.prop(look_at, "type", text="", translate=False)
580
+
581
+ offset_from_head_bone_column = layout.column()
582
+ offset_from_head_bone_column.label(text="Offset from Head Bone:")
583
+ offset_from_head_bone_column.row().prop(
584
+ look_at, "offset_from_head_bone", icon="BONE_DATA", text="", translate=False
585
+ )
586
+
587
+ column = layout.box().column(align=True)
588
+ column.label(text="Range Map Horizontal Inner", icon="FULLSCREEN_EXIT")
589
+ column.prop(look_at.range_map_horizontal_inner, "input_max_value")
590
+ column.prop(look_at.range_map_horizontal_inner, "output_scale")
591
+ column = layout.box().column(align=True)
592
+ column.label(text="Range Map Horizontal Outer", icon="FULLSCREEN_ENTER")
593
+ column.prop(look_at.range_map_horizontal_outer, "input_max_value")
594
+ column.prop(look_at.range_map_horizontal_outer, "output_scale")
595
+ column = layout.box().column(align=True)
596
+ column.label(text="Range Map Vertical Up", icon="TRIA_UP")
597
+ column.prop(look_at.range_map_vertical_up, "input_max_value")
598
+ column.prop(look_at.range_map_vertical_up, "output_scale")
599
+ column = layout.box().column(align=True)
600
+ column.label(text="Range Map Vertical Down", icon="TRIA_DOWN")
601
+ column.prop(look_at.range_map_vertical_down, "input_max_value")
602
+ column.prop(look_at.range_map_vertical_down, "output_scale")
603
+
604
+
605
+ class VRM_PT_vrm1_look_at_armature_object_property(Panel):
606
+ bl_idname = "VRM_PT_vrm1_look_at_armature_object_property"
607
+ bl_label = "Look At"
608
+ bl_translation_context = "VRM"
609
+ bl_space_type = "PROPERTIES"
610
+ bl_region_type = "WINDOW"
611
+ bl_context = "object"
612
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
613
+ bl_parent_id = VRM_PT_vrm_armature_object_property.bl_idname
614
+
615
+ @classmethod
616
+ def poll(cls, context: Context) -> bool:
617
+ return active_object_is_vrm1_armature(context)
618
+
619
+ def draw_header(self, _context: Context) -> None:
620
+ self.layout.label(icon="HIDE_OFF")
621
+
622
+ def draw(self, context: Context) -> None:
623
+ active_object = context.active_object
624
+ if not active_object:
625
+ return
626
+ if active_object.type != "ARMATURE":
627
+ return
628
+ armature_data = active_object.data
629
+ if not isinstance(armature_data, Armature):
630
+ return
631
+ _draw_vrm1_look_at_layout(
632
+ active_object,
633
+ context,
634
+ self.layout,
635
+ get_armature_extension(armature_data).vrm1.look_at,
636
+ )
637
+
638
+
639
+ class VRM_PT_vrm1_look_at_ui(Panel):
640
+ bl_idname = "VRM_PT_vrm1_look_at_ui"
641
+ bl_label = "Look At"
642
+ bl_translation_context = "VRM"
643
+ bl_space_type = "VIEW_3D"
644
+ bl_region_type = "UI"
645
+ bl_category = "VRM"
646
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
647
+
648
+ @classmethod
649
+ def poll(cls, context: Context) -> bool:
650
+ return search.current_armature_is_vrm1(context)
651
+
652
+ def draw_header(self, _context: Context) -> None:
653
+ self.layout.label(icon="HIDE_OFF")
654
+
655
+ def draw(self, context: Context) -> None:
656
+ armature = search.current_armature(context)
657
+ if not armature:
658
+ return
659
+ armature_data = armature.data
660
+ if not isinstance(armature_data, Armature):
661
+ return
662
+ _draw_vrm1_look_at_layout(
663
+ armature,
664
+ context,
665
+ self.layout,
666
+ get_armature_extension(armature_data).vrm1.look_at,
667
+ )
668
+
669
+
670
+ def _draw_vrm1_expressions_morph_target_bind_layout(
671
+ context: Context,
672
+ layout: UILayout,
673
+ bind: Vrm1MorphTargetBindPropertyGroup,
674
+ ) -> None:
675
+ blend_data = context.blend_data
676
+
677
+ bind_column = layout.column()
678
+
679
+ bind_column.prop(
680
+ bind.node,
681
+ "bpy_object",
682
+ text="Mesh",
683
+ icon="OUTLINER_OB_MESH",
684
+ )
685
+ mesh_object = blend_data.objects.get(bind.node.mesh_object_name)
686
+ if not mesh_object:
687
+ return
688
+ mesh = mesh_object.data
689
+ if not isinstance(mesh, Mesh):
690
+ return
691
+ shape_keys = mesh.shape_keys
692
+ if not shape_keys:
693
+ return
694
+ key_blocks = shape_keys.key_blocks
695
+ if not key_blocks:
696
+ return
697
+
698
+ bind_column.prop_search(
699
+ bind,
700
+ "index",
701
+ shape_keys,
702
+ "key_blocks",
703
+ text="Shape key",
704
+ )
705
+ bind_column.prop(bind, "weight", slider=True)
706
+
707
+
708
+ def _draw_vrm1_expressions_material_color_bind_layout(
709
+ context: Context,
710
+ layout: UILayout,
711
+ bind: Vrm1MaterialColorBindPropertyGroup,
712
+ ) -> None:
713
+ blend_data = context.blend_data
714
+
715
+ bind_column = layout.column()
716
+ bind_column.prop_search(bind, "material", blend_data, "materials")
717
+ bind_column.prop(bind, "type")
718
+ target_value_split = bind_column.split(factor=0.5)
719
+ target_value_split.label(text="Target Value:")
720
+ if bind.type == "color":
721
+ target_value_split.prop(bind, "target_value", text="", translate=False)
722
+ else:
723
+ target_value_split.prop(bind, "target_value_as_rgb", text="", translate=False)
724
+
725
+
726
+ def _draw_vrm1_expressions_texture_transform_bind_layout(
727
+ context: Context,
728
+ layout: UILayout,
729
+ bind: Vrm1TextureTransformBindPropertyGroup,
730
+ ) -> None:
731
+ if not bind.show_experimental_preview_feature:
732
+ blend_data = context.blend_data
733
+ bind_column = layout.column()
734
+ bind_column.prop_search(bind, "material", blend_data, "materials")
735
+ bind_column.prop(bind, "scale")
736
+ bind_column.prop(bind, "offset")
737
+ if bpy.app.version < (4, 2):
738
+ return
739
+ bind_column.separator()
740
+ bind_column.prop(bind, "show_experimental_preview_feature")
741
+ return
742
+
743
+ bind_column = layout.column()
744
+ bind_column.prop(bind, "show_experimental_preview_feature")
745
+
746
+ # Find the armature object
747
+ armature = search.current_armature(context)
748
+ if not armature:
749
+ layout.label(text="No VRM Armature found in the scene", icon="ERROR")
750
+ return
751
+ armature_data = armature.data
752
+ if not isinstance(armature_data, Armature):
753
+ layout.label(text="Invalid armature data", icon="ERROR")
754
+ return
755
+
756
+ try:
757
+ extension = get_armature_extension(armature_data)
758
+ vrm1 = extension.vrm1
759
+ expressions = vrm1.expressions
760
+
761
+ all_expression_names = list(expressions.all_name_to_expression_dict().keys())
762
+ if (
763
+ 0
764
+ <= expressions.active_expression_ui_list_element_index
765
+ < len(all_expression_names)
766
+ ):
767
+ expression_name = all_expression_names[
768
+ expressions.active_expression_ui_list_element_index
769
+ ]
770
+ else:
771
+ expression_name = ""
772
+ except TypeError:
773
+ layout.label(text="Invalid VRM extension", icon="ERROR")
774
+ return
775
+
776
+ # Add refresh preview button
777
+ refresh_row = bind_column.row()
778
+ refresh_op = layout_operator(
779
+ refresh_row,
780
+ vrm1_ops.VRM_OT_refresh_vrm1_expression_texture_transform_bind_preview,
781
+ text="Refresh Preview",
782
+ icon="FILE_REFRESH",
783
+ )
784
+ refresh_op.armature_object_name = armature.name
785
+ refresh_op.expression_name = expression_name
786
+
787
+ bind_column.separator()
788
+
789
+ bind_column.prop_search(bind, "material", context.blend_data, "materials")
790
+ # Only show scale, and offset properties if there's a valid bind
791
+ if bind and bind.material:
792
+ bind_column.prop(bind, "scale")
793
+ bind_column.prop(bind, "offset")
794
+ else:
795
+ bind_column.label(text="No texture transform bind for this expression")
796
+
797
+
798
+ def _draw_vrm1_expressions_layout(
799
+ armature: Object,
800
+ context: Context,
801
+ layout: UILayout,
802
+ expressions: Vrm1ExpressionsPropertyGroup,
803
+ ) -> None:
804
+ defer_migrate(armature.name, heavy_migration=True)
805
+
806
+ expression_preset_and_expressions = (
807
+ expressions.preset.expression_preset_and_expressions()
808
+ )
809
+
810
+ (
811
+ expression_collection_ops,
812
+ expression_collection_item_ops,
813
+ expression_ui_list_element_index,
814
+ _,
815
+ _,
816
+ ) = draw_template_list(
817
+ layout,
818
+ VRM_UL_vrm1_expression,
819
+ expressions,
820
+ "expression_ui_list_elements",
821
+ "active_expression_ui_list_element_index",
822
+ vrm1_ops.VRM_OT_add_vrm1_expressions_custom_expression,
823
+ vrm1_ops.VRM_OT_remove_vrm1_expressions_custom_expression,
824
+ vrm1_ops.VRM_OT_move_up_vrm1_expressions_custom_expression,
825
+ vrm1_ops.VRM_OT_move_down_vrm1_expressions_custom_expression,
826
+ can_remove=lambda active_collection_index: (
827
+ active_collection_index >= len(expression_preset_and_expressions)
828
+ ),
829
+ can_move=lambda active_collection_index: (
830
+ len(expressions.custom) >= 2
831
+ and active_collection_index >= len(expression_preset_and_expressions)
832
+ ),
833
+ menu_and_context_pointer_set_callback=(
834
+ VRM_MT_vrm1_expression,
835
+ VRM_MT_vrm1_expression.layout_context_pointer_set(armature),
836
+ ),
837
+ )
838
+
839
+ for expression_collection_op in expression_collection_ops:
840
+ expression_collection_op.armature_object_name = armature.name
841
+ expression_collection_op.custom_expression_name = "custom"
842
+
843
+ custom_index = expression_ui_list_element_index - len(
844
+ expression_preset_and_expressions
845
+ )
846
+
847
+ if 0 <= expression_ui_list_element_index < len(expression_preset_and_expressions):
848
+ expression_preset, expression = expression_preset_and_expressions[
849
+ expression_ui_list_element_index
850
+ ]
851
+ layout.label(
852
+ text=expression_preset.name, translate=False, icon=expression_preset.icon
853
+ )
854
+ expression_name = expression_preset.name
855
+ elif 0 <= custom_index < len(expressions.custom):
856
+ expression = expressions.custom[custom_index]
857
+
858
+ for expression_collection_item_op in expression_collection_item_ops:
859
+ expression_collection_item_op.custom_expression_name = (
860
+ expression.custom_name
861
+ )
862
+
863
+ layout.prop(expression, "custom_name")
864
+ expression_name = expression.custom_name
865
+ else:
866
+ return
867
+
868
+ column = layout.column()
869
+ column.prop(expression, "preview", icon="PLAY", text="Preview")
870
+ column.prop(expression, "is_binary", icon="IPO_CONSTANT")
871
+ column.prop(expression, "override_blink")
872
+ column.prop(expression, "override_look_at")
873
+ column.prop(expression, "override_mouth")
874
+ column.separator(factor=0.5)
875
+
876
+ morph_target_binds_box = column.box()
877
+ morph_target_binds_box.label(text="Morph Target Binds", icon="MESH_DATA")
878
+
879
+ (
880
+ morph_target_bind_collection_ops,
881
+ morph_target_bind_collection_item_ops,
882
+ morph_target_bind_index,
883
+ morph_target_bind,
884
+ _,
885
+ ) = draw_template_list(
886
+ morph_target_binds_box,
887
+ VRM_UL_vrm1_morph_target_bind,
888
+ expression,
889
+ "morph_target_binds",
890
+ "active_morph_target_bind_index",
891
+ vrm1_ops.VRM_OT_add_vrm1_expression_morph_target_bind,
892
+ vrm1_ops.VRM_OT_remove_vrm1_expression_morph_target_bind,
893
+ vrm1_ops.VRM_OT_move_up_vrm1_expression_morph_target_bind,
894
+ vrm1_ops.VRM_OT_move_down_vrm1_expression_morph_target_bind,
895
+ )
896
+
897
+ for morph_target_bind_collection_op in morph_target_bind_collection_ops:
898
+ morph_target_bind_collection_op.armature_object_name = armature.name
899
+ morph_target_bind_collection_op.expression_name = expression_name
900
+
901
+ for morph_target_bind_collection_item_op in morph_target_bind_collection_item_ops:
902
+ morph_target_bind_collection_item_op.bind_index = morph_target_bind_index
903
+
904
+ if isinstance(morph_target_bind, Vrm1MorphTargetBindPropertyGroup):
905
+ _draw_vrm1_expressions_morph_target_bind_layout(
906
+ context,
907
+ morph_target_binds_box,
908
+ morph_target_bind,
909
+ )
910
+
911
+ column.separator(factor=0.2)
912
+
913
+ material_color_binds_box = column.box()
914
+ material_color_binds_box.label(text="Material Color Binds", icon="MATERIAL")
915
+
916
+ (
917
+ material_color_bind_collection_ops,
918
+ material_color_bind_collection_item_ops,
919
+ material_color_bind_index,
920
+ material_color_bind,
921
+ _,
922
+ ) = draw_template_list(
923
+ material_color_binds_box,
924
+ VRM_UL_vrm1_material_color_bind,
925
+ expression,
926
+ "material_color_binds",
927
+ "active_material_color_bind_index",
928
+ vrm1_ops.VRM_OT_add_vrm1_expression_material_color_bind,
929
+ vrm1_ops.VRM_OT_remove_vrm1_expression_material_color_bind,
930
+ vrm1_ops.VRM_OT_move_up_vrm1_expression_material_color_bind,
931
+ vrm1_ops.VRM_OT_move_down_vrm1_expression_material_color_bind,
932
+ )
933
+
934
+ for material_color_bind_collection_op in material_color_bind_collection_ops:
935
+ material_color_bind_collection_op.armature_object_name = armature.name
936
+ material_color_bind_collection_op.expression_name = expression_name
937
+
938
+ for (
939
+ material_color_bind_collection_item_op
940
+ ) in material_color_bind_collection_item_ops:
941
+ material_color_bind_collection_item_op.bind_index = material_color_bind_index
942
+
943
+ if isinstance(material_color_bind, Vrm1MaterialColorBindPropertyGroup):
944
+ _draw_vrm1_expressions_material_color_bind_layout(
945
+ context,
946
+ material_color_binds_box,
947
+ material_color_bind,
948
+ )
949
+ column.separator(factor=0.2)
950
+
951
+ texture_transform_binds_box = column.box()
952
+ texture_transform_binds_box.label(text="Texture Transform Binds", icon="MATERIAL")
953
+
954
+ (
955
+ texture_transform_bind_collection_ops,
956
+ texture_transform_bind_collection_item_ops,
957
+ texture_transform_bind_index,
958
+ texture_transform_bind,
959
+ _,
960
+ ) = draw_template_list(
961
+ texture_transform_binds_box,
962
+ VRM_UL_vrm1_texture_transform_bind,
963
+ expression,
964
+ "texture_transform_binds",
965
+ "active_texture_transform_bind_index",
966
+ vrm1_ops.VRM_OT_add_vrm1_expression_texture_transform_bind,
967
+ vrm1_ops.VRM_OT_remove_vrm1_expression_texture_transform_bind,
968
+ vrm1_ops.VRM_OT_move_up_vrm1_expression_texture_transform_bind,
969
+ vrm1_ops.VRM_OT_move_down_vrm1_expression_texture_transform_bind,
970
+ )
971
+
972
+ for texture_transform_bind_collection_op in texture_transform_bind_collection_ops:
973
+ texture_transform_bind_collection_op.armature_object_name = armature.name
974
+ texture_transform_bind_collection_op.expression_name = expression_name
975
+
976
+ for (
977
+ texture_transform_bind_collection_item_op
978
+ ) in texture_transform_bind_collection_item_ops:
979
+ texture_transform_bind_collection_item_op.bind_index = (
980
+ texture_transform_bind_index
981
+ )
982
+
983
+ if isinstance(texture_transform_bind, Vrm1TextureTransformBindPropertyGroup):
984
+ _draw_vrm1_expressions_texture_transform_bind_layout(
985
+ context,
986
+ texture_transform_binds_box,
987
+ texture_transform_bind,
988
+ )
989
+
990
+
991
+ class VRM_PT_vrm1_expressions_armature_object_property(Panel):
992
+ bl_idname = "VRM_PT_vrm1_expressions_armature_object_property"
993
+ bl_label = "Expressions"
994
+ bl_translation_context = "VRM"
995
+ bl_space_type = "PROPERTIES"
996
+ bl_region_type = "WINDOW"
997
+ bl_context = "object"
998
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
999
+ bl_parent_id = VRM_PT_vrm_armature_object_property.bl_idname
1000
+
1001
+ @classmethod
1002
+ def poll(cls, context: Context) -> bool:
1003
+ return active_object_is_vrm1_armature(context)
1004
+
1005
+ def draw_header(self, _context: Context) -> None:
1006
+ self.layout.label(icon="SHAPEKEY_DATA")
1007
+
1008
+ def draw(self, context: Context) -> None:
1009
+ active_object = context.active_object
1010
+ if not active_object:
1011
+ return
1012
+ if active_object.type != "ARMATURE":
1013
+ return
1014
+ armature_data = active_object.data
1015
+ if not isinstance(armature_data, Armature):
1016
+ return
1017
+ _draw_vrm1_expressions_layout(
1018
+ active_object,
1019
+ context,
1020
+ self.layout,
1021
+ get_armature_extension(armature_data).vrm1.expressions,
1022
+ )
1023
+
1024
+
1025
+ class VRM_PT_vrm1_expressions_ui(Panel):
1026
+ bl_idname = "VRM_PT_vrm1_expressions_ui"
1027
+ bl_label = "Expressions"
1028
+ bl_translation_context = "VRM"
1029
+ bl_space_type = "VIEW_3D"
1030
+ bl_region_type = "UI"
1031
+ bl_category = "VRM"
1032
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
1033
+
1034
+ @classmethod
1035
+ def poll(cls, context: Context) -> bool:
1036
+ return search.current_armature_is_vrm1(context)
1037
+
1038
+ def draw_header(self, _context: Context) -> None:
1039
+ self.layout.label(icon="SHAPEKEY_DATA")
1040
+
1041
+ def draw(self, context: Context) -> None:
1042
+ armature = search.current_armature(context)
1043
+ if not armature:
1044
+ return
1045
+ armature_data = armature.data
1046
+ if not isinstance(armature_data, Armature):
1047
+ return
1048
+ _draw_vrm1_expressions_layout(
1049
+ armature,
1050
+ context,
1051
+ self.layout,
1052
+ get_armature_extension(armature_data).vrm1.expressions,
1053
+ )
1054
+
1055
+
1056
+ def _draw_vrm1_meta_layout(
1057
+ armature: Object,
1058
+ _context: Context,
1059
+ layout: UILayout,
1060
+ meta: Vrm1MetaPropertyGroup,
1061
+ ) -> None:
1062
+ defer_migrate(armature.name, heavy_migration=False)
1063
+
1064
+ thumbnail_column = layout.column()
1065
+ thumbnail_column.label(text="Thumbnail:")
1066
+ thumbnail_column.template_ID_preview(meta, "thumbnail_image")
1067
+
1068
+ layout.prop(meta, "vrm_name", icon="FILE_BLEND")
1069
+ layout.prop(meta, "version", icon="LINENUMBERS_ON")
1070
+
1071
+ authors_column = layout.column()
1072
+ authors_column.label(text="Authors:")
1073
+
1074
+ (
1075
+ author_collection_ops,
1076
+ author_collection_item_ops,
1077
+ author_index,
1078
+ _,
1079
+ _,
1080
+ ) = draw_template_list(
1081
+ authors_column,
1082
+ VRM_UL_vrm1_meta_author,
1083
+ meta,
1084
+ "authors",
1085
+ "active_author_index",
1086
+ vrm1_ops.VRM_OT_add_vrm1_meta_author,
1087
+ vrm1_ops.VRM_OT_remove_vrm1_meta_author,
1088
+ vrm1_ops.VRM_OT_move_up_vrm1_meta_author,
1089
+ vrm1_ops.VRM_OT_move_down_vrm1_meta_author,
1090
+ can_remove=lambda _: len(meta.authors) >= 2,
1091
+ compact=True,
1092
+ )
1093
+
1094
+ for author_collection_op in author_collection_ops:
1095
+ author_collection_op.armature_object_name = armature.name
1096
+
1097
+ for author_collection_item_op in author_collection_item_ops:
1098
+ author_collection_item_op.author_index = author_index
1099
+
1100
+ layout.prop(meta, "copyright_information")
1101
+ layout.prop(meta, "contact_information")
1102
+
1103
+ references_column = layout.column()
1104
+ references_column.label(text="References:")
1105
+
1106
+ (
1107
+ reference_collection_ops,
1108
+ reference_collection_item_ops,
1109
+ reference_index,
1110
+ _,
1111
+ _,
1112
+ ) = draw_template_list(
1113
+ references_column,
1114
+ VRM_UL_vrm1_meta_reference,
1115
+ meta,
1116
+ "references",
1117
+ "active_reference_index",
1118
+ vrm1_ops.VRM_OT_add_vrm1_meta_reference,
1119
+ vrm1_ops.VRM_OT_remove_vrm1_meta_reference,
1120
+ vrm1_ops.VRM_OT_move_up_vrm1_meta_reference,
1121
+ vrm1_ops.VRM_OT_move_down_vrm1_meta_reference,
1122
+ compact=True,
1123
+ )
1124
+
1125
+ for reference_collection_op in reference_collection_ops:
1126
+ reference_collection_op.armature_object_name = armature.name
1127
+
1128
+ for reference_collection_item_op in reference_collection_item_ops:
1129
+ reference_collection_item_op.reference_index = reference_index
1130
+
1131
+ layout.prop(meta, "third_party_licenses")
1132
+ # layout.prop(meta, "license_url", icon="URL")
1133
+ layout.prop(meta, "avatar_permission", icon="MATCLOTH")
1134
+ layout.prop(meta, "commercial_usage", icon="SOLO_OFF")
1135
+ layout.prop(meta, "credit_notation")
1136
+ layout.prop(meta, "modification")
1137
+ layout.prop(meta, "allow_excessively_violent_usage")
1138
+ layout.prop(meta, "allow_excessively_sexual_usage")
1139
+ layout.prop(meta, "allow_political_or_religious_usage")
1140
+ layout.prop(meta, "allow_antisocial_or_hate_usage")
1141
+ layout.prop(meta, "allow_redistribution")
1142
+ layout.prop(meta, "other_license_url", icon="URL")
1143
+ draw_url_warning(layout, meta.other_license_url)
1144
+
1145
+
1146
+ class VRM_PT_vrm1_meta_armature_object_property(Panel):
1147
+ bl_idname = "VRM_PT_vrm1_meta_armature_object_property"
1148
+ bl_label = "Meta"
1149
+ bl_translation_context = "VRM"
1150
+ bl_space_type = "PROPERTIES"
1151
+ bl_region_type = "WINDOW"
1152
+ bl_context = "object"
1153
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
1154
+ bl_parent_id = VRM_PT_vrm_armature_object_property.bl_idname
1155
+
1156
+ @classmethod
1157
+ def poll(cls, context: Context) -> bool:
1158
+ return active_object_is_vrm1_armature(context)
1159
+
1160
+ def draw_header(self, _context: Context) -> None:
1161
+ self.layout.label(icon="FILE_BLEND")
1162
+
1163
+ def draw(self, context: Context) -> None:
1164
+ active_object = context.active_object
1165
+ if not active_object:
1166
+ return
1167
+ if active_object.type != "ARMATURE":
1168
+ return
1169
+ armature_data = active_object.data
1170
+ if not isinstance(armature_data, Armature):
1171
+ return
1172
+ ext = get_armature_extension(armature_data)
1173
+ _draw_vrm1_meta_layout(active_object, context, self.layout, ext.vrm1.meta)
1174
+
1175
+
1176
+ class VRM_PT_vrm1_meta_ui(Panel):
1177
+ bl_idname = "VRM_PT_vrm1_meta_ui"
1178
+ bl_label = "Meta"
1179
+ bl_translation_context = "VRM"
1180
+ bl_space_type = "VIEW_3D"
1181
+ bl_region_type = "UI"
1182
+ bl_category = "VRM"
1183
+ bl_options: ClassVar = {"DEFAULT_CLOSED"}
1184
+
1185
+ @classmethod
1186
+ def poll(cls, context: Context) -> bool:
1187
+ return search.current_armature_is_vrm1(context)
1188
+
1189
+ def draw_header(self, _context: Context) -> None:
1190
+ self.layout.label(icon="FILE_BLEND")
1191
+
1192
+ def draw(self, context: Context) -> None:
1193
+ armature = search.current_armature(context)
1194
+ if not armature:
1195
+ return
1196
+ armature_data = armature.data
1197
+ if not isinstance(armature_data, Armature):
1198
+ return
1199
+ _draw_vrm1_meta_layout(
1200
+ armature,
1201
+ context,
1202
+ self.layout,
1203
+ get_armature_extension(armature_data).vrm1.meta,
1204
+ )
1205
+
1206
+
1207
+ class VRM_PT_vrm1_bone_property(Panel):
1208
+ bl_idname = "VRM_PT_vrm1_bone_property"
1209
+ bl_label = "VRM"
1210
+ bl_space_type = "PROPERTIES"
1211
+ bl_region_type = "WINDOW"
1212
+ bl_context = "bone"
1213
+
1214
+ @classmethod
1215
+ def poll(cls, context: Context) -> bool:
1216
+ active_object = context.active_object
1217
+ if not active_object:
1218
+ return False
1219
+ if active_object.type != "ARMATURE":
1220
+ return False
1221
+ armature_data = active_object.data
1222
+ if not isinstance(armature_data, Armature):
1223
+ return False
1224
+ if not armature_data.bones.active:
1225
+ return False
1226
+ return search.current_armature_is_vrm1(context)
1227
+
1228
+ def draw(self, context: Context) -> None:
1229
+ active_object = context.active_object
1230
+ if not active_object:
1231
+ return
1232
+ if active_object.type != "ARMATURE":
1233
+ return
1234
+ armature_data = active_object.data
1235
+ if not isinstance(armature_data, Armature):
1236
+ return
1237
+ # context.active_bone is a EditBone
1238
+ bone = armature_data.bones.active
1239
+ if not bone:
1240
+ return
1241
+ ext = get_bone_extension(bone)
1242
+ layout = self.layout
1243
+ layout.prop(ext, "axis_translation")