Integrating C++ additions
by Chris Beals · in Torque 2D Beginner · 02/18/2014 (5:35 pm) · 13 replies
Hello,
So I have been working with C++ trying to implement my own AI algorithms, and I want to test it in the game now. I have posted before and looked all over for information on how to do it, but none of it works right. I always get this:
Warning: (....sourceconsoleconsoleObject.cc @ 138) Couldn't find class rep for dynamic class: Test
I am using the exact files as said in this thread:
http://www.garagegames.com/community/forums/viewthread/133395
I have found multiple threads talking about this but most end in the same solution but there is something going wrong for me. I am using Visual Studios 2012 Express if that has an effect. I am concerned I am not including my files in the build path, but I am not sure.
So I have been working with C++ trying to implement my own AI algorithms, and I want to test it in the game now. I have posted before and looked all over for information on how to do it, but none of it works right. I always get this:
Warning: (....sourceconsoleconsoleObject.cc @ 138) Couldn't find class rep for dynamic class: Test
I am using the exact files as said in this thread:
http://www.garagegames.com/community/forums/viewthread/133395
I have found multiple threads talking about this but most end in the same solution but there is something going wrong for me. I am using Visual Studios 2012 Express if that has an effect. I am concerned I am not including my files in the build path, but I am not sure.
About the author
Recent CS graduate trying to get a foothold into the videogame industry. I currently am trying to implement interesting applications for a novel AI.
#2
The oldest threads use SceneObject, but there are ones from a few years ago that used SimObject. Even the main thread used SimObject to inherit from.
EDIT:
I found the problem. It was tied to the compiler and the configuration. Thank you.
02/18/2014 (6:23 pm)
I did the DECLARE_CONOBJECT and IMPLEMENT_CONOBJECT from the start. I also have my .h file inheriting from the SimObject class instead of the SceneObject class. I had both as some point but the change was because the threads I have seen had different ones.The oldest threads use SceneObject, but there are ones from a few years ago that used SimObject. Even the main thread used SimObject to inherit from.
EDIT:
I found the problem. It was tied to the compiler and the configuration. Thank you.
#3
02/18/2014 (9:32 pm)
So I actually ran into another issue with the same situation. I am finding out that in order to call any function you created in a C++ file in the engine. You need to have some binding, is that correct? I haven't seen this at all.
#4
In the development branch we've switched to a new format for better integration with doxygen reference document generation. Here's an example from the Sprite class:
02/18/2014 (9:40 pm)
Do you mean being able to call functions from TorqueScript? This isn't really described anywhere but there are plenty of examples in the source code - all binding functions and methods are contained within their own xxx_ScriptBinding.h file.In the development branch we've switched to a new format for better integration with doxygen reference document generation. Here's an example from the Sprite class:
/*! Sets whether or not the texture is flipped vertically.
@param flipY Whether or not to flip the texture along the y (vertical) axis.
@return No return value.
*/
ConsoleMethodWithDocs(Sprite, setFlipY, ConsoleVoid, 3, 3, (bool flipY))
{
// Set Flip.
object->setFlipY( dAtob(argv[2]) );
}
//-----------------------------------------------------------------------------
/*! Gets whether or not the texture is flipped horizontally.
@return (bool flipX) Whether or not the texture is flipped along the x axis.
*/
ConsoleMethodWithDocs(Sprite, getFlipX, ConsoleBool, 2, 2, ())
{
return object->getFlipX();
}
#5
The #if defined section allows me to develop my editor outside of the Torque project.
02/20/2014 (10:46 am)
For my iPad editor (using the release branch), I did the following in my Editor class for exposing access to an Objective-C method:#if defined(TORQUE_DEBUG) || defined(TORQUE_OS_IOS) || defined(TORQUE_RELEASE)
ConsoleFunction(editFile, void, 2, 2, "(string modulename) Edit the current module's source files")
{
NSString* modulename = [[NSString alloc] initWithUTF8String:argv[1]];
... get/instantiate ObjC class and call method ...
}
#endifThe #if defined section allows me to develop my editor outside of the Torque project.
#6
02/20/2014 (3:39 pm)
Is there a difference between ConsoleMethod and ConsoleFunction? And is this _ScriptBinding.h file just like a normal .h file such that you need to have your proper #include tags?
#7
A ConsoleMethod is linked to a specific object type; it is a Method of that object.
For example, the pickpoint ConsoleMethod in CompositeSprite_Scriptbinding.h could only be called on a valid CompositeSprite Object.
A ConsoleFunction has no parent object and can be called from wherever, by itself
xxx_ScriptBinding.h
Scriptbinding files are part of an effort by Mike Lilligreen and Charlie Patterson to regroup all console functions and methods within easily searchable files instead of finding them all around the .cc files.
You are free to declare Consolemethods and Consolefunctions wherever you wish, the xxx_ScriptBinding.h way it's just a convention that was adopted for clarity.
If you wish to share your code eventually or submit pull requests to the official repository however, I would suggest using the xxx_ScriptBinding.h way.
02/20/2014 (4:26 pm)
ConsoleMethod vs. ConsoleFunctionA ConsoleMethod is linked to a specific object type; it is a Method of that object.
For example, the pickpoint ConsoleMethod in CompositeSprite_Scriptbinding.h could only be called on a valid CompositeSprite Object.
%MyCompositeSprite.pickpoint(...)
A ConsoleFunction has no parent object and can be called from wherever, by itself
Vector2Add(...)
xxx_ScriptBinding.h
Scriptbinding files are part of an effort by Mike Lilligreen and Charlie Patterson to regroup all console functions and methods within easily searchable files instead of finding them all around the .cc files.
You are free to declare Consolemethods and Consolefunctions wherever you wish, the xxx_ScriptBinding.h way it's just a convention that was adopted for clarity.
If you wish to share your code eventually or submit pull requests to the official repository however, I would suggest using the xxx_ScriptBinding.h way.
#8
02/21/2014 (3:20 pm)
Is there any documentation on what the actual arguments for the ConsoleMethod is?
#9
I don't think so? (Mike or Michael might chime in on this)
The best way to truly understand it is to look at a few examples in the source, copy one of them and modify it.
An example might help clarify things a bit though, taken from SceneObject_ScriptBinding.h
- The commented part starting with /*! describes the function, its expected arguments and return value
- SceneObject is the Class on which to call the Method
- getUpdateCallback is the name of the Method
In this example, in script you'd call
- ConsoleBool is the type which the method will return; in this case it's a boolean value (true or false).
- The first "2" is the minimum number of arguments the Console method takes. 2 is always the lowest number you can put here, 3 would mean you have 1 extra argument, passed as a string (all arguments are received as strings)
The first 2 arguments will basically be the Class of the object and the name of the function; in any case, always assume that 2 means "no extra arguments"
For an even clearer example, the following method in script would use 4 as the minimum_argument_count.
- The second "2" is the maximum number of arguments the method will take.
Read the examples in the code to learn how to determine how many arguments were passed.
In the ConsoleMethod proper, argc is the number of arguments received(argumentcount) and argv[x] is the argument value in position x.
Note that this starts at argv[0]; for a count of 3 arguments, that means argv[0], argv[1] and argv[2];
Still in the method, object-> will point to the actual instance of the object which the method was called on. In our example, that's %MySceneObject.
Then you call whatever you need from the C++ engine code as usual. Just make sure to convert the string arguments into the proper format.
For example,
This will convert the string in the first passed argument to a float. dAtofb will convert to boolean, dAtoi to integer, etc.
And that value will be sent to the C++ method callsomeMethod.
Again, no amount of documentation can replace just messing around with the code.
02/21/2014 (4:08 pm)
Edit: Corrected with Richard's wisdom.I don't think so? (Mike or Michael might chime in on this)
The best way to truly understand it is to look at a few examples in the source, copy one of them and modify it.
An example might help clarify things a bit though, taken from SceneObject_ScriptBinding.h
/*! Gets whether the 'onUpdate' callback is called or not.
@return (bool status ) Whether the 'onUpdate' callback is called or not.
*/
ConsoleMethodWithDocs(SceneObject, getUpdateCallback, ConsoleBool, 2, 2, ())
{
...
}- The commented part starting with /*! describes the function, its expected arguments and return value
- SceneObject is the Class on which to call the Method
- getUpdateCallback is the name of the Method
In this example, in script you'd call
%MySceneObject = new SceneObject(); %MySceneObject.getUpdateCallback();
- ConsoleBool is the type which the method will return; in this case it's a boolean value (true or false).
- The first "2" is the minimum number of arguments the Console method takes. 2 is always the lowest number you can put here, 3 would mean you have 1 extra argument, passed as a string (all arguments are received as strings)
The first 2 arguments will basically be the Class of the object and the name of the function; in any case, always assume that 2 means "no extra arguments"
For an even clearer example, the following method in script would use 4 as the minimum_argument_count.
getUpdateCallBack(%argument1, %argument2)
- The second "2" is the maximum number of arguments the method will take.
Read the examples in the code to learn how to determine how many arguments were passed.
In the ConsoleMethod proper, argc is the number of arguments received(argumentcount) and argv[x] is the argument value in position x.
Note that this starts at argv[0]; for a count of 3 arguments, that means argv[0], argv[1] and argv[2];
Still in the method, object-> will point to the actual instance of the object which the method was called on. In our example, that's %MySceneObject.
Then you call whatever you need from the C++ engine code as usual. Just make sure to convert the string arguments into the proper format.
For example,
F32 ArgumentOne = dAtof(argv[3]); object->callsomeMethod(ArgumentOne);
This will convert the string in the first passed argument to a float. dAtofb will convert to boolean, dAtoi to integer, etc.
And that value will be sent to the C++ method callsomeMethod.
Again, no amount of documentation can replace just messing around with the code.
#10
<edit - wrong author>
Get Edward Maurina's book - it covers this thoroughly....
02/21/2014 (4:20 pm)
Look at the examples from above:/*! Sets whether or not the texture is flipped vertically.
@param flipY Whether or not to flip the texture along the y (vertical) axis.
@return No return value.
*/
ConsoleMethodWithDocs(Sprite, setFlipY, ConsoleVoid, 3, 3, (bool flipY))
{
// Set Flip.
object->setFlipY( dAtob(argv[2]) );
}
//-----------------------------------------------------------------------------
/*! Gets whether or not the texture is flipped horizontally.
@return (bool flipX) Whether or not the texture is flipped along the x axis.
*/
ConsoleMethodWithDocs(Sprite, getFlipX, ConsoleBool, 2, 2, ())
{
return object->getFlipX();
}So, it's class name, method name, return type, min args, max args, (args). Note that the minimum value for a console method's min and max args is 2 (class and method names), for ConsoleFunctions it's 1 (just the function name).<edit - wrong author>
Get Edward Maurina's book - it covers this thoroughly....
#11
02/25/2014 (5:34 pm)
It seems that you cannot return a string in a script exposed function. How would you accomplish this? I see char* is there, but is that understood by the Torque script end? It seems it doesn't because when I echo the variable is is special characters and that's it.
#12
02/25/2014 (6:06 pm)
Of course you can return a string....ConsoleMethod(SceneObject, getArea, const char*, 2, 2, "() Gets the object's area.\n"
"@return (float x1/float y1/float x2/float y2) A space separated list of the lower left corner x and y position and the upper right corner x and y positions.")
{
// Fetch position and half-size.
const Vector2 position = object->getPosition();
const Vector2 halfSize = object->getHalfSize();
// -------------------------------------------------------------
// RIGHT HERE....
// -------------------------------------------------------------
// Create Returnable Buffer.
char* pBuffer = Con::getReturnBuffer(64);
// Format Buffer.
dSprintf(pBuffer, 64, "%g %g %g %g", position.x-halfSize.x, position.y-halfSize.y, position.x+halfSize.x, position.y+halfSize.y);
// Return Velocity.
return pBuffer;
// --------------------------------------------------------------
}Read ... read code ... code....
#13
04/04/2014 (3:43 pm)
edited: Fixed
Associate Simon Love
I ran into =>
My problem stemmed from not calling
DECLARE_CONOBJECT(Test);
in my .h file and
IMPLEMENT_CONOBJECT(Test);
in my .cpp file
Also make sure that your class inherits from SceneObject if you want to add it in the simulation.