HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BM_State.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: Direct manipulation library (C++)
7  *
8  * COMMENTS:
9  * The base class of a BM state.
10  *
11  */
12 #ifndef __BM_State_H__
13 #define __BM_State_H__
14 
15 #include "BM_API.h"
16 #include "BM_ParmState.h"
17 #include <UI/UI_Keyboard.h>
18 #include <UT/UT_Array.h>
19 
20 
21 class DD_ChoiceList;
22 class DD_Source;
23 class UT_Options;
24 class UT_StringHolder;
25 class UT_Undo;
26 class UI_KeyResolveInfo;
27 class PI_StateTemplate;
28 class OP_Node;
29 class OP_Network;
30 class BM_OpHandleLink;
31 
32 // A dummy base class for GUI_DetailLook.
34 {
35 public:
36  virtual ~BM_DetailLook() { }
37 };
38 
40 {
41 public:
43  sticky = 1; // must be sticky by default (obsolete)
44  entered = 0;
45  scratch = 0;
46  requestnew = 0;
47  preempted = 0;
48  busybuild = 0;
49  wantlocate = 0;
50  modifier = 0;
51  concealed = 0;
52  }
53  unsigned sticky:1, // does not pop back after an operation
54  entered:3, // the way it was entered (BM_EntryType)
55  scratch:3, // entered from scratch
56  requestnew:1, // a new node is requested when generating
57  exsitu:1, // ex situ when generating
58  preempted:1, // have I been interrupted or not
59  busybuild:1, // I'm in the building stage (not editing)
60  wantlocate:1, // want to get locate events
61  modifier:1, // changes geometry, etc or not?
62  concealed:1; // are we concealed in a non-visible desktop?
63 };
64 
66 {
67 public:
68  enum BM_GenerateMode { BM_INLINE = 0x01,
69  BM_OUTLINE = 0x02,
70  BM_REGENERATE = 0x04
71  };
72 
73  // Class constructor and destructor.
74  BM_State( BM_SceneManager &app,
75  PI_StateTemplate &templ,
76  const char *cursor = 0,
77  const char *const *vnames = 0,
78  UI_EventMethod const *vmethods = 0);
79  ~BM_State() override;
80 
81  // Return the current status string for this state. This is used by the
82  // viewport rendering code to display some extra information in the
83  // viewport instead of in the blue status bar. If this string is
84  // returned empty (the default), it is ignored.
85  virtual void status(UT_String &s) const { s.harden(""); }
86 
87  // Render whatever extra things may be needed beside the status string.
88  // You can assume that translations to that location have been performed
89  // already (i.e., you can render without moving).
90  virtual void renderStatusExtras(RE_Render *) {}
91 
92  int isHandle() const override { return 0; }
93 
94  // Enter or exit this state. There are 2 entry types:
95  // 1. fulltime (BM_FULLTIME_ENTRY): the state stays on until another one
96  // is invoked; that other state replaces the current.
97  // 2. overlay (BM_OVERLAY_ENTRY): also known as "volatile", it gets
98  // triggered by pressing a key and stays on until the key is released.
99  // Upon exiting it returns control to the previous state. It is not
100  // allowed to overlay the current state with itself or to have
101  // nested overlay states. When starting the overlay state, the
102  // previous state is _interrupted_, not exited; then, it is _resumed_.
103  // enter() returns 0 if entered and -1 if not.
104  int enter(BM_SimpleState::BM_EntryType how) override;
105  void exit() override;
106 
107 
108  //
109  // When the current desktop is changed, it's possible that the state might
110  // have to clean up some stuff. The concealed() method is called when the
111  // desktop is changed, the revealed() method when the desktop is re-opened.
112  // Note, it may be possible to get a revealed() called without having the
113  // concealed called.
114  //
115  virtual void concealState();
116  virtual void revealState();
117 
118  // Interrupt this state or resume its activity. These methods should
119  // be called by overlay states when entering and exiting respectively.
120  // Interrupt will leave the state in limbo and will usually turn off
121  // the feed from the app; resume will do the opposite. interrupt()
122  // should not change the modeler's current state. If 'state' is given, it
123  // is the state that has interrupted/resumed us. This may be particularly
124  // useful if we are interrupted by a handle (possibly ours).
125  void interrupt(BM_SimpleState *state = 0) override;
126  void resume(BM_SimpleState *state = 0) override;
127  virtual void handleVolatileChanges() {}
128 
129  // Pre-process a mouse start event, in case we wish to push/position a
130  // handle so the mouse event is processed by the handle.
131  virtual int preprocessSelect(UI_Event *event);
132 
133  // Deal with the events the modeler has sent me. Scene events imply use
134  // of the mouse. Return 1 if consumed and 0 otherwise.
135  int handleMouseEvent (UI_Event *event) override;
136 
137  // This is where mouse wheel events get sent.
138  // Integer deltas are stored into event->state.values[Z] where 1 step is a
139  // multiple of 100. Positive values indicates that the wheel rotated
140  // forwards away from the use, while negative values are the opposite.
141  // Return 1 if consumed and 0 otherwise.
142  virtual int handleMouseWheelEvent(UI_Event *event);
143 
144  // Return false if un-handled.
145  virtual bool handleDoubleClickEvent(UI_Event *);
146 
147  // Called whenever the geometry changed (but not when the change was
148  // caused by modelling in this state)
149  virtual void handleGeoChangedEvent(UI_Event *);
150 
151  // Called when a detail look's geometry is modified.
152  virtual void handleDetailLookGeoChanged(BM_DetailLook *look);
153 
154  // Called by the viewer to pass the handleDetailLookGeoChanged() calls
155  // down to any other saved (interrupted) states.
156  void propagateDetailLookGeoChanged(BM_DetailLook *look);
157 
158  // Called by the viewport to allow the state to render its own bits.
159  // It calls doRender(), which is what derived classes should implement.
160  void render(RE_Render *r, int x, int y) override;
161 
162  // The state might contain something that it wants to display in a
163  // non-destructive manner (eg. by xor'ing). Note that this method is not
164  // called during the normal rendering of the workbench.
165  virtual void renderPartialOverlay(RE_Render *r, int x, int y);
166 
168  {
169  public:
171  : myInsertMode(true), myRequestNew(false), myExSitu(false) {}
172 
173  // We can start generating either in inline (insert) mode
174  // or in branching-off mode. The generation mode is relevant only when
175  // generating ops in a network.
176  void setInsertMode(bool insert_mode) { myInsertMode = insert_mode; }
177  bool insertMode() const { return myInsertMode; }
178 
179  // Some states reuse existing ops when possible instead of generating
180  // new ones. A request can be made for new ops here, but it is up to
181  // the individual state to interpret it.
182  void setRequestNew(bool request_new) { myRequestNew = request_new; }
183  bool requestNew() const { return myRequestNew; }
184 
185  // When the ex situ flag is true, this call is being made after the tool
186  // that the user triggered did something like change the viewer network
187  // so that the generate() is occuring in a different context to the one
188  // the user had when initially triggering the tool.
189  void setExSitu(bool ex_situ) { myExSitu = ex_situ; }
190  bool isExSitu() const { return myExSitu; }
191 
192  private:
193  bool myInsertMode;
194  bool myRequestNew;
195  bool myExSitu;
196  };
197 
198  // Similar to enter, but totally from scratch. At this level, it's the
199  // same as doing an enter. It cannot be entered in volatile mode.
200  virtual int generate(BM_SimpleState::BM_EntryType how,
201  const GenerateParms &parms);
202 
203  // Start or stop the generation process. At this level, generating doesn't
204  // mean a thing. We can start generating either in inline (insert) mode
205  // or in branching-off mode. The inline mode is the default. The mode
206  // is relevant only when generating ops in a network.
209  bool requestnew = false,
210  bool exsitu = false)
211  {
212  myFlags.scratch = how;
213  myFlags.requestnew = requestnew;
214  myFlags.exsitu = exsitu;
215  }
216  virtual void stopGenerating()
217  {
218  myFlags.scratch = 0;
219  myFlags.requestnew = 0;
220  myFlags.exsitu = 0;
221  }
222 
223  // Restart cancels what is currently being done and starts generating anew.
224  virtual void restart();
225 
226  // Check if the state will allow a restart to be triggered by a given key
227  // event. Override this to return false if you do not want this key to
228  // trigger a restart.
229  virtual bool allowRestartWithKey(const UI_Event &event) const;
230 
231  // Also, find out whether you meet the conditions to be entered, or simply
232  // if the given key matches (one of) yours:
233  int meetsEntryConditions (const UI_Event &event) const;
234  virtual int isEntryCondition (UI_Keyboard key) const;
235 
236  virtual void getKeyResolveInfo(UI_KeyResolveInfo &info);
237 
238  // Override this to handle transitory key presses, default implementation
239  // does nothing. Return true if key was handled. The key is in
240  // event.state.id and the keypress state is in event.state.data.
241  virtual bool handleTransitoryKey(const UI_Event & /*event*/,
242  int /*hotkey_id*/)
243  { return false; }
244 
245  // Called if the state needs to handle changes in op parameters
246  virtual int hasOpNode(const OP_Node &/*node*/) const;
247  virtual void handleOpNodeChange(OP_Node &/*node*/);
248  virtual void handleOpUIChange(OP_Node &/*node*/);
249  virtual void handleOpNetChange(OP_Network &/*net*/);
250  virtual void handleOpNetClear();
251 
252  // See how you can handle a node being deleted. If it's an implicit
253  // node we might be OK. Return 0 if we can handle it, -1 if we must be
254  // exited or restarted from scratch.
255  virtual int handleNodeDeleted(OP_Node &/*node*/);
256 
257  // Set or get the "locate" flag, which determines whether we're interested
258  // in locate events or not.
259  void wantsLocates(int yesNo) { myFlags.wantlocate=yesNo; }
260  virtual int hasLocates() const{ return myFlags.wantlocate;}
261  virtual bool doesHandleLocates() const { return false; }
262 
263  // Query some of the flags:
264  int isPreempted() const { return myFlags.preempted; }
265  int isBuilding () const { return myFlags.busybuild; }
266  int isEntered() const { return myFlags.entered; }
267  bool isConcealed() const { return myFlags.concealed; }
268 
269  int isGenerating() const { return myFlags.scratch; }
270  int isGeneratingInline() const
271  { return myFlags.scratch==BM_State::BM_INLINE; }
272  bool isRequestingNew() const
273  { return myFlags.requestnew; }
274  bool isGeneratingExSitu() const
275  { return myFlags.exsitu; }
276  int isRegenerating() const
277  { return myFlags.scratch==BM_State::BM_REGENERATE; }
278 
279  bool isOverlay() const override
280  {
281  return (myFlags.entered &
283  }
284  int isFullTime() const
285  {
286  return myFlags.entered &
288  }
289  int isModifier() const override
290  {
291  return myFlags.modifier;
292  }
293 
294  // If a state generates a sop and displays it (eg. a hide sop), it
295  // will want the state controller to ignore the change so the state
296  // doesn't exit.
297  virtual bool ignoreDisplayFlagChange() const { return false; }
298 
299  // Return a pointer to the feel containing the extra buttons of the state.
300  // If a state has no extra buttons, 0 will be returned.
301  virtual int findPI(BM_OpHandleLink *pi) const;
302 
303  // Find out if the state is inherently sticky whether entered FULLTIME or
304  // not. Non-sticky (ie oneTime) states pop back to the view state after
305  // they've completed an operation. A state is sticky by default.
306  int isSticky() const { return myFlags.sticky; }
307 
308  // Check if MMB can be used for indirect handle drags. Some states use
309  // the MMB themselves.
310  virtual bool getAllowIndirectHandleDrag() const { return true; }
311 
312  // Checks if and how an RMB menu can be popped up. Usually, when the state
313  // is in building mode, the RMB menus are not allowed (since RMB is used
314  // to complete building/drawing/selection).
316  {
317  BM_RMB_MENU_ALLOWED, // show the menu right away
318  BM_RMB_MENU_DELAYED, // wait and show menu if mouse was not dragged
319  BM_RMB_MENU_DENIED // don't show the menu at all
320  };
321  virtual BM_RMBMenuPopupMode getRMBMenuPopupMode(short altflags) const;
322 
323  // Return this state's index in the list of states:
324  int index() const { return myIndex; }
325  void index(int idx) { myIndex = idx; }
326 
327  // The name of this class:
328  const char *className() const override;
329 
330  const PI_StateTemplate &getTemplate() const { return myTemplate; }
331  PI_StateTemplate &getTemplate() { return myTemplate; }
332 
333  // For most states, op dependency is determined entirely by the state
334  // template. It is possible, however, for the state instance itself
335  // to dynamically change whether or not it is op dependent on the fly.
336  // Any state changing its op dependency in this fashion must notify the
337  // appropriate BM_OpStateControl by calling its updateOpDependence()
338  // method. In general, getTemplate().opIndependent() should be false
339  // for such states to allow use of switchToOpDependent().
340  virtual int isOpIndependent() const;
341 
342  // Normally, when a user wants to switch to a node's default state, say
343  // by hitting BM_KEY_ACCEPT, when already in that state, we have to use
344  // a new instance whenever the current instance is not op dependent.
345  //
346  // These methods make it possible to override that behavior and change
347  // the current instance to be op dependent.
348  //
349  // NB: Only used when !getTemplate().opIndependent() && isOpIndependent(),
350  // i.e., it is registered as an op dependent state that is currently
351  // not op dependent, and hasOpNode() returns true for the target node.
352  virtual bool canSwitchToOpDependent() const { return false; }
353  virtual void switchToOpDependent();
354 
355  // Returns the icon name and label that should appear in the viewer
356  // operation controls bar when we are in this state. The default
357  // implementation extracts this information from the state template.
358  const char *getOperationBarIconName() const override;
359  const char *getOperationBarLabel() const override;
360  const char *getHotkeyString() const override;
361 
362  virtual void afterUndo();
363 
364  // The user can dynamically change the bindings from the textport
365  // We need to refresh the current handles in the viewport because
366  // they could be affected.
367  virtual void refreshBindings(int id, const char *op_type);
368  // This method is called reload the stored settings of any attached
369  // PIs when these settings may have been changed.
370  virtual void refreshSettings(int id, const char *op_type);
371 
372  const char *replaceCursor(const char *newcursor) override;
373 
374  // Return the help for this state in the string that's passed in.
375  // (Note that custom states may override getHelp() to
376  // provide help, even though there is no actual help file.) is_html
377  // will be set to indicate if the help is in html or not.
378  // NOTE: The help file may contain unexpanded hotkey variables.
379  virtual void getHelp(UT_String &help_text, bool &is_html);
380 
381  // Find all help file information, see FUSE:openHdoxURL().
382  virtual void getHelpDirAndNameOrUrl(UT_StringHolder &dir,
384  UT_StringHolder &url);
385 
386  // Show persistent handles in this state?
387  virtual bool showPersistent() const { return true; }
388 
389  // Return true if we would like to receive an event intended for the
390  // click-orienter but was not consumed by it. All normal states should
391  // only want this event if they are overlay states.
392  virtual bool wantFailedOrienterEvent() const { return isOverlay(); }
393 
394  // Show the geometry of the selected operator in this state?
395  virtual bool getShowSelectedOp() const { return true; }
396 
397  // Reset and clear any remembered state data. Used mainly for states such
398  // as view, which would like to home on world origin again, etc.
399  virtual void resetStateForNew() { };
400 
401  // A state can override what appears in the select mode side bar of the
402  // viewer.
403  virtual UI_Feel *getCustomSelectModeSideBar() const { return 0; }
404 
405  // Returns true if the state respects the secure selection setting.
406  virtual bool useSecureSelection() const { return true; }
407 
408  // Returns true if the state supports volatile selections.
409  virtual bool useVolatileSelection() const { return false; }
410 
411  // Get the global state preferences. Preferences for individual states
412  // should be prefixed with "<getTemplate().name()>.".
413  static UT_Options &getGlobalPrefs();
414 
415  // returns true if this instance is executing code in a 'busy' mode
416  bool isBusyProcessing() const
417  {
418  return myBusyCounter > 0;
419  }
420 
421  // Drag and drop support
422  virtual int testDragDrop(DD_Source &)
423  {
424  return 0;
425  }
427  {
428  }
429  virtual int acceptDragDrop(DD_Source &, const char * /*label*/)
430  {
431  return 0;
432  }
433 
434 protected:
435  friend class Busy;
436 
437  // The state might contain some geometry it wants to display, but may not
438  // want it to be part of the main gdp. This method allows the state to
439  // "sneak in" this special geometry that it might have (eg. a rubber band
440  // when building curves). This method is called by DM_State::render().
441  virtual void doRender(RE_Render *r, int x, int y, int ghost);
442 
443  // Similar to doRender() but called on a saved (interrupted) state for
444  // states which may want to handle it.
445  virtual void doRenderSaved(RE_Render *r, int x, int y, int ghost);
446 
447  // Make this a state that changes data or not (0 by default):
448  void setModifier(int yn) { myFlags.modifier = yn; }
449 
450  // Find out whether the general entry conditions for overlay states
451  // are met (before you test for your specific key conditions).
452  // The basic conditions are that:
453  // - the event type is key up/down
454  // - no mouse button is down
455  // - we're not the current state
456  // - the current state is not and overlay itself
457  int meetsBasicEntryConditions(const UI_Event &e) const;
458 
459  // Set the build flag, ie. whether we're actually building something now
460  // or making changes to geometry that is linked to this state.
461  virtual void setBuild(int onOff);
462 
463  void handleMouseEventVoidRet(UI_Event *event);
464 
465  // Call doRenderSaved on saved states recursively in case they want to
466  // handle it.
467  void renderSaved(RE_Render *r, int x, int y, int ghost);
468 
469  // This class is intended for classes deriving from BM_State to execute
470  // their code in a 'busy' mode. While the code executes, calling
471  // BM_State::isBusyProcessing() will return true. The 'busy' mode gets reset
472  // when the derived class method using Busy goes out of scope.
473  struct Busy
474  {
475  Busy() = delete;
476 
477  Busy( BM_State & state ) : myState(state)
478  {
479  myState.myBusyCounter++;
480  }
481 
483  {
484  if (myState.myBusyCounter > 0)
485  {
486  myState.myBusyCounter--;
487  }
488  }
489 
491  };
492 
493  BM_StateFlags myFlags; // useful flags
494 
497 
498 private:
499  PI_StateTemplate &myTemplate;
500 
501  UT_Array<int> myVolatileKeys;// the key used for entry condition
502  int myIndex; // index in the list of states
503 
504  bool myCursorPushed;
505  int myBusyCounter;
506 };
507 
508 #endif
virtual void stopGenerating()
Definition: BM_State.h:216
virtual ~BM_DetailLook()
Definition: BM_State.h:36
void setExSitu(bool ex_situ)
Definition: BM_State.h:189
virtual bool ignoreDisplayFlagChange() const
Definition: BM_State.h:297
virtual void status(UT_String &s) const
Definition: BM_State.h:85
static UI_Event theDelayedSelectionEvent
Definition: BM_State.h:496
int isPreempted() const
Definition: BM_State.h:264
virtual bool getShowSelectedOp() const
Definition: BM_State.h:395
int isGenerating() const
Definition: BM_State.h:269
bool insertMode() const
Definition: BM_State.h:177
void index(int idx)
Definition: BM_State.h:325
BM_RMBMenuPopupMode
Definition: BM_State.h:315
PI_StateTemplate & getTemplate()
Definition: BM_State.h:331
virtual int testDragDrop(DD_Source &)
Definition: BM_State.h:422
bool requestNew() const
Definition: BM_State.h:183
int isRegenerating() const
Definition: BM_State.h:276
void setModifier(int yn)
Definition: BM_State.h:448
GLuint const GLchar * name
Definition: glcorearb.h:785
virtual void resume(BM_SimpleState *=0)
virtual bool useVolatileSelection() const
Definition: BM_State.h:409
bool isGeneratingExSitu() const
Definition: BM_State.h:274
static bool theDelayedSelectionEventIsValid
Definition: BM_State.h:495
bool isBusyProcessing() const
Definition: BM_State.h:416
GLint GLenum GLint x
Definition: glcorearb.h:408
struct _cl_event * event
Definition: glcorearb.h:2960
bool isExSitu() const
Definition: BM_State.h:190
virtual int enter(BM_EntryType how=BM_SimpleState::BM_OVERLAY_ENTRY)=0
int isEntered() const
Definition: BM_State.h:266
void wantsLocates(int yesNo)
Definition: BM_State.h:259
void setInsertMode(bool insert_mode)
Definition: BM_State.h:176
int isBuilding() const
Definition: BM_State.h:265
virtual UI_Feel * getCustomSelectModeSideBar() const
Definition: BM_State.h:403
void startGenerating(BM_State::BM_GenerateMode how=BM_State::BM_INLINE, bool requestnew=false, bool exsitu=false)
Definition: BM_State.h:207
BM_GenerateMode
Definition: BM_State.h:68
bool isOverlay() const override
Definition: BM_State.h:279
virtual void resetStateForNew()
Definition: BM_State.h:399
virtual bool useSecureSelection() const
Definition: BM_State.h:406
int index() const
Definition: BM_State.h:324
bool isConcealed() const
Definition: BM_State.h:267
void harden()
Take shallow copy and make it deep.
Definition: UT_String.h:206
virtual void interrupt(BM_SimpleState *=0)
void setRequestNew(bool request_new)
Definition: BM_State.h:182
virtual bool wantFailedOrienterEvent() const
Definition: BM_State.h:392
Busy(BM_State &state)
Definition: BM_State.h:477
virtual bool handleTransitoryKey(const UI_Event &, int)
Definition: BM_State.h:241
#define BM_API
Definition: BM_API.h:10
BM_State & myState
Definition: BM_State.h:490
bool isRequestingNew() const
Definition: BM_State.h:272
A map of string to various well defined value types.
Definition: UT_Options.h:84
int isGeneratingInline() const
Definition: BM_State.h:270
const PI_StateTemplate & getTemplate() const
Definition: BM_State.h:330
virtual void exit()=0
BM_StateFlags myFlags
Definition: BM_State.h:493
int isModifier() const override
Definition: BM_State.h:289
virtual bool getAllowIndirectHandleDrag() const
Definition: BM_State.h:310
virtual int handleMouseEvent(UI_Event *event)=0
virtual void getDragDropChoice(DD_Source &, DD_ChoiceList &)
Definition: BM_State.h:426
virtual int acceptDragDrop(DD_Source &, const char *)
Definition: BM_State.h:429
UI_Keyboard
Definition: UI_Keyboard.h:6
int isHandle() const override
Definition: BM_State.h:92
void(UI_Object::* UI_EventMethod)(UI_Event *)
Definition: UI_Object.h:36
virtual void render(RE_Render *r, int x, int y)
constexpr T pi()
Pi constant taken from Boost to match old behaviour.
Definition: Math.h:118
virtual bool showPersistent() const
Definition: BM_State.h:387
virtual void renderStatusExtras(RE_Render *)
Definition: BM_State.h:90
virtual void handleVolatileChanges()
Definition: BM_State.h:127
virtual bool canSwitchToOpDependent() const
Definition: BM_State.h:352
GLboolean r
Definition: glcorearb.h:1221
int isFullTime() const
Definition: BM_State.h:284
virtual bool doesHandleLocates() const
Definition: BM_State.h:261
GLdouble s
Definition: glew.h:1395
GLint y
Definition: glcorearb.h:102
int isSticky() const
Definition: BM_State.h:306
virtual int hasLocates() const
Definition: BM_State.h:260