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:
82
common/blender_manifest.py
Normal file
82
common/blender_manifest.py
Normal file
@@ -0,0 +1,82 @@
|
||||
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BlenderManifest:
|
||||
id: str
|
||||
version: tuple[int, int, int]
|
||||
blender_version_min: tuple[int, int, int]
|
||||
blender_version_max: Optional[tuple[int, int, int]]
|
||||
|
||||
@classmethod
|
||||
def default_blender_manifest_path(cls) -> 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"
|
||||
),
|
||||
)
|
||||
Reference in New Issue
Block a user