SceneViewer.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package MemoryX::gui-plugins::SceneEditor
19  * @date 2015
20  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21  * GNU General Public License
22  */
23 
24 #include "SceneViewer.h"
25 
26 #include "../controller/DeselectOperation.h"
27 #include "../controller/SelectOperation.h"
28 #include <Inventor/SoPickedPoint.h>
29 #include <Inventor/actions/SoRayPickAction.h>
30 #include <Inventor/events/SoLocation2Event.h>
31 #include <Inventor/events/SoMouseButtonEvent.h>
32 
34  SoQtExaminerViewer(widget), control(control)
35 {
36  this->setBackgroundColor(SbColor(100 / 255.0f, 100 / 255.0f, 100 / 255.0f));
37  this->setAccumulationBuffer(false);
38  this->setHeadlight(true);
39  this->setViewing(false);
40  this->setDecoration(false);
41 #ifdef WIN32
42 #ifndef _DEBUG
43  this->setAntialiasing(true, 4);
44 #endif
45 #endif
46  this->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND);
47  this->setFeedbackVisibility(true);
48 }
49 
50 //Override the default navigation behaviour of the SoQtExaminerViewer
51 SbBool
52 scene3D::SceneViewer::processSoEvent(const SoEvent* const event)
53 {
54  const SoType type(event->getTypeId());
55 
56  //Remapping mouse press events
57  if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId()))
58  {
59  SoMouseButtonEvent* const ev = (SoMouseButtonEvent*)event;
60  const int button = ev->getButton();
61  const SbBool press = ev->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
62 
63  //LEFT MOUSE BUTTON
64  if (button == SoMouseButtonEvent::BUTTON1)
65  {
67  {
68  if (!controller->getScene()->getSelectionManager()->getCreateOperations())
69  {
70  //SelectionManager is not creating Operations, so we shouldn't either!
71  return SoQtRenderArea::processSoEvent(ev);
72  }
73  }
74 
75  if (press)
76  {
77  /*We could just pass action into scenegraph here. There is only one litte thing
78  that doesnt work then: deselecting by clicking into void is performed as
79  many single deselection operations in controller. Undoing then performs
80  every deselection seperately, which is annoying. SoSelection on the other
81  hand doesn't tell us this 'click into void' event so we have to check ourself before this action
82  goes into scenegraph. */
83 
84  SoRayPickAction rp(this->getViewportRegion());
85  rp.setPickAll(false);
86  rp.setPoint(event->getPosition());
87  rp.apply(this->getSceneGraph());
88  SoPickedPoint* picked = rp.getPickedPoint();
89 
90  if (!picked)
91  {
92  /*We clicked into the void here, so we handle this event ourselves, instead of
93  leaving this up to the SoSelection Node... Tell controller to deselect everything
94  in one big operation block and then return, if there are any objects selected of course*/
95 
96  //Shift click into void doesnt change anything
97  if (!ev->wasShiftDown())
98  {
100  {
101  if (controller->getScene()
102  ->getSelectionManager()
103  ->getAllSelected()
104  .size() != 0)
105  {
106  std::shared_ptr<std::vector<controller::OperationPtr>> operations(
107  new std::vector<controller::OperationPtr>());
108 
109  // deselect all objects
110  for (scene3D::SceneObjectPtr object : controller->getScene()
111  ->getSelectionManager()
112  ->getAllSelected())
113  {
114  controller::OperationPtr deselect(
116  controller->getMemoryXController(),
117  controller->getScene(),
118  object->getObjectId()));
119  operations->push_back(deselect);
120  }
121 
125  operations);
126  }
127  }
128  }
129 
130  return TRUE;
131  }
132  else
133  {
134  /* The performed click is above something!*/
135 
136  /*We have to make sure we didn't click on a manipulator before we can make more decisions here. In the case we have clicked one,
137  we can simply pass the event into scenegraph, because we dont have to change the behaviour here!*/
138 
139  SoFullPath* p = (SoFullPath*)picked->getPath();
140 
141  for (int i = 0; i < p->getLength(); i++)
142  {
143  SoNode* n = p->getNode(i);
144 
145  if (n->isOfType(SoTransformManip::getClassTypeId()))
146  {
147  //Manipulator found, pass event into scenegraph
148  return SoQtRenderArea::processSoEvent(ev);
149  }
150  }
151 
152  /* Seems like we selected something and it is not a manipulator, must be an object! Let's check some last cases we have
153  to manually handle.*/
154 
155  if (!ev->wasShiftDown())
156  {
157  /*If shift is not down we might get the case where mutiple objects are deselected before the picked object
158  is selected. We just do this work for the SoSelection node and group all deselect operations and the select operation
159  into one block (which is what SoSelection can't do for us). */
161  {
162  //Is there more than one object already selected?
163  if (controller->getScene()
164  ->getSelectionManager()
165  ->getAllSelected()
166  .size() > 0)
167  {
168  //Find out which object to select
169  SceneObjectPtr obj;
170 
171  for (int i = 0; i < picked->getPath()->getLength(); i++)
172  {
173  SoNode* n = picked->getPath()->getNode(i);
174 
175  if (n->isOfType(SceneObject::getClassTypeId()))
176  {
177  obj.reset((SceneObject*)n);
178  }
179  }
180 
181  //Is there only one object selected and it is also the object we want to select here?
182  if (controller->getScene()
183  ->getSelectionManager()
184  ->getAllSelected()
185  .size() == 1 &&
186  controller->getScene()->getSelectionManager()->isSelected(obj))
187  {
188  //No need to do something, pass this to Selection node, default behaviour.
189  return SoQtRenderArea::processSoEvent(ev);
190  }
191  else
192  {
193  //Deselect all and select object in one block operation
194  std::shared_ptr<std::vector<controller::OperationPtr>>
195  operations(new std::vector<controller::OperationPtr>());
196 
197  // deselect all objects
198  for (scene3D::SceneObjectPtr object :
199  controller->getScene()
200  ->getSelectionManager()
201  ->getAllSelected())
202  {
203  controller::OperationPtr deselect(
205  controller->getMemoryXController(),
206  controller->getScene(),
207  object->getObjectId()));
208  operations->push_back(deselect);
209  }
210 
211  controller->execute(
215  operations);
216 
217  //Let SoSelection node handle the selection
218  return SoQtRenderArea::processSoEvent(ev);
219  }
220  }
221  else
222  {
223  //Nothing selected, so its gonna be only one operation. Let SoSelection node do this.
224  return SoQtRenderArea::processSoEvent(ev);
225  }
226  }
227  }
228  else
229  {
230  /*If shift is down and an object is being picked, selection list can only grow by one element
231  or one element is deselected. We therefore don't need to put all operations into one block of operations
232  because it can only be one operation at once. Just pass this event right into the scenegraph and let
233  the SoSelection node handle it automatically. */
234  return SoQtRenderArea::processSoEvent(ev);
235  }
236  }
237  }
238  else
239  {
240  return SoQtRenderArea::processSoEvent(ev);
241  }
242  }
243 
244  //RIGHT MOUSE BUTTON
245  if (button == SoMouseButtonEvent::BUTTON2)
246  {
247  /*Right mouse button has no functionality yet, so ignore it.*/
248  return TRUE;
249  }
250 
251  //MIDDLE MOUSE BUTTON
252  if (button == SoMouseButtonEvent::BUTTON3)
253  {
254  /*Middle mouse button now is used for all changes in camera perspective.
255  To also display the cool little rotation cursor, viewing mode is set to on
256  while button is down*/
257 
258  //Enable or disable viewing mode while BUTTON3 pressed
259  if (press)
260  {
261  if (!this->isViewing())
262  {
263  this->setViewing(true);
264  }
265  }
266  else
267  {
268  if (this->isViewing())
269  {
270  this->setViewing(false);
271  }
272  }
273 
274  //Remap BUTTON3 to BUTTON1
275  ev->setButton(SoMouseButtonEvent::BUTTON1);
276 
277  //Make sure this REALLY only can happen when viewing mode is on.
278  //Zooming can also turn it on and it leads to weird effects when doing both
279  //(deselections in scene etc.) because SoQtExaminerViewer passes BUTTON1
280  //events up to scenegraph when not in viewing mode.
281  if (this->isViewing())
282  {
283  return SoQtExaminerViewer::processSoEvent(ev);
284  }
285  }
286 
287  //MOUSE WHEEL UP AND DOWN
288  if (button == SoMouseButtonEvent::BUTTON4 || button == SoMouseButtonEvent::BUTTON5)
289  {
290  /*Zooming is allowed, so just use it. We have to temporarily turn viewing mode
291  on to make SoQtExaminerViewer allow zooming.*/
292 
293  //Swap BUTTON4 and BUTTON5 because zooming out while scrolling up is just retarded
294  ev->setButton(button == SoMouseButtonEvent::BUTTON4 ? SoMouseButtonEvent::BUTTON5
295  : SoMouseButtonEvent::BUTTON4);
296 
297  //Zooming is allowed, so just pass it and temporarily set viewing mode on, if it is not already
298  //(otherwise coin gives us warning messages...)
299  if (!this->isViewing())
300  {
301  if (!this->isViewing())
302  {
303  this->setViewing(true);
304  }
305 
306  SoQtExaminerViewer::processSoEvent(ev);
307 
308  if (this->isViewing())
309  {
310  this->setViewing(false);
311  }
312  }
313  else
314  {
315  SoQtExaminerViewer::processSoEvent(ev);
316  }
317 
318  return TRUE;
319  }
320  }
321 
322  // Keyboard handling
323  if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId()))
324  {
325  const SoKeyboardEvent* const ev = (const SoKeyboardEvent*)event;
326 
327  /*The escape key and super key (windows key) is used to switch between
328  viewing modes. We need to disable this behaviour completely.*/
329 
330  //65513 seems to be the super key, which is not available in the enum of keys in coin....
331  if (ev->getKey() == SoKeyboardEvent::ESCAPE || ev->getKey() == 65513)
332  {
333  return TRUE;
334  }
335  else if (ev->getKey() == SoKeyboardEvent::S && ev->getState() == SoButtonEvent::DOWN)
336  {
337  if (!this->isSeekMode())
338  {
339  if (!this->isViewing())
340  {
341  this->setViewing(true);
342  }
343 
344  SoQtExaminerViewer::processSoEvent(ev);
345  this->setSeekTime(0.5);
346  this->seekToPoint(ev->getPosition());
347 
348  if (this->isViewing())
349  {
350  this->setViewing(false);
351  }
352  }
353  }
354  else
355  {
356  SoQtExaminerViewer::processSoEvent(ev);
357  }
358 
359  SoQtExaminerViewer::processSoEvent(ev);
360  }
361 
362  //Let all move events trough
363  if (type.isDerivedFrom(SoLocation2Event::getClassTypeId()))
364  {
365  return SoQtExaminerViewer::processSoEvent(event);
366  }
367 
368  //YOU SHALL NOT PASS!
369  return TRUE;
370 }
scene3D::SceneViewer::SceneViewer
SceneViewer(const controller::ControllerPtr &control, QWidget *widget)
Constructor Creates an Instance of the Class.
Definition: SceneViewer.cpp:33
controller::Controller::EXECUTE_ON_SCENE
static const int EXECUTE_ON_SCENE
A flag to execute operations on the Scene.
Definition: Controller.h:73
controller::Controller::UNDOABLE
static const int UNDOABLE
A flag to save the executed operations to the history.
Definition: Controller.h:80
controller
Definition: AddOperation.h:39
controller::ControllerPtr
std::shared_ptr< Controller > ControllerPtr
Definition: ClassDefinitions.h:41
controller::DeselectOperation
A operation to deselect a object.
Definition: DeselectOperation.h:41
SceneViewer.h
controller::OperationPtr
std::shared_ptr< Operation > OperationPtr
Definition: ClassDefinitions.h:54
scene3D::SceneObjectPtr
boost::intrusive_ptr< SceneObject > SceneObjectPtr
Definition: PointerDefinitions.h:40
controller::Controller::EXECUTE_ON_WM
static const int EXECUTE_ON_WM
A Flag to execute operations on the WorkingMemory.
Definition: Controller.h:66
control
This file is part of ArmarX.