Reference System Changes

This topic describes changes to 3ds Max's Reference System that affect existing plug-ins developed under Version 8 and earlier of the 3ds Max SDK.

ReferenceMaker::MakeRefByID() has been Deprecated

This function has been deprecated for public use. Use ReplaceReference() instead.

Also note the following:

It is extremely important to initialize a reference to NULL before a plug-in's first call to ReplaceReference().

Failure to do so will result in generally volatile behavior of 3ds Max.

Tests to ensure that references are set up correctly

There are 2 tests that can be enabled to ensure that plug-ins set up their references correctly. Both are executed when a plug-in calls ReplaceReference():

  1. The first test ensures that all references of a plug-in are initialized to NULL before it establishes its first reference. Whether to perform this check defaults to TRUE for Hybrid and Debug builds, and FALSE for Release builds. The 3DSMAX_REFCHECK_ENABLED environment variable can be used to override the default behavior. See the description of boolUtilityInterface::GetBoolEnvironmentVariable( TCHAR* pEnvVar, bool DefaultVal) for the values this environment variable can take.
  2. The second test ensures that all references of a plug-in have been set up correctly. This test can also detect "dangling" references - those that are non-NULL but point to non-existent reference targets. Whether to perform this check defaults to FALSE for all build configurations (Debug, Hybrid and Release). The 3DSMAX_REFCHECK_PARANOID_ENABLED environment variable can be used to override the default behavior. See the description of boolUtilityInterface::GetBoolEnvironmentVariable( TCHAR* pEnvVar, bool DefaultVal) for the values this environment variable can take.

ReferenceMaker::EnumDependents() has been Deprecated

This function has been deprecated for public use. Two new methods are provided for developers. If you want to call the built-in replacement for EnumDependents(), call DoEnumDependents(). If your plug-in needs to customize the default dependent enumeration, it can overwrite DoEnumDependentsImpl(). The behavior of DoEnumDependents guarantees that each ReferenceMaker is visited only once.

RemapDir& NoRemap() replaced by class DefaultRemapDir

The NoRemap() function, which returned a reference to a RemapDir has been removed. Its functionality has been replaced by a the class DefaultRemapDir whose constructor provides the same information.

IWeakReference renamed to IIndirectReference

See IIndirectRefMaker.h in which the class is declared and all symbols and methods renamed.

Indirect References Can Be Used Instead of Node Pointers

Many plug-in developers need to use circular reference hierarchies in their work. The problem caused by using node pointers to create circular references is that node pointers are not automatically saved and loaded by external reference (Xref) code, nor are they valid between 3ds Max sessions. Indirect references give developers a safe, official method for handling circular reference hierarchies. The following topics address these subject in more detail:

ReferenceMaker::IsRealDependency()

The default behavior of ReferenceMaker::IsRealDependency() continues to return TRUE so that references are, by default, real or strong. If IsRealDependency returns FALSE, the return value from ShouldPersistWeakRef (not ShouldPersistIndirectRef) is checked on file save. If it returns FALSE, we do not force the save of the RT.

The return values from IsRealDependency and ShouldPersistWeakRef are stored in the scene file. If we do a load of an RM where both are FALSE, the RT is not forced to load. If ShouldPersistWeakRef returns TRUE, and this ReferenceMaker is loaded or saved, the weak reference will be forced to be loaded or saved. If FALSE, the reference will not be forced to be loaded or saved, but will be hooked back up if it is loaded.

As before, any ReferenceMakers that hold a weak reference to the reference target will receive a REFMSG_TARGET_DELETED notification.