Namespace help. i want to be like GuiControls.
by Orion Elenzil · in Torque Game Engine · 07/25/2006 (11:52 am) · 7 replies
Hey all.
so here's a weirdness.
GuiControl inherits like this:
GuiControl -> SimGroup -> SimSet -> SimObject
but GuiControl has a really useful script namespace capability which it's not getting from its parents.
the following code:
produces this output:
.. basically it works for GuiControl, but not for its parents.
is there a simple answer here ?
.. aha,
the answer to that is no.
i'm pretty sure it has to do with GuiControl's onAdd:
.. i'm looking at including that in my SimObject-derived class now.
more to come.
so here's a weirdness.
GuiControl inherits like this:
GuiControl -> SimGroup -> SimSet -> SimObject
but GuiControl has a really useful script namespace capability which it's not getting from its parents.
the following code:
function testNamespace()
{
new GuiControl(myGuiControl);
new SimGroup(mySimGroup);
new SimObject(mySimObject);
myGuiControl.func1();
mySimGroup.func1();
mySimObject.func1();
}
function myGuiControl::func1(%this)
{
echo("guicontrol!");
}
function mySimGroup::func1(%this)
{
echo("simgroup!");
}
function mySimObject::func1(%this)
{
echo("simobject!");
}produces this output:
[7/25/06 11:32:16][Inf] ==>testNamespace(); [7/25/06 11:32:16][Inf] guicontrol! [7/25/06 11:32:16][Err] dev/testNamespace.cs (8): Unknown command func1. [7/25/06 11:32:16][Err] Object mySimGroup(7720) SimGroup -> SimSet -> SimObject [7/25/06 11:32:16][Err] dev/testNamespace.cs (9): Unknown command func1. [7/25/06 11:32:16][Err] Object mySimObject(7721) SimObject
.. basically it works for GuiControl, but not for its parents.
is there a simple answer here ?
.. aha,
the answer to that is no.
i'm pretty sure it has to do with GuiControl's onAdd:
bool GuiControl::onAdd()
{
if(!Parent::onAdd())
return false;
const char *name = getName();
if(name && name[0] && getClassRep())
{
Namespace *parent = getClassRep()->getNameSpace();
if(Con::linkNamespaces(parent->mName, name))
mNameSpace = Con::lookupNamespace(name);
}
Sim::getGuiGroup()->addObject(this);
Con::executef(this, 1, "onAdd");
return true;
}.. i'm looking at including that in my SimObject-derived class now.
more to come.
About the author
#2
I dont think you want to do it with a ConsoleMethod. Putting it in SimObject is similarly probably not a good idea. If you have objects deriving from SimObject that you want to have that functionality, just move the ScriptObject class def into a header and derive from ScriptObject instead. If you have a class derived from something other then SimObject directly and can't change the hierachy that far up then use the gank-from-ScriptObject method.
Note that datablocks derived from GameBaseDatablock (e.g. pretty much all of them) already do some namespace linkage (just class, not superclass). I think GameBase may do so too, but I'm not 100% sure without checking. GameBase seems like a good place to do it, though, for game objects.
T.
07/25/2006 (12:19 pm)
Have a look at the code for ScriptObject. To get the script namespace linking you can just gank ScriptObject::onAdd() and onRemove() as well as the two persist fields. That's probably better (or at least, easier) then ganking it from GuiControl.I dont think you want to do it with a ConsoleMethod. Putting it in SimObject is similarly probably not a good idea. If you have objects deriving from SimObject that you want to have that functionality, just move the ScriptObject class def into a header and derive from ScriptObject instead. If you have a class derived from something other then SimObject directly and can't change the hierachy that far up then use the gank-from-ScriptObject method.
Note that datablocks derived from GameBaseDatablock (e.g. pretty much all of them) already do some namespace linkage (just class, not superclass). I think GameBase may do so too, but I'm not 100% sure without checking. GameBase seems like a good place to do it, though, for game objects.
T.
#3
I looked at ScriptObject::onAdd() and it seems to be doing more than the minimum for what i want,
and in fact the part of ScriptObject::onAdd() which i want in particular really just boils down to what GuiControl::onAdd() does.
hmm, why not ?
again with the hmm, why not ?
it seems to be working well,
and by putting it in SimObject i can extend this functionality to existing class instances such as SimSets, SimGroups, MessageVector, etc.
with the addition of SimObject::allowInstanceMethods(), this sample code:
yields these results:
.. which is what i want.
for them as are interested, i submitted a resource with this stuff here.
07/25/2006 (1:23 pm)
Hey Tom - many thanks for the reply.I looked at ScriptObject::onAdd() and it seems to be doing more than the minimum for what i want,
and in fact the part of ScriptObject::onAdd() which i want in particular really just boils down to what GuiControl::onAdd() does.
Quote:
I dont think you want to do it with a ConsoleMethod.
hmm, why not ?
Quote:
Putting it in SimObject is similarly probably not a good idea.
again with the hmm, why not ?
it seems to be working well,
and by putting it in SimObject i can extend this functionality to existing class instances such as SimSets, SimGroups, MessageVector, etc.
with the addition of SimObject::allowInstanceMethods(), this sample code:
function testNamespace()
{
new SimObject(mySimObject);
new SimObject(mySimObject2);
new GuiControl(myGuiControl);
mySimObject2.allowInstanceMethods();
mySimObject.func1();
mySimObject2.func1();
myGuiControl.func1();
}
function mySimObject::func1(%this)
{
echo("mySimObject func1()");
}
function mySimObject2::func1(%this)
{
echo("mySimObject2 func1()");
}
function myGuiControl::func1(%this)
{
echo("myGuiControl func1()");
}yields these results:
[7/25/06 13:15:28][Inf] ==>testNamespace(); [7/25/06 13:15:28][Err] dev/testNamespace.cs (9): Unknown command func1. [7/25/06 13:15:28][Err] Object mySimObject(5762) SimObject [7/25/06 13:15:28][Inf] mySimObject2 func1() [7/25/06 13:15:28][Inf] myGuiControl func1()
.. which is what i want.
for them as are interested, i submitted a resource with this stuff here.
#4
@Tom: I think Orion's usage of this is primarily from script code and not necessarily from a derived SimObject class within the engine. That's why he might be putting it at the SimObject level.
@Orion: now I don't know, but what would happen if we called allowInstanceMethods twice on an object? You might want to confirm that it works properly
07/25/2006 (1:51 pm)
Your approach is good. I can see why you might want to do this. I like the fact you didn't add this logic right into SimObject::onAdd(). You provided a consolemethod so basically the user is able to pick & choose which objects has this capability. Using ScriptOjbect as a reference would given u the capability of using two higher class names (super and just class). If you didn't want to expose this, and just wanted the minimum, then it's cool what you've done. At first wehn I read this resource it made no sense to me. But then I realized all that you were trying to achieve was "introducing namespace'ing to SimObjects". I think the title of your resource is a little confusing personally. @Tom: I think Orion's usage of this is primarily from script code and not necessarily from a derived SimObject class within the engine. That's why he might be putting it at the SimObject level.
@Orion: now I don't know, but what would happen if we called allowInstanceMethods twice on an object? You might want to confirm that it works properly
#5
Exposing the functionality to script as a ConsoleMethod is doing stuff in script that should be done in C++. There is probably no technical reason why you can't do it, but it screams bad practice.
Implementing the namespaces on SimObject will force every Torque object that's exposed to script to use it. This may have undesired side effects since some classes lower down the inheritance tree already do it. The way I suggested you do it limits the impact on the rest of the codebase and the side effects, if any, are more controllable.
Also, there is already a ScriptGroup (not sure on sets) that is a SimGroup with the script namespace stuff from ScriptObject. It's at the end of scriptObject.cc if I remember correctly.
At the end of the day though, it's your codebase and you can do whatever you want. However, I don't think that recommending it as a good solution for everybody is a good idea. If I wasnt busy I'd write up a better critique, but I'm sure Ben or someone will be along at some point to fill in the gaps ;-)
T.
07/25/2006 (2:01 pm)
@Orion,Exposing the functionality to script as a ConsoleMethod is doing stuff in script that should be done in C++. There is probably no technical reason why you can't do it, but it screams bad practice.
Implementing the namespaces on SimObject will force every Torque object that's exposed to script to use it. This may have undesired side effects since some classes lower down the inheritance tree already do it. The way I suggested you do it limits the impact on the rest of the codebase and the side effects, if any, are more controllable.
Also, there is already a ScriptGroup (not sure on sets) that is a SimGroup with the script namespace stuff from ScriptObject. It's at the end of scriptObject.cc if I remember correctly.
At the end of the day though, it's your codebase and you can do whatever you want. However, I don't think that recommending it as a good solution for everybody is a good idea. If I wasnt busy I'd write up a better critique, but I'm sure Ben or someone will be along at some point to fill in the gaps ;-)
T.
#6
thanks again for putting thought into this.
I guess i disagree on whether it should be exposed to script or not. Maybe if we ever meet up in person we can have a thumb war or something to figure it out properly.
Note that i'm *not* doing this for every SimObject,
i'm merely giving every SimObject the option of doing it.
Lateral -
thanks also for your thoughts.
good idea on testing it twice.
I tried it out and confirmed that the second time thru, the nameSpace list is unchanged.
ie:
(note that SimObject::getNamespaceList() is custom)
07/25/2006 (2:12 pm)
Hey Tom -thanks again for putting thought into this.
I guess i disagree on whether it should be exposed to script or not. Maybe if we ever meet up in person we can have a thumb war or something to figure it out properly.
Note that i'm *not* doing this for every SimObject,
i'm merely giving every SimObject the option of doing it.
Lateral -
thanks also for your thoughts.
good idea on testing it twice.
I tried it out and confirmed that the second time thru, the nameSpace list is unchanged.
ie:
==>new simObject(foo); ==>echo(foo.getNamespaceList()); SimObject ==>foo.allowInstanceMethods(); ==>echo(foo.getNamespaceList()); foo -> SimObject ==>foo.allowInstanceMethods(); ==>echo(foo.getNamespaceList()); foo -> SimObject
(note that SimObject::getNamespaceList() is custom)
#7
I've had the misfortune to have to debug a bunch of script namespace related issues recently and so I'm painfully aware of how much of a pain in the arse it is to track down problems with namespace linkage. Exposing the mechanics behind it to script increases the chances of that happening. That was my thinking behind not recommending it as a solution for everybody. When it's just your own codebase then obviously you know what you're doing with it and so problems are easier to track down, and thus it doesnt really matter what you do.
I think I must have misread you on the all objects thing. That said, it would be nice if the class / superClass / namespaces etc were consistent across the whole engine. Then this would be a non-issue. But, as I mentioned, whilst implementing that is easy in theory, the knock on effects can be hard to track down and fix.
Just random thoughts. Currently on a break and my head is full of other code ;)
T.
07/25/2006 (3:05 pm)
Orion,I've had the misfortune to have to debug a bunch of script namespace related issues recently and so I'm painfully aware of how much of a pain in the arse it is to track down problems with namespace linkage. Exposing the mechanics behind it to script increases the chances of that happening. That was my thinking behind not recommending it as a solution for everybody. When it's just your own codebase then obviously you know what you're doing with it and so problems are easier to track down, and thus it doesnt really matter what you do.
I think I must have misread you on the all objects thing. That said, it would be nice if the class / superClass / namespaces etc were consistent across the whole engine. Then this would be a non-issue. But, as I mentioned, whilst implementing that is easy in theory, the knock on effects can be hard to track down and fix.
Just random thoughts. Currently on a break and my head is full of other code ;)
T.
Associate Orion Elenzil
Real Life Plus
that worked.
going now to implement a new ConsoleMethod in SimObject along the lines of "extendNamespace()"
which will simply do the above.
presuming i can get it to work,
does anyone know a reason why this would be undesirable ?