Driver controlled in Panel

I am attempting to control an object using a driver, which works fine,
but then I try to control the speed of the motion in a Panel . . . .
it fails every time, so I am either doing something wrong or missing something.


import bpy
from bpy.types import Panel, Menu

cube = bpy.ops.mesh.primitive_cube_add(radius=1, view_align=False, enter_editmode=False, location=(0, 0, 1))
bpy.context.object.name = "cube"
driv = bpy.context.object.driver_add('rotation_euler', 1)
driv.driver.type = 'SCRIPTED'
# Create a property, to control the speed using a custom property
bpy.context.object["speed"] = 1.0
speed = bpy.data.objects['cube'].values()[0]
driv.driver.expression = "frame * " +str(speed)+ " * .05"

OK, Now I want to add this to a panel, so I can change the speed.


class IA_Panel(bpy.types.Panel): 
    bl_label = "Controls" 
    bl_space_type = 'VIEW_3D' 
    bl_region_type = 'UI'
    @classmethod
    def poll(cls, context):
        return (bpy.context.object is not None)
    def draw(self, context): 
        layout = self.layout 
        ob = bpy.context.object
        row = layout.row()
        try:
            ob["speed"]
            layout.prop(ob, '["speed"]')
            setSpeed(ob["speed"])
        except:
            pass
            

def register(): 
    bpy.utils.register_class(IA_Panel)

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

if __name__ == "__main__": 
    register()

def setSpeed(speed):
    driv.driver.expression = "frame * " +str(speed)+ " * .05"

All of this code works in the command line, if I run the setSpeed() function in the command line,
it updates and the object speeds up.

This problem is partially solved. I have the speed updating, via a button.
Ideally though, I would like it to work without a button, when I hit the
Enter Key. Is that possible? Seems like a slider would do that. The
difficult part is done I think though.

In case you have any trouble viewing the panel, you have to first run the
script, then put your cursor in the 3D view and press the ā€œnā€ button.

This is the almost completely solved code:


# Make sure Autorun scripting is enabled in Preferences under "File"!
import bpy
from bpy.types import Panel, Menu

cube = bpy.ops.mesh.primitive_cube_add(radius=1, view_align=False, enter_editmode=False, location=(0, 0, 1))
bpy.context.object.name = "cube"
driv = bpy.context.object.driver_add('rotation_euler', 1)
driv.driver.type = 'SCRIPTED'
# Create a property, to control the speed using a custom property
bpy.context.object["speed"] = 1.0
speed = bpy.data.objects['cube'].values()[0]
driv.driver.expression = "frame * " +str(speed)+ " * .05"

# OK, Now I want to add this to a panel, so I can change the speed.
class IA_Panel_Speed(bpy.types.Panel): 
    bl_label = "Controls" 
    bl_space_type = 'VIEW_3D' 
    bl_region_type = 'UI'
    bl_context = "object"
    @classmethod
    def poll(cls, context):
        return (bpy.context.object is not None)
    def draw(self, context): 
        layout = self.layout 
        ob = bpy.context.object
        row = layout.row()
        try:
            ob["speed"]
            layout.prop(ob, '["speed"]')
            layout.operator(SimpleOperator.bl_idname) 
        except:
            pass


class SimpleOperator(bpy.types.Operator):
    bl_idname = "speed.run"
    bl_label = "Enter"
    dr = bpy.context.object.driver_add('rotation_euler', 1)
    dr.driver.type = 'SCRIPTED'
    dr.driver.expression = "frame * " +str(speed)+ " * .05"
    
    def execute(self, context):
        self.__class__.dr.driver.expression = "frame * " +str(bpy.context.object['speed'])+ " * .05"
        self.report({'INFO'}, str(self.__class__.dr))
        return {"FINISHED"}


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


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


if __name__ == "__main__":
    register()

I think I almost died of old age solving this one! :eek:

Here is a simple example of how to do this:


import bpy


def changeSpeed(self, context):
    obj = context.object
    obj.location.z = obj.speed


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_context = "object"


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


        obj = context.object
        row = layout.row()
        row.prop(obj, "speed")       




def register():
    bpy.utils.register_class(HelloWorldPanel)
    bpy.types.Object.speed = bpy.props.FloatProperty(name='Speed', update=changeSpeed)




def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)
    del bpy.types.Object.speed


if __name__ == "__main__":
    register()

Here, I use the speed to change the z location of the object. The update in the float property runs every time the float property is changed. It should be self-explanatory, but feel free to ask any questions.

Thanks a lot! This looks like it will get me over that hurdle, and it might even help
me simplify my spaghetti code some! :smiley: