Basic Scriptable SimObject
by John Vanderbeck · 04/09/2004 (7:53 pm) · 15 comments
Download Code File
This simply illustrates a very basic C++ object that is scriptable in TGE. It doesn't do anything useful, it simply serves as an illustration to build your own useful ones. Hopefully this will unveil an extremely powerful part of the engine for others to take advantage of. I've attached a zip file that has the code and example script file for easy adding to your project. I will also detail it all here for those who just want to learn.
To install the included files
Just copy BasicObject.h/.cc to your engine/console directory and then add them to your project and compile.
Place the test.cs file anywhere you want in your application, exec it, and then look in the file for comments. You really don't even need to use the .cs file, as you an do all the testing from the console. Its the comments in the .cs file that are the important things.
The code! Gimme the code!
I'm going to detail how it all works here, so those who just want to learn or have a quick reference whenever they need it don't have to bother dowloading anything.
Basically you have two sides. You have the C++ side, where we create an object that derives from SimObject and you have the script side where you simply interact with the object. First i'll cover the C++ side where we actually create the object. I'm simply going to post the header file and then the CC file in thier entirety here. I commented them pretty well so they shoudl be self explanatory. If they aren't please let me know and i'll fix that. In a nutshell we make the class a derived class of SimObject which gives us the tie ins to the script system. We overload a few basic functions then we create our own custom functions and the script functions to make them callable from script. So without further ado...
Header File
Source File
Next i'm going to show a .cs script file that I used just to test it all out. I commented this heavily as well. It basically just shows how to use it all from script.
Script File
This simply illustrates a very basic C++ object that is scriptable in TGE. It doesn't do anything useful, it simply serves as an illustration to build your own useful ones. Hopefully this will unveil an extremely powerful part of the engine for others to take advantage of. I've attached a zip file that has the code and example script file for easy adding to your project. I will also detail it all here for those who just want to learn.
To install the included files
Just copy BasicObject.h/.cc to your engine/console directory and then add them to your project and compile.
Place the test.cs file anywhere you want in your application, exec it, and then look in the file for comments. You really don't even need to use the .cs file, as you an do all the testing from the console. Its the comments in the .cs file that are the important things.
The code! Gimme the code!
I'm going to detail how it all works here, so those who just want to learn or have a quick reference whenever they need it don't have to bother dowloading anything.
Basically you have two sides. You have the C++ side, where we create an object that derives from SimObject and you have the script side where you simply interact with the object. First i'll cover the C++ side where we actually create the object. I'm simply going to post the header file and then the CC file in thier entirety here. I commented them pretty well so they shoudl be self explanatory. If they aren't please let me know and i'll fix that. In a nutshell we make the class a derived class of SimObject which gives us the tie ins to the script system. We overload a few basic functions then we create our own custom functions and the script functions to make them callable from script. So without further ado...
Header File
//-----------------------------------------------------------------------------
// Torque Game Engine
// Written by John Vanderbeck
//
// This code is written by John Vanderbeck and is offered freely to the Torque
// Game Engine wth no express warranties. Use it for whatever you want, all
// I ask is that you don't rip it off and call it your own. Credit where
// credit is due. If you do use this, just drop me a line to let me know. It
// makes me fell good :)
// Contact: jvanderbeck@novusdelta.com
// http://www.novusdelta.com
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// This code implements a very basic Scriptable Object
//-----------------------------------------------------------------------------
#ifndef _BASICOBJECT_H_
#define _BASICOBJECT_H_
#ifndef _SIMBASE_H_
#include "console/simBase.h"
#endif
class BasicObject : public SimObject
{
// This typedef is required for tie ins with the script language.
//--------------------------------------------------------------------------
protected:
typedef SimObject Parent;
//--------------------------------------------------------------------------
public:
BasicObject();
~BasicObject();
// These are overloaded functions from SimObject that we handle for
// tie in to the script language. The .cc file has more in depth
// comments on these.
//-----------------------------------------------------------------------
bool processArguments(S32 argc, const char **argv);
bool onAdd();
void onRemove();
static void initPersistFields();
//-----------------------------------------------------------------------
void setVariable(int var);
int sum(int a, int b);
void doCallback();
private:
int mMemberVar;
// This macro ties us into the script engine, and MUST MUST MUST be declared
// in a public section of the class definition. If it isn't you WILL get
// errors that will confuse you.
//--------------------------------------------------------------------------
public:
DECLARE_CONOBJECT(BasicObject);
//--------------------------------------------------------------------------
};
#endif // _BASICOBJECT_H_Source File
//-----------------------------------------------------------------------------
// Torque Game Engine
// Written by John Vanderbeck
//
// This code is written by John Vanderbeck and is offered freely to the Torque
// Game Engine wth no express warranties. Use it for whatever you want, all
// I ask is that you don't rip it off and call it your own. Credit where
// credit is due. If you do use this, just drop me a line to let me know. It
// makes me feel good :)
// Contact: jvanderbeck@novusdelta.com
// http://www.novusdelta.com
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// This code implements a very basic Scriptable Object
//
// One of the really powerful features of Torque is the ability to have C++
// functions or classes that are controlled via the engine's script language.
// This allows for incredible flexability.
//
// The purpose of this code here is to demonstrate what it takes to make a
// scriptable object. It is really very easy.
//-----------------------------------------------------------------------------
#include "console/basicobject.h"
#include "console/simBase.h"
#include "console/consoleInternal.h"
// This macro is required in order to "tie in" with the scripting engine.
IMPLEMENT_CONOBJECT(BasicObject);
// Just your standard object constructor. Nothing fancy here.
BasicObject::BasicObject()
{
mMemberVar = 0;
}
// Just your standard object destructor. Nothing fancy here.
BasicObject::~BasicObject()
{
}
// This is the first of the functions which deals with the script system.
// This one is actually almost never used by other Torque objects. In fact
// only one object currently uses it and that is TCPObject. To the best of
// my knowledge anyway. This is similiar to arguments when running Torque.
// If you create a new instance of this object and specify "arguments"
// furing the creation liek this:
//
// $object = new BasicObject(Name, argument1, argument 2);
//
// argument1, and argument2 would get passed into this function as
// arguments. As I said its rarely used but I included it here
// for completeness.
bool BasicObject::processArguments(S32 argc, const char **argv)
{
if(argc == 0)
return true;
else
return true;
return false;
}
// This is a very important function. Basically this is called when
// an instance of your object is created and registered by the script
// engine. What we do here is first call our parent's onAdd() and
// return false if it fails. Next, we find out what the script user
// "named" this instance of our object and create a valid namespace
// for that name. This is important and is what allows the script
// user to write script like this:
//
// $object = new BasicObject(myObject);
// myObject::onCallback(%this, %var)
// {
// };
//
// In the above example, "myObject" is what the script user named
// the object instance. Without the code below, the function above
// would have to be BasicObject::onCallback().
bool BasicObject::onAdd()
{
if (!Parent::onAdd())
return false;
const char *name = getName();
if(name && name[0] && getClassRep())
{
Namespace *parent = getClassRep()->getNameSpace();
Con::linkNamespaces(parent->mName, name);
mNameSpace = Con::lookupNamespace(name);
}
return true;
}
// This is the function that gets called when an instance
// of your object is being removed from the system and being
// destroyed. Use this to do your clean up and what not.
void BasicObject::onRemove()
{
Parent::onRemove();
}
// To be honest i'm not 100% sure on when this is called yet.
// Basically its used to set the values of any persistant fields
// the object has. Similiar to the way datablocks work. I'm
// just not sure how and when this gets called.
void BasicObject::initPersistFields()
{
Parent::initPersistFields();
}
//-----------------------------------------------------------------------
// These functions below are our custom functions that we will tie into
// script. They are all pretty self explanatory except for doCallback()
// which executes a scrpit function named "onCallback".
void BasicObject::setVariable(int var)
{
mMemberVar = var;
}
int BasicObject::sum(int a, int b)
{
return a + b;
}
void BasicObject::doCallback()
{
Con::executef(this, 2, "onCallback", "string_variable");
}
//-----------------------------------------------------------------------
// These functions are the code that actually tie our object into the scripting
// language. As you can see each one of these is called by scrpit and in turn
// calls the C++ class function.
ConsoleMethod(BasicObject, setVariable, void, 3, 3, "(int variable) Sets a variable in the BasicObject")
{
object->setVariable(dAtoi(argv[2]));
}
ConsoleMethod(BasicObject, sum, S32, 4, 4, "(int var1, int var2) sums the two ints")
{
return object->sum(dAtoi(argv[2]),dAtoi(argv[3]));
}
ConsoleMethod(BasicObject, doCallback, void, 2, 2, "Calls the BasicObject callback script function")
{
object->doCallback();
}Next i'm going to show a .cs script file that I used just to test it all out. I commented this heavily as well. It basically just shows how to use it all from script.
Script File
// These functions are the script side of BasicObject and just brielfy show
// the use of that object from script.
// This is nothing really exciting, it just creates an instance of the object
// and names it "myObject". It then echose the object handle to be sure it
// was created ok. Note that it stores it in a global variable so that we can
// eacily access it from the console for testing. All of this is just test
// code to illustrate use, not the best way to use it.
function initTest()
{
$BasicObject = new BasicObject(myObject);
echo("BasicObject = " @ $BasicObject);
}
// This declares the object callback. Note even though the callback only has
// one variable, this function has two. The first is always "%this".
function myObject::onCallback(%this, %var)
{
echo("myObject::onCallback(" @ %this SPC %var @ ") has been called");
}
// This just destroys the object when we are done testing it.
function endTest()
{
$BasicObject.destroy();
}
// This calls the BasicObject's setVariable function. You can also do this
// directly in the console of course.
//
// $BasicObject.setVariable(100);
// myObject.setVariable(100);
function testSetVariable(%var)
{
myObject.setVariable(%var);
}
// I didin't make test functions for the other two. The function above
// shows how simple it is. You can test out the other two BasicObject
// functions just by typing in the console like this:
//
// $BasicObject.sum(1, 5);
// $BasicObject.doCallback();
//
// When you trip the callback you will see the echo statement from
// myObject::onCallback() above. That show you that it is being
// called.
//
// That's about it. Its all pretty basic, but extremely powerful.
// You should be able to take this simple base and expand on it
// for your own purposes. Enjoy!
#2
04/11/2004 (6:26 am)
There's always more to do :)
#4
04/13/2004 (8:17 am)
Just realized that once again the download link didn't work (IS this some bug with the GG website? Seems I run into this a lot). Reuploaded it and it should be fine now.
#5
Just from inside item.c, initPersistFields contains the following:
Now I'm not sure what addGroup does. I see some initPersistFields with them and some without.
But I do know that if you take the addField paramters in order they are:
addField(
06/19/2004 (9:00 pm)
Umm, just for a reference, if I am not mistaken. initPersistFields() lets you link variables in the script side of the object to variables in the c++ side of the object without having to write special functions.Just from inside item.c, initPersistFields contains the following:
addGroup("Misc"); // MM: Added Group Header.
addField("collideable", TypeBool, Offset(mCollideable, Item));
addField("static", TypeBool, Offset(mStatic, Item));
addField("rotate", TypeBool, Offset(mRotate, Item));
endGroup("Misc"); // MM: Added Group Footer.Now I'm not sure what addGroup does. I see some initPersistFields with them and some without.
But I do know that if you take the addField paramters in order they are:
addField(

Torque Owner Dylan Sale