290 lines
9.0 KiB
Python
290 lines
9.0 KiB
Python
bl_info = {
|
|
"name": "Mabulig Rigger Plugin",
|
|
"author": "Fritz Villahermosa",
|
|
"version": (1, 0),
|
|
"blender": (5, 2, 0),
|
|
"location": "View3D > Sidebar > Mabulig Rigger",
|
|
"description": "Frog rigging made simple!",
|
|
"category": "3D View",
|
|
}
|
|
|
|
|
|
import bpy
|
|
import os
|
|
from bpy.props import FloatProperty, PointerProperty, BoolProperty
|
|
|
|
# =========================================================================
|
|
# GLOBAL VARIABLES
|
|
# =========================================================================
|
|
|
|
|
|
|
|
# =========================================================================
|
|
# PROPERTIES
|
|
# =========================================================================
|
|
|
|
# SVL Properties
|
|
class SpecimenProperties(bpy.types.PropertyGroup):
|
|
svl: FloatProperty(
|
|
name="Specimen SVL",
|
|
description="Snout-Vent Length of the specimen in meters",
|
|
default=0.1, # 10 cm default
|
|
min=0.001,
|
|
soft_max=10.0,
|
|
unit='LENGTH'
|
|
) # pyright: ignore[reportInvalidTypeForm]
|
|
|
|
# Model Picker
|
|
target_model: PointerProperty(
|
|
type=bpy.types.Object,
|
|
name="Target Model",
|
|
description="Points to the specimen's 3d model"
|
|
) # type: ignore
|
|
|
|
class PanelProperties(bpy.types.PropertyGroup):
|
|
panel2_g1: BoolProperty(
|
|
name="Panel 2, Group 1",
|
|
description="Toggle panel/group visibility",
|
|
default=False
|
|
) # pyright: ignore[reportInvalidTypeForm]
|
|
panel2_g2: BoolProperty(
|
|
name="Panel 2, Group 2",
|
|
description="Toggle panel/group visibility",
|
|
default=False
|
|
) # pyright: ignore[reportInvalidTypeForm]
|
|
panel3_g1: BoolProperty(
|
|
name="Panel 2, Group 1",
|
|
description="Toggle panel/group visibility",
|
|
default=False
|
|
) # pyright: ignore[reportInvalidTypeForm]
|
|
|
|
|
|
|
|
|
|
# =========================================================================
|
|
# OPERATORS
|
|
# =========================================================================
|
|
|
|
# SETUP SCENE BUTTON
|
|
class SceneSetup(bpy.types.Operator):
|
|
bl_idname = "scene_setup.operator"
|
|
bl_label = "Setup Scene_test"
|
|
bl_description = "Imports all the necessary rigging setup components"
|
|
|
|
def execute(self, context):
|
|
|
|
# Enable Panel 2, Group 1
|
|
bpy.context.scene.panel_propert.panel2_g1 = True
|
|
|
|
return {'FINISHED'}
|
|
|
|
# SETUP SKELETAL BONES
|
|
class SkelSetup(bpy.types.Operator):
|
|
bl_idname = "skel_setup.operator"
|
|
bl_label = "Skeletal Bones"
|
|
bl_description = "Enables the empties for easier skeletal bone placement"
|
|
|
|
def execute(self, context):
|
|
print("Hello World")
|
|
return {'FINISHED'}
|
|
|
|
# SETUP GULAR BONES
|
|
class GularSetup(bpy.types.Operator):
|
|
bl_idname = "gular_setup.operator"
|
|
bl_label = "Gular Bones"
|
|
bl_description = "Enables the gular mesh and empties"
|
|
|
|
def execute(self, context):
|
|
print("Hello World")
|
|
return {'FINISHED'}
|
|
|
|
# SETUP BELLY BONES
|
|
class BellySetup(bpy.types.Operator):
|
|
bl_idname = "belly_setup.operator"
|
|
bl_label = "Belly Bones"
|
|
bl_description = "Enables the belly mesh and empties"
|
|
|
|
def execute(self, context):
|
|
print("Hello World")
|
|
return {'FINISHED'}
|
|
|
|
# SETUP NOSTRIL BONES
|
|
class NostrilsSetup(bpy.types.Operator):
|
|
bl_idname = "nostrils_setup.operator"
|
|
bl_label = "Nostril Bones"
|
|
bl_description = "Enables the nostrils mesh"
|
|
|
|
def execute(self, context):
|
|
print("Hello World")
|
|
return {'FINISHED'}
|
|
|
|
# SPAWN RULER PLANE
|
|
class RulerPlane(bpy.types.Operator):
|
|
bl_idname = "ruler_plane.operator"
|
|
bl_label = "Spawn Ruler Plane"
|
|
bl_description = "Spawns a plane with the SVL length"
|
|
|
|
def execute(self, context):
|
|
props = context.scene.specimen_props
|
|
svl_val = props.svl
|
|
|
|
# Directly reset the scene cursor location and rotation
|
|
context.scene.cursor.location = (0.0, 0.0, 0.0)
|
|
context.scene.cursor.rotation_euler = (0.0, 0.0, 0.0)
|
|
|
|
# Spawn plane mesh, set size to SVL, diplaymode to wireframe, then show in front
|
|
bpy.ops.mesh.primitive_plane_add(size=2, enter_editmode=False, align='WORLD', scale=(1, 1, 1))
|
|
rulerplane_obj = context.active_object
|
|
rulerplane_obj.scale = (svl_val, svl_val, 1.0)
|
|
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
|
|
rulerplane_obj.name = f"Specimen_Plane_{svl_val:.2f}m"
|
|
rulerplane_obj.display_type = 'WIRE'
|
|
rulerplane_obj.show_in_front = True
|
|
|
|
# Enable Panel 2, Group 2
|
|
bpy.context.scene.panel_propert.panel2_g2 = True
|
|
|
|
return {'FINISHED'}
|
|
|
|
# APPLY SCALE
|
|
class ApplyScale(bpy.types.Operator):
|
|
bl_idname = "apply_scale.operator"
|
|
bl_label = "Apply Scale and Adjust"
|
|
bl_description = "Applies the scale and adjusts the mesh for the 3d viewer scale"
|
|
|
|
def execute(self, context):
|
|
props = context.scene.specimen_props
|
|
|
|
bpy.ops.object.select_all(action='DESELECT')
|
|
|
|
target_obj = props.target_model
|
|
|
|
if target_obj:
|
|
target_obj.select_set(True)
|
|
target_obj.scale = (10, 10, 10)
|
|
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
|
|
|
|
# Enable Panel 2, Group 2
|
|
bpy.context.scene.panel_propert.panel3_g1 = True
|
|
|
|
else:
|
|
print("No model selected")
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
# =========================================================================
|
|
# PANELS
|
|
# =========================================================================
|
|
|
|
class MabuligRiggerSceneSetupPanel(bpy.types.Panel):
|
|
|
|
bl_label = "1. Scene Setup"
|
|
bl_idname = "scene_setup.panel"
|
|
bl_space_type = 'VIEW_3D'
|
|
bl_region_type = 'UI'
|
|
bl_category = "Mabulig Rigger"
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
#Add Scene Setup button
|
|
layout.operator("scene_setup.operator", icon='OUTLINER_COLLECTION')
|
|
|
|
class ModelPrepPanel(bpy.types.Panel):
|
|
|
|
bl_label = "2. Model Preparation"
|
|
bl_idname = "model_prep.panel"
|
|
bl_space_type = 'VIEW_3D'
|
|
bl_region_type = 'UI'
|
|
bl_category = "Mabulig Rigger"
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
props = context.scene.specimen_props
|
|
# paneler = context.scene.panel_propert
|
|
# paneler.panel2_g1 = True
|
|
|
|
mod_prep_col1 = layout.column()
|
|
mod_prep_col1.prop(props, "svl")
|
|
mod_prep_col1.operator("ruler_plane.operator", icon='MESH_PLANE')
|
|
mod_prep_col1.enabled = bpy.context.scene.panel_propert.panel2_g1
|
|
|
|
layout.separator()
|
|
|
|
mod_prep_col2 = layout.column()
|
|
mod_prep_col2.prop(props, "target_model")
|
|
mod_prep_col2.operator("apply_scale.operator", icon='FIXED_SIZE')
|
|
mod_prep_col2.enabled = bpy.context.scene.panel_propert.panel2_g2
|
|
|
|
|
|
class RiggingProcessPanel(bpy.types.Panel):
|
|
|
|
bl_label = "3. Rigging Process"
|
|
bl_idname = "rigging_process.panel"
|
|
bl_space_type = 'VIEW_3D'
|
|
bl_region_type = 'UI'
|
|
bl_category = "Mabulig Rigger"
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
rig_proc_row = layout.row()
|
|
rig_proc_row.alignment = 'CENTER'
|
|
rig_proc_row.label(text="Setup Helpers")
|
|
|
|
rig_proc_grid = layout.grid_flow(columns=2, align=True)
|
|
#Add Buttons
|
|
rig_proc_grid.operator("skel_setup.operator")
|
|
rig_proc_grid.operator("gular_setup.operator")
|
|
rig_proc_grid.operator("belly_setup.operator")
|
|
rig_proc_grid.operator("nostrils_setup.operator")
|
|
rig_proc_grid.enabled = bpy.context.scene.panel_propert.panel3_g1
|
|
|
|
classes = (SceneSetup, SkelSetup, GularSetup, BellySetup, NostrilsSetup, RulerPlane, ApplyScale, MabuligRiggerSceneSetupPanel, ModelPrepPanel, RiggingProcessPanel, SpecimenProperties, PanelProperties)
|
|
|
|
def register():
|
|
for i in classes:
|
|
bpy.utils.register_class(i)
|
|
|
|
|
|
bpy.types.Scene.specimen_props = bpy.props.PointerProperty(type=SpecimenProperties)
|
|
bpy.types.Scene.panel_propert = bpy.props.PointerProperty(type=PanelProperties)
|
|
|
|
# for scene in bpy.data.scenes:
|
|
# if "panel_propert" in scene:
|
|
# del scene["panel_propert"]
|
|
# print("test")
|
|
#
|
|
# if "specimen_props" in scene:
|
|
# del scene["specimen_props"]
|
|
# print("test")
|
|
|
|
|
|
def unregister():
|
|
# for scene in bpy.data.scenes:
|
|
# if "panel_propert" in scene:
|
|
# del scene["panel_propert"]
|
|
# print("test")
|
|
#
|
|
# if "specimen_props" in scene:
|
|
# del scene["specimen_props"]
|
|
# print("test")
|
|
|
|
for i in classes:
|
|
bpy.utils.unregister_class(i)
|
|
|
|
|
|
del bpy.types.Scene.specimen_props
|
|
del bpy.types.Scene.panel_propert
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# bpy.context.scene.panel_propert.panel2_g1 = False
|
|
# bpy.context.scene.panel_propert.panel2_g2 = False
|
|
# bpy.context.scene.panel_propert.panel3_g1 = False
|
|
register()
|
|
|
|
#del bpy.context.scene["panel_propert"] |