Game Development Community

TGEA 1.7 Python Support

by Prairie Games · in Torque Game Engine Advanced · 03/29/2008 (11:28 am) · 75 replies

Hey all, been doing some R&D on a new project and wanted to try out the (awesome) new build system
included with TGEA 1.7

I also wanted to have a look at some embedded scripting... and so dusted off PyTorque, got it ported over to 1.7, changed it around to be an embedded system, and hooked it up with the new build system.

www.prairiegames.com/gg/tgea_python.jpg
There are only very minor changes necessary to the core engine to support Python scripting. It is pretty powerful stuff... the docs are a bit sparse, but if you head over to MMOWorkshop.com you can browse through a lot of examples...

BTW, this is a newer system than what was used for Minions of Mirth. It is actually quite a bit cleaner... so, when in doubt check out the included example.py :)

You can snag PyTorque for TGEA 1.7 HERE

This was a pretty quick package job... so, post here with any glaring issues.

-Prairie Games, Inc
#21
04/15/2008 (5:40 am)
Are you getting an exception when you run it? If you add a try/except block around your additions, does it run?
#22
04/16/2008 (6:37 pm)
Yes, it throws an exception. When I catch it the game doesn't crash. When I echo the exception, it resolves to the following string:

pytorque.export() - non-string namespace

I am playing around with trying to get more info out of it, if there is any more to get.
#23
04/16/2008 (6:58 pm)
Try:

pytorque.export(PyHelloWorld, "", "PyHelloWorld", "Just has python echo to the console.", 1, 1)
#24
04/16/2008 (7:10 pm)
It no longer throws an exception. But it doesn't seem to export either. If I type PyHelloWorld() in the console, it says:

(0): Unable to find function PyHelloWorld
#25
04/16/2008 (8:18 pm)
Try:

pytorque.export(PyHelloWorld, "PyHelloWorld", "Just has python echo to the console.", 1, 1)

That should export to global namespace.

Also, try:

pytorque.export(PyHelloWorld, "PyHelloWorld", "Just has python echo to the console.", 0, 0)

If you get complaints about incorrect number of args...
#26
04/16/2008 (8:40 pm)
That worked!
Thank you so much for your help.

-- Mike
#27
04/17/2008 (5:59 am)
Great, should probably allow the None, "" forms as well... when in doubt, check the C++ sources for the console bindings... there's only 16k of source there so it shouldn't be too bad ;)
#28
05/14/2008 (12:04 pm)
Argument Passing

Unaware if someone posted the fix yet for pytorque exports, here is the fixed code.

pytorque.cpp line 279

Old Code
if (argc > 1)
      args = PyTuple_New(argc-1);

   for (int i=1;i<argc;i++)

New Code
if (argc > 1)
      args = PyTuple_New(argc);
   
   // argument fix
   for (int i=1;i<=argc;i++)

As you can see PyTuple_New became PyTuple_New(argc)


and in the iteration loop your condition changed to i<=argc

Seems to work with 0 arguments, and other numbers as well, YMMV though.
#29
05/14/2008 (12:16 pm)
Thanks, I think there may have been console side changes that affected this from TGE 1.5/TGEA 1.0.3 -> 1.7
#30
06/07/2008 (9:38 am)
Guys,

I'm desperate to get this Python suport runnin; but am hitting this problem at the linking stage on a VS 2008 express compile:

sfxDSDevice.obj : error LNK2019: unresolved external symbol "public: static class SFXDSVoice * __cdecl SFXDSVoice::create(class SFXDSBuffer *)" (?create@SFXDSVoice@@SAPAV1@PAVSFXDSBuffer@@@Z) referenced in function "public: virtual class SFXVoice * __thiscall SFXDSDevice::createVoice(class SFXBuffer *)" (?createVoice@SFXDSDevice@@UAEPAVSFXVoice@@PAVSFXBuffer@@@Z)
sfxNullDevice.obj : error LNK2019: unresolved external symbol "protected: __thiscall SFXNullVoice::SFXNullVoice(void)" (??0SFXNullVoice@@IAE@XZ) referenced in function "public: virtual class SFXVoice * __thiscall SFXNullDevice::createVoice(class SFXBuffer *)" (?createVoice@SFXNullDevice@@UAEPAVSFXVoice@@PAVSFXBuffer@@@Z)
sfxALDevice.obj : error LNK2019: unresolved external symbol "public: static class SFXALVoice * __cdecl SFXALVoice::create(class SFXALBuffer *)" (?create@SFXALVoice@@SAPAV1@PAVSFXALBuffer@@@Z) referenced in function "public: virtual class SFXVoice * __thiscall SFXALDevice::createVoice(class SFXBuffer *)" (?createVoice@SFXALDevice@@UAEPAVSFXVoice@@PAVSFXBuffer@@@Z)
../../../game/PyTorque.exe : fatal error LNK1120: 3 unresolved externals


I went and rebuild the engine with another project and that worked perfectly, also using the T3D project files from the pyTorque project worked; I'm so nearly there but being beaten at the last hurdle.

Can someone shed some light !?!?!?!
#31
06/07/2008 (4:48 pm)
I personally haven't tried this in TGEA but in TGE with the Python bindings from Prairie Games (dunno if this is even the same style of bindings) we don't compile the engine as an executable; instead it's compiled as a Multi-Threaded DLL and then loaded by a Python script which you can then compile with any of PyInstaller, Py2Exe, Py2App and so forth.

