SOSELECTION(3iv)

✨ SoSelection(3IV) ✨

okay bestie, welcome to the SoSelection(3IV) man page. this is part 1 and it's giving very much "selection management but make it fashion". no cap. πŸ’…


πŸ’– NAME πŸ’–

SoSelection β€” manages a list of selected objects. literally the whole point. it's the node that keeps track of what's selected in your scene graph. iconic. πŸ‘‘


πŸ‘‘ INHERITS FROM πŸ‘‘

SoBase > SoFieldContainer > SoNode > SoGroup > SoSeparator > SoSelection

so it's got a whole lineage. main character energy inherited from way back. 🌈


🌸 SYNOPSIS 🌸

here's the code, bestie. keep it exact because we don't play with syntax. every typedef, enum, field, and method is in here. πŸŽ€

       #include <Inventor/nodes/SoSelection.h>

     typedef void        SoSelectionPathCB(void *userData, SoPath *path)
     typedef void        SoSelectionClassCB(void *userData, SoSelection *sel)
     typedef SoPath *    SoSelectionPickCB(void *userData, const SoPickedPoint
                              *pick)

     enum Policy {
          SoSelection::SINGLE  Left mouse pick on object clears selection, then
                                    selects object. Left mouse pick on nothing
                                    clears selection. Only one object may be
                                    selected at a time.
          SoSelection::TOGGLE  Left mouse pick on object toggles its selection
                                    status. Left mouse pick on nothing does
                                    nothing. Multiple objects may be selected.
          SoSelection::SHIFT   When shift key is down, selection policy is
                                    TOGGLE. When shift key is up, selection
                                    policy is SINGLE. Multiple objects may be
                                    selected.
     }

          Fields from class SoSelection:

     SoSFEnum            policy

          Fields from class SoSeparator:

     SoSFEnum            renderCaching
     SoSFEnum            boundingBoxCaching
     SoSFEnum            renderCulling
     SoSFEnum            pickCulling

          Methods from class SoSelection:

                         SoSelection()
                         SoSelection(int nChildren)
     static SoType       getClassTypeId()
     void                select(const SoPath *path)
     void                select(SoNode *node)
     void                deselect(const SoPath *path)
     void                deselect(int which)
     void                deselect(SoNode *node)
     void                toggle(const SoPath *path)
     void                toggle(SoNode *node)
     SbBool              isSelected(const SoPath *path) const
     SbBool              isSelected(SoNode *node) const
     void                deselectAll()
     int                 getNumSelected() const
     const SoPathList *  getList() const
     SoPath *            getPath(int index) const
     SoPath *            operator [](int i) const
     void                addSelectionCallback(SoSelectionPathCB *f, void
                              *userData = NULL)
     void                removeSelectionCallback(SoSelectionPathCB *f, void
                              *userData = NULL)
     void                addDeselectionCallback(SoSelectionPathCB *f, void
                              *userData = NULL)
     void                removeDeselectionCallback(SoSelectionPathCB *f, void
                              *userData = NULL)
     void                addStartCallback(SoSelectionClassCB *f, void *userData
                              = NULL)
     void                removeStartCallback(SoSelectionClassCB *f, void
                              *userData = NULL)
     void                addFinishCallback(SoSelectionClassCB *f, void
                              *userData = NULL)
     void                removeFinishCallback(SoSelectionClassCB *f, void
                              *userData = NULL)
     void                setPickFilterCallback(SoSelectionPickCB *f, void
                              *userData = NULL, SbBool callOnlyIfSelectable =
                              TRUE)
     void                setPickMatching(SbBool pickTwice)
     SbBool              getPickMatching() const

          Methods from class SoSeparator:

     static void         setNumRenderCaches(int howMany)
     static int          getNumRenderCaches()

          Methods from class SoGroup:

     void                addChild(SoNode *child)
     void                insertChild(SoNode *child, int newChildIndex)
     SoNode *            getChild(int index) const
     int                 findChild(const SoNode *child) const
     int                 getNumChildren() const
     void                removeChild(int index)
     void                removeChild(SoNode *child)
     void                removeAllChildren()
     void                replaceChild(int index, SoNode *newChild)
     void                replaceChild(SoNode *oldChild, SoNode *newChild)

          Methods from class SoNode:

     void                setOverride(SbBool state)
     SbBool              isOverride() const
     SoNode *            copy(SbBool copyConnections = FALSE) const
     virtual SbBool      affectsState() const
     static SoNode *     getByName(const SbName &name)
     static int          getByName(const SbName &name, SoNodeList &list)

          Methods from class SoFieldContainer:

     void                setToDefaults()
     SbBool              hasDefaultValues() const
     SbBool              fieldsAreEqual(const SoFieldContainer *fc) const
     void                copyFieldValues(const SoFieldContainer *fc, SbBool
                              copyConnections = FALSE)
     SbBool              set(const char *fieldDataString)
     void                get(SbString &fieldDataString)
     virtual int         getFields(SoFieldList &resultList) const
     virtual SoField *   getField(const SbName &fieldName) const
     SbBool              getFieldName(const SoField *field, SbName &fieldName)
                              const
     SbBool              isNotifyEnabled() const
     SbBool              enableNotify(SbBool flag)

          Methods from class SoBase:

     void                ref()
     void                unref() const
     void                unrefNoDelete() const
     void                touch()
     virtual SoType      getTypeId() const
     SbBool              isOfType(SoType type) const
     virtual void        setName(const SbName &name)
     virtual SbName      getName() const

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so SoSelection defines a node that you can insert into a scene graph, and it will generate and manage a selection list from picks on any node in the subgraph below it. nodes are selected based on a current selection policy. callback functions report back to the application when a path has been selected or deselected. the selection list can also be managed programmatically. πŸ’–

