Python controller (Module) : how to give arguments?

Hi,

I was checking the new version of Yo Frankie and enjoying the improvements.
I have a few questions.

1. Properties
Are all the properties in the left side of the Logic panel (F4) still needed?
Isn’t it possible to just initialize properties using a script :


own['grounded']=0
own['predator']=True
...

I would like to know if this allows other features (except ‘Print Debug Info’ button) or if we can already clean our .blend and delete all those properties.

2. External scripts
I am trying to use external scripts but I get this error :

ImportError: No module named scripts
  • In my main folder, I have a folder called ‘scripts’.
  • In this ‘scripts’ folder, I have a script called display.py

This is the content of display.py


import GameLogic as g
cont = g.getCurrentController()
own = cont.owner

own["var1"] = 2
own["var2"] = 1

def main(cont):
    print own["var1"]
    print own["var2"]

  • An always sensor is set to no Pulse mode
  • A Python controller is calling a module :
scripts.display.main

What am I doing wrong?

For the second question, I’m going to guess that “scripts” is not a Python “package.” To do this simply put an init.py file in the folder. This script can be empty.

Moguri
that helped, but I also needed to add the line

import display

in the init.py file.
display.pyc was then created (I was wondering what those files were, in the yo frankie scripts folder).
Without it, I had the error

AttributeError:'module' object has no attribute 'display'

Thank you!

Does anybody know the answer to my first question?

If you use “import” in your init.py, then it will import things into the package. For example if there was a setRGB() function in the scripts.display, and you imported display in init.py, then you only use scripts.setRGB().

You should be able to initialize properties in the script with no problems- but only if every object that uses that script can have the same property initialized with the same value.

What I started doing was to set defaults for properties used- if the object doesn’t have a property, the script initializes it with the default value, so I can still add the property on any object that I want to change the initial value.

Moguri
I see. So, how can I solve that error :

AttributeError:‘module’ object has no attribute ‘display’
If I use an empty init.py as you suggested?
What am I doing wrong?

Captain Oblivion
That’s a clever use. So, if I understand well :

  • For a unique object (player) I can have a “player_init.py” that initializes properties, and no need to add properties in the F4 panel anymore
  • For multiple objects sharing the same properties, I can have a “enemies_init.py” that initializes default properties values for all objects (health, attack_power, speed, recovering_speed, range, etc…), and then ‘Add properties’ only for the objects and only the properties that need a different value (ex: A big boss at the end of a level is more powerful, faster, and has a different health value than others).

We should have it written somewhere in the resources section :slight_smile:
Thank you again for taking the time.

You understand well.
I could yank that bit outta my particle system (the only blend I’ve used it in so far) and put it in the resources, I have an easy-to-use function ready to go. I’m just not sure it merits a thread of it’s own, so I might poke around to see if there’s anything else to bundle in.

@cray, YoFrankie could have had all props initialized by a script, however I think its a bit cryptic for other people who look at the files? (ok it was a bit cryptic anyway, but still)

With using packages this is not different to python packages (without blender)

Be sure your using 2.49a and do…

foo.blend -> (In foo.blend have a script that does “import display”)
display/init.py -> (does not need to contain anything but can import modules its self or define vars. say “import bgetest”)
display/bgetest.py -> (a module imported by init)

So you can do…


import display
print display.bgetest

The only thing thats new in 2.49a is that the current blend file dirs are included in sys.path for module searches, so its not really that big a change, python does the rest.

Hi,

Captain Oblivion
Anything you could provide would be useful.

ideasman42

however I think its a bit cryptic for other people who look at the files? (ok it was a bit cryptic anyway, but still)
I think that it is a good idea to have those properties displayed and I felt that it was a good choice, especially that all the scripts are really well commented (thank you again for the great work).
But I think it is also important to tell to the blenderArtists that they don’t need it if it is not necessary. I had assumed that I would get errors if I had forgotten to create some of it. But I was wrong, I can clean up my .blend and that’s a good news!

About modules I get the idea, thank you for those explanations.


Questions

  1. I am still trying to understand :

If you use “import” in your init.py, then it will import things into the package. For example if there was a setRGB() function in the scripts.display, and you imported display in init.py, then you only use scripts.setRGB().
by writing import display it doesn’t work for me.
In that case I would need to use from display import setRGB otherwise I would get the error ‘module object has no attribute setRGB’
Is it what you meant?

  1. I still can’t make it work with an empty init.py
    Please see the example below, and delete the content of init.py

I have made a working example using external module call through Python text editor, and through Python controller.
Maybe some Blender artists will find it useful.

//////////////////////////////////////////////////////////////////////////////
FILE UPLOAD : Module_test (tar.gz, Mediafire, 36ko)
//////////////////////////////////////////////////////////////////////////////


Note

I can use display.bgetest in the Text Editor and it works fine.
But if I use display.bgetest with the Python controller (Module), it starts fine (displaying my print “# Default values initialization”) but after that it raises an error :

Python module function error “Direct_Call#CONTR#2”:
“display.bgetest” not callable"

But it was called, because my print was displayed ("# …initialization")

I thought that both methods would be the same.
An idea?

did you use display.setRGB() or just setRGB? when you use from import you don’t have to have module.function but when you import the whole module, you do.

Sorry for the short reply, I spent some time looking at your example but cant figure out what the problem is.

When all controllers are enabled it works without error.

But to answer some questions.
-python will see an empty init.py as an empty module, this isnt related to blender, youll just have to import modules from there, this is just how python works.

  • " from display import setRGB" will only work if init.py has setRGB defined or imported. Basically at the bottom of init,py you should be able to do “print setRGB” not “print someModule.setRGB

First question:
You can initialize properties with an init script, I’m not so sure BUT,
own[‘grounded’]=0 means that property ‘grounded’ can be anything(string, float, int,timer etc.)
If you use properties in the logic panel you can predefine the property type (float,string…etc) this is used for memory optimization by blender… so if you can predefined properties type with Python it will be usefull to have init script.

Second question:
Look how pygame modules are imported and use the same method.
OR just add your script.py file to the python26.zip and it will be accessible with just: ‘import script’

PS. I was wrong about variables declaration!
Unlike other languages “Python has no explicit variable declarations. Variables spring into existence by being assigned a value, and they are automatically destroyed when they go out of scope.”
So this means, that init script is just fine for assigning variables.

I will learn a lot from those informations.
I will take time to read again and study Python documentation more.

Time to practice, now.
Thank you all for your help.

I have a last question :

I know that the equivalent of myfunction() is myfolder.myfile.myfunction in the Python controller (Module)

What is the equivalent of myfunction(cont,distance) if I want to use the same Python controller (Module)?

Using myfolder.myfile.myfunction, I get the error :

myfunction takes exactly 2 arguments (0 given)