Running a function inside a class from a python controller?

Is it possible to run a function from a class by using a python controller module?

And if you found that confusing here is an example:


class Example:
    def exampleFunction():
        need to run this from the controller

I tried to and it seems like it only runs once, I assume that’s to init it.

Thanks
Ex.

Yes it is. But not so simple one could think of it:



class GameObj(bge.types.KX_GameObject):
    """ registers and Indentify Objects """
    def __init__(self, this):
        """ initialises Object """
        
        # give Object a reference of its own
        bge.types.KX_GameObject.__init__(self)
        self['this'] = self
        
        # goto state 2
        self.state = 2
        
    def main(self,cont):
        """ the main function"""
        print ("GameObj.main(self,  cont)")
        
        
    
def register(cont):
    """ registers the Obj, instances it, attach controller on state 1"""
    own = cont.owner
    obj = GameObj(own)
    
def main(cont)
    """ calls the main function of GameObj instance, attach controller on state 2"""
    own = cont.owner
    own.main(cont)


This is one way to do it, there might be better solutions:eyebrowlift:

Using a script for this wouldn’t be that complex -


from bge import logic

cont = logic.getCurrentController()
obj = cont.owner

# Assuming the 'Example' class is in an external module of the same name,

from Example import *

if not 'init' in obj:
     obj['example'] = Example()

obj['example'].exampleFunction()

That should work.

EDIT: Of course, that’s a simple script, but if you want to run it squarely from the controller… Hmm…

According to the Blender Wiki, about Module mode…

"… Then you define a function on that module and call that function from the controller. Instead of writing “myScript.py” on the script edit box, you’ll write “myModule.myFunc” on the module edit box. This function will run every time the controller is called. But other functions and variables outside of myFunc’s scope will only run once. This is good for optimizing your code when you want to initiate variables only once then use them later.

The Python module controller supports any number of attributes, this means packages are supported automatically. As well as “myModule.myFunc” you can do “myPackage.myModule.myFunc”, nested packages work too, as does method calls on class instances like: “myPackage.myModule.myInstance.myMethod”. The python controller is passed to the python function as an argument for functions that take one arg."

So, if you define the function or variable inside of what the controller runs, it should run every frame. Also, apparently, class functions should run every frame, as well… Are you sure it’s not working correctly?

You could also assign a method object to a variable in the module. If runme() is the function and obj is the object do:

runthis = obj.runme

Note no () after runme, that saves a reference to the method with object and all in runthis, so You can just call it with ‘module.runthis’.

As modules are global You can from any other python module change the function with:

module.runthis = newobj.newrunme

Nether the object nor the function need be the same - and they can be from a different module! Bu You have to import the module to be able to access the variable in it from the outside.

Thanks for all the replies. Your solutions will mostly work, however I still would want it to work inside the controller. I changed the way my code runs so this isn’t a problem for me anymore, but I would still like to know why it doesn’t work.

Here is a blend with the problem: http://www.pasteall.org/blend/6651

Thanks
Ex.

Yes, it appear like all before the last . have to be module name. If I add:

test2 = test.test2

Last in Text.py (without indenting it) and change pyton1 controller to call Text.test2 it works.

But You use it a bit strange. You can call functions on a class but usually You create a instance (a object) and call functions on that.

Your first controller calls the class constructor creating a object and then throwing it away - is that intended?