How to create panel for setting operator properties?

I’m creating a tool that is an operator that runs modaly. I’d like the user to be able to change attributes of my tool while it’s running, so I’d like to be able to create a Panel that shows properties of my tool and lets users set them. (My tool runs in the View3D in edit mode).

So far I’ve created one Panel that sits in the tools window and has a button that launches my tool:

class NormalToolPanel(bpy.types.Panel):

    """Panel for the Normal Tool on tool shelf"""
    bl_label = "Normal Tool Panel"
    bl_idname = "3D_VIEW_PT_normal_tool"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_context = "edit"

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

        obj = context.object

        row = layout.row()
        row.operator("kitfox.normal_tool")

This is fine for just getting my operator to run, but I’d also like to be able to display and set things (like a ‘strength’ property that varies from 0 to 1). Also, since 2.8 the TOOLS window seems to be only intended for storing an icon for starting your operator. I’ve tried creating a second panel and setting its bl_region_type = 'TOOL_PROPS', but I have no idea where this shows up in the UI (if it is showing up).

Where should I place my panel that lists my tool’s properties? Also, how would I have my panel adjust my operator’s properties, since my operator is a completely separate object?

1 Like

I recently spent over half a day trying to find a good example of how to build a panel with a custom property that used a slider. Eventually I found this:

import bpy

class SomePanel( bpy.types.Panel ):
    bl_label = "Property panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"

    def draw(self, context):
        layout = self.layout
        scn = context.scene
        layout.prop( scn, 'someValue' )

#Update function example:
#self is the object to which you have assigned the property
#context is similar to the context given in the execute function of an operator
def do_update( self, context ):
    if context.active_object:
        context.active_object.location.x = self.someValue
    print( 'update', self.someValue )

def register():
    bpy.types.Scene.someValue = bpy.props.FloatProperty(name = "Float", 
        description = "Enter a float", min = -100, max = 100, update=do_update )
    bpy.utils.register_class(SomePanel)

def unregister():
    bpy.utils.unregister_class(SomePanel)
    del bpy.types.Scene.someValue

if __name__ == "__main__":
    register()

It seems the biggest thing to remember is the custom property is put in the register function. From this, one should be able to hack out whatever they need for their control panel.

1 Like

Ohw, I guess that is also the answer on my question on How to create an operator for the mapping node (scale) where I try to find a solution on how to add a slider in the Panel to adjust the scaling of a Mapping node. I’ve spend a whole day on figuring that out, and have seen all kinds of things like handlers, persistence, FloatingProperty, etc come across. It’s probably not that difficult, but its so easy to get overwhelmed trying to grab info all over the internet.

1 Like

As far as I can tell, you can get normal properties to update immediately when you set the slider, but I don’t think the same thing is possible with a custom property . . . . last thing I built like that I had to put an OK button at the bottom for the user to click to make it update the 3D View.