Plugin Registration Changes
- Re-wrote how the plugin registers itself. - No longer need @register_wrapper classes get auto detected and added. - The new Auto loader is much better then the old way, no longer need "if "bpy" not in locals():" this was an old way of doing things and wasn't really efficient. using auto_load.py provides several advantages: - It automatically discovers and loads all modules in the addon. - It handles dependencies between classes correctly through topological sorting. - It manages registration order automatically. - It properly handles unregistration in the correct order. This approach is much less error prone and I not had any issues so far. However it still needs testing fully. I have also start to re-organise files into folders as well, this is going to be needed so we don't have a long list of files as Avatar Toolkit is getting larger then i originally planned.
This commit is contained in:
+9
-51
@@ -1,55 +1,13 @@
|
|||||||
if "bpy" not in locals():
|
modules = None
|
||||||
import bpy
|
ordered_classes = None
|
||||||
from . import ui
|
|
||||||
from . import core
|
|
||||||
from . import functions
|
|
||||||
from .core import register
|
|
||||||
from .core.register import __bl_ordered_classes
|
|
||||||
from .core import properties
|
|
||||||
from .core import addon_preferences
|
|
||||||
from .core.updater import check_for_update_on_start
|
|
||||||
else:
|
|
||||||
import importlib
|
|
||||||
importlib.reload(ui)
|
|
||||||
importlib.reload(core)
|
|
||||||
importlib.reload(functions)
|
|
||||||
importlib.reload(properties)
|
|
||||||
importlib.reload(addon_preferences)
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
print("Registering Avatar Toolkit")
|
from .core import auto_load
|
||||||
# Register the addon properties
|
print("Starting registration")
|
||||||
properties.register()
|
auto_load.init()
|
||||||
|
auto_load.register()
|
||||||
# Load the translations
|
print("Registration complete")
|
||||||
functions.translations.load_translations()
|
|
||||||
|
|
||||||
# Order the classes before registration
|
|
||||||
core.register.order_classes()
|
|
||||||
# Register the UI classes
|
|
||||||
for cls in core.register.__bl_ordered_classes:
|
|
||||||
print("registering " + str(cls))
|
|
||||||
bpy.utils.register_class(cls)
|
|
||||||
|
|
||||||
#finally register properties that may use some classes.
|
|
||||||
core.register.register_properties()
|
|
||||||
|
|
||||||
bpy.app.handlers.load_post.append(check_for_update_on_start)
|
|
||||||
|
|
||||||
from .functions.mesh_tools import AvatarToolkit_OT_ApplyShapeKey
|
|
||||||
|
|
||||||
bpy.types.MESH_MT_shape_key_context_menu.append((lambda self, context: self.layout.separator()))
|
|
||||||
bpy.types.MESH_MT_shape_key_context_menu.append((lambda self, context: self.layout.operator(AvatarToolkit_OT_ApplyShapeKey.bl_idname, icon="KEY_HLT")))
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
print("Unregistering Avatar Toolkit")
|
from .core import auto_load
|
||||||
# Unregister the UI classes
|
auto_load.unregister()
|
||||||
if check_for_update_on_start in bpy.app.handlers.load_post:
|
|
||||||
bpy.app.handlers.load_post.remove(check_for_update_on_start)
|
|
||||||
|
|
||||||
# Iterate over the classes to unregister in reverse order and unregister them
|
|
||||||
for cls in reversed(list(__bl_ordered_classes)):
|
|
||||||
bpy.utils.unregister_class(cls)
|
|
||||||
print("unregistering " + str(cls))
|
|
||||||
core.register.unregister_properties()
|
|
||||||
properties.unregister()
|
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# core/__init__.py
|
|
||||||
|
|
||||||
from .register import register_wrap
|
|
||||||
|
|
||||||
#to reload all things in this directory and import them properly - @989onan
|
|
||||||
if "bpy" not in locals():
|
|
||||||
import bpy
|
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
from os.path import dirname, basename, isfile, join
|
|
||||||
modules = glob.glob(join(dirname(__file__), "*.py"))
|
|
||||||
for module_name in [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]:
|
|
||||||
exec("from . import "+module_name)
|
|
||||||
print("importing " +module_name)
|
|
||||||
else:
|
|
||||||
import importlib
|
|
||||||
modules = glob.glob(join(dirname(__file__), "*.py"))
|
|
||||||
for module_name in [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]:
|
|
||||||
exec("importlib.reload("+module_name+")")
|
|
||||||
print("reloading " +module_name)
|
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
import os
|
||||||
|
import bpy
|
||||||
|
import sys
|
||||||
|
import typing
|
||||||
|
import inspect
|
||||||
|
import pkgutil
|
||||||
|
import tomllib
|
||||||
|
import importlib
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
|
"init",
|
||||||
|
"register",
|
||||||
|
"unregister",
|
||||||
|
)
|
||||||
|
|
||||||
|
modules = None
|
||||||
|
ordered_classes = None
|
||||||
|
|
||||||
|
def init():
|
||||||
|
global modules
|
||||||
|
global ordered_classes
|
||||||
|
print("Auto-load init starting")
|
||||||
|
modules = get_all_submodules(Path(__file__).parent.parent)
|
||||||
|
ordered_classes = get_ordered_classes_to_register(modules)
|
||||||
|
print(f"Found modules: {modules}")
|
||||||
|
print(f"Found classes: {ordered_classes}")
|
||||||
|
|
||||||
|
def register():
|
||||||
|
print("Registering classes")
|
||||||
|
for cls in ordered_classes:
|
||||||
|
print(f"Registering: {cls}")
|
||||||
|
try:
|
||||||
|
bpy.utils.register_class(cls)
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for module in modules:
|
||||||
|
if module.__name__ == __name__:
|
||||||
|
continue
|
||||||
|
if hasattr(module, "register"):
|
||||||
|
module.register()
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
for cls in reversed(ordered_classes):
|
||||||
|
bpy.utils.unregister_class(cls)
|
||||||
|
|
||||||
|
for module in modules:
|
||||||
|
if module.__name__ == __name__:
|
||||||
|
continue
|
||||||
|
if hasattr(module, "unregister"):
|
||||||
|
module.unregister()
|
||||||
|
|
||||||
|
def get_manifest_id():
|
||||||
|
manifest_path = Path(__file__).parent.parent / "blender_manifest.toml"
|
||||||
|
with open(manifest_path, "rb") as f:
|
||||||
|
manifest = tomllib.load(f)
|
||||||
|
return manifest["id"]
|
||||||
|
|
||||||
|
def get_all_submodules(directory):
|
||||||
|
modules = []
|
||||||
|
addon_id = get_manifest_id()
|
||||||
|
for root, dirs, files in os.walk(directory):
|
||||||
|
if "__pycache__" in root:
|
||||||
|
continue
|
||||||
|
path = Path(root)
|
||||||
|
if path == directory:
|
||||||
|
package_name = f"bl_ext.user_default.{addon_id}"
|
||||||
|
else:
|
||||||
|
relative_path = path.relative_to(directory).as_posix().replace('/', '.')
|
||||||
|
package_name = f"bl_ext.user_default.{addon_id}.{relative_path}"
|
||||||
|
for name in sorted(iter_module_names(path)):
|
||||||
|
modules.append(importlib.import_module(f".{name}", package_name))
|
||||||
|
return modules
|
||||||
|
|
||||||
|
def iter_submodules(path, package_name):
|
||||||
|
for name in sorted(iter_module_names(path)):
|
||||||
|
yield importlib.import_module("." + name, package_name)
|
||||||
|
|
||||||
|
def iter_module_names(path):
|
||||||
|
print(f"Scanning path: {path}") # Debug path
|
||||||
|
modules_list = list(pkgutil.iter_modules([str(path)]))
|
||||||
|
print(f"Found these modules: {modules_list}") # Debug modules
|
||||||
|
for _, module_name, is_pkg in modules_list:
|
||||||
|
if not is_pkg:
|
||||||
|
print(f"Found module: {module_name}")
|
||||||
|
yield module_name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_ordered_classes_to_register(modules):
|
||||||
|
return toposort(get_register_deps_dict(modules))
|
||||||
|
|
||||||
|
def get_register_deps_dict(modules):
|
||||||
|
deps_dict = {}
|
||||||
|
classes_to_register = set(iter_classes_to_register(modules))
|
||||||
|
for cls in classes_to_register:
|
||||||
|
deps_dict[cls] = set(iter_own_register_deps(cls, classes_to_register))
|
||||||
|
return deps_dict
|
||||||
|
|
||||||
|
def iter_own_register_deps(cls, classes_to_register):
|
||||||
|
yield from (dep for dep in iter_register_deps(cls) if dep in classes_to_register)
|
||||||
|
|
||||||
|
def iter_register_deps(cls):
|
||||||
|
for value in typing.get_type_hints(cls, {}, {}).values():
|
||||||
|
dependency = get_dependency_from_annotation(value)
|
||||||
|
if dependency is not None:
|
||||||
|
yield dependency
|
||||||
|
|
||||||
|
def get_dependency_from_annotation(value):
|
||||||
|
if isinstance(value, tuple) and len(value) == 2:
|
||||||
|
if value[0] in (bpy.props.PointerProperty, bpy.props.CollectionProperty):
|
||||||
|
return value[1]["type"]
|
||||||
|
return None
|
||||||
|
|
||||||
|
def iter_classes_to_register(modules):
|
||||||
|
base_types = get_register_base_types()
|
||||||
|
for cls in get_classes_in_modules(modules):
|
||||||
|
if any(base in base_types for base in cls.__bases__):
|
||||||
|
if not getattr(cls, "_is_registered", False):
|
||||||
|
yield cls
|
||||||
|
|
||||||
|
def get_classes_in_modules(modules):
|
||||||
|
classes = set()
|
||||||
|
for module in modules:
|
||||||
|
for cls in iter_classes_in_module(module):
|
||||||
|
classes.add(cls)
|
||||||
|
return classes
|
||||||
|
|
||||||
|
def iter_classes_in_module(module):
|
||||||
|
for value in module.__dict__.values():
|
||||||
|
if inspect.isclass(value):
|
||||||
|
yield value
|
||||||
|
|
||||||
|
def get_register_base_types():
|
||||||
|
return set(getattr(bpy.types, name) for name in [
|
||||||
|
"Panel", "Operator", "PropertyGroup",
|
||||||
|
"AddonPreferences", "Header", "Menu",
|
||||||
|
"Node", "NodeSocket", "NodeTree",
|
||||||
|
"UIList", "RenderEngine"
|
||||||
|
])
|
||||||
|
|
||||||
|
def toposort(deps_dict):
|
||||||
|
sorted_list = []
|
||||||
|
sorted_values = set()
|
||||||
|
|
||||||
|
# First pass: Register panels without parents
|
||||||
|
panels_to_sort = [(value, deps) for value, deps in deps_dict.items()
|
||||||
|
if hasattr(value, 'bl_parent_id')]
|
||||||
|
|
||||||
|
base_panels = [(value, deps) for value, deps in deps_dict.items()
|
||||||
|
if not hasattr(value, 'bl_parent_id')]
|
||||||
|
|
||||||
|
# Add base panels first
|
||||||
|
for value, deps in base_panels:
|
||||||
|
if len(deps) == 0:
|
||||||
|
sorted_list.append(value)
|
||||||
|
sorted_values.add(value)
|
||||||
|
|
||||||
|
# Then add child panels
|
||||||
|
while len(deps_dict) > len(sorted_values):
|
||||||
|
unsorted = []
|
||||||
|
for value, deps in deps_dict.items():
|
||||||
|
if value not in sorted_values:
|
||||||
|
if len(deps - sorted_values) == 0:
|
||||||
|
sorted_list.append(value)
|
||||||
|
sorted_values.add(value)
|
||||||
|
else:
|
||||||
|
unsorted.append(value)
|
||||||
|
|
||||||
|
return sorted_list
|
||||||
|
|
||||||
@@ -6,7 +6,6 @@ import time
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from ..core.register import register_wrap
|
|
||||||
from typing import List, Optional, Tuple
|
from typing import List, Optional, Tuple
|
||||||
from bpy.types import Object, ShapeKey, Mesh, Context, Material, PropertyGroup
|
from bpy.types import Object, ShapeKey, Mesh, Context, Material, PropertyGroup
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from .common import get_armature
|
from ...core.common import get_armature
|
||||||
from bpy.types import Object, ShapeKey, Mesh, Context, Operator
|
from bpy.types import Object, ShapeKey, Mesh, Context, Operator
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from ..core.register import register_wrap
|
from ...core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_ExportResonite(Operator):
|
class AvatarToolKit_OT_ExportResonite(Operator):
|
||||||
bl_idname = 'avatar_toolkit.export_resonite'
|
bl_idname = 'avatar_toolkit.export_resonite'
|
||||||
bl_label = t("Importer.export_resonite.label")
|
bl_label = t("Importer.export_resonite.label")
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"language": 0
|
|
||||||
}
|
|
||||||
+153
-142
@@ -1,169 +1,180 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..functions.translations import t, get_languages_list, update_language
|
from .translations import t, get_languages_list, update_language
|
||||||
from ..core.register import register_property
|
from bpy.types import PropertyGroup, Material, Scene, Object, Context
|
||||||
from bpy.types import Scene, Object, Material, Context
|
from bpy.props import (StringProperty, BoolProperty, EnumProperty,
|
||||||
from bpy.props import BoolProperty, EnumProperty, IntProperty, CollectionProperty, StringProperty, FloatVectorProperty, PointerProperty
|
IntProperty, FloatProperty, CollectionProperty,
|
||||||
from ..core.addon_preferences import get_preference
|
PointerProperty)
|
||||||
from ..core.common import SceneMatClass, MaterialListBool, get_armatures, get_mesh_items, get_armatures_that_are_not_selected
|
from .addon_preferences import get_preference
|
||||||
|
from .common import SceneMatClass, MaterialListBool, get_armatures, get_mesh_items, get_armatures_that_are_not_selected
|
||||||
from .updater import get_version_list
|
from .updater import get_version_list
|
||||||
|
|
||||||
def register() -> None:
|
class AvatarToolkitSceneProperties(PropertyGroup):
|
||||||
default_language = get_preference("language", 0)
|
language: EnumProperty(
|
||||||
register_property((bpy.types.Scene, "avatar_toolkit_language", bpy.props.EnumProperty(
|
name="Language",
|
||||||
name=t("Settings.language.label", "Language"),
|
description="Select the language for the addon",
|
||||||
description=t("Settings.language.desc", "Select the language for the addon"),
|
|
||||||
items=get_languages_list,
|
items=get_languages_list,
|
||||||
default=default_language,
|
|
||||||
update=update_language
|
update=update_language
|
||||||
)))
|
)
|
||||||
|
|
||||||
register_property((bpy.types.Scene, "selected_mesh", bpy.props.EnumProperty(
|
selected_mesh: EnumProperty(
|
||||||
items=get_mesh_items,
|
items=get_mesh_items,
|
||||||
name=t("VisemePanel.selected_mesh.label"),
|
name="Selected Mesh",
|
||||||
description=t("VisemePanel.selected_mesh.desc")
|
description="Select mesh to modify"
|
||||||
)))
|
)
|
||||||
|
|
||||||
register_property((bpy.types.Object, "material_group_expanded", bpy.props.BoolProperty(
|
material_search_filter: StringProperty(
|
||||||
name="Expand Material Group",
|
|
||||||
description="Show/hide materials for this mesh",
|
|
||||||
default=False
|
|
||||||
)))
|
|
||||||
|
|
||||||
register_property((bpy.types.Material, "material_expanded", bpy.props.BoolProperty(
|
|
||||||
name="Expand Material",
|
|
||||||
description="Show/hide material properties",
|
|
||||||
default=False
|
|
||||||
)))
|
|
||||||
|
|
||||||
register_property((bpy.types.Scene, "material_search_filter", bpy.props.StringProperty(
|
|
||||||
name="Search Materials",
|
name="Search Materials",
|
||||||
description="Filter materials by name",
|
description="Filter materials by name",
|
||||||
default=""
|
default=""
|
||||||
)))
|
)
|
||||||
|
|
||||||
register_property((bpy.types.Material, "include_in_atlas", bpy.props.BoolProperty(
|
merge_armature_apply_transforms: BoolProperty(
|
||||||
name=t("TextureAtlas.include_in_atlas"),
|
|
||||||
description=t("TextureAtlas.include_in_atlas_desc"),
|
|
||||||
default=True
|
|
||||||
)))
|
|
||||||
|
|
||||||
register_property((bpy.types.Scene, "merge_armature_apply_transforms", bpy.props.BoolProperty(
|
|
||||||
default=False,
|
default=False,
|
||||||
name=t("MergeArmature.merge_armatures.apply_transforms.label"),
|
name="Apply Transforms",
|
||||||
description=t("MergeArmature.merge_armatures.apply_transforms.desc")
|
description="Apply transforms when merging armatures"
|
||||||
)))
|
)
|
||||||
register_property((bpy.types.Scene, "merge_armature_align_bones", bpy.props.BoolProperty(
|
|
||||||
|
merge_armature_align_bones: BoolProperty(
|
||||||
default=False,
|
default=False,
|
||||||
name=t("MergeArmature.merge_armatures.align_bones.label"),
|
name="Align Bones",
|
||||||
description=t("MergeArmature.merge_armatures.align_bones.desc")
|
description="Align bones when merging armatures"
|
||||||
)))
|
)
|
||||||
|
|
||||||
register_property((bpy.types.Scene, "avatar_toolkit_language_changed", bpy.props.BoolProperty(default=False)))
|
|
||||||
|
|
||||||
register_property((bpy.types.Scene, "avatar_toolkit_progress_steps", bpy.props.IntProperty(default=0)))
|
progress_steps: IntProperty(default=0)
|
||||||
register_property((bpy.types.Scene, "avatar_toolkit_progress_current", bpy.props.IntProperty(default=0)))
|
progress_current: IntProperty(default=0)
|
||||||
|
language_changed: BoolProperty(default=False)
|
||||||
|
|
||||||
register_property((bpy.types.Scene, "avatar_toolkit_mouth_a", bpy.props.StringProperty(
|
mouth_a: StringProperty(
|
||||||
name=t("VisemePanel.mouth_a.label"),
|
name="Mouth A",
|
||||||
description=t("VisemePanel.mouth_a.desc")
|
description="Shape key for A sound"
|
||||||
)))
|
)
|
||||||
register_property((bpy.types.Scene, "avatar_toolkit_mouth_o", bpy.props.StringProperty(
|
|
||||||
name=t("VisemePanel.mouth_o.label"),
|
mouth_o: StringProperty(
|
||||||
description=t("VisemePanel.mouth_o.desc")
|
name="Mouth O",
|
||||||
)))
|
description="Shape key for O sound"
|
||||||
register_property((bpy.types.Scene, "avatar_toolkit_mouth_ch", bpy.props.StringProperty(
|
)
|
||||||
name=t("VisemePanel.mouth_ch.label"),
|
|
||||||
description=t("VisemePanel.mouth_ch.desc")
|
mouth_ch: StringProperty(
|
||||||
)))
|
name="Mouth CH",
|
||||||
register_property((bpy.types.Scene, "avatar_toolkit_shape_intensity", bpy.props.FloatProperty(
|
description="Shape key for CH sound"
|
||||||
name=t("VisemePanel.shape_intensity"),
|
)
|
||||||
description=t("VisemePanel.shape_intensity_desc"),
|
|
||||||
|
shape_intensity: FloatProperty(
|
||||||
|
name="Shape Intensity",
|
||||||
|
description="Intensity of shape key modifications",
|
||||||
default=1.0,
|
default=1.0,
|
||||||
min=0.0,
|
min=0.0,
|
||||||
max=2.0
|
max=2.0
|
||||||
)))
|
)
|
||||||
register_property((bpy.types.Scene, "merge_twist_bones", bpy.props.BoolProperty(
|
|
||||||
name=t("Tools.merge_twist_bones.label"),
|
merge_twist_bones: BoolProperty(
|
||||||
description=t("Tools.merge_twist_bones.desc"),
|
name="Merge Twist Bones",
|
||||||
|
description="Merge twist bones during processing",
|
||||||
default=True
|
default=True
|
||||||
)))
|
)
|
||||||
|
|
||||||
register_property((bpy.types.Scene, "selected_armature", bpy.props.EnumProperty(
|
selected_armature: EnumProperty(
|
||||||
items=get_armatures,
|
items=get_armatures,
|
||||||
name=t("Quick_Access.selected_armature.label"),
|
name="Selected Armature",
|
||||||
description=t("Quick_Access.selected_armature.desc"),
|
description="Select the armature to work with"
|
||||||
default=0
|
)
|
||||||
)))
|
|
||||||
|
|
||||||
register_property((bpy.types.Scene, "merge_armature_source", bpy.props.EnumProperty(
|
merge_armature_source: EnumProperty(
|
||||||
items=get_armatures_that_are_not_selected,
|
items=get_armatures_that_are_not_selected,
|
||||||
name=t("MergeArmatures.selected_armature.label"),
|
name="Source Armature",
|
||||||
description=t("MergeArmatures.selected_armature.label"),
|
description="Select the source armature for merging"
|
||||||
default=0
|
)
|
||||||
)))
|
|
||||||
|
|
||||||
register_property((bpy.types.Scene, "avatar_toolkit_updater_version_list", bpy.props.EnumProperty(
|
texture_atlas_material_index: IntProperty(
|
||||||
name=t('Scene.avatar_toolkit_updater_version_list.name'),
|
default=-1,
|
||||||
description=t('Scene.avatar_toolkit_updater_version_list.description'),
|
get=lambda self: -1,
|
||||||
items=get_version_list
|
set=lambda self, context: None
|
||||||
)))
|
)
|
||||||
|
|
||||||
#happy with how compressed this get_texture_node_list method is - @989onan
|
|
||||||
def get_texture_node_list(self: Material, context: Context) -> list[set[3]]:
|
|
||||||
|
|
||||||
if self.use_nodes:
|
|
||||||
|
|
||||||
Object.Enum = [((i.image.name if i.image else i.name+"_image"),(i.image.name if i.image else "node with no image..."),(i.image.name if i.image else i.name),index+1) for index,i in enumerate(self.node_tree.nodes) if i.bl_idname == "ShaderNodeTexImage"]
|
|
||||||
if not len(Object.Enum):
|
|
||||||
Object.Enum = [(t("TextureAtlas.error.label"), t("TextureAtlas.no_images_error.desc") , t("TextureAtlas.error.label"), 0)]
|
|
||||||
else:
|
|
||||||
Object.Enum = [(t("TextureAtlas.error.label"), t("TextureAtlas.no_nodes_error.desc"), t("TextureAtlas.error.label"), 0)]
|
|
||||||
Object.Enum.append((t("TextureAtlas.none.label"), t("TextureAtlas.none.label"), t("TextureAtlas.none.label"), 0))
|
|
||||||
return Object.Enum
|
|
||||||
|
|
||||||
register_property((Material, "texture_atlas_albedo", EnumProperty(
|
|
||||||
name=t("TextureAtlas.albedo"),
|
|
||||||
description=t("TextureAtlas.texture_use_atlas.desc").format(name=t("TextureAtlas.albedo").lower()),
|
|
||||||
default=0,
|
|
||||||
items=get_texture_node_list)))
|
|
||||||
register_property((Material, "texture_atlas_normal", EnumProperty(
|
|
||||||
name=t("TextureAtlas.normal"),
|
|
||||||
description=t("TextureAtlas.texture_use_atlas.desc").format(name=t("TextureAtlas.normal").lower()),
|
|
||||||
default=0,
|
|
||||||
items=get_texture_node_list)))
|
|
||||||
register_property((Material, "texture_atlas_emission", EnumProperty(
|
|
||||||
name=t("TextureAtlas.emission"),
|
|
||||||
description=t("TextureAtlas.texture_use_atlas.desc").format(name=t("TextureAtlas.emission").lower()),
|
|
||||||
default=0,
|
|
||||||
items=get_texture_node_list)))
|
|
||||||
register_property((Material, "texture_atlas_ambient_occlusion", EnumProperty(
|
|
||||||
name=t("TextureAtlas.ambient_occlusion"),
|
|
||||||
description=t("TextureAtlas.texture_use_atlas.desc").format(name=t("TextureAtlas.ambient_occlusion").lower()),
|
|
||||||
default=0,
|
|
||||||
items=get_texture_node_list)))
|
|
||||||
register_property((Material, "texture_atlas_height", EnumProperty(
|
|
||||||
name=t("TextureAtlas.height"),
|
|
||||||
description=t("TextureAtlas.texture_use_atlas.desc").format(name=t("TextureAtlas.height").lower()),
|
|
||||||
default=0,
|
|
||||||
items=get_texture_node_list)))
|
|
||||||
register_property((Material, "texture_atlas_roughness", EnumProperty(
|
|
||||||
name=t("TextureAtlas.roughness"),
|
|
||||||
description=t("TextureAtlas.texture_use_atlas.desc").format(name=t("TextureAtlas.roughness").lower()),
|
|
||||||
default=0,
|
|
||||||
items=get_texture_node_list)))
|
|
||||||
|
|
||||||
register_property((Scene, "texture_atlas_material_index", IntProperty(
|
|
||||||
default=-1,
|
|
||||||
get=(lambda self : -1),
|
|
||||||
set=(lambda self,context : None))))
|
|
||||||
|
|
||||||
register_property((Scene, "materials", CollectionProperty(type=SceneMatClass)))
|
materials: CollectionProperty(type=SceneMatClass)
|
||||||
|
|
||||||
register_property((Scene, "texture_atlas_Has_Mat_List_Shown", BoolProperty(
|
texture_atlas_Has_Mat_List_Shown: BoolProperty(
|
||||||
default=False,
|
default=False,
|
||||||
get=MaterialListBool.get_bool,
|
get=MaterialListBool.get_bool,
|
||||||
set=MaterialListBool.set_bool)))
|
set=MaterialListBool.set_bool
|
||||||
|
)
|
||||||
|
|
||||||
def unregister() -> None:
|
class AvatarToolkitMaterialProperties(PropertyGroup):
|
||||||
#if you register properties with register_property then you shouldn't need this function.
|
material_expanded: BoolProperty(
|
||||||
pass
|
name="Expand Material",
|
||||||
|
description="Show/hide material properties",
|
||||||
|
default=False
|
||||||
|
)
|
||||||
|
|
||||||
|
include_in_atlas: BoolProperty(
|
||||||
|
name="Include in Atlas",
|
||||||
|
description="Include this material in texture atlas",
|
||||||
|
default=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_texture_node_list(self, context):
|
||||||
|
if self.use_nodes:
|
||||||
|
nodes = [(i.image.name if i.image else i.name+"_image",
|
||||||
|
i.image.name if i.image else "node with no image...",
|
||||||
|
i.image.name if i.image else i.name, index+1)
|
||||||
|
for index, i in enumerate(self.node_tree.nodes)
|
||||||
|
if i.bl_idname == "ShaderNodeTexImage"]
|
||||||
|
if not nodes:
|
||||||
|
nodes = [("Error", "No images found", "Error", 0)]
|
||||||
|
else:
|
||||||
|
nodes = [("Error", "No node tree found", "Error", 0)]
|
||||||
|
nodes.append(("None", "None", "None", 0))
|
||||||
|
return nodes
|
||||||
|
|
||||||
|
texture_atlas_albedo: EnumProperty(
|
||||||
|
name="Albedo",
|
||||||
|
description="Albedo texture for atlas",
|
||||||
|
items=get_texture_node_list
|
||||||
|
)
|
||||||
|
|
||||||
|
texture_atlas_normal: EnumProperty(
|
||||||
|
name="Normal",
|
||||||
|
description="Normal map for atlas",
|
||||||
|
items=get_texture_node_list
|
||||||
|
)
|
||||||
|
|
||||||
|
texture_atlas_emission: EnumProperty(
|
||||||
|
name="Emission",
|
||||||
|
description="Emission texture for atlas",
|
||||||
|
items=get_texture_node_list
|
||||||
|
)
|
||||||
|
|
||||||
|
texture_atlas_ambient_occlusion: EnumProperty(
|
||||||
|
name="Ambient Occlusion",
|
||||||
|
description="AO texture for atlas",
|
||||||
|
items=get_texture_node_list
|
||||||
|
)
|
||||||
|
|
||||||
|
texture_atlas_height: EnumProperty(
|
||||||
|
name="Height",
|
||||||
|
description="Height map for atlas",
|
||||||
|
items=get_texture_node_list
|
||||||
|
)
|
||||||
|
|
||||||
|
texture_atlas_roughness: EnumProperty(
|
||||||
|
name="Roughness",
|
||||||
|
description="Roughness map for atlas",
|
||||||
|
items=get_texture_node_list
|
||||||
|
)
|
||||||
|
|
||||||
|
class AvatarToolkitObjectProperties(PropertyGroup):
|
||||||
|
material_group_expanded: BoolProperty(
|
||||||
|
name="Expand Material Group",
|
||||||
|
description="Show/hide materials for this mesh",
|
||||||
|
default=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def register():
|
||||||
|
bpy.types.Scene.avatar_toolkit = PointerProperty(type=AvatarToolkitSceneProperties)
|
||||||
|
bpy.types.Material.avatar_toolkit = PointerProperty(type=AvatarToolkitMaterialProperties)
|
||||||
|
bpy.types.Object.avatar_toolkit = PointerProperty(type=AvatarToolkitObjectProperties)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
del bpy.types.Scene.avatar_toolkit
|
||||||
|
del bpy.types.Material.avatar_toolkit
|
||||||
|
del bpy.types.Object.avatar_toolkit
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
import bpy
|
|
||||||
import typing
|
|
||||||
from typing import List, Type
|
|
||||||
|
|
||||||
# List to store the classes to register
|
|
||||||
__bl_classes = []
|
|
||||||
# List to store the ordered classes for registration
|
|
||||||
__bl_ordered_classes = []
|
|
||||||
# List to store props to register
|
|
||||||
__bl_props = []
|
|
||||||
|
|
||||||
def register_wrap(cls):
|
|
||||||
# Check if the class has a 'bl_rna' attribute (indicating it's a Blender class)
|
|
||||||
if hasattr(cls, 'bl_rna'):
|
|
||||||
# Add the class to the list of classes to register
|
|
||||||
__bl_classes.append(cls)
|
|
||||||
return cls
|
|
||||||
|
|
||||||
# Register all properties
|
|
||||||
def register_property(prop):
|
|
||||||
__bl_props.append(prop)
|
|
||||||
|
|
||||||
def register_properties():
|
|
||||||
for prop in __bl_props:
|
|
||||||
if isinstance(prop[2], bpy.props._PropertyDeferred):
|
|
||||||
setattr(prop[0], prop[1], prop[2])
|
|
||||||
else:
|
|
||||||
prop()
|
|
||||||
|
|
||||||
def clear_registration():
|
|
||||||
__bl_classes.clear()
|
|
||||||
__bl_ordered_classes.clear()
|
|
||||||
__bl_props.clear()
|
|
||||||
|
|
||||||
def unregister_properties():
|
|
||||||
for prop in reversed(__bl_props):
|
|
||||||
try:
|
|
||||||
delattr(prop[0], prop[1])
|
|
||||||
except AttributeError:
|
|
||||||
continue
|
|
||||||
clear_registration()
|
|
||||||
|
|
||||||
#- @989onan had to add this from Cats. This is extremely important else you will be screamed at by register order issues!
|
|
||||||
# Find order to register to solve dependencies
|
|
||||||
|
|
||||||
#################################################
|
|
||||||
|
|
||||||
def toposort(deps_dict):
|
|
||||||
sorted_list = []
|
|
||||||
sorted_values = set()
|
|
||||||
while len(deps_dict) > 0:
|
|
||||||
unsorted = []
|
|
||||||
for value, deps in deps_dict.items():
|
|
||||||
if len(deps) == 0:
|
|
||||||
sorted_list.append(value)
|
|
||||||
sorted_values.add(value)
|
|
||||||
else:
|
|
||||||
unsorted.append(value)
|
|
||||||
deps_dict = {value : deps_dict[value] - sorted_values for value in unsorted}
|
|
||||||
|
|
||||||
#sort_order(sorted_list) #to sort by 'bl_order' so we can choose how things may appear in the ui
|
|
||||||
return sorted_list
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def order_classes():
|
|
||||||
deps_dict = {}
|
|
||||||
classes_to_register = set(iter_classes_to_register())
|
|
||||||
for class_obj in classes_to_register:
|
|
||||||
deps_dict[class_obj] = set(iter_own_register_deps(class_obj, classes_to_register))
|
|
||||||
|
|
||||||
__bl_ordered_classes.clear()
|
|
||||||
# Then put everything else sorted into the list
|
|
||||||
for class_obj in toposort(deps_dict):
|
|
||||||
__bl_ordered_classes.append(class_obj)
|
|
||||||
|
|
||||||
print(__bl_ordered_classes)
|
|
||||||
__bl_classes.clear()
|
|
||||||
|
|
||||||
|
|
||||||
def iter_classes_to_register():
|
|
||||||
for class_obj in __bl_classes:
|
|
||||||
yield class_obj
|
|
||||||
|
|
||||||
|
|
||||||
def iter_own_register_deps(class_obj, own_classes):
|
|
||||||
yield from (dep for dep in iter_register_deps(class_obj) if dep in own_classes)
|
|
||||||
|
|
||||||
|
|
||||||
def iter_register_deps(class_obj):
|
|
||||||
for value in typing.get_type_hints(class_obj, {}, {}, True).values():
|
|
||||||
dependency = get_dependency_from_annotation(value)
|
|
||||||
if dependency is not None:
|
|
||||||
yield dependency
|
|
||||||
if hasattr(class_obj, "bl_parent_id"):
|
|
||||||
if class_obj.bl_parent_id != "":
|
|
||||||
for dependency in __bl_classes:
|
|
||||||
if dependency.bl_idname == class_obj.bl_parent_id:
|
|
||||||
yield dependency
|
|
||||||
|
|
||||||
def get_dependency_from_annotation(value):
|
|
||||||
if isinstance(value, tuple) and len(value) == 2:
|
|
||||||
if value[0] in (bpy.props.PointerProperty, bpy.props.CollectionProperty):
|
|
||||||
return value[1]["type"]
|
|
||||||
return None
|
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import bpy
|
||||||
|
from bpy.app.translations import locale
|
||||||
|
from typing import Dict, List, Tuple
|
||||||
|
from .addon_preferences import save_preference, get_preference
|
||||||
|
|
||||||
|
# Use __file__ to get the current file's directory
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
main_dir = os.path.dirname(current_dir)
|
||||||
|
resources_dir = os.path.join(main_dir, "resources")
|
||||||
|
translations_dir = os.path.join(resources_dir, "translations")
|
||||||
|
|
||||||
|
dictionary: Dict[str, str] = dict()
|
||||||
|
languages: List[str] = []
|
||||||
|
verbose: bool = True
|
||||||
|
|
||||||
|
def load_translations() -> bool:
|
||||||
|
global dictionary, languages
|
||||||
|
|
||||||
|
old_dictionary = dictionary.copy()
|
||||||
|
|
||||||
|
dictionary = dict()
|
||||||
|
languages = ["auto"]
|
||||||
|
|
||||||
|
# Populate languages list
|
||||||
|
for i in os.listdir(translations_dir):
|
||||||
|
lang = i.split(".")[0]
|
||||||
|
if lang != "auto":
|
||||||
|
languages.append(lang)
|
||||||
|
|
||||||
|
language_index = get_preference("language", 0)
|
||||||
|
# print(f"Loading translations for language index: {language_index}") # Debug print
|
||||||
|
|
||||||
|
if language_index == 0: # "auto"
|
||||||
|
language = bpy.context.preferences.view.language
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
language = languages[language_index]
|
||||||
|
except IndexError:
|
||||||
|
language = bpy.context.preferences.view.language
|
||||||
|
|
||||||
|
# print(f"Selected language: {language}") # Debug print
|
||||||
|
|
||||||
|
translation_file: str = os.path.join(translations_dir, language + ".json")
|
||||||
|
if os.path.exists(translation_file):
|
||||||
|
with open(translation_file, 'r', encoding='utf-8') as file:
|
||||||
|
dictionary = json.load(file)["messages"]
|
||||||
|
# print(f"Loaded translations: {dictionary}") # Debug print
|
||||||
|
else:
|
||||||
|
custom_language: str = language.split("_")[0]
|
||||||
|
custom_translation_file: str = os.path.join(translations_dir, custom_language + ".json")
|
||||||
|
if os.path.exists(custom_translation_file):
|
||||||
|
with open(custom_translation_file, 'r', encoding='utf-8') as file:
|
||||||
|
dictionary = json.load(file)["messages"]
|
||||||
|
# print(f"Loaded custom translations: {dictionary}") # Debug print
|
||||||
|
else:
|
||||||
|
print(f"Translation file not found for language: {language}")
|
||||||
|
default_file: str = os.path.join(translations_dir, "en_US.json")
|
||||||
|
if os.path.exists(default_file):
|
||||||
|
with open(default_file, 'r', encoding='utf-8') as file:
|
||||||
|
dictionary = json.load(file)["messages"]
|
||||||
|
# print(f"Loaded default translations: {dictionary}") # Debug print
|
||||||
|
else:
|
||||||
|
print("Default translation file 'en_US.json' not found.")
|
||||||
|
|
||||||
|
return dictionary != old_dictionary
|
||||||
|
|
||||||
|
def t(phrase: str, default: str = None, **kwargs) -> str:
|
||||||
|
output: str = dictionary.get(phrase)
|
||||||
|
if output is None:
|
||||||
|
if verbose:
|
||||||
|
print(f'Warning: Unknown phrase: {phrase}')
|
||||||
|
return default if default is not None else phrase
|
||||||
|
# print(f"Translating '{phrase}' to '{output}'") # Debug print
|
||||||
|
return output.format(**kwargs) if kwargs else output
|
||||||
|
|
||||||
|
def get_language_display_name(lang: str) -> str:
|
||||||
|
if lang == "auto":
|
||||||
|
return t("Language.auto", "Automatic")
|
||||||
|
return t(f"Language.{lang}", lang)
|
||||||
|
|
||||||
|
def get_languages_list(self, context) -> List[Tuple[str, str, str]]:
|
||||||
|
return [(str(i), get_language_display_name(lang), f"Use {lang} language") for i, lang in enumerate(languages)]
|
||||||
|
|
||||||
|
def update_language(self, context):
|
||||||
|
print(f"Updating language to: {self.avatar_toolkit_language}") # Debug print
|
||||||
|
save_preference("language", int(self.avatar_toolkit_language))
|
||||||
|
load_translations()
|
||||||
|
# Set a flag to indicate that a language change has occurred
|
||||||
|
context.scene.avatar_toolkit_language_changed = True
|
||||||
|
# Show popup after language change
|
||||||
|
bpy.ops.avatar_toolkit.translation_restart_popup('INVOKE_DEFAULT')
|
||||||
|
|
||||||
|
# Initial load of translations
|
||||||
|
# print("Performing initial load of translations") # Debug print
|
||||||
|
load_translations()
|
||||||
+7
-8
@@ -10,10 +10,9 @@ import time
|
|||||||
from urllib import request, error
|
from urllib import request, error
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from bpy.app.handlers import persistent
|
from bpy.app.handlers import persistent
|
||||||
from ..functions.translations import t
|
from .translations import t
|
||||||
from .addon_preferences import get_preference, get_current_version, save_preference
|
from .addon_preferences import get_preference, get_current_version, save_preference
|
||||||
from .register import register_wrap
|
from ..ui.main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from ..ui.panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
|
||||||
from typing import Dict, List, Tuple, Optional, Set, Any
|
from typing import Dict, List, Tuple, Optional, Set, Any
|
||||||
|
|
||||||
GITHUB_REPO = "teamneoneko/Avatar-Toolkit"
|
GITHUB_REPO = "teamneoneko/Avatar-Toolkit"
|
||||||
@@ -27,7 +26,7 @@ version_list: Optional[Dict[str, List[str]]] = None
|
|||||||
main_dir: str = os.path.dirname(os.path.dirname(__file__))
|
main_dir: str = os.path.dirname(os.path.dirname(__file__))
|
||||||
downloads_dir: str = os.path.join(main_dir, "downloads")
|
downloads_dir: str = os.path.join(main_dir, "downloads")
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_CheckForUpdate(bpy.types.Operator):
|
class AvatarToolkit_OT_CheckForUpdate(bpy.types.Operator):
|
||||||
bl_idname = 'avatar_toolkit.check_for_update'
|
bl_idname = 'avatar_toolkit.check_for_update'
|
||||||
bl_label = t('CheckForUpdateButton.label')
|
bl_label = t('CheckForUpdateButton.label')
|
||||||
@@ -38,7 +37,7 @@ class AvatarToolkit_OT_CheckForUpdate(bpy.types.Operator):
|
|||||||
check_for_update_background()
|
check_for_update_background()
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_UpdateToLatest(bpy.types.Operator):
|
class AvatarToolkit_OT_UpdateToLatest(bpy.types.Operator):
|
||||||
bl_idname = 'avatar_toolkit.update_latest'
|
bl_idname = 'avatar_toolkit.update_latest'
|
||||||
bl_label = t('UpdateToLatestButton.label')
|
bl_label = t('UpdateToLatestButton.label')
|
||||||
@@ -49,7 +48,7 @@ class AvatarToolkit_OT_UpdateToLatest(bpy.types.Operator):
|
|||||||
update_now(latest=True)
|
update_now(latest=True)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_UpdateNotificationPopup(bpy.types.Operator):
|
class AvatarToolkit_OT_UpdateNotificationPopup(bpy.types.Operator):
|
||||||
bl_idname = "avatar_toolkit.update_notification_popup"
|
bl_idname = "avatar_toolkit.update_notification_popup"
|
||||||
bl_label = t('UpdateNotificationPopup.label')
|
bl_label = t('UpdateNotificationPopup.label')
|
||||||
@@ -69,7 +68,7 @@ class AvatarToolkit_OT_UpdateNotificationPopup(bpy.types.Operator):
|
|||||||
col = layout.column(align=True)
|
col = layout.column(align=True)
|
||||||
col.label(text=t('UpdateNotificationPopup.newUpdate', default="New update available: {version}").format(version=latest_version_str))
|
col.label(text=t('UpdateNotificationPopup.newUpdate', default="New update available: {version}").format(version=latest_version_str))
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_PT_UpdaterPanel(bpy.types.Panel):
|
class AvatarToolkit_PT_UpdaterPanel(bpy.types.Panel):
|
||||||
bl_label = t("Updater.label")
|
bl_label = t("Updater.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_updater"
|
bl_idname = "OBJECT_PT_avatar_toolkit_updater"
|
||||||
@@ -83,7 +82,7 @@ class AvatarToolkit_PT_UpdaterPanel(bpy.types.Panel):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
draw_updater_panel(context, layout)
|
draw_updater_panel(context, layout)
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_RestartBlenderPopup(bpy.types.Operator):
|
class AvatarToolkit_OT_RestartBlenderPopup(bpy.types.Operator):
|
||||||
bl_idname = "avatar_toolkit.restart_blender_popup"
|
bl_idname = "avatar_toolkit.restart_blender_popup"
|
||||||
bl_label = t('RestartBlenderPopup.label', default="Restart Blender")
|
bl_label = t('RestartBlenderPopup.label', default="Restart Blender")
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
from ..core.register import register_wrap
|
|
||||||
|
|
||||||
#to reload all things in this directory and import them properly - @989onan
|
|
||||||
if "bpy" not in locals():
|
|
||||||
import bpy
|
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
from os.path import dirname, basename, isfile, join
|
|
||||||
modules = glob.glob(join(dirname(__file__), "*.py"))
|
|
||||||
for module_name in [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]:
|
|
||||||
exec("from . import "+module_name)
|
|
||||||
print("importing " +module_name)
|
|
||||||
else:
|
|
||||||
import importlib
|
|
||||||
modules = glob.glob(join(dirname(__file__), "*.py"))
|
|
||||||
for module_name in [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]:
|
|
||||||
exec("importlib.reload("+module_name+")")
|
|
||||||
print("reloading " +module_name)
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import math
|
import math
|
||||||
from bpy.types import Context, Operator
|
from bpy.types import Context, Operator
|
||||||
from ..core.register import register_wrap
|
|
||||||
from ..core.common import get_selected_armature, is_valid_armature, get_all_meshes
|
from ..core.common import get_selected_armature, is_valid_armature, get_all_meshes
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_ApplyTransforms(Operator):
|
class AvatarToolKit_OT_ApplyTransforms(Operator):
|
||||||
bl_idname = "avatar_toolkit.apply_transforms"
|
bl_idname = "avatar_toolkit.apply_transforms"
|
||||||
bl_label = t("Tools.apply_transforms.label")
|
bl_label = t("Tools.apply_transforms.label")
|
||||||
@@ -37,7 +36,7 @@ class AvatarToolKit_OT_ApplyTransforms(Operator):
|
|||||||
self.report({'INFO'}, t("Tools.apply_transforms.success"))
|
self.report({'INFO'}, t("Tools.apply_transforms.success"))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_ConnectBones(Operator):
|
class AvatarToolKit_OT_ConnectBones(Operator):
|
||||||
bl_idname = "avatar_toolkit.connect_bones"
|
bl_idname = "avatar_toolkit.connect_bones"
|
||||||
bl_label = t("Tools.connect_bones.label")
|
bl_label = t("Tools.connect_bones.label")
|
||||||
@@ -90,7 +89,7 @@ class AvatarToolKit_OT_ConnectBones(Operator):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.prop(self, "min_distance")
|
layout.prop(self, "min_distance")
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_DeleteBoneConstraints(Operator):
|
class AvatarToolKit_OT_DeleteBoneConstraints(Operator):
|
||||||
bl_idname = "avatar_toolkit.delete_bone_constraints"
|
bl_idname = "avatar_toolkit.delete_bone_constraints"
|
||||||
bl_label = t("Tools.delete_bone_constraints.label")
|
bl_label = t("Tools.delete_bone_constraints.label")
|
||||||
@@ -120,7 +119,7 @@ class AvatarToolKit_OT_DeleteBoneConstraints(Operator):
|
|||||||
self.report({'INFO'}, t("Tools.delete_bone_constraints.success").format(constraints_removed=constraints_removed))
|
self.report({'INFO'}, t("Tools.delete_bone_constraints.success").format(constraints_removed=constraints_removed))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_SeparateByMaterials(Operator):
|
class AvatarToolKit_OT_SeparateByMaterials(Operator):
|
||||||
bl_idname = "avatar_toolkit.separate_by_materials"
|
bl_idname = "avatar_toolkit.separate_by_materials"
|
||||||
bl_label = t("Tools.separate_by_materials.label")
|
bl_label = t("Tools.separate_by_materials.label")
|
||||||
@@ -140,7 +139,7 @@ class AvatarToolKit_OT_SeparateByMaterials(Operator):
|
|||||||
self.report({'INFO'}, t("Tools.separate_by_materials.success"))
|
self.report({'INFO'}, t("Tools.separate_by_materials.success"))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_SeparateByLooseParts(Operator):
|
class AvatarToolKit_OT_SeparateByLooseParts(Operator):
|
||||||
bl_idname = "avatar_toolkit.separate_by_loose_parts"
|
bl_idname = "avatar_toolkit.separate_by_loose_parts"
|
||||||
bl_label = t("Tools.separate_by_loose_parts.label")
|
bl_label = t("Tools.separate_by_loose_parts.label")
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
|
||||||
from bpy.types import Context, Mesh, Panel, Operator, Armature, EditBone
|
from bpy.types import Context, Mesh, Panel, Operator, Armature, EditBone
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
from ..core.common import get_selected_armature, get_all_meshes
|
from ..core.common import get_selected_armature, get_all_meshes
|
||||||
from ..core import common
|
from ..core import common
|
||||||
from ..core.dictionaries import bone_names
|
from ..core.dictionaries import bone_names
|
||||||
from mathutils import Matrix
|
from mathutils import Matrix
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_StartPoseMode(Operator):
|
class AvatarToolkit_OT_StartPoseMode(Operator):
|
||||||
bl_idname = 'avatar_toolkit.start_pose_mode'
|
bl_idname = 'avatar_toolkit.start_pose_mode'
|
||||||
bl_label = t("Quick_Access.start_pose_mode.label")
|
bl_label = t("Quick_Access.start_pose_mode.label")
|
||||||
@@ -33,7 +32,7 @@ class AvatarToolkit_OT_StartPoseMode(Operator):
|
|||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_StopPoseMode(Operator):
|
class AvatarToolkit_OT_StopPoseMode(Operator):
|
||||||
bl_idname = 'avatar_toolkit.stop_pose_mode'
|
bl_idname = 'avatar_toolkit.stop_pose_mode'
|
||||||
bl_label = t("Quick_Access.stop_pose_mode.label")
|
bl_label = t("Quick_Access.stop_pose_mode.label")
|
||||||
@@ -55,7 +54,7 @@ class AvatarToolkit_OT_StopPoseMode(Operator):
|
|||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_ApplyPoseAsShapekey(Operator):
|
class AvatarToolkit_OT_ApplyPoseAsShapekey(Operator):
|
||||||
bl_idname = 'avatar_toolkit.apply_pose_as_shapekey'
|
bl_idname = 'avatar_toolkit.apply_pose_as_shapekey'
|
||||||
bl_label = t("Quick_Access.apply_pose_as_shapekey.label")
|
bl_label = t("Quick_Access.apply_pose_as_shapekey.label")
|
||||||
@@ -98,7 +97,7 @@ class AvatarToolkit_OT_ApplyPoseAsShapekey(Operator):
|
|||||||
self.report({'INFO'}, t('Tools.apply_pose_as_rest.success'))
|
self.report({'INFO'}, t('Tools.apply_pose_as_rest.success'))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_ApplyPoseAsRest(Operator):
|
class AvatarToolkit_OT_ApplyPoseAsRest(Operator):
|
||||||
bl_idname = 'avatar_toolkit.apply_pose_as_rest'
|
bl_idname = 'avatar_toolkit.apply_pose_as_rest'
|
||||||
bl_label = t("Quick_Access.apply_pose_as_rest.label")
|
bl_label = t("Quick_Access.apply_pose_as_rest.label")
|
||||||
@@ -117,7 +116,7 @@ class AvatarToolkit_OT_ApplyPoseAsRest(Operator):
|
|||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_RemoveZeroWeightBones(Operator):
|
class AvatarToolkit_OT_RemoveZeroWeightBones(Operator):
|
||||||
bl_idname = "avatar_toolkit.remove_zero_weight_bones"
|
bl_idname = "avatar_toolkit.remove_zero_weight_bones"
|
||||||
bl_label = t("Tools.remove_zero_weight_bones.label")
|
bl_label = t("Tools.remove_zero_weight_bones.label")
|
||||||
@@ -218,7 +217,7 @@ class AvatarToolkit_OT_RemoveZeroWeightBones(Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_MergeBonesToActive(Operator):
|
class AvatarToolkit_OT_MergeBonesToActive(Operator):
|
||||||
bl_idname = "avatar_toolkit.merge_bones_to_active"
|
bl_idname = "avatar_toolkit.merge_bones_to_active"
|
||||||
bl_label = t("Tools.merge_bones_to_active.label")
|
bl_label = t("Tools.merge_bones_to_active.label")
|
||||||
@@ -267,7 +266,7 @@ class AvatarToolkit_OT_MergeBonesToActive(Operator):
|
|||||||
bpy.ops.object.mode_set(mode=prev_mode)
|
bpy.ops.object.mode_set(mode=prev_mode)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_MergeBonesToParents(Operator):
|
class AvatarToolkit_OT_MergeBonesToParents(Operator):
|
||||||
bl_idname = "avatar_toolkit.merge_bones_to_parents"
|
bl_idname = "avatar_toolkit.merge_bones_to_parents"
|
||||||
bl_label = t("Tools.merge_bones_to_parents.label")
|
bl_label = t("Tools.merge_bones_to_parents.label")
|
||||||
@@ -342,7 +341,7 @@ class AvatarToolkit_OT_MergeBonesToParents(Operator):
|
|||||||
bpy.ops.object.mode_set(mode=prev_mode)
|
bpy.ops.object.mode_set(mode=prev_mode)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_MergeArmatures(Operator):
|
class AvatarToolkit_OT_MergeArmatures(Operator):
|
||||||
bl_idname = "avatar_toolkit.merge_armatures"
|
bl_idname = "avatar_toolkit.merge_armatures"
|
||||||
bl_label = t("MergeArmature.merge_armatures.label")
|
bl_label = t("MergeArmature.merge_armatures.label")
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ import bpy
|
|||||||
import os
|
import os
|
||||||
from typing import List, Tuple, Optional
|
from typing import List, Tuple, Optional
|
||||||
from bpy.types import Material, Operator, Context, Object, Image, Mesh, MeshUVLoopLayer, Float2AttributeValue, ShaderNodeTexImage, ShaderNodeBsdfPrincipled, ShaderNodeNormalMap
|
from bpy.types import Material, Operator, Context, Object, Image, Mesh, MeshUVLoopLayer, Float2AttributeValue, ShaderNodeTexImage, ShaderNodeBsdfPrincipled, ShaderNodeNormalMap
|
||||||
from ..core.register import register_wrap
|
|
||||||
from ..core.common import SceneMatClass, MaterialListBool
|
from ..core.common import SceneMatClass, MaterialListBool
|
||||||
from ..core.packer.rectangle_packer import MaterialImageList, BinPacker
|
from ..core.packer.rectangle_packer import MaterialImageList, BinPacker
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
|
|
||||||
class MaterialImageList:
|
class MaterialImageList:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -134,7 +133,7 @@ def prep_images_in_scene(context: Context) -> list[MaterialImageList]:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_AtlasMaterials(Operator):
|
class AvatarToolKit_OT_AtlasMaterials(Operator):
|
||||||
|
|
||||||
bl_idname = "avatar_toolkit.atlas_materials"
|
bl_idname = "avatar_toolkit.atlas_materials"
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import re
|
|||||||
from typing import List, Tuple, Optional, Set, Dict
|
from typing import List, Tuple, Optional, Set, Dict
|
||||||
from bpy.types import Material, Operator, Context, Object, NodeTree
|
from bpy.types import Material, Operator, Context, Object, NodeTree
|
||||||
from ..core.common import clean_material_names, get_selected_armature, is_valid_armature, get_all_meshes, init_progress, update_progress, finish_progress
|
from ..core.common import clean_material_names, get_selected_armature, is_valid_armature, get_all_meshes, init_progress, update_progress, finish_progress
|
||||||
from ..core.register import register_wrap
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
|
|
||||||
def textures_match(tex1: bpy.types.ImageTexture, tex2: bpy.types.ImageTexture) -> bool:
|
def textures_match(tex1: bpy.types.ImageTexture, tex2: bpy.types.ImageTexture) -> bool:
|
||||||
return tex1.image == tex2.image and tex1.extension == tex2.extension
|
return tex1.image == tex2.image and tex1.extension == tex2.extension
|
||||||
@@ -52,7 +51,7 @@ def get_base_name(name: str) -> str:
|
|||||||
mat_match = re.match(r"^(.*)\.\d{3}$", name)
|
mat_match = re.match(r"^(.*)\.\d{3}$", name)
|
||||||
return mat_match.group(1) if mat_match else name
|
return mat_match.group(1) if mat_match else name
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_CombineMaterials(Operator):
|
class AvatarToolKit_OT_CombineMaterials(Operator):
|
||||||
bl_idname = "avatar_toolkit.combine_materials"
|
bl_idname = "avatar_toolkit.combine_materials"
|
||||||
bl_label = t("Optimization.combine_materials.label")
|
bl_label = t("Optimization.combine_materials.label")
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core import common
|
from ..core import common
|
||||||
from ..core import register_wrap
|
from ..core.translations import t
|
||||||
from .translations import t
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_CreateDigitigradeLegs(bpy.types.Operator):
|
class AvatarToolKit_OT_CreateDigitigradeLegs(bpy.types.Operator):
|
||||||
bl_idname = "avatar_toolkit.create_digitigrade_legs"
|
bl_idname = "avatar_toolkit.create_digitigrade_legs"
|
||||||
bl_label = t('Tools.create_digitigrade_legs.label')
|
bl_label = t('Tools.create_digitigrade_legs.label')
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy_extras.io_utils import ImportHelper
|
from bpy_extras.io_utils import ImportHelper
|
||||||
from ..core.register import register_wrap
|
from ..core.importers.importer import imports, import_types
|
||||||
from ..core.importer import imports, import_types
|
|
||||||
from ..core.common import remove_default_objects
|
from ..core.common import remove_default_objects
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
import pathlib
|
import pathlib
|
||||||
import os
|
import os
|
||||||
|
|
||||||
VRM_IMPORTER_URL = "https://github.com/saturday06/VRM_Addon_for_Blender"
|
VRM_IMPORTER_URL = "https://github.com/saturday06/VRM_Addon_for_Blender"
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_ImportAnyModel(Operator, ImportHelper):
|
class AvatarToolKit_OT_ImportAnyModel(Operator, ImportHelper):
|
||||||
bl_idname = 'avatar_toolkit.import_any_model'
|
bl_idname = 'avatar_toolkit.import_any_model'
|
||||||
bl_label = t('Tools.import_any_model.label')
|
bl_label = t('Tools.import_any_model.label')
|
||||||
@@ -67,7 +66,7 @@ class AvatarToolKit_OT_ImportAnyModel(Operator, ImportHelper):
|
|||||||
self.report({'INFO'}, t('Quick_Access.import_success'))
|
self.report({'INFO'}, t('Quick_Access.import_success'))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class VRMImporterPopup(Operator):
|
class VRMImporterPopup(Operator):
|
||||||
bl_idname = "wm.vrm_importer_popup"
|
bl_idname = "wm.vrm_importer_popup"
|
||||||
bl_label = "VRM Importer Not Installed"
|
bl_label = "VRM Importer Not Installed"
|
||||||
@@ -87,7 +86,7 @@ class VRMImporterPopup(Operator):
|
|||||||
#TODO: This needs to be done with our own MMD importer.
|
#TODO: This needs to be done with our own MMD importer.
|
||||||
"""
|
"""
|
||||||
#stolen from cats. Oh wait I made this code riiiiiiight - @989onan
|
#stolen from cats. Oh wait I made this code riiiiiiight - @989onan
|
||||||
@register_wrap
|
|
||||||
class ImportMMDAnimation(bpy.types.Operator, ImportHelper):
|
class ImportMMDAnimation(bpy.types.Operator, ImportHelper):
|
||||||
bl_idname = 'avatar_toolkit.import_mmd_animation'
|
bl_idname = 'avatar_toolkit.import_mmd_animation'
|
||||||
bl_label = t('Importer.mmd_anim_importer.label')
|
bl_label = t('Importer.mmd_anim_importer.label')
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ import bpy
|
|||||||
from typing import List, Optional, Set
|
from typing import List, Optional, Set
|
||||||
from bpy.types import Operator, Context, Object
|
from bpy.types import Operator, Context, Object
|
||||||
from ..core.common import fix_uv_coordinates, get_selected_armature, get_all_meshes, is_valid_armature, apply_shapekey_to_basis, has_shapekeys, select_current_armature, init_progress, update_progress, finish_progress
|
from ..core.common import fix_uv_coordinates, get_selected_armature, get_all_meshes, is_valid_armature, apply_shapekey_to_basis, has_shapekeys, select_current_armature, init_progress, update_progress, finish_progress
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
from ..core.register import register_wrap
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_RemoveUnusedShapekeys(bpy.types.Operator):
|
class AvatarToolkit_OT_RemoveUnusedShapekeys(bpy.types.Operator):
|
||||||
tolerance: bpy.props.FloatProperty(name=t("Tools.remove_unused_shapekeys.tolerance.label"), default=0.001, description=t("Tools.remove_unused_shapekeys.tolerance.desc"))
|
tolerance: bpy.props.FloatProperty(name=t("Tools.remove_unused_shapekeys.tolerance.label"), default=0.001, description=t("Tools.remove_unused_shapekeys.tolerance.desc"))
|
||||||
bl_idname = "avatar_toolkit.remove_unused_shapekeys"
|
bl_idname = "avatar_toolkit.remove_unused_shapekeys"
|
||||||
@@ -56,7 +55,7 @@ class AvatarToolkit_OT_RemoveUnusedShapekeys(bpy.types.Operator):
|
|||||||
continue
|
continue
|
||||||
ob.shape_key_remove(ob.data.shape_keys.key_blocks[kb_name])
|
ob.shape_key_remove(ob.data.shape_keys.key_blocks[kb_name])
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_ApplyShapeKey(bpy.types.Operator):
|
class AvatarToolkit_OT_ApplyShapeKey(bpy.types.Operator):
|
||||||
bl_idname = "avatar_toolkit.apply_shape_key"
|
bl_idname = "avatar_toolkit.apply_shape_key"
|
||||||
bl_label = t("Tools.apply_shape_key.label")
|
bl_label = t("Tools.apply_shape_key.label")
|
||||||
@@ -79,7 +78,7 @@ class AvatarToolkit_OT_ApplyShapeKey(bpy.types.Operator):
|
|||||||
self.report({'ERROR'}, t("Tools.apply_shape_key.error"))
|
self.report({'ERROR'}, t("Tools.apply_shape_key.error"))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_JoinAllMeshes(Operator):
|
class AvatarToolKit_OT_JoinAllMeshes(Operator):
|
||||||
bl_idname = "avatar_toolkit.join_all_meshes"
|
bl_idname = "avatar_toolkit.join_all_meshes"
|
||||||
bl_label = t("Optimization.join_all_meshes.label")
|
bl_label = t("Optimization.join_all_meshes.label")
|
||||||
@@ -150,7 +149,7 @@ class AvatarToolKit_OT_JoinAllMeshes(Operator):
|
|||||||
finish_progress(context)
|
finish_progress(context)
|
||||||
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_JoinSelectedMeshes(Operator):
|
class AvatarToolKit_OT_JoinSelectedMeshes(Operator):
|
||||||
bl_idname = "avatar_toolkit.join_selected_meshes"
|
bl_idname = "avatar_toolkit.join_selected_meshes"
|
||||||
bl_label = t("Optimization.join_selected_meshes.label")
|
bl_label = t("Optimization.join_selected_meshes.label")
|
||||||
|
|||||||
@@ -2,13 +2,12 @@ import bpy
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import re
|
import re
|
||||||
from bpy.types import Operator, Context, Material, ShaderNodeTexImage, ShaderNodeGroup, Object
|
from bpy.types import Operator, Context, Material, ShaderNodeTexImage, ShaderNodeGroup, Object
|
||||||
from ..core.register import register_wrap
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
from ..core.common import get_selected_armature, is_valid_armature, get_all_meshes, init_progress, update_progress, finish_progress
|
from ..core.common import get_selected_armature, is_valid_armature, get_all_meshes, init_progress, update_progress, finish_progress
|
||||||
from ..functions.additional_tools import AvatarToolKit_OT_ConnectBones, AvatarToolKit_OT_DeleteBoneConstraints
|
from ..functions.additional_tools import AvatarToolKit_OT_ConnectBones, AvatarToolKit_OT_DeleteBoneConstraints
|
||||||
from ..functions.armature_modifying import AvatarToolkit_OT_RemoveZeroWeightBones, AvatarToolkit_OT_MergeBonesToParents
|
from ..functions.armature_modifying import AvatarToolkit_OT_RemoveZeroWeightBones, AvatarToolkit_OT_MergeBonesToParents
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_CleanupMesh(Operator):
|
class AvatarToolKit_OT_CleanupMesh(Operator):
|
||||||
bl_idname = "avatar_toolkit.cleanup_mesh"
|
bl_idname = "avatar_toolkit.cleanup_mesh"
|
||||||
bl_label = t("MMDOptions.cleanup_mesh.label")
|
bl_label = t("MMDOptions.cleanup_mesh.label")
|
||||||
@@ -61,7 +60,7 @@ class AvatarToolKit_OT_CleanupMesh(Operator):
|
|||||||
if key.name != 'Basis' and all(abs(key.data[i].co[j] - obj.data.shape_keys.reference_key.data[i].co[j]) < 0.0001 for i in range(len(key.data)) for j in range(3)):
|
if key.name != 'Basis' and all(abs(key.data[i].co[j] - obj.data.shape_keys.reference_key.data[i].co[j]) < 0.0001 for i in range(len(key.data)) for j in range(3)):
|
||||||
obj.shape_key_remove(key)
|
obj.shape_key_remove(key)
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_OptimizeWeights(Operator):
|
class AvatarToolKit_OT_OptimizeWeights(Operator):
|
||||||
bl_idname = "avatar_toolkit.optimize_weights"
|
bl_idname = "avatar_toolkit.optimize_weights"
|
||||||
bl_label = t("MMDOptions.optimize_weights.label")
|
bl_label = t("MMDOptions.optimize_weights.label")
|
||||||
@@ -108,7 +107,7 @@ class AvatarToolKit_OT_OptimizeWeights(Operator):
|
|||||||
for g in sorted_groups[self.max_weights:]:
|
for g in sorted_groups[self.max_weights:]:
|
||||||
obj.vertex_groups[g.group].remove([v.index])
|
obj.vertex_groups[g.group].remove([v.index])
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_OptimizeArmature(Operator):
|
class AvatarToolKit_OT_OptimizeArmature(Operator):
|
||||||
bl_idname = "avatar_toolkit.optimize_armature"
|
bl_idname = "avatar_toolkit.optimize_armature"
|
||||||
bl_label = t("MMDOptions.optimize_armature.label")
|
bl_label = t("MMDOptions.optimize_armature.label")
|
||||||
@@ -339,7 +338,7 @@ def fix_vrm_shader(material: Material):
|
|||||||
material.node_tree.links = [link for link in material.node_tree.links
|
material.node_tree.links = [link for link in material.node_tree.links
|
||||||
if not (link.from_node == node or link.to_node == node)]
|
if not (link.from_node == node or link.to_node == node)]
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_ConvertMaterials(Operator):
|
class AvatarToolKit_OT_ConvertMaterials(Operator):
|
||||||
bl_idname = "avatar_toolkit.convert_materials"
|
bl_idname = "avatar_toolkit.convert_materials"
|
||||||
bl_label = t("MMDOptions.convert_materials.label")
|
bl_label = t("MMDOptions.convert_materials.label")
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from typing import List, TypedDict, Any
|
from typing import List, TypedDict, Any
|
||||||
from bpy.types import Operator, Context, Object
|
from bpy.types import Operator, Context, Object
|
||||||
from ..core.register import register_wrap
|
|
||||||
from ..core.common import get_selected_armature, is_valid_armature, select_current_armature, get_all_meshes
|
from ..core.common import get_selected_armature, is_valid_armature, select_current_armature, get_all_meshes
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
|
|
||||||
class meshEntry(TypedDict):
|
class meshEntry(TypedDict):
|
||||||
mesh: Object
|
mesh: Object
|
||||||
@@ -11,7 +10,7 @@ class meshEntry(TypedDict):
|
|||||||
vertices: int
|
vertices: int
|
||||||
cur_vertex_pass: int
|
cur_vertex_pass: int
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_RemoveDoublesSafelyAdvanced(Operator):
|
class AvatarToolKit_OT_RemoveDoublesSafelyAdvanced(Operator):
|
||||||
bl_idname = "avatar_toolkit.remove_doubles_safely_advanced"
|
bl_idname = "avatar_toolkit.remove_doubles_safely_advanced"
|
||||||
bl_label = t("Optimization.remove_doubles_safely_advanced.label")
|
bl_label = t("Optimization.remove_doubles_safely_advanced.label")
|
||||||
@@ -39,7 +38,7 @@ class AvatarToolKit_OT_RemoveDoublesSafelyAdvanced(Operator):
|
|||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_RemoveDoublesSafely(Operator):
|
class AvatarToolKit_OT_RemoveDoublesSafely(Operator):
|
||||||
bl_idname = "avatar_toolkit.remove_doubles_safely"
|
bl_idname = "avatar_toolkit.remove_doubles_safely"
|
||||||
bl_label = t("Optimization.remove_doubles_safely.label")
|
bl_label = t("Optimization.remove_doubles_safely.label")
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
import re
|
import re
|
||||||
from bpy.types import Operator, Context, Object
|
from bpy.types import Operator, Context, Object
|
||||||
from ..core.dictionaries import bone_names
|
from ..core.dictionaries import bone_names
|
||||||
from ..core.common import get_selected_armature, simplify_bonename, is_valid_armature
|
from ..core.common import get_selected_armature, simplify_bonename, is_valid_armature
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_ConvertToResonite(Operator):
|
class AvatarToolKit_OT_ConvertToResonite(Operator):
|
||||||
bl_idname = 'avatar_toolkit.convert_to_resonite'
|
bl_idname = 'avatar_toolkit.convert_to_resonite'
|
||||||
bl_label = t('Tools.convert_to_resonite.label')
|
bl_label = t('Tools.convert_to_resonite.label')
|
||||||
|
|||||||
@@ -1,18 +1,9 @@
|
|||||||
# This code is heavily based on the Rigify-Move-DEF by NyankoNyan (https://github.com/NyankoNyan/Rigify-Move-DEF), which is licensed under the MIT License. We just heavily improve the code and add some new features.
|
# This code is heavily based on the Rigify-Move-DEF by NyankoNyan (https://github.com/NyankoNyan/Rigify-Move-DEF), which is licensed under the MIT License. We just heavily improve the code and add some new features.
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
|
||||||
from ..core.common import get_selected_armature, is_valid_armature
|
from ..core.common import get_selected_armature, is_valid_armature
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
from bpy.types import Operator, Context
|
from bpy.types import Operator, Context
|
||||||
|
|
||||||
import bpy
|
|
||||||
from ..core.register import register_wrap
|
|
||||||
from ..core.common import get_selected_armature, is_valid_armature
|
|
||||||
from ..functions.translations import t
|
|
||||||
from bpy.types import Operator, Context
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_ConvertRigifyToUnity(Operator):
|
class AvatarToolKit_OT_ConvertRigifyToUnity(Operator):
|
||||||
bl_idname = "avatar_toolkit.convert_rigify_to_unity"
|
bl_idname = "avatar_toolkit.convert_rigify_to_unity"
|
||||||
bl_label = t("Tools.convert_rigify_to_unity.label")
|
bl_label = t("Tools.convert_rigify_to_unity.label")
|
||||||
|
|||||||
@@ -4,15 +4,14 @@ from bpy.types import Operator, Object, Context, Mesh, MeshUVLoopLayer
|
|||||||
import bmesh
|
import bmesh
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import math
|
import math
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
from ..core.register import register_wrap
|
|
||||||
|
|
||||||
class GenerateLoopTreeResult(TypedDict):
|
class GenerateLoopTreeResult(TypedDict):
|
||||||
tree: dict[str, set[str]]
|
tree: dict[str, set[str]]
|
||||||
selected_loops: dict[str,list[int]]
|
selected_loops: dict[str,list[int]]
|
||||||
selected_verts: dict[str,int]
|
selected_verts: dict[str,int]
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_OT_AlignUVEdgesToTarget(Operator):
|
class AvatarToolkit_OT_AlignUVEdgesToTarget(Operator):
|
||||||
bl_idname = "avatar_toolkit.align_uv_edges_to_target"
|
bl_idname = "avatar_toolkit.align_uv_edges_to_target"
|
||||||
bl_label = t("avatar_toolkit.align_uv_edges_to_target.label")
|
bl_label = t("avatar_toolkit.align_uv_edges_to_target.label")
|
||||||
|
|||||||
+2
-3
@@ -1,11 +1,10 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core import common
|
from ..core import common
|
||||||
from ..core.register import register_wrap
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
from ..core.common import get_selected_armature, is_valid_armature, get_all_meshes, init_progress, update_progress, finish_progress
|
from ..core.common import get_selected_armature, is_valid_armature, get_all_meshes, init_progress, update_progress, finish_progress
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_AutoVisemeButton(bpy.types.Operator):
|
class AvatarToolKit_OT_AutoVisemeButton(bpy.types.Operator):
|
||||||
bl_idname = 'avatar_toolkit.create_visemes'
|
bl_idname = 'avatar_toolkit.create_visemes'
|
||||||
bl_label = t('AutoVisemeButton.label')
|
bl_label = t('AutoVisemeButton.label')
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
if "bpy" not in locals():
|
|
||||||
import bpy
|
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
from os.path import dirname, basename, isfile, join
|
|
||||||
modules = glob.glob(join(dirname(__file__), "*.py"))
|
|
||||||
for module_name in [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]:
|
|
||||||
exec("from . import "+module_name)
|
|
||||||
print("importing " +module_name)
|
|
||||||
else:
|
|
||||||
import importlib
|
|
||||||
modules = glob.glob(join(dirname(__file__), "*.py"))
|
|
||||||
for module_name in [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]:
|
|
||||||
print("reloading " +module_name)
|
|
||||||
exec("importlib.reload("+module_name+")")
|
|
||||||
|
|||||||
+39
-54
@@ -1,57 +1,51 @@
|
|||||||
from bpy.types import UIList, Panel, UILayout, Object, Context,Material, Operator
|
from bpy.types import UIList, Panel, UILayout, Object, Context, Material, Operator
|
||||||
import bpy
|
import bpy
|
||||||
from math import sqrt
|
from math import sqrt
|
||||||
from ..core.register import register_wrap
|
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from .panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
|
||||||
from ..core.common import SceneMatClass, MaterialListBool, get_selected_armature
|
from ..core.common import SceneMatClass, MaterialListBool, get_selected_armature
|
||||||
from ..functions.atlas_materials import AvatarToolKit_OT_AtlasMaterials
|
from ..functions.atlas_materials import AvatarToolKit_OT_AtlasMaterials
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_SelectAllMaterials(Operator):
|
class AvatarToolKit_OT_SelectAllMaterials(Operator):
|
||||||
bl_idname = 'avatar_toolkit.select_all_materials'
|
bl_idname = 'avatar_toolkit.select_all_materials'
|
||||||
bl_label = "Select All"
|
bl_label = "Select All"
|
||||||
bl_description = "Select all materials for atlas"
|
bl_description = "Select all materials for atlas"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
for item in context.scene.materials:
|
for item in context.scene.avatar_toolkit.materials:
|
||||||
item.mat.include_in_atlas = True
|
item.mat.avatar_toolkit.include_in_atlas = True
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_SelectNoneMaterials(Operator):
|
class AvatarToolKit_OT_SelectNoneMaterials(Operator):
|
||||||
bl_idname = 'avatar_toolkit.select_none_materials'
|
bl_idname = 'avatar_toolkit.select_none_materials'
|
||||||
bl_label = "Select None"
|
bl_label = "Select None"
|
||||||
bl_description = "Deselect all materials"
|
bl_description = "Deselect all materials"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
for item in context.scene.materials:
|
for item in context.scene.avatar_toolkit.materials:
|
||||||
item.mat.include_in_atlas = False
|
item.mat.avatar_toolkit.include_in_atlas = False
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_ExpandAllMaterials(Operator):
|
class AvatarToolKit_OT_ExpandAllMaterials(Operator):
|
||||||
bl_idname = 'avatar_toolkit.expand_all_materials'
|
bl_idname = 'avatar_toolkit.expand_all_materials'
|
||||||
bl_label = "Expand All"
|
bl_label = "Expand All"
|
||||||
bl_description = "Expand all material settings"
|
bl_description = "Expand all material settings"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
for item in context.scene.materials:
|
for item in context.scene.avatar_toolkit.materials:
|
||||||
item.mat.material_expanded = True
|
item.mat.avatar_toolkit.material_expanded = True
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_CollapseAllMaterials(Operator):
|
class AvatarToolKit_OT_CollapseAllMaterials(Operator):
|
||||||
bl_idname = 'avatar_toolkit.collapse_all_materials'
|
bl_idname = 'avatar_toolkit.collapse_all_materials'
|
||||||
bl_label = "Collapse All"
|
bl_label = "Collapse All"
|
||||||
bl_description = "Collapse all material settings"
|
bl_description = "Collapse all material settings"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
for item in context.scene.materials:
|
for item in context.scene.avatar_toolkit.materials:
|
||||||
item.mat.material_expanded = False
|
item.mat.avatar_toolkit.material_expanded = False
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_OT_ExpandSectionMaterials(Operator):
|
class AvatarToolKit_OT_ExpandSectionMaterials(Operator):
|
||||||
bl_idname = 'avatar_toolkit.expand_section_materials'
|
bl_idname = 'avatar_toolkit.expand_section_materials'
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
@@ -62,23 +56,22 @@ class AvatarToolKit_OT_ExpandSectionMaterials(Operator):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def execute(self, context: Context) -> set:
|
def execute(self, context: Context) -> set:
|
||||||
if not context.scene.texture_atlas_Has_Mat_List_Shown:
|
if not context.scene.avatar_toolkit.texture_atlas_Has_Mat_List_Shown:
|
||||||
context.scene.materials.clear()
|
context.scene.avatar_toolkit.materials.clear()
|
||||||
newlist: list[Material] = []
|
newlist: list[Material] = []
|
||||||
for obj in bpy.context.scene.objects:
|
for obj in context.scene.objects:
|
||||||
if len(obj.material_slots)>0:
|
if len(obj.material_slots)>0:
|
||||||
for mat_slot in obj.material_slots:
|
for mat_slot in obj.material_slots:
|
||||||
if mat_slot.material:
|
if mat_slot.material:
|
||||||
if mat_slot.material not in newlist:
|
if mat_slot.material not in newlist:
|
||||||
newlist.append(mat_slot.material)
|
newlist.append(mat_slot.material)
|
||||||
newitem: SceneMatClass = context.scene.materials.add()
|
newitem: SceneMatClass = context.scene.avatar_toolkit.materials.add()
|
||||||
newitem.mat = mat_slot.material
|
newitem.mat = mat_slot.material
|
||||||
MaterialListBool.old_list[context.scene.name] = newlist
|
MaterialListBool.old_list[context.scene.name] = newlist
|
||||||
else:
|
else:
|
||||||
context.scene.texture_atlas_Has_Mat_List_Shown = False
|
context.scene.avatar_toolkit.texture_atlas_Has_Mat_List_Shown = False
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_UL_MaterialTextureAtlasProperties(UIList):
|
class AvatarToolKit_UL_MaterialTextureAtlasProperties(UIList):
|
||||||
bl_label = t("TextureAtlas.material_list_label")
|
bl_label = t("TextureAtlas.material_list_label")
|
||||||
bl_idname = "Material_UL_avatar_toolkit_texture_atlas_mat_list_mat"
|
bl_idname = "Material_UL_avatar_toolkit_texture_atlas_mat_list_mat"
|
||||||
@@ -93,38 +86,35 @@ class AvatarToolKit_UL_MaterialTextureAtlasProperties(UIList):
|
|||||||
row.operator("avatar_toolkit.select_none_materials", text="", icon='CHECKBOX_DEHLT')
|
row.operator("avatar_toolkit.select_none_materials", text="", icon='CHECKBOX_DEHLT')
|
||||||
row.operator("avatar_toolkit.expand_all_materials", text="", icon='DISCLOSURE_TRI_DOWN')
|
row.operator("avatar_toolkit.expand_all_materials", text="", icon='DISCLOSURE_TRI_DOWN')
|
||||||
row.operator("avatar_toolkit.collapse_all_materials", text="", icon='DISCLOSURE_TRI_RIGHT')
|
row.operator("avatar_toolkit.collapse_all_materials", text="", icon='DISCLOSURE_TRI_RIGHT')
|
||||||
row.prop(context.scene, "material_search_filter", text="", icon='VIEWZOOM')
|
row.prop(context.scene.avatar_toolkit, "material_search_filter", text="", icon='VIEWZOOM')
|
||||||
|
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
row = box.row()
|
row = box.row()
|
||||||
row.label(text=f"Estimated Atlas Size: {self.calculate_atlas_size(context)}px")
|
row.label(text=f"Estimated Atlas Size: {self.calculate_atlas_size(context)}px")
|
||||||
|
|
||||||
def draw_item(self, context: Context, layout: UILayout, data: Object, item: SceneMatClass, icon, active_data, active_propname, index):
|
def draw_item(self, context: Context, layout: UILayout, data: Object, item: SceneMatClass, icon, active_data, active_propname, index):
|
||||||
if context.scene.texture_atlas_Has_Mat_List_Shown:
|
if context.scene.avatar_toolkit.texture_atlas_Has_Mat_List_Shown:
|
||||||
if context.scene.material_search_filter and context.scene.material_search_filter.lower() not in item.mat.name.lower():
|
if context.scene.avatar_toolkit.material_search_filter and context.scene.avatar_toolkit.material_search_filter.lower() not in item.mat.name.lower():
|
||||||
return
|
return
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
|
||||||
# Add a clear checkbox for material selection
|
row.prop(item.mat.avatar_toolkit, "include_in_atlas", text="", icon='CHECKBOX_HLT' if item.mat.avatar_toolkit.include_in_atlas else 'CHECKBOX_DEHLT')
|
||||||
row.prop(item.mat, "include_in_atlas", text="", icon='CHECKBOX_HLT' if item.mat.include_in_atlas else 'CHECKBOX_DEHLT')
|
|
||||||
|
|
||||||
# Material name and expansion toggle
|
row.prop(item.mat.avatar_toolkit, "material_expanded",
|
||||||
row.prop(item.mat, "material_expanded",
|
|
||||||
text=item.mat.name,
|
text=item.mat.name,
|
||||||
icon='DOWNARROW_HLT' if item.mat.material_expanded else 'RIGHTARROW',
|
icon='DOWNARROW_HLT' if item.mat.avatar_toolkit.material_expanded else 'RIGHTARROW',
|
||||||
emboss=False)
|
emboss=False)
|
||||||
|
|
||||||
# Show texture settings if expanded
|
if item.mat.avatar_toolkit.material_expanded and item.mat.avatar_toolkit.include_in_atlas:
|
||||||
if item.mat.material_expanded and item.mat.include_in_atlas:
|
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
col = box.column(align=True)
|
col = box.column(align=True)
|
||||||
self.draw_texture_row(col, item.mat, "texture_atlas_albedo", "IMAGE_RGB")
|
self.draw_texture_row(col, item.mat.avatar_toolkit, "texture_atlas_albedo", "IMAGE_RGB")
|
||||||
self.draw_texture_row(col, item.mat, "texture_atlas_normal", "NORMALS_FACE")
|
self.draw_texture_row(col, item.mat.avatar_toolkit, "texture_atlas_normal", "NORMALS_FACE")
|
||||||
self.draw_texture_row(col, item.mat, "texture_atlas_emission", "LIGHT")
|
self.draw_texture_row(col, item.mat.avatar_toolkit, "texture_atlas_emission", "LIGHT")
|
||||||
self.draw_texture_row(col, item.mat, "texture_atlas_ambient_occlusion", "SHADING_SOLID")
|
self.draw_texture_row(col, item.mat.avatar_toolkit, "texture_atlas_ambient_occlusion", "SHADING_SOLID")
|
||||||
self.draw_texture_row(col, item.mat, "texture_atlas_height", "IMAGE_ZDEPTH")
|
self.draw_texture_row(col, item.mat.avatar_toolkit, "texture_atlas_height", "IMAGE_ZDEPTH")
|
||||||
self.draw_texture_row(col, item.mat, "texture_atlas_roughness", "MATERIAL")
|
self.draw_texture_row(col, item.mat.avatar_toolkit, "texture_atlas_roughness", "MATERIAL")
|
||||||
|
|
||||||
col.separator(factor=0.5)
|
col.separator(factor=0.5)
|
||||||
|
|
||||||
@@ -136,21 +126,15 @@ class AvatarToolKit_UL_MaterialTextureAtlasProperties(UIList):
|
|||||||
else:
|
else:
|
||||||
row.label(text="", icon='X')
|
row.label(text="", icon='X')
|
||||||
|
|
||||||
def is_material_ready(self, material):
|
|
||||||
return bool(material.texture_atlas_albedo or
|
|
||||||
material.texture_atlas_normal or
|
|
||||||
material.texture_atlas_emission)
|
|
||||||
|
|
||||||
def calculate_atlas_size(self, context):
|
def calculate_atlas_size(self, context):
|
||||||
total_size = 0
|
total_size = 0
|
||||||
for mat in context.scene.materials:
|
for mat in context.scene.avatar_toolkit.materials:
|
||||||
if mat.mat.include_in_atlas:
|
if mat.mat.avatar_toolkit.include_in_atlas:
|
||||||
if mat.mat.texture_atlas_albedo:
|
if mat.mat.avatar_toolkit.texture_atlas_albedo:
|
||||||
img = bpy.data.images[mat.mat.texture_atlas_albedo]
|
img = bpy.data.images[mat.mat.avatar_toolkit.texture_atlas_albedo]
|
||||||
total_size += img.size[0] * img.size[1]
|
total_size += img.size[0] * img.size[1]
|
||||||
return f"{int(sqrt(total_size))}x{int(sqrt(total_size))}"
|
return f"{int(sqrt(total_size))}x{int(sqrt(total_size))}"
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_PT_TextureAtlasPanel(Panel):
|
class AvatarToolKit_PT_TextureAtlasPanel(Panel):
|
||||||
bl_label = t("TextureAtlas.label")
|
bl_label = t("TextureAtlas.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_texture_atlas"
|
bl_idname = "OBJECT_PT_avatar_toolkit_texture_atlas"
|
||||||
@@ -170,18 +154,18 @@ class AvatarToolKit_PT_TextureAtlasPanel(Panel):
|
|||||||
|
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
row = box.row()
|
row = box.row()
|
||||||
direction_icon = 'RIGHTARROW' if not context.scene.texture_atlas_Has_Mat_List_Shown else 'DOWNARROW_HLT'
|
direction_icon = 'RIGHTARROW' if not context.scene.avatar_toolkit.texture_atlas_Has_Mat_List_Shown else 'DOWNARROW_HLT'
|
||||||
row.operator(AvatarToolKit_OT_ExpandSectionMaterials.bl_idname,
|
row.operator(AvatarToolKit_OT_ExpandSectionMaterials.bl_idname,
|
||||||
text=(t("TextureAtlas.reload_list") if not context.scene.texture_atlas_Has_Mat_List_Shown else t("TextureAtlas.loaded_list")),
|
text=(t("TextureAtlas.reload_list") if not context.scene.avatar_toolkit.texture_atlas_Has_Mat_List_Shown else t("TextureAtlas.loaded_list")),
|
||||||
icon=direction_icon)
|
icon=direction_icon)
|
||||||
|
|
||||||
if context.scene.texture_atlas_Has_Mat_List_Shown:
|
if context.scene.avatar_toolkit.texture_atlas_Has_Mat_List_Shown:
|
||||||
row = box.row()
|
row = box.row()
|
||||||
row.template_list(AvatarToolKit_UL_MaterialTextureAtlasProperties.bl_idname,
|
row.template_list(AvatarToolKit_UL_MaterialTextureAtlasProperties.bl_idname,
|
||||||
'material_list',
|
'material_list',
|
||||||
context.scene,
|
context.scene.avatar_toolkit,
|
||||||
'materials',
|
'materials',
|
||||||
context.scene,
|
context.scene.avatar_toolkit,
|
||||||
'texture_atlas_material_index',
|
'texture_atlas_material_index',
|
||||||
rows=12,
|
rows=12,
|
||||||
type='DEFAULT')
|
type='DEFAULT')
|
||||||
@@ -195,3 +179,4 @@ class AvatarToolKit_PT_TextureAtlasPanel(Panel):
|
|||||||
icon='NODE_TEXTURE')
|
icon='NODE_TEXTURE')
|
||||||
else:
|
else:
|
||||||
layout.label(text=t("Tools.select_armature"), icon='ERROR')
|
layout.label(text=t("Tools.select_armature"), icon='ERROR')
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from .panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
from ..core.common import open_web_after_delay_multi_threaded
|
from ..core.common import open_web_after_delay_multi_threaded
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_PT_CreditsSupport(bpy.types.Panel):
|
class AvatarToolkit_PT_CreditsSupport(bpy.types.Panel):
|
||||||
bl_label = t("CreditsSupport.label")
|
bl_label = t("CreditsSupport.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_credits_support"
|
bl_idname = "OBJECT_PT_avatar_toolkit_credits_support"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
|
CATEGORY_NAME = "Avatar Toolkit"
|
||||||
|
|
||||||
def draw_title(self: bpy.types.Panel):
|
def draw_title(self: bpy.types.Panel):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
@@ -8,9 +9,6 @@ def draw_title(self: bpy.types.Panel):
|
|||||||
layout.label(text=t("AvatarToolkit.desc2"))
|
layout.label(text=t("AvatarToolkit.desc2"))
|
||||||
layout.label(text=t("AvatarToolkit.desc3"))
|
layout.label(text=t("AvatarToolkit.desc3"))
|
||||||
|
|
||||||
CATEGORY_NAME = "Avatar Toolkit"
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolKit_PT_AvatarToolkitPanel(bpy.types.Panel):
|
class AvatarToolKit_PT_AvatarToolkitPanel(bpy.types.Panel):
|
||||||
bl_label = t("AvatarToolkit.label")
|
bl_label = t("AvatarToolkit.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit"
|
bl_idname = "OBJECT_PT_avatar_toolkit"
|
||||||
@@ -21,4 +19,3 @@ class AvatarToolKit_PT_AvatarToolkitPanel(bpy.types.Panel):
|
|||||||
def draw(self: bpy.types.Panel, context: bpy.types.Context):
|
def draw(self: bpy.types.Panel, context: bpy.types.Context):
|
||||||
draw_title(self)
|
draw_title(self)
|
||||||
|
|
||||||
|
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from .panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
|
||||||
from bpy.types import Panel, Context
|
from bpy.types import Panel, Context
|
||||||
from ..core.common import get_selected_armature
|
from ..core.common import get_selected_armature
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
from ..functions.armature_modifying import AvatarToolkit_OT_MergeArmatures
|
from ..functions.armature_modifying import AvatarToolkit_OT_MergeArmatures
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_PT_MergeArmaturesPanel(Panel):
|
class AvatarToolkit_PT_MergeArmaturesPanel(Panel):
|
||||||
bl_label = t("MergeArmatures.label")
|
bl_label = t("MergeArmatures.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_merge_armatures"
|
bl_idname = "OBJECT_PT_avatar_toolkit_merge_armatures"
|
||||||
@@ -29,14 +26,14 @@ class AvatarToolkit_PT_MergeArmaturesPanel(Panel):
|
|||||||
box = layout.box()
|
box = layout.box()
|
||||||
col = box.column(align=True)
|
col = box.column(align=True)
|
||||||
|
|
||||||
col.prop(context.scene, property="selected_armature", text=t("MergeArmatures.target_armature.label"), icon="ARMATURE_DATA")
|
col.prop(context.scene.avatar_toolkit, "selected_armature", text=t("MergeArmatures.target_armature.label"), icon="ARMATURE_DATA")
|
||||||
col.prop(context.scene, property="merge_armature_source", icon="OUTLINER_OB_ARMATURE")
|
col.prop(context.scene.avatar_toolkit, "merge_armature_source", icon="OUTLINER_OB_ARMATURE")
|
||||||
|
|
||||||
layout.separator(factor=0.5)
|
layout.separator(factor=0.5)
|
||||||
|
|
||||||
col = layout.column(align=True)
|
col = layout.column(align=True)
|
||||||
col.prop(context.scene, property="merge_armature_align_bones", icon="BONE_DATA")
|
col.prop(context.scene.avatar_toolkit, "merge_armature_align_bones", icon="BONE_DATA")
|
||||||
col.prop(context.scene, property="merge_armature_apply_transforms", icon="OBJECT_ORIGIN")
|
col.prop(context.scene.avatar_toolkit, "merge_armature_apply_transforms", icon="OBJECT_ORIGIN")
|
||||||
|
|
||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
|
|
||||||
|
|||||||
+2
-5
@@ -1,13 +1,11 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from .panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
from ..functions.mmd_functions import *
|
from ..functions.mmd_functions import *
|
||||||
from ..functions.mesh_tools import AvatarToolKit_OT_JoinAllMeshes
|
from ..functions.mesh_tools import AvatarToolKit_OT_JoinAllMeshes
|
||||||
from ..functions.combine_materials import AvatarToolKit_OT_CombineMaterials
|
from ..functions.combine_materials import AvatarToolKit_OT_CombineMaterials
|
||||||
from ..functions.additional_tools import AvatarToolKit_OT_ApplyTransforms
|
from ..functions.additional_tools import AvatarToolKit_OT_ApplyTransforms
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_PT_MMDOptionsPanel(bpy.types.Panel):
|
class AvatarToolkit_PT_MMDOptionsPanel(bpy.types.Panel):
|
||||||
bl_label = t("MMDOptions.label")
|
bl_label = t("MMDOptions.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_mmd_options"
|
bl_idname = "OBJECT_PT_avatar_toolkit_mmd_options"
|
||||||
@@ -48,4 +46,3 @@ class AvatarToolkit_PT_MMDOptionsPanel(bpy.types.Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.scale_y = 1.2
|
row.scale_y = 1.2
|
||||||
row.operator(AvatarToolKit_OT_ConvertMaterials.bl_idname, icon='SHADING_TEXTURE')
|
row.operator(AvatarToolKit_OT_ConvertMaterials.bl_idname, icon='SHADING_TEXTURE')
|
||||||
|
|
||||||
|
|||||||
+3
-7
@@ -1,13 +1,11 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from .panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
from ..functions.remove_doubles_safely import AvatarToolKit_OT_RemoveDoublesSafely, AvatarToolKit_OT_RemoveDoublesSafelyAdvanced
|
from ..functions.remove_doubles_safely import AvatarToolKit_OT_RemoveDoublesSafely, AvatarToolKit_OT_RemoveDoublesSafelyAdvanced
|
||||||
from ..core.common import get_selected_armature
|
from ..core.common import get_selected_armature
|
||||||
from ..functions.mesh_tools import AvatarToolKit_OT_JoinAllMeshes, AvatarToolKit_OT_JoinSelectedMeshes
|
from ..functions.mesh_tools import AvatarToolKit_OT_JoinAllMeshes, AvatarToolKit_OT_JoinSelectedMeshes
|
||||||
from ..functions.combine_materials import AvatarToolKit_OT_CombineMaterials
|
from ..functions.combine_materials import AvatarToolKit_OT_CombineMaterials
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_PT_OptimizationPanel(bpy.types.Panel):
|
class AvatarToolkit_PT_OptimizationPanel(bpy.types.Panel):
|
||||||
bl_label = t("Optimization.label")
|
bl_label = t("Optimization.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_optimization"
|
bl_idname = "OBJECT_PT_avatar_toolkit_optimization"
|
||||||
@@ -17,7 +15,7 @@ class AvatarToolkit_PT_OptimizationPanel(bpy.types.Panel):
|
|||||||
bl_parent_id = AvatarToolKit_PT_AvatarToolkitPanel.bl_idname
|
bl_parent_id = AvatarToolKit_PT_AvatarToolkitPanel.bl_idname
|
||||||
bl_order = 2
|
bl_order = 2
|
||||||
|
|
||||||
def draw(self: bpy.types.Panel, context: bpy.types.Context):
|
def draw(self, context: bpy.types.Context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
armature = get_selected_armature(context)
|
armature = get_selected_armature(context)
|
||||||
|
|
||||||
@@ -46,5 +44,3 @@ class AvatarToolkit_PT_OptimizationPanel(bpy.types.Panel):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
layout.label(text=t("Optimization.select_armature"), icon='ERROR')
|
layout.label(text=t("Optimization.select_armature"), icon='ERROR')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+9
-14
@@ -1,17 +1,15 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from .panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
from ..core.exporters.export_resonite import AvatarToolKit_OT_ExportResonite
|
||||||
from ..core.export_resonite import AvatarToolKit_OT_ExportResonite
|
|
||||||
from bpy.types import Context, Mesh, Panel, Operator
|
from bpy.types import Context, Mesh, Panel, Operator
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
|
from ..core.common import get_selected_armature
|
||||||
from ..core.import_pmx import import_pmx
|
|
||||||
from ..core.import_pmd import import_pmd
|
|
||||||
from ..functions.import_anything import AvatarToolKit_OT_ImportAnyModel
|
from ..functions.import_anything import AvatarToolKit_OT_ImportAnyModel
|
||||||
from ..functions.armature_modifying import AvatarToolkit_OT_StartPoseMode, AvatarToolkit_OT_StopPoseMode, AvatarToolkit_OT_ApplyPoseAsRest, AvatarToolkit_OT_ApplyPoseAsShapekey
|
from ..functions.armature_modifying import (AvatarToolkit_OT_StartPoseMode,
|
||||||
from ..core.common import get_selected_armature, set_selected_armature, get_all_meshes
|
AvatarToolkit_OT_StopPoseMode,
|
||||||
|
AvatarToolkit_OT_ApplyPoseAsRest,
|
||||||
|
AvatarToolkit_OT_ApplyPoseAsShapekey)
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkitQuickAccessPanel(Panel):
|
class AvatarToolkitQuickAccessPanel(Panel):
|
||||||
bl_label = t("Quick_Access.label")
|
bl_label = t("Quick_Access.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_quick_access"
|
bl_idname = "OBJECT_PT_avatar_toolkit_quick_access"
|
||||||
@@ -28,7 +26,7 @@ class AvatarToolkitQuickAccessPanel(Panel):
|
|||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
|
|
||||||
layout.label(text=t("Quick_Access.select_armature"), icon='ARMATURE_DATA')
|
layout.label(text=t("Quick_Access.select_armature"), icon='ARMATURE_DATA')
|
||||||
layout.prop(context.scene, "selected_armature", text="")
|
layout.prop(context.scene.avatar_toolkit, "selected_armature", text="")
|
||||||
|
|
||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
|
|
||||||
@@ -58,8 +56,6 @@ class AvatarToolkitQuickAccessPanel(Panel):
|
|||||||
row.scale_y = 1.2
|
row.scale_y = 1.2
|
||||||
row.operator(AvatarToolkit_OT_StartPoseMode.bl_idname, text=t("Quick_Access.start_pose_mode.label"), icon='POSE_HLT')
|
row.operator(AvatarToolkit_OT_StartPoseMode.bl_idname, text=t("Quick_Access.start_pose_mode.label"), icon='POSE_HLT')
|
||||||
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AVATAR_TOOLKIT_OT_ExportMenu(bpy.types.Operator):
|
class AVATAR_TOOLKIT_OT_ExportMenu(bpy.types.Operator):
|
||||||
bl_idname = "avatar_toolkit.export_menu"
|
bl_idname = "avatar_toolkit.export_menu"
|
||||||
bl_label = t("Quick_Access.export_menu.label")
|
bl_label = t("Quick_Access.export_menu.label")
|
||||||
@@ -82,7 +78,6 @@ class AVATAR_TOOLKIT_OT_ExportMenu(bpy.types.Operator):
|
|||||||
layout.operator(AvatarToolKit_OT_ExportResonite.bl_idname, text=t("Quick_Access.select_export_resonite.label"), icon='SCENE_DATA')
|
layout.operator(AvatarToolKit_OT_ExportResonite.bl_idname, text=t("Quick_Access.select_export_resonite.label"), icon='SCENE_DATA')
|
||||||
layout.operator(AVATAR_TOOLKIT_OT_ExportFbx.bl_idname, text=t("Quick_Access.export_fbx.label"), icon='OBJECT_DATA')
|
layout.operator(AVATAR_TOOLKIT_OT_ExportFbx.bl_idname, text=t("Quick_Access.export_fbx.label"), icon='OBJECT_DATA')
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AVATAR_TOOLKIT_OT_ExportFbx(bpy.types.Operator):
|
class AVATAR_TOOLKIT_OT_ExportFbx(bpy.types.Operator):
|
||||||
bl_idname = 'avatar_toolkit.export_fbx'
|
bl_idname = 'avatar_toolkit.export_fbx'
|
||||||
bl_label = t("Quick_Access.export_fbx.label")
|
bl_label = t("Quick_Access.export_fbx.label")
|
||||||
|
|||||||
+5
-9
@@ -1,9 +1,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from .panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkitSettingsPanel(bpy.types.Panel):
|
class AvatarToolkitSettingsPanel(bpy.types.Panel):
|
||||||
bl_label = t("Settings.label")
|
bl_label = t("Settings.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_settings"
|
bl_idname = "OBJECT_PT_avatar_toolkit_settings"
|
||||||
@@ -17,9 +15,8 @@ class AvatarToolkitSettingsPanel(bpy.types.Panel):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
layout.label(text=t("Settings.language.label"))
|
layout.label(text=t("Settings.language.label"))
|
||||||
layout.prop(context.scene, "avatar_toolkit_language", text="", icon='WORLD')
|
layout.prop(context.scene.avatar_toolkit, "language", text="", icon='WORLD')
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AVATAR_TOOLKIT_OT_translation_restart_popup(bpy.types.Operator):
|
class AVATAR_TOOLKIT_OT_translation_restart_popup(bpy.types.Operator):
|
||||||
bl_idname = "avatar_toolkit.translation_restart_popup"
|
bl_idname = "avatar_toolkit.translation_restart_popup"
|
||||||
bl_label = t("Settings.translation_restart_popup.label")
|
bl_label = t("Settings.translation_restart_popup.label")
|
||||||
@@ -27,9 +24,9 @@ class AVATAR_TOOLKIT_OT_translation_restart_popup(bpy.types.Operator):
|
|||||||
bl_options = {'INTERNAL'}
|
bl_options = {'INTERNAL'}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
if context.scene.avatar_toolkit_language_changed:
|
if context.scene.avatar_toolkit.language_changed:
|
||||||
bpy.ops.script.reload()
|
bpy.ops.script.reload()
|
||||||
context.scene.avatar_toolkit_language_changed = False
|
context.scene.avatar_toolkit.language_changed = False
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
@@ -39,4 +36,3 @@ class AVATAR_TOOLKIT_OT_translation_restart_popup(bpy.types.Operator):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.label(text=t("Settings.translation_restart_popup.message1"), icon='INFO')
|
layout.label(text=t("Settings.translation_restart_popup.message1"), icon='INFO')
|
||||||
layout.label(text=t("Settings.translation_restart_popup.message2"), icon='FILE_REFRESH')
|
layout.label(text=t("Settings.translation_restart_popup.message2"), icon='FILE_REFRESH')
|
||||||
|
|
||||||
|
|||||||
+12
-12
@@ -1,17 +1,20 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from .panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
|
||||||
from bpy.types import Context
|
from bpy.types import Context
|
||||||
from ..functions.digitigrade_legs import AvatarToolKit_OT_CreateDigitigradeLegs
|
from ..functions.digitigrade_legs import AvatarToolKit_OT_CreateDigitigradeLegs
|
||||||
from ..functions.resonite_functions import AvatarToolKit_OT_ConvertToResonite
|
from ..functions.resonite_functions import AvatarToolKit_OT_ConvertToResonite
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
from ..core.common import get_selected_armature
|
from ..core.common import get_selected_armature
|
||||||
from ..functions.mesh_tools import AvatarToolkit_OT_RemoveUnusedShapekeys
|
from ..functions.mesh_tools import AvatarToolkit_OT_RemoveUnusedShapekeys
|
||||||
from ..functions.additional_tools import AvatarToolKit_OT_ApplyTransforms, AvatarToolKit_OT_ConnectBones, AvatarToolKit_OT_DeleteBoneConstraints, AvatarToolKit_OT_SeparateByMaterials, AvatarToolKit_OT_SeparateByLooseParts
|
from ..functions.additional_tools import (AvatarToolKit_OT_ApplyTransforms,
|
||||||
from ..functions.armature_modifying import AvatarToolkit_OT_RemoveZeroWeightBones, AvatarToolkit_OT_MergeBonesToActive, AvatarToolkit_OT_MergeBonesToParents
|
AvatarToolKit_OT_ConnectBones,
|
||||||
from ..functions.rigify_functions import AvatarToolKit_OT_ConvertRigifyToUnity
|
AvatarToolKit_OT_DeleteBoneConstraints,
|
||||||
|
AvatarToolKit_OT_SeparateByMaterials,
|
||||||
|
AvatarToolKit_OT_SeparateByLooseParts)
|
||||||
|
from ..functions.armature_modifying import (AvatarToolkit_OT_RemoveZeroWeightBones,
|
||||||
|
AvatarToolkit_OT_MergeBonesToActive,
|
||||||
|
AvatarToolkit_OT_MergeBonesToParents)
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkit_PT_ToolsPanel(bpy.types.Panel):
|
class AvatarToolkit_PT_ToolsPanel(bpy.types.Panel):
|
||||||
bl_label = t("Tools.label")
|
bl_label = t("Tools.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_tools"
|
bl_idname = "OBJECT_PT_avatar_toolkit_tools"
|
||||||
@@ -33,10 +36,6 @@ class AvatarToolkit_PT_ToolsPanel(bpy.types.Panel):
|
|||||||
row.scale_y = 1.5
|
row.scale_y = 1.5
|
||||||
row.operator(AvatarToolKit_OT_ConvertToResonite.bl_idname, text=t("Tools.convert_to_resonite.label"), icon='SCENE_DATA')
|
row.operator(AvatarToolKit_OT_ConvertToResonite.bl_idname, text=t("Tools.convert_to_resonite.label"), icon='SCENE_DATA')
|
||||||
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.scale_y = 1.5
|
|
||||||
row.operator(AvatarToolKit_OT_ConvertRigifyToUnity.bl_idname, text=t("Tools.convert_rigify_to_unity.label"), icon='ARMATURE_DATA')
|
|
||||||
|
|
||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
|
|
||||||
layout.label(text=t("Tools.separate_by.label"), icon='MESH_DATA')
|
layout.label(text=t("Tools.separate_by.label"), icon='MESH_DATA')
|
||||||
@@ -62,7 +61,7 @@ class AvatarToolkit_PT_ToolsPanel(bpy.types.Panel):
|
|||||||
row.operator(AvatarToolKit_OT_DeleteBoneConstraints.bl_idname, text=t("Tools.delete_bone_constraints.label"), icon='CONSTRAINT_BONE')
|
row.operator(AvatarToolKit_OT_DeleteBoneConstraints.bl_idname, text=t("Tools.delete_bone_constraints.label"), icon='CONSTRAINT_BONE')
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(context.scene, "merge_twist_bones")
|
row.prop(context.scene.avatar_toolkit, "merge_twist_bones")
|
||||||
|
|
||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
|
|
||||||
@@ -74,3 +73,4 @@ class AvatarToolkit_PT_ToolsPanel(bpy.types.Panel):
|
|||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
else:
|
else:
|
||||||
layout.label(text=t("Tools.select_armature"), icon='ERROR')
|
layout.label(text=t("Tools.select_armature"), icon='ERROR')
|
||||||
|
|
||||||
|
|||||||
+3
-6
@@ -1,9 +1,7 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
from .main_panel import draw_title
|
||||||
from .panel import draw_title
|
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class UVTools_PT_MainPanel(bpy.types.Panel):
|
class UVTools_PT_MainPanel(bpy.types.Panel):
|
||||||
bl_label = t("AvatarToolkit.label")
|
bl_label = t("AvatarToolkit.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_uv"
|
bl_idname = "OBJECT_PT_avatar_toolkit_uv"
|
||||||
@@ -13,5 +11,4 @@ class UVTools_PT_MainPanel(bpy.types.Panel):
|
|||||||
|
|
||||||
def draw(self: bpy.types.Panel, context: bpy.types.Context):
|
def draw(self: bpy.types.Panel, context: bpy.types.Context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
draw_title(self)
|
||||||
draw_title(self)
|
|
||||||
|
|||||||
+3
-7
@@ -1,12 +1,9 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from ..core.translations import t
|
||||||
from ..functions.translations import t
|
|
||||||
from ..functions.uv_tools import AvatarToolkit_OT_AlignUVEdgesToTarget
|
from ..functions.uv_tools import AvatarToolkit_OT_AlignUVEdgesToTarget
|
||||||
from .panel import draw_title
|
from .main_panel import draw_title
|
||||||
from .uv_panel import UVTools_PT_MainPanel
|
from .uv_panel import UVTools_PT_MainPanel
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class UVTools_PT_Tools(bpy.types.Panel):
|
class UVTools_PT_Tools(bpy.types.Panel):
|
||||||
bl_label = t("Tools.label")
|
bl_label = t("Tools.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_uv_tools"
|
bl_idname = "OBJECT_PT_avatar_toolkit_uv_tools"
|
||||||
@@ -18,6 +15,5 @@ class UVTools_PT_Tools(bpy.types.Panel):
|
|||||||
|
|
||||||
def draw(self, context: bpy.types.Context):
|
def draw(self, context: bpy.types.Context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.operator(AvatarToolkit_OT_AlignUVEdgesToTarget.bl_idname, text=t("avatar_toolkit.align_uv_edges_to_target.label"), icon='GP_MULTIFRAME_EDITING')
|
row.operator(AvatarToolkit_OT_AlignUVEdgesToTarget.bl_idname, text=t("avatar_toolkit.align_uv_edges_to_target.label"), icon='GP_MULTIFRAME_EDITING')
|
||||||
|
|||||||
+8
-11
@@ -1,11 +1,9 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from ..core.register import register_wrap
|
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
||||||
from .panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
|
|
||||||
from ..functions.viseme import AvatarToolKit_OT_AutoVisemeButton
|
from ..functions.viseme import AvatarToolKit_OT_AutoVisemeButton
|
||||||
from ..functions.translations import t
|
from ..core.translations import t
|
||||||
from ..core.common import get_selected_armature
|
from ..core.common import get_selected_armature
|
||||||
|
|
||||||
@register_wrap
|
|
||||||
class AvatarToolkitVisemePanel(bpy.types.Panel):
|
class AvatarToolkitVisemePanel(bpy.types.Panel):
|
||||||
bl_label = t("VisemePanel.label")
|
bl_label = t("VisemePanel.label")
|
||||||
bl_idname = "OBJECT_PT_avatar_toolkit_viseme"
|
bl_idname = "OBJECT_PT_avatar_toolkit_viseme"
|
||||||
@@ -24,20 +22,20 @@ class AvatarToolkitVisemePanel(bpy.types.Panel):
|
|||||||
|
|
||||||
layout.separator(factor=0.5)
|
layout.separator(factor=0.5)
|
||||||
|
|
||||||
layout.prop(context.scene, "selected_mesh", text=t("VisemePanel.select_mesh"), icon='OUTLINER_OB_MESH')
|
layout.prop(context.scene.avatar_toolkit, "selected_mesh", text=t("VisemePanel.select_mesh"), icon='OUTLINER_OB_MESH')
|
||||||
|
|
||||||
mesh = bpy.data.objects.get(context.scene.selected_mesh)
|
mesh = bpy.data.objects.get(context.scene.avatar_toolkit.selected_mesh)
|
||||||
if mesh and mesh.type == 'MESH':
|
if mesh and mesh.type == 'MESH':
|
||||||
if mesh.data.shape_keys:
|
if mesh.data.shape_keys:
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
col = box.column(align=True)
|
col = box.column(align=True)
|
||||||
col.prop_search(context.scene, "avatar_toolkit_mouth_a", mesh.data.shape_keys, "key_blocks", text=t('VisemePanel.mouth_a.label'), icon='SHAPEKEY_DATA')
|
col.prop_search(context.scene.avatar_toolkit, "mouth_a", mesh.data.shape_keys, "key_blocks", text=t('VisemePanel.mouth_a.label'), icon='SHAPEKEY_DATA')
|
||||||
col.prop_search(context.scene, "avatar_toolkit_mouth_o", mesh.data.shape_keys, "key_blocks", text=t('VisemePanel.mouth_o.label'), icon='SHAPEKEY_DATA')
|
col.prop_search(context.scene.avatar_toolkit, "mouth_o", mesh.data.shape_keys, "key_blocks", text=t('VisemePanel.mouth_o.label'), icon='SHAPEKEY_DATA')
|
||||||
col.prop_search(context.scene, "avatar_toolkit_mouth_ch", mesh.data.shape_keys, "key_blocks", text=t('VisemePanel.mouth_ch.label'), icon='SHAPEKEY_DATA')
|
col.prop_search(context.scene.avatar_toolkit, "mouth_ch", mesh.data.shape_keys, "key_blocks", text=t('VisemePanel.mouth_ch.label'), icon='SHAPEKEY_DATA')
|
||||||
|
|
||||||
layout.separator(factor=0.5)
|
layout.separator(factor=0.5)
|
||||||
|
|
||||||
layout.prop(context.scene, 'avatar_toolkit_shape_intensity', text=t('VisemePanel.shape_intensity'), icon='FORCE_LENNARDJONES')
|
layout.prop(context.scene.avatar_toolkit, 'shape_intensity', text=t('VisemePanel.shape_intensity'), icon='FORCE_LENNARDJONES')
|
||||||
|
|
||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
|
|
||||||
@@ -53,4 +51,3 @@ class AvatarToolkitVisemePanel(bpy.types.Panel):
|
|||||||
|
|
||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
layout.label(text=t('VisemePanel.info.selectMesh'), icon='HELP')
|
layout.label(text=t('VisemePanel.info.selectMesh'), icon='HELP')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user