So, in order to make things work as-far-as-I-can-tell, you need to go through every project in your VS solution, change them to Multi-Threaded DLLs and also change the name of the file created from being a .exe to a .pyd. After a clean build you should be able to run the following script...


# assuming your compiled DLL is named "pytorque.pyd" and
# exists in the same directory as this script...

import pytorque
import sys

def main():
    pytorque.initialize()
    while pytorque.tick():
        pass
    pytorque.shutdown()
    sys.exit()

if __name__ == "__main__":
    main()

Not sure if all this is how things work in the TGEA bindings, but at least this is how things work with the old TGE ones.

If this helps:
    cheers()
else:
    sorry()

Edit: fixed some typos after actually reading the example script heh
#32
06/07/2008 (4:59 pm)
Thanks for the response; however with the TGEA 1.7 python support they are embedding the interpreter into C rather than extending python with a dll.

So i'm still stuck with build troubles
#33
06/07/2008 (5:00 pm)
In this particular version it is embedded into TGEA as an executable and thus doesn't require it to be multi-threaded DLL. I'm not sure what the issue that Alitair is having though, I haven't tried compiling with VS2008 though.
#34
06/07/2008 (5:39 pm)
--phew just sorted it, I can't work out what went wrong; but the solution was to generate a new T3D project using the generateprojects.bat file , then add the python include directories etc by hand.

I havn't tested any python stuff yet, but the executable seems to work
#35
06/20/2008 (8:16 am)
Just realized I was an idiot and forgot to fix one more case of arguments, look at line 273 and make sure you correct the conditional to create your tuples. It should be >= 1, NOT > 1. If you ever pass a single argument it will crash due to an access violation.


Correct code pytorque.cpp line 273
// number of arguments fix
   if (argc >= 1)
      args = PyTuple_New(argc);

BAD CODE
// number of arguments fix
   if (argc > 1)
      args = PyTuple_New(argc);
#36
06/28/2008 (10:14 am)
Thx for your work, i love TGEA 1.7 + PYTHON :D

Some info:
*Any python error un main.py cause engine crash with "out of bins" error on console.log. I put my test code in run.py
*Python can't access dyn fields. SOLVED.
*For create dyn fileds, use TorqueObject.setFieldValue(fieldname,value)
*Python can't access methods in object name namescape. SOLVED
*All vars recieved from a exported function are strings. It's necesary to check and convert types.
*Callbacks methods exported recieve console object ID as string. Added TorqueObject(ID as string) for facilitate creation.
*Memory leak and a error in PyTorqueObject_call that cause string used in argv are deleted before they are used. SOLVED
*Change pytorque.export(callback,[namespace],functionname,usagedoc,minargs,maxargs) for add funtionality of override console method. You can define important engine callback as onAdd, onRemove, onCollide... etc.
*Exported callbacks check methods in all class inheritance
*main.py example for test all features. WORKING ON THIS
*Port to 1.7.1 WORKING ON THIS

Updated version of pytoque.cpp

main.py
#--- Torque Python Module Example ---
#Any error in this file cause a engine crash with a "out of bins" mensage in console.log

#Torque as a standard Python extension (no longer a executable)
import pytorque
import sys

class ConsoleLog:
	def __init__(self):
		self.file = open('pytest.log','w')
	def write(self, stuff):	
		self.file.write(stuff)
		if stuff != "\n": #print(string) double call write, 1 for "string" and 2 for "\n"			
			pytorque.evaluate('echo("%s");'%stuff)		
						

sys.stdout = ConsoleLog()
sys.stderr = ConsoleLog()

#initialize pytorque, this also executes main.cs and the .cs packages
pytorque.initialize()

pytorque.evaluate('echo("%s");'%pytorque.__doc__)

try:
	import run
except:
	pytorque.evaluate('echo("RUN ERROR: %s");'%sys.exc_info()[1])


#the main loop is broken out and can be combined with other frameworks rather easily
while pytorque.tick():
    pass

#cleanup pytorque.. goodbye!
pytorque.shutdown()

SORRY FOR MY BAD ENGLISH T_T
#37
06/28/2008 (5:43 pm)
Nice list of fixes here.
#38
06/29/2008 (2:15 am)
*Add get/set dynamics fields but can't create in python

Updated version of pytoque.cpp

def py_OnButton(v1,v2,v3):
	value = v1+v2+v3
	pytorque.evaluate('echo("button click: %s");'%value)

pytorque.export(py_OnButton,"ts_OnButton","Example button command2",3,3)

pytorque.evaluate('ts_OnButton(3,4,5);') #345 on console.log O_O
py_OnButton(3,4,5) #12 on console.log
#39
06/29/2008 (2:39 am)
Another nice addition. Though with the way you have things pasted in there, I can't get the latest changes to work. Would probalby be easier if you copied the entire function in there (getattr/setattr) as it may be missing some code or something that was previously changed. I can't get it to compile. It gets this error:

error C2446: '!=' : no conversion from 'const char *' to 'const AbstractClassRep::Field *'

I'm guessing theres some additional changes above it.
#40
06/29/2008 (2:55 am)
Ok, sorry if some code are wrong. I update it with var types solved and a main.py for test all features