Torque Game Engine DocumentationVersion 1.3.x |
Alright, up until this point, we have talked about scripting alone. Now we will discuss the interface between the console and the core engine.
Before starting it is important that we define a consistent set of terms to describe the concepts we are about to explore:
Table 5.1. Engine-Console Interface Terminology
| Term | Definition |
|---|---|
| C++-Specific Terms | |
| C++ Variable |
|
| C++ Function |
|
| Member |
|
| Method |
|
| Script-Specific Terms | |
| Local or Global Variable |
|
| Function |
|
| Field |
|
| Dynamic Field |
|
| Command (deprecated) |
|
| Console Method |
|
They say, "a picture is worth a thousand words". So, here is an illustration of the above table:

Before we jump into the gory details of interfacing the engine and console, here is a problem solution matrix:
Table 5.2. Engine Interface Problem-Solution Matrix
| Problem | Solution | Solution Type |
|---|---|---|
| C++ to Console | ||
Expose Member as Field | FUNCTION | |
Expose Member as Field | MACRO | |
Expose/Remove global C++ Variable or static Member as Local Variable | FUNCTION | |
Expose Method as Command (deprecated) | Con::addCommand() (deprecated) | FUNCTION |
Create Console Method from C++ | MACRO | |
Create Console Function from C++ | MACRO | |
This function allows you to link C++ class Members to console object Fields.
The rules for using this function are
void ConsoleObject::addField(const char* in_pFieldname,
const U32 in_fieldType,
const dsize_t in_fieldOffset,
const char* in_pFieldDocs)
void ConsoleObject::addField(const char* in_pFieldname,
const U32 in_fieldType,
const dsize_t in_fieldOffset,
const U32 in_elementCount,
EnumTable *in_table,
const char* in_pFieldDocs)
Here is an example (found in guiCrossHairHud.cc):
class GuiCrossHairHud : public GuiBitmapCtrl
{
...
ColorF mDamageFillColor; // declared here
...
};
void GuiCrossHairHud::initPersistFields()
{
...
addField( "damageFillColor", TypeColorF, Offset( mDamageFillColor,
GuiCrossHairHud)); // added in initPersistFields()
...
}
In this code, the Member mDamageFillColor has been linked to the Field damageFillColor. If you wish to test the ability to inspect and modify this field, do the following:
echo(####.damageFillColor);
####.damageFillColor = " 1.0 0.0 0.0 1.0";
echo(####.damageFillColor);
You may notice that although the contents of the variable were changed (to 100% opaque RED), the reticule stayed GREEN. This is because you changed the Server-copy of the variable, not the Client-copy. The relationship between clients and servers can get confusing. We don't have space to go into it here, but to get a better understanding, checkout the Torque networking documentation.
For clarity's sake here are some made up samples demonstrating the use of this function:
//// Adding simple variable
// the varible we want to add
bool bTorqueRocks;
// adding it
addField( "TorqueRocks", TypeBool, Offset(bTorqueRocks,EGTClass));
//// Adding an array
// the varible we want to add
S32 arynEGTChapters[28];
// adding it
addField( "TorqueRocks", TypeS32, Offset(arynEGTChapters,EGTClass),28);
//// Adding an ENUM
// the varible we want to add
StateData::LoadedState stateLoaded[MaxStates];
// the EnumTable
static EnumTable::Enums enumLoadedStates[] =
{
{ ShapeBaseImageData::StateData::IgnoreLoaded, "Ignore" },
{ ShapeBaseImageData::StateData::Loaded, "Loaded" },
{ ShapeBaseImageData::StateData::NotLoaded, "Empty" },
};
static EnumTable EnumLoadedState(3, &enumLoadedStates[0]);
// adding it
addField("stateLoadedFlag", TypeEnum, Offset(stateLoaded, ShapeBaseImageData), MaxStates, &EnumLoadedState);
Having covered the most commonly used version of the addField() functions, lets quickly outline the uses and syntax for the other variety.
This is a specialized version of the addField() function. It does not handle arrays or ENUMs, but it has the nice feature of a validator function. Let us look at the syntax and then I'll explain validator functions.
void ConsoleObject::addFieldV(const char* in_pFieldname,
const U32 in_fieldType,
const dsize_t in_fieldOffset,
TypeValidator *v)
Type Validator Classes are used to restrict the values a field may be given. If illegal values are assigned to a validated field, the validator function will print an error to the console and set the field to a valid value.
The two most commonly used Type Validator Classes are FRangeValidator and IRangeValidator. As you might imagine, the prior validates that the values a user inputs for the 'to be validated' field are within an inclusive range of floating-point values. The later is used for integers.
// from projectile.cc around line 126
// light radius is limited to between 1.0 and 20.0, inclusive.
addNamedFieldV(lightRadius, TypeF32, ProjectileData, new FRangeValidator(1, 20));
These two varients of addField() are actually MACROS that do nothing more than give the console field the same name as the class member which is being accessed.
#define addNamedField(fieldName,type,className) \ addField(#fieldName, type, Offset(fieldName,className))
#define addNamedFieldV(fieldName,type,className, validator) \ addFieldV(#fieldName, type, Offset(fieldName,className), validator)
I glossed over the Offset macro above in the interest of first discussing the usage of addField() and its many versions. The offset macro is a cool bit of coding that calculates the position of a variable within an instance of a class. Or, more exactly, the Offset macro calculates how many bytes from the beginning of a class in memory a variable is located. Here is the syntax:
Offset(VariableName, ClassName)
This function allows you to unlink a previously linked member-field pair. In fact, this removes the field from the console entirely. Simple as that. Why do it? Consider the case where you derive from an object that does an addField() call for a member that you have decided should not be accessible (like position for Terrain data).
bool ConsoleObject::removeField(const char* in_pFieldname)
// 1. TerrainBlock is inherited from SceneObject.
// 2. SceneObject links member mObjToWorld with position.
// 3. TerrainBlock undoes this(in terrData.cc) removeField("position");
This function allows you to expose a global C++ variable or a static Member as a global variable in the console. (See camera.cc.)
Con::addVariable(const char *name, S32 t, void *dp);
The above code exposes the global C++ variable mMovementSpeed in the console as a global variable named Camera::movementSpeed.
Note: This controls the free camera flight speed while editting. Now you know another way to set it beyond the normal editor keystrokes.
This function allows you to remove a global variable from the console that was previously added with one of the variants of the addVariable() function.
bool removeVariable(const char *name)
Upon searching, I found not a single instance in which this was used. This is probably because it would be a sign of poor planning to add then remove a variable. Having the source code, you could just remove the add call and be done with. Nonetheless, you can use this function if it suits you to do so.
This function allows you to expose a Method as a Command. However, it is now deprecated-- you are not encouraged to use it. Instead, you should create a method in C++ (if you need to use it in the engine or it needs to be fast), and then call this method from within a ConsoleMethod.
This is a macro that allows you to create a new Console Method from C++. The use of ConsoleMethod() is not much expanded in the engine as it has been chosen as a means of replacing the more clumsy addCommand() calls. The static variant of ConsoleMethod is for methods that you want to call statically. For example, 'GameConnection::getServerConnection()'.
ConsoleMethod(className,scriptname,returnType,minArgs,maxArgs,usage)
ConsoleStaticMethod(className,scriptname,returnType,minArgs,maxArgs,usage)
minargs- The minimum arguments this method takes.
maxargs- The maximum number of args that can be passed to this method.
//From SimBase.cc
ConsoleMethod(SimObject, getId, S32, 2, 2, "obj.getId()")
{
argc; argv;
return object->getId();
}
In the above function, we've (well, the engine authors really...) written a simple utility to return the current object's unique ID (its handle). A short breakdown is as follow:
Internally,
This is a macro that allows you to create a new Console Function from C++. Ex: ShapeBase.cc
ConsoleFunction(name,returnType,minArgs,maxArgs,usage)
minArgs- Minimum arguments this function can accept.
maxArgs- Maximum arguments this function can accept.
// From main.cc
ConsoleFunction( getSimTime, S32, 1, 1, "getSimTime() - Time since game started.")
{
return Sim::getCurrentTime();
}
First, I corrected the above consolefunction declaration for this example. In the engine, the usage parameter was used instead to give information about the function's purpose. Really, we'd want it to tell us what to do if we messed up the args list. It's pretty clear that this creates a function in the console named 'getSimtTime', which returns a signed 32-bit value, and takes 1 argument. Interestingly, internally, we call the static method 'Sim::getCurrentTime()'. Remember, Console functions can internally call any function in the scope of the macros declaration or any static method.
In addition to the major functions we've discussed so far, there are some other important, though less used, functions you should know about. I will cover them briefly, and rely on your ability to examine the source code for usage examples. Note: I will use some of these in the tutorials that come with this guide also.
This function allows you to get the contents of a local variable in the console from within the engine. Note: The value is returned as a char string.
const char *Con::getLocalVariable(const char* name);
This function allows you to set the contents of a local variable in the console from within the engine. Note: all values passed as char strings to the console. The console automatically converts this information as necessary.
Con::setLocalVariable(const char *name, const char *value);
These functions provide the ability to print various levels of information into the console (and subsequently the log if logging is enabled).
Con::printf(const char *_format, ...);
Con::warnf(ConsoleLogEntry::Type type, const char *_format, ...);
type- A category indicator, where the category can be:
Con::errorf(ConsoleLogEntry::Type type, const char *_format, ...);
type- A category indicator, where the category can be: