Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support to (Partially) MMD Tools formats #104

Merged
merged 2 commits into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Blender add-on for importing some files from drag-and-drop.
- `*.gltf`
- `*.obj`
- `*.ply`
- `*.pmx` (Required [MMD Tools](https://github.com/UuuNyaa/blender_mmd_tools))
- `*.stl`
- `*.svg`
- `*.usd`
Expand Down
2 changes: 2 additions & 0 deletions src/addon/formats/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from . import glb
from . import obj
from . import obj_legacy
from . import pmx
from . import png
from . import ply
from . import stl
Expand All @@ -36,6 +37,7 @@
CLASSES.extend(fbx.OPERATORS)
CLASSES.extend(glb.OPERATORS)
CLASSES.extend(obj.OPERATORS)
CLASSES.extend(pmx.OPERATORS)
CLASSES.extend(png.OPERATORS)
CLASSES.extend(ply.OPERATORS)
CLASSES.extend(stl.OPERATORS)
Expand Down
190 changes: 190 additions & 0 deletions src/addon/formats/pmx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# ------------------------------------------------------------------------------------------
# Copyright (c) Natsuneko. All rights reserved.
# Licensed under the MIT License. See LICENSE in the project root for license information.
# ------------------------------------------------------------------------------------------

# pyright: reportGeneralTypeIssues=false
# pyright: reportUnknownArgumentType=false
# pyright: reportUnknownMemberType=false
# pyright: reportInvalidTypeForm=false

from typing import Set
import bpy

from bpy.props import (
BoolProperty, # pyright: ignore[reportUnknownVariableType]
EnumProperty, # pyright: ignore[reportUnknownVariableType]
FloatProperty, # pyright: ignore[reportUnknownVariableType]
IntProperty, # pyright: ignore[reportUnknownVariableType]
)
from bpy.types import Context

from .super import (
ImportWithDefaultsBase,
ImportsWithCustomSettingsBase,
VIEW3D_MT_Space_Import_BASE,
)


def include_types(cls, _): # type: ignore
types = cls.types.copy() # type: ignore

if "PHYSICS" in types:
types.add("ARMATURE")
if "DISPLAY" in types:
types.add("ARMATURE")
if "MORPHS" in types:
types.add("ARMATURE")
types.add("MESH")

if types != cls.types:
cls.types = types


class ImportPMXWithDefaults(ImportWithDefaultsBase):
bl_idname = "object.import_pmx_with_defaults"
bl_label = "Import MikuMikuDance Model File"

def execute(self, context: Context) -> Set[str] | Set[int]:
bpy.ops.mmd_tools.import_model(filepath=self.filepath())
return {"FINISHED"}


class ImportPMXWithCustomSettings(ImportsWithCustomSettingsBase):
bl_idname = "object.import_pmx_with_custom_settings"
bl_label = "Import MikuMikuDance Model File"

# Properties based on MMD Tools 2.x
# https://github.com/UuuNyaa/blender_mmd_tools/blob/d148bdbd520a0ddb2ffd0389a0217a297ad107f0/mmd_tools/operators/fileio.py#L62
types: EnumProperty(
default={
"MESH",
"ARMATURE",
"PHYSICS",
"DISPLAY",
"MORPHS",
},
name="Types",
items=[
("MESH", "Mesh", "Mesh", 1),
("ARMATURE", "Armature", "Armature", 2),
("PHYSICS", "Physics", "Rigidbodies and joints (include Armature)", 4),
("DISPLAY", "Display", "Display frames (include Armature)", 8),
("MORPHS", "Morphs", "Morphs (include Armature and Mesh)", 16),
], # type: ignore
options={"ENUM_FLAG"},
update=include_types,
)
scale: FloatProperty(default=0.08, min=1e-06, max=1e06, name="Scale")
clean_model: BoolProperty(
default=True,
name="Clean Model",
description="Remove unused vertices, materials, and textures",
)
remove_doubles: BoolProperty(
default=True,
name="Remove Doubles",
description="Merge duplicated vertices and faces",
)
fix_IK_links: BoolProperty(
default=False,
name="Fix IK Links",
description="Fix IK links to be Blender suitable",
)
ik_loop_factor: IntProperty(
default=5,
min=1,
soft_max=10,
max=100,
name="IK Loop Factor",
description="Scaling factor of MMD IK loop",
)
apply_bone_fixed_axis: BoolProperty(
default=False,
name="Apply Bone Fixed Axis",
description="Apply bone's fixed axis to be Blender Suitable",
)
rename_bones: BoolProperty(
default=True,
name="Rename Bones - L / R Suffix",
description="Use Blender naming convention for Left / Right paired bones",
)
use_underscore: BoolProperty(
default=False,
name="Rename Bones - Use Underscore",
description="Will not use dot, e.g. if renaming bones, will use _R instead of .R",
)
# dictionary: EnumProperty() # NOT SUPPORTED YET IN Drag-and-Drop Support
use_mipmap: BoolProperty(
default=True,
name="Use MIP maps for UV textures",
description="Specify if mipmaps will be generated",
)
sph_blend_factor: FloatProperty(
default=1.0,
name="Influence of .sph textures",
description="The diffuse color factor of texture slot for .sph textures",
)
spa_blend_factor: FloatProperty(
default=1.0,
name="Influence of .spa textures",
description="The specular color factor of texture slot for .spa textures",
)

def draw(self, context: Context):
column = self.get_column()
column.prop(self, "types")
column.prop(self, "scale")
column.prop(self, "clean_model")
column.prop(self, "remove_doubles")
column.prop(self, "fix_IK_links")
column.prop(self, "ik_loop_factor")
column.prop(self, "apply_bone_fixed_axis")
column.prop(self, "rename_bones")
column.prop(self, "use_underscore")
column.prop(self, "use_mipmap")
column.prop(self, "sph_blend_factor")
column.prop(self, "spa_blend_factor")

def execute(self, context: Context) -> Set[str] | Set[int]:
bpy.ops.mmd_tools.import_model(
filepath=self.filepath(),
types=self.types,
scale=self.scale,
clean_model=self.clean_model,
remove_doubles=self.remove_doubles,
fix_IK_links=self.fix_IK_links,
ik_loop_factor=self.ik_loop_factor,
apply_bone_fixed_axis=self.apply_bone_fixed_axis,
rename_LR_bones=self.rename_bones,
use_underscore=self.use_underscore,
use_mipmap=self.use_mipmap,
sph_blend_factor=self.sph_blend_factor,
spa_blend_factor=self.spa_blend_factor,
)

return {"FINISHED"}


class VIEW3D_MT_Space_Import_PMD(VIEW3D_MT_Space_Import_BASE):
bl_label = "Import MikuMikuDance Model File"

@staticmethod
def format():
return "pmx"


class VIEW3D_MT_Space_Import_PMX(VIEW3D_MT_Space_Import_BASE):
bl_label = "Import MikuMikuDance Model File"

@staticmethod
def format():
return "pmx"


OPERATORS = [
ImportPMXWithDefaults,
ImportPMXWithCustomSettings,
VIEW3D_MT_Space_Import_PMD,
VIEW3D_MT_Space_Import_PMX,
]
4 changes: 4 additions & 0 deletions src/addon/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
# formats that Blender does not supported by default
conditionals: typing.Dict[str, typing.Callable[[], bool]] = {
"3mf": lambda: hasattr(bpy.ops.import_mesh, "threemf"),
"pmd": lambda: hasattr(bpy.ops, "mmd_tools"),
"pmx": lambda: hasattr(bpy.ops, "mmd_tools"),
"vmd": lambda: hasattr(bpy.ops, "mmd_tools"),
"vpd": lambda: hasattr(bpy.ops, "mmd_tools"),
"vrm": lambda: hasattr(bpy.ops.import_scene, "vrm"),
}

Expand Down