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.
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:
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.