when handling events, SoSelection makes sure that the mouse release event was over the same object as the mouse press event before changing the list of selected objects. this allows users to mouse down on an object, change their mind and move the cursor off the object, then release the mouse button without altering the selection. so considerate. 😭

the selection can be highlighted automatically through the SoXtRenderArea, or the application can provide custom highlights. please see the chapter "Creating a Selection Highlight Style" in the Inventor Toolmaker. ✨


πŸŽ€ FIELDS πŸŽ€

  • SoSFEnum policy β€” selection policy that is followed in response to user interaction. this can be set to SoSelection::SINGLE, SoSelection::TOGGLE, or SoSelection::SHIFT. πŸ’…

✨ METHODS ✨

Bestie, here's the whole menu of stuff you can do with a SoSelection node. Every single one, no skips πŸ’…

  • SoSelection() β€” makes a selection node with all the default settings. Blank slate, main character energy ✨
  • SoSelection(int nChildren) β€” same vibe, but you get to tell it roughly how many children to expect. nChildren is approximate, it's not a hard limit, it's just a heads-up 🫢
  • static SoType getClassTypeId() β€” hands you back the type id for the SoSelection class. That's it, that's the whole job πŸ’–
  • void select(const SoPath *path) β€” selects the path you pass in by adding it to the selection list. The selection node must lie in that path, okay? The path gets copied and then truncated so the selection node ends up as the head of the path. And if the selection node isn't in the path at all? Nothing happens, the selection list stays exactly how it was. Also, heads up: this one straight up ignores the current selection policy. Periodt.
  • void select(SoNode *node) β€” selects the node you pass by building a path to it and then calling select(path) on that path. If there's more than one instance of node hanging out beneath the selection node, the path it builds is the first instance it finds. First come, first served, no cap.
  • void deselect(const SoPath *path) β€” deselects by yanking that path out of the selection list. Bye bestie πŸ‘‹
  • void deselect(int which) β€” deselects a path by removing it from the list. The which argument tells it which path in the list to remove.
  • void deselect(SoNode *node) β€” deselects the node by creating a path to it, then removing it from the selection list via deselect(path). Same deal as before: if node shows up more than once beneath the selection node, the path created is the first instance found.
  • void toggle(const SoPath *path) β€” flips the selection status of the path, like a little switch ✨ If it's in the selection list, it gets removed. If it's not in the list, it gets added. Chaotic but make it fashion.
  • void toggle(SoNode *node) β€” toggles the node by creating a path to it, then calling toggle(path). And yeah, you already know: multiple instances of node beneath the selection node means the created path is the first instance found.
  • SbBool isSelected(const SoPath *path) const β€” returns TRUE if the path you passed is selected, meaning it's sitting in the selection list. Simple as that πŸ’–
  • SbBool isSelected(SoNode *node) const β€” returns TRUE if the node is selected, by creating a path to it and then calling isSelected(). And once again β€” you guessed it β€” more than one instance of node under the selection node means the path created is the first instance found.
  • void deselectAll() β€” deselects every path in the selection list. Basically it clears the whole list. Clean slate, new era 🌈
  • int getNumSelected() const β€” returns how many paths are chillin' in the selection list.
  • const SoPathList *getList() const β€” returns the list of selected paths. The whole roster πŸ‘‘
  • SoPath *getPath(int index) const
  • SoPath *operator [](int i) const

β€” both of these return the i-th path in the selection list. Two ways in, same destination πŸ’«

  • void addSelectionCallback(SoSelectionPathCB *f, void *userData = NULL)
  • void removeSelectionCallback(SoSelectionPathCB *f, void *userData = NULL)

