Extending Python with T3D
by Frank Carney · 11/23/2011 (8:12 am) · 17 comments
Python is a very powerful development environment. It allows the programmer to have access to some of the highest quality libraries available on the internet. Thousands of libraries have been used to extend Python to make it the ultimate 'glue' language. It can be used in a web server, the desktop, to control super computers, and many other tasks.
T3D is a very powerful and complete game engine. However, every time there is a need for a library that is not part of the Torque code base it must be linked into the Torque engine. Often times this process requires turning the library into console object functions and data. This can be time consuming and error prone. Python has a unique advantage of getting rid of this scenario. Many people have already spent the time to integrate and debug connecting an app or library to Python. So if T3D can be made to connect with Python we get instant access to the wealth of stable and tested Python libraries. This is where this tutorial comes in. It describes how to 'extend' Python to make T3D act as a library for Python with full console object access.
The Good News
Someone has already taken the time to integrate Python with T3D. Actually they did it with TGE. This was done by the folks at [http://www.mmoworkshop.com/trac/mom/wiki/PyTorque Prairie Games]. They have a working MMO that is very good. The amount of blood and sweat that has gone into the MoM MMO is astonishing. If you have not played it check it out [http://www.minionsofmirth.com/ here].
The Bad News
Out of the box the code available [http://www.mmoworkshop.com/trac/mom/wiki/PyTorque here] does not work with T3D, it works with TGE. But that is what this article is all about...which leads us to...
The Great News
It did not take long to determine what changes needed to be made to extend Python with T3D. The T3D codebase is actually more suited to extending Python than the TGE codebase. The reason is because most of the T3D engine is already a library! This allows the new functionality to be logically split from the original code. It also allows us to add a few more functions to the DLL to allow it to talk to Python.
The Fine Print
Extending Python with T3D is not going to make the engine suddenly independent of Torque Script. You still have to have a main.cs and it has to have a minimum of certain modules loaded. The reason is the main.cs must create a canvas at some point in the Initialization of the engine. There is still a significant amount of work that needs to go into using Python with T3D. It has no integration to the built in editors and has no knowledge of the asset directory structure. This is very much a barebones setup and will require a significant amount of assembly. My goal with this article is to invite people to build their Python toolsets and share some of that information with the GG community. I thought about putting this information later in the article. However I wanted to warn the reader that there is much more to do after this extension is completed.
Garage Games
Prairie Games
Python
Extending Python
TDN PyTorque
Source Code
PyTorque
pytorque.cc diff
For creating the engine and making this possible.
Prairie Games
For doing the hard work of figuring out how to make Torque objects play nice with Python objects.
If you have not played their game [http://www.minionsofmirth.com/ Minions of Mirth] I highly recommend it. The game is very inspiring as to what can be achieved with the TGE and/or T3D engines.
This article was written using T3D 1.1 and 1.2, Python 2.6, and PG's PyTorque code.
I am sure 2.7 of Python will work fine, but if you run into issues go back to 2.6 to remove that as a factor. Once you have it working experiment with 2.7. I may be surprised, but I do not think this will work with Python 3.x. Just as a note of interest the latest version of MoM (as of this writing) uses 2.7.
Licensing Note
I cannot provide files with the modifications made in this resource. Do NOT upload them into this resource. The reason is the PyTorque code license if very similar to the Torque code license. The license does not allow for hosting the code on another website for public consumption. PyTorque code was developed by PG and is owned by PG. Respect their license by not hosting the code somewhere else. The most I can provide is diff files and links to the PyTorque source code. The reason PG provides the PyTorque source code is to draw traffic to their products. By hosting the code somewhere else you are stealing their traffic. They have been very gracious to provide this code to the community. To ensure the PyTorque resource is maintained please visit their site and purchase their products.
Create a New Project
If you don't already know how to create a project follow this link and learn how to do that: Your First Project Tutorial. Make sure you create a "full" project for this.
Get the PyTorque Source Code from PG
The source code is located here: PyTorque. Click on the PyTorque in the side menu and get the file from the Downloads section.
Backup the Engine Source Code
The engine source is typically located here: "C:TorqueTorque 3D Pro 1.1Engine" on a Windows system. Make a copy of the 'source' directory or backup the 'source' directory to another location. I just made a backup by doing a copy and paste. That way I ended up with a directory named 'source - Copy'. The reason for this step is that this part of the source code is shared across projects. We will be making changes to this code and it is always nice to be able to compare against an untouched file to see what was changed.
Of course, if you are comfortable making these changes or already have some sort of revision control setup then feel free to skip this step.
Copy PyTorque Code Into the Engine Directories
This step is to place the PyTorque code into the engine directories in the correct locations.
If your base directory for your Torque install differs from what is shown here just make the necessary substitution.
1 Unzip the pytorque.zip file somewhere.
2 From the 'tge15enginecore' directory copy tDictionary.h and tDictionary.cc to the 'C:TorqueTorque 3D Pro 1.1Enginesourcecore' directory.
3 Create a new directory under the 'C:TorqueTorque 3D Pro 1.1Enginesource' directory and call it 'python'.
4 From the 'tge15enginepython' directory copy pytorque.cc to the 'python' directory you just created.
Add Python Development Headers and Libraries to Visual C++ Project
1 Open up the Visual C++ project you created from the Torque Toolbox.
2 Goto the 'DLL' project and select 'Properties'. Update the C/C++ 'Additional Include Directories' to include 'C:Python26include' directory.
3 Do the same for the Linker 'Additional Library Directories' to include the 'C:Python26libs' directory.
Adjust Project to Produce Python Library
In the DLL Project go to Properties->Linker settings again and change the 'Output File' from the dll to 'pytorque.pyd'. If you want this can be name anything as long as the extension is pyd. Also, if you want to be able to run the non-dll portion of the project you created you can change the dll opened in main.cpp as follows:
Add tDictionary.h, tDictionary.cc, and pytorque.cc to the 'DLL' project. At this point the project will fail compilation if you try to compile.
Changes to pytorque.cc
1 Comment out this include: #include "platform/gameInterface.h"
2 At the end of the file comment out the functions: Torque_Initialize, Torque_Tick, and Torque_Shutdown.
3 Add this code at the end of the file:
Changes to compiledEval.cpp
1 Below line 540 (1.1)/ 537 (1.2) change this:
2 Below line 1481 (1.1) / 1489 (1.2) change this:
3 Below line 1638 (1.1) / 1646 (1.2) change this:
4 Below line 1940 (1.1) / 1949 (1.2) change this:
Changes to codeBlock.cpp
1 Below line 22 change this:
Changes to codeBlock.h
1 Below line 26 change this:
Changes to mainLoop.cpp
1 Below line 362 (1.1) / 369 (1.2) change this:
Running Under Python Control
Once the changes are in place it should compile without errors. Now you can create a Python script to control the engine. Here are some simple scripts to get you started.
Script Test1:
So now the ball is in your court. Have fun!
Edits:
1. Fixed some bugs with pytorque.cc. One of them caused crashing.
2. No longer need extra bogus parameter for functions. I believe this was a legacy TGE issue. Not sure.
3. Added new link to TDN article location. Will be adding code there and invite others to contribute code samples as well.
4. Added link to diff file with latest changes. I will add diffs incrementally so if there are issues it will be easy to regress if needed.
T3D is a very powerful and complete game engine. However, every time there is a need for a library that is not part of the Torque code base it must be linked into the Torque engine. Often times this process requires turning the library into console object functions and data. This can be time consuming and error prone. Python has a unique advantage of getting rid of this scenario. Many people have already spent the time to integrate and debug connecting an app or library to Python. So if T3D can be made to connect with Python we get instant access to the wealth of stable and tested Python libraries. This is where this tutorial comes in. It describes how to 'extend' Python to make T3D act as a library for Python with full console object access.
The Good News
Someone has already taken the time to integrate Python with T3D. Actually they did it with TGE. This was done by the folks at [http://www.mmoworkshop.com/trac/mom/wiki/PyTorque Prairie Games]. They have a working MMO that is very good. The amount of blood and sweat that has gone into the MoM MMO is astonishing. If you have not played it check it out [http://www.minionsofmirth.com/ here].
The Bad News
Out of the box the code available [http://www.mmoworkshop.com/trac/mom/wiki/PyTorque here] does not work with T3D, it works with TGE. But that is what this article is all about...which leads us to...
The Great News
It did not take long to determine what changes needed to be made to extend Python with T3D. The T3D codebase is actually more suited to extending Python than the TGE codebase. The reason is because most of the T3D engine is already a library! This allows the new functionality to be logically split from the original code. It also allows us to add a few more functions to the DLL to allow it to talk to Python.
The Fine Print
Extending Python with T3D is not going to make the engine suddenly independent of Torque Script. You still have to have a main.cs and it has to have a minimum of certain modules loaded. The reason is the main.cs must create a canvas at some point in the Initialization of the engine. There is still a significant amount of work that needs to go into using Python with T3D. It has no integration to the built in editors and has no knowledge of the asset directory structure. This is very much a barebones setup and will require a significant amount of assembly. My goal with this article is to invite people to build their Python toolsets and share some of that information with the GG community. I thought about putting this information later in the article. However I wanted to warn the reader that there is much more to do after this extension is completed.
Reference Information
LinksGarage Games
Prairie Games
Python
Extending Python
TDN PyTorque
Source Code
PyTorque
pytorque.cc diff
Credits
Garage GamesFor creating the engine and making this possible.
Prairie Games
For doing the hard work of figuring out how to make Torque objects play nice with Python objects.
If you have not played their game [http://www.minionsofmirth.com/ Minions of Mirth] I highly recommend it. The game is very inspiring as to what can be achieved with the TGE and/or T3D engines.
Nuts and Bolts
Version NoteThis article was written using T3D 1.1 and 1.2, Python 2.6, and PG's PyTorque code.
I am sure 2.7 of Python will work fine, but if you run into issues go back to 2.6 to remove that as a factor. Once you have it working experiment with 2.7. I may be surprised, but I do not think this will work with Python 3.x. Just as a note of interest the latest version of MoM (as of this writing) uses 2.7.
Licensing Note
I cannot provide files with the modifications made in this resource. Do NOT upload them into this resource. The reason is the PyTorque code license if very similar to the Torque code license. The license does not allow for hosting the code on another website for public consumption. PyTorque code was developed by PG and is owned by PG. Respect their license by not hosting the code somewhere else. The most I can provide is diff files and links to the PyTorque source code. The reason PG provides the PyTorque source code is to draw traffic to their products. By hosting the code somewhere else you are stealing their traffic. They have been very gracious to provide this code to the community. To ensure the PyTorque resource is maintained please visit their site and purchase their products.
Create a New Project
If you don't already know how to create a project follow this link and learn how to do that: Your First Project Tutorial. Make sure you create a "full" project for this.
Get the PyTorque Source Code from PG
The source code is located here: PyTorque. Click on the PyTorque in the side menu and get the file from the Downloads section.
Backup the Engine Source Code
The engine source is typically located here: "C:TorqueTorque 3D Pro 1.1Engine" on a Windows system. Make a copy of the 'source' directory or backup the 'source' directory to another location. I just made a backup by doing a copy and paste. That way I ended up with a directory named 'source - Copy'. The reason for this step is that this part of the source code is shared across projects. We will be making changes to this code and it is always nice to be able to compare against an untouched file to see what was changed.
Of course, if you are comfortable making these changes or already have some sort of revision control setup then feel free to skip this step.
Copy PyTorque Code Into the Engine Directories
This step is to place the PyTorque code into the engine directories in the correct locations.
If your base directory for your Torque install differs from what is shown here just make the necessary substitution.
1 Unzip the pytorque.zip file somewhere.
2 From the 'tge15enginecore' directory copy tDictionary.h and tDictionary.cc to the 'C:TorqueTorque 3D Pro 1.1Enginesourcecore' directory.
3 Create a new directory under the 'C:TorqueTorque 3D Pro 1.1Enginesource' directory and call it 'python'.
4 From the 'tge15enginepython' directory copy pytorque.cc to the 'python' directory you just created.
Add Python Development Headers and Libraries to Visual C++ Project
1 Open up the Visual C++ project you created from the Torque Toolbox.
2 Goto the 'DLL' project and select 'Properties'. Update the C/C++ 'Additional Include Directories' to include 'C:Python26include' directory.
3 Do the same for the Linker 'Additional Library Directories' to include the 'C:Python26libs' directory.
Adjust Project to Produce Python Library
In the DLL Project go to Properties->Linker settings again and change the 'Output File' from the dll to 'pytorque.pyd'. If you want this can be name anything as long as the extension is pyd. Also, if you want to be able to run the non-dll portion of the project you created you can change the dll opened in main.cpp as follows:
//sprintf(gameLib, "%s.dll", filename); sprintf(gameLib,"pytorque.pyd");Adding files to the project
Add tDictionary.h, tDictionary.cc, and pytorque.cc to the 'DLL' project. At this point the project will fail compilation if you try to compile.
Changes to pytorque.cc
1 Comment out this include: #include "platform/gameInterface.h"
2 At the end of the file comment out the functions: Torque_Initialize, Torque_Tick, and Torque_Shutdown.
3 Add this code at the end of the file:
extern "C"
{
bool torque_engineinit(int argc, const char **argv);
int torque_enginetick();
bool torque_engineshutdown();
};
static int Torque_Initialize(int argc, const char** argv)
{
if (!torque_engineinit(argc, argv))
return 1;
gPyTorqueInitialized = true;
return 0;
}
static int Torque_Tick()
{
return torque_enginetick();
}
static int Torque_Shutdown()
{
torque_engineshutdown();
gPyTorqueInitialized = false;
return 0;
}4 In the function 'cTorqueToPythonCallback' (line ~231) change this://why is argc one too many? only in the case of object? argc-=1;to this:
//why is argc one too many? only in the case of object? //argc-=1;5 In the function 'pytorque_export' (line ~393) change this:
gCallableLookup.insertEqual(lookup,callable); Con::addCommand(ns,fname,cTorqueToPythonCallback,usage,minargs+1,maxargs+1); } elseto this:
gCallableLookup.insertEqual(lookup,callable); Con::addCommand(ns,fname,cTorqueToPythonCallback,usage,minargs,maxargs); }6 In the function 'pytorque_export' (line ~410) change this:
} Py_INCREF(Py_None); return Py_None;to this:
} // must increment ref for stored object references Py_XINCREF(callable); Py_INCREF(Py_None); return Py_None;
Changes to compiledEval.cpp
1 Below line 540 (1.1)/ 537 (1.2) change this:
U32 lineNumber = code[ ip + 3 ] >> 1; #ifdef TORQUE_DEMOto this:
U32 lineNumber = code[ ip + 3 ] >> 1; // added for PyTorque CodeBlock::sfnNameSpace=fnNamespace; #ifdef TORQUE_DEMO
2 Below line 1481 (1.1) / 1489 (1.2) change this:
fnName = U32toSTE(code[ip]); // Try to look it up.to this:
fnName = U32toSTE(code[ip]); // added for PyTorque CodeBlock::sfnNameSpace=fnNamespace; // Try to look it up.
3 Below line 1638 (1.1) / 1646 (1.2) change this:
STR.popFrame();
}
else
{
switch(nsEntry->mType)to this:STR.popFrame();
}
else
{
// added for PyTorque
CodeBlock::sfnNameSpace=nsEntry->mNamespace->mName;
switch(nsEntry->mType)4 Below line 1940 (1.1) / 1949 (1.2) change this:
execFinished: if ( telDebuggerOn && setFrame < 0 )to this:
execFinished: // added for PyTorque CodeBlock::sfnNameSpace=NULL; if ( telDebuggerOn && setFrame < 0 )
Changes to codeBlock.cpp
1 Below line 22 change this:
ConsoleParser *CodeBlock::smCurrentParser = NULL; //-------------------------------------------------------------------------to this:
ConsoleParser *CodeBlock::smCurrentParser = NULL; // added for PyTorque StringTableEntry CodeBlock::sfnNameSpace=NULL; //-------------------------------------------------------------------------
Changes to codeBlock.h
1 Below line 26 change this:
static Compiler::ConsoleParser * smCurrentParser; static CodeBlock* getCurrentBlock()to this:
static Compiler::ConsoleParser * smCurrentParser; // added for PyTorque static StringTableEntry CodeBlock::sfnNameSpace; static CodeBlock* getCurrentBlock()
Changes to mainLoop.cpp
1 Below line 362 (1.1) / 369 (1.2) change this:
// Set our working directory. Torque::FS::SetCwd( "game:/" ); // Set our working directory. Platform::setCurrentDirectory( Platform::getMainDotCsDir() ); #ifdef TORQUE_PLAYERto this:
// Set our working directory.
Torque::FS::SetCwd( "game:/" );
// Set our working directory.
if(strncmp(Platform::getExecutableName(),"python",6) == 0){
// if being launched from Python
Platform::setMainDotCsDir( Platform::getCurrentDirectory() );
Platform::setCurrentDirectory( Platform::getCurrentDirectory() );
Torque::FS::Unmount( "game" );
Torque::FS::Mount( "game", Platform::FS::createNativeFS( ( const char* ) Platform::getCurrentDirectory() ) );
}else{
// if launched from Torque Toolbox or the executable wrapper for the DLL
Platform::setCurrentDirectory( Platform::getMainDotCsDir() );
}
#ifdef TORQUE_PLAYERRunning Under Python Control
Once the changes are in place it should compile without errors. Now you can create a Python script to control the engine. Here are some simple scripts to get you started.
Script Test1:
# script test1
import sys, os
import pytorque
from pytorque import TorqueObject
pytorque.initialize(len(sys.argv),sys.argv)
while pytorque.tick():
pass
pytorque.shutdown()Script Test2:# script test2
import sys, os
import pytorque
from pytorque import TorqueObject
pytorque.initialize(len(sys.argv),sys.argv)
pytorque.evaluate("""
// this will print to the console
for(%count = 0; %count < 10; %count++)
{
echo(%count);
}
""")
while pytorque.tick():
pass
pytorque.shutdown()Script Test3 (add this before the while loop of the previous script:def runonce():
pytorque.evaluate("""
new GuiBitmapButtonCtrl(MyButton) {
profile = "GuiButtonProfile";
horizSizing = "right";
vertSizing = "bottom";
position = "404 361";
extent = "285 85";
minExtent = "8 2";
visible = "1";
text = "Button";
groupNum = "-1";
buttonType = "PushButton";
bitmap = "./button";
helpTag = "0";
};""")
button = TorqueObject("MyButton")
def OnMyButton(value):
# this will print to the Python console, not the Torque console
print "Button pushed with value",value
pytorque.export(OnMyButton,"MyButton","OnButton","Example button command",1,1)
# I don't know why it needs the second parameter here. <Solved>
#button.command = "MyButton::OnButton(42,1);"
button.command = "MyButton::OnButton(42);" # fixed bug that required extra do nothing parameter
button.performClick()
pytorque.setglobal("$MyVariable",42)
print pytorque.getglobal("$MyVariable")
# this prints to the Torque console
pytorque.evaluate('echo ("*** Here is your variable:" @ $MyVariable);')
return button
button = runonce()Conclusion
Now that you have a running PyTorque system with T3D it is time to get to the real work. For instance the engine needs the current main.cs to run properly. Without the canvas does not get initialized and we will get an error message. This happens inside the Torque initialization process which occurs when you run pytorque.initialize. I have started to isolate the needed modules for my own projects to get a barebones system. However that may not really be necessary. You may be able to work within the default framework. Time will tell. If I have to gut the system to determine what is what then that will be a great opportunity to learn the ins and out of the CS code.So now the ball is in your court. Have fun!
Edits:
1. Fixed some bugs with pytorque.cc. One of them caused crashing.
2. No longer need extra bogus parameter for functions. I believe this was a legacy TGE issue. Not sure.
3. Added new link to TDN article location. Will be adding code there and invite others to contribute code samples as well.
4. Added link to diff file with latest changes. I will add diffs incrementally so if there are issues it will be easy to regress if needed.
About the author
I Started programming in HS and have never stopped. Now an 18 year vet of programming anything from assembler on a NES console to a nuclear waste processing system. If it can be programmed I may have tried to program it!
#2
11/23/2011 (5:50 pm)
Nice job!
#3
Thanks for the kudos.
11/24/2011 (7:26 pm)
Corrected the mainLoop.cpp code. It would not launch correctly under Torque Toolbox control. Now it detects if the controlling executable is Python. Might need to use a case insensitive compare. Thanks for the kudos.
#4
I got questions,
core/util/
seems to already have tDictionary.cpp and tDictionary.h ,
do we need to overwrite them with pytorque tDictionary.cc and tDictionary.h from .zip file?
or just add them to core/ folder as per your instructions to the project like a duplicate?
I tried them both and either way they throw compile errs.
line 47 tDictionary.h dStrcmp identifier not found.
which i kinda got over the error by adding:
#ifndef _STRINGFUNCTIONS_H_
#include "core/strings/stringFunctions.h"
#endif
to the file.
Also I plan to use it as .exe instead of extension
so ill just let it compile as .dll right?
well, i went ahead and built it as .exe and .dll and it compiled ok after my fix.
but am puzzled on how to make it work.
tried the ingame console importing a .py file to call a method but get syntax errors.
any suggestion, or is this meant to only work as an extension?
will appreciate your input or any example you can provide to call a function from ingame, ie: gui etc...
thanks
11/24/2011 (9:20 pm)
Thank you Frank, great resource.I got questions,
core/util/
seems to already have tDictionary.cpp and tDictionary.h ,
do we need to overwrite them with pytorque tDictionary.cc and tDictionary.h from .zip file?
or just add them to core/ folder as per your instructions to the project like a duplicate?
I tried them both and either way they throw compile errs.
line 47 tDictionary.h dStrcmp identifier not found.
which i kinda got over the error by adding:
#ifndef _STRINGFUNCTIONS_H_
#include "core/strings/stringFunctions.h"
#endif
to the file.
Also I plan to use it as .exe instead of extension
so ill just let it compile as .dll right?
well, i went ahead and built it as .exe and .dll and it compiled ok after my fix.
but am puzzled on how to make it work.
tried the ingame console importing a .py file to call a method but get syntax errors.
any suggestion, or is this meant to only work as an extension?
will appreciate your input or any example you can provide to call a function from ingame, ie: gui etc...
thanks
#5
#include "core/util/tDictionary.h"
See if that works without the files from the PyTorque kit. If it does then that is one less step.
Edit:
I just tried taking it out and it seems to do fine without it after a rebuild. In the pytorque.cc change the include like above. I will work on removing the instructions to add those files.
11/25/2011 (3:39 pm)
I never noticed the other tdictionary files. The new code goes in 'core' not 'util'. They may be the same with the 1.2 files being updated. I would guess including the file like this from pytorque.cc #include "core/util/tDictionary.h"
See if that works without the files from the PyTorque kit. If it does then that is one less step.
Edit:
I just tried taking it out and it seems to do fine without it after a rebuild. In the pytorque.cc change the include like above. I will work on removing the instructions to add those files.
#6
11/25/2011 (3:51 pm)
How come every time I go to edit the article it removes the back slashes from my file paths? This has got to be a bug. I do not want to have to replace those every time.
#7
11/25/2011 (4:06 pm)
Okay, I just updated the instructions. No longer do you use the tDictionary files form the zip file. Just use the existing by changing the #include.
#8
i dont think this is meant to work for .exe and .dll setup.
and only for as extension setup.
with .exe and .dll setup requires the python26.dll which i copy it to the game folder and ran ok, but still can not execute python scripts from ingame console, unless there is a particular way to do so that i am not aware of.
the .py examples show how to execute a torque script and torque .gui from python,
but I guess if this setup is ran as .exe and.dll we need to be able to execute a python script from a torque script. or .gui
ie: like it was done from tmmokit setup:
new GuiBitmapButtonCtrl(Example_functionButton) {
profile = "ButtonProfile";
horizSizing = "right";
vertSizing = "bottom";
position = "142 12";
extent = "32 32";
minExtent = "8 2";
visible = "1";
command = "Py::OnExampleFunctionButton();";
mouseOver = "0";
groupNum = "1";
buttonType = "RadioButton";
hasStateBitmaps = "0";
};
//--- OBJECT WRITE END ---
PyExec("path/examplefunctionfile.py");
will need look more closely to the pytorque.cc code to find out.
cheers
11/25/2011 (5:04 pm)
Thanks, got it to compile with default stock tDictionaries ok.i dont think this is meant to work for .exe and .dll setup.
and only for as extension setup.
with .exe and .dll setup requires the python26.dll which i copy it to the game folder and ran ok, but still can not execute python scripts from ingame console, unless there is a particular way to do so that i am not aware of.
the .py examples show how to execute a torque script and torque .gui from python,
but I guess if this setup is ran as .exe and.dll we need to be able to execute a python script from a torque script. or .gui
ie: like it was done from tmmokit setup:
new GuiBitmapButtonCtrl(Example_functionButton) {
profile = "ButtonProfile";
horizSizing = "right";
vertSizing = "bottom";
position = "142 12";
extent = "32 32";
minExtent = "8 2";
visible = "1";
command = "Py::OnExampleFunctionButton();";
mouseOver = "0";
groupNum = "1";
buttonType = "RadioButton";
hasStateBitmaps = "0";
};
//--- OBJECT WRITE END ---
PyExec("path/examplefunctionfile.py");
will need look more closely to the pytorque.cc code to find out.
cheers
#9
Could you please tell us what's the goal of using python instead of ts?
Is it to build some key components in python instead of C++/ts?
Is it to run faster?
I don't know python at all, so I'm wondering why people are looking into it :d
Why python and not C# (like unity) or lua ?
In all case, that's good to know that we can plug other languages.
Thanks,
11/26/2011 (1:42 am)
Hi,Could you please tell us what's the goal of using python instead of ts?
Is it to build some key components in python instead of C++/ts?
Is it to run faster?
I don't know python at all, so I'm wondering why people are looking into it :d
Why python and not C# (like unity) or lua ?
In all case, that's good to know that we can plug other languages.
Thanks,
#10
You should not need to copy the python dll into the same folder. Unless the default Python is not 2.6. If you have a later version like 2.7 you could change the library and include paths for 2.7. That way it will find the default version if it is 2.7.
Also, this has not been tested with Python 3.x. My guess is it will not work.
You cannot execute Python from the console. That is not what this does. This extends Python with Torque. You will have to create a Python console interface (not sure how to do that) to execute Python commands. I believe there are examples of a Python console, but it will need probably a custom GUI widget to support it.
You could execute Python code, but you would need to create a custom TS console command. If it has global access then it could a security issue. I did not write the initial code for this and am still trying to understand it. However, I know it did not add commands for executing Python form the TS console.
elvince,
This is not a replacement for TS. The reason you would extend Python with Torque is to have a wealth of Python libraries available. Python out of the box supports tons of databases, network protocol libraries (Twisted and others), lxml (a personal favorite of mine), and literally thousands of other libraries. Now that Torque is extended with Python you auto-magically have access to all of those libraries. This saves you the effort of porting those individually and working out the bugs to make them work with Torque.
Now, doing this modification does not automatically make it all work together. I plan on creating examples that explore making this stuff work together. If you look at the examples you will see that Python controls the execution loop. That means you will have other logic and events on the Python side as well as on the Torque side.
One thing to start people thinking is how to replace the default GUI with a GUI that uses Python events. The example has a button event, but you never see the button. It is not associated with any GUI that is actually viewable.
Another item to think about is how you can leverage network resources of the Python side. For instance you could go to Google and find their Python code for oauth. With some smart coding you could make it so a user signs in to the game with a google gmail account or even a facebook account. This could be a way to verify someone is a real person rather than using an email verification. This is just one example of existing Python code that you now have access to.
11/26/2011 (11:31 am)
pilotcap232,You should not need to copy the python dll into the same folder. Unless the default Python is not 2.6. If you have a later version like 2.7 you could change the library and include paths for 2.7. That way it will find the default version if it is 2.7.
Also, this has not been tested with Python 3.x. My guess is it will not work.
You cannot execute Python from the console. That is not what this does. This extends Python with Torque. You will have to create a Python console interface (not sure how to do that) to execute Python commands. I believe there are examples of a Python console, but it will need probably a custom GUI widget to support it.
You could execute Python code, but you would need to create a custom TS console command. If it has global access then it could a security issue. I did not write the initial code for this and am still trying to understand it. However, I know it did not add commands for executing Python form the TS console.
elvince,
This is not a replacement for TS. The reason you would extend Python with Torque is to have a wealth of Python libraries available. Python out of the box supports tons of databases, network protocol libraries (Twisted and others), lxml (a personal favorite of mine), and literally thousands of other libraries. Now that Torque is extended with Python you auto-magically have access to all of those libraries. This saves you the effort of porting those individually and working out the bugs to make them work with Torque.
Now, doing this modification does not automatically make it all work together. I plan on creating examples that explore making this stuff work together. If you look at the examples you will see that Python controls the execution loop. That means you will have other logic and events on the Python side as well as on the Torque side.
One thing to start people thinking is how to replace the default GUI with a GUI that uses Python events. The example has a button event, but you never see the button. It is not associated with any GUI that is actually viewable.
Another item to think about is how you can leverage network resources of the Python side. For instance you could go to Google and find their Python code for oauth. With some smart coding you could make it so a user signs in to the game with a google gmail account or even a facebook account. This could be a way to verify someone is a real person rather than using an email verification. This is just one example of existing Python code that you now have access to.
#11
All changes in 'pytorque.cc':
in the function 'cTorqueToPythonCallback' change:
in the function 'pytorque_export' change:
in the function 'pytorque_export' change:
The first two changes address the too many parameters issue. The button function required more parameters than necessary. I think this issue was a legacy issue with TGE.
The second issue is more serious. In a Python extension you must keep track of ALL objects. A function is an object. So the Py_XINCREF is needed to ensure proper memory tracking and allocation/deallocation. This was never done in the PyTorque code that I can tell. This solved a crashing issue I was having when strings seemed to be too long when sent to the callback. Now it works without issue and no more strange crashes.
Added to the resource!
11/27/2011 (11:31 am)
I have found and corrected some fairly serious bugs. I will capture them here and put them in the resource later:All changes in 'pytorque.cc':
in the function 'cTorqueToPythonCallback' change:
//why is argc one too many? only in the case of object? argc-=1;to:
//why is argc one too many? only in the case of object? //argc-=1;
in the function 'pytorque_export' change:
gCallableLookup.insertEqual(lookup,callable); Con::addCommand(ns,fname,cTorqueToPythonCallback,usage,minargs+1,maxargs+1);to:
gCallableLookup.insertEqual(lookup,callable); Con::addCommand(ns,fname,cTorqueToPythonCallback,usage,minargs,maxargs);
in the function 'pytorque_export' change:
} Py_INCREF(Py_None); return Py_None; }to:
} // must increment ref for stored object references Py_XINCREF(callable); Py_INCREF(Py_None); return Py_None; }
The first two changes address the too many parameters issue. The button function required more parameters than necessary. I think this issue was a legacy issue with TGE.
The second issue is more serious. In a Python extension you must keep track of ALL objects. A function is an object. So the Py_XINCREF is needed to ensure proper memory tracking and allocation/deallocation. This was never done in the PyTorque code that I can tell. This solved a crashing issue I was having when strings seemed to be too long when sent to the callback. Now it works without issue and no more strange crashes.
Added to the resource!
#12
11/29/2011 (8:25 pm)
Added diff with thread fixes. I will also add new threaded examples on TDN.
#13
Edit:
Change that to dStrnicmp for the T3D defined version. May help with cross platform compatibility.
12/11/2011 (6:37 pm)
Here is a small tweak for the code that detects if Python launched the app or not:if(strnicmp(Platform::getExecutableName(),"python",6) == 0){I changed the strncmp to a strnicmp so it is not case sensitive. At the time I wrote it I forgot that all I had to do was include the 'i' in the function call. I was thinking I was going to need to modify the string.Edit:
Change that to dStrnicmp for the T3D defined version. May help with cross platform compatibility.
#14
When compiling against the Python headers and libraries in "debug" mode it will require a different Python lib and set some debug flags. I have found this to be quite annoying and recommend modifying pyconfig.h.
Change where it shows this:
Also change this:
12/23/2011 (1:23 am)
Found another issue:When compiling against the Python headers and libraries in "debug" mode it will require a different Python lib and set some debug flags. I have found this to be quite annoying and recommend modifying pyconfig.h.
Change where it shows this:
pragma comment(lib,"python27_d.lib")to this:
pragma comment(lib,"python27.lib")
Also change this:
#ifdef _DEBUG # define Py_DEBUG #endifto this:
#ifdef _DEBUG //# define Py_DEBUG #endifThat way you do not have to download any additional debug libraries for python development. I just changed my Python version from 2.6 to 2.7 and ran into this issue again. So I figured I had better share! :)
#15
01/16/2012 (5:16 pm)
The next step is to add a SWIG interface, and then you ought to be able to do everything in native Python without having to write any TorqueScript at all. With a good understanding of the necessary macros for creating console commands, you shouldn't even have to make any changes to most of the engine.
#16
What is a workable method of debugging the PYD when running inside of a Python application?
My goal is a crash debugger showing me more than the disassembled machine code at the fault location.
02/03/2012 (7:48 am)
Great resource.What is a workable method of debugging the PYD when running inside of a Python application?
My goal is a crash debugger showing me more than the disassembled machine code at the fault location.
#17
03/17/2012 (10:19 am)
What is the process to get the scripts to kick in? Do you have to initiate them somewhere or is the resource looking for a certain .py file at a certain location? Is one of the examples easier to know if things are working than the others?
Torque 3D Owner Novack
CyberianSoftware
Thank you very much :)