Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file GUISUMOViewParent.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @author Laura Bieker
19 : /// @author Andreas Gaubatz
20 : /// @date Sept 2002
21 : ///
22 : // A single child window which contains a view of the simulation area
23 : /****************************************************************************/
24 :
25 : #include <utils/common/MsgHandler.h>
26 : #include <utils/foxtools/MFXCheckableButton.h>
27 : #include <utils/foxtools/MFXMenuButtonTooltip.h>
28 : #include <utils/gui/globjects/GUIShapeContainer.h>
29 : #include <utils/gui/div/GUIGlobalSelection.h>
30 : #include <utils/gui/div/GUIDesigns.h>
31 : #include <gui/dialogs/GUIDialog_GLObjChooser.h>
32 : #include <guisim/GUIPerson.h>
33 : #include <guisim/GUIEdge.h>
34 : #include <guisim/GUILane.h>
35 : #include <guisim/GUINet.h>
36 : #include <guisim/GUIVehicleControl.h>
37 : #include <guisim/GUITransportableControl.h>
38 :
39 : #include "GUIViewTraffic.h"
40 : #include "GUIApplicationWindow.h"
41 : #include "GUISUMOViewParent.h"
42 :
43 : #include <mesogui/GUIMEVehicleControl.h>
44 :
45 : #include <osgview/GUIOSGView.h>
46 :
47 : #define SPEEDFACTOR_SCALE 100.0
48 :
49 : // ===========================================================================
50 : // FOX callback mapping
51 : // ===========================================================================
52 : FXDEFMAP(GUISUMOViewParent) GUISUMOViewParentMap[] = {
53 : FXMAPFUNC(SEL_COMMAND, MID_MAKESNAPSHOT, GUISUMOViewParent::onCmdMakeSnapshot),
54 : // FXMAPFUNC(SEL_COMMAND, MID_ALLOWROTATION, GUISUMOViewParent::onCmdAllowRotation),
55 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_J_LOCATEJUNCTION, GUISUMOViewParent::onCmdLocate),
56 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_E_LOCATEEDGE, GUISUMOViewParent::onCmdLocate),
57 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_V_LOCATEVEHICLE, GUISUMOViewParent::onCmdLocate),
58 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_P_LOCATEPERSON, GUISUMOViewParent::onCmdLocate),
59 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_C_LOCATECONTAINER, GUISUMOViewParent::onCmdLocate),
60 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_T_LOCATETLS, GUISUMOViewParent::onCmdLocate),
61 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL, GUISUMOViewParent::onCmdLocate),
62 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_O_LOCATEPOI, GUISUMOViewParent::onCmdLocate),
63 : FXMAPFUNC(SEL_COMMAND, MID_HOTKEY_SHIFT_L_LOCATEPOLY, GUISUMOViewParent::onCmdLocate),
64 :
65 : FXMAPFUNC(SEL_UPDATE, MID_SPEEDFACTOR, GUISUMOViewParent::onUpdSpeedFactor),
66 : FXMAPFUNC(SEL_COMMAND, MID_SPEEDFACTOR, GUISUMOViewParent::onCmdSpeedFactor),
67 : FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUISUMOViewParent::onSimStep),
68 :
69 : };
70 :
71 : // Object implementation
72 26197063 : FXIMPLEMENT(GUISUMOViewParent, GUIGlChildWindow, GUISUMOViewParentMap, ARRAYNUMBER(GUISUMOViewParentMap))
73 :
74 :
75 : // ===========================================================================
76 : // member method definitions
77 : // ===========================================================================
78 7090 : GUISUMOViewParent::GUISUMOViewParent(FXMDIClient* p, FXMDIMenu* mdimenu,
79 : const FXString& name,
80 : GUIMainWindow* parentWindow,
81 : FXIcon* ic, FXuint opts,
82 7090 : FXint x, FXint y, FXint w, FXint h) :
83 7090 : GUIGlChildWindow(p, parentWindow, mdimenu, name, nullptr, ic, opts, x, y, w, h) {
84 7090 : buildSpeedControlToolbar();
85 7090 : myGUIMainWindowParent->addGLChild(this);
86 7090 : }
87 :
88 :
89 : GUISUMOAbstractView*
90 7090 : GUISUMOViewParent::init(FXGLCanvas* share, GUINet& net, GUISUMOViewParent::ViewType type) {
91 7090 : switch (type) {
92 6679 : default:
93 : case VIEW_2D_OPENGL:
94 6679 : myView = new GUIViewTraffic(myChildWindowContentFrame, *myGUIMainWindowParent, this, net, myGUIMainWindowParent->getGLVisual(), share);
95 6679 : break;
96 : #ifdef HAVE_OSG
97 411 : case VIEW_3D_OSG:
98 411 : myView = new GUIOSGView(myChildWindowContentFrame, *myGUIMainWindowParent, this, net, myGUIMainWindowParent->getGLVisual(), share);
99 411 : break;
100 : #endif
101 : }
102 7090 : myView->buildViewToolBars(this);
103 7090 : if (myGUIMainWindowParent->isGaming()) {
104 0 : myStaticNavigationToolBar->hide();
105 : }
106 7090 : return myView;
107 : }
108 :
109 :
110 14160 : GUISUMOViewParent::~GUISUMOViewParent() {
111 7080 : myGUIMainWindowParent->removeGLChild(this);
112 14160 : }
113 :
114 :
115 : void
116 0 : GUISUMOViewParent::setToolBarVisibility(const bool value) {
117 0 : if (value) {
118 0 : myStaticNavigationToolBar->show();
119 : } else {
120 0 : myStaticNavigationToolBar->hide();
121 : }
122 0 : }
123 :
124 :
125 : void
126 0 : GUISUMOViewParent::eraseGLObjChooser(GUIDialog_GLObjChooser* GLObjChooser) {
127 0 : myGLObjChooser[GLObjChooser->getMessageId()] = nullptr;
128 0 : }
129 :
130 :
131 : long
132 0 : GUISUMOViewParent::onCmdMakeSnapshot(FXObject* sender, FXSelector, void*) {
133 0 : MFXCheckableButton* button = dynamic_cast<MFXCheckableButton*>(sender);
134 : // check if cast was successfully
135 0 : if (button) {
136 0 : if (button->amChecked()) {
137 0 : myView->endSnapshot();
138 0 : button->setChecked(false);
139 0 : return 1;
140 : }
141 : // get the new file name
142 0 : FXFileDialog opendialog(this, TL("Save Snapshot"));
143 0 : opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::CAMERA));
144 0 : opendialog.setSelectMode(SELECTFILE_ANY);
145 : #ifdef HAVE_FFMPEG
146 0 : opendialog.setPatternList("All Image and Video Files (*.gif,*.bmp,*.xpm,*.pcx,*.ico,*.rgb,*.xbm,*.tga,*.png,*.jpg,*.jpeg,*.tif,*.tiff,*.ps,*.eps,*.pdf,*.svg,*.tex,*.pgf,*.h264,*.hevc,*.mp4)\n"
147 : "All Video Files (*.h264,*.hevc,*.mp4)\n"
148 : #else
149 : opendialog.setPatternList("All Image Files (*.gif,*.bmp,*.xpm,*.pcx,*.ico,*.rgb,*.xbm,*.tga,*.png,*.jpg,*.jpeg,*.tif,*.tiff,*.ps,*.eps,*.pdf,*.svg,*.tex,*.pgf)\n"
150 : #endif
151 : "GIF Image (*.gif)\nBMP Image (*.bmp)\nXPM Image (*.xpm)\nPCX Image (*.pcx)\nICO Image (*.ico)\n"
152 : "RGB Image (*.rgb)\nXBM Image (*.xbm)\nTARGA Image (*.tga)\nPNG Image (*.png)\n"
153 : "JPEG Image (*.jpg,*.jpeg)\nTIFF Image (*.tif,*.tiff)\n"
154 : "Postscript (*.ps)\nEncapsulated Postscript (*.eps)\nPortable Document Format (*.pdf)\n"
155 : "Scalable Vector Graphics (*.svg)\nLATEX text strings (*.tex)\nPortable LaTeX Graphics (*.pgf)\n"
156 : "All Files (*)");
157 0 : if (gCurrentFolder.length() != 0) {
158 0 : opendialog.setDirectory(gCurrentFolder);
159 : }
160 0 : if (!opendialog.execute() || !MFXUtils::userPermitsOverwritingWhenFileExists(this, opendialog.getFilename())) {
161 : return 1;
162 : }
163 0 : gCurrentFolder = opendialog.getDirectory();
164 0 : std::string file = opendialog.getFilename().text();
165 0 : if (file.find(".") == std::string::npos) {
166 0 : file.append(".png");
167 0 : WRITE_MESSAGE(TL("No file extension was specified - saving Snapshot as PNG."));
168 : }
169 0 : std::string error = myView->makeSnapshot(file);
170 0 : if (error == "video") {
171 0 : button->setChecked(!button->amChecked());
172 0 : } else if (error != "") {
173 0 : FXMessageBox::error(this, MBOX_OK, TL("Saving failed."), "%s", error.c_str());
174 : } else {
175 0 : WRITE_MESSAGE(TL("Snapshot successfully saved!"));
176 : }
177 0 : }
178 : return 1;
179 : }
180 :
181 :
182 : std::vector<GUIGlID>
183 0 : GUISUMOViewParent::getObjectIDs(int messageId) const {
184 0 : switch (messageId) {
185 0 : case MID_HOTKEY_SHIFT_J_LOCATEJUNCTION:
186 0 : return static_cast<GUINet*>(GUINet::getInstance())->getJunctionIDs(myGUIMainWindowParent->listInternal());
187 0 : case MID_HOTKEY_SHIFT_E_LOCATEEDGE:
188 0 : return GUIEdge::getIDs(myGUIMainWindowParent->listInternal());
189 : case MID_HOTKEY_SHIFT_V_LOCATEVEHICLE: {
190 : std::vector<GUIGlID> vehicles;
191 0 : if (MSGlobals::gUseMesoSim) {
192 0 : static_cast<GUIMEVehicleControl*>(static_cast<GUINet*>(MSNet::getInstance())->getGUIMEVehicleControl())->insertVehicleIDs(vehicles);
193 : } else {
194 0 : static_cast<GUIVehicleControl&>(MSNet::getInstance()->getVehicleControl()).insertVehicleIDs(
195 0 : vehicles, myGUIMainWindowParent->listParking(), myGUIMainWindowParent->listTeleporting());
196 : }
197 : return vehicles;
198 0 : }
199 : case MID_HOTKEY_SHIFT_P_LOCATEPERSON: {
200 : std::vector<GUIGlID> persons;
201 0 : static_cast<GUITransportableControl&>(MSNet::getInstance()->getPersonControl()).insertIDs(persons);
202 : return persons;
203 0 : }
204 : case MID_HOTKEY_SHIFT_C_LOCATECONTAINER: {
205 : // get containers
206 : std::vector<GUIGlID> containers;
207 0 : static_cast<GUITransportableControl&>(MSNet::getInstance()->getContainerControl()).insertIDs(containers);
208 : return containers;
209 0 : }
210 0 : case MID_HOTKEY_SHIFT_T_LOCATETLS:
211 0 : return static_cast<GUINet*>(GUINet::getInstance())->getTLSIDs();
212 0 : case MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL:
213 0 : return GUIGlObject_AbstractAdd::getIDList(GLO_ADDITIONALELEMENT);
214 0 : case MID_HOTKEY_SHIFT_O_LOCATEPOI:
215 0 : return static_cast<GUIShapeContainer&>(GUINet::getInstance()->getShapeContainer()).getPOIIds();
216 0 : case MID_HOTKEY_SHIFT_L_LOCATEPOLY:
217 0 : return static_cast<GUIShapeContainer&>(GUINet::getInstance()->getShapeContainer()).getPolygonIDs();
218 0 : default:
219 0 : throw ProcessError(TL("Unknown Message ID in onCmdLocate"));
220 : }
221 : }
222 :
223 :
224 : long
225 0 : GUISUMOViewParent::onCmdLocate(FXObject*, FXSelector sel, void*) {
226 0 : int messageId = FXSELID(sel);
227 0 : if (myGLObjChooser.count(messageId) == 0 || myGLObjChooser[messageId] == nullptr) {
228 : FXIcon* icon = nullptr;
229 0 : std::string titleString = "";
230 0 : switch (messageId) {
231 0 : case MID_HOTKEY_SHIFT_J_LOCATEJUNCTION:
232 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEJUNCTION);
233 0 : titleString = TL("Junction Chooser");
234 : break;
235 0 : case MID_HOTKEY_SHIFT_E_LOCATEEDGE:
236 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEEDGE);
237 0 : titleString = TL("Edge Chooser");
238 : break;
239 0 : case MID_HOTKEY_SHIFT_V_LOCATEVEHICLE:
240 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEVEHICLE);
241 0 : titleString = TL("Vehicle Chooser");
242 : break;
243 0 : case MID_HOTKEY_SHIFT_P_LOCATEPERSON:
244 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEPERSON);
245 0 : titleString = TL("Person Chooser");
246 : break;
247 0 : case MID_HOTKEY_SHIFT_C_LOCATECONTAINER:
248 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATECONTAINER);
249 0 : titleString = TL("Container Chooser");
250 : break;
251 0 : case MID_HOTKEY_SHIFT_T_LOCATETLS:
252 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATETLS);
253 0 : titleString = TL("Traffic Lights Chooser");
254 : break;
255 0 : case MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL:
256 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEADD);
257 0 : titleString = TL("Additional Objects Chooser");
258 : break;
259 0 : case MID_HOTKEY_SHIFT_O_LOCATEPOI:
260 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEPOI);
261 0 : titleString = TL("POI Chooser");
262 : break;
263 0 : case MID_HOTKEY_SHIFT_L_LOCATEPOLY:
264 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEPOLY);
265 0 : titleString = TL("Polygon Chooser");
266 : break;
267 0 : default:
268 0 : throw ProcessError(TL("Unknown Message ID in onCmdLocate"));
269 : }
270 :
271 0 : myGLObjChooser[messageId] = new GUIDialog_GLObjChooser(this, messageId, icon, titleString.c_str(), getObjectIDs(messageId), GUIGlObjectStorage::gIDStorage);
272 :
273 : } else {
274 0 : myGLObjChooser[messageId]->restore();
275 0 : myGLObjChooser[messageId]->setFocus();
276 0 : myGLObjChooser[messageId]->raise();
277 : }
278 0 : myLocatorPopup->popdown();
279 0 : myLocatorButton->killFocus();
280 0 : myLocatorPopup->update();
281 0 : return 1;
282 : }
283 :
284 :
285 : long
286 5826763 : GUISUMOViewParent::onSimStep(FXObject*, FXSelector, void*) {
287 5826763 : myView->update();
288 5826763 : myView->checkSnapshots();
289 5826763 : return 1;
290 : }
291 :
292 :
293 : bool
294 0 : GUISUMOViewParent::isSelected(GUIGlObject* o) const {
295 : GUIGlObjectType type = o->getType();
296 0 : if (gSelected.isSelected(type, o->getGlID())) {
297 : return true;
298 0 : } else if (type == GLO_EDGE) {
299 0 : GUIEdge* edge = dynamic_cast<GUIEdge*>(o);
300 0 : if (edge == nullptr) {
301 : // hmph, just some security stuff
302 : return false;
303 : }
304 : const std::vector<MSLane*>& lanes = edge->getLanes();
305 0 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
306 0 : GUILane* l = dynamic_cast<GUILane*>(*j);
307 0 : if (l != nullptr && gSelected.isSelected(GLO_LANE, l->getGlID())) {
308 : return true;
309 : }
310 : }
311 : return false;
312 : } else {
313 : return false;
314 : }
315 : }
316 :
317 :
318 : long
319 0 : GUISUMOViewParent::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
320 0 : myView->onKeyPress(o, sel, ptr);
321 0 : return 0;
322 : }
323 :
324 :
325 : long
326 0 : GUISUMOViewParent::onKeyRelease(FXObject* o, FXSelector sel, void* ptr) {
327 0 : myView->onKeyRelease(o, sel, ptr);
328 0 : return 0;
329 : }
330 :
331 :
332 : void
333 7090 : GUISUMOViewParent::buildSpeedControlToolbar() {
334 7090 : auto toolbar = myGripNavigationToolbar ? myGripNavigationToolbar : myStaticNavigationToolBar;
335 7090 : new FXVerticalSeparator(toolbar, GUIDesignVerticalSeparator);
336 :
337 : //myToolBarDragSpeed = new FXToolBarShell(this, GUIDesignToolBar);
338 : //myToolBarSpeed = new FXToolBar(toolbar, myToolBarDragSpeed, GUIDesignToolBarRaisedSameTop);
339 : //mySpeedFactorSlider = new FXSlider(myToolBarSpeed, this, MID_SPEEDFACTOR, LAYOUT_FIX_WIDTH | SLIDER_ARROW_UP | SLIDER_TICKS_TOP, 0, 0, 300, 10, 0, 0, 5, 0);
340 7090 : mySpeedFactorSlider = new FXSlider(toolbar, this, MID_SPEEDFACTOR, LAYOUT_FIX_WIDTH | SLIDER_ARROW_UP | SLIDER_TICKS_TOP, 0, 0, 200, 10, 0, 0, 5, 0);
341 7090 : mySpeedFactorSlider->setRange(0, 200);
342 7090 : mySpeedFactorSlider->setHeadSize(10);
343 7090 : mySpeedFactorSlider->setIncrement(1);
344 7090 : mySpeedFactorSlider->setTickDelta(100);
345 7090 : mySpeedFactorSlider->setValue(100);
346 14180 : mySpeedFactorSlider->setHelpText("Control speedFactor of tracked object");
347 : //mySpeedFactorSlider->hide();
348 7090 : }
349 :
350 : long
351 0 : GUISUMOViewParent::onCmdSpeedFactor(FXObject*, FXSelector, void*) {
352 0 : if (myView != nullptr && myView->getTrackedID() != GUIGlObject::INVALID_ID) {
353 0 : GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(myView->getTrackedID());
354 0 : if (o != nullptr) {
355 0 : const double speedFactor = mySpeedFactorSlider->getValue() / SPEEDFACTOR_SCALE;
356 0 : if (o->getType() == GLO_VEHICLE) {
357 0 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(o);
358 0 : veh->setChosenSpeedFactor(speedFactor);
359 : } else if (o->getType() == GLO_PERSON) {
360 : //MSPerson* person = dynamic_cast<MSPerson*>(o);
361 : //person->setChosenSpeedFactor(speedFactor);
362 : }
363 0 : mySpeedFactorSlider->setTipText(toString(speedFactor).c_str());
364 : }
365 :
366 : }
367 0 : return 1;
368 : }
369 :
370 : long
371 604871 : GUISUMOViewParent::onUpdSpeedFactor(FXObject* sender, FXSelector, void* ptr) {
372 604871 : bool disable = myView == nullptr || myView->getTrackedID() == GUIGlObject::INVALID_ID;
373 604871 : sender->handle(this, FXSEL(SEL_COMMAND, disable ? ID_DISABLE : ID_ENABLE), ptr);
374 604871 : if (disable) {
375 604871 : mySpeedFactorSlider->hide();
376 : } else {
377 0 : GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(myView->getTrackedID());
378 0 : if (o != nullptr) {
379 0 : if (o->getType() == GLO_VEHICLE) {
380 0 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(o);
381 0 : mySpeedFactorSlider->setValue((int)(veh->getChosenSpeedFactor() * SPEEDFACTOR_SCALE));
382 0 : } else if (o->getType() == GLO_PERSON) {
383 0 : MSPerson* person = dynamic_cast<MSPerson*>(o);
384 0 : mySpeedFactorSlider->setValue((int)(person->getChosenSpeedFactor() * SPEEDFACTOR_SCALE));
385 : }
386 0 : mySpeedFactorSlider->show();
387 : } else {
388 0 : myView->stopTrack();
389 0 : mySpeedFactorSlider->hide();
390 : }
391 : }
392 604871 : return 1;
393 : }
394 :
395 :
396 : /****************************************************************************/
|