Saturday, February 16, 2019

Learning Blender Addon two buttons and a textfield

Hi,

I thought this post might be helpful for learning how to begin writing blender addons.
This is a simple hello world type addon with two buttons and a text field.
it moves object in object mode.
hope you find it helpful.

This is a little bit on installing addon:
#save file as .py file to disk
#file > user preferences > Add on tab > install from file > pick and choose file
#in new blender > Add on tab > click category User > enable add on
#after running in script editor to run operator 'spacebar' and type the bl_label
#if its a panel find it where its saved ex in bottom of properties

Tip for starting addon:
Start here: https://docs.blender.org/api/blender_python_api_2_65_5/info_tutorial_addon.html

In writing the addon below i first started with a single operator, then an operator with a panel, then an operator with a text field, then finally two operators and a text field.

I'm still learning the ideas in blender ui's but there is certainly inheritance going on.  ex Inheriting from Operator or Panel.  For buttons there is doing stuff in its 'execute' function.  For panel doing stuff in its 'draw' function.  There is registering and unregistering of all buttons and textfields we make.  I think textfield thought of as stringProperty.

Happy Sketching!
Nate

bl_info = {
    "name": "Simple Button to Move Chosen Object(s) Y",
    "category": "Object"
}

import bpy

from bpy.props import(
    StringProperty,
    PointerProperty
    )

from bpy.types import(
    Operator,
    Panel,
    PropertyGroup
    )

class LoadSelectedOperator(Operator):
    bl_idname = "obj.load_sel" #this is how panel finds this button
    bl_label = "Load Selected"
    bl_options = {"REGISTER","UNDO"}
    
    def execute(self,context):
        myPrp = context.scene.my_prop
        selected = [x.name for x in context.selected_objects ]
        myPrp.name = ' '.join(selected)
        
        return {'FINISHED'} #this is required

class ButtonOperator(Operator):
    bl_idname = "obj.button"
    bl_label = "Move Object"
    bl_options = {"REGISTER","UNDO"}

    def execute(self, context):
        
        #get name from text field
        myPrp  = context.scene.my_prop
        arg = myPrp.name
        #could have multiple name space separated
        names = arg.split() 
        for name in names:
            #only move scene names
            if name in context.scene.objects:
                obj = bpy.data.objects[name]
                #move it
                obj.location.y += 1.0
            else:
                msg = "Please enter name of object in scene to move skipping %s" %name
                #print to info console
                self.report({'INFO'}, msg )
        
        return {'FINISHED'}

class ButtonPanel(Panel):
    bl_label = "Move Object Panel"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"

    def draw(self, context):
        myPrp = context.scene.my_prop
        
        layout = self.layout
        layout.label(text="Move Object Label")
        layout.operator("obj.load_sel")
        layout.prop( myPrp, "name", text = "Enter Name(s) space separated" )
        layout.operator("obj.button")

class ButtonProperties(PropertyGroup):
    
    name = StringProperty(
        name = "Name",
        description = "object name want to move"
        )


def register():
    bpy.utils.register_class(LoadSelectedOperator)
    bpy.utils.register_class(ButtonOperator)
    bpy.utils.register_class(ButtonPanel)
    bpy.utils.register_class(ButtonProperties)
    bpy.types.Scene.my_prop = PointerProperty(
        type = ButtonProperties
        )
    
def unregister():
    bpy.utils.unregister_class(LoadSelectedOperator)
    bpy.utils.unregister_class(ButtonOperator)
    bpy.utils.unregister_class(ButtonPanel)
    bpy.utils.unregsiter_class(ButtonProperties)
    del bpy.types.Scene.my_prop
    
    
if __name__ == "__main__":
    register()


Inspired by:
https://github.com/sobotka/blender-addons/blob/master/mesh_auto_mirror.py
https://blender.stackexchange.com/questions/110572/prop-search-with-a-custom-propertygroup
https://blender.stackexchange.com/questions/717/is-it-possible-to-print-to-the-report-window-in-the-info-view