2.5 Operators in Scripted Expression Of Drivers?

Hi All,

I am just wondering is it possible to create a scripted driver for a value. Then, in the expression field, place a call to an operator that returns a valid value?

Would this be called every frame?

  1. Yes, this is possible, but…
  2. Operators do not return values when called.
  3. This would get called on every frame… in fact, it would also be called everytime a dependency is moved/changed…

It’s also quite a hackish idea, running operators from inside the animation system. Not recommended.

I can’t get it to work. For example, the simple operator that comes with 2.5. I am using 28719.

Care to post an example?

Operators, seem to return strings, but drivers want a float.

Why is this hackish?
Having no frame change event has put my script development at a standstill in 2.5.
Is there another way?

@Aligorith:

Yes, this is possible, but…

I can live with all the caveats, I just can’t get it to work. Can you post an example piece of code that I can paste into a driver with a scripted expression that calls the Simple Operator?

Thanks!

Disclaimer: this is a very ugly hack, but it works (tested on 28790).

Steps for the default scene:

  1. Create an empty
  2. Insert a single keyframe for the x-rotation of the empty
  3. In the graph editor make certain that the x-rotation for each frame is different (just key two values and use a cyclic modifier)
  4. Add a single driver to the y-rotation of the empty
  5. Set up the following scripted expression for the y-rotation driver:
float(exec("
".join([l.line for l in bpy.context.main.texts["Text"].lines]))==None)
  1. Create a text in Blender’s text editor (called: Text) that contains the code that needs to be run on a frame-change. For instance:
import bpy
ob = bpy.data.objects["Cube"]
scene = bpy.context.scene
ob.location[2] = scene.frame_current/scene.render.fps

If you want to be certain that the script is only run on a frame change, you can add a check in the script to see if the current frame is different from the previous time the script was run.
You can of course also alter the code at step 5, to directly call an operator.

Final disclaimer: I fully agree with broken. This is not recommended. However until we get python access to event notifiers, this is probably the only way to get working onFrameChange functionality.

Thanks, that works!

If you want to be certain that the script is only run on a frame change, you can add a check in the script to see if the current frame is different from the previous time the script was run.

In 2.49 I used the registry for just such purposes. Does that still exist in 2.5?

No, the registry doesn’t exist anymore. Easiest way would probably be to create an id-property at the empty. Something like:

ob = bpy.data.objects["Empty"]
ob["old_frame"] = bpy.context.scene.frame_current

hey Crouch, thanks for you hack but when i want script an operator and create a driver i must enter your expresion like a variable :

MyDriver.driver.expression = “float(exec(”
“.join([l.line for l in bpy.context.main.texts["MyScript"].lines]))==None)”

I’ve got a error : “unexecpected character after line continuation character” because i use "
" and python don’t like that lol

do you have a solution?

thanks

Hi volkukan, it looks like you should escape the quotes around the newline also (like you did with the quotes around MyScript, as well as escape the newline. this should work:

MyDriver.driver.expression = “float(exec("
".join([l.line for l in bpy.context.main.texts["MyScript"].lines]))==None)”

example script for blender-2.5 with script in ipo-driver

it moves a cube following an empty, if the distance to the empty is greater than some predefined value.

and does anyone know, where the limitation is to insert the lines of a script into this script-ipo-driver?

test-dr: Your example code is already out of date. The developers have renamed “current_frame” to “frame_current”.

and does anyone know, where the limitation is to insert the lines of a script into this script-ipo-driver

What are you really asking here?

aaahhh - yes (may be), i still use some older version 2.5alpha2… build …xxxx -
and the question is:

the scripted driver expression builds an internal-exec with the loop over the lines ot the script in the text-“buffer” - that is a duplication of this script and i wonder if the input has no memory restrictions like a script in such a text-buffer (only the normal program-memory limitations…).
There is still the lack for an exec of scripts in the drivers and other object attributs like constraints. But this “funny” way to insert a whole script via exec is such a thing and it makes my keyboard-input in the 3d-window deaf, i can press for example the i-key, but only this driver is executed and i cannot insert a ipo-entry as long as this driver is valid.
Maybe thats why there is still no “final” entry for using scripts in other parts (like in constraints and so on).

Apparently they’re looking for ‘a better way’ to do the pyconstraints, etc. but no one has come up with a design for the new system… or at least has written it down.

Not enough time in the day I think is what’s holding it up.

I’m not sure what the limit is, I suspect there is a limit. But I am running around 300 lines of code using this technique without any problems.

I am no python expert, but even if you run into a limit, couldn’t you just do a single line import and get an entire script that way as well?

In Blender 2.54 bpy.context.main does not seem to exist anymore. Is this true? Has it been moved?

Are there any available hacks or official methods to have a python script called when an object is transformed in the 3D view?

Any ideas would be much appreciated.

bpy.context still exists as far I can tell.

Did you remember to import bpy at the top of your script?

I can access bpy.context no problem, but if I am using the interactive mode and hit ctrl-space to bring up the autocomplete for all of the bpy.context modules I don’t see ‘main’ on the list. And if I type bpy.context.main into the prompt anyway I get an error that says bpy.context contains no attribute ‘main’

I’m using 2.54 on a PowerPC Mac Pro.

Hi,

I am not very familiar with the blender 2.5 api yet, but I managed to make a script I needed at last. Now I am trying to get the script to run upon every frame change. I am trying Crouch’s hack, but I can’t create a “Single driver” to the y-rotation of the empty. The nearest I can get is right clicking the coordinates of the control point of the Fcurve, and selecting “add single driver”. However this creates nothing and the console gives this error:
“Add driver: Could not add driver as RNA path is invalid for the given ID (ID= OBEmpty, path= co)”

Thanks in advance for any help!
Boy this was easier with a scriptlink. Let’s hope they will make something similar (or better) again.

my latest version gives:
Error in Driver: The following Python expression failed:
‘float(exec("
".join([l.line for l in bpy.context.main.texts[“FRAME”].lines]))==None)’
Traceback (most recent call last):
File “<bpy driver>”, line 1, in <module>
AttributeError: ‘Context’ object has no attribute ‘main’

But another question? HOW can I see edit the driver? Where is it to be found?

EDIT:
found one has to press the N-Key …