scriptT3D extension for Python
by Demolishun · 05/20/2012 (6:59 pm) · 54 comments
Requirements:
Windows OS (Windows XP and above I would assume)
Python 2.7 (32 bit)
T3D 1.2 (It may work for previous versions, but is untested by myself. Entr0py got it working with 1.1.)
T3D MIT 1.2 for MIT Release (Most likely would work fine with 1.2/1.1)
SWIG 2.0.4 (if you are rebuilding source from the .i files)
SWIG 2.0.8 for MIT Release (2.0.4 may work, but i upgraded to 2.0.8)
Code:
MIT ScriptT3D 1.2
Source files are included for engine source files. So you won't need to manually change engine files unless you have a highly modified version of T3D.
older scriptT3D 1.1
older scriptT3D 1.0
The older versions contain a diff against the engine source, the source files after generation through
SWIG, the SWIG files in case you want to modify the interface, the generated Python code, and sample Python scripts.
Description:
There is lots of documentation in the Python scripts on how to use the interface. The difficult part is how to structure your source code. I put everything including the modified engine source under the source directory in the project directory. This allows me to keep the source files separate from the engine source files. This includes the engine source files I changed. There is also instructions on how to setup SWIG to work with VC++. Look through the source files as I tried to document the interface in the comments where ever I could. This will hopefully make it so I can remember what I did 6 months from now.
Here is a link to a resource that shows how to structure your source in your project: www.garagegames.com/community/resources/view/21664
I included the directory structure in the zip file of how the sub-directories should look. Of course if you want to modify the engine source in the normal engine source directory that is up to you.
The diff file contains all the changes needed to the engine source files. Just ignore the lines that say "Only In". Also, use Wordpad to view the files if running under Windows. Notepad just does not handle *nix style files very well. I used Gnu DiffUtils for Windows to produce the diff.
Please have a look and see what needs to be improved not only for the actual code, but for the installation instructions. I have been getting burned out looking at the code and would like to get it into your hands now. I very much intend for you to add, change, improve, etc. If something is hard to setup or use then let me know and I will tweak this resource to help make it easier for the next person.
Have fun!!!
Install Instructions:
Python Interface Theory of Operation:
I realized there is not a good description of how this works at the function call level. There is some confusion to this effect. Here I will try and describe what takes place for the various interfaces and function calls. This may only be useful to those really needing to know how it works under the hood.
Notes:
TS means Torque Script.
Python Issues:
You may need to tweak Python for this to work properly. The issue arises from Python development libraries using a debug symbol and requiring a separate debug library for development. I don't recommend using this additional library/libraries. This can be fixed by tweaking a header file in the Python headers. Look in C:/Python27/include/pyconfig.h. Change the lines that look for the _DEBUG symbol being present. Change the line that try to require the debug version of the Python lib to look like this:
Changes:
5/29/2012: Changed how global variables and simobjects are accessed through Sim(). Example:
Contributed:
Look at the posts made by Guy Allard to this resource. He has created some really useful code templates for testing out the engine interface.
Credits:
Thanks to everyone in this community for just being your awesome selves.
Thanks to:
GarageGames for making an awesome engine.
Python developers, of which there are too many to count.
Vince Gee for giving me really good ideas on where to take this interface.
Guy Allard for being the guinea pig.
My Creator, for giving me the drive to create.
Windows OS (Windows XP and above I would assume)
Python 2.7 (32 bit)
T3D 1.2 (It may work for previous versions, but is untested by myself. Entr0py got it working with 1.1.)
T3D MIT 1.2 for MIT Release (Most likely would work fine with 1.2/1.1)
SWIG 2.0.4 (if you are rebuilding source from the .i files)
SWIG 2.0.8 for MIT Release (2.0.4 may work, but i upgraded to 2.0.8)
Code:
MIT ScriptT3D 1.2
Source files are included for engine source files. So you won't need to manually change engine files unless you have a highly modified version of T3D.
older scriptT3D 1.1
older scriptT3D 1.0
The older versions contain a diff against the engine source, the source files after generation through
SWIG, the SWIG files in case you want to modify the interface, the generated Python code, and sample Python scripts.
MIT Version of ScriptT3D
MIT ScriptT3D 1.2 is the version of ScriptT3D that works with the MIT 1.2 version of T3D. The ScriptT3D source code is officially released under the MIT license as well. This is in keeping with the desire to create a mind share of code development, but not limit commercial use of the code. Most of the documentation below still applies. However, the API is radically different. There is limited example code as well as unit tests. In addition there are some text files that help explain some parts of the interface. My intention over the next few months will be to convert the old examples, add new examples, and add new features to this interface. I am ramping up my development efforts on a particular project and this codebase will be the foundation for that work. So when I develop particularly useful features, fix bugs, and otherwise abuse this code those changes will end up here.Description:
There is lots of documentation in the Python scripts on how to use the interface. The difficult part is how to structure your source code. I put everything including the modified engine source under the source directory in the project directory. This allows me to keep the source files separate from the engine source files. This includes the engine source files I changed. There is also instructions on how to setup SWIG to work with VC++. Look through the source files as I tried to document the interface in the comments where ever I could. This will hopefully make it so I can remember what I did 6 months from now.
Here is a link to a resource that shows how to structure your source in your project: www.garagegames.com/community/resources/view/21664
I included the directory structure in the zip file of how the sub-directories should look. Of course if you want to modify the engine source in the normal engine source directory that is up to you.
The diff file contains all the changes needed to the engine source files. Just ignore the lines that say "Only In". Also, use Wordpad to view the files if running under Windows. Notepad just does not handle *nix style files very well. I used Gnu DiffUtils for Windows to produce the diff.
Please have a look and see what needs to be improved not only for the actual code, but for the installation instructions. I have been getting burned out looking at the code and would like to get it into your hands now. I very much intend for you to add, change, improve, etc. If something is hard to setup or use then let me know and I will tweak this resource to help make it easier for the next person.
Have fun!!!
Install Instructions:
- Create a new project or use existing one.
- Copy the zip_source.zip file to your project source directory. Usually located in the C:/Torque/Torque 3D 1.2/My Projects/<project name>/source
- Unzip the contents into the source directory.
- Run the getEngineSourceFiles.bat to copy the needed engine sources to be modified.
- Look at the changes in changes_diff.txt to modify the source files you just copied into the project source directories.
- Add the following project source files to your projects DLL project in VC++: scriptT3D.cpp, scriptT3D.h, scriptT3D_wrap.cxx, app/mainLoop.cpp, console/compiledEval.cpp, console/console.h, console/consoleInternal.cpp, console/consoleInternal.h, console/scriptObjects.h, console/simObject.h
- Add the the following project sources files to your projects executable project in VC++: main/main.cpp.
- Set the DLL project to produce: _scriptT3D.pyd instead of the <projectname>.dll file.
- Everything should now compile correctly.
- The main app should run be compiled and will run as well because we modified it to use the _scriptT3D.pyd library as well. BTW, pyds are still DLLs. So they can be used like DLLs under Windows.
- Copy scriptT3D.py to your projects "game" directory. Copy the files in the pyscripts directory to the "game" directory.
- Now run the test scripts and read through them to learn how to use the code.
Python Interface Theory of Operation:
I realized there is not a good description of how this works at the function call level. There is some confusion to this effect. Here I will try and describe what takes place for the various interfaces and function calls. This may only be useful to those really needing to know how it works under the hood.
Notes:
TS means Torque Script.
- SimObject creation: For SimObject creation (and derived objects) I rely on the console to do the heavy lifting. The reason is there is a lot going on when creating an object and I figure it is best for the existing console code to handle this. This is generally handled through the use the Evaluate command. This is usually called like this scriptT3D.Sim().Evaluate(<string to evaluate>).
- Python objects are handled in Python of course. However, they can be imported into the T3D and will have a SimObject host. This SimObject will call methods that are detected at the time of import as executable. It will also access attributes of various types natively in TS. That means you can literally import a Python object and access it in TS as if it were a TS object. Calling a function on an import Python object directly calls the method on the corresponding Python object. It is very fast. Note: For the 1.2 MIT version this option was removed. I did not feel good about the code. If people request I can put this back in. I have not received a lot of feedback on this particular feature so I don't think it will be missed. You can always simulate this feature using callback exports anyway.
- Calling functions on a TS object from Python is fast, however it does require a lookup in Python to verify the attribute is actually a function, and then it calls the function directly. The only time it does not call the function directly is if the :: method notation is used. This is not a typical way to call a function. In that case it will use Evaluate. It is also not a recommended way to call a function and is only supported for legacy reasons. It is also not how you call functions in Python. You have to use special syntax to call a function that way.
- Callbacks are a way to call Python functions directly from TS. You can create global callbacks in TS that will call functions in Python. In fact, when you import a Python object into TS it creates callbacks for every attribute that is detected as a method or function. This allows for TS objects as part of their normal processing to call Python functions without doing anything special. For instance, you could create a 'think' callback against the AIPlayer namespace. Then every time an AI 'think' method is invoked it would actually call the Python method associated with the callback. Callbacks provide a very powerful way to invoke Python code as if it were part of the TS code.
Python Issues:
You may need to tweak Python for this to work properly. The issue arises from Python development libraries using a debug symbol and requiring a separate debug library for development. I don't recommend using this additional library/libraries. This can be fixed by tweaking a header file in the Python headers. Look in C:/Python27/include/pyconfig.h. Change the lines that look for the _DEBUG symbol being present. Change the line that try to require the debug version of the Python lib to look like this:
ifdef _DEBUG # pragma comment(lib,"python27.lib") # else # pragma comment(lib,"python27.lib") # endif /* _DEBUG */Also disable the Py_DEBUG symbol by commenting it out like this (notice the slashes):
#ifdef _DEBUG //# define Py_DEBUG #endif
Changes:
5/29/2012: Changed how global variables and simobjects are accessed through Sim(). Example:
print Sim().o.objectname Sim().o.objectname = object # illegal, will fail print Sim().g.globalname Sim().g.globalname = "blah, blah, blah"9/28/2012: Fixed example for new API:
import sys
import scriptT3D
import sched, time
import Queue
# use for scheduling events
# This allows us to have functions occur after a delay.
# Good for doing tests that are created before the main loop, but execute in the main loop.
# This may or may not be used in this program
s = sched.scheduler(time.time, time.sleep)
# just assigning the object to a variable
# Just a preference
engine = scriptT3D
# Each time you run engine.Sim() it creates an object to access the console.
# Not a big deal, but just to help you be aware of that. I had issues trying
# to create a singleton.
console = engine.Sim()
conObjects = console.o
conGlobals = console.g
# put everything in a giant exception check for testing
# Not recommended for normal functioning.
# I got tired of everything freezing before the engine loop...
try:
# init
# Sends command line args to engine
if not engine.init(len(sys.argv),sys.argv):
sys.exit(1)
# console consumer callback
# Sends console output to Python stdout.
def consumerCallback(level, line):
# notice you can tell the level # (normal, warning, error) of the message
print level, line
# export consumer
engine.ExportConsumer(consumerCallback)
# execute our own startup
# For my setup I rename game.cs (which is called by default) in the root directory to main_hook.cs.
# I create an empty game.cs so that the engine does not complain.
# If you prefer to use the game.cs as is then this should just give an error in the console output.
# My intent is to be able to more finely control the startup sequence. Eventually I will have
# Python be in charge of more of the startup like creating objects and setting up the canvas.
# This will take some time to figure out, but in the meantime we can use the normal TS startup.
# Another intent is to allow pieces of the engine to be tested out. This gives you the ability
# to create objects and test their interfaces without the rest of the engine getting in the way.
# create main hook
def main_hook():
print "executing main_hook()"
console.Evaluate(""" exec("main_hook.cs"); """)
# execute the main_hook
main_hook();
# export a function
def exfunction(data):
print data
return len(data)
# exported into global namespace
engine.ExportCallback(exfunction,"exfunction")
# call using evaluate
print console.Evaluate("""exfunction("hello");""")
# call using execute
# Takes a SimObject (name or id), length of the argument list, and an argument list.
# If no SimObject, ie a global function, then provide empty string "".
# The first argument is the function name.
# It may make sense to make this simpler.
arglist = ["exfunction","world"]
print console.Execute("",len(arglist),arglist)
# messing with global data
console.g.global_variable = "Some Data"
print console.g.global_variable
console.g.another_global = "Some more data..."
# creating a SimObject and get the id as a string
# It is best to let T3D create its own objects. Hence the use of the evaluate function
simobj = console.Evaluate("""%temp = new SimObject(UniqueObjectName){attrib1="some value";}; return %temp;""")
print simobj # prints the id
# use id to get a reference to a python SimObject
psimobj = console.FindObject(simobj)
# now print out attrib1
print psimobj.attrib1
# another way, if you know the object name or if you have the number, problem is you cannot put the number in from a variable easily
print console.o.UniqueObjectName.attrib1
# can set it this way too
console.o.UniqueObjectName.attrib1 = "some other value"
# make more attributes
console.o.UniqueObjectName.attrib2 = "can also make new attributes"
# get the object Torque Script equivalent
# Can be a way to save object states to a database...
print repr(psimobj)
# export a queue object
q = Queue.Queue()
# returns the extScriptObject created to hold the exported object
# Mainly useful for using in TS functions
qobj = engine.ExportObject(q)
# this just shows the object type
# Notice the unique name generated by the export.
# This keeps the namespace unique for each object.
print repr(qobj)
# get the id for use in evaluate scripts
print qobj.getID()
# show the functions and variables that got exported from the queue object
# This calls the 'dump' function of the SimObject.
# There is a lot of junk in the 'dump', but you can see the methods that got exported like: put, qsize, get
qobj.dump()
# testing putting something on the queue
console.Evaluate("""{0!s}.put("{1!s}");""".format(qobj.getID(),'a message on the queue'))
# now test pulling from the queue
print "queue message:",q.get_nowait()
# function callbacks
# These are very interesting because I had to make some decisions to get
# the ability to use any function as a callback, but still have the ability
# to detect which SimObject, if any, it was called against. If I had not
# made this decision then it would be harder to export entire objects unless
# I used a different callback mechanism. I finally decided to use one solid
# mechanism, but for every callback you can still see the SimObject if any
# the function was called against. This is possible because functions are
# objects themselves and are capable of having attributes set on them.
# lets create a function to test this on
def test_callback():
if(hasattr(test_callback,"__SimObject__")):
print "Called from the namespace of this object:",test_callback.__SimObject__,test_callback.__SimObject__.getName()
else:
print "Not called from SimObject namespace"
# now lets export some callbacks
# callback export syntax: ExportCallback(<function>,"name","namespace"=None,"usage"=None,override=True)
# function is the function or method
# name is the function name in TS
# namespace is the namespace, can be None if not used
# usage is the usage string, can be None if not used
# override is if this will override existing functions, default is True, if false it will kick back an error if override is attempted
# Every parameter after name is optional.
engine.ExportCallback(test_callback,"test_callback") # global namespace
engine.ExportCallback(test_callback,"test_callback","SimObject") # SimObject namespace
console.Evaluate("""test_callback();""") # global call
console.Evaluate("""{0!s}.test_callback();""".format(simobj)) # test against simobject we created earlier
# Callbacks against class methods are the same as above. Python class callbacks already
# know which Python class they are called on. Just use the __SimObject__ attribute to find
# out which SimObject called the callback if any.
# some more info on object exporting
# complex class
class cattrib(object):
def __init__(self):
self.attr1 = ['a','b']
self.attr2 = (0,1)
self.attr3 = {'one':1,'two':2}
self.attr4 = int(5)
self.attr5 = float(1.2)
self.attr6 = str('doodle')
# export an instance of the cattrib object
cobj = engine.ExportObject(cattrib())
# use id to call functions in TS
# accessing arrays, tuples, dictionaries, stings, and numbers are supported
# When setting attributes from TS the functions try and maintain data if
# the attribute already exists. If not it will default to a type like string
# or dictionary as they are easist to convert to a Python representation.
# So if you want a particular datatype then define it on the Python side first.
# Also note that if the key or index for a sequence (array, tuple, dictionary)
# is of the wrong type it will fail to set or read the sequence. Tuples and strings
# are not able to be written as they are immutable types.
console.Evaluate("""echo({0!s}.attr1[1]);""".format(cobj.getId()))
console.Evaluate("""echo({0!s}.attr2[0]);""".format(cobj.getId()))
console.Evaluate("""echo({0!s}.attr3["two"]);""".format(cobj.getId()))
console.Evaluate("""echo({0!s}.attr4);""".format(cobj.getId()))
console.Evaluate("""echo({0!s}.attr5);""".format(cobj.getId()))
console.Evaluate("""echo({0!s}.attr6);""".format(cobj.getId()))
# hwnd handle
# This is so other apps can use the T3D hwnd handle. I have tested this with
# wxPython and it does work. However, wxPython event system interferes with the
# T3D event system so it is not recommended to be used with wxPython. Other
# packages I would try to use this with is pyOgre and pyGame. Those have independent
# event systems that are not needed. Now, these graphicssystems are not necessarily
# any better than T3D, it is I just wanted to have the capability. There are other
# GUI systems that might make sense to use with T3D.
hwnd = engine.gethwnd()
# run the main loop
while engine.tick():
# run any scheduled events
s.run()
# normal shutdown
engine.shutdown()
except Exception,e:
print eContributed:
Look at the posts made by Guy Allard to this resource. He has created some really useful code templates for testing out the engine interface.
Credits:
Thanks to everyone in this community for just being your awesome selves.
Thanks to:
GarageGames for making an awesome engine.
Python developers, of which there are too many to count.
Vince Gee for giving me really good ideas on where to take this interface.
Guy Allard for being the guinea pig.
My Creator, for giving me the drive to create.
About the author
I love programming, I love programming things that go click, whirr, boom. For organized T3D Links visit: http://demolishun.com/?page_id=67
#42
I am working on my prototype using ScriptT3D and am already taking notes on things I need to add. I am also working on some simple libraries for structuring the code better. So I hope to add to this resource in the next few months some Python code to make interfacing with TS cleaner.
I am using this with MIT 3.0 so I know it works. There is some code that got moved around in the mainloop.cpp that will be addressed in an update to ScriptT3D.
Also, if using this with the script improvements I think a lot more tweaks will need to be made to make this work properly.
08/07/2013 (7:38 pm)
I was going to say, check to see that everything is added to the project. It sounds like you are got it pretty close.I am working on my prototype using ScriptT3D and am already taking notes on things I need to add. I am also working on some simple libraries for structuring the code better. So I hope to add to this resource in the next few months some Python code to make interfacing with TS cleaner.
I am using this with MIT 3.0 so I know it works. There is some code that got moved around in the mainloop.cpp that will be addressed in an update to ScriptT3D.
Also, if using this with the script improvements I think a lot more tweaks will need to be made to make this work properly.
#43
I have some ideas of my own for some wrapper functions on the Python side for creating objects and so on... looking forward to seeing what you come up with!
Also, for the record, you may want to set whatever you develop in to use spaces instead of tabs for T3D work. It's a pain, I know, but we should probably follow existing conventions...
08/07/2013 (7:54 pm)
Yep, that did it. ALso note that I had to add C:\Python27\libs to the linker library paths, and C:\Python27\include to the include paths. And build in Release mode. Now I'm getting 'module has no attribute Sim' from 'engine.Sim()', but that sounds more manageable.I have some ideas of my own for some wrapper functions on the Python side for creating objects and so on... looking forward to seeing what you come up with!
Also, for the record, you may want to set whatever you develop in to use spaces instead of tabs for T3D work. It's a pain, I know, but we should probably follow existing conventions...
#44
All the Python stuff must be 4 spaces per indent. There may be some issues with that in there too. I can't do anything about any generated code that does not comply.
08/08/2013 (12:10 pm)
I generally try to use 4 spaces in place of a tab. There may have been some issues with using VC++ early on. I will look at spacing and settings in VC++ to get that fixed.All the Python stuff must be 4 spaces per indent. There may be some issues with that in there too. I can't do anything about any generated code that does not comply.
#45
Still not sure why this discrepancy with no Sim() function existing. I checked the generated source in scriptT3D.py and there's no sign of it. Is it supposed to be provided by the PYD?
08/08/2013 (2:44 pm)
Yeah, Python is an odd kitten and generated code is what it is. I was just referring to engine modifications. It becomes obvious when you git diff the codebase, and git inserts a different number of spacer per tab, so everything gets out of whack :P.Still not sure why this discrepancy with no Sim() function existing. I checked the generated source in scriptT3D.py and there's no sign of it. Is it supposed to be provided by the PYD?
#46
Like I said the resource needs some work.
Edit:
What are the standard spaces per tab in T3D? I can fix that later.
08/08/2013 (6:04 pm)
Use the fixed example for the new api. Sim() does not exist anymore. I need to update the resource to be less confusing. The examples that come with the code should work, but if any of them contain Sim() then it is old. Also, the .o, .g, etc stuff is gone. I now access that this way:import scriptT3D as engine Con = engine.Con Globals = engine.Globals SimObjects = engine.SimObjects
Like I said the resource needs some work.
Edit:
What are the standard spaces per tab in T3D? I can fix that later.
#47
08/08/2013 (6:06 pm)
Oh, and refer to the unit tests for examples of how things are supposed to work for now. It does pretty much cover how everything should work with the new API. I keep having to look at the unit tests to remember how to do it right. LOL!
#48
Uh yeah, 3 spaces/tab for Torque. I'm still trying to find a Vim plugin that can handle tabs-for-indentation-spaces-for-formatting properly...
08/08/2013 (7:26 pm)
Ok, I should have checked the unit test files a bit more carefully - I assumed one of the examples (in the resource or the comments) would do it. They all still use Sim() though :P. I didn't want to deal with unit tests, I wanted to head straight to a canvas!Uh yeah, 3 spaces/tab for Torque. I'm still trying to find a Vim plugin that can handle tabs-for-indentation-spaces-for-formatting properly...
#49
In the directory called pyscripts there are two examples.
Use the one called "scriptT3D_interface_testing_1.2.0.py".
You will need to rename main.cs to main_hook.cs. Also provide this simple cs file as main.cs:
I also have a minimal startup that I call "main_minimal.cs" that looks like this:
08/08/2013 (7:38 pm)
Okay, sorry about that.In the directory called pyscripts there are two examples.
Use the one called "scriptT3D_interface_testing_1.2.0.py".
You will need to rename main.cs to main_hook.cs. Also provide this simple cs file as main.cs:
// Check to see if started from Python
if(startsWith(getExecutableName(),"python")){
// startup is controlled by Python...sort of
echo("main.cs called under control of Python");
}else{
// started with regular executable
exec("main_hook.cs");
}I also have a minimal startup that I call "main_minimal.cs" that looks like this:
new GuiControlProfile(GuiDefaultProfile);
new GuiControlProfile(GuiToolTipProfile);
new GuiCanvas(Canvas);
Canvas.setWindowTitle("ScriptT3D");
new RenderPassManager(DiffuseRenderPassManager);
setLightManager("Basic Lighting");
activateDirectInput();
GlobalActionMap.bindCmd("keyboard", "escape", "quit();", "");
new GuiControlProfile(GuiTextProfile)
{
fontSize = 48;
fontColor = "50 50 50";
justify = "center";
};
%txt = new GuiTextCtrl()
{
profile = GuiTextProfile;
position = "200 100";
extent = "200 100";
horizSizing = "center";
verSizing = "center";
text = "Hello ScriptT3D!!";
};
Canvas.setContent(%txt);That will give you a minimal canvas setup.
#50
As of now I do NOT have a pure Python startup of the engine. I was going to build a compiler to do the conversion, but I have not taken that path yet. I need to get my game to the prototype stage at this point.
08/08/2013 (7:43 pm)
I am in the process of reworking this. I intend to have clear hooks into client/server portions of code. One thing that is radically different is all the code will be precompiled and not execed like TS is. So I need to think about how that will work in a pure client or a pure server. It could be that the client compiles both client/server code, but will only exec client code when acting as a pure client. Of course the compilation can be done beforehand just like TS. Generally it is by default.As of now I do NOT have a pure Python startup of the engine. I was going to build a compiler to do the conversion, but I have not taken that path yet. I need to get my game to the prototype stage at this point.
#51
This is something I will address at some point. The problem is how to create objects and datablocks without using the syntax of used by TS. I suppose I can create the datablock in C++ and assign variables after creation, then make it a "live" object exposed to TS. This will require some changes to ScriptT3D to facilitate making objects through C++ rather than through TS.
08/08/2013 (7:47 pm)
Oh, another thing is I am using engine Con.eval() to create SimObjects. I don't like this syntax, but I can hide it in objects like this:# mission manager for loading/saving missions in the database
class MissionManager(object):
def __init__(self):
# check if mission manager exists
if ast.literal_eval(Con.isObject(self.__class__.__name__)):
self.misobj = SimObjects[self.__class__.__name__].getId()
Con.warn("{0} object already exists: {1}".format(self.__class__.__name__, self.misobj))
else:
# create mission manager script object
self.misobj = Con.Eval("new ScriptObject({0});".format(self.__class__.__name__))
# export console accessible functions to MissionManager namespace
engine.ExportCallback(self.getNumMissions,"getNumMissions",self.__class__.__name__)
engine.ExportCallback(self.loadMission,"loadMission",self.__class__.__name__)
engine.ExportCallback(self.saveMission,"saveMission",self.__class__.__name__)
Con.echo("Created {0} object: {1}.".format(self.__class__.__name__, self.misobj))
def getNumMissions(self):
return 0
def loadMission(self, name):
return ""
def saveMission(self, name, misobj):
return TrueThis is something I will address at some point. The problem is how to create objects and datablocks without using the syntax of used by TS. I suppose I can create the datablock in C++ and assign variables after creation, then make it a "live" object exposed to TS. This will require some changes to ScriptT3D to facilitate making objects through C++ rather than through TS.
#52
08/08/2013 (10:18 pm)
Thanks for all that! I'm going to have a good go at this on the way home. Having networking would be awesome. I think I'll focus my attention on getting t3d-bones using Python. Should be awesome.
#53
When making a debug build, the project compiles successfully and when Torque launches from the built exe, while loading the AssertFatal (in console/simObject.cpp at line 531) is called giving me the error "Object did not call SimObject::onAdd()."
When making a release build, the exe loads fine.
I've performed the main.cs->main_hook.cs and new main.cs operation.
After I made this progress, I haven't found a way to exec python from inside the engine, loaded by exe. As a result, I played around in a command prompt, went to my Torque project directory (the one with _scriptT3D.pyd) and loaded Python interactively. I was able to import scriptT3D perfectly.
All went well, until I went to execute scriptT3D.init(). It would result in a "failed to open main.cs" error (app/mainLoop.cpp @ ~516). I tried again, using os.getcwd() to verify python is using the current directory, same error.
I decided to approach Torque for this and I took advantage of the ifdef code above alertok() to open a file dialog box when main.cs can't be found and then give the error if still no success.
Code was compiled and I'm able to start Torque from interactive Python after selecting my main.cs in my game folder. I've tried sending the full path of the main.cs, based on os.getcwd() but it hasn't worked so far.
Overall, after two days of work, I'm happy with this starting place. I'm about to look into SWIG and the scriptT3D engine mods to try and understand more.
One question, was there any original intent to be able to use python from inside the engine (for example, maybe an "exec" or some such in a TorqueScript to start off a chain such as with execs in TorqueScript) and I'm missing something, or is that my next little project?
11/02/2013 (6:26 pm)
I'm using Visual Studio 2010. I've successfully compiled Python 2.7 (for the debug library) and combined this with T3D 3.0. The DLL is compiling as _scriptT3D.pydWhen making a debug build, the project compiles successfully and when Torque launches from the built exe, while loading the AssertFatal (in console/simObject.cpp at line 531) is called giving me the error "Object did not call SimObject::onAdd()."
When making a release build, the exe loads fine.
I've performed the main.cs->main_hook.cs and new main.cs operation.
After I made this progress, I haven't found a way to exec python from inside the engine, loaded by exe. As a result, I played around in a command prompt, went to my Torque project directory (the one with _scriptT3D.pyd) and loaded Python interactively. I was able to import scriptT3D perfectly.
All went well, until I went to execute scriptT3D.init(). It would result in a "failed to open main.cs" error (app/mainLoop.cpp @ ~516). I tried again, using os.getcwd() to verify python is using the current directory, same error.
I decided to approach Torque for this and I took advantage of the ifdef code above alertok() to open a file dialog box when main.cs can't be found and then give the error if still no success.
Code was compiled and I'm able to start Torque from interactive Python after selecting my main.cs in my game folder. I've tried sending the full path of the main.cs, based on os.getcwd() but it hasn't worked so far.
Overall, after two days of work, I'm happy with this starting place. I'm about to look into SWIG and the scriptT3D engine mods to try and understand more.
One question, was there any original intent to be able to use python from inside the engine (for example, maybe an "exec" or some such in a TorqueScript to start off a chain such as with execs in TorqueScript) and I'm missing something, or is that my next little project?
#54
06/10/2014 (10:47 pm)
Robert, in case you're still wondering, I think ScriptT3D allows you to call out to Python through native TS object callbacks. I haven't actually tried to do this yet but I'll let you know if I get anywhere. 
Torque Owner Daniel Buckmaster
T3D Steering Committee
C:devTorque3DMy ProjectsScriptT3Dgame>python game.py Traceback (most recent call last): File "game.py", line 3, in <module> import scriptT3D File "C:devTorque3DMy ProjectsScriptT3DgamescriptT3D.py", line 26, in <module> _scriptT3D = swig_import_helper() File "C:devTorque3DMy ProjectsScriptT3DgamescriptT3D.py", line 22, in swig_import_helper _mod = imp.load_module('_scriptT3D', fp, pathname, description) ImportError: dynamic module does not define init function (init_scriptT3D)I did put the scriptT3D*.cpp/h files in a folder though (as in, Engine/source/scriptT3D/scriptT3Dsimple.cpp), so I'll try moving them out of it first.EDIT: Ooh, I just realised the Project Manager hadn't added the .cxx file to the solution. Let's see if that helps.