Start of the Major Overhaul

I decided to go through each function and UI section one by one, improving and overhauling things. Each function and section is going to be fully tested and not rushed out.

This is the best way to catch things, but also include the code base as much as possible.
This commit is contained in:
Yusarina
2024-12-03 22:58:17 +00:00
parent 7f9dc20564
commit ff23d23cfc
38 changed files with 604 additions and 4765 deletions
+132
View File
@@ -0,0 +1,132 @@
import bpy
from typing import Set, Optional, List, Tuple
from bpy.types import Operator, Panel, Menu, Context, UILayout
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
from ..core.translations import t
from ..core.common import (
get_active_armature,
clear_default_objects,
validate_armature,
get_armature_list,
get_armature_stats
)
from ..core.importers.importer import import_types, imports
from ..functions.pose_mode import (
AvatarToolkit_OT_StartPoseMode,
AvatarToolkit_OT_StopPoseMode,
AvatarToolkit_OT_ApplyPoseAsShapekey,
AvatarToolkit_OT_ApplyPoseAsRest
)
class AvatarToolKit_OT_Import(Operator):
"""Import FBX files into Blender with Avatar Toolkit settings"""
bl_idname = "avatar_toolkit.import"
bl_label = t("QuickAccess.import")
def execute(self, context: Context) -> Set[str]:
clear_default_objects()
bpy.ops.import_scene.fbx('INVOKE_DEFAULT', filter_glob=imports)
return {'FINISHED'}
class AvatarToolKit_OT_ExportFBX(Operator):
"""Export selected objects as FBX"""
bl_idname = "avatar_toolkit.export_fbx"
bl_label = t("QuickAccess.export_fbx")
def execute(self, context: Context) -> Set[str]:
bpy.ops.export_scene.fbx('INVOKE_DEFAULT')
return {'FINISHED'}
class AvatarToolKit_MT_ExportMenu(Menu):
"""Export menu containing various export options"""
bl_idname = "AVATAR_TOOLKIT_MT_export_menu"
bl_label = t("QuickAccess.export")
def draw(self, context: Context) -> None:
layout: UILayout = self.layout
layout.operator("avatar_toolkit.export_fbx", text=t("QuickAccess.export_fbx"))
layout.operator("avatar_toolkit.export_resonite", text=t("QuickAccess.export_resonite"))
class AvatarToolKit_OT_ExportMenu(Operator):
"""Open the export menu"""
bl_idname = "avatar_toolkit.export"
bl_label = t("QuickAccess.export")
def execute(self, context: Context) -> Set[str]:
bpy.ops.wm.call_menu(name=AvatarToolKit_MT_ExportMenu.bl_idname)
return {'FINISHED'}
class AvatarToolKit_PT_QuickAccessPanel(Panel):
"""Quick access panel for common Avatar Toolkit operations"""
bl_label = t("QuickAccess.label")
bl_idname = "OBJECT_PT_avatar_toolkit_quick_access"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = CATEGORY_NAME
bl_parent_id = AvatarToolKit_PT_AvatarToolkitPanel.bl_idname
bl_order = 0
@classmethod
def poll(cls, context: Context) -> bool:
"""Only show panel in Object or Pose mode"""
return context.mode in {'OBJECT', 'POSE'}
def draw(self, context: Context) -> None:
"""Draw the panel layout"""
layout: UILayout = self.layout
# Armature Selection Box
armature_box: UILayout = layout.box()
col: UILayout = armature_box.column(align=True)
col.label(text=t("QuickAccess.select_armature"), icon='ARMATURE_DATA')
col.separator(factor=0.5)
# Armature Selection
col.prop(context.scene.avatar_toolkit, "active_armature", text="")
# Armature Validation
active_armature = get_active_armature(context)
if active_armature:
is_valid: bool
message: str
is_valid, message = validate_armature(active_armature)
if is_valid:
info_box: UILayout = col.box()
row: UILayout = info_box.row()
split: UILayout = row.split(factor=0.6)
split.label(text=t("QuickAccess.valid_armature"), icon='CHECKMARK')
stats: dict = get_armature_stats(active_armature)
split.label(text=t("QuickAccess.bones_count", count=stats['bone_count']))
if stats['has_pose']:
info_box.label(text=t("QuickAccess.pose_bones_available"), icon='POSE_HLT')
else:
col.separator(factor=0.5)
col.label(text=message, icon='ERROR')
# Pose Mode Controls
pose_box: UILayout = layout.box()
col = pose_box.column(align=True)
col.label(text=t("QuickAccess.pose_controls"), icon='ARMATURE_DATA')
col.separator(factor=0.5)
if context.mode == "POSE":
col.operator(AvatarToolkit_OT_StopPoseMode.bl_idname, icon='POSE_HLT')
col.separator(factor=0.5)
col.operator(AvatarToolkit_OT_ApplyPoseAsRest.bl_idname, icon='MOD_ARMATURE')
col.operator(AvatarToolkit_OT_ApplyPoseAsShapekey.bl_idname, icon='MOD_ARMATURE')
else:
col.operator(AvatarToolkit_OT_StartPoseMode.bl_idname, icon='POSE_HLT')
# Import/Export Box
import_box: UILayout = layout.box()
col = import_box.column(align=True)
col.label(text=t("QuickAccess.import_export"), icon='IMPORT')
col.separator(factor=0.5)
# Import/Export Buttons
button_row: UILayout = col.row(align=True)
button_row.scale_y = 1.5
button_row.operator("avatar_toolkit.import", text=t("QuickAccess.import"), icon='IMPORT')
button_row.operator("avatar_toolkit.export", text=t("QuickAccess.export"), icon='EXPORT')