Game Development Community

A bug! or atleast something that shouldn't be possible....

by Vince Gee · in Torque 3D Professional · 08/01/2013 (1:33 pm) · 8 replies

Ok,

I was doing some digging and I realized that guiTreeViewCtrl.cpp has a console method defined as

ConsoleMethod( GuiTreeViewCtrl, sort, void, 2, 6, "( int parent, bool traverseHierarchy=false, bool parentsFirst=false, bool caseSensitive=true ) - Sorts all items of the given parent (or root).  With 'hierarchy', traverses hierarchy." )

But the class is derived from SimSet right?

Well SimSet has a console method defined in it

ConsoleMethod( SimSet, sort, void, 3, 3, "( string callbackFunction ) Sort the objects in the set using the given comparison function.n"
   "@param callbackFunction Name of a function that takes two object arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." )

So which sort is used when you call sort on a GuiTreeViewCtrl since they have the same signature? And if I called sort w/ 1 parameter which sort would it call? What if I wanted to call the other sort?

****Hurts my widdle head****

Vince

#1
08/01/2013 (1:57 pm)
Eek found another one..

GuiFilterCtrl.cpp which is based off of GuiControl has a console method defined as

ConsoleMethod( GuiFilterCtrl, setValue, void, 3, 20, "(f1, f2, ...)"
              "Reset the filter to use the specified points, spread equidistantly across the domain."
			  "@internal")


GuiControl has a DefineEngineMethod for setvalue

DefineEngineMethod( GuiControl, setValue, void, ( const char* value ),,
   "Set the value associated with the control.\n"
   "@param value The new value for the control.\n" )

If I call it w/ just one parameter, which one does it use?
#2
08/01/2013 (2:04 pm)
Wait... that's not all

guiInstpectorTypes has a console method defined as

ConsoleMethod( GuiInspectorTypeFileName, apply, void, 3,3, "apply(newValue);" )

But... the class is derived from field.cpp which also has it defined as

ConsoleMethod( GuiInspectorField, apply, void, 3, 4, "( string newValue, bool callbacks=true ) - Set the field's value. Suppress callbacks for undo if callbacks=false." )
#3
08/01/2013 (2:14 pm)
I wish I was done...

guiPopUpCtrl has

ConsoleMethod( GuiPopUpMenuCtrl, add, void, 3, 5, "(string name, int idNum, int scheme=0)")

but is derived from simSet which also has it defined

ConsoleMethod( SimSet, add, void, 3, 0,
   "( SimObject objects... ) Add the given objects to the set.\n"
   "@param objects The objects to add to the set." )
#4
08/01/2013 (2:17 pm)
Since ambiguity is so rampant in this engine, I am starting to think that there is a "new" functionality going on here. As in, when a derived class redefines a previously existing function it overwrites the entry point. So any console method defined on the base object become inaccessible to the derived object's ability to call through the console.

That or no one ever gave a crap about it cause it "kinda" worked. Who cares about performance.....

Hope someone knows the answer.
#5
08/01/2013 (2:24 pm)
This works as designed. When using a method the TorqueScript subsystem resolves the call by looking up the method in the object's defined methods then through the parent class methods and all the way up to the base class methods. If none match then you get an error like so:
==>2007.doesnotexist();
<input> (0): Unknown command doesnotexist.
  Object (2007) GuiButtonCtrl -> GuiButtonBaseCtrl -> GuiControl -> SimGroup -> SimSet -> SimObject
It says it looked up GuiButtonCtrl then GuiButtonBaseCtrl then etc.. until hitting the last class in the hierarchy SimObject.

You have to keep in mind that TorqueScript was designed to be as simple as C but with some C++ classes support and that includes methods acting as virtual functions in the lookup.
#6
08/01/2013 (2:26 pm)
Ok, so it is doing what I thought, it allows you to re-define a console method in a later derived class.

and there would be no way to call the function from a parent class from the derived object unless the parameters didn't match.

Correct?
#7
08/03/2013 (2:07 am)
Umm, maybe not.

You could try this:
$object = new GuiTreeViewCtrl(); // with whatever is needed to make it
SimSet::sort($object, < other params >);
You just have to give it the equivalent of the 'this' pointer if I remember right.

Also, C++ does the exact same thing with virtual functions. It has to decide at 'runtime' which function to call. This can get really expensive when you have multiple or diamond inheritance. Now, this may have changed as compilers have gotten smarter, but I think some of this is still going on.

I have found out some interesting things about packages as well. If you look at the documentation in the Torque Script Manual it says it will unregister packages higher up in the chain if you unregister one in between. However, it doesn't do it. At least what I tested did not do it. The function I was testing continued to call the last registered package, even though one in between was unregistered. Then I unregistered the last package and the intermediate one was gone as expected. So that documentation about Packages in the script manual is not correct. If someone wants to test this I can rig up a test script for you. I will have to do this to get the docs changed anyway.
#8
08/03/2013 (8:19 am)
You could also use the Parent namespace if you're inside a function of the object in question and want to do the override, something like:

%object = new GuiTreeViewCtrl(); // with whatever is needed to make it  
%object.doSort();

function GuiTreeViewCtrl::doSort(%this)
{
   Parent::sort(%this, < other params >); 
}


Interesting on the package inheritance stuff Demo, I hadn't messed with packages much yet myself, so I hadn't run into that. Something to take note of/track down eventually.