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