4
$\begingroup$

I have this script - rather lengthy - that creates simple skin, eyes and mouth shaders for figures imported into Blender from Poser. I wish to create a panel/addon (something!) that does the following things:

  • set the path to the image files used in the shaders
  • define via dropdown the core figure type
  • pass this data on to the script, and save this info somewhere
  • have a button on the panel actually invoke running the script

I have looked at example scripts (the templates) but they all involve in-built operators that do things directly to mesh. Given this appears to be the predominant use of panel tools, I'm wondering if I should use a panel for this purpose or if another mechanism would be more appropriate.

Here is what I have so far... the panel code:

import bpy

class MatShaderInfoPanel(bpy.types.Panel):
    """Create shaders for your Poser figure: Panel"""
    bl_label = "Figure Files Info"
    bl_idname = "MATERIALS_PT_shaders"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Skin Shaders"

def draw(self, context):
    layout = self.layout

    obj = context.object

    row = layout.row()
    row.label(text='Figure Name')

    row = layout.row()
    row.label(text="Active object is: " + obj.name)
    row = layout.row()
    row.prop(obj, "name")

    row = layout.row()
    row.operator("mesh.primitive_cube_add", text='Find Images', icon='FILESEL')
    row = layout.row()
    row.operator("object.runScript", text = 'Apply Shaders')
def register():
    bpy.utils.register_class(MatShaderInfoPanel)

...and the custom operator (as kindly suggested by m.ardito in the link provided below):

import bpy

def main(context):
    filename = 'Shaders034.py'
    exec(compile(open(filename).read(), filename, 'exec'))

class runScript(bpy.types.Operator):
    """Tooltip"""
    # was bl_idname = "object.run_script" - is now:
    bl_idname = "object.runScript"
    bl_label = "Invokes a Script"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}

def register():
    bpy.utils.register_class(runScript)
def unregister():
    bpy.utils.unregister_class(runScript)
if __name__ == "__main__":
    register()

When I try to run the panel code, I get a slew of the following error messages:

rna_uiItemO: operator missing srna 'object.runScript' /home/robyn/Documents/Blender/Projects/AllScripts/Shader_blend/skinShader034.blend/MatShader_panel.py:28

...and this bit:

row = layout.row()
row.operator("object.runScript", text = 'Apply Shaders')

...doesn't end up displaying anything on the panel. I'm clearly missing a step.

$\endgroup$
  • 1
    $\begingroup$ probably related to blender.stackexchange.com/questions/18951/… $\endgroup$ – m.ardito Nov 4 '15 at 11:36
  • $\begingroup$ Looks like you're right, m.ardito (sorry I didn't find it first, myself). It addresses the last dot-point (the button) well. If I read it correctly, those are meant to be two scripts: one can't combine the classes? IOW, the SimpleOperator class needs to be registered separately? $\endgroup$ – RobinsSea Nov 4 '15 at 11:59
  • $\begingroup$ I never used python in blender :) but probably you need to call a your defined function that does everything you need, instead of an operator? $\endgroup$ – m.ardito Nov 4 '15 at 12:18
2
$\begingroup$

The following works for me:

import bpy

class MatShaderInfoPanel(bpy.types.Panel):
    """Create shaders for your Poser figure: Panel"""
    bl_label = "Figure Files Info"
    bl_idname = "MATERIALS_PT_shaders"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Skin Shaders"

    def draw(self, context):
        layout = self.layout

        obj = context.object

        row = layout.row()
        row.label(text='Figure Name')

        row = layout.row()
        row.label(text="Active object is: " + obj.name)
        row = layout.row()
        row.prop(obj, "name")

        row = layout.row()
        row.operator("mesh.primitive_cube_add", text='Find Images', icon='FILESEL')
        row = layout.row()
        row.operator("object.run_script", text = 'Apply Shaders')

class runScript(bpy.types.Operator):
    """Tooltip"""
    # was bl_idname = "object.run_script" - is now:
    bl_idname = "object.run_script"
    bl_label = "Invokes a Script"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        print('Yay!')

        return {'FINISHED'}

def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_class(__name__)

if __name__ == "__main__":
    register()
$\endgroup$
  • $\begingroup$ Works for me, too, Andrew. Thanks for answering all my questions with this!! $\endgroup$ – RobinsSea Nov 6 '15 at 8:41
1
$\begingroup$

The operator name used in the line that places the button in the panel needs to match up with the operator name specified in the operators bl_idname (not the class name).

row.operator("object.runScript", text = 'Apply Shaders')

and in your operator you have

bl_idname = "object.run_script"

object.runScript doesn't match object.run_script

$\endgroup$
  • $\begingroup$ Thank you, Sambler - fixed that. Still generating the same error, though. Wondering if I'm meant to be creating or setting some Operator Property or something... dunno. I've been trying to sort out the addon help file in the API. Has me baffled. $\endgroup$ – RobinsSea Nov 5 '15 at 19:13
  • $\begingroup$ Double-checked that the scripts are all with the .blend (I'd had a few issues with path stuff) and even saved all scripts out to .py files. Still getting that not found error: home/robyn/Documents/Blender/Projects/AllScripts/Shader_Blend/skinShader034.blend/MatShader_panel.py:28 search for unknown operator 'OBJECT_OT_runScript', 'object.runScript' rna_uiItemO: operator missing srna 'object.runScript' ... totally confused. I've fixed the code in the original post to reflect what's current. $\endgroup$ – RobinsSea Nov 5 '15 at 23:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.