From 091ad6a49a34a734daea927524b4edc242913b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E7=85=9C?= <2082529121@qq.com> Date: Thu, 1 Jan 2026 14:21:56 +0800 Subject: [PATCH] feat: Add VRM Blender addon with complete import/export functionality - Add core VRM addon infrastructure with manifest and registration - Add common utilities module with file system, logging, and conversion helpers - Add human bone mapper with support for multiple rigging standards (Mixamo, MMD, Unreal, Rigify, etc.) - Add VRM 0.x and 1.x format support with property groups and handlers - Add editor UI panels for VRM metadata, spring bones, and MToon materials - Add exporter with glTF2 extension support for VRM format serialization - Add importer with scene reconstruction and armature generation - Add MToon shader support with auto-setup and material migration - Add spring bone physics simulation with constraint handling - Add node constraint editor for advanced rigging control - Add comprehensive validation and error handling with user dialogs - Add scene watcher for real-time property synchronization - Add workspace management and preference system - Include Python cache files and Blender manifest configuration - This is the initial commit establishing the complete VRM addon ecosystem for Blender --- README.txt | 3 + __init__.py | 41 + __pycache__/__init__.cpython-311.pyc | Bin 0 -> 1725 bytes __pycache__/registration.cpython-311.pyc | Bin 0 -> 36905 bytes blender_manifest.toml | 26 + common/__init__.py | 1 + common/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 224 bytes .../blender_manifest.cpython-311.pyc | Bin 0 -> 4043 bytes common/__pycache__/char.cpython-311.pyc | Bin 0 -> 950 bytes common/__pycache__/convert.cpython-311.pyc | Bin 0 -> 13785 bytes .../__pycache__/convert_any.cpython-311.pyc | Bin 0 -> 1561 bytes common/__pycache__/debug.cpython-311.pyc | Bin 0 -> 4187 bytes common/__pycache__/deep.cpython-311.pyc | Bin 0 -> 8179 bytes .../__pycache__/error_dialog.cpython-311.pyc | Bin 0 -> 13199 bytes common/__pycache__/fs.cpython-311.pyc | Bin 0 -> 2155 bytes common/__pycache__/gl.cpython-311.pyc | Bin 0 -> 1259 bytes common/__pycache__/gltf.cpython-311.pyc | Bin 0 -> 25114 bytes .../__pycache__/legacy_gltf.cpython-311.pyc | Bin 0 -> 743 bytes common/__pycache__/logger.cpython-311.pyc | Bin 0 -> 2958 bytes .../mtoon_unversioned.cpython-311.pyc | Bin 0 -> 2961 bytes .../__pycache__/preferences.cpython-311.pyc | Bin 0 -> 12888 bytes common/__pycache__/progress.cpython-311.pyc | Bin 0 -> 4776 bytes common/__pycache__/rotation.cpython-311.pyc | Bin 0 -> 3537 bytes .../__pycache__/safe_removal.cpython-311.pyc | Bin 0 -> 1561 bytes .../__pycache__/scene_watcher.cpython-311.pyc | Bin 0 -> 11601 bytes common/__pycache__/shader.cpython-311.pyc | Bin 0 -> 84922 bytes common/__pycache__/version.cpython-311.pyc | Bin 0 -> 7853 bytes common/__pycache__/workspace.cpython-311.pyc | Bin 0 -> 7870 bytes common/blender_manifest.py | 82 + common/char.py | 16 + common/convert.py | 297 ++ common/convert_any.py | 36 + common/debug.py | 60 + common/deep.py | 146 + common/error_dialog.py | 242 + common/fs.py | 42 + common/gl.py | 20 + common/gltf.py | 605 +++ common/human_bone_mapper/__init__.py | 1 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 242 bytes .../__pycache__/biped_mapping.cpython-311.pyc | Bin 0 -> 4923 bytes ...r_plugin_fix_model_mapping.cpython-311.pyc | Bin 0 -> 4089 bytes .../human_bone_mapper.cpython-311.pyc | Bin 0 -> 10060 bytes ...icrosoft_rocketbox_mapping.cpython-311.pyc | Bin 0 -> 4734 bytes .../mixamo_mapping.cpython-311.pyc | Bin 0 -> 4593 bytes .../__pycache__/mmd_mapping.cpython-311.pyc | Bin 0 -> 6210 bytes .../ready_player_me_mapping.cpython-311.pyc | Bin 0 -> 4171 bytes .../rigify_meta_rig_mapping.cpython-311.pyc | Bin 0 -> 4094 bytes .../unreal_mapping.cpython-311.pyc | Bin 0 -> 3918 bytes .../vrm_addon_mapping.cpython-311.pyc | Bin 0 -> 6425 bytes .../__pycache__/vroid_mapping.cpython-311.pyc | Bin 0 -> 5505 bytes common/human_bone_mapper/biped_mapping.py | 84 + .../cats_blender_plugin_fix_model_mapping.py | 63 + common/human_bone_mapper/human_bone_mapper.py | 179 + .../microsoft_rocketbox_mapping.py | 69 + common/human_bone_mapper/mixamo_mapping.py | 62 + common/human_bone_mapper/mmd_mapping.py | 115 + .../ready_player_me_mapping.py | 65 + .../rigify_meta_rig_mapping.py | 65 + common/human_bone_mapper/unreal_mapping.py | 62 + common/human_bone_mapper/vrm_addon_mapping.py | 112 + common/human_bone_mapper/vroid_mapping.py | 89 + common/legacy_gltf.py | 16 + common/logger.py | 58 + common/mtoon0.blend | Bin 0 -> 179720 bytes common/mtoon1.blend | Bin 0 -> 302686 bytes common/mtoon1_outline.blend | Bin 0 -> 478512 bytes common/mtoon_auto_setup.blend | Bin 0 -> 116081 bytes common/mtoon_unversioned.py | 62 + common/ops/__init__.py | 10 + .../ops/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 400 bytes .../__pycache__/export_scene.cpython-311.pyc | Bin 0 -> 2178 bytes common/ops/__pycache__/icyp.cpython-311.pyc | Bin 0 -> 1668 bytes .../__pycache__/import_scene.cpython-311.pyc | Bin 0 -> 1826 bytes common/ops/__pycache__/vrm.cpython-311.pyc | Bin 0 -> 48319 bytes common/ops/__pycache__/wm.cpython-311.pyc | Bin 0 -> 5071 bytes common/ops/export_scene.py | 67 + common/ops/icyp.py | 53 + common/ops/import_scene.py | 57 + common/ops/vrm.py | 1890 ++++++++ common/ops/wm.py | 165 + common/preferences.py | 361 ++ common/progress.py | 87 + common/rotation.py | 87 + common/safe_removal.py | 28 + common/scene_watcher.py | 228 + common/shader.py | 2045 +++++++++ common/test_helper.py | 59 + common/transparent_z_write.blend | Bin 0 -> 134583 bytes common/version.py | 161 + common/vrm0/__init__.py | 1 + .../vrm0/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 229 bytes .../__pycache__/human_bone.cpython-311.pyc | Bin 0 -> 20583 bytes common/vrm0/human_bone.py | 743 ++++ common/vrm1/__init__.py | 1 + .../vrm1/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 229 bytes .../__pycache__/human_bone.cpython-311.pyc | Bin 0 -> 18859 bytes common/vrm1/human_bone.py | 790 ++++ common/workspace.py | 221 + editor/__init__.py | 1 + editor/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 224 bytes editor/__pycache__/extension.cpython-311.pyc | Bin 0 -> 20234 bytes editor/__pycache__/handler.cpython-311.pyc | Bin 0 -> 742 bytes .../__pycache__/make_armature.cpython-311.pyc | Bin 0 -> 29965 bytes editor/__pycache__/migration.cpython-311.pyc | Bin 0 -> 10811 bytes editor/__pycache__/ops.cpython-311.pyc | Bin 0 -> 20212 bytes editor/__pycache__/panel.cpython-311.pyc | Bin 0 -> 12834 bytes .../property_group.cpython-311.pyc | Bin 0 -> 38212 bytes editor/__pycache__/search.cpython-311.pyc | Bin 0 -> 27373 bytes .../__pycache__/subscription.cpython-311.pyc | Bin 0 -> 6697 bytes editor/__pycache__/t_pose.cpython-311.pyc | Bin 0 -> 29491 bytes editor/__pycache__/validation.cpython-311.pyc | Bin 0 -> 40565 bytes editor/extension.py | 539 +++ editor/handler.py | 10 + editor/make_armature.py | 712 +++ editor/migration.py | 258 ++ editor/mtoon1/__init__.py | 1 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 231 bytes .../__pycache__/handler.cpython-311.pyc | Bin 0 -> 1393 bytes .../__pycache__/migration.cpython-311.pyc | Bin 0 -> 19185 bytes editor/mtoon1/__pycache__/ops.cpython-311.pyc | Bin 0 -> 44113 bytes .../mtoon1/__pycache__/panel.cpython-311.pyc | Bin 0 -> 20287 bytes .../property_group.cpython-311.pyc | Bin 0 -> 147342 bytes .../__pycache__/scene_watcher.cpython-311.pyc | Bin 0 -> 13346 bytes editor/mtoon1/handler.py | 24 + editor/mtoon1/migration.py | 529 +++ editor/mtoon1/ops.py | 1158 +++++ editor/mtoon1/panel.py | 447 ++ editor/mtoon1/property_group.py | 3780 ++++++++++++++++ editor/mtoon1/scene_watcher.py | 377 ++ editor/node_constraint1/__init__.py | 1 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 241 bytes .../__pycache__/panel.cpython-311.pyc | Bin 0 -> 13322 bytes .../property_group.cpython-311.pyc | Bin 0 -> 1196 bytes editor/node_constraint1/panel.py | 316 ++ editor/node_constraint1/property_group.py | 25 + editor/ops.py | 405 ++ editor/panel.py | 287 ++ editor/property_group.py | 851 ++++ editor/search.py | 721 +++ editor/spring_bone1/__init__.py | 1 + .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 237 bytes .../__pycache__/handler.cpython-311.pyc | Bin 0 -> 27099 bytes .../__pycache__/migration.cpython-311.pyc | Bin 0 -> 3330 bytes .../__pycache__/ops.cpython-311.pyc | Bin 0 -> 61427 bytes .../__pycache__/panel.cpython-311.pyc | Bin 0 -> 25348 bytes .../property_group.cpython-311.pyc | Bin 0 -> 51523 bytes .../__pycache__/ui_list.cpython-311.pyc | Bin 0 -> 8905 bytes editor/spring_bone1/handler.py | 858 ++++ editor/spring_bone1/migration.py | 61 + editor/spring_bone1/ops.py | 1601 +++++++ editor/spring_bone1/panel.py | 599 +++ editor/spring_bone1/property_group.py | 1271 ++++++ editor/spring_bone1/ui_list.py | 246 ++ editor/subscription.py | 147 + editor/t_pose.py | 716 +++ editor/validation.py | 1006 +++++ editor/vrm0/__init__.py | 1 + .../vrm0/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 229 bytes .../vrm0/__pycache__/handler.cpython-311.pyc | Bin 0 -> 1714 bytes editor/vrm0/__pycache__/menu.cpython-311.pyc | Bin 0 -> 1413 bytes .../__pycache__/migration.cpython-311.pyc | Bin 0 -> 33277 bytes editor/vrm0/__pycache__/ops.cpython-311.pyc | Bin 0 -> 103528 bytes editor/vrm0/__pycache__/panel.cpython-311.pyc | Bin 0 -> 54075 bytes .../property_group.cpython-311.pyc | Bin 0 -> 39785 bytes .../vrm0/__pycache__/ui_list.cpython-311.pyc | Bin 0 -> 15713 bytes editor/vrm0/gizmo_group.py | 62 + editor/vrm0/handler.py | 37 + editor/vrm0/menu.py | 24 + editor/vrm0/migration.py | 731 +++ editor/vrm0/ops.py | 2767 ++++++++++++ editor/vrm0/panel.py | 1249 ++++++ editor/vrm0/property_group.py | 1117 +++++ editor/vrm0/ui_list.py | 419 ++ editor/vrm1/__init__.py | 1 + .../vrm1/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 229 bytes .../vrm1/__pycache__/handler.cpython-311.pyc | Bin 0 -> 2188 bytes editor/vrm1/__pycache__/menu.cpython-311.pyc | Bin 0 -> 1403 bytes .../__pycache__/migration.cpython-311.pyc | Bin 0 -> 14114 bytes editor/vrm1/__pycache__/ops.cpython-311.pyc | Bin 0 -> 110455 bytes editor/vrm1/__pycache__/panel.cpython-311.pyc | Bin 0 -> 55023 bytes .../property_group.cpython-311.pyc | Bin 0 -> 65395 bytes .../__pycache__/scene_watcher.cpython-311.pyc | Bin 0 -> 4655 bytes .../vrm1/__pycache__/ui_list.cpython-311.pyc | Bin 0 -> 12027 bytes editor/vrm1/handler.py | 45 + editor/vrm1/menu.py | 26 + editor/vrm1/migration.py | 281 ++ editor/vrm1/ops.py | 2730 ++++++++++++ editor/vrm1/panel.py | 1222 +++++ editor/vrm1/property_group.py | 1812 ++++++++ editor/vrm1/scene_watcher.py | 93 + editor/vrm1/ui_list.py | 302 ++ exporter/__init__.py | 1 + exporter/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 226 bytes ...abstract_base_vrm_exporter.cpython-311.pyc | Bin 0 -> 16822 bytes .../__pycache__/export_scene.cpython-311.pyc | Bin 0 -> 39469 bytes ...ltf2_export_user_extension.cpython-311.pyc | Bin 0 -> 1568 bytes ...vrm_vrm_animation_exporter.cpython-311.pyc | Bin 0 -> 40321 bytes .../__pycache__/vrm0_exporter.cpython-311.pyc | Bin 0 -> 122803 bytes .../__pycache__/vrm1_exporter.cpython-311.pyc | Bin 0 -> 124451 bytes exporter/abstract_base_vrm_exporter.py | 384 ++ exporter/export_scene.py | 905 ++++ exporter/gltf2_export_user_extension.py | 33 + exporter/uni_vrm_vrm_animation_exporter.py | 1034 +++++ exporter/vrm0_exporter.py | 3911 +++++++++++++++++ exporter/vrm1_exporter.py | 3313 ++++++++++++++ exporter/vrm_animation_exporter.py | 1075 +++++ external/__init__.py | 1 + external/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 226 bytes .../io_scene_gltf2_support.cpython-311.pyc | Bin 0 -> 14050 bytes external/auto_rig_pro_support.py | 3 + external/io_scene_gltf2_support.py | 375 ++ external/rigify_support.py | 1 + importer/__init__.py | 1 + importer/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 226 bytes ...abstract_base_vrm_importer.cpython-311.pyc | Bin 0 -> 64738 bytes .../__pycache__/file_handler.cpython-311.pyc | Bin 0 -> 4461 bytes ...ltf2_import_user_extension.cpython-311.pyc | Bin 0 -> 3208 bytes .../__pycache__/import_scene.cpython-311.pyc | Bin 0 -> 23865 bytes .../license_validation.cpython-311.pyc | Bin 0 -> 9193 bytes ...vrm_vrm_animation_importer.cpython-311.pyc | Bin 0 -> 31389 bytes .../__pycache__/vrm0_importer.cpython-311.pyc | Bin 0 -> 66435 bytes .../__pycache__/vrm1_importer.cpython-311.pyc | Bin 0 -> 83300 bytes importer/abstract_base_vrm_importer.py | 1435 ++++++ importer/file_handler.py | 83 + importer/gltf2_import_user_extension.py | 62 + importer/import_scene.py | 559 +++ importer/license_validation.py | 198 + importer/uni_vrm_vrm_animation_importer.py | 781 ++++ importer/vrm0_importer.py | 1562 +++++++ importer/vrm1_importer.py | 1875 ++++++++ importer/vrm_animation_importer.py | 776 ++++ importer/vrm_diff.py | 310 ++ locale/__init__.py | 1 + locale/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 224 bytes locale/__pycache__/ja_jp.cpython-311.pyc | Bin 0 -> 33707 bytes .../translation_dictionary.cpython-311.pyc | Bin 0 -> 426 bytes locale/__pycache__/zh_hans.cpython-311.pyc | Bin 0 -> 27261 bytes locale/ja_jp.py | 781 ++++ locale/ruff.toml | 8 + locale/translation_dictionary.py | 7 + locale/zh_hans.py | 920 ++++ registration.py | 601 +++ 243 files changed, 60636 insertions(+) create mode 100644 README.txt create mode 100644 __init__.py create mode 100644 __pycache__/__init__.cpython-311.pyc create mode 100644 __pycache__/registration.cpython-311.pyc create mode 100644 blender_manifest.toml create mode 100644 common/__init__.py create mode 100644 common/__pycache__/__init__.cpython-311.pyc create mode 100644 common/__pycache__/blender_manifest.cpython-311.pyc create mode 100644 common/__pycache__/char.cpython-311.pyc create mode 100644 common/__pycache__/convert.cpython-311.pyc create mode 100644 common/__pycache__/convert_any.cpython-311.pyc create mode 100644 common/__pycache__/debug.cpython-311.pyc create mode 100644 common/__pycache__/deep.cpython-311.pyc create mode 100644 common/__pycache__/error_dialog.cpython-311.pyc create mode 100644 common/__pycache__/fs.cpython-311.pyc create mode 100644 common/__pycache__/gl.cpython-311.pyc create mode 100644 common/__pycache__/gltf.cpython-311.pyc create mode 100644 common/__pycache__/legacy_gltf.cpython-311.pyc create mode 100644 common/__pycache__/logger.cpython-311.pyc create mode 100644 common/__pycache__/mtoon_unversioned.cpython-311.pyc create mode 100644 common/__pycache__/preferences.cpython-311.pyc create mode 100644 common/__pycache__/progress.cpython-311.pyc create mode 100644 common/__pycache__/rotation.cpython-311.pyc create mode 100644 common/__pycache__/safe_removal.cpython-311.pyc create mode 100644 common/__pycache__/scene_watcher.cpython-311.pyc create mode 100644 common/__pycache__/shader.cpython-311.pyc create mode 100644 common/__pycache__/version.cpython-311.pyc create mode 100644 common/__pycache__/workspace.cpython-311.pyc create mode 100644 common/blender_manifest.py create mode 100644 common/char.py create mode 100644 common/convert.py create mode 100644 common/convert_any.py create mode 100644 common/debug.py create mode 100644 common/deep.py create mode 100644 common/error_dialog.py create mode 100644 common/fs.py create mode 100644 common/gl.py create mode 100644 common/gltf.py create mode 100644 common/human_bone_mapper/__init__.py create mode 100644 common/human_bone_mapper/__pycache__/__init__.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/biped_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/cats_blender_plugin_fix_model_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/human_bone_mapper.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/microsoft_rocketbox_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/mixamo_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/mmd_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/ready_player_me_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/rigify_meta_rig_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/unreal_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/vrm_addon_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/__pycache__/vroid_mapping.cpython-311.pyc create mode 100644 common/human_bone_mapper/biped_mapping.py create mode 100644 common/human_bone_mapper/cats_blender_plugin_fix_model_mapping.py create mode 100644 common/human_bone_mapper/human_bone_mapper.py create mode 100644 common/human_bone_mapper/microsoft_rocketbox_mapping.py create mode 100644 common/human_bone_mapper/mixamo_mapping.py create mode 100644 common/human_bone_mapper/mmd_mapping.py create mode 100644 common/human_bone_mapper/ready_player_me_mapping.py create mode 100644 common/human_bone_mapper/rigify_meta_rig_mapping.py create mode 100644 common/human_bone_mapper/unreal_mapping.py create mode 100644 common/human_bone_mapper/vrm_addon_mapping.py create mode 100644 common/human_bone_mapper/vroid_mapping.py create mode 100644 common/legacy_gltf.py create mode 100644 common/logger.py create mode 100644 common/mtoon0.blend create mode 100644 common/mtoon1.blend create mode 100644 common/mtoon1_outline.blend create mode 100644 common/mtoon_auto_setup.blend create mode 100644 common/mtoon_unversioned.py create mode 100644 common/ops/__init__.py create mode 100644 common/ops/__pycache__/__init__.cpython-311.pyc create mode 100644 common/ops/__pycache__/export_scene.cpython-311.pyc create mode 100644 common/ops/__pycache__/icyp.cpython-311.pyc create mode 100644 common/ops/__pycache__/import_scene.cpython-311.pyc create mode 100644 common/ops/__pycache__/vrm.cpython-311.pyc create mode 100644 common/ops/__pycache__/wm.cpython-311.pyc create mode 100644 common/ops/export_scene.py create mode 100644 common/ops/icyp.py create mode 100644 common/ops/import_scene.py create mode 100644 common/ops/vrm.py create mode 100644 common/ops/wm.py create mode 100644 common/preferences.py create mode 100644 common/progress.py create mode 100644 common/rotation.py create mode 100644 common/safe_removal.py create mode 100644 common/scene_watcher.py create mode 100644 common/shader.py create mode 100644 common/test_helper.py create mode 100644 common/transparent_z_write.blend create mode 100644 common/version.py create mode 100644 common/vrm0/__init__.py create mode 100644 common/vrm0/__pycache__/__init__.cpython-311.pyc create mode 100644 common/vrm0/__pycache__/human_bone.cpython-311.pyc create mode 100644 common/vrm0/human_bone.py create mode 100644 common/vrm1/__init__.py create mode 100644 common/vrm1/__pycache__/__init__.cpython-311.pyc create mode 100644 common/vrm1/__pycache__/human_bone.cpython-311.pyc create mode 100644 common/vrm1/human_bone.py create mode 100644 common/workspace.py create mode 100644 editor/__init__.py create mode 100644 editor/__pycache__/__init__.cpython-311.pyc create mode 100644 editor/__pycache__/extension.cpython-311.pyc create mode 100644 editor/__pycache__/handler.cpython-311.pyc create mode 100644 editor/__pycache__/make_armature.cpython-311.pyc create mode 100644 editor/__pycache__/migration.cpython-311.pyc create mode 100644 editor/__pycache__/ops.cpython-311.pyc create mode 100644 editor/__pycache__/panel.cpython-311.pyc create mode 100644 editor/__pycache__/property_group.cpython-311.pyc create mode 100644 editor/__pycache__/search.cpython-311.pyc create mode 100644 editor/__pycache__/subscription.cpython-311.pyc create mode 100644 editor/__pycache__/t_pose.cpython-311.pyc create mode 100644 editor/__pycache__/validation.cpython-311.pyc create mode 100644 editor/extension.py create mode 100644 editor/handler.py create mode 100644 editor/make_armature.py create mode 100644 editor/migration.py create mode 100644 editor/mtoon1/__init__.py create mode 100644 editor/mtoon1/__pycache__/__init__.cpython-311.pyc create mode 100644 editor/mtoon1/__pycache__/handler.cpython-311.pyc create mode 100644 editor/mtoon1/__pycache__/migration.cpython-311.pyc create mode 100644 editor/mtoon1/__pycache__/ops.cpython-311.pyc create mode 100644 editor/mtoon1/__pycache__/panel.cpython-311.pyc create mode 100644 editor/mtoon1/__pycache__/property_group.cpython-311.pyc create mode 100644 editor/mtoon1/__pycache__/scene_watcher.cpython-311.pyc create mode 100644 editor/mtoon1/handler.py create mode 100644 editor/mtoon1/migration.py create mode 100644 editor/mtoon1/ops.py create mode 100644 editor/mtoon1/panel.py create mode 100644 editor/mtoon1/property_group.py create mode 100644 editor/mtoon1/scene_watcher.py create mode 100644 editor/node_constraint1/__init__.py create mode 100644 editor/node_constraint1/__pycache__/__init__.cpython-311.pyc create mode 100644 editor/node_constraint1/__pycache__/panel.cpython-311.pyc create mode 100644 editor/node_constraint1/__pycache__/property_group.cpython-311.pyc create mode 100644 editor/node_constraint1/panel.py create mode 100644 editor/node_constraint1/property_group.py create mode 100644 editor/ops.py create mode 100644 editor/panel.py create mode 100644 editor/property_group.py create mode 100644 editor/search.py create mode 100644 editor/spring_bone1/__init__.py create mode 100644 editor/spring_bone1/__pycache__/__init__.cpython-311.pyc create mode 100644 editor/spring_bone1/__pycache__/handler.cpython-311.pyc create mode 100644 editor/spring_bone1/__pycache__/migration.cpython-311.pyc create mode 100644 editor/spring_bone1/__pycache__/ops.cpython-311.pyc create mode 100644 editor/spring_bone1/__pycache__/panel.cpython-311.pyc create mode 100644 editor/spring_bone1/__pycache__/property_group.cpython-311.pyc create mode 100644 editor/spring_bone1/__pycache__/ui_list.cpython-311.pyc create mode 100644 editor/spring_bone1/handler.py create mode 100644 editor/spring_bone1/migration.py create mode 100644 editor/spring_bone1/ops.py create mode 100644 editor/spring_bone1/panel.py create mode 100644 editor/spring_bone1/property_group.py create mode 100644 editor/spring_bone1/ui_list.py create mode 100644 editor/subscription.py create mode 100644 editor/t_pose.py create mode 100644 editor/validation.py create mode 100644 editor/vrm0/__init__.py create mode 100644 editor/vrm0/__pycache__/__init__.cpython-311.pyc create mode 100644 editor/vrm0/__pycache__/handler.cpython-311.pyc create mode 100644 editor/vrm0/__pycache__/menu.cpython-311.pyc create mode 100644 editor/vrm0/__pycache__/migration.cpython-311.pyc create mode 100644 editor/vrm0/__pycache__/ops.cpython-311.pyc create mode 100644 editor/vrm0/__pycache__/panel.cpython-311.pyc create mode 100644 editor/vrm0/__pycache__/property_group.cpython-311.pyc create mode 100644 editor/vrm0/__pycache__/ui_list.cpython-311.pyc create mode 100644 editor/vrm0/gizmo_group.py create mode 100644 editor/vrm0/handler.py create mode 100644 editor/vrm0/menu.py create mode 100644 editor/vrm0/migration.py create mode 100644 editor/vrm0/ops.py create mode 100644 editor/vrm0/panel.py create mode 100644 editor/vrm0/property_group.py create mode 100644 editor/vrm0/ui_list.py create mode 100644 editor/vrm1/__init__.py create mode 100644 editor/vrm1/__pycache__/__init__.cpython-311.pyc create mode 100644 editor/vrm1/__pycache__/handler.cpython-311.pyc create mode 100644 editor/vrm1/__pycache__/menu.cpython-311.pyc create mode 100644 editor/vrm1/__pycache__/migration.cpython-311.pyc create mode 100644 editor/vrm1/__pycache__/ops.cpython-311.pyc create mode 100644 editor/vrm1/__pycache__/panel.cpython-311.pyc create mode 100644 editor/vrm1/__pycache__/property_group.cpython-311.pyc create mode 100644 editor/vrm1/__pycache__/scene_watcher.cpython-311.pyc create mode 100644 editor/vrm1/__pycache__/ui_list.cpython-311.pyc create mode 100644 editor/vrm1/handler.py create mode 100644 editor/vrm1/menu.py create mode 100644 editor/vrm1/migration.py create mode 100644 editor/vrm1/ops.py create mode 100644 editor/vrm1/panel.py create mode 100644 editor/vrm1/property_group.py create mode 100644 editor/vrm1/scene_watcher.py create mode 100644 editor/vrm1/ui_list.py create mode 100644 exporter/__init__.py create mode 100644 exporter/__pycache__/__init__.cpython-311.pyc create mode 100644 exporter/__pycache__/abstract_base_vrm_exporter.cpython-311.pyc create mode 100644 exporter/__pycache__/export_scene.cpython-311.pyc create mode 100644 exporter/__pycache__/gltf2_export_user_extension.cpython-311.pyc create mode 100644 exporter/__pycache__/uni_vrm_vrm_animation_exporter.cpython-311.pyc create mode 100644 exporter/__pycache__/vrm0_exporter.cpython-311.pyc create mode 100644 exporter/__pycache__/vrm1_exporter.cpython-311.pyc create mode 100644 exporter/abstract_base_vrm_exporter.py create mode 100644 exporter/export_scene.py create mode 100644 exporter/gltf2_export_user_extension.py create mode 100644 exporter/uni_vrm_vrm_animation_exporter.py create mode 100644 exporter/vrm0_exporter.py create mode 100644 exporter/vrm1_exporter.py create mode 100644 exporter/vrm_animation_exporter.py create mode 100644 external/__init__.py create mode 100644 external/__pycache__/__init__.cpython-311.pyc create mode 100644 external/__pycache__/io_scene_gltf2_support.cpython-311.pyc create mode 100644 external/auto_rig_pro_support.py create mode 100644 external/io_scene_gltf2_support.py create mode 100644 external/rigify_support.py create mode 100644 importer/__init__.py create mode 100644 importer/__pycache__/__init__.cpython-311.pyc create mode 100644 importer/__pycache__/abstract_base_vrm_importer.cpython-311.pyc create mode 100644 importer/__pycache__/file_handler.cpython-311.pyc create mode 100644 importer/__pycache__/gltf2_import_user_extension.cpython-311.pyc create mode 100644 importer/__pycache__/import_scene.cpython-311.pyc create mode 100644 importer/__pycache__/license_validation.cpython-311.pyc create mode 100644 importer/__pycache__/uni_vrm_vrm_animation_importer.cpython-311.pyc create mode 100644 importer/__pycache__/vrm0_importer.cpython-311.pyc create mode 100644 importer/__pycache__/vrm1_importer.cpython-311.pyc create mode 100644 importer/abstract_base_vrm_importer.py create mode 100644 importer/file_handler.py create mode 100644 importer/gltf2_import_user_extension.py create mode 100644 importer/import_scene.py create mode 100644 importer/license_validation.py create mode 100644 importer/uni_vrm_vrm_animation_importer.py create mode 100644 importer/vrm0_importer.py create mode 100644 importer/vrm1_importer.py create mode 100644 importer/vrm_animation_importer.py create mode 100644 importer/vrm_diff.py create mode 100644 locale/__init__.py create mode 100644 locale/__pycache__/__init__.cpython-311.pyc create mode 100644 locale/__pycache__/ja_jp.cpython-311.pyc create mode 100644 locale/__pycache__/translation_dictionary.cpython-311.pyc create mode 100644 locale/__pycache__/zh_hans.cpython-311.pyc create mode 100644 locale/ja_jp.py create mode 100644 locale/ruff.toml create mode 100644 locale/translation_dictionary.py create mode 100644 locale/zh_hans.py create mode 100644 registration.py diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..ed0b994 --- /dev/null +++ b/README.txt @@ -0,0 +1,3 @@ +# VRM Add-on for Blender + +See https://vrm-addon-for-blender.info for more information. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..ab06240 --- /dev/null +++ b/__init__.py @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: MIT OR GPL-3.0-or-later +# SPDX-FileCopyrightText: 2018 iCyP + +from . import registration +from .exporter import gltf2_export_user_extension +from .importer import gltf2_import_user_extension + +bl_info = { + "name": "VRM format", + "author": "saturday06, iCyP", + "version": ( + 3, # x-release-please-major + 17, # x-release-please-minor + 1, # x-release-please-patch + ), + "location": "File > Import-Export", + "description": "Import-Edit-Export VRM", + "blender": (2, 93, 0), + "warning": "", + "support": "COMMUNITY", + "wiki_url": "", + "doc_url": "https://vrm-addon-for-blender.info", + "tracker_url": "https://github.com/saturday06/VRM-Addon-for-Blender/issues", + "category": "Import-Export", +} + + +def register() -> None: + registration.register() + + +def unregister() -> None: + registration.unregister() + + +class glTF2ImportUserExtension(gltf2_import_user_extension.glTF2ImportUserExtension): + pass + + +class glTF2ExportUserExtension(gltf2_export_user_extension.glTF2ExportUserExtension): + pass diff --git a/__pycache__/__init__.cpython-311.pyc b/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..70beafd758087e9b8b0a99bd0a1da81a95322019 GIT binary patch literal 1725 zcmb_c&2JM&6rZ)%_WCQf2?dM^F{Ki?#db?u4pEDg22yc|sR$s|TC`d`8)w6QxU;*^ z_!O!954rSMQAPYSM#^C|QcpeQ=E^;B;=Ng~iA@i!)bY&EZ{B+|^WJaX?C-^5jzG)& z@~wGGCge|?#H~0LCclAjNGPF_MQo`nNhl|*gq`drg`BixJJn5rEYlQC(+pK;mgZ<4 zMu8UT5-t5&=%(ofdgi6v&A|UM{3{9aJ)vh`68e#m+RMhrzDg4E8b;K*S>bgKyv`fR zJrONh7QAw_vP~M*6A4TWi5HmBH$9)}zUewJuk|f|=cZ=-JaCz>1)jk`_6^6IGn@85 zn1{K?54P$%F0*xiSoU;3U{v4#{ML=Sxv~F4BYA?Mo>Tx>0$_M{)3l8G?fN~jS@W(q za(FJDQq!O6>aZ^?$3-Vk5MU5acy{Cd*4CrWy@x*zKi>8Ifw$IfKWBDRr_^Z> zWjNGeEz{X?hikD<-}HBbr>&lAx8FzEhC`a`vz6aPE8C{$1%@{)#!-nN8wD;qx^3{Z z9{9U1`>t^2{_4o_V1&$8`EU;{^lckSj0DXQmb~i)X0Y z6G9%YqxTG$N38<;8GV=S^E5MnQm50y^y7x4Ag_}f0EfiKYn`^enfwYguVXdALfj@t zQm2t%xRfhV4H)c*OwjACwXvo?f~)t`b!wYVR39!=*9U_;y05DbTpiSXbxKlw(+wOd z(vDT?SFNwrS>brpnr6E+uuv{&+E0OQMV7@tuVSDG zpTL-u01jrqP*x7^L`k8?9E1NR%IIazN6GM<#UMUK9l~`K1mKkk6_8y8xzotAJnE7F zT#3Fj24k|An&MLc(-cnO)j*lRI~Elpt^(s1+btaZR{194={9SD3ufiP*O!cwk|d24 zBGpFZ;^`ieFGlnIL(Mo%iq&wbK2FHx^f*T<*TUt`!csLXRl?H6uzV&geHkv_56i3L yE0ug=OaKlt^{uKgW8&ajLC literal 0 HcmV?d00001 diff --git a/__pycache__/registration.cpython-311.pyc b/__pycache__/registration.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4ebd83b11d5367cc6a9966244b6efcee98d4fd7 GIT binary patch literal 36905 zcmdU&30xf6nb@nLfChn(1d>K~O9DwCKp>$DApznL5~l!NJxHyFE}&6gQ{8~j=$N%< z)?=@{9(&ho?|Qw4_v4T+u2Byr9+>viHd$L{yuSFftx z>uNyWS^s`%wW{C0-uLeNt5=WTEGsKf;8XPR^WpElqA0&dfq%+O!}lL=QM7qEM3q%d0KFJk6`h&Nj7FOHV@OQIY68=|HD z(rB5#EV|LZFwy#E3-mqyyaZ96k>26Ko1A~TnP`KZ5>nKy#D&fmq%W9D)&*ZcdKc@vn=`v;hLOJp!Q`MUZQ5d10^SNtyv_Pes|#|8V{S@yRD`#o9qccvBX>TG}q_*suuKYLf8 zpgO$ropQ1`4R(3C*a0?h~%7HC$WdjdrSiV74HC@xS!AZYjafwXte>H;Ml)IXaN zXilJcfffY1FVLbu4+MHupoaoI66mo&PXu~Rpq~=xV*-8LL8oV5cTnr>8v^~bK%Wrk zO@Tfs(5D3Y8G)V(^l5>9R-n%a^p-%M73gyU{hUBQFVN=&`UM9y&wfFmFADUF0{xOe zUlQn-1^Ti;zar4D3bZ89uL<<)0{w#kp8ZXM-Vx|sf&R2WR>#DA z`I=z&b%FkjKz~-CZwU0~1p4y={RM&kqCmeT&|ebhFAMZdf&Pj>e^sErCeUvS^w$OY z8v^}Jfxacs-xBC=3-osc`nv-CJ%RqdK>t9X-x25^3iOWz`o{wO6M_DzK>tjje=bnk zK__OH9aJ~_OrU=uP)4Bl9CUH^UplB~_I-h#3-oP)41s=EpnoOMia`Hbpnv0_uG#Mh z^j(4etw6sg(7zMt1A+d%K>tCY|0vM+9Mm`ap9K2P0{s_({;NR$O`!iS5E1A@fqq}0 z?>p$!>>mj90|#B0{T~ATPl0|Y(Ek$XM*{tC2c4V!KLY(_8znB6c$37NCEg-&g~XK- zZo)N#Y$6@056##JeTlBk^8|_et!Nc)!F4Bt9r{mBiH&ACma6#788qk+@dk zqY~FiTrY8h#K#{z_B|anZS&3UDJ|}Uj#OEcxAaR?- z?GkrLd{N>~iMu53mbgdaOA_}=d|Bcv68A~mFY$oHgAxx(JnY~Ws1H{q9+7xd;xUP@ zNqk-68xr4?_?Em@T;kgj-;p>V@m-075>H4xDRD?*P2wqurzM_|I4rR>K*4x) z9LndO!=7?P;;6(iiQ^I{99#qbz2e}bz`DdqiBl5KNjxv{g2eY7dH5RpMfaD@6|NwRx(ddj-_2w}F0je`Mq> zPxMQW?k{<08X@&dzsx0_zhDPavtQ=-O#T&#e^ufo&eN)>8wBlPRp`L$Dun!NU^>W5 zzaH|8DmB&LqmBk^JVwE_SU4U7LrFr@li_4ai=}|dhvVT`O4En+INVPy)@(60b%a9k z*s!imX}T7h)RKm`LyrbibGl}z7vnL_DD2gOAx$^R`n1JxYvlNGZWms=+z+WUwq3v6ed9zIbrm#Y z9|(p*-}69z)TlM{3KGG}ypGFf};?i7ZUc(8SWbnv7_{SW*i_ zoNAH^e{CBsGv@Ri^l@$)6dT3beaL%y%P5)& z#zGOAkBhomdpnu;Sh6G znmQgx&LwE> zQc28bTQa3XoE(wTDXAZMlSgkFnpDR0?k^1CaeyQ zLAIAAXW|P1r~uQtmQ23u(dkURrrgM%NGuvflW}On_fz^#xM`HrI_a#?yPzTlqNzAk zLafVy7&J_*MEY*(8 zqh;t*NDtF?pdX>`x0t>=YOhZ7!zf@DHF+#?I$bLyX({-8KT34Aj9*KF591x7XgCIy zmvtlK9f?F&Fclmhi3j2K^!UXH>p*-x@wphb1%7M1x#8rv)%23%6DS#o>(k@&dURaZ zrqNfZzYU2+ovswvg-)T9bRO`Uva)gW(|fO7S}EF+DLSxpdb#LmhJG&*#Z%DkS@CYn zcu##}VcFZ3@wTPCZ7XV7M%}-3_?wk!^}@1xA){UZ!-~2iqaJ>zXjyH{sEuj0aYfyf zQ4hWoPOE2@)iW9O3>a3_%^7w3G8NsC=HKr_Bow14Fc+IkYN1KmjQEE(4c44~8w_G| zN?8>ds+wiC8?d4ib; zNJ}K4BTUQ$<`Phv8m-lVI1EXF@D%jAX8#fhCm~CM^TBW=2&JmiHK&muOe74i*}o=@ zN;j`)#}ti2y`*IgO{xQak~CL+I$alHEu`&?u2Pb8>G7KKgF>bF!peq?Pfuqy?8A4=CMf^nCTdgqv?$|!DdVkw-`o7m+q_cR@nL>mamgPja3S>a1Fuq0@>UlVsZ_Rl zJ9zJ2q~8LYAG=6BdLEq!{KSeiFT1Z}6A?8C4?LCb``YAOO7o>=G+#0p)qF6HrC_M{ z1(QCjJdf1)!ZDv)fgP!7C@Jy5=Z5B62*y&rRNSYn)60b!E#|{UuIV(0q;C@XFD=x- zeC&-cXiyXCeBmkIf@b*|PWeJ%9i}dkMH(sFeVs2D^RYREZy_9s_~Mh3b2=4)q%jZ8 zF4-5K^6^e7nF{LAt)8O+OoH>^d^{Xtd4V2HESlj$Pv(P=!!hPluAHD5G1$Wzi{1%! zM5oFEXZ`J>H|ZrrE$C7g>Te~jzvWw=E@aC0Wy+gr{XI$R?@0pnxBSh*57eU9FJ;uq zj9T-)+V~8*C+~Tv#07;=i3kbc zojoN?LW;n#`LTOTm*Ib%Qx7_<>;2$iO%W>|)?=~ZPOpNydJDbmhl{b*?DyCdJr<0Z zlgK>QRXGPp)?pdmWN@B!k~-DvJc0ko4!E#htDxnZRm*ByMr}*0ZG0dz2dHJWHlx<2 z)mk=U9bCG!tkz}Jx-|c?e0{JLrWy^Y#e|k@=z)27uQ_)unv4XKNtg}ieNTnJbgIIo z^F%gRH#^`-xMzLnxWVeg?-$cD33-+*E2qKPWi2^M#+C_5(?Ghv=8Zgi1t*s8BPC@` z2Nh+B#x?5`%73V2P5!J2AJhuV2U~N$WKABO-lewKWKS7W+w8kp;n0jTKV8c0{ZQ|m zAzNeTk~LlA()2gGHa(q4gm#JUX&if(Qrxb1P=waPZjZJ$HR4wv>&=4Y0!9N8z!t+S5Wt%J_<*=M$f zo0cq}`5pS38nelk{m4VP{u2ph#17?!Q&7j<=Ex^Mw^y>qt+mQvEx&L63Hm*5`#o#L z<0H=;e&nG{eI%jK zRUrH1NQ*NROZFpAi?jaz_&H|9FGpIOp;)pnoEEF*=Lp4F`j%`~DED~2LmjckyRX1a zr)p{)bE$&txfD}q6%PK$)9}4NgwKQW5vFwkrEzS!#aB%=sw$mfKG?`Dv=F<0+E8af zQEhkwff%eC0|C$#B_d(aEu!+(Cd;Gq2Ai+kP(`){RkMlU<^-3y3Yo2)Vhd0H%;lZwoHNz6fdfbRzcBc@!KD++m4`Exhu_J6XUjYJnaaB54fUA~^{;iUs3o81 z|5$%|^MR$VWwizt;%T+UT$aD|zPkUJx_`x6k?|f{@$UVwAfK+x;X>%;2PMj;?Nl3i zh+W>yU-52uTKvA(_sr{Cs#x|`XS~&E_Wj`C@s+Y|nX>aFKd-9rLj^9dz^^KNqc@}a zV1ZwCVpZ$?jm)|QT<@o@_fyyV3*YF@sC&S*?-;W_3)Vhr?W5Md!Z*4y>h85YKhVTn zp99wisOtmN^?|}SdNS%>s(S#PgYWI#nf+&%)s~Ffl2%)oPBrTu$nAf-I&+|TSv{Fi zPo~wAprb4Bn(B?c@2l0%)atjVGlxz)^sZd{!L4JNL!i6m>t;(i!mYy&H7<9WTXEtD z-V}PTse4(4g!QD=o)yb?)AF}=XPQQq)zOSPnpQ`%t@mb{#+KD<8TDFPy=GhQd0(x1 zrdGXub6IW3s10egA=~bDruy8n+L}>Y(`u`2UH!gV_e`yOuf8Kw?-sIY|Ml@q{gq|4 zFQfLQ)jr$#q4(ALXKMY|BbkQ&WpyB<4y4rq+xm~^+RE158E=z|N@`a|tzTA;Wz=J7 z_1Fiz5$#`s;y;p6kEHn*wM5V|txqACm`37jOe5jcQrQoqvPMAFa_@LFW$TA#>3G3D zOVt0YPs*{5w`H?N?jSV(CyI1(xg! zr@(TVBL&V@V#$8wp;+bYl23biNrFyf-Fe2I*sWVSN7@}Bzi^5-@mS~Z+sEx)QoL5Y z*Yew0Gc4JUJOy;-X?|vNhf>XDpq5&_ed>_oE}iY#16w?F7bPTRYCQcicRtGaX8O77?rSM%c%p2Jph z*UnwRL#^z1I&39(7gu%Xu$A0(t?JHU3-0LSDf5%+a$kUFG+n_Biy1vvj4zK60E>bTMRpYzs6|p``k*=TFx>*l{iEa=}22&|rr?Ul?Qk|~IbvjYf z>55<9Krc+s04ff;#YPJ;C59dV3uBX=8K}g79d>iER5+@2)9r6MRVvdBX_Fe;L#B^Y zF0makZHaz|-pz|AjY8O2q{Zg-J#YiIlcnIt`Mmituud;~pa_$nXG>nTx#f^G19y44 z>^7TstdsskmlSI(NY+{n@r727#T2)8TZi!#UXCRkw_be#=v+L0;64Ax*p}kR@YPnf z+-{9Uv9P43Yi?MYNh@*p6+3Kql2-8_6m9(Ue0qD`a#4MzsGe#y4zHAMNtYg?7WdOT z8kUQWWr~hbi<*_v%5>=wYLQBBt;OA0)S`N&bW^&tidxL2w;f$Bs>>ABF$Kv=>E?84 z^{QUEhf%)$%SFrOzD&7~C~CoZc6l?ObQWh6)7y0CA8JXF*;WC)kh--yEm&YHI-Lh&&qY@jtoy&+ zIo3_G&XKMGStn`~PR66rcuc1c{IR2=IzQadSc-NHs1>IDl~HEiLWQxum)_fG-lH8S z?EBMw^k$(J3d0svTf4T*Q|Z0s3GRQdQtHV+pg#|+W>@(>#)BD z^}JrxR)cK=wcQhm!%i`+!SO)BvC$cy8_*dLj;88FJRV^?3XMYC8;gTKn+CAi1Dzij zH8%zVLt_DmYCzg*9SSGuHpUQaK-Xi?`izQE*j65!79K4aTY6x>TuQvRnQHyTTiXY; za1ro{0&Hu)=*50fVju{w zBj}|6O*T?QmL)F1J#v0WB32Zy%+%M>S}}A=vuf5er9Id^_V2*pV+MtZ{W=m)tty z?!rZqJ}GjEh#1?=R7ku<^RkKMNOpGY66}(qLz-9U5VBIVq6OI0ACKSbNR80PFIk1O z-4<|hxmwZF;%&-VytMi?4aD`t%vex|8EbY8rnS6@*K#POxSlOjO=ZTQV}RFQ#^@^! zQ*k|-Ek_-#ua*Wj5G_U2TGnh!in=@ii z$JcT-9D#mabaT|eubx@GsjJ2IeBE za3ZqkD(FMOLFib55m$*rwpTC%7@Y}ErCj9>pj>w}4E@i%<|QMuFG&Glrz}Ed6;ZSO3RUd0m{@T1%IxybfbM<;Bin`hzLpv+)`(|{xdlt*#gz1^H z9M*JHhmNpJ)|5VO2f@o{O*dxt@v>S|z6rx{l-rt4%tT-rt|{Gu0l1atnr=^`Td8c< zbY|A;HRa^?W)`?u&Tj3^RZwVet`aWo%~einZ>}=g?afupj1-oYtHdhp%~jsLy}62- z?akHBtany>Gll4zzPSbG;XCUwyvXgW?Q3~!+%k@3Wc*uQk1H-z2v=SP9Mz{ z=~8Nj^j zsF{nF?#b|(w(u4o|ot;P3&aEHREy`)mDZKSfm?0eJ5k zbRD1?OU?v>me#~z3Fne5nx;<^pxQC^IQ?i8{K3ORur`K{N%3J9$YN$i3NL0I-3R-m}s}L)) zMCZarz4PXbsfNn!$97k7@P{RU$HQ52SVMCAxZmlci$n0c$tfb#uACKiS57D3-x;T+ zTP?}y?SZvig71zJp_<`!mWU||?j0opdxBr2L>%H`t~J3~C5|?kGkK0&lbnEmb#~gD z;C=V_y+AOPyI8lmNrNwq&ik6Bq)O)YX=g4M4&Sn#MdVB(_btl>_{RIDq;pp`Z+Nhs z9s4*}TeCkoy0(nnbXioOD-=9LFm||kL|-~cVf}J&|ruxxfT?Y2}ygkgNX5iEvo_-iqObhGW8|Q!`)kJwfVZn0m z9l<(=67ZcWU<2^RJ3WnrjTDZd1g!Z845@;1c$fe$ZWgQD|mzOpnnr1!+9zVI2-wTLB03SO_?DVjV7yn?W!aZ2QRC(P9$-XCkcJa15-6 zT;lE~ci0&L9%VN{)=ToV*)eq!<=J56vWpNeTNY*G#QI_@I${HnGasCT5zYguT>QP?y0?ZKHe-cgq>8bID>jK*Ut)M6nxhi02hQ4> zJ21&{tFsu^PN3wP*P?YNRdUaJtyQZq_7!|=SXU}>(#OkS&14yTC|Peh3|=o*jkuIp zw#HmX^^=^PT5kzS?s$b-N17y;JfiSkWOy3RxTA|yYvRldY-t8_OgK#p29Gd3YiAKB zw2(e_m>F|40j(~8zQ9J26g`k{ItFjtg(s5+n;V0)nSMr>BBIMZWPWY%V<>Bg%cr&$f)fRV|HS%`no(>lWJmEQ#;o^d~)SRhsal;nh ztom7lv2zNZ?Sc=<(ugEFa+wtKQpuHm7bik`c-41ivWpwn5oz6#b1TXm6L=m_j`ZYk z#rvCFg_^?|FQwcio5NvN9eu%N#u_Uq*E+gt5JH*SeZ;D6c&6E%v_oByyOZWM)I56% zx@n;vn0x2~pdh6^cG5U+jy}+#!PIny4hDh)_bi50tTrFk7P7{KCN^^98WWr|bJx`| zYFAmyWToydBy_pZMBJsa=kKe_(PrQ(VNS#NT*j>XtBErGr(@h$O_ofLr4g!#CSV&i#ST~Y?aGJq25auDu7+iq& zknqR^j;Wvr=iy@+mTK%&O-VQ|lWw}PBFHAvmU4zE10cNSz;SE$@Yc(nw}z<>Ogv(m z&#jXXlSp`K5qfRd!HJW0gSRNyW*7_1>5)J<7Ff_G0uy?C0S@6c_}rQuH)sze5JZB$ zFOakZ*qNSg0=&y&@kbp7J1-FS<0oLXFcF5cT^6l0@WD@(hAxaAtnKQ?QVG$MwLxP- zA4kDsIu;q4Qg~bzPin@N>v|OSIhzM(v$vv*3VUxhD7UB;s7?>tH(@FTXJMmPe3`@6 zL3BJc_GAe{ErM~Hu7cn|?}J&^mUbAQIZ~m$mQc_L zg#(o|9$_ltq*2j*b9iWEEHK*HJ=kq-H#aI>ZU#|h3>s(CM;OC{ff+550JXRtW!cij zj!K7Zxk;#`{j?G~6uJS}EN>mBPM<(hA$+I`RgcvZSBY&_LIod;ivBPh!cKSDIkL{q z6*#_}SCNq6p&-364$j=VxfPH<6zCNJQ zONd@3>1CQ;=sS>jD3MA}Y}e^IXGVFz@pv~G2(Z@^jUxUM%LtVz1ob&Qkj6(SPy}WS zp83LF{$Z#a28#H)BpUMt3b&y|oSXkruz-DXw^P=UctY#d|WvdtNIfg+-p7 zUsQ<#KTDPDN4``ld8H(;*t7Gkd7{A2QWg8LFCXTE#Ophm40(x3Z}IH<)+wUE&+mlT zkA1PE!IIQ6X^-c~5d_G4cxX|RMIh{mMAQ~%Z!QQ(J07=G-FB~9MwN`tlC6xknUdQXy~OA^*}-Thqh_*;(QZa3$sR^~88wl8 zjC_ph$$mx$7Z$>Jq*v24i97a``=keOd^MnFB1)U3b~t1BhMfYk}xtHghkWSNA4j(xt|On4kBePk4QjJv;v zd>wg=+(5pGJVb6G`;ptp%gE!%=gDp4JIEa*fP5FZg#?i&xcf=u5OOQgkf)H_$Tac{ zcOOQEKOI8LtC!qEjv#lEC~^$BnZ%J3$bIA$WF2{kB$45Gcl2)#c^-L?EFj-UzCsp} zA0Q8qSCJob_m7YtBVQ*^klXW_|5r%|>!Zm<?7?esUFg1o;vfMIJ-$AlHzuBe#(o$TyKMlUvAsZvQg!IC3+& zjeLi50QoL*I|(9BAa{^Snq9IQqpCQx8Gr;gSXzEEA8UA2QK?(eo0CEpGg4{-; z$T8$yB#xXwt|zY`!yy6%8{v-%kR);n82mp==8)%+>&XK0edGqRi2MM#k-Uoh5V?&! zLVk>ViabGXSDF9kNQa8;AGw=!B6lJ8l5XT4;BxrmJLD2_FY*C$8TkrwE9pb-M?ORb zkOz@_$Pn@{awEBlJc8U#Mv=#mYsod_>&TbL4dk21P2?7`ANdS<8F?J}0J)8P2f395 zknbWNB0=N{Wa$5qL&&v6L!LrDN2ZZykgG`;84fn2`O`-3AxDsFNEA5+499%*kvMV! z`6PJ-84ijlfa5(*k|Z)5HAMLwnM0mO?jj4w_mNMKMdSy_$H}Y650NjDN63$Xx5JSb zvoZ1NkQMd2$QckK9IHMjl6QB)5_8AfF%s z&Vx^E;&vLcTz{k$aHa$R*@nE?j-}rgUFZ35b`i`AGwM=f_#dM zB99?M`6FLPZXq|2Zz8vnTgZN7D1YQ}3?5$e-(Lz+m9lTAzvidkgp?mksHW2k`7D`6o&nza9`x5?WcY(Ol+TcR z$PwhTB#InEK1brn3C^z|!x=!-{RNUlhCixAxsA*r&m+V9ANf9V7goba=7-BcCFj$X&>%NjGv2@>y~Txfl5&xr}@T8QMQ`KQhe! zkq41`$q@1|@^Nw%c?9_+8ATpLK1Hq}Uq?PeZXn-8zCdmv`;pI*myyST%V~dl8~G0M zX%axbi`+_r$P>uW|09Qx>xhOt#obRM&j4?EPd!Y+$Z+6pf%iT2Ai0MeK|VyH$T8%@ zB#xZm{0cIhSx4PBlO%EqxrNLj&m+V95BWYYq;Ef2M1FvLfV_(Q5E#bmGvpESW8?<% z1i8JK**B98)V*9pK1Mo`yO2+jZsZ>1Dslw5@2J%hLw~+nFr^w65I$g^Dj9&!X3#((4(w~sUaaF^ooezNkpTKsKq>6_P{ zZlFKcpO(^}v8N>ty7_b?rP~?rF8Vv3@$Q7*blIMacdx@DT~-B$*OQ9k;=_NCzX1-t z&o3*<`%vjFpt@{&HO>7cidyu>={MTmntGPMJDtD#xq2wgzRN0{LrBfvRX2QM@Z*Eu zEq&>|(sSRY*H(6|W!IymxS+V?!~7z8us&QsZ3&mkHct&v_~k=p>dI^N>?8`md}x{2 JJ@)wHj{pJ}n&|)l literal 0 HcmV?d00001 diff --git a/blender_manifest.toml b/blender_manifest.toml new file mode 100644 index 0000000..9c65819 --- /dev/null +++ b/blender_manifest.toml @@ -0,0 +1,26 @@ +schema_version = "1.0.0" + +id = "vrm" +version = "3.17.1" + +name = "VRM format" +tagline = "VRM import, export and editing capabilities" +maintainer = "Isamu Mogi " +type = "add-on" + +website = "https://vrm-addon-for-blender.info" + +tags = ["Import-Export", "Animation", "Modeling", "Material", "Physics"] + +blender_version_min = "4.2.0" +blender_version_max = "5.1.0" + +license = ["SPDX:MIT", "SPDX:GPL-3.0-or-later"] + +copyright = [ + "2020 Isamu Mogi", + "2018 iCyP", +] + +[permissions] +files = "Import/export VRM from/to disk" diff --git a/common/__init__.py b/common/__init__.py new file mode 100644 index 0000000..3822ea3 --- /dev/null +++ b/common/__init__.py @@ -0,0 +1 @@ +# SPDX-License-Identifier: MIT OR GPL-3.0-or-later diff --git a/common/__pycache__/__init__.cpython-311.pyc b/common/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28ae0f3eb2a6419d697df377b19e6462a3677f80 GIT binary patch literal 224 zcmZ3^%ge<81nkYWnZ`i+F^B^Lj8MjBHXvgj95RZM7c zYEf~FV@hsjUS@GgQDRAcQH*0jflFdZVoXqeB2YLz#wjN?FD11|!7aZuFD0=gGd~X| z6l0=i8k1U4lA2cx6fKTPf~btoFG`OoE6R;Y&d<#Ss*aBbnqCqguUAm{i^C>2KczG$ d)vkyY=mwB0i}``X2WCb_#t#fIqKFwN1^|3eK7s%M literal 0 HcmV?d00001 diff --git a/common/__pycache__/blender_manifest.cpython-311.pyc b/common/__pycache__/blender_manifest.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73579ada321647b694a22cf0f5fcc8f98da3cb68 GIT binary patch literal 4043 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 Hy|?@YaH8;o literal 0 HcmV?d00001 diff --git a/common/__pycache__/convert.cpython-311.pyc b/common/__pycache__/convert.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a78095097f8f880757e74501c9f6c9bc201efd9 GIT binary patch literal 13785 zcmd@)ZEV}r9u9VN2l zka7~I@~XDMs@%L)Z7+>hG^>iGS7+A^9*%H^(Gv7w{HhcDmvc|Z7kz0dQIKdG&)q2O?TV>0q;FGc+`-V_hsEIj#Z zmZI)Z0wvH4D81;IaV#=3%pyC((pbktor|s+7b&w*_aZmLEqZ1=aPJgc(V9hm zh9_lr)Vo+aQ%h40N~{&@-lr+*12~Oi#w&URTJ(waVuRQyHVIsNv569!#YTafca&@9 z-R1I3i{KIcLXF6Y4$)t(FPG+7fxpSlvK0J}qIG_jk+hH`7U1b9t=w@qjUycW@h1+&=h=Usvya65%o zp-pHP0z!wdP3ZiAYo<%+x=D#$x$PwaS_gd(=BWl8-#8+Yv5U2LJ!Q) zQ&HCob-hBLiNgvz;J#1jhx>t2znxIGqoQsQ>iUIXsoyTRAF$vM3R!7`j*FNn6DA`Lcd+YK2r`%-U3C~ zGOx-d;Mypxb2q^s5vyVYJ*(EkGwz4JL&BJSu4l^8IAHG~*rl1QxaE1QwJ^&8=r=4J zw9aCswe4vR0qzLFHRrHm7H6>5!T5)v&tAff5zy8eu@UNCfVzFc5s|fWrP$xDD?q~u zz#bJQpTf5F2E3zyw_iB+T)g9eHzv?$so>OO6rbrJqjRSdq7+WVCEa}{ytEXFE$G}? z@yfCon-hbyUNaw!hZCVlY(5@z=-lf|iAX#aj_S_yF(^DnYXw;RTs(GFloFwEYy~?l zh>1`%zOW!lI{T^|kLmPP-6e^MWhpjSGH}opj48#y`6LG54&|W|mewR?H;Airtf7xe zH~`f=c2E)++zViG&r;W@>&yk}8l7+!TPf-ij!ljvZ6E6_b)TLNvN{`qr`J8_R+hw5 zk`$LD+ye9ttVNoH67f*{olD{zP{6DTI;2{};ffV9E~vZvSJI0w%$}D;NuHe&79+8U zoFGHYPAx5+3@5^~Z^pw=y)b(sD#ip+>V7G{923Gw&SKT<*zowQcs(J;WT=&A-!U*l zacN=psr?dH&E~>dLOMm;| zdk528n)~<>-&~+*rv>DFP3c5BQDC6<Kpu|+!fy}fr@hLHIBpoRO%MHVu zN77NrV5uIOfWLSo@_oKbr{UO2!q& zEFD6Hp%ol<{RT^5G0;is8KW?E>3C`s$EO;Fea>;F=G4xL`n z=^H_|%y6AEc0$-F8Q9*SDG12YZUo3mX&8Wvq5-DEv>okWwL_O+{|jA(EhH}O$NeO+ zyc89seSmlvdq@CM6qsnQKO^4#g39-6e7}YFTz#hHPWyM-v-`i@^5zkWNul4m6a3}mVysJ1mwW4As}EmzywrUjtZ7PB_Nk!N}%6h zlKynUK-;&6XN|wxj=Oklnz-S;!tldt!U|3=&Q9|xe z3uq-9D|bYJvg^sW9cxW66fF%wC%BB@#Ub^

