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:
87
common/progress.py
Normal file
87
common/progress.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# SPDX-License-Identifier: MIT OR GPL-3.0-or-later
|
||||
import math
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
from typing import Final, Optional
|
||||
from uuid import uuid4
|
||||
|
||||
import bpy
|
||||
from bpy.types import Context
|
||||
|
||||
from .logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class PartialProgress:
|
||||
def __init__(
|
||||
self, progress: "Progress", partial_start_ratio: float, partial_end_ratio: float
|
||||
) -> None:
|
||||
self.progress: Final = progress
|
||||
self.partial_start_ratio: Final = partial_start_ratio
|
||||
self.partial_end_ratio: Final = partial_end_ratio
|
||||
|
||||
def update(self, ratio: float) -> None:
|
||||
ratio = min(max(0.0, ratio), 1.0)
|
||||
self.progress.update(
|
||||
self.partial_start_ratio
|
||||
+ ratio * (self.partial_end_ratio - self.partial_start_ratio)
|
||||
)
|
||||
|
||||
|
||||
class Progress:
|
||||
active_progress_uuid: Optional[str] = None
|
||||
|
||||
def __init__(self, context: Context, *, show_progress: bool) -> None:
|
||||
self.context: Final = context
|
||||
self.show_progress: Final = show_progress
|
||||
self.uuid: Final = uuid4().hex
|
||||
self.last_ratio = 0.0
|
||||
|
||||
def partial_progress(self, partial_end_ratio: float) -> PartialProgress:
|
||||
partial_end_ratio = min(max(0.0, partial_end_ratio), 1.0)
|
||||
return PartialProgress(self, self.last_ratio, partial_end_ratio)
|
||||
|
||||
def update(self, ratio: float) -> None:
|
||||
ratio = min(max(0.0, ratio), 1.0)
|
||||
self.last_ratio = ratio
|
||||
if self.active_progress_uuid != self.uuid:
|
||||
logger.error(
|
||||
"Progress.update() called from different progress active=%s self=%s",
|
||||
self.active_progress_uuid,
|
||||
self.uuid,
|
||||
)
|
||||
return
|
||||
|
||||
if not self.show_progress:
|
||||
return
|
||||
|
||||
if bpy.app.version >= (5, 0):
|
||||
progress_value = ratio * 9999
|
||||
else:
|
||||
# The mouse cursor becomes a four-digit number, and there is an area
|
||||
# where values from 0 to 9999 can be displayed. However, if the
|
||||
# progress rate is directly converted to a number from 0 to 9999, the
|
||||
# last two digits will frequently round-trip, making the progress
|
||||
# difficult to understand. Therefore, only the last two digits display
|
||||
# area is used to show the progress rate as a number from 0 to 99.
|
||||
progress_value = math.floor(ratio * 99)
|
||||
|
||||
self.context.window_manager.progress_update(progress_value)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def create_progress(
|
||||
context: Context, *, show_progress: bool = True
|
||||
) -> Iterator[Progress]:
|
||||
saved_progress_uuid = Progress.active_progress_uuid
|
||||
try:
|
||||
if show_progress and Progress.active_progress_uuid is None:
|
||||
context.window_manager.progress_begin(0, 9999)
|
||||
progress = Progress(context, show_progress=show_progress)
|
||||
Progress.active_progress_uuid = progress.uuid
|
||||
yield progress
|
||||
finally:
|
||||
Progress.active_progress_uuid = saved_progress_uuid
|
||||
if show_progress and Progress.active_progress_uuid is None:
|
||||
context.window_manager.progress_end()
|
||||
Reference in New Issue
Block a user