Public Member Functions

MultiSelectCallback Class Reference

Search for all occurrences

Detailed Description

This is the callback object used to perform the [de]selection via Animatable:: SvGetMultiSelectCallback().

Schematic view supports multiple selection. When the user selects a set of objects in the schematic view and then "transfers" that selection set to the rest of max (either by having "synchronize selection" on or by manually moving the selection out), there are a number of ambiguities that can arise. For example, some of the objects in the schematic view cannot be selected in the viewports, material editor, or modifier stack. Another example: the material editor only supports one active material/map but many materials and maps can be selected simultaneously in the schematic view. The "MultiSelectCallback" system exists order to handle these cases and to handle selection synchronization between SV and future editors in 3ds Max. When the schematic view attempts to synchronize selection by moving the SV selection set to the "outside" world, it follows this procedure:

1. First SV calls SvGetMultiSelectCallback() on all the visible SV nodes to "collect" MultiSelectCallback objects. Objects that want to synchronize their selection state with the schematic view (not a common or trivial operation -- this is really more associated with adding a new editor in 3ds Max rather than adding new plug-in) return a pointer to a static instance of a MultiSelectCallback derived object. There is only one instance of a MultiSelectCallback per editor. Furthermore, if an editor displays objects of many classes, all the classes should override SvGetMultiSelectCallback() to return the same MultiSelectCallback instance. This implies that, as far as the schematic view is concerned, there is never more than one primary editor class associated with any particular object class (currently, viewports for nodes, material editor for materials and maps and the modifier panel for modifiers). For example, here is the code in BaseNode that returns the MultiSelectCallback instance for nodes (this is the MultiSelectCallback used for viewports):

class BaseNodeMSelCB : public MultiSelectCallback
{
    private:
        bool clear;
        BaseNodeTab selNodeTab;
        BaseNodeTab deselNodeTab;

        int Priority() { return 1000; }
        void Begin(IGraphObjectManager *gom, bool clear);
        void Select(IGraphObjectManager *gom, IGraphNode *gNode, bool isSelected);
        void End(IGraphObjectManager *gom);
};
static BaseNodeMSelCB baseNodeMSelCB;
MultiSelectCallback* BaseNode::SvGetMultiSelectCallback(IGraphObjectManager *gom, IGraphNode *gNode)
{
    return &baseNodeMSelCB;
}

2. For each selection class (unique MultiSelectCallback instance), the schematic views calls "Begin()". This is the spot where any "pre-selection" preparation takes place. The order that the MultiSelectCallback instances are called in is determined by their priority. The priority is returned by the "Priority()" method. MultiSelectCallback's with a higher priority (lower value) are called before those with a lower priority (higher value). For example, here is the Begin associated with the viewports:

void BaseNodeMSelCB::Begin(IGraphObjectManager *gom, bool clear)
{
    this->clear = clear;
//
// If the "clear" bool is true, the current viewport selection set is cleared...
//
        if (clear)
        GetActiveSelSet()->Clear(FALSE);
//
// Some housekeeping in preparation for the select...
//
    selNodeTab.Resize(0);
    deselNodeTab.Resize(0);
}

3. For each of objects in the schematic view whose selection state is changing, the object's MultiSelectCallback instance is retrieved (again) and the "Select" method is called. Here is where the actual selection/de-selection work can take place. I say "can" because, in practice, the select method usually just collects all the objects to be selected and all the objects to be deselected into lists which are then processed in the "End()" method. This is simply for performance -- it is often more efficient to set the selection state of a group of objects all at once. Here's the "Select()" method from BaseNode:

void Select(IGraphObjectManager *gom, IGraphNode *gNode, bool isSelected)
{
    BaseNode *baseNode = (BaseNode *) gNode->GetAnim();

    if (isSelected) {
        if (!baseNode->IsRootNode() && !baseNode->IsFrozen()
            && !baseNode->IsHidden())
            selNodeTab.AppendNode(baseNode, FALSE);
    }
    else {
        if (baseNode->Selected())
            deselNodeTab.AppendNode(baseNode, FALSE);
    }
}

4. Finally, for each selection class (unique MultiSelectCallback instance), the schematic views calls "End()". This is the spot where any "post-selection" operations take place. For example, here is the "End()" for the BaseNode (viewports):

void End(IGraphObjectManager *gom)
{
    if (selNodeTab.Count() > 0 || deselNodeTab.Count() > 0) {
        theHold.Begin();
        if (selNodeTab.Count() > 0)
            GetActiveSelSet()->SelectMultiple(selNodeTab, FALSE);

        if (deselNodeTab.Count() > 0)
            GetActiveSelSet()->DeselectMultiple(deselNodeTab, FALSE);

        theHold.Accept(getResMgr().getString(IDS_SV_SELECT, appInst));
        RedrawViewports(GetCOREInterface()->GetTime(), VP_DONT_SIMPLIFY);
    }
    else {
        if (clear)
            RedrawViewports(GetCOREInterface()->GetTime(), VP_DONT_SIMPLIFY);
    }
}
See also:
Animatable

#include <svcore.h>

Inheritance diagram for MultiSelectCallback:
Inheritance graph
[legend]

List of all members.

Public Member Functions

virtual  ~MultiSelectCallback ()
virtual int  Priority ()=0
  Returns the priority of the callback.
virtual void  Begin (IGraphObjectManager *gom, bool clear)=0
  Called to begin the multi-selection process.
virtual void  Select (IGraphObjectManager *gom, IGraphNode *gNode, bool isSelected)=0
  Selects or de-selects the node passed.
virtual void  End (IGraphObjectManager *gom)=0
  Called when done.

Constructor & Destructor Documentation

virtual ~MultiSelectCallback ( ) [inline, virtual]
{}

Member Function Documentation

virtual int Priority ( ) [pure virtual]

Returns the priority of the callback.

MultiSelectCallback's with a higher priority (lower value) are called before those with a lower with a higher priority (lower value) are called before those with a lower priority (higher value).

virtual void Begin ( IGraphObjectManager gom,
bool  clear 
) [pure virtual]

Called to begin the multi-selection process.

This is the spot where any "pre-selection" operations take place.

Parameters:
gom - Points to the schematic view window manager.
clear - true to clear the previous selection; false to leave intact.
virtual void Select ( IGraphObjectManager gom,
IGraphNode gNode,
bool  isSelected 
) [pure virtual]

Selects or de-selects the node passed.

Parameters:
gom Points to the schematic view window manager.
gNode Points to the node in schematic view.
isSelected true if select; false if deselect.
virtual void End ( IGraphObjectManager gom ) [pure virtual]

Called when done.

! This is the spot where any "post-selection" operations take place.

Parameters:
gom Points to the schematic view window manager.

MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback
MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback MultiSelectCallback