FrameChanged Script Link

I’ve had partial success in getting the frameChanged script-link mechanism to work. If I create a blank new Blender project and make a simple script saying print ‘hello’, link it to the global world frameChanged script link and press ‘anim’ it all works - I get ‘hello’…in the console. But if I do the same with a Blender project I’m working on that has a number of other scripts (which work) in it, then it does not work. Then, if I reopen my previous simple blank project and press ‘anim’, it doesn’t work any more. If I then restart Blender then the simple blank project with the little ‘hello’ script works again.
Something about my project appears to disable Blender’s frameChanged mechanism. Anyone seen this one ?

I never had that problem personnally. Do you think you could upload the .blend file somewhere so we could have a look?

Martin

Sure. I’ve posted two blender files at:
http://www.thesethings.clara.net/resource/basil.blend
http://www.thesethings.clara.net/resource/parsley.blend

They are both very similar and simple blender files, each having a few scripts, one of which if called ‘frameChanged’ which is linked to the frameChanged event in the script links global world setting.
If I first open ‘basil’ and press ‘anim’ then I get what I expect, the script is run on frameChanged. Then I edit the frameChanged script in any way and run it again by pressing ‘anim’. Now it doesn’t work. So now I open the other file ‘parsley’ and press ‘anim’ - it doesn’t work. then I restart blender (close it and open it again) and open ‘parsley’ and it runs fine.
I think it has something to do with importing something in a script-link-script because the ‘basil’ script has an import statement first whereas ‘parsley’ doesn’t.

I think it’s because first of all, the frameChanged script in basil.blend cannot even by runed by it self. First, it uses a method from a class defined in quice, and nowhere does it import quice. Second, quice (should be quice.py if you want to import it) in itself cannot run since there’s two syntaxt errors: a class takes no parenthesis if there is no inheritance, methods of a class needs at least an argument, the object it self (usually called “self” in the argument list in parenthesis). Structurally speaking, Python doesn’t necesarely need it, but it will pass the argument to the method nonetheless. Also, you cannot use the method of a class directly. First, you have to create an instance of that class, and than call the method through that instance.

anyway, after those small errors are cleared, any changes you apply to the frameChanged script is automaticly applied the next time it is runned.

hope that helps.

Martin

Right, I understand to some extent. In basil.blend I was experimenting with the idea that I might be able to maintain state between frameChanged invokations (my basic problem) if I created a singleton (the class in quince). I was trying to guess Pyhton’s syntax for class-members because I thought that if that class could hold a class-member reference to an instance of itself then I could reliably refer to that instance in later invokations and have the same object instance.
But that’s another problem.
Now I’ve tried what your advicec (thanks), removed my test class from quince and now I’m trying simply to have frameChanged import quince or lemon at all. I renamed quice and lemon to quince.py and lemon.py and added import quice.py and import lemon.py to frameChanged and restarted blender. Quince.py and lemon.py now do nothing at all but simply print ‘hello from quince’ and ‘hello from lemon’. But frameChanged will not run if it imports either quice.py or lemon.py.
So the problem appears to be importing other scripts into a script that runs on the frameChanged event - that can’t be done.
Therefore, I have two important questions:

  1. how does one use classes of another script in a frameChanged script
  2. how does one maintain the state of an object across changeChanged script invokations in order that one can refer to the same object instance from frame to frame ?
    Thanks for your help sir.

actually, yes, that can be done, as I’ve done it a lot of time with success, and not particular trick or anything.

  1. like usual, you import the module with either:

import name

or


from name import object1,object2,object3

or


from name import *

when using from, the objects are imported directly in the namespace of the script, so you can access them directly by calling their name.
when using import, you have to access them through the module object.


module.function()
print module.variable

  1. depends on which version of Blender you use.
    2.23 and lower: the global namespace is not resetted between different runs, so every global variable will be kept unchanged
    higher than 2.23 (BF-Blender, Tuhopuu, all the new compilation): the global namespace is resetted between runs, so global variables are lost. HOWEVER, the Blender module is NOT resetted after every run, so the trick is to embed the variables you want to keep in the Blender module

import Blender
var1 = 2
var2 = 3
var3 = 6
Blender.gvar = []
Blender.gvar.extend([var1,var2,var3])

and then if you run this, it will work as expected


import Blender
var1 = Blender.gvar[0]
var2 = Blender.gvar[1]
var3 = Blender.gvar[2]
print var1,var2,var3

hope that was helpful.
Martin

gold-dust. Excellent advice. The import problems are totally solved now I understand python namespaces. I can refer to objects in other scripts - great!
I have not had success with (2) though. Is ‘Blender.gvar’ a special name ? What is happening here - will the Blender module just let you add members to it ad hoc ?
It looks as though I can called it Blender.mySpecialMemberName – either way I can’t seem to get Blender to remember anything using your example code or otherwise…but then I probably have it wrong…

Right, now (2) is solved too. Thankyou very much, this is everything I need. You can just add members to the Blender module having any name you like. But you cannot check their values before you’ve assigned them:

if (Blender.jam == None):
Blender.jam = “raspberry”

will fail unless Blender.jam was previously assigned a value other than None. So the trick is to include an initialization script to establish such members so they can be referred to later.

Also scripts run on the frameChanged event will not report errors, they just quietly fail.

Great! Thankyou sir!

or you can test if the variable exist like this:


try:
        Blender.jam
except NameError:
        Blender.jam = "raspberry"

Martin