@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,316 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later
2
+ import math
3
+ import re
4
+ from sys import float_info
5
+ from typing import Final
6
+
7
+ from mathutils import Quaternion
8
+
9
+ from ..common import deep, gltf
10
+ from ..common.convert import Json
11
+ from ..common.deep import make_json
12
+ from ..common.gltf import read_accessors
13
+
14
+ ASSET_GENERATOR_PATTERN: Final = (
15
+ r"\AVRM Add-on for Blender v999\.999\.999"
16
+ + r" with Khronos glTF Blender I/O v[0-9]+\.[0-9]+\.[0-9]+\Z"
17
+ )
18
+
19
+ FIXED_ASSET_GENERATOR_VALUE: Final = (
20
+ "VRM Add-on for Blender v999.999.999"
21
+ + " with Khronos glTF Blender I/O v999.999.999"
22
+ )
23
+
24
+
25
+ def _human_bone_sort_key(human_bone_dict: Json) -> int:
26
+ if not isinstance(human_bone_dict, dict):
27
+ return -1
28
+ node = human_bone_dict.get("node")
29
+ if not isinstance(node, int):
30
+ return -1
31
+ return node
32
+
33
+
34
+ def _create_vrm_json_dict(data: bytes) -> dict[str, Json]:
35
+ json_dict, buffer0_bytes = gltf.parse_glb(data)
36
+ json_dict["__decoded_accessors"] = make_json(
37
+ read_accessors(json_dict, buffer0_bytes)
38
+ )
39
+
40
+ extensions_dict = json_dict.get("extensions")
41
+ if isinstance(extensions_dict, dict):
42
+ is_vrm0 = bool(extensions_dict.get("VRM"))
43
+ else:
44
+ is_vrm0 = False
45
+
46
+ asset_dict = json_dict.get("asset")
47
+ if isinstance(asset_dict, dict):
48
+ asset_generator = asset_dict.get("generator")
49
+ if isinstance(asset_generator, str):
50
+ asset_dict["generator"] = re.sub(
51
+ ASSET_GENERATOR_PATTERN,
52
+ FIXED_ASSET_GENERATOR_VALUE,
53
+ asset_generator,
54
+ )
55
+
56
+ node_dicts = json_dict.get("nodes")
57
+ if isinstance(node_dicts, list):
58
+ for node_dict in node_dicts:
59
+ if not isinstance(node_dict, dict):
60
+ continue
61
+
62
+ if is_vrm0:
63
+ skin_index = node_dict.get("skin")
64
+ if isinstance(skin_index, int):
65
+ skin_dicts = json_dict.get("skins")
66
+ if (
67
+ isinstance(skin_dicts, list)
68
+ and skin_dicts
69
+ and 0 <= skin_index < len(skin_dicts)
70
+ and not deep.diff(skin_dicts[0], skin_dicts[skin_index])
71
+ ):
72
+ node_dict["skin"] = 0
73
+
74
+ if "matrix" in node_dict:
75
+ continue
76
+
77
+ if "translation" not in node_dict:
78
+ node_dict["translation"] = [0.0, 0.0, 0.0]
79
+
80
+ if "scale" not in node_dict:
81
+ node_dict["scale"] = [1.0, 1.0, 1.0]
82
+
83
+ rotation = node_dict.get("rotation")
84
+ if rotation is None:
85
+ node_dict["rotation"] = [0.0, 0.0, 0.0, 1.0]
86
+ continue
87
+
88
+ if not isinstance(rotation, list) or len(rotation) != 4:
89
+ continue
90
+
91
+ rotation_x, rotation_y, rotation_z, rotation_w = rotation
92
+ if (
93
+ not isinstance(rotation_x, (float, int))
94
+ or not isinstance(rotation_y, (float, int))
95
+ or not isinstance(rotation_z, (float, int))
96
+ or not isinstance(rotation_w, (float, int))
97
+ ):
98
+ continue
99
+
100
+ axis, angle = Quaternion(
101
+ (rotation_w, rotation_x, rotation_y, rotation_z)
102
+ ).to_axis_angle()
103
+ if abs(angle - math.pi) > 0.000001:
104
+ continue
105
+
106
+ if abs(axis.x) > abs(axis.y) and abs(axis.x) > abs(axis.z):
107
+ if axis.x < 0:
108
+ axis = -axis
109
+ elif abs(axis.y) > abs(axis.z):
110
+ if axis.y < 0:
111
+ axis = -axis
112
+ elif axis.z < 0:
113
+ axis = -axis
114
+
115
+ q = Quaternion(axis, angle).normalized()
116
+ node_dict["rotation"] = [q.x, q.y, q.z, q.w]
117
+
118
+ if is_vrm0:
119
+ skin_dicts = json_dict.get("skins")
120
+ if isinstance(skin_dicts, list) and skin_dicts:
121
+ first_skin_dict = skin_dicts[0]
122
+ if all(
123
+ not deep.diff(skin_dict, first_skin_dict)
124
+ for skin_dict in skin_dicts
125
+ if isinstance(skin_dict, dict)
126
+ ):
127
+ while len(skin_dicts) > 1:
128
+ skin_dicts.pop()
129
+
130
+ scene_dicts = json_dict.get("scenes")
131
+ if isinstance(scene_dicts, list):
132
+ for scene_dict in scene_dicts:
133
+ if not isinstance(scene_dict, dict):
134
+ continue
135
+ scene_extras_dict = scene_dict.get("extras")
136
+ if not isinstance(scene_extras_dict, dict):
137
+ continue
138
+ for k in ("show_mmd_tabs", "embed_textures", "ui_lang"):
139
+ scene_extras_dict.pop(k, None)
140
+ if not scene_extras_dict:
141
+ scene_dict.pop("extras", None)
142
+
143
+ extensions_dict = json_dict.get("extensions")
144
+ if not isinstance(extensions_dict, dict):
145
+ return json_dict
146
+
147
+ vrm0_extension_dict = extensions_dict.get("VRM")
148
+ if not isinstance(vrm0_extension_dict, dict):
149
+ return json_dict
150
+
151
+ vrm0_first_person_dict = vrm0_extension_dict.get("firstPerson")
152
+ if not isinstance(vrm0_first_person_dict, dict):
153
+ vrm0_first_person_dict = {}
154
+ vrm0_extension_dict["firstPerson"] = vrm0_first_person_dict
155
+
156
+ vrm0_humanoid_dict = vrm0_extension_dict.get("humanoid")
157
+ if isinstance(vrm0_humanoid_dict, dict):
158
+ vrm0_human_bone_dicts = vrm0_humanoid_dict.get("humanBones")
159
+ if isinstance(vrm0_human_bone_dicts, list):
160
+ vrm0_humanoid_dict["humanBones"] = sorted(
161
+ vrm0_human_bone_dicts, key=_human_bone_sort_key
162
+ )
163
+
164
+ vrm0_first_person_bone = vrm0_first_person_dict.get("firstPersonBone")
165
+ if vrm0_first_person_bone in {None, -1}:
166
+ for vrm0_human_bone_dict in vrm0_human_bone_dicts:
167
+ if not isinstance(vrm0_human_bone_dict, dict):
168
+ continue
169
+ node = vrm0_human_bone_dict.get("node")
170
+ if not isinstance(node, int) or node < 0:
171
+ continue
172
+ if vrm0_human_bone_dict.get("bone") == "head":
173
+ vrm0_first_person_dict["firstPersonBone"] = node
174
+ break
175
+
176
+ for look_at_key in (
177
+ "lookAtHorizontalInner",
178
+ "lookAtHorizontalOuter",
179
+ "lookAtVerticalDown",
180
+ "lookAtVerticalUp",
181
+ ):
182
+ if look_at_key not in vrm0_first_person_dict:
183
+ vrm0_first_person_dict[look_at_key] = {}
184
+ look_at_dict = vrm0_first_person_dict[look_at_key]
185
+ if not isinstance(look_at_dict, dict):
186
+ continue
187
+ if "curve" not in look_at_dict:
188
+ look_at_dict["curve"] = [0, 0, 0, 1, 1, 1, 1, 0]
189
+
190
+ vrm0_blend_shape_master_dict = vrm0_extension_dict.get("blendShapeMaster")
191
+ if isinstance(vrm0_blend_shape_master_dict, dict):
192
+ vrm0_blend_shape_group_dicts = vrm0_blend_shape_master_dict.get(
193
+ "blendShapeGroups"
194
+ )
195
+ if isinstance(vrm0_blend_shape_group_dicts, list):
196
+ for vrm0_blend_shape_group_dict in vrm0_blend_shape_group_dicts:
197
+ if not isinstance(vrm0_blend_shape_group_dict, dict):
198
+ continue
199
+ if "isBinary" not in vrm0_blend_shape_group_dict:
200
+ vrm0_blend_shape_group_dict["isBinary"] = False
201
+ if "binds" not in vrm0_blend_shape_group_dict:
202
+ vrm0_blend_shape_group_dict["binds"] = []
203
+ if "materialValues" not in vrm0_blend_shape_group_dict:
204
+ vrm0_blend_shape_group_dict["materialValues"] = []
205
+
206
+ vrm0_secondary_animation = vrm0_extension_dict.get("secondaryAnimation")
207
+ if isinstance(vrm0_secondary_animation, dict):
208
+ vrm0_collider_group_dicts = vrm0_secondary_animation.get("colliderGroups")
209
+ if isinstance(vrm0_collider_group_dicts, list):
210
+
211
+ def sort_collider_groups_with_index_key(
212
+ collider_group_with_index: tuple[int, Json],
213
+ ) -> int:
214
+ (_, collider_group) = collider_group_with_index
215
+ if not isinstance(collider_group, dict):
216
+ return -999
217
+ node = collider_group.get("node")
218
+ if not isinstance(node, int):
219
+ return -999
220
+ return node
221
+
222
+ sorted_collider_groups_with_original_index = sorted(
223
+ enumerate(vrm0_collider_group_dicts),
224
+ key=sort_collider_groups_with_index_key,
225
+ )
226
+ vrm0_collider_group_dicts = [
227
+ collider_group
228
+ for _, collider_group in sorted_collider_groups_with_original_index
229
+ ]
230
+ original_index_to_sorted_index = {
231
+ original_index: sorted_index
232
+ for (sorted_index, (original_index, _)) in enumerate(
233
+ sorted_collider_groups_with_original_index
234
+ )
235
+ }
236
+
237
+ vrm0_bone_groups = vrm0_secondary_animation.get("boneGroups")
238
+ if isinstance(vrm0_bone_groups, list):
239
+ for vrm0_bone_group in vrm0_bone_groups:
240
+ if not isinstance(vrm0_bone_group, dict):
241
+ continue
242
+ if "comment" not in vrm0_bone_group:
243
+ vrm0_bone_group["comment"] = ""
244
+ collider_groups = vrm0_bone_group.get("colliderGroups")
245
+ if not isinstance(collider_groups, list):
246
+ continue
247
+ for i, collider_group in enumerate(list(collider_groups)):
248
+ if not isinstance(collider_group, int):
249
+ continue
250
+ if collider_group not in original_index_to_sorted_index:
251
+ collider_groups[i] = -999
252
+ continue
253
+ collider_groups[i] = original_index_to_sorted_index[
254
+ collider_group
255
+ ]
256
+
257
+ vrm0_material_properties = vrm0_extension_dict.get("materialProperties")
258
+ if isinstance(vrm0_material_properties, list):
259
+ for vrm0_material_property in vrm0_material_properties:
260
+ if not isinstance(vrm0_material_property, dict):
261
+ continue
262
+ if vrm0_material_property.get("shader") != "VRM/MToon":
263
+ continue
264
+
265
+ keyword_map = vrm0_material_property.get("keywordMap")
266
+ if not isinstance(keyword_map, dict):
267
+ keyword_map = {}
268
+
269
+ vrm0_float_properties = vrm0_material_property.get("floatProperties")
270
+ if isinstance(vrm0_float_properties, dict):
271
+ if vrm0_float_properties.get("_OutlineWidthMode", 0) == 0:
272
+ vrm0_float_properties["_OutlineWidth"] = 0
273
+ vrm0_float_properties["_OutlineColorMode"] = 0
274
+ vrm0_float_properties["_OutlineLightingMix"] = 0
275
+ keyword_map.pop("MTOON_OUTLINE_COLOR_FIXED", None)
276
+ keyword_map.pop("MTOON_OUTLINE_COLOR_MIXED", None)
277
+
278
+ if vrm0_float_properties.get("_OutlineWidthMode") != 2:
279
+ vrm0_float_properties["_OutlineScaledMaxDistance"] = 1
280
+
281
+ if vrm0_float_properties.get("_OutlineColorMode") == 0:
282
+ vrm0_float_properties["_OutlineLightingMix"] = 0
283
+
284
+ outline_lighting_mix = vrm0_float_properties.get("_OutlineLightingMix")
285
+ if (
286
+ isinstance(outline_lighting_mix, (float, int))
287
+ and abs(outline_lighting_mix) < float_info.epsilon
288
+ ):
289
+ vrm0_float_properties["_OutlineColorMode"] = 0
290
+ keyword_map.pop("MTOON_OUTLINE_COLOR_MIXED", None)
291
+ if "MTOON_OUTLINE_COLOR_FIXED" not in keyword_map:
292
+ keyword_map["MTOON_OUTLINE_COLOR_FIXED"] = True
293
+
294
+ vrm0_vector_properties = vrm0_material_property.get("vectorProperties")
295
+ if isinstance(vrm0_vector_properties, dict):
296
+ vrm0_emission_color = vrm0_vector_properties.get("_EmissionColor")
297
+ if (
298
+ isinstance(vrm0_emission_color, list)
299
+ and len(vrm0_emission_color) == 4
300
+ ):
301
+ vrm0_emission_color[3] = 1
302
+
303
+ vrm0_outline_color = vrm0_vector_properties.get("_OutlineColor")
304
+ if (
305
+ isinstance(vrm0_outline_color, list)
306
+ and len(vrm0_outline_color) == 4
307
+ ):
308
+ vrm0_outline_color[3] = 1
309
+
310
+ return json_dict
311
+
312
+
313
+ def vrm_diff(before: bytes, after: bytes, float_tolerance: float) -> list[str]:
314
+ return deep.diff(
315
+ _create_vrm_json_dict(before), _create_vrm_json_dict(after), float_tolerance
316
+ )
@@ -0,0 +1 @@
1
+ # SPDX-License-Identifier: MIT OR GPL-3.0-or-later