HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OP3D_InputSelector.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: OP3D_InputSelector.h
7  *
8  * COMMENTS:
9  * This descendant of BM_InputSelector knows about the viewer. It uses
10  * the viewer to find out display/current sop and to use the viewer's
11  * selection type buttons.
12  */
13 
14 #ifndef __OP3D_InputSelector_h__
15 #define __OP3D_InputSelector_h__
16 
17 #include "OP3D_API.h"
18 #include "OP3D_InputSelectorBase.h"
19 #include "OP3D_SelectionManager.h"
20 #include "OP3D_GUSelectionSet.h"
21 #include <UI/UI_HotkeyHelper.h>
22 #include <OP/OP_DataTypes.h>
23 #include <PI/PI_ClassManager.h>
24 #include <GEO/GEO_PrimTypeCompat.h>
25 #include <GU/GU_SelectionSet.h>
27 #include <UT/UT_Rect.h>
28 #include <UT/UT_Map.h>
29 
30 class GU_SelectResult;
31 class GUI_DisplayOption;
32 class OP_Network;
33 class OP3D_InputSelectorUndoWorker;
34 class OP3D_EdgeLoopHelper;
35 class OP3D_PatternSelectHelper;
36 class SOP_Node;
37 class GA_Attribute;
38 
39 typedef bool (*OP3D_ValidForPickFilter)(void *data, GUI_DetailLook *look);
40 
42 {
47 };
48 
50 {
52  myGeoIndex(-1), myOpId(-1),
53  myIsSelectionSetOwner(false),
54  myIsSelected(false), myIsLocalScope(true) {}
55 
57  { return mySelectionSet->selection(myActiveType); }
59  { return myActiveType; }
60 
61  void updateProxy(GU_SelectionHandle sel, bool create);
62  GUI_DetailLook *getLook() const;
63 
64 
66  int myOpId;
67  // The index within the geolook.
68  // TODO: The DOP data name is probably more useful.
70 
73 
74  // The auto converted selection is set if we had to convert to an allowed
75  // selection type in selectorFinished() and should be cleared whenever we
76  // respond to a selection type change event.
78 
81 
82  // Proxy which represents the binding between the GUI_DetailLook and
83  // our selection. Manages our reference to the GUI_DetailLook, and
84  // the look's reference to the active selection.
86 
90 };
91 
93 {
94 public:
95 
96  OP3D_InputSelector(OP3D_View &viewer, PI_SelectorTemplate &templ);
97  ~OP3D_InputSelector() override;
98 
99  const char *className() const override;
100 
101  // This selector has the ability to locate components.
102  int hasLocates() const override
103  { return 1; }
104 
105  // The selector handles mouse events and modifies the selection
106  // accordingly. Return 1 if the event was consumed and 0 otherwise.
107  int handleMouseEvent(UI_Event *event) override;
108 
109  // Handle double-click events. Returns true if handled.
110  bool handleDoubleClickEvent(UI_Event *event) override;
111 
112  void getKeyResolveInfo(UI_KeyResolveInfo &info) override;
113 
114  // Selectors respond to keyboard events to know when to finish a selection
115  // stage and possibly enter the next.
116  int handleKeyEvent(int key, UI_Event *event,
117  DM_Viewport &viewport) override;
118  bool handleTransitoryKey(const UI_Event &event,
119  int hotkey_id) override;
120  bool willHandleKeyEvent(int key, UI_Event *event);
121 
122  // Is the selector required to attach an input node to the current
123  // node? If it is but nothing was selected, an empty model sop will
124  // be attached. By default, an input is not required.
125  bool inputRequired() const { return myInputRequiredFlag; }
126  void setInputRequired(bool onoff)
127  { myInputRequiredFlag = onoff; }
128 
129  // Some sops (eg. group and delete) need a '*' in the input field if
130  // everything is selected. Other sops will operate on everything if
131  // the input field is blank.
133  { return myUseAsteriskToSelectAll; }
134  void setUseAsteriskToSelectAll(bool onoff)
135  { myUseAsteriskToSelectAll = onoff;}
136 
137  // Specifies whether or not to use primitive id's when selecting edges.
138  // This setting allows the selector to distinguish between a general edge
139  // (e.g p0-1) and an edge on a primitive (e.g. 0e1)
140  void setUsePrimsInEdgeSelections(bool use_prims)
141  { myUsePrimsInEdgeSelectionFlag = use_prims; }
142 
143  // Specifies whether the selector can guess and return edge rings based
144  // on the choice of end elements or should always stick to edge loops.
145  void setAllowEdgeRingSelection(bool allow)
146  { myAllowEdgeRingSelection = allow; }
147 
148  // Specifies whether the selector can guess and return edge rings based
149  // on the choice of end elements or should always stick to edge loops.
151  { myOffsetVertexMarkersOverride = offset; }
152 
153  // Get or set the primitive mask used for picking. The virtual primMask
154  // overrides DM_InputSelector which allows DM_Viewport to access the
155  // primitive mask for pre-selection highlighting.
157  primMask() const override
158  { return myPrimMask; }
160  { myPrimMask = primmask; }
161 
162  // A selector can optionally be "sloppy" whereby the user can initially
163  // pick any of the component types allowed by getSelectionAllowedTypes(),
164  // regardless of the selection type UI value. Once a component has been
165  // picked in this mode, only components of that type can be picked until
166  // the selections are cleared or a pick occurs as a GU_ReplaceSelect.
167  //
168  // The component type of area select operations when a component has not
169  // yet been picked is determined by the selection type UI value.
170  //
171  // The selection type UI values can be used in this mode to convert the
172  // current selection and are also automatically updated by the selector
173  // as the user picks different component types.
174  //
175  // NB: setSloppy() should be called after setSelectionAllowedTypes().
176  void setSloppyPick(bool on);
177  bool getSloppyPick() const
178  { return mySloppyPick; }
179 
180  // Restrict sloppy picks to a subset of getSelectionAllowedTypes(). Must
181  // be called after setSloppyPick(true) in order to have an effect.
182  //
183  // Note that this only restricts the subset of component types allowed for
184  // sloppy picks and will not affect the current selection, even when it is
185  // of a type we're excluding.
186  bool restrictSloppyAllowedTypesToSubset(
187  const PI_GeometryTypeArray &types);
188 
189  // Some selectors allow picking components at the object level.
190  void setPickAtObjLevel(bool flag)
191  { myPickAtObjLevelFlag = flag; }
192  bool getPickAtObjLevel() const
193  { return myPickAtObjLevelFlag; }
194 
195  // The selector needs to be notified when it starts/stops selecting
196  // so it can add/remove interests (the selection type, etc.).
197  void startSelecting() override;
198  void stopSelecting() override;
199  void restartWithStashedSelection();
200 
201  // Commit the pre-selection in the viewport to a geometry selection.
203  GU_SelectionRule sel_rule) override;
204 
205  // Return a list of looks from which we can select.
206  void getSelectableLooks(GUI_DetailList &looklist) override;
207 
208  // Add the cook selection, if any, from the specified SOP to our current
209  // selection.
210  bool addCookedSelection(SOP_Node *sop);
211 
212  // The selector needs to know the node for which it is reselecting so that
213  // it can properly place visibility operators.
214  void nodeIdForReselecting(int node_id)
215  { myNodeIdForReselecting = node_id; }
216 
217  // Clear the selections of the selection. This method is called when,
218  // for example, the selection stages are aborted.
219  virtual void clearSelections();
220 
221  // Consume the user selections made for this selector by clearing any
222  // correponding selections stashed in the selection manager/cache and
223  // clear our selection infos.
224  virtual void consumeSelections();
225 
226  // Remove the selections we assigned to detail looks.
227  void removeSelectionsFromDetailLooks();
228 
229  // This method allows the resource manager can set the workbench to
230  // something different if a selector is reused. It should not be used
231  // otherwise. A nil pointer is allowed so the select can remove any
232  // of its interests. However, methods of the selector should never be
233  // called when its workbench is nil. The method is virtual so
234  // descendants can also have a chance to clean up.
235  void setViewer(BM_View *viewer) override;
236 
237  // This method must be called after retrieving a new/recycled selector
238  // from the resource manager.
239  void setSelectionUIValues(UI_Value *sel_type,
240  UI_Value *sel_rule,
241  UI_Value *sel_style,
242  UI_Value *sel_visible,
243  UI_Value *sel_contained,
244  UI_Value *sel_full,
245  UI_Value *locate_always,
246  UI_Value *finished);
247 
248  // Any nodes created by this selector are tagged with the creator state's
249  // name.
250  void setCreatorStateName(const char *state_name)
251  { myCreatorStateName.harden(state_name); }
253  { return myCreatorStateName; }
254 
255  // Can this selector use a box or lasso for picking, or just click picks?
256  void setAllowDragSelect(bool allow_drag)
257  { myAllowDragSelFlag = allow_drag; }
258 
259  // Should this selector only select the full geometry?
260  void setSelectFullGeometry(bool select_full)
261  { myFullSelFlag = select_full; }
262 
263  // Should this selector start with the existing selection, if any? The
264  // cook group will be used for the chosen SOP if true and there is no
265  // applicable pending temporary selection. In some cases, you'll want
266  // to control whether we use existing temp or cook selections separately.
267  void setUseExistingSelection(bool use_existing)
268  {
269  setUseExistingTempSelection(use_existing);
270  setUseExistingCookSelection(use_existing);
271  }
272  bool useExistingSelection() const
273  {
274  return useExistingTempSelection() ||
275  useExistingCookSelection();
276  }
277 
278  // Should this selector start with the existing temporary selection,
279  // if any?
280  void setUseExistingTempSelection(bool use_existing)
281  { myUseExistingTempSelection = use_existing; }
283  { return myUseExistingTempSelection; }
284 
285  // Should this selector start with the cook selection for the chosen SOP
286  // either if useExistTempSelection() is false or there was no applicable
287  // pending temporary selection.
288  void setUseExistingCookSelection(bool use_existing)
289  { myUseExistingCookSelection = use_existing; }
291  { return myUseExistingCookSelection; }
292 
293  // TODO: Rename to setExportUserSelectionOnFinish().
294  void setStashSelectionOnFinish(bool stash)
295  { myStashSelectionOnFinish = stash; }
297  { return myStashSelectionOnFinish; }
298 
299  void setAllowMultiPickLoopStart(bool allow)
300  { myAllowMultiPickLoopStart = allow; }
301 
302  // Set an initial selection for the given op path.
303  //
304  // If useExistingTempSelection() or useExistingCookSelection() is true,
305  // then this initial selection will be in addition to those selections,
306  // and may even overwrite them entirely. Any number of op paths can be
307  // set. Only the op paths that exist within the selector context will
308  // have their initial selection set.
309  void setInitialSelection(const char *op_path,
311  const char *selection_string);
312 
313  // Should this selector save undo information?
314  void setSaveUndos(bool yesno) { mySaveUndosFlag = yesno; }
315  bool saveUndos() const { return mySaveUndosFlag; }
316 
317  // Generate merge(s) and connect them to the given op, filling in the
318  // specified input parm with the selection. If there is a menu in the
319  // op that needs to be set and menu_idx is not null, the value menu_idx
320  // points to will be set to a non-negative index into the menu. If menu_idx
321  // is not null but there is no menu, *menu_idx = -1.
322  // If the selection consists of the entire gdp, the group field
323  // is filled with an empty string. To force it to be filled
324  // with a string (even for the entire gdp), use force_selection_string.
325  // An array of the previous input nodes may optionally be provided to
326  // suppress the automatic repositioning of new_node when it is simply
327  // reconnected to the same inputs.
328  bool connectOps(OP_Node &new_node, int op_input_index,
329  const UT_String &input_parm,
330  int *menu_idx = 0,
331  bool branch_off = false,
332  bool multi_input = false,
333  bool force_selection_string = false,
334  bool force_numeric = false,
335  const UT_IntArray *prev_input_nodes = 0);
336 
337  /// Some convenience methods for managing mySelectedInfoIndices.
338  void addSelectedInfo(int info_i, bool set_pick_order=true);
339  void removeSelectedInfo(int info_i);
340 
341  /// Update our internal selection cache and the detail look, if any, with
342  /// the provided selection.
343  int updateSelection(const char *path, OP_Node *node,
344  GUI_DetailLook *look, int geo_idx,
346  const GU_Detail &gdp);
347 
348  /// Returns the current set of ops that have selections on them using this
349  /// selector. The size of the array matches that of the array returned by
350  /// \c selectedselections and \c selectedAutoConvertedSelections.
351  UT_StringArray selectedOpPaths() const;
352 
353  /// Returns the current set of selection objects used to mark the
354  /// component selection for each op used for selection. The size of this
355  /// array matches that of the array returned by \c selectedOpPaths.
356  ///
357  /// In many cases you should use \c selectedAutoConvertedSelections
358  /// instead of this method.
359  OP3D_SelectionHandles selectedSelections() const;
360 
361  /// Returns the current set of auto converted (to the best allowed
362  /// selection type) selection objects for each op used for selection.
363  /// The size of this array matches that of the array returned by
364  /// \c selectedOpPaths.
365  //
366  /// The conversion is done in selectorFinished(), so if this method is
367  /// called before this it is identical to calling selectedSelections().
368  /// Typically you'll want to use this method wherever you call either
369  /// getGeometryTypeAtFinish() or getGroupTypeMenuValAtFinish(). Unlike
370  /// selectedSelections(), entries may be empty or even NULL.
371  OP3D_SelectionHandles selectedAutoConvertedSelections() const;
372 
373  /// Returns a selection handle, given an op path. If the selector is not
374  /// holding a matching op path, then an empty handle is returned.
375  GU_SelectionHandle selectionFromOpPath(UT_StringRef path,
376  bool only_selected=true) const;
377 
378  /// Returns a selection handle, given an info key. If the selector is not
379  /// holding a matching info, then an empty handle is returned.
380  class InfoKey;
381  GU_SelectionHandle selectionFromInfoKey(const InfoKey &key,
382  bool only_selected=true) const;
383 
384  // Returns whether this selector has a non-empty selection instance.
385  bool hasNonEmptySelection() const;
386 
387  // Return the stored selection for the specified geometry, or, if none,
388  // return the selection of the specified type passed in new_selection,
389  // if any, or return an entirely new selection of the specified type
390  // and set new_selection to point to it.
391  GU_SelectionHandle getOrCreateSelection(int node_id, int detail_index,
392  int &info_i,
393  GU_SelectionHandle &new_selection,
394  GA_GroupType sel_type);
395  GU_SelectionHandle getExistingSelection(int node_id, int detail_index,
396  int &info_i,
397  GA_GroupType sel_type);
398 
399  // The state needs to be able to get the current prompt and set the default
400  // prompt. The custom message is for the selector, and the default message
401  // is displayed by the state. The default prompt is passed on by the state
402  // and should not be changed. If you make the const versions public and
403  // the non-const versions private it won't compile, so they're all public.
404  const UT_String &currentPrompt() const { return myCurrentPrompt; }
405  UT_String &currentPrompt() { return myCurrentPrompt; }
406  const UT_String &defaultPrompt() const { return myDefaultPrompt; }
407  UT_String &defaultPrompt() { return myDefaultPrompt; }
408 
409  // Clean up when selector is about to transmit done event. If drag is
410  // true, the selector indicates to the state that the selection should
411  // be dragged right away.
412  void selectorFinished(bool drag = false);
413 
414  // Create an object merge for the given object-sop combination, or combine
415  // the given path into the network if do_combine is true. In that case,
416  // the sop path and selection instance is updated to point to the moved
417  // sop.
418  static SOP_Node *createObjectMerge(OP_Network *network,
419  UT_String &path,
421  const UT_String &creator_state_name,
422  bool keep_original_objects,
423  bool display_origina_objects);
424 
425  // Override the undo worker that gets used for undos. Pass in NULL to use
426  // a default worker.
427  void setUndoWorker(OP3D_InputSelectorUndoWorker *worker=0);
428  // Sets and returns a default undo worker.
429  OP3D_InputSelectorUndoWorker *getDefaultUndoWorker();
430 
431  // Return the feel containing the RMB menu.
432  UI_Menu *getSelectorMenu() const override;
433  UI_Menu *getSelectorHotkeyMenu() const override;
434 
435  void setValidForPickFilter(void *data,
437 
438  // Get or set the current selection type or selection rule explicitly.
439  // Setting the selection type will change the selection type for all
440  // displayed geometry and all geometry that has been selected.
441  void setGeometryType(PI_GeometryType geo_type,
442  bool update_buttons);
443  GA_GroupType selectionType() const;
444 
445  // Get the component type as it was set when the selection was completed.
446  PI_GeometryType getGeometryTypeAtFinish() const;
447  int getGroupTypeMenuValAtFinish() const;
448  bool getKeepOriginalObjects() const;
449 
450  // Query if the selector is currently updating the geometry selection
451  // type button. This can be useful in determining if the selector is
452  // responsible for a given selection type change notification sent by
453  // the workbench.
454  bool currentlyUpdatingGeometryTypeButtons() const;
455 
456  const PI_GeometryTypeArray &getSelectionAllowedTypes() const;
457  void setSelectionAllowedTypes(
458  const PI_GeometryTypeArray &allowedtypes);
459 
460  // Call this method to query the next best allowed selection type when the
461  // given type is not allowed. Returns PI_GEOTYPE_INVALID when we have no
462  // explicit preference among the allowed selection types.
463  PI_GeometryType getNextBestAllowedType(
464  PI_GeometryType disallowed_type) const;
465 
466  // Call this method to query the allowed selection type to use for the
467  // given type. The failure_type is returned if there are no preferred
468  // allowed selection types for the given type.
469  PI_GeometryType mapToAllowedType(
471  PI_GeometryType failure_type
472  = PI_GEOTYPE_INVALID) const;
473 
474  // This function uses the below static function to generate a single
475  // selection string for all selections merged into a single detail.
476  //
477  // If consume_selections is true, the selections will be removed from
478  // this selector and the viewer's selection cache.
479  void generateAllSelectionStrings(UT_String &sel_string,
480  bool only_one_gdp,
481  bool force_numeric,
482  bool consume_selections) override;
483  static void generateMergedSelectionString(UT_String &sel_string,
485  OP3D_SelectionHandles &selections,
486  bool ordered,
487  bool collapse,
488  bool use_ast_to_select_all,
489  bool force_numeric);
490 
491  // A utility method to get a pick record representing the current loop
492  // start pick with the component indices mapped into a detail composed
493  // by merging all the selected details. Returns true on success, false
494  // otherwise. The record will be cleared on failure. The look ID and
495  // detail index returned in the GR_PickRecord are meaningless. We are
496  // unable to export the component info when myLoopStartPickPath is not
497  // in the list of selected paths.
498  bool getPostMergeLoopStart(GR_PickRecord &pick);
499 
500  // A method for bootstrapping the current loop start pick, typically with
501  // a pick derived from an earlier selector. Only the geometry component
502  // data is relevant in the supplied GR_PickRecord.
503  void bootstrapLoopStart(const char *path,
504  const GR_PickRecord &pick,
505  bool only_selected_path);
506 
507  // This method is used by HOM to replace the current selection for a
508  // particular component type.
509  void scriptReplaceSelection(
510  PI_GeometryType geo_type,
511  const UT_StringArray &paths,
512  OP3D_SelectionHandles &selections);
513 
514  // Convert to a particular geometry selection from the given list of
515  // objects
516  static bool createSelectionFromObjects(
517  const OP_NodeList &objects,
518  DM_Viewport &viewport,
519  PI_GeometryType geo_type,
521  OP3D_SelectionHandles &selections);
522 
523  bool getStateParmNames(
524  UT_StringArray &ret,
525  const char* prefix = nullptr) override;
526  bool evalStateParm(
527  const char *name,
528  UT_StringHolder &ret) override;
529  bool setStateParm(
530  const char *name,
531  const UT_StringHolder &val) override;
532  bool pressStateButton(const char *name) override;
533 
535  {
536  public:
537  InfoKey(int node_id, int detail_index)
538  : myNodeId(node_id), myDetailIndex(detail_index)
539  {
540  }
541  bool operator==(const InfoKey &key) const
542  {
543  return myNodeId == key.myNodeId &&
544  myDetailIndex == key.myDetailIndex;
545  }
546  int getNodeId() const { return myNodeId; }
547  int getDetailIndex() const { return myDetailIndex; }
548 
549  private:
550  int myNodeId;
551  int myDetailIndex;
552  };
553 
554  using LocateFilter = std::function<bool(DM_Viewport *)>;
556  { myLocateFilter = filter; }
557 
558 protected:
559  // React to the user pressing a button to change the component type.
560  virtual void handleSelectionTypeChange(UI_Event *event);
561 
562  /// Called when selection finishes and we need to stash away the group
563  /// menu index that gets set for the target operator of this selector.
564  virtual void updateGroupMenuValue(PI_GeometryType geo_type,
565  int &group_menu_type) = 0;
566 
567  // Called when the selection changes and nothing is removed. Added_geo is
568  // a pointer to the added geometry, allowing derived classes to process it
569  // if they so wish.
571  const char *path,
572  GU_SelectionHandle sel,
573  GU_SelectResult &added_geo)
574  { }
575 
576  // Handle a pick during which nothing was selected. Return true if
577  // any changes were made to the existing selections.
578  virtual bool handleNoPick(UI_Event *event);
579 
580  // Insert additional nodes between the last created node and the
581  // state's node.
582  virtual void appendToLastNode(SOP_Node *&/*input_node*/,
583  const UT_String &/*creator_state_name*/,
584  bool /*branch_off*/) {}
585 
586  // Add additional input nodes for the new node.
587  virtual void generateAdditionalInputNodes(SOP_Node & /*new_node*/,
588  SOP_Node * /*last_selected_node */,
589  const UT_String & /*sel_string*/,
590  const UT_String & /*creator_state_name*/) {}
591 
592  // Modify default parameters if necessary.
593  virtual void setNodeParameters(OP_Node &) {}
594 
595  // Return the pick masks to be used for single or area picks. These masks
596  // are a function of the current selection type for all non-sloppy (normal)
597  // selectors, and both the current selection type and the current selection
598  // state for sloppy selectors. These are the masks used to select entities
599  // that the selection knows how to handle.
600  int singlePickMask(GU_SelectionRule sel_rule) const;
601  int areaPickMask(GU_SelectionRule sel_rule) const;
602 
603  // Return the pick mask to be set in the workbench to control the automatic
604  // display of useful visual markers.
605  int displayPickMask() const;
606 
607  // THESE TWO METHODS ARE DEPRECATED.
608  // Overriding selection type in this manner is dangerous as there
609  // is no guarantee the button bar will remain disabled.
610  // If you find yourself wanting to use this (ie: MSS_JoinSelector)
611  // your selector is likely a state in disguise.
612 
613  // This method is called to overwrite UI values. Disables the
614  // toolbox which allows the user to change the values.
615  void overrideSelectionValues(int sel_type, int sel_rule,
616  int sel_style, int sel_full,
617  int locate);
618  // Restore the values indicated by the UI.
619  void restoreSelectionValues();
620 
621  // Save the contents of the selector so later changes can be undone/redone.
622  void saveForUndo() override;
623 
624  // Implements the getPickName function to return the string representation
625  // of a pick id.
626  bool getPickName(const OP3D_PickId &pickid,
627  UT_String &name,
628  bool descriptivename) const override;
629 
630  // Override the base class needObjectPick() method to add support for our
631  // getPickAtObjLevel() flag.
632  bool needObjectPick() const override;
633 
634  // Clear the selections of all the gdp's with selections in them.
635  // This method is called when failing to select something at all.
636  bool emptySelections(const char *path_to_skip = 0,
637  bool refresh = true);
638 
639  // Delay the selection dirty opChanged calls
641  {
642  public:
643  virtual ~DirtySelectionScope();
644  void delayDirtySelection(SOP_Node *s);
645 
646  private:
647  UT_Array<SOP_Node *> myNodes;
648  };
649  // Mark this selection as dirty so that the SOP node and the viewport
650  // will be properly refreshed with the new selection state.
651  void dirtySelection(SOP_Node *sop_node, DirtySelectionScope *scope);
652  void dirtySelection(const GUI_DetailLook &geo_look, int geo_idx, DirtySelectionScope *scope);
653  void dirtySelection(const OP3D_SelectionInfo &sel_info, DirtySelectionScope *scope);
654 
655 
656 
657  // Clear mySelectionInfos as well as mySelectedInfoIndices.
658  void clearSelectionInfos();
659 
660  // Clear mySelectedInfoIndices, but keep mySelectionInfos.
661  void clearSelectedInfoIndices();
662 
663  // Utility method to compute the next unused pick order from our current
664  // selections.
665  int computeNextPickOrder(GA_GroupType sel_type) const;
666 
667  int findInfo(int node_id, int detail_index) const;
668  int findInfo(const char *path) const;
669 
670 
671 private:
672  void handleStartSelecting(UI_Event *event);
673 
674  // Rather than putting the undo code in this file, it's in a friend class.
675  friend class OP3D_InputSelectorUndo;
676 
677  void getPickableGeometry(GUI_DetailList &geos,
678  bool objects_only) const;
679 
680  // Return true if the selection has changed and false otherwise.
681  bool singleSelectGeometry(UI_Event *event,
682  bool save_undo,
683  bool selecting_loop,
685  bool boxSelectGeometry(UI_Event *event,
686  int xcenter, int ycenter,
687  int xsize, int ysize);
688  bool lassoSelectGeometry(UI_Event *event,
689  int *lasso_points);
690  bool brushSelectGeometry(UI_Event *event,
691  uint8 *enablemap,
692  int minx, int miny,
693  int maxx, int maxy,
694  bool visible_only,
695  bool contained_only);
696  bool singleSelectObject(UI_Event *event,
697  UT_Array<GR_PickRecord> &pick_records);
698 
699  // Use the contents of the pick buffer to modify the selections. Return
700  // true if the selection has changed and false otherwise.
701  bool modifySelections(UI_Event *event,
702  const UT_Array<GR_PickRecord> &pick_records,
703  GU_SelectionRule sel_rule);
704 
705  /// Handles a toggle from the "Select Whole Geometry" menu option
706  void fullSelectionChanged(UI_Event *);
707 
708  // Select everything that's visible in the viewport, select nothing, or
709  // toggle the selections of everything in the viewport.
710  void selectAllOrNoneOrToggle(OP3D_SelectionAction action,
711  DM_Viewport &viewport);
712 
713  // Revert the current selection to only the cook selection on the current
714  // node.
715  void revertToCookSelection(DM_Viewport &viewport);
716 
717  // Select the boundary of the current selection. This means
718  // everything which is selected and has a neighbour which is
719  // unselected.
720  void selectBoundary(DM_Viewport &viewport);
721  void selectEdgeBoundary(DM_Viewport &viewport);
722  void shrinkSelection(DM_Viewport &viewport);
723  void growSelection(DM_Viewport &viewport);
724  void selectPrimitivesWithVertexCount(
725  DM_Viewport &viewport,
726  const char *command_name,
727  GA_Size min_vtx, GA_Size max_vtx);
728 
729  using PatternExpandFunc = bool (OP3D_PatternSelectHelper::*)
730  (const GU_Detail &,
733  void patternSet(DM_Viewport &viewport);
734  void patternExpand(DM_Viewport &viewport,
735  PatternExpandFunc func,
737 
738  // Select everything that's visible in the uv viewport, but only if the
739  // face has a specific winding (orientation).
740  void uvSelectAllByWinding(DM_Viewport &viewport,
741  bool front_facing,
742  bool back_facing);
743 
744  void convertSelection(DM_Viewport &viewport,
745  GA_GroupType target_type);
746 
747  bool handlePick(UI_Event *event,
748  const UT_Array<GR_PickRecord> &in_pick_records,
749  GU_SelectionRule sel_rule,
750  bool &added_something);
751 
752  void handleBoxPick(UI_Event *event) override;
753  void activeBoxPick(UI_Event *event) override;
754  void handleLassoPick(UI_Event *event) override;
755  void activeLassoPick(UI_Event *event) override;
756  void handleBrushPick(UI_Event *event) override;
757  void activeBrushPick(UI_Event *event) override;
758  void handleLaserPick(UI_Event *event) override;
759  void activeLaserPick(UI_Event *event) override;
760 
761  // Respond to the user using the selection visibility menu in the toolbar.
762  void handleSelectionHideOrExpose(UI_Event *event);
763 
764  // Should we allow picking from this GUI_DetailLook? (eg. Templates
765  // can't be picked from, and ordered selectors need to pick from the
766  // merges, even if the inputs of the merges are displayed.)
767  bool validForPickRender(GUI_DetailLook *detail,
768  const GUI_DisplayOption &dopt) const;
769 
770  // A higher level method than validForPickRender(), used to consolidate
771  // additional common restrictions.
772  //
773  // TODO: Merge with validForPickRender().
774  bool allowPickOperation(GUI_DetailLook *detail,
775  const GUI_DisplayOption &dopt) const;
776 
777  UT_Array<const OP3D_SelectionInfo *> getNonEmptySelectedInfos() const;
778 
779  // Is any of the geometry visible on the screen selected?
780  bool isAnythingSelected();
781 
782  // Create and connect a visibility sop to modify the visibility of geometry
783  // in the specified sop. Returns the newly created sop, if any, and a flag
784  // indicating whether the visibility sop was inserted above the specified
785  // sop instead of below.
786  SOP_Node *createAndConnectVisibilitySop(SOP_Node *sop,
787  bool *inserted_above);
788 
789  // Set the parameters in the visibility sop to match the action being
790  // performed.
791  void setVisibilitySopParameters(SOP_Node &visibility_sop,
792  bool exposing,
793  bool applying_to_selection,
794  bool cumulative,
795  const UT_String &sel_string);
796 
797  OP3D_EdgeLoopHelper &getEdgeLoopHelper();
798 
799  OP3D_PatternSelectHelper &getPatternSelectHelper(int sop_node_id,
800  int geo_idx);
801 
802  SOP_Node *getChosenSOP() const;
803 
804  SOP_Node * findChosenSop(bool &need_object_pick);
805  void handleSwitchToChosenOp(UI_Event *event);
806 
807  void doneNormalSelection();
808 
809  bool areaSelectGeometry(UI_Event *e,
810  const UT_DimRect &area,
811  uint8 *mask,
812  unsigned pick_mask,
814  bool visible_only,
815  bool contained,
816  bool add_to_existing_picks);
817 
818  // A wrapper around DM_Viewport::adoptLocatedItems() that also handles any
819  // necessary communication with DM_GroupInfo.
820  //
821  // Returns if the viewport located items have changed.
822  bool adoptLocatedItems(DM_Viewport *viewport,
824  UT_Array<GR_PickRecord> &faded_items,
825  bool force_locate = false);
826 
827  // Add any pending (i.e. saved temporary selections) for visible (and
828  // pickable) geometry in the viewer. Returns whether any non-empty
829  // selections were added. We also set have_chosen_sop_temp_sel flag
830  // to indicate if we found any non-null pending selection for the chosen
831  // SOP, including an empty one.
832  bool initWithPendingSelectionForVisibleOps(
833  SOP_Node *chosen_sop,
834  bool &have_chosen_sop_temp_sel);
835  void stashPendingSelection();
836 
837  void autoConvertToFinishGeometryType();
838 
839  void addInitialSelections();
840 
841  void handleGeoChanged(UI_Event *event);
842 
843  void updateSelectMask();
844 
845  // Reset mySloppyPickMask from myAllowedTypes.
846  void resetSloppyPickMask();
847 
848  // Update the set sloppy selection type, if any, to the specified type.
849  void updateExistingSloppySelectionType(
850  GA_GroupType sel_type);
851 
852  // Initialize an unset sloppy selection type from the given pick records
853  // and selection rule.
854  void initSloppySelectionType(
855  const UT_Array<GR_PickRecord> &pick_records,
856  GU_SelectionRule sel_rule);
857 
858  // Set the sloppy selection type to the specified type along with any
859  // extra book-keeping.
860  void setSloppySelectionType(
861  GA_GroupType sel_type);
862 
863  static OP_Node * mergeViaCombine(fpreal t,
864  OP_Network *network,
865  UT_String &path,
867  const UT_String &creator_state_name);
868 
869  bool acceptKey(int key, UI_Event *event);
870  bool fullSelectionKey(int key, UI_Event *event);
871  bool selectByNormalKey(int key, UI_Event *event);
872  bool keepOriginalObjKey(int key, UI_Event *event);
873  bool locateKey(int key, UI_Event *event);
874  bool selectAllKey(int key, UI_Event *event);
875  bool invertSelectionKey(int key, UI_Event *event);
876  bool selectNoneKey(int key, UI_Event *event);
877  bool revertToCookSelectionKey(int key, UI_Event *event);
878  bool selectBoundaryKey(int key, UI_Event *event);
879  bool selectEdgeBoundaryKey(int key, UI_Event *event);
880  bool shrinkSelectionKey(int key, UI_Event *event);
881  bool growSelectionKey(int key, UI_Event *event);
882  bool patternSetKey(int key, UI_Event *event);
883  bool patternForwardKey(int key, UI_Event *event);
884  bool patternBackwardKey(int key, UI_Event *event);
885  bool patternLeftKey(int key, UI_Event *event);
886  bool patternRightKey(int key, UI_Event *event);
887  bool patternForwardToEndKey(int key, UI_Event *event);
888  bool patternBackwardToEndKey(int key, UI_Event *event);
889  bool patternLeftToEndKey(int key, UI_Event *event);
890  bool patternRightToEndKey(int key, UI_Event *event);
891  bool selectUVSelectAllFrontKey(int key, UI_Event *event);
892  bool selectUVSelectAllBackKey(int key, UI_Event *event);
893  bool visibleSelectToggleKey(int key, UI_Event *event);
894  bool containedSelectToggleKey(int key, UI_Event *event);
895  bool doubleClickJumpToObjectKey(int key, UI_Event *event);
896  bool redoSelectionKey(int key, UI_Event *event);
897  bool selectNextGroupKey(int key, UI_Event *event);
898  bool selectPrevGroupKey(int key, UI_Event *event);
899  bool copyCurrentGroupNameKey(int key, UI_Event *event);
900  bool copyCurrentSelectionKey(int key, UI_Event *event);
901 
902  bool selectionConvertPointKey(int key, UI_Event *event);
903  bool selectionConvertEdgeKey(int key, UI_Event *event);
904  bool selectionConvertPrimitiveKey(int key, UI_Event *event);
905  bool selectionConvertVertexKey(int key, UI_Event *event);
906  bool selectionConvertBreakpointKey(int key,
907  UI_Event *event);
908 
909  bool selectPrimitiveTrianglesKey(int key, UI_Event *event);
910  bool selectPrimitiveQuadsKey(int key, UI_Event *event);
911  bool selectPrimitiveNgonsKey(int key, UI_Event *event);
912 
913  void handleLocatedPickComplete(UI_Event *event);
914  void handleMouseActionComplete();
915 
916  // Use a seed pick to expand to new picks by normal. Adds new
917  // components to the pick if its normal is within the spread angle
918  // tolerance from the normal of the base pick.
919  void expandPickByNormal(
920  UT_Array<GR_PickRecord> &new_picks,
921  const GR_PickRecord &base_pick,
922  const GU_Detail &gdp,
923  fpreal spread_angle,
924  bool pick_all_matching_normals,
925  bool use_static_reference_normal,
926  const GU_SelectionHandle & prev_selection);
927 
928  // Use a seed pick to expand to new picks by flood filling. Finds
929  // islands of unselected geometry for selection, and/or islands of
930  // selected geometry for deselection.
931  void expandPickByFloodFill(
932  UT_Array<GR_PickRecord> &new_picks,
933  const UT_Array<GR_PickRecord> &seed_picks,
934  const GU_Detail &gdp,
936  GU_SelectionRule rule);
937 
938  // Utility method to update myLoopStartPick to refer to the detail look
939  // corresponding to myLoopStartPickPath when necessary, and, optionally,
940  // note the fact that we've done this in myLoopStartPickRecordMatchesPath
941  // when we expect it to remain synchronized over an extended operation.
942  void updateLoopStartPickRecordFromPath(
943  bool record_match_state);
944 
945  bool selectFromSingleRecord(UI_Event *event,
946  const GR_PickRecord &pick,
947  GU_SelectionRule sel_rule);
948 
949  void addInfoLookup(const OP3D_SelectionInfo &sel_info,
950  int sel_info_index);
951 
952  const GA_Attribute *getUVAttrib(const GU_Detail *gdp);
953  bool areVerticesOfSamePoint(
954  const UT_Array<GR_PickRecord> &pick_records);
955 
956  void extendVertexPickRecords(
957  const UT_Array<GR_PickRecord> &pick_records,
958  UT_Array<GR_PickRecord> &extended_pick_records);
959 
960  // Hotkey methods
961  static UI_HotkeyHelper::Entry theHotkeyList[];
962 
963  UI_HotkeyHelper myHotkeyHelper;
964  DM_Viewport *myHotkeyViewport;
965 
966  UT_String myCurrentPrompt;
967  UT_String myDefaultPrompt;
968 
969  UT_String myCreatorStateName;
970 
971  UI_Value *myGeoChangedValue;
972  UI_Value *mySelectionTypeValue; // prims, points, etc.
973  UI_Value *myFullSelection; // select whole gdp
974  UI_Value *myAlwaysLocate; // always do locating
975 
976  // A selector can optionally be "sloppy" as described in the comment for
977  // setSloppyPick(), whereby the user can pick any of the component types
978  // allowed by mySloppyPickMask (automatically built from myAllowedTypes).
979  // Once a component is picked in this mode, mySloppySelectionType will be
980  // set and only components of that type can be selected until selections
981  // are cleared.
982  unsigned mySloppyPickMask;
983  GA_GroupType mySloppySelectionType;
984  GA_GroupType mySloppyFallbackSelectionType;
985  bool mySloppyPick;
986  bool mySloppySelectionTypeIsSet;
987 
988  // When overriding the values indicated by the UI buttons for the
989  // above, keep previous values so we can restore.
990  bool myCustomSelValFlag;
991  int mySavedSelType;
992  int mySavedSelRule;
993  int mySavedSelStyle;
994  int mySavedFullSel;
995  int mySavedAlwaysLocate;
996 
997  GEO_PrimTypeCompat::TypeMask myPrimMask; // polygon, nurbs, etc.
998 
999  // NB: The relative order of the selection infos only matters when the
1000  // individual selections have the same pick order set.
1001  UT_Array<OP3D_SelectionInfo> mySelectionInfos;
1002  UT_Map<InfoKey, int> mySelectionInfoLookup;
1003 
1004  UT_IntArray mySelectedInfoIndices;
1005  int myNextPickOrder;
1006 
1008  ScopeKey myScope;
1009 
1010  int myLastMouseDown; // needed for changed events
1011  int myLastMouseStartX; // " " " "
1012  int myLastMouseStartY; // " " " "
1013 
1014  int myNodeIdForReselecting;// reselecting for this node
1015 
1016  bool myUseExistingTempSelection;
1017  bool myUseExistingCookSelection;
1018  bool myStashSelectionOnFinish;
1019  bool myInputRequiredFlag; // is an input op required?
1020  bool myAllowDragSelFlag; // allow box/lasso selecting?
1021  bool myFullSelFlag; // do only full selections?
1022  bool mySaveUndosFlag; // save undo information?
1023  bool myUseAsteriskToSelectAll; // use '*' to select all?
1024  bool myUsePrimsInEdgeSelectionFlag; // use primitives when
1025  // selecting edges (e.g. 0e1)
1026  bool myPickAtObjLevelFlag; // pick geo at OBJ level
1027  bool myAllowEdgeRingSelection;
1028  int myOffsetVertexMarkersOverride;
1029  int myOffsetVertexMarkersSaved;
1030 
1031  // Flag to track whether the auto converted selections stored in the
1032  // selection info have been set.
1033  bool myAutoConvertedSelectionsFlag;
1034 
1035  // After we finish selecting we must remember our type.
1036  PI_GeometryType myFinishGeometryType;
1037  int myFinishGroupTypeMenuVal;
1038 
1039  // Component type of current selection.
1040  PI_GeometryType myCurrentComponentType;
1041 
1042  // A flag to track whether this selector is currently updating the geometry
1043  // type buttons in setGeometryType().
1044  bool myUpdatingGeometryTypeButtons;
1045 
1046  bool myHadDoubleClick;
1047 
1048  struct InitialSelection
1049  {
1051  int index;
1052  UT_StringHolder selection_string;
1053  };
1054  UT_StringMap<InitialSelection> myInitialSelections;
1055 
1056  OP3D_InputSelectorUndoWorker *myUndoWorker;
1057  bool myOwnUndoWorker;
1058  PI_GeometryTypeArray myAllowedTypes;
1059 
1060  // Utility for edge loops. The loop start pick is persistent across
1061  // multiple locate events, and so myLoopStartPickPath should be used
1062  // to identify the geometry to use with myLoopStartPick instead of
1063  // myLoopStartPick.getLookId() and myLoopStartPick.getDetailIndex().
1064  // To help avoid unnecessary lookups using the path, we track when
1065  // we've already updated the myLoopStartPick record to match the path
1066  // across extended operations in myLoopStartPickRecordMatchesPath.
1067  OP3D_EdgeLoopHelper *myEdgeLoopHelper;
1068  UT_String myLoopStartPickPath;
1069  GR_PickRecord myLoopStartPick;
1070  GR_PickRecord myLoopPrevPick;
1071  bool myLoopStartPickOnlyLocated;
1072  bool myLoopStartPickRecordMatchesPath;
1073  OP3D_ValidForPickFilter myValidForPickFilter;
1074  void *myValidForPickFilterData;
1075 
1076  LocateFilter myLocateFilter = nullptr;
1077  bool myAllowMultiPickLoopStart = false;
1078 
1079  // A map from SOP node ID and detail handle index to a helper class for
1080  // pattern selections.
1081  UT_Map<std::pair<int, int>, OP3D_PatternSelectHelper*> myPatternHelpers;
1082 };
1083 
1084 #endif
type
Definition: core.h:977
GT_API const UT_StringHolder selection
const UT_String & creatorStateName()
Definition of a geometry attribute.
Definition: GA_Attribute.h:196
UT_StringHolder myOpPath
GUI_GUSelectionProxyHandle myProxy
Unsorted map container.
Definition: UT_Map.h:83
bool operator==(const InfoKey &key) const
GU_SelectionHandle selection() const
virtual void generateAllSelectionStrings(UT_String &sel_string, bool only_one_gdp, bool force_numeric, bool consume_selections)
void startSelecting() override
virtual UI_Menu * getSelectorHotkeyMenu() const
UT_SharedPtr< GUI_GUSelectionProxy > GUI_GUSelectionProxyHandle
std::function< bool(DM_Viewport *)> LocateFilter
GLsizei const GLchar *const * path
Definition: glcorearb.h:3340
virtual bool handleDoubleClickEvent(UI_Event *event)
OP3D_SelectionAction
bool useExistingTempSelection() const
void setAllowEdgeRingSelection(bool allow)
void setUseAsteriskToSelectAll(bool onoff)
PI_GeometryType
void stopSelecting() override
GLuint const GLchar * name
Definition: glcorearb.h:785
bool handleTransitoryKey(const UI_Event &event, int hotkey_id) override
void setSaveUndos(bool yesno)
GLdouble GLdouble t
Definition: glew.h:1403
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:234
void updateProxy(GU_SelectionHandle sel, bool create)
virtual int handleMouseEvent(UI_Event *event)
GA_GroupType myActiveType
struct _cl_event * event
Definition: glcorearb.h:2960
bool inputRequired() const
unsigned char uint8
Definition: SYS_Types.h:36
void setInputRequired(bool onoff)
virtual void generateAdditionalInputNodes(SOP_Node &, SOP_Node *, const UT_String &, const UT_String &)
virtual int handleKeyEvent(int key, UI_Event *event, DM_Viewport &viewport)=0
void nodeIdForReselecting(int node_id)
bool setStateParm(const char *name, const UT_StringHolder &val) override
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
GU_SelectionRule
Definition: GU_SelectType.h:40
GLint GLuint mask
Definition: glcorearb.h:123
void setPrimMask(GEO_PrimTypeCompat::TypeMask primmask)
void setViewer(BM_View *viewer) override
void setUseExistingTempSelection(bool use_existing)
UT_String & currentPrompt()
UT_String & defaultPrompt()
virtual UI_Menu * getSelectorMenu() const =0
GA_API const UT_StringHolder drag
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1296
int hasLocates() const override
void setStashSelectionOnFinish(bool stash)
void setPickAtObjLevel(bool flag)
UT_SharedPtr< GU_Selection > GU_SelectionHandle
InfoKey(int node_id, int detail_index)
void setUseExistingCookSelection(bool use_existing)
void setUseExistingSelection(bool use_existing)
GLboolean * data
Definition: glcorearb.h:130
Contains transitional objects to provide some backward compatibility for code that references old GEO...
GLuint GLfloat * val
Definition: glcorearb.h:1607
GUI_DetailLook * getLook() const
virtual void addToSelection(UI_Event *event, const char *path, GU_SelectionHandle sel, GU_SelectResult &added_geo)
GLenum func
Definition: glcorearb.h:782
bool pressStateButton(const char *name) override
fpreal64 fpreal
Definition: SYS_Types.h:277
GA_GroupType
An ordinal enum for the different types of groups in GA.
Definition: GA_Types.h:159
GLuint index
Definition: glcorearb.h:785
OP3D_PatternDirection
void setOffsetVertexMarkersOverride(bool offset)
virtual void commitViewportPreSelection(UI_Event *event, GU_SelectionRule sel_rule)
bool getStashSelectionOnFinish() const
const UT_String & currentPrompt() const
void setUsePrimsInEdgeSelections(bool use_prims)
GA_GroupType selectionType() const
bool getPickAtObjLevel() const
virtual void appendToLastNode(SOP_Node *&, const UT_String &, bool)
#define OP3D_API
Definition: OP3D_API.h:10
OP3D_SelectionManager::ComponentScopeKey ScopeKey
UT_SharedPtr< OP3D_GUSelectionSet > OP3D_GUSelectionSetHandle
const char * className() const override
virtual void setNodeParameters(OP_Node &)
GLintptr offset
Definition: glcorearb.h:664
void setAllowDragSelect(bool allow_drag)
GEO_PrimTypeCompat::TypeMask primMask() const override
GLsizei GLenum GLenum * types
Definition: glcorearb.h:2541
const UT_String & defaultPrompt() const
GU_SelectionHandle myAutoConvertedSelection
void setLocateFilter(LocateFilter filter)
virtual void getKeyResolveInfo(UI_KeyResolveInfo &info)=0
virtual void getSelectableLooks(GUI_DetailList &look_list)
bool useExistingSelection() const
GLdouble s
Definition: glew.h:1395
OP3D_GUSelectionSetHandle mySelectionSet
bool getSloppyPick() const
void setCreatorStateName(const char *state_name)
bool evalStateParm(const char *name, UT_StringHolder &ret) override
void setAllowMultiPickLoopStart(bool allow)
GA_API const UT_StringHolder area
bool useAsteriskToSelectAll() const
bool getStateParmNames(UT_StringArray &ret, const char *prefix=nullptr) override
GLenum const void * paths
Definition: glew.h:13872
bool(* OP3D_ValidForPickFilter)(void *data, GUI_DetailLook *look)
bool useExistingCookSelection() const
void setSelectFullGeometry(bool select_full)