The following is a list of best practices regarding usage of the reference system:
- Make sure you choose correctly between storing a pointer or a reference in your plug-in to a scene entity. Storing a pointer
to a scene entity is seldom safe because the pointer could become invalid if the scene entity is deleted and your plug-in
fails to update the pointer. Although pointers to scene entities could be used as local variables in plug-in member functions,
they should not be cached as plug-in data members and their life span should be as short as possible.
For information on converting pointers to weak or indirect references see Using Indirect References Instead of Pointers.
References can be stored as plug-in member variables but it is the plug-in's responsibility to properly implement their management,
so that they do get updated, do not prevent the dependent entity to be destroyed, etc.
- When observing nodes always use weak references instead of strong references. This is because nodes can be deleted by the
user.
- Make sure you choose the right type of reference your plug-in needs to create to a scene entity it depends on. See the topic
Choosing the Kind of Reference for more information.
- Never store pointers to scene nodes as plug-in data members because they can be invalidated at any time (e.g. due to the
user deleting them). Use a node monitor instead (INodeMonitor or INodeTransformMonitor).
- A plug-in's implementation of ReferenceMaker::SetReference() should always assign the ReferenceTarget passed in by the caller to the corresponding plug-in data member, as opposed to implementing its own logic to update that
reference.
- A plug-in that needs to maintain a variable number of references, should use the class IRefTargContainer.
- In order to allow 3ds Max to manage the life-time of your plug-in instances, the plug-in would not override Animatable::DeleteThis() or ReferenceTarget::AutoDelete(). When a plug-in needs to behave as a singleton, it should overwrite ReferenceTarget::AutoDelete() to return REF_SUCCEED. In this case, the plug-in should take care of deleting itself its sole instance since 3ds Max will not be able to do it.
- Do not call the delete operator on a pointer to an object derived from Animatable or any of its sub-classes. For more information see Manual Deallocation of Referenced Objects.
- For managing one single reference, a plug-in should consider using an instance of class SingleRefMaker or class SingleWeakRefMaker.
- Initialize ReferenceTarget pointers to NULL before the first call to ReferenceMaker::ReplaceReference(). This should be done in the member initialization list of the constructor.
- When receiving a REFMSG_TARGET_DELETED message a ReferenceMaker should always set its reference to the ReferenceTarget instance being deleted to NULL.
- If the plug-in wishes to delete itself in response to REFMSG_TARGET_DELETED, it should return REF_AUTO_DELETE from its implementation of ReferenceMaker::NotifyRefChanged().
- Never call ReferenceMaker::SetReference(), always call ReferenceMaker::ReplaceReference() instead.
- Use Animatable::GetAnimByHandle() and compare the result to NULL to verify that an animatable (or ReferenceTarget) pointer is valid.
- If appropriate call ReferenceMaker::DeleteAllRefs() in the destructor of a plug-in that derives from reference maker, to assure that all references are deleted. Normally if
an object is deleted correctly then this shouldn't be necessary.
- Send reference messages sparingly. They can slow down the system. For example if a large number of changes are made to a
plug-in at once, then the plug-in should try to send only a single REFMSG_CHANGE message for the set of changes.
- When setting ReferenceTarget pointers to NULL in repsonse to REFMSG_TARGET_DELETED, be sure to only assign one pointer to the ReferenceTarget to NULL in the case that you have multiple references to the same target.
- A reference maker should support the setting of NULL references for any of its reference indexes.