β€” the selection callbacks fire every time an object gets selected, whether that's from the user interacting with stuff or from a method call. And important detail: they're invoked after the object has been added to the selection list. Order matters, bestie.

  • void addDeselectionCallback(SoSelectionPathCB *f, void *userData = NULL)
  • void removeDeselectionCallback(SoSelectionPathCB *f, void *userData = NULL)

β€” the deselection callbacks fire every time an object gets deselected, again whether it's user interaction or a method call. These get invoked after the object has been removed from the selection list. Same rule, different direction.

  • void addStartCallback(SoSelectionClassCB *f, void *userData = NULL)
  • void removeStartCallback(SoSelectionClassCB *f, void *userData = NULL)

β€” the start callbacks fire when the user has kicked off an interactive change to the selection list (by picking objects, iykyk). What comes next? The select and/or deselect callbacks get invoked, and then finally each finish callback. A start callback is genuinely so useful for stuff like saving the current selection so you can restore it later β€” undo/redo vibes, iconic. BUT: the start callbacks are not called when the selection list gets changed programmatically. Nope, only for user-driven changes.

  • void addFinishCallback(SoSelectionClassCB *f, void *userData = NULL)
  • void removeFinishCallback(SoSelectionClassCB *f, void *userData = NULL)

β€” the finish callbacks fire when the user has finished interactively changing the selection list (by picking objects). Before this happened: each start callback got invoked, plus the select and/or deselect callbacks. And same caveat as start: the finish callbacks are not called when the selection list changes programmatically. Programmatic changes don't get the ✨experience✨.

  • void setPickFilterCallback(SoSelectionPickCB *f, void *userData = NULL, SbBool callOnlyIfSelectable = TRUE) β€” okay this one is the whole plot, so pay attention πŸ“

The pick filter callback gets invoked when a pick has happened and the selection node is about to change the selection list. Your callback function returns the path that the selection node should use when selecting and deselecting.

If no pick callback is registered (which is the default), the selection node just uses the path returned by SoPickedPoint::getPath() on the picked point associated with the event being processed.

The returned path should not be ref'd β€” selection will ref() and unref() it for you. (See SoPath::unrefNoDelete().)

Also note: a picked object may or may not be a child of the selection node. Doesn't matter β€” a selection node will only select paths that pass through it. That's the rule.

Possible return values from the callback, and what each one means:

  • [a] NULL β€” selection behaves as if nothing was picked (so for SINGLE and SHIFT policies, this clears the selection list). Handle event action traversal halts.
  • [b] Path β€” this path will be selected/deselected according to the selection policy, and it must lie under the selection node. Handle event action traversal halts.
  • [c] Path containing only the selection node β€” apply the selection policy as if nothing was picked. Handle event action traversal continues.
  • [d] Path not passing through the selection node β€” selection ignores this pick event entirely and no change is made to the selection list. Handle event action traversal continues.

A super simple way to tell selection to ignore the pick? Just return an SoPath with no nodes in it. Like this:

return new SoPath;

Selection will always ref() the path returned by the callback, make a copy of the path, and then unref() the path. Every time, no exceptions πŸ’€

Now about callOnlyIfSelectable β€” when it's TRUE, the pick callback function only gets invoked on picks that pass through the selection node. When it's FALSE, all picks get handed to the callback whether they pass through the selection or not. Choose wisely 🌸

  • void setPickMatching(SbBool pickTwice)
  • SbBool getPickMatching() const

β€” here's the tea: SoSelection will pick once on mouse down and once on mouse up, and it makes sure the two picks match before it changes the selection list. Why do we care? Because this lets the user pick down on an object, change their mind, drag off the object, release the mouse button, and the selection stays untouched. Self-care πŸ’…

Pass TRUE to enable this behavior. Pass FALSE to disable it β€” which means whatever gets picked on a mouse release is added to or removed from the selection list. And the default? Pick-matching is on. πŸ”₯


πŸ“ FILE FORMAT/DEFAULTS πŸ“

Here's exactly what a default Selection node looks like, verbatim bestie:

Selection {
   renderCaching       AUTO
   boundingBoxCaching  AUTO
   renderCulling       AUTO
   pickCulling         AUTO
   policy              SHIFT
}

πŸ‘€ SEE ALSO πŸ‘€

Go check these out when you're done here, they're all part of the same friend group:

  • SoEventCallback
  • SoXtRenderArea
  • SoBoxHighlightRenderAction
  • SoLineHighlightRenderAction

And that's the whole page, babe πŸŽ€ This was SoSelection(3IV) from the SGI/Inventor docs β€” that's the source and version tag, and it's dated with that classic page footer timestamp. You made it to the end, I'm so proud of you, go select something iconic πŸ’–βœ¨