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