$)*HJWpxSJUUa92s@2y;>5u+d@% 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 literal 0 HcmV?d00001 diff --git a/common/__pycache__/convert_any.cpython-311.pyc b/common/__pycache__/convert_any.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4bf65917bf160be81dcff4b6df5da6283d7fe344 GIT binary patch literal 1561 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 literal 0 HcmV?d00001 diff --git a/common/__pycache__/deep.cpython-311.pyc b/common/__pycache__/deep.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8426b5def5430baa0e417d03840e4de20dd9f87f GIT binary patch literal 8179 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 IiExzv1uu=$6951J literal 0 HcmV?d00001 diff --git a/common/__pycache__/fs.cpython-311.pyc b/common/__pycache__/fs.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb23d2f156d0be63c7797842cac1956fbf4e2eba GIT binary patch literal 2155 zcma)-&2Jk;6u@Wp%j>VWA&Hx+QL|D)6>~^AfG8<#l@e0aN-1hU&|qY3ypv>G@7m0c zi5=EefF7(WQd3maNPv`632F~L_P~MmFR+m%td$}~;=~C{xkNefW?kEHn+j&fZ{ECl z^E~@Jzvo|~(GY?b`0lLvlZ4P;e9~%x=gRJ9pxj3WGH?dX@lnWNOPCWd*TsxzNplkD z5)llU2n&*-+>+*GBj{TKL?X(uR!ro3D294Vo(mXw79~P|^R<}-_N0$=wgjVkCCALH zt!F$b2NqAEgypH7#_b>o$)Jny*;T=MAGzpyd$EKWUwPgbyj81RZ`&Whu7~Y-Q|ODC zlHdwdHn1!Fh<+AqYzQUMMVkk9x1u2AVpm*&X?K(o3c@)y`N>{thWJS8_QuFQGJ;s7 z<2s6{h|x8)c5xXM#A|37yC@Ago`sybh@Yw?u~^67eIeqvIHAn!<8cpt3`q>+bV_XI ztc*?TW`-CV%W7##bVjtiZGM?2nqg9sW?5R)c$O!$gz8DQZV^wWy1hs|(J4A!z|sqj zxk9|)vdNZG&2{Sr?DYayW}aGWD&>F z7m352G~V{D_a~B{ID|UMNy9R26Wnw-R&p|zo6?z{yqeX)yqLU@A+|xNHVrWio!^j_ zDf!m;+euPj#CE{yBZinLQ%hk|uEi_z_hMm{oz)$7) z{LtON6(a!~c4TtB{XIIl`9CUB^aHjYXn>cCUFkyY~6&^x;&+ zI8`A24^@xj)f4YjW2bAe(`9KV+*>|Z?>l<`%=c&Rp1pS#D2fi%j~-tS^9M+3NFDYz zWzOEoTI6KK@BhVKLqWmlpX%Tr>flDas%kY=tEd_<-XwCTXX5cxrDp>A;Y7X>zkr2j zICP;$eip?b6L=<}`acq{)odwa&Qt#X znV%?36k!3PC{c{95ygoTEJ(CLlw={I6j7S36J?09EKIaXlw%R1XGG6glqgSBU@@X1 zQHjNgwuoM|p}c*^FQhEoxKC8AH@I^l-2_i--A=1osh`%wwh9Tfyl5SM?1-wsDS~uf zZ&y$2;_;*H;IBRqdGZ8|E+rTUEKGeU#)jkH;3@QMcnl)JDt=Tm5vH8u_%B= zb+OVC+Z|Qlh98Yum0PM%UT{lnin!s`H)KBGQLS>;>~gBc{;VS`!QQDCvH5G%aN+}4gO&o zZhrgWZnvjt`lL5eb#2`38XlhVa`AETbKzgOvBo9HCB$W&OPEW9OO#8DOPmW{D;OIn zKj9t~9)?G6rSq|3jHQY^R5f)xF?ti-kSe3mac|O-T6z!dzH~THG+8kUC;EjZ(@;xG zdcC(VDPJdwHs+&BpB^i_y3v=u7(?l^J{;<@x{pC4gLX-p+p`4 literal 0 HcmV?d00001 diff --git a/common/__pycache__/gltf.cpython-311.pyc b/common/__pycache__/gltf.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf0d06ad5f96b033c9ee14203b73e71531649004 GIT binary patch literal 25114 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 Fe*gu3Nn`*3 literal 0 HcmV?d00001 diff --git a/common/__pycache__/legacy_gltf.cpython-311.pyc b/common/__pycache__/legacy_gltf.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b6b2901d883925ad40ce0860f0059aa2821b108 GIT binary patch literal 743 zcmY*XO>fgM7e>lakt{d%(jdpKY^Q2D zA@K)x<0l|~0{^1BAzwLhE81-*oUm2HvYx!p>o>2TJa4{Lt1d9B{N+{r!vf$}M($SO zHn`q5!B@}+7z_ZmuuZMR9@rMZg+YPX#KBI-RN&&En6pyO%7aqQDmhy@19kV)^q52_ zoOu!L9eHwuFcF>_A?1;2EEU1tkX&#Ecn$5Uo498gj}7 zRAg$p5M5$iB#7!YlEhNR6S6#c$itAPnVMy4y?6Mb*Y6&}cc<_BJ$UM$9G=w+x{?ru zD2+qCB6u2&7?DyJQ$}N@Yv=y)f91Azhe#55kjc;wme=O8^ji1rzJI^|v|iR_2r&;K z)Fm|=$1D=rd_={7u0eSb6}qBs~k-r9+~U@0&YO&OaK4? literal 0 HcmV?d00001 diff --git a/common/__pycache__/logger.cpython-311.pyc b/common/__pycache__/logger.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3abde519c9fa6d65dc1f587a26d397f303e78f70 GIT binary patch literal 2958 zcmb_e&2JmW6`$qqa+lwvMACHR54w?^QnD2%a0|qU+E^0F29>Bpi4BBdu%Ng@g7Wes zvnxe17=UO6)GgB1mm)%K142=_3fw=S$DWEFdLWGjLJVL)Ku*4GAO{H2L;GfzOG!=) zDROM|9BDlf+=nhhv1+G;8Ua`mD5nsd2>Y$bdTm~ z@I{_uHeM4NVo|iQpm`foQL?e9$qir8*YFqpjX*JA+c+&)3}T-iz}#BM9ZvP$v_~Z4 z7_Eg}E8vKWPr3jV!%gX^S265Cd8A6)NR@H;0guo_c$`v zP$u|%h-3gZ0y5+95~dg{2|7Ydc?EpInv^*3WpjH;Z*}LS`hjQ;t&>& z`X2Fv7B#GL)v?>C%BhjDefRa?!)R;`A~HMQI}Fe&7oaInhH z1S;dric)V@Thy-`K;luX;SCJ5;Z1{-spx2YL$6VxOlmq|`<>wng#w8JA~7b$Kv3_^ zkC+4X5^SuKX2soN0UBj^*oOzd0`VvAQ)IA-49nUGcen?DACB~oeI8`Efezje;CbkN zhSuB>P=`~wj_)pne8+Pa-4|+}j`SC91$Fq2&=EUcmA@x+sVNsnCsH6dB5O6eD!^R>bqfl;OD(dTPOehbnnE(}ZtW^mM9ujAQ zE$$gYNP^jtAgJGFQE9S%e2P-h%DS#7It#}1sC2*iaQnuXwAZd^! z=n8fS^#6eXuH2t>3WZ{WiS*!wiNWP7*16Lnkl>2_$e1NE1qg~;5<@bICM_RBel(sM z1fzD14WfxV>dvg0%MnykJIOvUo0*dCK#lF!T|6!3udp z6Hj@0+;0U~Z>Lb=q;;C1GboX=&N7rn(bSH#%kSRU4VbBmX5^AHzaOFTlh%vOV-oqp z)_I0TbN(KPoO2nW0^1RC0`$u0OoPJ6W;7rC8LZFE1?ZVvz!@x)49nr!UmIEVl)+Av z>j4+0Q`Bd&it4%PVJ+m14!6tZ@~vX9tTrr$3*f!xa~1f~zM5U#eIL(I4`7^!_E@a_ z_!NFI&B|9>W8lt$4+L! zegz)=E{HCA9EzKvGdo5jB#PBP;Tb-cc%(@3SIX^a6#-81FY zij#{xE!|;HWQj|+vlR6LhO2}R|xdsTMrfuhVGK( lJ;On^`nK3v`jT0n9yTp-UhdMJcPs?2oe%8SbA?UL{{dabuu1>` literal 0 HcmV?d00001 diff --git a/common/__pycache__/mtoon_unversioned.cpython-311.pyc b/common/__pycache__/mtoon_unversioned.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bfd9af5e7bef6acd2efacb075a82f13cc5c1cccf GIT binary patch literal 2961 zcmZ`*&2Q646dyOvhm)pBKhl!Yre72YECm+IwonkIrEH}QtQra>iZpUF)7HYVv$j); z!~tpd4?x<(_Rs^D-OUOP{3!-i+Q=uQJ#llzo;dBBahxXI;*4K@?>FzwJkPv0_Mh>1 z6u}k#`KIzgLg*i+_?OrKpXUJlh6o~pipoMk5E$-IJIaAVpezp{ugg3pZ5ed zJ4FS7phCwgL{SJRFh2?WDiDzbL54^eWQ0f{qa+5hlf*%Gkp##j=?2+DdO`M)6v%!u z0P+M$gB&C$K@O2&kQp)pa+HjL948YXPmuupCdq03&oKL)*^B)y6hs=NAsVKkbTjUa zjzdf%NwT9N?l?oB6|vvgfs z)wZc&!cJ21X%xnC;yCvZ_(vXl-wES|s-nk)R7Kh4_=`q zs%+EzmQ3_#+_d}uR1C9zFj6)wC)$D=9c=#RjSded@QPCYLD}50AP;lOj?;BSPcnlg zgPIyuf7G8*!$}+^BHkD**)`()zlEwR%HSjPM>$%ha6+Vt1R4rA}=wpRgTTW-2mi9aOT9cf-v#6Mstd*!U z&@kjZtsT9-PwRs9G^|^>F1)%uuPNnx$1m#)Zd*0!bXl%jS||m{y)z)ryneP<7eD6+^F>nC_IeWNnjTqLeHr zmXj6jA>Fa626Z}l!uneBzHXFdwJcYBCe@bk*r$726U!%)cgu>&s;_C5%vZLkLFWna zZK9B^KJIN@W1mdJX0UDK+kkVj`P3gR8+9T;@YvyT+X9d95{9GQNwrt4KWtxHarkT} z_Csc_QQQpIiLv_f&HDV!;JfFuJ&nz0G5Xw~<*h4zs%YfMx_2%r8yi)V^8Icc2p*36 zQFv+uruL9uK3vNNoe=i;#?j&_UCoE^bcu!T!Dcmj>c}<}vTopY*`&v&#$dzXn6$|z zVD+&kmnp`uQn;*>s>*OD#y?eMwb2u99Kgm59KS|@oxuUqGK?TY35;b;Ym}IYv5{j& zYfL<0g1zn?ktb=WS|M;Y|AjsShrYa6xL#Z};S?{-c5=Bz~s~2vJ;Z6_78SX;TpndYZn_x;3Nhj^03vM@4dXUunYT4~&xDQD~ z_V7hF#gu*|joIU~?f_FxAZgs5xZ$RmGKi!TyBYT+!$U|qWl!F6hnbQ=QpO&+;*Kz7 z6iMmb3+@=h;~t)1_!JttRPP^TZTKQ*+J~zSH%wnfmB-{lvL?|JnM$1jCtGHx-)(dl0sm zc^$3=YWZ4ZfAlg?Y#a~=91Wu0G3GRwt*1s{JU14)4*ei(apLvkTK?TcZEb(@8c@s+ z!~sW1GpSfFKAT(S+UJ>S)qFuDPKZ;f~;<(!dh{ literal 0 HcmV?d00001 diff --git a/common/__pycache__/preferences.cpython-311.pyc b/common/__pycache__/preferences.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2c39043821b6b4f47e96414c2c0de227e2fa10c GIT binary patch literal 12888 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 Dg$})_ literal 0 HcmV?d00001 diff --git a/common/__pycache__/progress.cpython-311.pyc b/common/__pycache__/progress.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f6e0ae45926587c159e1cabe45fa7a903269dcd0 GIT binary patch literal 4776 zcmbtY-ER}w6~FUkkL~eCFeM=*!Gwg3X$geTjR;=~VIj0Dv)VwlwX9B^%p^GLkMzz2 z*eFPm%7ax=l}cNYm8g`5EnNf;d8BVu{{lO*#Aqa>sMV_F%~4nh?NiUWu>9p=duq6O{|E%=y+5qKISF*Xu{5oO0nn=Wc$E%J!dqPn8R^gUXe&g*Ua z-Kk{8r|r4tdkp=j9xol&xJiR(8M4=s-E)`Avj#`O#VX~9RjLpwq z%9`2Cr=={gXEPV`uyvg#E|(UH8opD}Wo1qc{xkz8rWXz18ks3aQZ3Qh%q?2TOqU7; zkakryIRAw$t12vIs_J6L4wVkNBWKv}#WwvL`Fi#0i64V=chr^4N%-=^ZGX0kTY9#^Qe(UlCSr{PEhC*H$O1v1BclEK8QG z+z-EyyVm6{ONrH#J}VM`VAk4?t%*KYUJvsz=eOtZ3;pl_?iHzw-UM!7JxT^ zBQItPx~keiRV|dXg*>(uRsGFEHs2VLX7Z)1Nq+=0*v6j_HrsgsV6^U^+q6Emw;aRP+NRejv7RQ@>-2Z0o^%)@Z;a zpck`ZPuReP0HquYK)YCMbAi@Fio?J*l0cS;)zc3+p;&!Gh!34F4S+++<4-e!Qy^TFFS`&HO5IG;O1Qi|01l8SCXUE#F<*+%=5`=*I2Dd~!I$*Nw3AO`e z)%8B7+n^dm#U^Dp{YINqG)Gnp9!=InRX56{_sjkLx;30Av@Yu&@;)CNRV zr6wPKArG(1!)vLkJYJK>EAGvlE*YT*;U#DS38q1g>e1$H0dh1us;b#yv1GDT%urQ| zDXuL}l}dRhfcD}fh9syG7EkG6Y+*ol02OVIg_Q&}jK@Hhn=b3zwxUE(kfV~v3r>-SUV z6>#_0pKwl8LDO;Hm0>6REsC`0SY(AuH3>s4j6 zri@mU(Uvg;I%Pu#$hTtiQ3nY2=|N0g76FBwF8v`-p!C3TS2l+?G$aqvp?xiEZ z0^O7#s6h4!A9;h>scDKq*$y@`&wOr*qNmwD^NV@-V5E5L)Q1G)1xx$rDHI4mlo$jd z-C&qSF*TtWU>(F`ki|~>Jo4}WcHq|c@>%Bt;ylHpLH{*A0tzp|aT_GG%r1-cRa$S0 z^jBJMi}Y4@yDhS>(t2-@;4-@`(p_o2H%L#V_1*}?%bgD9?Wc=67qo2Y*IkAo7!*wCdfdRP03h!kcYv3oW-jKrOn>DGuF1Zp+ Rc2j`a_j>Al3zuQ*e*qu5`fmUL literal 0 HcmV?d00001 diff --git a/common/__pycache__/rotation.cpython-311.pyc b/common/__pycache__/rotation.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..88b857b580df274e8348bfbf44f88155d57dffb4 GIT binary patch literal 3537 zcmb7GO>Emn79NT}A{|L|V%M>qCYIBQx-#mU6jdmeu;SbMce+BL*GVq$vU>^Smm`~6W(vZgFP@Ykkd`Jl~ zWE{$|c~0T-yu#Bln-lV3B@8^L@i{RsDH4N1NSE}ky9`42;i)%8)C6Up&gc;>JOv_6 zRHAew(NUKYqoaLv6wyOEr}Jx}0dG3eqI!6Z(_$ZSimY|g%X(OgYTavswjXS|JK7x3 z_cv^Mz~+F~eFY_Ye<5omLM}g-H8MGuUox_$0b^nD+6{fxcE!J$mj1eF=n2N{y0nq8 zbxbUNAzLG&b=_8T=K8vhLA{i^I(vEH&BX<`|MKG1)K%crw-#q+)h10>YWdA8YHDHr z;%vKBph*ZWyS$)*>NN=4 z6|in^U}M$)77#f3)+{`aKLY6|sEBUBpx*3|$077KeAzpGlDgcgS=hoPx+Z;QGi#|C zV?C$iFlaE@z8mwW>l>hOqqeCwIT9Kv&g&SP*yZf4g6?ugCa))W{2Xy0P`8_n_g3Tm zp3BpfEb_JEq&>AROs1DC9b4&?md_el%f=bo#OYL_Fq5$}>C0vY#OvwTbGiYWi_e)G zhDHy=6Q#$KFQ@fQTQ@8?A}f8ZZV73>p1z6m=~XkIH;uHnqhw*r9V9UI1Zu`=+8a(l zXygp6?}5CJY621uRl+A8{B>q0JmZ9Cs`Al_Jh3aE-I33h<#QGJoFksw3lFx~oH$!K zu~-&IwuRfm9ihZOln3rilqT*?ID=zf&X(oLiahCvlisvxCrmnZ{nD;Hy(3ST)++TiJf(Z5d4fL9;w)0@ZtVU6ipC^OJW!z=m_){_`(SV1q{4Lyp@S} zd(aypRBF0{0x4V?L&2!SrP1waTUKqmG{{=GA1o95Faip@L^&>;Vps%1vWlHWN|`<2{}s03qTSa#WDU1@GeKZ;p4zs4x+_32_q^@2Er0e($m=Pb=zkzf@)7aEEqhF1d$1YUHE;uBqN2_9NTkw$KfvzvU z+n3zwOP2diSNcwWylM{FqB^#lQ-Q%(ZPC3#!;(^#W`qXeHM2g0vmxCH&;3ON&CEcQn*#%fUd45c{- zY;xv})+oWO76PmJ7AqeW2tiJ>8VeQ^wvP$O%Z@11T8r$n#VkNr({Dk0F{>l2)U=ux zF%<4lk@VW42zY1ov@K~P$>6Em+iEU|Hs!GpSq>~Sl zb34+UBh6J?r71@uz1n+>*#0cW{uTL0q#7B280mKQA1g;jDv=SIjK>-&De)4dBoN3a zAQ768d)&cY?)VOO{GRmfa}IaB%uQFgX~*j{>k>V#02LUjBqkfgBwt+VT45_m>avB& zcgG|>TqzHyuwiF&R=w88iH2O0uBfV{e5-2x_d!D--U&~|DfkP4pN7})d9Wl1uvDNmmSLDZH01n`UgKCMR71Z{M8pg`DBj%n&=IG# z?@2w|gSX!(ONT4c;r9iA_Y0#A>c2DMpd|D%N>+~o(;_%L@1UOBOAdnfd>PHxgkGk< zI&kF9&C;ebG+G%rU1LGA$ICSy-Zj)pk_Q=~&6-GFd!xp}dykiDJiKeDm5d)?&NFS( UsAy`s#uA23BuowcKT1EqZ%!c)Z~y=R literal 0 HcmV?d00001 diff --git a/common/__pycache__/safe_removal.cpython-311.pyc b/common/__pycache__/safe_removal.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f67a0e23c51318350ae29e0950b3c9ea45f8158 GIT binary patch literal 1561 zcmaJ=L2DaV5PolWwem`9uadS-Nm?TZlvqwG0*+}Bu2VZE#}wk^Vm64??u(JK+7)jl zw+=D{>VpqDw9wKVO%AS$eefYaqldLvhm1eWTK*b(bIUql`JGV)T~ zodSDmWFP56gxbL)TSu&nu$SVEVvp?`U+#X=!To4%Vq`2kFcHVn0rdVT=|4=0 z2vd=IY$k~S&I5e{|M?fd_(gZnb7coZdRPzW7onS3M}MLsW*O79ZJ3~%>%d$IrF$&p znZzL;&yvqy{P3`>Kl2Fn^cAa7b823T8ZDRVE6wJb(K7TWt^wvvebpw8MQHw!+jcC2 zhl@@6{nDZivq~Hfte##SAS*82)VF9uH{C`9(4O&vR48eAep2eDbI%^SyG zBUD9-66Nzu`H;~pFm`2>WmuZWCpQm7r#N8pQr&b0Y<#zO74G{r3I*|++>fd~Ob2u2 zU~UC!Jyli%Wi=GRcc$b5vAs+)KHZ zDSu!QIO_7n#8Shx+BR9Hv*6%Q$$J7U6fwr3jPNZV6+Zq#c^c>5d>tYXhtrWbS&PJf HvMA@j^j37g literal 0 HcmV?d00001 diff --git a/common/__pycache__/scene_watcher.cpython-311.pyc b/common/__pycache__/scene_watcher.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7f4c8d93f04cfa90dcfc6be4d0a6a4ca6a3b96bb GIT binary patch literal 11601 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 XfoK!FOc2!pt|N56ht{d*(&P94ngN2p literal 0 HcmV?d00001 diff --git a/common/__pycache__/shader.cpython-311.pyc b/common/__pycache__/shader.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef6199ba460e19ec73cfddad4ddd5e3d1ac99839 GIT binary patch literal 84922 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 literal 0 HcmV?d00001 diff --git a/common/__pycache__/version.cpython-311.pyc b/common/__pycache__/version.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec3fa86b320c81286029f24628e831094de4258d GIT binary patch literal 7853 zcmeGhOKcm*b#}Sr@+;DjKJ-8oj$U~Lnc*jafR{iLfBkCWi&jGZjvrPME69_-a)f+D6rylR62qKN zaw$H>bBH^Vj+77+7%n88DOb$Ja4spvM5uQr-6>DZ17$8nOnOtkn2+J^q(2pi1vtVJ zHK4ZKfj&Nkx13^rmFLN6qIgz`;=RK|9lYgq2eMDC4-yMP`=H{3pC2&aV#unp)8%$p z<@LFp=6>Lg0KDNXr`U5!i|SHa_gDpFo>zjaLaa^Mql6%DXZ1VPUFxoRzD8BUfPM$i z?FKqV1#}Ku?Q>AO2WmTjvK8>o3f=~IR|Rheyc=+ry4TirCzSVWQN9bx!&{W^hVov8 zyFelxk8niO5zh1|vM$GyvZld@cRrbsbt#da&%l@aXIVXwNy|yZvkR)Ot5@|$xI|D8 zJdsq>ib~JP>BPLM>DU@bq-17cL8bBPgaP8Hd^~v>kdKH;Vw^%^{2N4dsDi>BgHnd^ z40A%6gJCYf1jH04i0m?*<8u6xYC4uQ)$9g|b!o0FgG509nd*?gyOf}+Vh-A>QxzGd zR7Oe6C*m>=OVSf5)eI-n2|XbvtE{TD@l0A*)B1EoG~JSvmQ$)EnO+HbEF}^5OVYbb za3jSm6z>s^w6eULqoCt0^9c%ymjK@QXxK12(CgSVpS}oWhvC)Q0KiCm9fq%`;OjN;iR6Vyv!J-ynV^4z z>9Y&EjrJlnOLpC?(|lM$9oMXq7OPrL{kC$KMR5UwsrnkJ+M>R6u}TkizyW=rjjg1` zYJc|ahnp_vv8d{EJKZ7+2C@DIr{hFdlCA%$UAoR)1A6=T^$x2I*h#dxEWN`Z$P06F zovY_2)wq#d-AF18A+t+(gTKz#x37hJ@8D)biwk`;%wu)NaK6C0(H@|jn2GG5eb{6_ z0<?GtWPBqsUWlAB@R`mF17Ev+5B)m~|4)i7FFtl~ftMaT93JmC1i-g$;%hg&UH|k5 zp6(Js;3uK>wWZC&Z@z!Z5MJ8sIsBk!bfagq&@*QAjOB%{qS*8Ch|xE>Ax`GS$s&ro zITS_W!EGFU)h?~Uz(L&sTB&BiYc?B{x^8pnb&hor*Ow*xHdP$u7MZpm{NUpoJ4-exWf67f4|NzUMFQ!!o1@Q?S+mY=tS35 zn<1vf5UX&P>wTf8>ILZpkk7%Zy#N4azb_D`Q2`y|T<^;GwVO=8>DDw}x+x z-5NH0dviNBeEagkzUEP*$z-EmZ*m>>QPZG~bd{uVcEbsCQ8o9CMo&9wYsuSN=IXdw z+#z7Cx&ko7Rn9f%k*nLqwN`eCAv}aJ)lTIgW8Ep*POH6blTom@+*(G(xwTW$+iMc( zJL~YR$5eG8uv=X9yTu;d+9kR#+P}eRVCd_fetK@^k{W*V{JAhh6$dlv@FiIbuU zyp)Agn5sm>uQN>wSL|u{MEMvR)-z!UfRoE%9T>zf$>{}Ei(WfX$10(P;dB^=;~BV( z1ZZXWNW$>P5&}}MyBYKakxd~g;jb)l?|di z1JS2kl&KoX5o{3gUVwQK>Vj2brp0ujF_QHX1nWo`bETvRUli`Rk18fuUYIy)?$a)H5uOaq=({Oqp z26vTsE^r(iO9&lH$Xlv-7k@{=*J=1V;oCXI0bSAm`eO%=Q~>_r4Sg{1v3C24F?j63 z;OULQ(}lrFV{me9px`}gc+Zxcyl0C0)t=@jQl`7TtFcZi1qIpT6hPa3@^(S4sXyrkub_q*|5bFbAI^aULe2T)m zGYWqMl5$u#j@Sf(3kWdeqG*XJE?k4Kl7kp z+US=G{j$+7mpo1n|Cj*y2EmH66ymv1?&Z6uZjY7-ppC%m3&c(gP z-4aR!^DW?W0@wH9VeGfB5wrw>?ZvzC+rKCgKpVmSRxWhw>Rre0ZS literal 0 HcmV?d00001 diff --git a/common/__pycache__/workspace.cpython-311.pyc b/common/__pycache__/workspace.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..125da756d977499f631c8b409c6fb9fe182977de GIT binary patch literal 7870 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 Path: + return Path(__file__).parent.parent / "blender_manifest.toml" + + @classmethod + def read_str(cls, blender_manifest: str, key: str) -> Optional[str]: + # When the version of Python used by the minimum supported version of Blender + # exceeds 3.11, it is rewritten in the tomli library. + lines = list(map(str.strip, blender_manifest.splitlines())) + + pattern = key + r' = "([^"]+)"' + for line in lines: + match = re.fullmatch(pattern, line) + if not match: + continue + return match[1] + + return None + + @classmethod + def read_3_tuple_version( + cls, blender_manifest: str, key: str + ) -> Optional[tuple[int, int, int]]: + # When the version of Python used by the minimum supported version of Blender + # exceeds 3.11, it is rewritten in the tomli library. + lines = list(map(str.strip, blender_manifest.splitlines())) + + pattern = key + r' = "(\d+)\.(\d+)\.(\d+)"' + for line in lines: + match = re.fullmatch(pattern, line) + if not match: + continue + return (int(match[1]), int(match[2]), int(match[3])) + + return None + + @classmethod + def read(cls, blender_manifest: Optional[str] = None) -> "BlenderManifest": + if blender_manifest is None: + blender_manifest = cls.default_blender_manifest_path().read_text( + encoding="UTF-8" + ) + + addon_id = cls.read_str(blender_manifest, "id") + if addon_id is None: + message = "'id' was not found in blender manifest" + raise ValueError(message) + + version = cls.read_3_tuple_version(blender_manifest, "version") + if version is None: + message = "'version' was not found in blender manifest" + raise ValueError(message) + + blender_version_min = cls.read_3_tuple_version( + blender_manifest, "blender_version_min" + ) + if blender_version_min is None: + message = "'blender_version_min' was not found in blender manifest" + raise ValueError(message) + + return BlenderManifest( + id=addon_id, + version=version, + blender_version_min=blender_version_min, + blender_version_max=cls.read_3_tuple_version( + blender_manifest, "blender_version_max" + ), + ) diff --git a/common/char.py b/common/char.py new file mode 100644 index 0000000..147e530 --- /dev/null +++ b/common/char.py @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: MIT OR GPL-3.0-or-later +from collections.abc import Mapping +from typing import Final + +INTERNAL_NAME_PREFIX: Final = "\N{FULLWIDTH BROKEN BAR}" +""" +The letter to be prefixed when naming internal invisible objects. It was chosen so that +the sort order would be backward and also so that it would be easy to identify the +object as internal. +""" + +DISABLE_TRANSLATION: Final = "\N{ZERO WIDTH SPACE}" + +FULLWIDTH_ASCII_TO_ASCII_MAP: Final[Mapping[str, str]] = { + chr(ascii_char + 0x0000_FEE0): chr(ascii_char) for ascii_char in range(0x21, 0x7E) +} diff --git a/common/convert.py b/common/convert.py new file mode 100644 index 0000000..fb190c2 --- /dev/null +++ b/common/convert.py @@ -0,0 +1,297 @@ +# SPDX-License-Identifier: MIT OR GPL-3.0-or-later +import math +from collections.abc import Iterator, Mapping, Sequence +from sys import float_info +from typing import Optional, Union + +from . import convert_any +from .logger import get_logger + +logger = get_logger(__name__) + +Json = Union[ + None, + bool, + int, + float, + str, + list["Json"], + dict[str, "Json"], +] + + +def iterator_or_none(v: object) -> Optional[Iterator[object]]: + try: + # "isinstance(v, Iterable)" doesn't work. + # https://github.com/python/cpython/blob/3.9/Doc/library/collections.abc.rst?plain=1#L126-L127 + iterator = iter(v) # type: ignore[call-overload] + except TypeError: + return None + return convert_any.iterator_to_object_iterator(iterator) + + +def sequence_or_none( + sequence_object: object, +) -> Optional[Sequence[object]]: + sequence = sequence_object + if not isinstance(sequence, Sequence): + return None + iterator = iterator_or_none(sequence_object) + if iterator is None: + return None + return list(iterator) + + +def mapping_or_none( + mapping_object: object, +) -> Optional[Mapping[object, object]]: + mapping = mapping_object + if not isinstance(mapping, Mapping): + return None + key_iterator = iterator_or_none(mapping_object) + if key_iterator is None: + return None + return {key: convert_any.to_object(mapping[key]) for key in key_iterator} + + +def vrm_json_vector3_to_tuple( + value: Json, +) -> Optional[tuple[float, float, float]]: + if not isinstance(value, Mapping): + return None + x = float_or(value.get("x"), 0.0) + y = float_or(value.get("y"), 0.0) + z = float_or(value.get("z"), 0.0) + return (x, y, z) + + +def vrm_json_curve_to_list(curve: Json) -> Optional[list[float]]: + if not isinstance(curve, list): + return None + values: list[float] = [float_or(v, 0.0) for v in curve] + while len(values) < 8: + values.append(0) + while len(values) > 8: + values.pop() + return values + + +def vrm_json_array_to_float_vector( + input_values: Json, defaults: list[float] +) -> list[float]: + if not isinstance(input_values, list): + return defaults + + output_values: list[float] = [] + for index, default in enumerate(defaults): + if index >= len(input_values): + output_values.append(default) + continue + + input_value = float_or(input_values[index], default) + output_values.append(input_value) + + return output_values + + +BPY_TRACK_AXIS_TO_VRM_AIM_AXIS = { + "TRACK_X": "PositiveX", + "TRACK_Y": "PositiveY", + "TRACK_Z": "PositiveZ", + "TRACK_NEGATIVE_X": "NegativeX", + "TRACK_NEGATIVE_Y": "NegativeY", + "TRACK_NEGATIVE_Z": "NegativeZ", +} + +VRM_AIM_AXIS_TO_BPY_TRACK_AXIS = { + v: k for k, v in BPY_TRACK_AXIS_TO_VRM_AIM_AXIS.items() +} + + +def mtoon_shading_toony_1_to_0(shading_toony: float, shading_shift: float) -> float: + base = 2 - shading_toony + shading_shift + if abs(base) < float_info.epsilon: + # https://github.com/Santarh/MToon/blob/43f02fe8c9b19c3cf9f3238003b7d8b332933833/MToon/Resources/Shaders/MToon.shader#L17 + return 0.9 + return max(0, min((shading_toony + shading_shift) / base, 1)) + + +def mtoon_shading_shift_1_to_0(shading_toony: float, shading_shift: float) -> float: + return max(-1, min(shading_toony - shading_shift - 1, 1)) + + +def mtoon_gi_equalization_to_intensity(gi_equalization: float) -> float: + return max(0, min(1, 1 - gi_equalization)) + + +# https://github.com/vrm-c/UniVRM/blob/f3479190c330ec6ecd2b40be919285aa93a53aff/Assets/VRMShaders/VRM10/MToon10/Runtime/MToon10Migrator.cs#L10-L19 +def mtoon_shading_toony_0_to_1( + shading_toony_0x: float, shading_shift_0x: float +) -> float: + (range_min, range_max) = get_shading_range_0x(shading_toony_0x, shading_shift_0x) + return max(0, min(1, (2 - (range_max - range_min)) * 0.5)) + + +# https://github.com/vrm-c/UniVRM/blob/f3479190c330ec6ecd2b40be919285aa93a53aff/Assets/VRMShaders/VRM10/MToon10/Runtime/MToon10Migrator.cs#L21-L30 +def mtoon_shading_shift_0_to_1( + shading_toony_0x: float, shading_shift_0x: float +) -> float: + (range_min, range_max) = get_shading_range_0x(shading_toony_0x, shading_shift_0x) + return max(-1, min(1, ((range_max + range_min) * 0.5 * -1))) + + +# https://github.com/vrm-c/UniVRM/blob/f3479190c330ec6ecd2b40be919285aa93a53aff/Assets/VRMShaders/VRM10/MToon10/Runtime/MToon10Migrator.cs#L32-L38 +def mtoon_intensity_to_gi_equalization(gi_intensity_0x: float) -> float: + return max(0, min(1, 1 - gi_intensity_0x)) + + +# https://github.com/vrm-c/UniVRM/blob/f3479190c330ec6ecd2b40be919285aa93a53aff/Assets/VRMShaders/VRM10/MToon10/Runtime/MToon10Migrator.cs#L40-L46 +def get_shading_range_0x( + shading_toony_0x: float, shading_shift_0x: float +) -> tuple[float, float]: + range_min = shading_shift_0x + range_max = (1 - shading_toony_0x) + shading_toony_0x * shading_shift_0x + return (range_min, range_max) + + +def float_or_none( + v: object, + min_value: float = -float_info.max, + max_value: float = float_info.max, +) -> Optional[float]: + if isinstance(v, float): + if math.isnan(v): + return None + return max(min_value, min(v, max_value)) + + if isinstance(v, bool): + return 1.0 if v else 0.0 + + if isinstance(v, int): + return max(min_value, min(float(v), max_value)) + + return None + + +def float_or( + v: object, + default: float, + min_value: float = -float_info.max, + max_value: float = float_info.max, +) -> float: + float_or_none_value = float_or_none(v, min_value, max_value) + if float_or_none_value is not None: + return float_or_none_value + + if min_value <= default <= max_value: + return default + + logger.warning( + "Default float value %s is out of range [%s, %s]", default, min_value, max_value + ) + + return max(min_value, min(default, max_value)) + + +def float4_or_none(value4: object) -> Optional[tuple[float, float, float, float]]: + value4_iterator = iterator_or_none(value4) + if value4_iterator is None: + return None + + result: list[float] = [] + for value in value4_iterator: + if len(result) == 4: + return None + float_value = float_or_none(value) + if float_value is None: + return None + result.append(float_value) + if len(result) != 4: + return None + return (result[0], result[1], result[2], result[3]) + + +def float4_or( + value4: object, default: tuple[float, float, float, float] +) -> tuple[float, float, float, float]: + float4 = float4_or_none(value4) + return float4 if float4 is not None else default + + +def float3_or_none(value3: object) -> Optional[tuple[float, float, float]]: + value3_iterator = iterator_or_none(value3) + if value3_iterator is None: + return None + + result: list[float] = [] + for value in value3_iterator: + if len(result) == 3: + return None + float_value = float_or_none(value) + if float_value is None: + return None + result.append(float_value) + if len(result) != 3: + return None + return (result[0], result[1], result[2]) + + +def float3_or( + value3: object, default: tuple[float, float, float] +) -> tuple[float, float, float]: + float3 = float3_or_none(value3) + return float3 if float3 is not None else default + + +def float2_or_none(value2: object) -> Optional[tuple[float, float]]: + value2_iterator = iterator_or_none(value2) + if value2_iterator is None: + return None + result: list[float] = [] + for value in value2_iterator: + if len(result) == 2: + return None + float_value = float_or_none(value) + if float_value is None: + return None + result.append(float_value) + if len(result) != 2: + return None + return (result[0], result[1]) + + +def float2_or(value2: object, default: tuple[float, float]) -> tuple[float, float]: + float2 = float2_or_none(value2) + return float2 if float2 is not None else default + + +def str_or(v: object, default: str) -> str: + if isinstance(v, str): + return v + return default + + +def axis_blender_to_gltf(vector3: Sequence[float]) -> tuple[float, float, float]: + return ( + -vector3[0], + vector3[2], + vector3[1], + ) + + +def linear_to_srgb( + non_color: Sequence[float], +) -> Sequence[float]: + return [ + math.pow(channel_value, 1.0 / 2.2) if channel_index < 3 else channel_value + for channel_index, channel_value in enumerate(non_color) + ] + + +def srgb_to_linear( + srgb_color: Sequence[float], +) -> Sequence[float]: + return [ + math.pow(channel_value, 2.2) if channel_index < 3 else channel_value + for channel_index, channel_value in enumerate(srgb_color) + ] diff --git a/common/convert_any.py b/common/convert_any.py new file mode 100644 index 0000000..991eae9 --- /dev/null +++ b/common/convert_any.py @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: MIT OR GPL-3.0-or-later +"""A module provides a function to convert a variable of type Any to a concrete type. + +Inevitably, variables of type Any may occur, and such variables cannot be handled +in type checkers in strict mode. Any is allowed only in the module here. +""" + +import sys +from collections.abc import Iterator +from typing import ( + Any, # Any is allowed only in the module here. + Optional, +) + + +def to_object( # type: ignore[explicit-any] + any_object: Any, # noqa: ANN401 # Any is allowed only in the module here. +) -> object: + # Interpret Unknown as object + # https://github.com/microsoft/pyright/issues/3650 + if not isinstance(any_object, object): + if sys.version_info >= (3, 11): + from typing import assert_never + + assert_never(any_object) + raise TypeError + return any_object + + +def iterator_to_object_iterator( # type: ignore[explicit-any] + any_iterator: Any, # noqa: ANN401 # Any is allowed only in the module here. +) -> Optional[Iterator[object]]: + any_iterator_without_partial_type_narrowing = any_iterator + if not isinstance(any_iterator, Iterator): + return None + return map(to_object, any_iterator_without_partial_type_narrowing) diff --git a/common/debug.py b/common/debug.py new file mode 100644 index 0000000..e3dcbe4 --- /dev/null +++ b/common/debug.py @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: MIT OR GPL-3.0-or-later +import math +from collections.abc import Sequence +from typing import Union + +from mathutils import Matrix, Quaternion, Vector + + +def dump(v: Union[Matrix, Vector, Quaternion, float]) -> str: + if isinstance(v, (float, int)): + return str(v) + + if isinstance(v, Matrix): + t, r, s = v.decompose() + return f"Matrix(T={dump(t)},R={dump(r)},S={dump(s)})" + + if isinstance(v, Vector): + return f"({v.x:.3f},{v.y:.3f},{v.z:.3f})" + + x, y, z = (round(math.degrees(xyz)) for xyz in v.to_euler()[:]) + return f"Euler({x},{y},{z})" + + +def assert_vector3_equals( + expected: Vector, actual: Sequence[float], message: str +) -> None: + if len(actual) != 3: + message = f"actual length is not 3: {actual}" + raise AssertionError(message) + + threshold = 0.0001 + if abs(expected[0] - actual[0]) > threshold: + message = f"{message}: {tuple(expected)} is different from {tuple(actual)}" + raise AssertionError(message) + if abs(expected[1] - actual[1]) > threshold: + message = f"{message}: {tuple(expected)} is different from {tuple(actual)}" + raise AssertionError(message) + if abs(expected[2] - actual[2]) > threshold: + message = f"{message}: {tuple(expected)} is different from {tuple(actual)}" + raise AssertionError(message) + + +def cleanse_modules() -> None: + """Search for your plugin modules in blender python sys.modules and remove them. + + To support reload properly, try to access a package var, if it's there, + reload everything. + + This function may cause errors that are difficult to investigate. Please use with + caution. See also: + https://github.com/saturday06/VRM-Addon-for-Blender/issues/506#issuecomment-2183766778 + """ + import sys + + all_modules = sys.modules + all_modules = dict(sorted(all_modules.items(), key=lambda x: x[0])) # sort them + + for k in all_modules: + if k == __name__ or k.startswith(__name__ + "."): + del sys.modules[k] diff --git a/common/deep.py b/common/deep.py new file mode 100644 index 0000000..f6d198c --- /dev/null +++ b/common/deep.py @@ -0,0 +1,146 @@ +# SPDX-License-Identifier: MIT OR GPL-3.0-or-later +import difflib +import math +from collections.abc import Mapping +from json import dumps as json_dumps + +from . import convert +from .convert import Json +from .logger import get_logger + +logger = get_logger(__name__) + + +def make_json(v: object) -> Json: + if v is None: + return None + if isinstance(v, int): + return v + if isinstance(v, float): + if not math.isfinite(v): + logger.warning("%s %s is non-finite value", v, type(v)) + return 0.0 + return v + if isinstance(v, bool): + return v + if isinstance(v, str): + return v + + mapping = convert.mapping_or_none(v) + if mapping is not None: + dict_result: dict[str, Json] = {} + for key, value in mapping.items(): + if isinstance(key, str): + dict_result[key] = make_json(value) + continue + logger.warning("%s %s is unrecognized type for dict key", key, type(key)) + return dict_result + + iterator = convert.iterator_or_none(v) + if iterator is not None: + return [make_json(x) for x in iterator] + + logger.warning("%s %s is unrecognized type", v, type(v)) + return None + + +def make_json_dict(v: Mapping[str, object]) -> dict[str, Json]: + return {key: make_json(value) for key, value in v.items()} + + +def diff( + left: Json, + right: Json, + float_tolerance: float = 0, + path: str = "", +) -> list[str]: + if isinstance(left, list): + if not isinstance(right, list): + return [f"{path}: left is list but right is {type(right)}"] + if len(left) != len(right): + result = [ + f"{path}: left length is {len(left)} but right length is {len(right)}" + ] + + right_json_str = json_dumps(right, indent=4, sort_keys=True) + right_json_lines = right_json_str.splitlines(keepends=True) + left_json_str = json_dumps(left, indent=4, sort_keys=True) + left_json_lines = left_json_str.splitlines(keepends=True) + + if len(right_json_lines) > 1000 or len(left_json_lines) > 1000: + return result + + unified_diff = [ + line.rstrip() + for line in difflib.unified_diff( + right_json_lines, + left_json_lines, + f"{path}/right", + f"{path}/left", + ) + ] + if len(unified_diff) > 1000: + return result + return result + unified_diff + diffs: list[str] = [] + for i, (left_child, right_child) in enumerate(zip(left, right)): + diffs.extend(diff(left_child, right_child, float_tolerance, f"{path}[{i}]")) + return diffs + + if isinstance(left, dict): + if not isinstance(right, dict): + return [f"{path}: left is dict but right is {type(right)}"] + diffs = [] + for key in sorted(set(list(left.keys()) + list(right.keys()))): + if key not in left: + diffs.append(f'{path}: {key} not in left. right["{key}"]={right[key]}') + continue + if key not in right: + diffs.append(f'{path}: {key} not in right, left["{key}"]={left[key]}') + continue + diffs.extend( + diff(left[key], right[key], float_tolerance, f'{path}["{key}"]') + ) + return diffs + + if isinstance(left, bool): + if not isinstance(right, bool): + return [f"{path}: left is bool but right is {type(right)}"] + if left != right: + return [f"{path}: left is {left} but right is {right}"] + return [] + + if isinstance(left, str): + if not isinstance(right, str): + return [f"{path}: left is str but right is {type(right)}"] + if left != right: + return [f'{path}: left is "{left}" but right is "{right}"'] + return [] + + if left is None and right is not None: + return [f"{path}: left is None but right is {type(right)}"] + + if isinstance(left, int) and isinstance(right, int): + if left != right: + return [f"{path}: left is {left} but right is {right}"] + return [] + + if isinstance(left, (int, float)) and isinstance(right, (int, float)): + if (isinstance(left, float) and not math.isfinite(left)) or ( + isinstance(right, float) and not math.isfinite(right) + ): + return [ + f"{path}: left is {left}" + + f" but right is {right}, They are not comparable numbers" + ] + + error = math.fabs(float(left) - float(right)) + if error > float_tolerance: + return [ + f"{path}: left is {float(left):20.17f}" + + f" but right is {float(right):20.17f}, error={error:19.17f}" + ] + return [] + + message = f"{path}: unexpected type left={type(left)} right={type(right)}" + raise ValueError(message) diff --git a/common/error_dialog.py b/common/error_dialog.py new file mode 100644 index 0000000..a7454bc --- /dev/null +++ b/common/error_dialog.py @@ -0,0 +1,242 @@ +# SPDX-License-Identifier: MIT OR GPL-3.0-or-later + +import contextlib +import datetime +import getpass +import platform +import sys +import sysconfig +from collections.abc import Sequence +from collections.abc import Set as AbstractSet +from pathlib import Path +from typing import TYPE_CHECKING, Union + +import bpy +from bpy.props import CollectionProperty, IntProperty, StringProperty +from bpy.types import ( + Context, + Event, + Operator, + PropertyGroup, + UILayout, + UIList, +) +from bpy_extras.io_utils import ExportHelper + +from ..common import ops +from ..common.logger import get_logger +from ..common.version import get_addon_version +from ..editor.ops import VRM_OT_open_url_in_web_browser, layout_operator +from ..editor.property_group import CollectionPropertyProtocol + +logger = get_logger(__name__) + + +def show_error_dialog( + title: str, + lines: Union[str, Sequence[str]], + *, + append_environment: bool = True, +) -> set[str]: + if isinstance(lines, str): + lines = list(map(str.rstrip, lines.splitlines())) + while lines and not lines[0].strip(): + del lines[0] + while lines and not lines[-1].strip(): + del lines[-1] + else: + lines = list(lines) + if not lines: + return {"CANCELLED"} + if append_environment: + if lines: + lines[0] = f"Python: {lines[0]}" + + os_name = None + platform_system, _, _ = platform.system_alias( + platform.system(), platform.release(), platform.version() + ) + if sys.version_info >= (3, 10) and platform_system not in ["Windows", "Darwin"]: + # https://github.com/python/cpython/blob/v3.10.18/Doc/library/platform.rst?plain=1#L271-L272 + with contextlib.suppress(OSError): + os_name = platform.freedesktop_os_release().get("PRETTY_NAME") + + if not os_name: + os_name = platform_system + + python_version = ( + platform.python_implementation() + + " " + + ".".join(map(str, sys.version_info[:3])) + ) + runtime_platform = os_name + " " + platform.machine() + build_platform = sysconfig.get_platform() + lines.insert( + 0, + "Environment: Blender {} / VRM Add-on {} / {} / {} ({})".format( + bpy.app.version_string, + ".".join(map(str, get_addon_version())), + python_version, + runtime_platform, + build_platform, + ), + ) + return ops.wm.vrm_error_dialog( + "INVOKE_DEFAULT", + title=title, + lines=[ + { + "name": f"error_line_{i}", + "line": mask_private_string(line), + } + for i, line in enumerate(lines) + ], + ) + + +def mask_private_string(message: str) -> str: + script_path = Path(__file__).parent.parent.parent.parent.parent + if len(script_path.parts) > 3: + message = message.replace(str(script_path), "