As the documentation says, you should call
drop() if you
grab() or if you called a
create...() function. It doesn't say what to do if you allocate an object with
new, but what you should do is pretty easy to figure out.
In the normal usage you would see code like this...
Code: Select all
ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(...);
node->addAnimator(anim);
anim->drop();
The first like creates an animator on the heap with a call to
new and returns a pointer to it. You can see the source for this
here. If you inspect
anim with a debugger, you should see that the reference count is 1 just before the
addAnimator() call.
The
addAnimator() call adds the animator to the scene nodes animator list and calls
grab() on the animator. Now the reference count is 2.
Finally we call
drop() on our pointer. The reference count will fall to 1. At this point, the scene node is the owner of the animator. If the animator is removed from the scene node with
removeAnimator(), it will call
drop() [it must because it called
grab() in
addAnimator()]. This will drop the reference count to 0 and the animator will delete itself.
Suppose that I've written my own animator,
MySceneNodeAnimator. When I create an instance of my animator on the heap, it is exactly the same as calling
create....() for one of the other animator types. The reference count will initially be set to 1.
So, when you create an object that inherits from
IUnknown [which should actually be
CRefCounted], the initial reference count is 1. When you are done with the object, you should
drop() it. If you pass a pointer to your object to another class, that class should
grab() the pointer when it takes control of the object, and it should
drop() that pointer when it is done with the object.
Your code is a special case. You are trying to remove/drop yourself.
As mentioned, you only
drop() if you
grab() or you created the object with a call to a
create...() function. We also know we should
drop() if we called
new to allocate an object instance ourselves.
If you look at the code for your animator, I seriously doubt that you are calling
grab(). That would be a really weird thing to do, and it could cause your object to remain in memory forever [it holds a reference to itself]. I know that your animator didn't allocate itself with
new or
create...() either because that is physically impossible. So you should not call
drop().
There is one other thing that you should be careful about. If you do something that could cause the object to be deleted, you should not access any of the member data of that object after that point. The following would be an example of this...
Code: Select all
void MySceneNodeAnimator::animateNode(ISceneNode* node, u32 timeMs)
{
//...
if (m_finished)
{
node->removeAnimator(this);
m_finished = false; // very bad!!!
}
}
If the call to
removeAnimator() resulted in the deletion of the scene node, you would be writing to memory that you no longer own. That would be roughly equivalent to this...
Code: Select all
int* ip = new int(5);
delete ip;
*ip = 10; // boom
Now the factory question. The reason you would want to create a factory would be so that you can register the factory with the scene manager. The scene manager would be able to create your derived animator type without knowing anything about it other than having a pointer to a factory. This will make it possible for you to load up a .irr scene file that has scene nodes with your animator already attached to them.
Unfortunately, this isn't incredibly useful at the moment. IrrEdit doesn't support add-ins, so there is no way to be able to use IrrEdit to add your animators to scene nodes. You can open up an existing .irr file with a text editor and add the appropriate entries.
Travis