Initial MMD Importer Commit

- This is the initial commit I spent several hours trying to get it up two Avatar Toolkit standard, it does not work yet because there are files missing but I been doing this since 6am and it is 4pm almost, i need food.
- I have also removed as much legacy code as i could, MMD Tools contains so much of it even though there have a 4.2+ only version there have not removed any of the legacy code for pre 4.2.... this is going to take a while.

God I hope this works fine once I am done.
This commit is contained in:
Yusarina
2025-04-03 15:39:03 +01:00
parent 3e3e245a4f
commit 3414ad8917
10 changed files with 4020 additions and 0 deletions
View File
+250
View File
@@ -0,0 +1,250 @@
# -*- coding: utf-8 -*-
# Copyright 2014 MMD Tools authors
# This file was originally part of the MMD Tools project, However Neoneko has added it to Avatar Toolkit.
# All credit goes to the original authors.
# Please note that some code was modified to fit the needs of Avatar Toolkit and some code may of been removed.
# MMD Tools is licensed under the terms of the GPL-3.0 license which Avatar Toolkit is also licensed under.
# You can find MMD Tools at: https://github.com/MMD-Blender/blender_mmd_tools/
import bpy
from bpy.types import PropertyGroup, Context, PoseBone
from bpy.props import (
StringProperty,
IntProperty,
BoolProperty,
FloatProperty,
FloatVectorProperty
)
from ..logging_setup import logger
from ..bone import FnBone
def _mmd_bone_update_additional_transform(prop, context: Context):
"""Update handler for additional transform properties"""
prop["is_additional_transform_dirty"] = True
p_bone = context.active_pose_bone
if p_bone and p_bone.mmd_bone.as_pointer() == prop.as_pointer():
FnBone.apply_additional_transformation(prop.id_data)
def _mmd_bone_update_additional_transform_influence(prop, context: Context):
"""Update handler for additional transform influence"""
pose_bone = context.active_pose_bone
if pose_bone and pose_bone.mmd_bone.as_pointer() == prop.as_pointer():
FnBone.update_additional_transform_influence(pose_bone)
else:
prop["is_additional_transform_dirty"] = True
def _mmd_bone_get_additional_transform_bone(prop):
"""Getter for additional transform bone property"""
arm = prop.id_data
bone_id = prop.get("additional_transform_bone_id", -1)
if bone_id < 0:
return ""
pose_bone = FnBone.find_pose_bone_by_bone_id(arm, bone_id)
if pose_bone is None:
return ""
return pose_bone.name
def _mmd_bone_set_additional_transform_bone(prop, value: str):
"""Setter for additional transform bone property"""
arm = prop.id_data
prop["is_additional_transform_dirty"] = True
if value not in arm.pose.bones.keys():
prop["additional_transform_bone_id"] = -1
return
pose_bone = arm.pose.bones[value]
prop["additional_transform_bone_id"] = FnBone.get_or_assign_bone_id(pose_bone)
def _pose_bone_update_mmd_ik_toggle(prop: PoseBone, _context):
"""Update handler for IK toggle property"""
v = prop.mmd_ik_toggle
armature_object = prop.id_data
for b in armature_object.pose.bones:
for c in b.constraints:
if c.type == "IK" and c.subtarget == prop.name:
logger.debug('Updating IK constraint %s on bone %s', c.name, b.name)
c.influence = v
b_chain = b if c.use_tail else b.parent
for chain_bone in ([b_chain] + b_chain.parent_recursive)[:c.chain_count]:
limit_c = next((c for c in chain_bone.constraints if c.type == "LIMIT_ROTATION" and not c.mute), None)
if limit_c:
limit_c.influence = v
class MMDBone(PropertyGroup):
"""Property group for MMD bone properties"""
name_j: StringProperty(
name="Name",
description="Japanese Name",
default="",
)
name_e: StringProperty(
name="Name(Eng)",
description="English Name",
default="",
)
bone_id: IntProperty(
name="Bone ID",
description="Unique ID for the reference of bone morph and rotate+/move+",
default=-1,
min=-1,
)
transform_order: IntProperty(
name="Transform Order",
description="Deformation tier",
min=0,
max=100,
soft_max=7,
)
is_controllable: BoolProperty(
name="Controllable",
description="Is controllable",
default=True,
)
transform_after_dynamics: BoolProperty(
name="After Dynamics",
description="After physics",
default=False,
)
enabled_fixed_axis: BoolProperty(
name="Fixed Axis",
description="Use fixed axis",
default=False,
)
fixed_axis: FloatVectorProperty(
name="Fixed Axis",
description="Fixed axis",
subtype="XYZ",
size=3,
precision=3,
step=0.1,
default=[0, 0, 0],
)
enabled_local_axes: BoolProperty(
name="Local Axes",
description="Use local axes",
default=False,
)
local_axis_x: FloatVectorProperty(
name="Local X-Axis",
description="Local x-axis",
subtype="XYZ",
size=3,
precision=3,
step=0.1,
default=[1, 0, 0],
)
local_axis_z: FloatVectorProperty(
name="Local Z-Axis",
description="Local z-axis",
subtype="XYZ",
size=3,
precision=3,
step=0.1,
default=[0, 0, 1],
)
is_tip: BoolProperty(
name="Tip Bone",
description="Is zero length bone",
default=False,
)
ik_rotation_constraint: FloatProperty(
name="IK Rotation Constraint",
description="The unit angle of IK",
subtype="ANGLE",
soft_min=0,
soft_max=4,
default=1,
)
has_additional_rotation: BoolProperty(
name="Additional Rotation",
description="Additional rotation",
default=False,
update=_mmd_bone_update_additional_transform,
)
has_additional_location: BoolProperty(
name="Additional Location",
description="Additional location",
default=False,
update=_mmd_bone_update_additional_transform,
)
additional_transform_bone: StringProperty(
name="Additional Transform Bone",
description="Additional transform bone",
set=_mmd_bone_set_additional_transform_bone,
get=_mmd_bone_get_additional_transform_bone,
update=_mmd_bone_update_additional_transform,
)
additional_transform_bone_id: IntProperty(
name="Additional Transform Bone ID",
default=-1,
update=_mmd_bone_update_additional_transform,
)
additional_transform_influence: FloatProperty(
name="Additional Transform Influence",
description="Additional transform influence",
default=1,
soft_min=-1,
soft_max=1,
update=_mmd_bone_update_additional_transform_influence,
)
is_additional_transform_dirty: BoolProperty(
name="",
default=True
)
def is_id_unique(self):
"""Check if the bone ID is unique"""
return self.bone_id < 0 or not next((b for b in self.id_data.pose.bones if b.mmd_bone != self and b.mmd_bone.bone_id == self.bone_id), None)
def register():
"""Register MMD bone properties"""
logger.info("Registering MMD bone properties")
bpy.utils.register_class(MMDBone)
# Add properties to PoseBone
bpy.types.PoseBone.mmd_bone = bpy.props.PointerProperty(type=MMDBone)
bpy.types.PoseBone.is_mmd_shadow_bone = bpy.props.BoolProperty(
name="is_mmd_shadow_bone",
default=False
)
bpy.types.PoseBone.mmd_shadow_bone_type = bpy.props.StringProperty(
name="mmd_shadow_bone_type"
)
bpy.types.PoseBone.mmd_ik_toggle = bpy.props.BoolProperty(
name="MMD IK Toggle",
description="MMD IK toggle is used to import/export animation of IK on-off",
update=_pose_bone_update_mmd_ik_toggle,
default=True,
)
def unregister():
"""Unregister MMD bone properties"""
logger.info("Unregistering MMD bone properties")
# Remove properties from PoseBone
del bpy.types.PoseBone.mmd_ik_toggle
del bpy.types.PoseBone.mmd_shadow_bone_type
del bpy.types.PoseBone.is_mmd_shadow_bone
del bpy.types.PoseBone.mmd_bone
bpy.utils.unregister_class(MMDBone)
+582
View File
@@ -0,0 +1,582 @@
# -*- coding: utf-8 -*-
# Copyright 2014 MMD Tools authors
# This file was originally part of the MMD Tools project, However Neoneko has added it to Avatar Toolkit.
# All credit goes to the original authors.
# Please note that some code was modified to fit the needs of Avatar Toolkit and some code may of been removed.
# MMD Tools is licensed under the terms of the GPL-3.0 license which Avatar Toolkit is also licensed under.
# You can find MMD Tools at: https://github.com/MMD-Blender/blender_mmd_tools/
"""Properties for MMD model root object"""
import bpy
from .. import utils
from ..bpyutils import FnContext
from ..core.material import FnMaterial
from ..core.model import FnModel
from ..core.sdef import FnSDEF
from . import patch_library_overridable
from .morph import BoneMorph, GroupMorph, MaterialMorph, UVMorph, VertexMorph
from .translations import MMDTranslation
def __driver_variables(constraint: bpy.types.Constraint, path: str, index=-1):
d = constraint.driver_add(path, index)
variables = d.driver.variables
for x in variables:
variables.remove(x)
return d.driver, variables
def __add_single_prop(variables, id_obj, data_path, prefix):
var = variables.new()
var.name = prefix + str(len(variables))
var.type = "SINGLE_PROP"
target = var.targets[0]
target.id_type = "OBJECT"
target.id = id_obj
target.data_path = data_path
return var
def _toggleUsePropertyDriver(self: "MMDRoot", _context):
root_object: bpy.types.Object = self.id_data
armature_object = FnModel.find_armature_object(root_object)
if armature_object is None:
ik_map = {}
else:
bones = armature_object.pose.bones
ik_map = {bones[c.subtarget]: (b, c) for b in bones for c in b.constraints if c.type == "IK" and c.is_valid and c.subtarget in bones}
if self.use_property_driver:
for ik, (b, c) in ik_map.items():
driver, variables = __driver_variables(c, "influence")
driver.expression = "%s" % __add_single_prop(variables, ik.id_data, ik.path_from_id("mmd_ik_toggle"), "use_ik").name
b = b if c.use_tail else b.parent
for b in ([b] + b.parent_recursive)[: c.chain_count]:
c = next((c for c in b.constraints if c.type == "LIMIT_ROTATION" and not c.mute), None)
if c:
driver, variables = __driver_variables(c, "influence")
driver.expression = "%s" % __add_single_prop(variables, ik.id_data, ik.path_from_id("mmd_ik_toggle"), "use_ik").name
for i in FnModel.iterate_mesh_objects(root_object):
for prop_hide in ("hide_viewport", "hide_render"):
driver, variables = __driver_variables(i, prop_hide)
driver.expression = "not %s" % __add_single_prop(variables, root_object, "mmd_root.show_meshes", "show").name
else:
for ik, (b, c) in ik_map.items():
c.driver_remove("influence")
b = b if c.use_tail else b.parent
for b in ([b] + b.parent_recursive)[: c.chain_count]:
c = next((c for c in b.constraints if c.type == "LIMIT_ROTATION" and not c.mute), None)
if c:
c.driver_remove("influence")
for i in FnModel.iterate_mesh_objects(root_object):
for prop_hide in ("hide_viewport", "hide_render"):
i.driver_remove(prop_hide)
# ===========================================
# Callback functions
# ===========================================
def _toggleUseToonTexture(self: "MMDRoot", _context):
use_toon = self.use_toon_texture
for i in FnModel.iterate_mesh_objects(self.id_data):
for m in i.data.materials:
if m:
FnMaterial(m).use_toon_texture(use_toon)
def _toggleUseSphereTexture(self: "MMDRoot", _context):
use_sphere = self.use_sphere_texture
for i in FnModel.iterate_mesh_objects(self.id_data):
for m in i.data.materials:
if m:
FnMaterial(m).use_sphere_texture(use_sphere, i)
def _toggleUseSDEF(self: "MMDRoot", _context):
mute_sdef = not self.use_sdef
for i in FnModel.iterate_mesh_objects(self.id_data):
FnSDEF.mute_sdef_set(i, mute_sdef)
def _toggleVisibilityOfMeshes(self: "MMDRoot", context: bpy.types.Context):
root = self.id_data
hide = not self.show_meshes
for i in FnModel.iterate_mesh_objects(self.id_data):
i.hide_set(hide)
i.hide_render = hide
if hide and context.active_object is None:
FnContext.set_active_object(context, root)
def _toggleVisibilityOfRigidBodies(self: "MMDRoot", context: bpy.types.Context):
root = self.id_data
hide = not self.show_rigid_bodies
for i in FnModel.iterate_rigid_body_objects(root):
i.hide_set(hide)
if hide and context.active_object is None:
FnContext.set_active_object(context, root)
def _toggleVisibilityOfJoints(self: "MMDRoot", context):
root_object = self.id_data
hide = not self.show_joints
for i in FnModel.iterate_joint_objects(root_object):
i.hide_set(hide)
if hide and context.active_object is None:
FnContext.set_active_object(context, root_object)
def _toggleVisibilityOfTemporaryObjects(self: "MMDRoot", context: bpy.types.Context):
root_object: bpy.types.Object = self.id_data
hide = not self.show_temporary_objects
with FnContext.temp_override_active_layer_collection(context, root_object):
for i in FnModel.iterate_temporary_objects(root_object):
i.hide_set(hide)
if hide and context.active_object is None:
FnContext.set_active_object(context, root_object)
def _toggleShowNamesOfRigidBodies(self: "MMDRoot", _context):
root = self.id_data
show_names = root.mmd_root.show_names_of_rigid_bodies
for i in FnModel.iterate_rigid_body_objects(root):
i.show_name = show_names
def _toggleShowNamesOfJoints(self: "MMDRoot", _context):
root = self.id_data
show_names = root.mmd_root.show_names_of_joints
for i in FnModel.iterate_joint_objects(root):
i.show_name = show_names
def _setVisibilityOfMMDRigArmature(prop: "MMDRoot", v: bool):
root = prop.id_data
arm = FnModel.find_armature_object(root)
if arm is None:
return
if not v and bpy.context.active_object == arm:
FnContext.set_active_object(bpy.context, root)
arm.hide_set(not v)
def _getVisibilityOfMMDRigArmature(prop: "MMDRoot"):
if prop.id_data.mmd_type != "ROOT":
return False
arm = FnModel.find_armature_object(prop.id_data)
return arm and not arm.hide_get()
def _setActiveRigidbodyObject(prop: "MMDRoot", v: int):
obj = FnContext.get_scene_objects(bpy.context)[v]
if FnModel.is_rigid_body_object(obj):
FnContext.set_active_and_select_single_object(bpy.context, obj)
prop["active_rigidbody_object_index"] = v
def _getActiveRigidbodyObject(prop: "MMDRoot"):
context = bpy.context
active_obj = FnContext.get_active_object(context)
if FnModel.is_rigid_body_object(active_obj):
prop["active_rigidbody_object_index"] = FnContext.get_scene_objects(context).find(active_obj.name)
return prop.get("active_rigidbody_object_index", 0)
def _setActiveJointObject(prop: "MMDRoot", v: int):
obj = FnContext.get_scene_objects(bpy.context)[v]
if FnModel.is_joint_object(obj):
FnContext.set_active_and_select_single_object(bpy.context, obj)
prop["active_joint_object_index"] = v
def _getActiveJointObject(prop: "MMDRoot"):
context = bpy.context
active_obj = FnContext.get_active_object(context)
if FnModel.is_joint_object(active_obj):
prop["active_joint_object_index"] = FnContext.get_scene_objects(context).find(active_obj.name)
return prop.get("active_joint_object_index", 0)
def _setActiveMorph(prop: "MMDRoot", v: bool):
if "active_morph_indices" not in prop:
prop["active_morph_indices"] = [0] * 5
prop["active_morph_indices"][prop.get("active_morph_type", 3)] = v
def _getActiveMorph(prop: "MMDRoot"):
if "active_morph_indices" in prop:
return prop["active_morph_indices"][prop.get("active_morph_type", 3)]
return 0
def _setActiveMeshObject(prop: "MMDRoot", v: int):
obj = FnContext.get_scene_objects(bpy.context)[v]
if FnModel.is_mesh_object(obj):
FnContext.set_active_and_select_single_object(bpy.context, obj)
prop["active_mesh_index"] = v
def _getActiveMeshObject(prop: "MMDRoot"):
context = bpy.context
active_obj = FnContext.get_active_object(context)
if FnModel.is_mesh_object(active_obj):
prop["active_mesh_index"] = FnContext.get_scene_objects(context).find(active_obj.name)
return prop.get("active_mesh_index", -1)
# ===========================================
# Property classes
# ===========================================
class MMDDisplayItem(bpy.types.PropertyGroup):
"""PMX 表示項目(表示枠内の1項目)"""
type: bpy.props.EnumProperty(
name="Type",
description="Select item type",
items=[
("BONE", "Bone", "", 1),
("MORPH", "Morph", "", 2),
],
)
morph_type: bpy.props.EnumProperty(
name="Morph Type",
description="Select morph type",
items=[
("material_morphs", "Material", "Material Morphs", 0),
("uv_morphs", "UV", "UV Morphs", 1),
("bone_morphs", "Bone", "Bone Morphs", 2),
("vertex_morphs", "Vertex", "Vertex Morphs", 3),
("group_morphs", "Group", "Group Morphs", 4),
],
default="vertex_morphs",
)
class MMDDisplayItemFrame(bpy.types.PropertyGroup):
"""PMX 表示枠
PMXファイル内では表示枠がリストで格納されています。
"""
name_e: bpy.props.StringProperty(
name="Name(Eng)",
description="English Name",
default="",
)
# 特殊枠フラグ
# 特殊枠はファイル仕様上の固定枠(削除、リネーム不可)
is_special: bpy.props.BoolProperty(
name="Special",
description="Is special",
default=False,
)
# 表示項目のリスト
data: bpy.props.CollectionProperty(
name="Display Items",
type=MMDDisplayItem,
)
# 現在アクティブな項目のインデックス
active_item: bpy.props.IntProperty(
name="Active Display Item",
min=0,
default=0,
)
class MMDRoot(bpy.types.PropertyGroup):
"""MMDモデルデータ
モデルルート用に作成されたEmtpyオブジェクトで使用します
"""
name: bpy.props.StringProperty(
name="Name",
description="The name of the MMD model",
default="",
)
name_e: bpy.props.StringProperty(
name="Name (English)",
description="The english name of the MMD model",
default="",
)
comment_text: bpy.props.StringProperty(
name="Comment",
description="The text datablock of the comment",
default="",
)
comment_e_text: bpy.props.StringProperty(
name="Comment (English)",
description="The text datablock of the english comment",
default="",
)
ik_loop_factor: bpy.props.IntProperty(
name="MMD IK Loop Factor",
description="Scaling factor of MMD IK loop",
min=1,
soft_max=10,
max=100,
default=1,
)
# TODO: Replace to driver for NLA
show_meshes: bpy.props.BoolProperty(
name="Show Meshes",
description="Show all meshes of the MMD model",
# get=_show_meshes_get,
# set=_show_meshes_set,
update=_toggleVisibilityOfMeshes,
default=True,
)
show_rigid_bodies: bpy.props.BoolProperty(
name="Show Rigid Bodies",
description="Show all rigid bodies of the MMD model",
update=_toggleVisibilityOfRigidBodies,
)
show_joints: bpy.props.BoolProperty(
name="Show Joints",
description="Show all joints of the MMD model",
update=_toggleVisibilityOfJoints,
)
show_temporary_objects: bpy.props.BoolProperty(
name="Show Temps",
description="Show all temporary objects of the MMD model",
update=_toggleVisibilityOfTemporaryObjects,
)
show_armature: bpy.props.BoolProperty(
name="Show Armature",
description="Show the armature object of the MMD model",
get=_getVisibilityOfMMDRigArmature,
set=_setVisibilityOfMMDRigArmature,
)
show_names_of_rigid_bodies: bpy.props.BoolProperty(
name="Show Rigid Body Names",
description="Show rigid body names",
update=_toggleShowNamesOfRigidBodies,
)
show_names_of_joints: bpy.props.BoolProperty(
name="Show Joint Names",
description="Show joint names",
update=_toggleShowNamesOfJoints,
)
use_toon_texture: bpy.props.BoolProperty(
name="Use Toon Texture",
description="Use toon texture",
update=_toggleUseToonTexture,
default=True,
)
use_sphere_texture: bpy.props.BoolProperty(
name="Use Sphere Texture",
description="Use sphere texture",
update=_toggleUseSphereTexture,
default=True,
)
use_sdef: bpy.props.BoolProperty(
name="Use SDEF",
description="Use SDEF",
update=_toggleUseSDEF,
default=True,
)
use_property_driver: bpy.props.BoolProperty(
name="Use Property Driver",
description="Setup drivers for MMD property animation (Visibility and IK toggles)",
update=_toggleUsePropertyDriver,
default=False,
)
is_built: bpy.props.BoolProperty(
name="Is Built",
)
active_rigidbody_index: bpy.props.IntProperty(
name="Active Rigidbody Index",
min=0,
get=_getActiveRigidbodyObject,
set=_setActiveRigidbodyObject,
)
active_joint_index: bpy.props.IntProperty(
name="Active Joint Index",
min=0,
get=_getActiveJointObject,
set=_setActiveJointObject,
)
# *************************
# Display Items
# *************************
display_item_frames: bpy.props.CollectionProperty(
name="Display Frames",
type=MMDDisplayItemFrame,
)
active_display_item_frame: bpy.props.IntProperty(
name="Active Display Item Frame",
min=0,
default=0,
)
# *************************
# Morph
# *************************
material_morphs: bpy.props.CollectionProperty(
name="Material Morphs",
type=MaterialMorph,
)
uv_morphs: bpy.props.CollectionProperty(
name="UV Morphs",
type=UVMorph,
)
bone_morphs: bpy.props.CollectionProperty(
name="Bone Morphs",
type=BoneMorph,
)
vertex_morphs: bpy.props.CollectionProperty(name="Vertex Morphs", type=VertexMorph)
group_morphs: bpy.props.CollectionProperty(
name="Group Morphs",
type=GroupMorph,
)
active_morph_type: bpy.props.EnumProperty(
name="Active Morph Type",
description="Select current morph type",
items=[
("material_morphs", "Material", "Material Morphs", 0),
("uv_morphs", "UV", "UV Morphs", 1),
("bone_morphs", "Bone", "Bone Morphs", 2),
("vertex_morphs", "Vertex", "Vertex Morphs", 3),
("group_morphs", "Group", "Group Morphs", 4),
],
default="vertex_morphs",
)
active_morph: bpy.props.IntProperty(
name="Active Morph",
min=0,
set=_setActiveMorph,
get=_getActiveMorph,
)
morph_panel_show_settings: bpy.props.BoolProperty(
name="Morph Panel Show Settings",
description="Show Morph Settings",
default=True,
)
active_mesh_index: bpy.props.IntProperty(
name="Active Mesh",
min=0,
set=_setActiveMeshObject,
get=_getActiveMeshObject,
)
# *************************
# Translation
# *************************
translation: bpy.props.PointerProperty(
name="Translation",
type=MMDTranslation,
)
@staticmethod
def __get_select(prop: bpy.types.Object) -> bool:
# TODO: Object.select is deprecated since v4.0.0, use Object.select_get() method instead
# utils.warn_deprecation("Object.select", "v4.0.0", "Use Object.select_get() method instead")
return prop.select_get()
@staticmethod
def __set_select(prop: bpy.types.Object, value: bool) -> None:
# TODO: Object.select is deprecated since v4.0.0, use Object.select_set() method instead
# utils.warn_deprecation("Object.select", "v4.0.0", "Use Object.select_set() method instead")
prop.select_set(value)
@staticmethod
def __get_hide(prop: bpy.types.Object) -> bool:
# TODO: Object.hide is deprecated since v4.0.0, use Object.hide_get() method instead
# utils.warn_deprecation("Object.hide", "v4.0.0", "Use Object.hide_get() method instead")
return prop.hide_get()
@staticmethod
def __set_hide(prop: bpy.types.Object, value: bool) -> None:
# TODO: Object.hide is deprecated since v4.0.0, use Object.hide_set() method instead
# utils.warn_deprecation("Object.hide", "v4.0.0", "Use Object.hide_set() method instead")
prop.hide_set(value)
if prop.hide_viewport != value:
prop.hide_viewport = value
@staticmethod
def register():
bpy.types.Object.mmd_type = patch_library_overridable(
bpy.props.EnumProperty(
name="Type",
description="Internal MMD type of this object (DO NOT CHANGE IT DIRECTLY)",
default="NONE",
items=[
("NONE", "None", "", 1),
("ROOT", "Root", "", 2),
("RIGID_GRP_OBJ", "Rigid Body Grp Empty", "", 3),
("JOINT_GRP_OBJ", "Joint Grp Empty", "", 4),
("TEMPORARY_GRP_OBJ", "Temporary Grp Empty", "", 5),
("PLACEHOLDER", "Place Holder", "", 6),
("CAMERA", "Camera", "", 21),
("JOINT", "Joint", "", 22),
("RIGID_BODY", "Rigid body", "", 23),
("LIGHT", "Light", "", 24),
("TRACK_TARGET", "Track Target", "", 51),
("NON_COLLISION_CONSTRAINT", "Non Collision Constraint", "", 52),
("SPRING_CONSTRAINT", "Spring Constraint", "", 53),
("SPRING_GOAL", "Spring Goal", "", 54),
],
)
)
bpy.types.Object.mmd_root = patch_library_overridable(bpy.props.PointerProperty(type=MMDRoot))
bpy.types.Object.select = patch_library_overridable(
bpy.props.BoolProperty(
get=MMDRoot.__get_select,
set=MMDRoot.__set_select,
options={
"SKIP_SAVE",
"ANIMATABLE",
"LIBRARY_EDITABLE",
},
)
)
bpy.types.Object.hide = patch_library_overridable(
bpy.props.BoolProperty(
get=MMDRoot.__get_hide,
set=MMDRoot.__set_hide,
options={
"SKIP_SAVE",
"ANIMATABLE",
"LIBRARY_EDITABLE",
},
)
)
@staticmethod
def unregister():
del bpy.types.Object.hide
del bpy.types.Object.select
del bpy.types.Object.mmd_root
del bpy.types.Object.mmd_type