- 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
83 lines
2.8 KiB
Python
83 lines
2.8 KiB
Python
# 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"
|
|
),
|
|
)
|