Files
Avatar-Toolkit/core/mmd/operators/sdef.py
T
2025-04-10 23:40:51 +01:00

111 lines
3.5 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2014 MMD Tools authors
# This file was originally part of the MMD Tools add-on for Blender
# You can find MMD Tools here: https://github.com/MMD-Blender/blender_mmd_tools
# Neoneko has modified this file to work with Avatar Toolkit and may of made changes or improvements.
# MMD Tools is licensed under the terms of the GNU General Public License version 3 (GPLv3) same as Avatar Toolkit.
from typing import Set
import bpy
from bpy.types import Operator
from ..core.model import FnModel
from ..core.sdef import FnSDEF
def _get_target_objects(context):
root_objects: Set[bpy.types.Object] = set()
selected_objects: Set[bpy.types.Object] = set()
for i in context.selected_objects:
if i.type == "MESH":
selected_objects.add(i)
continue
root_object = FnModel.find_root_object(i)
if root_object is None:
continue
if root_object in root_objects:
continue
root_objects.add(root_object)
selected_objects |= set(FnModel.iterate_mesh_objects(root_object))
return selected_objects, root_objects
class ResetSDEFCache(Operator):
bl_idname = "mmd_tools.sdef_cache_reset"
bl_label = "Reset MMD SDEF cache"
bl_description = "Reset MMD SDEF cache of selected objects and clean unused cache"
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
def execute(self, context):
target_meshes, _ = _get_target_objects(context)
for i in target_meshes:
FnSDEF.clear_cache(i)
FnSDEF.clear_cache(unused_only=True)
return {"FINISHED"}
class BindSDEF(Operator):
bl_idname = "mmd_tools.sdef_bind"
bl_label = "Bind SDEF Driver"
bl_description = "Bind MMD SDEF data of selected objects"
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
mode: bpy.props.EnumProperty(
name="Mode",
description="Select mode",
items=[
("2", "Bulk", "Speed up with numpy (may be slower in some cases)", 2),
("1", "Normal", "Normal mode", 1),
("0", "- Auto -", "Select best mode by benchmark result", 0),
],
default="0",
)
use_skip: bpy.props.BoolProperty(
name="Skip",
description="Skip when the bones are not moving",
default=True,
)
use_scale: bpy.props.BoolProperty(
name="Scale",
description="Support bone scaling (slow)",
default=False,
)
def invoke(self, context, event):
vm = context.window_manager
return vm.invoke_props_dialog(self)
# TODO: Utility Functionalize
def execute(self, context):
target_meshes, root_objects = _get_target_objects(context)
for r in root_objects:
r.mmd_root.use_sdef = True
param = ((None, False, True)[int(self.mode)], self.use_skip, self.use_scale)
count = sum(FnSDEF.bind(i, *param) for i in target_meshes)
self.report({"INFO"}, f"Binded {count} of {len(target_meshes)} selected mesh(es)")
return {"FINISHED"}
class UnbindSDEF(Operator):
bl_idname = "mmd_tools.sdef_unbind"
bl_label = "Unbind SDEF Driver"
bl_description = "Unbind MMD SDEF data of selected objects"
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
# TODO: Utility Functionalize
def execute(self, context):
target_meshes, root_objects = _get_target_objects(context)
for i in target_meshes:
FnSDEF.unbind(i)
for r in root_objects:
r.mmd_root.use_sdef = False
return {"FINISHED"}