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
This commit is contained in:
60
common/debug.py
Normal file
60
common/debug.py
Normal file
@@ -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]
|
||||
Reference in New Issue
Block a user