@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 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
@@ -0,0 +1,168 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
2
+
3
+ from collections.abc import Mapping, Sequence
4
+ from typing import Final
5
+
6
+ from ..vrm1.expression_preset import (
7
+ ExpressionPreset,
8
+ ExpressionPresets,
9
+ )
10
+
11
+ ARKIT_SHAPE_KEYS: Final[tuple[str, ...]] = (
12
+ # https://developer.apple.com/documentation/arkit/arfaceanchor/blendshapelocation
13
+ "eyeBlinkLeft",
14
+ "eyeLookDownLeft",
15
+ "eyeLookInLeft",
16
+ "eyeLookOutLeft",
17
+ "eyeLookUpLeft",
18
+ "eyeSquintLeft",
19
+ "eyeWideLeft",
20
+ "eyeBlinkRight",
21
+ "eyeLookDownRight",
22
+ "eyeLookInRight",
23
+ "eyeLookOutRight",
24
+ "eyeLookUpRight",
25
+ "eyeSquintRight",
26
+ "eyeWideRight",
27
+ "jawForward",
28
+ "jawLeft",
29
+ "jawRight",
30
+ "jawOpen",
31
+ "mouthClose",
32
+ "mouthFunnel",
33
+ "mouthPucker",
34
+ "mouthLeft",
35
+ "mouthRight",
36
+ "mouthSmileLeft",
37
+ "mouthSmileRight",
38
+ "mouthFrownLeft",
39
+ "mouthFrownRight",
40
+ "mouthDimpleLeft",
41
+ "mouthDimpleRight",
42
+ "mouthStretchLeft",
43
+ "mouthStretchRight",
44
+ "mouthRollLower",
45
+ "mouthRollUpper",
46
+ "mouthShrugLower",
47
+ "mouthShrugUpper",
48
+ "mouthPressLeft",
49
+ "mouthPressRight",
50
+ "mouthLowerDownLeft",
51
+ "mouthLowerDownRight",
52
+ "mouthUpperUpLeft",
53
+ "mouthUpperUpRight",
54
+ "browDownLeft",
55
+ "browDownRight",
56
+ "browInnerUp",
57
+ "browOuterUpLeft",
58
+ "browOuterUpRight",
59
+ "cheekPuff",
60
+ "cheekSquintLeft",
61
+ "cheekSquintRight",
62
+ "noseSneerLeft",
63
+ "noseSneerRight",
64
+ "tongueOut",
65
+ )
66
+
67
+
68
+ VRM1_PRESET_TO_ARKIT_SHAPE_KEY_MAPPING: Final[
69
+ Mapping[ExpressionPreset, Sequence[Mapping[str, float]]]
70
+ ] = {
71
+ ExpressionPresets.HAPPY: [
72
+ {
73
+ "mouthSmileLeft": 0.5,
74
+ "mouthSmileRight": 0.5,
75
+ }
76
+ ],
77
+ ExpressionPresets.ANGRY: [
78
+ {
79
+ "mouthFrownLeft": 0.5,
80
+ "mouthFrownRight": 0.5,
81
+ }
82
+ ],
83
+ ExpressionPresets.SAD: [
84
+ {
85
+ "browDownLeft": 0.25,
86
+ "browDownRight": 0.25,
87
+ }
88
+ ],
89
+ ExpressionPresets.SURPRISED: [
90
+ {
91
+ "browInnerUp": 0.25,
92
+ "browOuterUpLeft": 0.25,
93
+ "browOuterUpRight": 0.25,
94
+ "jawOpen": 0.25,
95
+ }
96
+ ],
97
+ ExpressionPresets.AA: [
98
+ {
99
+ "jawOpen": 0.5,
100
+ }
101
+ ],
102
+ ExpressionPresets.IH: [
103
+ {
104
+ "jawOpen": 0.2,
105
+ "mouthStretchLeft": 0.2,
106
+ "mouthStretchRight": 0.2,
107
+ }
108
+ ],
109
+ ExpressionPresets.OU: [
110
+ {
111
+ "jawOpen": 0.2,
112
+ "mouthPucker": 0.2,
113
+ }
114
+ ],
115
+ ExpressionPresets.EE: [
116
+ {
117
+ "jawOpen": 0.3,
118
+ "mouthStretchLeft": 0.3,
119
+ "mouthStretchRight": 0.3,
120
+ }
121
+ ],
122
+ ExpressionPresets.OH: [
123
+ {
124
+ "jawOpen": 0.3,
125
+ "mouthPucker": 0.3,
126
+ }
127
+ ],
128
+ ExpressionPresets.BLINK: [
129
+ {
130
+ "eyeBlinkLeft": 1.0,
131
+ "eyeBlinkRight": 1.0,
132
+ }
133
+ ],
134
+ ExpressionPresets.BLINK_LEFT: [
135
+ {
136
+ "eyeBlinkLeft": 1.0,
137
+ }
138
+ ],
139
+ ExpressionPresets.BLINK_RIGHT: [
140
+ {
141
+ "eyeBlinkRight": 1.0,
142
+ }
143
+ ],
144
+ ExpressionPresets.LOOK_UP: [
145
+ {
146
+ "eyeLookUpLeft": 1.0,
147
+ "eyeLookUpRight": 1.0,
148
+ }
149
+ ],
150
+ ExpressionPresets.LOOK_DOWN: [
151
+ {
152
+ "eyeLookDownLeft": 1.0,
153
+ "eyeLookDownRight": 1.0,
154
+ }
155
+ ],
156
+ ExpressionPresets.LOOK_LEFT: [
157
+ {
158
+ "eyeLookOutLeft": 1.0,
159
+ "eyeLookInRight": 1.0,
160
+ }
161
+ ],
162
+ ExpressionPresets.LOOK_RIGHT: [
163
+ {
164
+ "eyeLookInLeft": 1.0,
165
+ "eyeLookOutRight": 1.0,
166
+ }
167
+ ],
168
+ }
@@ -0,0 +1,62 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
2
+
3
+ from collections.abc import Mapping, Sequence
4
+ from typing import Final
5
+
6
+ from ..vrm1.expression_preset import ExpressionPreset, ExpressionPresets
7
+
8
+ VRM1_PRESET_TO_MMD_SHAPE_KEY_MAPPING: Final[
9
+ Mapping[ExpressionPreset, Sequence[Mapping[str, float]]]
10
+ ] = {
11
+ ExpressionPresets.AA: [
12
+ {"あ": 1.0},
13
+ ],
14
+ ExpressionPresets.IH: [
15
+ {"い": 1.0},
16
+ ],
17
+ ExpressionPresets.OU: [
18
+ {"う": 1.0},
19
+ ],
20
+ ExpressionPresets.EE: [
21
+ {"え": 1.0},
22
+ {"えー": 0.5},
23
+ ],
24
+ ExpressionPresets.OH: [
25
+ {"お": 1.0},
26
+ ],
27
+ ExpressionPresets.BLINK: [
28
+ {"まばたき": 1.0},
29
+ ],
30
+ ExpressionPresets.BLINK_RIGHT: [
31
+ {"ウィンク右": 1.0},
32
+ {"ウィンク2右": 1.0},
33
+ {"ウィンク2右": 1.0},
34
+ ],
35
+ ExpressionPresets.BLINK_LEFT: [
36
+ {"ウィンク": 1.0},
37
+ {"ウィンク2": 1.0},
38
+ {"ウィンク2": 1.0},
39
+ ],
40
+ ExpressionPresets.HAPPY: [
41
+ {"笑い": 1.0},
42
+ {"にこり": 1.0},
43
+ ],
44
+ ExpressionPresets.RELAXED: [
45
+ {"なごみ": 1.0},
46
+ ],
47
+ ExpressionPresets.ANGRY: [
48
+ {"怒り": 1.0},
49
+ ],
50
+ ExpressionPresets.SAD: [
51
+ {"困る": 1.0},
52
+ ],
53
+ ExpressionPresets.SURPRISED: [
54
+ {"びっくり": 1.0},
55
+ ],
56
+ ExpressionPresets.LOOK_UP: [
57
+ {"上": 1.0},
58
+ ],
59
+ ExpressionPresets.LOOK_DOWN: [
60
+ {"下": 1.0},
61
+ ],
62
+ }
@@ -0,0 +1,52 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
2
+
3
+ from collections.abc import Mapping, Sequence
4
+ from typing import Final
5
+
6
+ from ..vrm1.expression_preset import ExpressionPreset, ExpressionPresets
7
+
8
+ VRM1_PRESET_TO_READY_PLAYER_ME_SHAPE_KEY_MAPPING: Final[
9
+ Mapping[ExpressionPreset, Sequence[Mapping[str, float]]]
10
+ ] = {
11
+ # https://docs.readyplayer.me/ready-player-me/api-reference/avatars/morph-targets/oculus-ovr-libsync
12
+ ExpressionPresets.AA: [
13
+ {"viseme_aa": 1.0},
14
+ ],
15
+ ExpressionPresets.IH: [
16
+ {"viseme_I": 1.0},
17
+ ],
18
+ ExpressionPresets.OU: [
19
+ {"viseme_U": 1.0},
20
+ ],
21
+ ExpressionPresets.EE: [
22
+ {"viseme_E": 1.0},
23
+ ],
24
+ ExpressionPresets.OH: [
25
+ {"viseme_O": 1.0},
26
+ ],
27
+ # https://docs.readyplayer.me/ready-player-me/api-reference/avatars/morph-targets/apple-arkit
28
+ ExpressionPresets.BLINK: [
29
+ {"eyesClosed": 1.0},
30
+ ],
31
+ ExpressionPresets.BLINK_LEFT: [
32
+ {"eyeBlinkLeft": 1},
33
+ ],
34
+ ExpressionPresets.BLINK_RIGHT: [
35
+ {"eyeBlinkRight": 1},
36
+ ],
37
+ ExpressionPresets.LOOK_UP: [
38
+ {"eyeLookUp": 0.75},
39
+ ],
40
+ ExpressionPresets.LOOK_DOWN: [
41
+ {"eyesLookDown": 0.75},
42
+ ],
43
+ ExpressionPresets.RELAXED: [
44
+ {"browInnerUp": 0.5},
45
+ ],
46
+ ExpressionPresets.HAPPY: [
47
+ {"mouthSmile": 0.5},
48
+ ],
49
+ ExpressionPresets.SAD: [
50
+ {"mouthFrown": 0.5},
51
+ ],
52
+ }
@@ -0,0 +1,17 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
2
+
3
+ from collections.abc import Mapping, Sequence
4
+ from typing import Final
5
+
6
+ from ..vrm1.expression_preset import ExpressionPreset, ExpressionPresets
7
+
8
+ VRM1_PRESET_TO_VRCHAT_SHAPE_KEY_MAPPING: Final[
9
+ Mapping[ExpressionPreset, Sequence[Mapping[str, float]]]
10
+ ] = {
11
+ ExpressionPresets.AA: [{"vrc.v_aa": 1.0}, {"vrc_v_aa": 1.0}],
12
+ ExpressionPresets.EE: [{"vrc.v_e": 1.0}, {"vrc_v_e": 1.0}],
13
+ ExpressionPresets.IH: [{"vrc.v_ih": 1.0}, {"vrc_v_ih": 1.0}],
14
+ ExpressionPresets.OH: [{"vrc.v_oh": 1.0}, {"vrc_v_oh": 1.0}],
15
+ ExpressionPresets.OU: [{"vrc.v_ou": 1.0}, {"vrc_v_ou": 1.0}],
16
+ ExpressionPresets.BLINK: [{"Blink": 1.0}],
17
+ }
@@ -0,0 +1,214 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
2
+ import inspect
3
+ import sys
4
+ from collections.abc import Sequence
5
+ from pathlib import Path
6
+ from types import ModuleType
7
+ from typing import Optional
8
+
9
+ import bpy
10
+ from bpy.types import Context
11
+
12
+ from . import convert
13
+ from .logger import get_logger
14
+
15
+ _logger = get_logger(__name__)
16
+
17
+
18
+ def get_third_party_user_extension_name(module: ModuleType) -> Optional[str]:
19
+ module_name = module.__name__
20
+ module_init_path_str = getattr(module, "__file__", None)
21
+ if not isinstance(module_init_path_str, str):
22
+ _logger.warning(
23
+ "Module %s does not have a valid __file__ attribute",
24
+ module_name,
25
+ )
26
+ return None
27
+ if not module_init_path_str:
28
+ _logger.warning(
29
+ "Module %s has an empty __file__ attribute",
30
+ module_name,
31
+ )
32
+ return None
33
+ module_init_path = Path(module_init_path_str)
34
+ if not module_init_path.exists():
35
+ _logger.warning("Module init path %s does not exist", module_init_path)
36
+ return None
37
+ module_root_path = module_init_path.parent
38
+ if not module_root_path.is_dir():
39
+ _logger.warning("Module root path %s is not a directory", module_root_path)
40
+ return None
41
+
42
+ if (
43
+ bpy.app.version >= (4, 2)
44
+ and (
45
+ blender_manifest_path := module_root_path / "blender_manifest.toml"
46
+ ).exists()
47
+ and sys.version_info >= (3, 11)
48
+ ):
49
+ import tomllib
50
+
51
+ try:
52
+ blender_manifest_str = blender_manifest_path.read_text(encoding="utf-8")
53
+ except (OSError, UnicodeError):
54
+ _logger.exception(
55
+ "Failed to read blender_manifest.toml for module %s",
56
+ module_name,
57
+ )
58
+ return None
59
+ try:
60
+ blender_manifest = tomllib.loads(blender_manifest_str)
61
+ except tomllib.TOMLDecodeError:
62
+ _logger.warning(
63
+ "Failed to parse blender_manifest.toml for module %s",
64
+ module_name,
65
+ )
66
+ return None
67
+ blender_manifest_name = blender_manifest.get("name")
68
+ if not isinstance(blender_manifest_name, str) or not blender_manifest_name:
69
+ _logger.warning(
70
+ "Module %s has a blender_manifest.toml without a valid name",
71
+ module_name,
72
+ )
73
+ return None
74
+ blender_manifest_version = blender_manifest.get("version")
75
+ if (
76
+ not isinstance(blender_manifest_version, str)
77
+ or not blender_manifest_version
78
+ ):
79
+ _logger.warning(
80
+ "Module %s has a blender_manifest.toml without a valid version",
81
+ module_name,
82
+ )
83
+ return None
84
+ return blender_manifest_name + " " + blender_manifest_version
85
+
86
+ bl_info = convert.mapping_or_none(getattr(module, "bl_info", None))
87
+ if not bl_info:
88
+ _logger.warning(
89
+ "Module %s does not have a valid bl_info dictionary",
90
+ module_name,
91
+ )
92
+ return None
93
+
94
+ bl_info_name = bl_info.get("name")
95
+ if not isinstance(bl_info_name, str):
96
+ bl_info_name = module_name
97
+
98
+ bl_info_version = convert.sequence_or_none(bl_info.get("version"))
99
+ if not bl_info_version:
100
+ bl_info_version = ("no-version",)
101
+
102
+ return (
103
+ bl_info_name
104
+ + " "
105
+ + ".".join(str(version_element) for version_element in bl_info_version)
106
+ )
107
+
108
+
109
+ def collect_third_party_user_extensions(
110
+ context: Context, user_extension_class_name: str
111
+ ) -> list[tuple[str, object]]:
112
+ user_extensions: list[tuple[str, object]] = []
113
+ preferences = context.preferences
114
+ for addon_name in preferences.addons.keys():
115
+ addon_module = sys.modules.get(addon_name)
116
+ if addon_module is None:
117
+ continue
118
+ user_extension_name = get_third_party_user_extension_name(addon_module)
119
+ if user_extension_name is None:
120
+ continue
121
+ user_extension_type = getattr(addon_module, user_extension_class_name, None)
122
+ if not isinstance(user_extension_type, type):
123
+ continue
124
+ try:
125
+ user_extension: object = user_extension_type()
126
+ except Exception:
127
+ _logger.exception(
128
+ "Failed to instantiate %s from addon '%s'",
129
+ user_extension_class_name,
130
+ addon_name,
131
+ )
132
+ continue
133
+ user_extensions.append((user_extension_name, user_extension))
134
+ return user_extensions
135
+
136
+
137
+ def trigger_third_party_user_extension_hook(
138
+ user_extensions: Sequence[object], method_name: str, *args: object
139
+ ) -> None:
140
+ for user_extension in user_extensions:
141
+ method = getattr(user_extension, method_name, None)
142
+ if not callable(method):
143
+ continue
144
+
145
+ try:
146
+ parameters = tuple(inspect.signature(method).parameters.values())
147
+ except (TypeError, ValueError):
148
+ # Some callables implemented outside Python don't expose a signature.
149
+ method_args = args
150
+ else:
151
+ if any(
152
+ parameter.kind is inspect.Parameter.KEYWORD_ONLY
153
+ and parameter.default is inspect.Parameter.empty
154
+ for parameter in parameters
155
+ ):
156
+ _logger.error(
157
+ "Failed to call %s of %s from addon '%s': "
158
+ "the callback has keyword-only arguments without defaults",
159
+ method_name,
160
+ user_extension.__class__.__name__,
161
+ user_extension.__class__.__module__,
162
+ )
163
+ continue
164
+
165
+ min_arg_count = sum(
166
+ 1
167
+ for parameter in parameters
168
+ if parameter.default is inspect.Parameter.empty
169
+ and parameter.kind
170
+ in (
171
+ inspect.Parameter.POSITIONAL_ONLY,
172
+ inspect.Parameter.POSITIONAL_OR_KEYWORD,
173
+ )
174
+ )
175
+ if len(args) < min_arg_count:
176
+ _logger.error(
177
+ "Failed to call %s of %s from addon '%s': "
178
+ "the callback requires %d argument%s, but only %d %s available",
179
+ method_name,
180
+ user_extension.__class__.__name__,
181
+ user_extension.__class__.__module__,
182
+ min_arg_count,
183
+ "" if min_arg_count == 1 else "s",
184
+ len(args),
185
+ "is" if len(args) == 1 else "are",
186
+ )
187
+ continue
188
+
189
+ max_arg_count = sum(
190
+ 1
191
+ for parameter in parameters
192
+ if parameter.kind
193
+ in (
194
+ inspect.Parameter.POSITIONAL_ONLY,
195
+ inspect.Parameter.POSITIONAL_OR_KEYWORD,
196
+ )
197
+ )
198
+ if any(
199
+ parameter.kind is inspect.Parameter.VAR_POSITIONAL
200
+ for parameter in parameters
201
+ ):
202
+ method_args = args
203
+ else:
204
+ method_args = args[:max_arg_count]
205
+
206
+ try:
207
+ method(*method_args)
208
+ except Exception:
209
+ _logger.exception(
210
+ "Failed to call %s of %s from addon '%s'",
211
+ method_name,
212
+ user_extension.__class__.__name__,
213
+ user_extension.__class__.__module__,
214
+ )
@@ -0,0 +1,161 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
2
+ import platform
3
+ from dataclasses import dataclass
4
+ from sys import float_info
5
+ from typing import Optional
6
+
7
+ import bpy
8
+ from bpy.app.translations import pgettext
9
+
10
+ from .blender_manifest import BlenderManifest
11
+ from .logger import get_logger
12
+
13
+ _logger = get_logger(__name__)
14
+
15
+
16
+ @dataclass
17
+ class Cache:
18
+ use: bool
19
+ last_blender_restart_required: bool
20
+ last_blender_manifest_modification_time: float
21
+ initial_blender_manifest_content: bytes
22
+
23
+
24
+ _cache = Cache(
25
+ use=False,
26
+ last_blender_restart_required=False,
27
+ last_blender_manifest_modification_time=0.0,
28
+ initial_blender_manifest_content=BlenderManifest.default_blender_manifest_path().read_bytes(),
29
+ )
30
+
31
+
32
+ def _clear_addon_version_cache() -> Optional[float]:
33
+ _cache.use = False
34
+ return None
35
+
36
+
37
+ def trigger_clear_addon_version_cache() -> None:
38
+ if tuple(bpy.app.version) >= (4, 2):
39
+ return
40
+ if bpy.app.timers.is_registered(_clear_addon_version_cache):
41
+ return
42
+ bpy.app.timers.register(_clear_addon_version_cache, first_interval=0.5)
43
+
44
+
45
+ def _min_unsupported_blender_major_minor_version() -> Optional[tuple[int, int]]:
46
+ blender_version_max = BlenderManifest.read().blender_version_max
47
+ if blender_version_max is None:
48
+ return None
49
+ return (blender_version_max[0], blender_version_max[1])
50
+
51
+
52
+ def get_addon_version() -> tuple[int, int, int]:
53
+ return BlenderManifest.read().version
54
+
55
+
56
+ def _blender_restart_required() -> bool:
57
+ if tuple(bpy.app.version) >= (4, 2):
58
+ return False
59
+
60
+ if _cache.use:
61
+ return _cache.last_blender_restart_required
62
+
63
+ _cache.use = True
64
+
65
+ if _cache.last_blender_restart_required:
66
+ return True
67
+
68
+ blender_manifest_path = BlenderManifest.default_blender_manifest_path()
69
+ blender_manifest_modification_time = blender_manifest_path.stat().st_mtime
70
+ if (
71
+ abs(
72
+ _cache.last_blender_manifest_modification_time
73
+ - blender_manifest_modification_time
74
+ )
75
+ < float_info.epsilon
76
+ ):
77
+ return False
78
+
79
+ _cache.last_blender_manifest_modification_time = blender_manifest_modification_time
80
+
81
+ blender_manifest_content = blender_manifest_path.read_bytes()
82
+ if blender_manifest_content == _cache.initial_blender_manifest_content:
83
+ return False
84
+
85
+ _cache.last_blender_restart_required = True
86
+ return True
87
+
88
+
89
+ def _stable_release() -> bool:
90
+ if bpy.app.version_cycle == "release":
91
+ return True
92
+
93
+ # Microsoft Store distributes RC versions of 3.3.11 and 3.6.3 as
94
+ # release versions.
95
+ return platform.system() == "Windows" and bpy.app.version_cycle == "rc"
96
+
97
+
98
+ def supported() -> bool:
99
+ v = _min_unsupported_blender_major_minor_version()
100
+ if v is None:
101
+ return True
102
+ return bpy.app.version[:2] < v
103
+
104
+
105
+ def preferences_warning_message() -> Optional[str]:
106
+ if _blender_restart_required():
107
+ return pgettext(
108
+ "The VRM add-on has been updated."
109
+ + " Please restart Blender to apply the changes."
110
+ )
111
+ if not _stable_release():
112
+ return pgettext(
113
+ "VRM add-on is not compatible with Blender {blender_version_cycle}."
114
+ ).format(blender_version_cycle=bpy.app.version_cycle.capitalize())
115
+ if not supported():
116
+ return pgettext(
117
+ "The installed VRM add-on is not compatible with Blender {blender_version}."
118
+ + " Please upgrade the add-on.",
119
+ ).format(blender_version=".".join(map(str, bpy.app.version[:2])))
120
+ return None
121
+
122
+
123
+ def panel_warning_message() -> Optional[str]:
124
+ if _blender_restart_required():
125
+ return pgettext(
126
+ "The VRM add-on has been\n"
127
+ + "updated. Please restart Blender\n"
128
+ + "to apply the changes."
129
+ )
130
+ if not _stable_release():
131
+ return pgettext(
132
+ "VRM add-on is\n"
133
+ + "not compatible with\n"
134
+ + "Blender {blender_version_cycle}."
135
+ ).format(blender_version_cycle=bpy.app.version_cycle.capitalize())
136
+ if not supported():
137
+ return pgettext(
138
+ "The installed VRM add-\n"
139
+ + "on is not compatible with\n"
140
+ + "Blender {blender_version}. Please update."
141
+ ).format(blender_version=".".join(map(str, bpy.app.version[:2])))
142
+ return None
143
+
144
+
145
+ def validation_warning_message() -> Optional[str]:
146
+ if _blender_restart_required():
147
+ return pgettext(
148
+ "The VRM add-on has been updated."
149
+ + " Please restart Blender to apply the changes."
150
+ )
151
+ if not _stable_release():
152
+ return pgettext(
153
+ "VRM add-on is not compatible with Blender {blender_version_cycle}."
154
+ + " The VRM may not be exported correctly.",
155
+ ).format(blender_version_cycle=bpy.app.version_cycle.capitalize())
156
+ if not supported():
157
+ return pgettext(
158
+ "The installed VRM add-on is not compatible with Blender {blender_version}."
159
+ + " The VRM may not be exported correctly."
160
+ ).format(blender_version=".".join(map(str, bpy.app.version)))
161
+ return None
@@ -0,0 +1 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later