1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file GUIOSGView.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Michael Behrisch
13 /// @date 19.01.2012
14 /// @version $Id$
15 ///
16 // An OSG-based 3D view on the simulation
17 /****************************************************************************/
18
19
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24
25 #ifdef HAVE_OSG
26
27 #include <iostream>
28 #include <utility>
29 #include <cmath>
30 #include <limits>
31 // osg may include windows.h somewhere so we need to guard against macro pollution
32 #ifdef WIN32
33 #define NOMINMAX
34 #pragma warning(push)
35 #pragma warning(disable: 4127) // do not warn about constant conditional expression
36 #endif
37 #include <osgViewer/Viewer>
38 #include <osgViewer/ViewerEventHandlers>
39 #include <osgGA/NodeTrackerManipulator>
40 #include <osgDB/ReadFile>
41 #include <osg/PositionAttitudeTransform>
42 #include <osg/Vec4>
43 #include <osg/ShapeDrawable>
44 #ifdef WIN32
45 #undef NOMINMAX
46 #pragma warning(pop)
47 #endif
48 #include <utils/gui/windows/GUISUMOAbstractView.h>
49 #include <utils/gui/windows/GUIPerspectiveChanger.h>
50 #include <utils/gui/windows/GUIAppEnum.h>
51 #include <utils/foxtools/MFXCheckableButton.h>
52 #include <utils/gui/images/GUIIconSubSys.h>
53 #include <gui/GUIApplicationWindow.h>
54 #include <utils/gui/windows/GUIDialog_ViewSettings.h>
55 #include <utils/gui/windows/GUIDialog_EditViewport.h>
56 #include <utils/gui/settings/GUICompleteSchemeStorage.h>
57 #include <utils/gui/images/GUITexturesHelper.h>
58 #include <utils/foxtools/MFXImageHelper.h>
59 #include <utils/gui/globjects/GUIGlObjectStorage.h>
60 #include <foreign/rtree/SUMORTree.h>
61 #include <utils/gui/div/GLHelper.h>
62 #include <guisim/GUINet.h>
63 #include <guisim/GUIJunctionWrapper.h>
64 #include <guisim/GUIEdge.h>
65 #include <guisim/GUILane.h>
66 #include <guisim/GUIVehicle.h>
67 #include <microsim/MSEdge.h>
68 #include <microsim/MSEdgeControl.h>
69 #include <microsim/MSLane.h>
70 #include <microsim/MSJunctionControl.h>
71 #include <microsim/MSTransportableControl.h>
72 #include <microsim/MSVehicleControl.h>
73 #include <microsim/traffic_lights/MSTLLogicControl.h>
74 #include <microsim/traffic_lights/MSSimpleTrafficLightLogic.h>
75 #include <utils/common/RGBColor.h>
76 #include <utils/common/MsgHandler.h>
77 #include <utils/common/StringUtils.h>
78 #include <utils/geom/PositionVector.h>
79 #include <gui/GUISUMOViewParent.h>
80 #include <utils/gui/globjects/GLIncludes.h>
81 #include "GUIOSGBuilder.h"
82 #include "GUIOSGView.h"
83
84
85 FXDEFMAP(GUIOSGView) GUIOSGView_Map[] = {
86 //________Message_Type_________ ___ID___ ________Message_Handler________
87 FXMAPFUNC(SEL_CHORE, MID_CHORE, GUIOSGView::OnIdle)
88 };
89 FXIMPLEMENT(GUIOSGView, GUISUMOAbstractView, GUIOSGView_Map, ARRAYNUMBER(GUIOSGView_Map))
90
91
92 std::ostream&
93 operator<<(std::ostream& os, const osg::Vec3d& v) {
94 return os << v.x() << "," << v.y() << "," << v.z();
95 }
96
97
98 // ===========================================================================
99 // GUIOSGView::Command_TLSChange member method definitions
100 // ===========================================================================
Command_TLSChange(const MSLink * const link,osg::Switch * switchNode)101 GUIOSGView::Command_TLSChange::Command_TLSChange(const MSLink* const link, osg::Switch* switchNode)
102 : myLink(link), mySwitch(switchNode), myLastState(LINKSTATE_TL_OFF_NOSIGNAL) {
103 execute();
104 }
105
106
~Command_TLSChange()107 GUIOSGView::Command_TLSChange::~Command_TLSChange() {}
108
109
110 void
execute()111 GUIOSGView::Command_TLSChange::execute() {
112 switch (myLink->getState()) {
113 case LINKSTATE_TL_GREEN_MAJOR:
114 case LINKSTATE_TL_GREEN_MINOR:
115 mySwitch->setSingleChildOn(0);
116 break;
117 case LINKSTATE_TL_YELLOW_MAJOR:
118 case LINKSTATE_TL_YELLOW_MINOR:
119 mySwitch->setSingleChildOn(1);
120 break;
121 case LINKSTATE_TL_RED:
122 mySwitch->setSingleChildOn(2);
123 break;
124 case LINKSTATE_TL_REDYELLOW:
125 mySwitch->setSingleChildOn(3);
126 break;
127 default:
128 mySwitch->setAllChildrenOff();
129 }
130 myLastState = myLink->getState();
131 }
132
133
134
135 // ===========================================================================
136 // GUIOSGView member method definitions
137 // ===========================================================================
GUIOSGView(FXComposite * p,GUIMainWindow & app,GUISUMOViewParent * parent,GUINet & net,FXGLVisual * glVis,FXGLCanvas * share)138 GUIOSGView::GUIOSGView(
139 FXComposite* p,
140 GUIMainWindow& app,
141 GUISUMOViewParent* parent,
142 GUINet& net, FXGLVisual* glVis,
143 FXGLCanvas* share) :
144 GUISUMOAbstractView(p, app, parent, net.getVisualisationSpeedUp(), glVis, share),
145 myTracked(0), myCameraManipulator(new SUMOTerrainManipulator()), myLastUpdate(-1) {
146
147 //FXGLVisual* glVisual=new FXGLVisual(getApp(),VISUAL_DOUBLEBUFFER|VISUAL_STEREO);
148
149 //m_gwFox = new GraphicsWindowFOX(this, glVisual, NULL, NULL, LAYOUT_FILL_X|LAYOUT_FILL_Y, x, y, w, h );
150
151 int w = getWidth();
152 int h = getHeight();
153 myAdapter = new FXOSGAdapter(this, new FXCursor(parent->getApp(), CURSOR_CROSS));
154
155 myViewer = new osgViewer::Viewer();
156 myViewer->getCamera()->setGraphicsContext(myAdapter);
157 myViewer->getCamera()->setViewport(0, 0, w, h);
158 myViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
159
160 const char* sumoPath = getenv("SUMO_HOME");
161 if (sumoPath != 0) {
162 std::string newPath = std::string(sumoPath) + "/data/3D";
163 if (FileHelpers::isReadable(newPath)) {
164 osgDB::FilePathList path = osgDB::Registry::instance()->getDataFilePathList();
165 path.push_back(newPath);
166 osgDB::Registry::instance()->setDataFilePathList(path);
167 }
168 }
169
170 myGreenLight = osgDB::readNodeFile("tlg.obj");
171 myYellowLight = osgDB::readNodeFile("tly.obj");
172 myRedLight = osgDB::readNodeFile("tlr.obj");
173 myRedYellowLight = osgDB::readNodeFile("tlu.obj");
174 if (myGreenLight == 0 || myYellowLight == 0 || myRedLight == 0 || myRedYellowLight == 0) {
175 WRITE_ERROR("Could not load traffic light files.");
176 }
177 myRoot = GUIOSGBuilder::buildOSGScene(myGreenLight, myYellowLight, myRedLight, myRedYellowLight);
178 // add the stats handler
179 myViewer->addEventHandler(new osgViewer::StatsHandler());
180 myViewer->setSceneData(myRoot);
181 myViewer->setCameraManipulator(myCameraManipulator);
182 osg::Vec3d lookFrom, lookAt, up;
183 myCameraManipulator->getHomePosition(lookFrom, lookAt, up);
184 double z = lookFrom[2];
185 lookFrom[2] = -lookFrom.y();
186 lookFrom[1] = z;
187 myCameraManipulator->setHomePosition(lookFrom, lookAt, up);
188 myViewer->home();
189 getApp()->addChore(this, MID_CHORE);
190 }
191
192
~GUIOSGView()193 GUIOSGView::~GUIOSGView() {
194 getApp()->removeChore(this, MID_CHORE);
195 myViewer->setDone(true);
196 myViewer = 0;
197 myRoot = 0;
198 myAdapter = 0;
199 }
200
201
202 void
buildViewToolBars(GUIGlChildWindow & v)203 GUIOSGView::buildViewToolBars(GUIGlChildWindow& v) {
204 // build coloring tools
205 {
206 const std::vector<std::string>& names = gSchemeStorage.getNames();
207 for (std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) {
208 v.getColoringSchemesCombo()->appendItem(i->c_str());
209 if ((*i) == myVisualizationSettings->name) {
210 v.getColoringSchemesCombo()->setCurrentItem(v.getColoringSchemesCombo()->getNumItems() - 1);
211 }
212 }
213 v.getColoringSchemesCombo()->setNumVisible(5);
214 }
215 // for junctions
216 new FXButton(v.getLocatorPopup(),
217 "\tLocate Junction\tLocate a junction within the network.",
218 GUIIconSubSys::getIcon(ICON_LOCATEJUNCTION), &v, MID_LOCATEJUNCTION,
219 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
220 // for edges
221 new FXButton(v.getLocatorPopup(),
222 "\tLocate Street\tLocate a street within the network.",
223 GUIIconSubSys::getIcon(ICON_LOCATEEDGE), &v, MID_LOCATEEDGE,
224 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
225 // for vehicles
226 new FXButton(v.getLocatorPopup(),
227 "\tLocate Vehicle\tLocate a vehicle within the network.",
228 GUIIconSubSys::getIcon(ICON_LOCATEVEHICLE), &v, MID_LOCATEVEHICLE,
229 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
230 // for persons
231 new FXButton(v.getLocatorPopup(),
232 "\tLocate Vehicle\tLocate a person within the network.",
233 GUIIconSubSys::getIcon(ICON_LOCATEPERSON), &v, MID_LOCATEPERSON,
234 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
235 // for tls
236 new FXButton(v.getLocatorPopup(),
237 "\tLocate TLS\tLocate a tls within the network.",
238 GUIIconSubSys::getIcon(ICON_LOCATETLS), &v, MID_LOCATETLS,
239 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
240 // for additional stuff
241 new FXButton(v.getLocatorPopup(),
242 "\tLocate Additional\tLocate an additional structure within the network.",
243 GUIIconSubSys::getIcon(ICON_LOCATEADD), &v, MID_LOCATEADD,
244 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
245 // for pois
246 new FXButton(v.getLocatorPopup(),
247 "\tLocate POI\tLocate a POI within the network.",
248 GUIIconSubSys::getIcon(ICON_LOCATEPOI), &v, MID_LOCATEPOI,
249 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
250 // for polygons
251 new FXButton(v.getLocatorPopup(),
252 "\tLocate Polygon\tLocate a Polygon within the network.",
253 GUIIconSubSys::getIcon(ICON_LOCATEPOLY), &v, MID_LOCATEPOLY,
254 ICON_ABOVE_TEXT | FRAME_THICK | FRAME_RAISED);
255 }
256
257
258 void
recenterView()259 GUIOSGView::recenterView() {
260 stopTrack();
261 Position center = myGrid->getCenter();
262 osg::Vec3d lookFromOSG, lookAtOSG, up;
263 myViewer->getCameraManipulator()->getHomePosition(lookFromOSG, lookAtOSG, up);
264 lookFromOSG[0] = center.x();
265 lookFromOSG[1] = center.y();
266 lookFromOSG[2] = myChanger->zoom2ZPos(100);
267 lookAtOSG[0] = center.x();
268 lookAtOSG[1] = center.y();
269 lookAtOSG[2] = 0;
270 myViewer->getCameraManipulator()->setHomePosition(lookFromOSG, lookAtOSG, up);
271 myViewer->home();
272 }
273
274
275 void
centerTo(GUIGlID id,bool,double)276 GUIOSGView::centerTo(GUIGlID id, bool /* applyZoom */, double /* zoomDist */) {
277 startTrack(id);
278 }
279
280
281 bool
setColorScheme(const std::string & name)282 GUIOSGView::setColorScheme(const std::string& name) {
283 if (!gSchemeStorage.contains(name)) {
284 return false;
285 }
286 if (myVisualizationChanger != 0) {
287 if (myVisualizationChanger->getCurrentScheme() != name) {
288 myVisualizationChanger->setCurrentScheme(name);
289 }
290 }
291 myVisualizationSettings = &gSchemeStorage.get(name.c_str());
292 myVisualizationSettings->gaming = myApp->isGaming();
293 update();
294 return true;
295 }
296
297
298 long
onPaint(FXObject *,FXSelector,void *)299 GUIOSGView::onPaint(FXObject*, FXSelector, void*) {
300 if (!isEnabled()) {
301 return 1;
302 }
303 myDecalsLock.lock();
304 for (std::vector<GUISUMOAbstractView::Decal>::iterator l = myDecals.begin(); l != myDecals.end(); ++l) {
305 GUISUMOAbstractView::Decal& d = *l;
306 if (!d.initialised) {
307 if (d.filename.length() == 6 && d.filename.substr(0, 5) == "light") {
308 GUIOSGBuilder::buildLight(d, *myRoot);
309 } else if (d.filename.length() > 3 && d.filename.substr(0, 3) == "tl:") {
310 const int linkStringIdx = (int)d.filename.find(':', 3);
311 GUINet* net = (GUINet*) MSNet::getInstance();
312 try {
313 MSTLLogicControl::TLSLogicVariants& vars = net->getTLSControl().get(d.filename.substr(3, linkStringIdx - 3));
314 const int linkIdx = StringUtils::toInt(d.filename.substr(linkStringIdx + 1));
315 if (linkIdx < 0 || linkIdx >= static_cast<int>(vars.getActive()->getLinks().size())) {
316 throw NumberFormatException("");
317 }
318 const MSLink* const l = vars.getActive()->getLinksAt(linkIdx)[0];
319 osg::Switch* switchNode = new osg::Switch();
320 switchNode->addChild(GUIOSGBuilder::getTrafficLight(d, d.layer < 0 ? 0 : myGreenLight, osg::Vec4d(0., 1., 0., .3)), false);
321 switchNode->addChild(GUIOSGBuilder::getTrafficLight(d, d.layer < 0 ? 0 : myYellowLight, osg::Vec4d(1., 1., 0., .3)), false);
322 switchNode->addChild(GUIOSGBuilder::getTrafficLight(d, d.layer < 0 ? 0 : myRedLight, osg::Vec4d(1., 0., 0., .3)), false);
323 switchNode->addChild(GUIOSGBuilder::getTrafficLight(d, d.layer < 0 ? 0 : myRedYellowLight, osg::Vec4d(1., .5, 0., .3)), false);
324 myRoot->addChild(switchNode);
325 vars.addSwitchCommand(new Command_TLSChange(l, switchNode));
326 } catch (NumberFormatException&) {
327 WRITE_ERROR("Invalid link index in '" + d.filename + "'.");
328 } catch (InvalidArgument&) {
329 WRITE_ERROR("Unknown traffic light in '" + d.filename + "'.");
330 }
331 } else {
332 GUIOSGBuilder::buildDecal(d, *myRoot);
333 }
334 d.initialised = true;
335 }
336 }
337 myDecalsLock.unlock();
338 MSVehicleControl::constVehIt it = MSNet::getInstance()->getVehicleControl().loadedVehBegin();
339 // reset active flag
340 for (auto& item : myVehicles) {
341 item.second.active = false;
342 }
343 for (; it != MSNet::getInstance()->getVehicleControl().loadedVehEnd(); it++) {
344 GUIVehicle* veh = static_cast<GUIVehicle*>(it->second);
345 if (!(veh->isOnRoad() || veh->isParking() || veh->wasRemoteControlled())) {
346 continue;
347 }
348 auto itVeh = myVehicles.find(veh);
349 if (itVeh == myVehicles.end()) {
350 myVehicles[veh] = GUIOSGBuilder::buildMovable(veh->getVehicleType());
351 myRoot->addChild(myVehicles[veh].pos);
352 } else {
353 itVeh->second.active = true;
354 }
355 osg::PositionAttitudeTransform* n = myVehicles[veh].pos;
356 n->setPosition(osg::Vec3d(veh->getPosition().x(), veh->getPosition().y(), veh->getPosition().z()));
357 const double dir = veh->getAngle() + M_PI / 2.;
358 const double slope = veh->getSlope();
359 n->setAttitude(osg::Quat(dir, osg::Vec3d(0, 0, 1)) *
360 osg::Quat(osg::DegreesToRadians(slope), osg::Vec3d(0, 1, 0)));
361 /*
362 osg::ref_ptr<osg::AnimationPath> path = new osg::AnimationPath;
363 // path->setLoopMode( osg::AnimationPath::NO_LOOPING );
364 osg::AnimationPath::ControlPoint pointA(n->getPosition(), n->getAttitude());
365 osg::AnimationPath::ControlPoint pointB(osg::Vec3(veh->getPosition().x(), veh->getPosition().y(), veh->getPosition().z()),
366 osg::Quat(dir, osg::Vec3(0, 0, 1)) *
367 osg::Quat(osg::DegreesToRadians(slope), osg::Vec3(0, 1, 0)));
368 path->insert(0.0f, pointA);
369 path->insert(0.5f, pointB);
370 n->setUpdateCallback(new osg::AnimationPathCallback(path));
371 */
372 const RGBColor& col = myVisualizationSettings->vehicleColorer.getScheme().getColor(veh->getColorValue(myVisualizationSettings->vehicleColorer.getActive()));
373 myVehicles[veh].geom->setColor(osg::Vec4d(col.red() / 255., col.green() / 255., col.blue() / 255., col.alpha() / 255.));
374 myVehicles[veh].lights->setValue(0, veh->signalSet(MSVehicle::VEH_SIGNAL_BLINKER_RIGHT | MSVehicle::VEH_SIGNAL_BLINKER_EMERGENCY));
375 myVehicles[veh].lights->setValue(1, veh->signalSet(MSVehicle::VEH_SIGNAL_BLINKER_LEFT | MSVehicle::VEH_SIGNAL_BLINKER_EMERGENCY));
376 myVehicles[veh].lights->setValue(2, veh->signalSet(MSVehicle::VEH_SIGNAL_BRAKELIGHT));
377 }
378 // remove inactive
379 for (auto it = myVehicles.begin(); it != myVehicles.end();) {
380 if (!it->second.active) {
381 removeVeh((it++)->first);
382 } else {
383 ++it;
384 }
385 }
386
387 const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
388 if (now != myLastUpdate || (myVisualizationChanger != 0 && myVisualizationChanger->shown())) {
389 GUINet::getGUIInstance()->updateColor(*myVisualizationSettings);
390 }
391 if (now != myLastUpdate && myTracked != 0) {
392 osg::Vec3d lookFrom, lookAt, up;
393 lookAt[0] = myTracked->getPosition().x();
394 lookAt[1] = myTracked->getPosition().y();
395 lookAt[2] = myTracked->getPosition().z();
396 const double angle = myTracked->getAngle();
397 lookFrom[0] = lookAt[0] + 50. * cos(angle);
398 lookFrom[1] = lookAt[1] + 50. * sin(angle);
399 lookFrom[2] = lookAt[2] + 10.;
400 osg::Matrix m;
401 m.makeLookAt(lookFrom, lookAt, osg::Z_AXIS);
402 myCameraManipulator->setByInverseMatrix(m);
403 }
404
405 // reset active flag
406 for (auto& item : myPersons) {
407 item.second.active = false;
408 }
409 for (std::map<std::string, MSTransportable*>::const_iterator it = MSNet::getInstance()->getPersonControl().loadedBegin(); it != MSNet::getInstance()->getPersonControl().loadedEnd(); ++it) {
410 MSTransportable* person = (*it).second;
411 // XXX if not departed: continue
412 if (person->hasArrived() || !person->hasDeparted()) {
413 //std::cout << SIMTIME << " person " << person->getID() << " is loaded but arrived\n";
414 continue;
415 }
416 auto itPers = myPersons.find(person);
417 if (itPers == myPersons.end()) {
418 myPersons[person] = GUIOSGBuilder::buildMovable(person->getVehicleType());
419 myRoot->addChild(myPersons[person].pos);
420 } else {
421 itPers->second.active = true;
422 }
423 osg::PositionAttitudeTransform* n = myPersons[person].pos;
424 const Position pos = person->getPosition();
425 n->setPosition(osg::Vec3d(pos.x(), pos.y(), pos.z()));
426 const double dir = person->getAngle() + M_PI / 2.;
427 n->setAttitude(osg::Quat(dir, osg::Vec3d(0, 0, 1)));
428 }
429 // remove inactive
430 for (auto it = myPersons.begin(); it != myPersons.end();) {
431 if (!it->second.active) {
432 removeTransportable((it++)->first);
433 } else {
434 ++it;
435 }
436 }
437
438
439 if (myAdapter->makeCurrent()) {
440 myViewer->frame();
441 makeNonCurrent();
442 }
443 myLastUpdate = now;
444 return 1;
445 }
446
447
448 void
removeVeh(MSVehicle * veh)449 GUIOSGView::removeVeh(MSVehicle* veh) {
450 if (myTracked == veh) {
451 stopTrack();
452 }
453 std::map<MSVehicle*, OSGMovable>::iterator i = myVehicles.find(veh);
454 if (i != myVehicles.end()) {
455 myRoot->removeChild(i->second.pos);
456 myVehicles.erase(i);
457 }
458 }
459
460
461 void
removeTransportable(MSTransportable * t)462 GUIOSGView::removeTransportable(MSTransportable* t) {
463 std::map<MSTransportable*, OSGMovable>::iterator i = myPersons.find(t);
464 if (i != myPersons.end()) {
465 myRoot->removeChild(i->second.pos);
466 myPersons.erase(i);
467 }
468 }
469
470
471 void
showViewportEditor()472 GUIOSGView::showViewportEditor() {
473 getViewportEditor(); // make sure it exists;
474 osg::Vec3d lookFromOSG, lookAtOSG, up;
475 myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFromOSG, lookAtOSG, up);
476 Position from(lookFromOSG[0], lookFromOSG[1], lookFromOSG[2]), at(lookAtOSG[0], lookAtOSG[1], lookAtOSG[2]);
477 myViewportChooser->setOldValues(from, at, 0);
478 myViewportChooser->show();
479 }
480
481
482 void
setViewportFromToRot(const Position & lookFrom,const Position & lookAt,double)483 GUIOSGView::setViewportFromToRot(const Position& lookFrom, const Position& lookAt, double /*rotation*/) {
484 osg::Vec3d lookFromOSG, lookAtOSG, up;
485 myViewer->getCameraManipulator()->getHomePosition(lookFromOSG, lookAtOSG, up);
486 lookFromOSG[0] = lookFrom.x();
487 lookFromOSG[1] = lookFrom.y();
488 lookFromOSG[2] = lookFrom.z();
489 lookAtOSG[0] = lookAt.x();
490 lookAtOSG[1] = lookAt.y();
491 lookAtOSG[2] = lookAt.z();
492 myViewer->getCameraManipulator()->setHomePosition(lookFromOSG, lookAtOSG, up);
493 myViewer->home();
494 }
495
496
497
498 void
copyViewportTo(GUISUMOAbstractView * view)499 GUIOSGView::copyViewportTo(GUISUMOAbstractView* view) {
500 osg::Vec3d lookFrom, lookAt, up;
501 myCameraManipulator->getHomePosition(lookFrom, lookAt, up);
502 view->setViewportFromToRot(Position(lookFrom[0], lookFrom[1], lookFrom[2]),
503 Position(lookAt[0], lookAt[1], lookAt[2]), 0);
504 }
505
506
507
508 void
startTrack(int id)509 GUIOSGView::startTrack(int id) {
510 if (myTracked == 0 || (int)myTracked->getGlID() != id) {
511 myTracked = 0;
512 MSVehicleControl::constVehIt it = MSNet::getInstance()->getVehicleControl().loadedVehBegin();
513 for (; it != MSNet::getInstance()->getVehicleControl().loadedVehEnd(); it++) {
514 GUIVehicle* veh = (GUIVehicle*)(*it).second;
515 if ((int)veh->getGlID() == id) {
516 if (!veh->isOnRoad() || myVehicles.find(veh) == myVehicles.end()) {
517 return;
518 }
519 myTracked = veh;
520 break;
521 }
522 }
523 if (myTracked != 0) {
524 osg::Vec3d lookFrom, lookAt, up;
525 lookAt[0] = myTracked->getPosition().x();
526 lookAt[1] = myTracked->getPosition().y();
527 lookAt[2] = myTracked->getPosition().z();
528 lookFrom[0] = lookAt[0] + 50.;
529 lookFrom[1] = lookAt[1] + 50.;
530 lookFrom[2] = lookAt[2] + 10.;
531 osg::Matrix m;
532 m.makeLookAt(lookFrom, lookAt, osg::Z_AXIS);
533 myCameraManipulator->setByInverseMatrix(m);
534 }
535 }
536 }
537
538
539 void
stopTrack()540 GUIOSGView::stopTrack() {
541 myTracked = 0;
542 }
543
544
545 GUIGlID
getTrackedID() const546 GUIOSGView::getTrackedID() const {
547 return myTracked == 0 ? GUIGlObject::INVALID_ID : myTracked->getGlID();
548 }
549
550
551 void
onGamingClick(Position pos)552 GUIOSGView::onGamingClick(Position pos) {
553 MSTLLogicControl& tlsControl = MSNet::getInstance()->getTLSControl();
554 const std::vector<MSTrafficLightLogic*>& logics = tlsControl.getAllLogics();
555 MSTrafficLightLogic* minTll = 0;
556 double minDist = std::numeric_limits<double>::infinity();
557 for (std::vector<MSTrafficLightLogic*>::const_iterator i = logics.begin(); i != logics.end(); ++i) {
558 // get the logic
559 MSTrafficLightLogic* tll = (*i);
560 if (tlsControl.isActive(tll)) {
561 // get the links
562 const MSTrafficLightLogic::LaneVector& lanes = tll->getLanesAt(0);
563 if (lanes.size() > 0) {
564 const Position& endPos = lanes[0]->getShape().back();
565 if (endPos.distanceTo(pos) < minDist) {
566 minDist = endPos.distanceTo(pos);
567 minTll = tll;
568 }
569 }
570 }
571 }
572 if (minTll != 0) {
573 const MSTLLogicControl::TLSLogicVariants& vars = tlsControl.get(minTll->getID());
574 const std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
575 if (logics.size() > 1) {
576 MSSimpleTrafficLightLogic* l = (MSSimpleTrafficLightLogic*) logics[0];
577 for (int i = 0; i < (int)logics.size() - 1; i++) {
578 if (minTll->getProgramID() == logics[i]->getProgramID()) {
579 l = (MSSimpleTrafficLightLogic*) logics[i + 1];
580 tlsControl.switchTo(minTll->getID(), l->getProgramID());
581 }
582 }
583 if (l == logics[0]) {
584 tlsControl.switchTo(minTll->getID(), l->getProgramID());
585 }
586 l->changeStepAndDuration(tlsControl, MSNet::getInstance()->getCurrentTimeStep(), 0, l->getPhase(0).duration);
587 update();
588 }
589 }
590 }
591
592
593 SUMOTime
getCurrentTimeStep() const594 GUIOSGView::getCurrentTimeStep() const {
595 return MSNet::getInstance()->getCurrentTimeStep();
596 }
597
598
onConfigure(FXObject * sender,FXSelector sel,void * ptr)599 long GUIOSGView::onConfigure(FXObject* sender, FXSelector sel, void* ptr) {
600 // update the window dimensions, in case the window has been resized.
601 myAdapter->getEventQueue()->windowResize(0, 0, getWidth(), getHeight());
602 myAdapter->resized(0, 0, getWidth(), getHeight());
603
604 return FXGLCanvas::onConfigure(sender, sel, ptr);
605 }
606
onKeyPress(FXObject * sender,FXSelector sel,void * ptr)607 long GUIOSGView::onKeyPress(FXObject* sender, FXSelector sel, void* ptr) {
608 int key = ((FXEvent*)ptr)->code;
609 myAdapter->getEventQueue()->keyPress(key);
610
611 return FXGLCanvas::onKeyPress(sender, sel, ptr);
612 }
613
onKeyRelease(FXObject * sender,FXSelector sel,void * ptr)614 long GUIOSGView::onKeyRelease(FXObject* sender, FXSelector sel, void* ptr) {
615 int key = ((FXEvent*)ptr)->code;
616 myAdapter->getEventQueue()->keyRelease(key);
617
618 return FXGLCanvas::onKeyRelease(sender, sel, ptr);
619 }
620
onLeftBtnPress(FXObject * sender,FXSelector sel,void * ptr)621 long GUIOSGView::onLeftBtnPress(FXObject* sender, FXSelector sel, void* ptr) {
622 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
623
624 FXEvent* event = (FXEvent*)ptr;
625 myAdapter->getEventQueue()->mouseButtonPress((float)event->click_x, (float)event->click_y, 1);
626 if (myApp->isGaming()) {
627 onGamingClick(getPositionInformation());
628 }
629
630 return FXGLCanvas::onLeftBtnPress(sender, sel, ptr);
631 }
632
onLeftBtnRelease(FXObject * sender,FXSelector sel,void * ptr)633 long GUIOSGView::onLeftBtnRelease(FXObject* sender, FXSelector sel, void* ptr) {
634 FXEvent* event = (FXEvent*)ptr;
635 myAdapter->getEventQueue()->mouseButtonRelease((float)event->click_x, (float)event->click_y, 1);
636
637 return FXGLCanvas::onLeftBtnRelease(sender, sel, ptr);
638 }
639
onMiddleBtnPress(FXObject * sender,FXSelector sel,void * ptr)640 long GUIOSGView::onMiddleBtnPress(FXObject* sender, FXSelector sel, void* ptr) {
641 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
642
643 FXEvent* event = (FXEvent*)ptr;
644 myAdapter->getEventQueue()->mouseButtonPress((float)event->click_x, (float)event->click_y, 2);
645
646 return FXGLCanvas::onMiddleBtnPress(sender, sel, ptr);
647 }
648
onMiddleBtnRelease(FXObject * sender,FXSelector sel,void * ptr)649 long GUIOSGView::onMiddleBtnRelease(FXObject* sender, FXSelector sel, void* ptr) {
650 FXEvent* event = (FXEvent*)ptr;
651 myAdapter->getEventQueue()->mouseButtonRelease((float)event->click_x, (float)event->click_y, 2);
652
653 return FXGLCanvas::onMiddleBtnRelease(sender, sel, ptr);
654 }
655
onRightBtnPress(FXObject * sender,FXSelector sel,void * ptr)656 long GUIOSGView::onRightBtnPress(FXObject* sender, FXSelector sel, void* ptr) {
657 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
658
659 FXEvent* event = (FXEvent*)ptr;
660 myAdapter->getEventQueue()->mouseButtonPress((float)event->click_x, (float)event->click_y, 3);
661
662 return FXGLCanvas::onRightBtnPress(sender, sel, ptr);
663 }
664
onRightBtnRelease(FXObject * sender,FXSelector sel,void * ptr)665 long GUIOSGView::onRightBtnRelease(FXObject* sender, FXSelector sel, void* ptr) {
666 FXEvent* event = (FXEvent*)ptr;
667 myAdapter->getEventQueue()->mouseButtonRelease((float)event->click_x, (float)event->click_y, 3);
668
669 return FXGLCanvas::onRightBtnRelease(sender, sel, ptr);
670 }
671
672 long
onMouseMove(FXObject * sender,FXSelector sel,void * ptr)673 GUIOSGView::onMouseMove(FXObject* sender, FXSelector sel, void* ptr) {
674 FXEvent* event = (FXEvent*)ptr;
675 myAdapter->getEventQueue()->mouseMotion((float)event->win_x, (float)event->win_y);
676
677 return FXGLCanvas::onMotion(sender, sel, ptr);
678 }
679
680 long
OnIdle(FXObject *,FXSelector,void *)681 GUIOSGView::OnIdle(FXObject* /* sender */, FXSelector /* sel */, void*) {
682 forceRefresh();
683 update();
684 getApp()->addChore(this, MID_CHORE);
685 return 1;
686 }
687
688
689
FXOSGAdapter(GUISUMOAbstractView * parent,FXCursor * cursor)690 GUIOSGView::FXOSGAdapter::FXOSGAdapter(GUISUMOAbstractView* parent, FXCursor* cursor)
691 : myParent(parent), myOldCursor(cursor) {
692 _traits = new GraphicsContext::Traits();
693 _traits->x = 0;
694 _traits->y = 0;
695 _traits->width = parent->getWidth();
696 _traits->height = parent->getHeight();
697 _traits->windowDecoration = false;
698 _traits->doubleBuffer = true;
699 _traits->sharedContext = 0;
700 if (valid()) {
701 setState(new osg::State());
702 getState()->setGraphicsContext(this);
703 if (_traits.valid() && _traits->sharedContext != 0) {
704 getState()->setContextID(_traits->sharedContext->getState()->getContextID());
705 incrementContextIDUsageCount(getState()->getContextID());
706 } else {
707 getState()->setContextID(createNewContextID());
708 }
709 }
710 }
711
712
~FXOSGAdapter()713 GUIOSGView::FXOSGAdapter::~FXOSGAdapter() {
714 delete myOldCursor;
715 }
716
717
grabFocus()718 void GUIOSGView::FXOSGAdapter::grabFocus() {
719 // focus this window
720 myParent->setFocus();
721 }
722
useCursor(bool cursorOn)723 void GUIOSGView::FXOSGAdapter::useCursor(bool cursorOn) {
724 if (cursorOn) {
725 myParent->setDefaultCursor(myOldCursor);
726 } else {
727 myParent->setDefaultCursor(NULL);
728 }
729 }
730
makeCurrentImplementation()731 bool GUIOSGView::FXOSGAdapter::makeCurrentImplementation() {
732 myParent->makeCurrent();
733 return true;
734 }
735
releaseContext()736 bool GUIOSGView::FXOSGAdapter::releaseContext() {
737 myParent->makeNonCurrent();
738 return true;
739 }
740
swapBuffersImplementation()741 void GUIOSGView::FXOSGAdapter::swapBuffersImplementation() {
742 myParent->swapBuffers();
743 }
744
745
746 #endif
747
748 /****************************************************************************/
749