Skip to content

Commit

Permalink
Set panel order
Browse files Browse the repository at this point in the history
  • Loading branch information
UuuNyaa committed Jun 13, 2024
1 parent a7e75d7 commit 47f4d17
Show file tree
Hide file tree
Showing 19 changed files with 1,154 additions and 1,030 deletions.
6 changes: 3 additions & 3 deletions mmd_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
bl_info = {
"name": "mmd_tools",
"author": "sugiany",
"version": (4, 2, 0),
"version": (4, 2, 1),
"blender": (4, 2, 0),
"location": "View3D > Sidebar > MMD Panel",
"description": "Utility tools for MMD model editing. (UuuNyaa's forked version)",
Expand Down Expand Up @@ -47,8 +47,8 @@
def register():
import bpy

import mmd_tools.operators.addon_updater
import mmd_tools.handlers
import mmd_tools.operators.addon_updater

mmd_tools.auto_load.register()

Expand All @@ -64,8 +64,8 @@ def register():
def unregister():
import bpy

import mmd_tools.operators.addon_updater
import mmd_tools.handlers
import mmd_tools.operators.addon_updater

mmd_tools.handlers.MMDHanders.unregister()
mmd_tools.operators.addon_updater.unregister_updater()
Expand Down
49 changes: 49 additions & 0 deletions mmd_tools/blender_manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
schema_version = "1.0.0"

id = "mmd_tools"
version = "4.2.1"
name = "MMD Tools"
tagline = "Utility tools for MMD model editing"
maintainer = "UuuNyaa <[email protected]>"
type = "add-on"

website = "https://mmd-blender.fandom.com/wiki/MMD_Tools"

# Optional list defined by Blender and server, see:
# https://docs.blender.org/manual/en/dev/advanced/extensions/tags.html
tags = [
"3D View",
"Camera",
"Import-Export",
"Material",
"Mesh",
"Object",
"Physics",
]

blender_version_min = "4.2.0"
blender_version_max = "5.0.0"

license = ["SPDX:GPL-3.0-or-later"]
copyright = ["2021 UuuNyaa", "2014-2022 powroupi", "2012-2015 sugiany"]

## Optional: add-ons can list which resources they will require:
## * files (for access of any filesystem operations)
## * network (for internet access)
## * clipboard (to read and/or write the system clipboard)
## * camera (to capture photos and videos)
## * microphone (to capture audio)
##
## If using network, remember to also check `bpy.app.online_access`
## https://docs.blender.org/manual/en/dev/advanced/extensions/addons.html#internet-access
##
## For each permission it is important to also specify the reason why it is required.
## Keep this a single short sentence without a period (.) at the end.
## For longer explanations use the documentation or detail page.
[permissions]
files = "Import/export PMD/PMX/VMD/VPD from/to disk"

# Optional: build settings.
# https://docs.blender.org/manual/en/dev/advanced/extensions/command_line_arguments.html#command-line-args-extension-build
[build]
paths_exclude_pattern = ["__pycache__/", ".vscode/", ".venv/"]
30 changes: 19 additions & 11 deletions mmd_tools/bpyutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ def __init__(self, active_object: bpy.types.Object, selected_objects: Optional[L
except Exception:
pass

for i in bpy.context.selected_objects:
contenxt = FnContext.ensure_context()

for i in contenxt.selected_objects:
i.select_set(False)

self.__active_object = active_object
Expand All @@ -55,8 +57,8 @@ def __init__(self, active_object: bpy.types.Object, selected_objects: Optional[L
self.__hides: List[bool] = []
for i in self.__selected_objects:
self.__hides.append(i.hide_get())
FnContext.select_object(bpy.context, i)
FnContext.set_active_object(bpy.context, active_object)
FnContext.select_object(contenxt, i)
FnContext.set_active_object(contenxt, active_object)

def __enter__(self) -> bpy.types.Object:
return self.__active_object
Expand Down Expand Up @@ -280,15 +282,16 @@ def mesh_remove_shape_key(mesh_object: bpy.types.Object, shape_key: bpy.types.Sh
key: bpy.types.Key = shape_key.id_data
assert key == mesh_object.data.shape_keys

fc_curve: bpy.types.FCurve
for fc_curve in mesh_object.animation_data.drivers:
if not fc_curve.data_path.startswith(shape_key.path_from_id()):
continue
mesh_object.driver_remove(fc_curve.data_path)
if mesh_object.animation_data is not None:
fc_curve: bpy.types.FCurve
for fc_curve in mesh_object.animation_data.drivers:
if not fc_curve.data_path.startswith(shape_key.path_from_id()):
continue
mesh_object.driver_remove(fc_curve.data_path)

key_blocks = key.key_blocks

last_index = mesh_object.active_shape_key_index
last_index = mesh_object.active_shape_key_index or 0
if last_index >= key_blocks.find(shape_key.name):
last_index = max(0, last_index - 1)

Expand Down Expand Up @@ -316,6 +319,10 @@ def set_active_object(context: bpy.types.Context, obj: bpy.types.Object) -> bpy.
context.view_layer.objects.active = obj
return obj

@staticmethod
def set_active_and_select_single_object(context: bpy.types.Context, obj: bpy.types.Object) -> bpy.types.Object:
return FnContext.set_active_object(context, FnContext.select_single_object(context, obj))

@staticmethod
def get_scene_objects(context: bpy.types.Context) -> bpy.types.SceneObjects:
return context.scene.objects
Expand All @@ -341,7 +348,7 @@ def __layer_check(layer_collection: bpy.types.LayerCollection) -> bool:
return True
return False

selected_objects = context.selected_objects
selected_objects = set(context.selected_objects)
__layer_check(context.view_layer.layer_collection)
if len(context.selected_objects) != len(selected_objects):
for i in context.selected_objects:
Expand All @@ -361,7 +368,8 @@ def select_objects(context: bpy.types.Context, *objects: bpy.types.Object) -> Li
@staticmethod
def select_single_object(context: bpy.types.Context, obj: bpy.types.Object) -> bpy.types.Object:
for i in context.selected_objects:
i.select_set(False)
if i != obj:
i.select_set(False)
return FnContext.select_object(context, obj)

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion mmd_tools/core/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ def create(name: str, name_e: str = "", scale: float = 1, obj_name: Optional[str
armature_object.pose.bones[bone_name].mmd_bone.name_j = bone_name
armature_object.pose.bones[bone_name].mmd_bone.name_e = "Root"

FnContext.set_active_object(context, FnContext.select_single_object(context, root))
FnContext.set_active_and_select_single_object(context, root)
return Model(root)

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion mmd_tools/operators/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ def execute(self, context: bpy.types.Context):
active_object: bpy.types.Object = context.active_object
mmd_root_object = FnModel.find_root_object(active_object)
assert mmd_root_object is not None
mmd_root = cast(MMDRoot, mmd_root_object.mmd_root)
mmd_root = mmd_root_object.mmd_root

mmd_root_object.hide_set(False)

Expand Down
4 changes: 2 additions & 2 deletions mmd_tools/panels/prop_bone.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
# Copyright 2015 MMD Tools authors
# This file is part of MMD Tools.

from bpy.types import Panel
import bpy


class MMDBonePanel(Panel):
class MMDBonePanel(bpy.types.Panel):
bl_idname = "BONE_PT_mmd_tools_bone"
bl_label = "MMD Bone Tools"
bl_space_type = "PROPERTIES"
Expand Down
100 changes: 100 additions & 0 deletions mmd_tools/panels/sidebar/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
# Copyright 2024 MMD Tools authors
# This file is part of MMD Tools.

from typing import Optional

import bpy

from mmd_tools.bpyutils import FnContext
from mmd_tools.core.model import FnModel


class FnDraw:
@staticmethod
def draw_bone_special(layout: bpy.types.UILayout, armature: bpy.types.Object, bone_name: str, mmd_name: Optional[str] = None):
if armature is None:
return
row = layout.row(align=True)
p_bone: bpy.types.PoseBone = armature.pose.bones.get(bone_name, None)
if p_bone:
bone = p_bone.bone
if mmd_name:
row.prop(p_bone.mmd_bone, mmd_name, text="", emboss=True)
ic = "RESTRICT_VIEW_ON" if bone.hide else "RESTRICT_VIEW_OFF"
row.prop(bone, "hide", text="", emboss=p_bone.mmd_bone.is_tip, icon=ic)
row.active = armature.mode != "EDIT"
else:
row.label() # for alignment only
row.label(icon="ERROR")


class PT_PanelBase:
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "MMD"


class PT_ProductionPanelBase(PT_PanelBase):
@classmethod
def poll(cls, context):
return FnContext.get_addon_preferences_attribute(context, "enable_mmd_model_production_features", True)


class UL_ObjectsMixIn:
model_filter: bpy.props.EnumProperty(
name="Model Filter",
description="Show items of active model or all models",
items=[
("ACTIVE", "Active Model", "", 0),
("ALL", "All Models", "", 1),
],
default="ACTIVE",
)
visible_only: bpy.props.BoolProperty(
name="Visible Only",
description="Only show visible items",
default=False,
)

def draw_item(self, context, layout, _data, item, _icon, _active_data, _active_propname, _index):
if self.layout_type in {"DEFAULT", "COMPACT"}:
row = layout.split(factor=0.5, align=True)
item_prop = getattr(item, self.prop_name)
row.prop(item_prop, "name_j", text="", emboss=False, icon=self.icon)
row = row.row(align=True)
row.prop(item_prop, "name_e", text="", emboss=True)
self.draw_item_special(context, row, item)
elif self.layout_type in {"GRID"}:
layout.alignment = "CENTER"
layout.label(text="", icon=self.icon)

def draw_filter(self, context, layout):
row = layout.row(align=True)
row.prop(self, "model_filter", expand=True)
row.prop(self, "visible_only", text="", toggle=True, icon="RESTRICT_VIEW_OFF")

def filter_items(self, context, data, propname):
objects = getattr(data, propname)
flt_flags = [~self.bitflag_filter_item] * len(objects)
flt_neworder = list(range(len(objects)))

if self.model_filter == "ACTIVE":
active_root = FnModel.find_root_object(context.active_object)
for i, obj in enumerate(objects):
if obj.mmd_type == self.mmd_type and FnModel.find_root_object(obj) == active_root:
flt_flags[i] = self.bitflag_filter_item
else:
for i, obj in enumerate(objects):
if obj.mmd_type == self.mmd_type:
flt_flags[i] = self.bitflag_filter_item

if self.visible_only:
for i, obj in enumerate(objects):
if obj.hide_get() and flt_flags[i] == self.bitflag_filter_item:
flt_flags[i] = ~self.bitflag_filter_item

indices = (i for i, x in enumerate(flt_flags) if x == self.bitflag_filter_item)
for i_new, i_orig in enumerate(sorted(indices, key=lambda k: objects[k].name)):
flt_neworder[i_orig] = i_new
return flt_flags, flt_neworder
Loading

0 comments on commit 47f4d17

Please sign in to comment.