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"]