Dev Blog, DotNetTorque(DNT) 1.1 Service Release Notes
by Paul Yoskowitz · 04/08/2013 (6:41 am) · 7 comments
We are in the final passes of our first major update to DNT. As you all are familiar, DNT allows you to use any Microsoft Dot Net language instead of TorqueScript for the glue of the engine. Some of the feedback we have received from our license holders has included bug reports, feature requests and well to put it bluntly, make DNT more like traditional Object Oriented programming.
So, this release will include a new DotNetTorque Customizer for one as well as new object abstractions. The new and improved customizer now parses even more details about the C++. We fixed a few bugs in regards to parsing ConsoleFunctions as well as several other minor parsing errors. The code base also went through a refactoring to organize it in a more straight forward approach.
DNT is now starting it's approach to true object oriented design.
How many times have you wondered?
Is this object an object instance or a datablock? Which console function is the correct console function for this object? (I.E. the object your using and the object it is derived from have the same console function but do different things.) What object is the object I'm using parent?
This and many other questions frequently pop into a scripter or programmers head during the duration of creating a game with T3D. Since the TorqueScript language isn't typed it often difficult to know the details of the objects your dealing with.
With a great deal of effort we were able to determine the inheritance of objects inside the engine. So how it is in C++ it is now in CSharp. For example in the C++ inheritance model for AIPlayer, the inheritance mode is:
And each step of the way console functions are added and over ridden, init persist fields are added and over ridden, etc. With using the new DotNet Object model, these functions are now exposed as member functions to the DotNet Classes.
An Example of the new model.
Some differences,
First this console function expects an object of type 'coPlayerData' or in C++ terms 'PlayerData' and 'CoPlayer' or in C++ terms 'Player'.
Once inside the body of the function, you now access dynamic object member parameters using the braces ([]), the values return and set by the braces are treated as string but are easily casted to other types.
Also, when you want to call a member function to the 'Player' class object, its member functions are now exposed with total IntelliSense. So typing the variable 'player' into the editor will display you a listing of the member functions, comments and parameters only pertaining to the player class.
If you add custom console functions in the C++, the DNTC will expose them in the CSharp object model. So, for example, you add a new console function 'JumpUpAndDown' in the player.cpp C++ code, it will be exposed to both the 'Player' and 'AIPlayer' IntelliSense respectively since AIPlayer is derived from Player.
Global variables also got a reworking. They are now exposed in the CSharp via several properties. Example usages would be:
The different interfaces are:
iGlobal['$variable'] Retrieves and set it as a integer bGlobal['$variable'] Retrieves and set it as a Boolean sGlobal['$variable'] Retrieves and set it as a String fGlobal['$variable'] Retrieves and set it as a Float dGlobal['$variable'] Retrieves and set it as a Double
Currently still in development is the exposure of the 'InitPersists' as member properties to the object. Along with being member properties, constructors for creating new objects will accept these parameters so you don't miss one when creating objects.
DNT 1.1 is our first step in migrating from a script interface to an object oriented interface to T3D. We have other features planned for this release but it is still too early to document how they will or won't work. But to give you an idea of the code difference I'll show you the TorqueScript and then the CSharp and you can decide which is more readable.
TorqueScript
CSharp
In the end it is your decision, which would you prefer?
Paul
Winterleaf Entertainment L.L.C.
So, this release will include a new DotNetTorque Customizer for one as well as new object abstractions. The new and improved customizer now parses even more details about the C++. We fixed a few bugs in regards to parsing ConsoleFunctions as well as several other minor parsing errors. The code base also went through a refactoring to organize it in a more straight forward approach.
The Big Change to DNT
DNT is now starting it's approach to true object oriented design.
How many times have you wondered?
This and many other questions frequently pop into a scripter or programmers head during the duration of creating a game with T3D. Since the TorqueScript language isn't typed it often difficult to know the details of the objects your dealing with.
The Object Model
With a great deal of effort we were able to determine the inheritance of objects inside the engine. So how it is in C++ it is now in CSharp. For example in the C++ inheritance model for AIPlayer, the inheritance mode is:
AIPlayer->Player->ShapeBase->GameBase->SceneObject->NetObject->SimObject
And each step of the way console functions are added and over ridden, init persist fields are added and over ridden, etc. With using the new DotNet Object model, these functions are now exposed as member functions to the DotNet Classes.
An Example of the new model.
public void ArmorOnAdd(coPlayerData datablock, coPlayer player)
{
player["mountVehicle"] = true.AsString();
player.setRechargeRate(datablock["rechargeRate"].AsFloat());
player.setRepairRate(0);
player.schedule("50", "updateHealth");
}Some differences,
First this console function expects an object of type 'coPlayerData' or in C++ terms 'PlayerData' and 'CoPlayer' or in C++ terms 'Player'.
Once inside the body of the function, you now access dynamic object member parameters using the braces ([]), the values return and set by the braces are treated as string but are easily casted to other types.
Also, when you want to call a member function to the 'Player' class object, its member functions are now exposed with total IntelliSense. So typing the variable 'player' into the editor will display you a listing of the member functions, comments and parameters only pertaining to the player class.
If you add custom console functions in the C++, the DNTC will expose them in the CSharp object model. So, for example, you add a new console function 'JumpUpAndDown' in the player.cpp C++ code, it will be exposed to both the 'Player' and 'AIPlayer' IntelliSense respectively since AIPlayer is derived from Player.
Globals
Global variables also got a reworking. They are now exposed in the CSharp via several properties. Example usages would be:
public void PlayerInitGlobals()
{
iGlobal["$CorpseTimeoutValue"] = 45 * 1000;
iGlobal["$PlayerDeathAnim::TorsoFrontFallForward"] = 1;
iGlobal["$PlayerDeathAnim::TorsoFrontFallBack"] = 2;
iGlobal["$PlayerDeathAnim::TorsoBackFallForward"] = 3;
iGlobal["$PlayerDeathAnim::TorsoLeftSpinDeath"] = 4;
iGlobal["$PlayerDeathAnim::TorsoRightSpinDeath"] = 5;
iGlobal["$PlayerDeathAnim::LegsLeftGimp"] = 6;
iGlobal["$PlayerDeathAnim::LegsRightGimp"] = 7;
iGlobal["$PlayerDeathAnim::TorsoBackFallForward"] = 8;
iGlobal["$PlayerDeathAnim::HeadFrontDirect"] = 9;
iGlobal["$PlayerDeathAnim::HeadBackFallForward"] = 10;
iGlobal["$PlayerDeathAnim::ExplosionBlowBack"] = 11;
}The different interfaces are:
Member Properties
Currently still in development is the exposure of the 'InitPersists' as member properties to the object. Along with being member properties, constructors for creating new objects will accept these parameters so you don't miss one when creating objects.
Summary
DNT 1.1 is our first step in migrating from a script interface to an object oriented interface to T3D. We have other features planned for this release but it is still too early to document how they will or won't work. But to give you an idea of the code difference I'll show you the TorqueScript and then the CSharp and you can decide which is more readable.
TorqueScript
function Armor::onCollision(%this, %obj, %col)
{
if (!isObject(%col) || %obj.getState() $= "Dead")
return;
// Try and pickup all items
if (%col.getClassName() $= "Item")
{
%obj.pickup(%col);
return;
}
// Mount vehicles
if (%col.getType() & $TypeMasks::GameBaseObjectType)
{
%db = %col.getDataBlock();
if ((%db.getClassName() $= "WheeledVehicleData" ) && %obj.mountVehicle && %obj.getState() $= "Move" && %col.mountable)
{
// Only mount drivers for now.
%obj.client.setFirstPerson(0);
// For this specific example, only one person can fit
// into a vehicle
%mount = %col.getMountNodeObject(0);
if(%mount)
return;
// For this specific FPS Example, always mount the player
// to node 0
%node = 0;
%col.mountObject(%obj, %node);
%obj.mVehicle = %col;
}
}
}CSharp
public void ArmorOnCollision(coPlayerData datablock, coPlayer player, coShapeBase col)
{
if (player.getState() == "Dead")
return;
// Try and pickup all items
if (col.getClassName() == "Item")
{
player.call("pickup", col);
return;
}
//AI are not allowed to drive they are lousey drivers....
if (!console.isObject(player["client"]))
return;
//Mount Vehicle.
if ((console.getTypeMask(col) && (UInt32)SceneObjectTypesAsUint.GameBaseObjectType) != (UInt32)SceneObjectTypesAsUint.GameBaseObjectType)
return;
coVehicleData db = new coVehicleData(col.getDataBlock());
if ((db.getClassName() != "WheeledVehicleData") || !player["mountVehicle"].AsBool() || player.getState() != "Move" || !col["mountable"].AsBool())
return;
// Only mount drivers for now.
new coGameConnection(player["client"]).setFirstPerson(false);
// For this specific example, only one person can fit
// into a vehicle
int mount = col.getMountNodeObject(0);
if (mount > 0)
return;
// For this specific FPS Example, always mount the player to node 0
col.mountObject(player, 0, new TransformF(true));
player["mVehicle"] = col;
}In the end it is your decision, which would you prefer?
Paul
Winterleaf Entertainment L.L.C.
About the author
http://winterleafentertainment.com/
#2
Also since it is c# this is not the only way to call functions:
My favourite feature is definetly the ObjectOriented design, I never have to look in the TorqueScript reference anymore because you got the whole list of functions at your fingertips with the visual studio intellisense!
04/08/2013 (7:24 am)
Worth noting, you can convert from strings to tsObjects like this:coStickyBehaviour bhv1 = (coStickyBehaviour)Spell["baseEmitter.ParticleBehaviour[0]"];Instead of this:
coStickyBehaviour bhv1 = new coStickyBehaviours(Spell["baseEmitter.ParticleBehaviour[0]"]);
Also since it is c# this is not the only way to call functions:
player.call("pickup", col);Naturally, if the function you want to call is written in c# you can circumvent T3D and just call it directly as c#:Inventory.Pickup(thePlayer, col, "1");Reducing typos etc..
My favourite feature is definetly the ObjectOriented design, I never have to look in the TorqueScript reference anymore because you got the whole list of functions at your fingertips with the visual studio intellisense!
#3
04/08/2013 (9:48 am)
Looks good Guys - I may have to dabble in DNT after my current project is finished.
#4
04/17/2013 (10:49 pm)
Great! Works perfect!
#5
07/19/2013 (10:46 am)
Any idea on an update release date? I am looking forward to a more formal object.method call functionality.
#6
The public GitHub is also updated.
github.com/WinterleafEnterainment/DNT-Torque3D-V1.1-MIT-3.0
07/19/2013 (11:26 am)
DNT 1.1 is already available if you own DNT it the DNTC for 1.1 should be on your download page. The public GitHub is also updated.
github.com/WinterleafEnterainment/DNT-Torque3D-V1.1-MIT-3.0

Torque Owner Vince Gee
WinterLeaf Entertainment