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