Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 16637403 : FXIMPLEMENT(GUISUMOViewParent, GUIGlChildWindow, GUISUMOViewParentMap, ARRAYNUMBER(GUISUMOViewParentMap))
73 :
74 :
75 : // ===========================================================================
76 : // member method definitions
77 : // ===========================================================================
78 7547 : GUISUMOViewParent::GUISUMOViewParent(FXMDIClient* p, FXMDIMenu* mdimenu,
79 : const FXString& name,
80 : GUIMainWindow* parentWindow,
81 : FXIcon* ic, FXuint opts,
82 7547 : FXint x, FXint y, FXint w, FXint h) :
83 7547 : GUIGlChildWindow(p, parentWindow, mdimenu, name, nullptr, ic, opts, x, y, w, h) {
84 7547 : buildSpeedControlToolbar();
85 7547 : myGUIMainWindowParent->addGLChild(this);
86 7547 : }
87 :
88 :
89 : GUISUMOAbstractView*
90 7547 : GUISUMOViewParent::init(FXGLCanvas* share, GUINet& net, GUISUMOViewParent::ViewType type) {
91 7547 : switch (type) {
92 7111 : default:
93 : case VIEW_2D_OPENGL:
94 7111 : myView = new GUIViewTraffic(myChildWindowContentFrame, *myGUIMainWindowParent, this, net, myGUIMainWindowParent->getGLVisual(), share);
95 7111 : break;
96 : #ifdef HAVE_OSG
97 436 : case VIEW_3D_OSG:
98 436 : myView = new GUIOSGView(myChildWindowContentFrame, *myGUIMainWindowParent, this, net, myGUIMainWindowParent->getGLVisual(), share);
99 436 : break;
100 : #endif
101 : }
102 7547 : myView->buildViewToolBars(this);
103 7547 : if (myGUIMainWindowParent->isGaming()) {
104 0 : myStaticNavigationToolBar->hide();
105 : }
106 7547 : return myView;
107 : }
108 :
109 :
110 15062 : GUISUMOViewParent::~GUISUMOViewParent() {
111 7531 : myGUIMainWindowParent->removeGLChild(this);
112 15062 : }
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(SUMOXMLDefinitions::ImageVideoFileExtensions.getMultilineString().c_str());
147 : #else
148 : opendialog.setPatternList(SUMOXMLDefinitions::ImageFileExtensions.getMultilineString().c_str());
149 : #endif
150 0 : if (gCurrentFolder.length() != 0) {
151 0 : opendialog.setDirectory(gCurrentFolder);
152 : }
153 0 : if (!opendialog.execute() || !MFXUtils::userPermitsOverwritingWhenFileExists(this, opendialog.getFilename())) {
154 : return 1;
155 : }
156 0 : gCurrentFolder = opendialog.getDirectory();
157 0 : std::string file = opendialog.getFilename().text();
158 0 : if (file.find(".") == std::string::npos) {
159 0 : file.append(".png");
160 0 : WRITE_MESSAGE(TL("No file extension was specified - saving Snapshot as PNG."));
161 : }
162 0 : std::string error = myView->makeSnapshot(file);
163 0 : if (error == "video") {
164 0 : button->setChecked(!button->amChecked());
165 0 : } else if (error != "") {
166 0 : FXMessageBox::error(this, MBOX_OK, TL("Saving failed."), "%s", error.c_str());
167 : } else {
168 0 : WRITE_MESSAGE(TL("Snapshot successfully saved!"));
169 : }
170 0 : }
171 : return 1;
172 : }
173 :
174 :
175 : std::vector<GUIGlID>
176 0 : GUISUMOViewParent::getObjectIDs(int messageId) const {
177 0 : switch (messageId) {
178 0 : case MID_HOTKEY_SHIFT_J_LOCATEJUNCTION:
179 0 : return static_cast<GUINet*>(GUINet::getInstance())->getJunctionIDs(myGUIMainWindowParent->listInternal());
180 0 : case MID_HOTKEY_SHIFT_E_LOCATEEDGE:
181 0 : return GUIEdge::getIDs(myGUIMainWindowParent->listInternal());
182 : case MID_HOTKEY_SHIFT_V_LOCATEVEHICLE: {
183 : std::vector<GUIGlID> vehicles;
184 0 : if (MSGlobals::gUseMesoSim) {
185 0 : static_cast<GUIMEVehicleControl*>(static_cast<GUINet*>(MSNet::getInstance())->getGUIMEVehicleControl())->insertVehicleIDs(vehicles);
186 : } else {
187 0 : static_cast<GUIVehicleControl&>(MSNet::getInstance()->getVehicleControl()).insertVehicleIDs(
188 0 : vehicles, myGUIMainWindowParent->listParking(), myGUIMainWindowParent->listTeleporting());
189 : }
190 : return vehicles;
191 0 : }
192 : case MID_HOTKEY_SHIFT_P_LOCATEPERSON: {
193 : std::vector<GUIGlID> persons;
194 0 : static_cast<GUITransportableControl&>(MSNet::getInstance()->getPersonControl()).insertIDs(persons);
195 : return persons;
196 0 : }
197 : case MID_HOTKEY_SHIFT_C_LOCATECONTAINER: {
198 : // get containers
199 : std::vector<GUIGlID> containers;
200 0 : static_cast<GUITransportableControl&>(MSNet::getInstance()->getContainerControl()).insertIDs(containers);
201 : return containers;
202 0 : }
203 0 : case MID_HOTKEY_SHIFT_T_LOCATETLS:
204 0 : return static_cast<GUINet*>(GUINet::getInstance())->getTLSIDs();
205 0 : case MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL:
206 0 : return GUIGlObject_AbstractAdd::getIDList(GLO_ADDITIONALELEMENT);
207 0 : case MID_HOTKEY_SHIFT_O_LOCATEPOI:
208 0 : return static_cast<GUIShapeContainer&>(GUINet::getInstance()->getShapeContainer()).getPOIIds();
209 0 : case MID_HOTKEY_SHIFT_L_LOCATEPOLY:
210 0 : return static_cast<GUIShapeContainer&>(GUINet::getInstance()->getShapeContainer()).getPolygonIDs();
211 0 : default:
212 0 : throw ProcessError(TL("Unknown Message ID in onCmdLocate"));
213 : }
214 : }
215 :
216 :
217 : long
218 0 : GUISUMOViewParent::onCmdLocate(FXObject*, FXSelector sel, void*) {
219 0 : int messageId = FXSELID(sel);
220 0 : if (myGLObjChooser.count(messageId) == 0 || myGLObjChooser[messageId] == nullptr) {
221 : FXIcon* icon = nullptr;
222 0 : std::string titleString = "";
223 0 : switch (messageId) {
224 0 : case MID_HOTKEY_SHIFT_J_LOCATEJUNCTION:
225 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEJUNCTION);
226 0 : titleString = TL("Junction Chooser");
227 : break;
228 0 : case MID_HOTKEY_SHIFT_E_LOCATEEDGE:
229 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEEDGE);
230 0 : titleString = TL("Edge Chooser");
231 : break;
232 0 : case MID_HOTKEY_SHIFT_V_LOCATEVEHICLE:
233 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEVEHICLE);
234 0 : titleString = TL("Vehicle Chooser");
235 : break;
236 0 : case MID_HOTKEY_SHIFT_P_LOCATEPERSON:
237 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEPERSON);
238 0 : titleString = TL("Person Chooser");
239 : break;
240 0 : case MID_HOTKEY_SHIFT_C_LOCATECONTAINER:
241 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATECONTAINER);
242 0 : titleString = TL("Container Chooser");
243 : break;
244 0 : case MID_HOTKEY_SHIFT_T_LOCATETLS:
245 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATETLS);
246 0 : titleString = TL("Traffic Lights Chooser");
247 : break;
248 0 : case MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL:
249 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEADD);
250 0 : titleString = TL("Additional Objects Chooser");
251 : break;
252 0 : case MID_HOTKEY_SHIFT_O_LOCATEPOI:
253 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEPOI);
254 0 : titleString = TL("POI Chooser");
255 : break;
256 0 : case MID_HOTKEY_SHIFT_L_LOCATEPOLY:
257 0 : icon = GUIIconSubSys::getIcon(GUIIcon::LOCATEPOLY);
258 0 : titleString = TL("Polygon Chooser");
259 : break;
260 0 : default:
261 0 : throw ProcessError(TL("Unknown Message ID in onCmdLocate"));
262 : }
263 :
264 0 : myGLObjChooser[messageId] = new GUIDialog_GLObjChooser(this, messageId, icon, titleString.c_str(), getObjectIDs(messageId), GUIGlObjectStorage::gIDStorage);
265 :
266 : } else {
267 0 : myGLObjChooser[messageId]->restore();
268 0 : myGLObjChooser[messageId]->setFocus();
269 0 : myGLObjChooser[messageId]->raise();
270 : }
271 0 : myLocatorPopup->popdown();
272 0 : myLocatorButton->killFocus();
273 0 : myLocatorPopup->update();
274 0 : return 1;
275 : }
276 :
277 :
278 : long
279 6469704 : GUISUMOViewParent::onSimStep(FXObject*, FXSelector, void*) {
280 6469704 : myView->update();
281 6469704 : myView->checkSnapshots();
282 6469704 : return 1;
283 : }
284 :
285 :
286 : bool
287 0 : GUISUMOViewParent::isSelected(GUIGlObject* o) const {
288 : GUIGlObjectType type = o->getType();
289 0 : if (gSelected.isSelected(type, o->getGlID())) {
290 : return true;
291 0 : } else if (type == GLO_EDGE) {
292 0 : GUIEdge* edge = dynamic_cast<GUIEdge*>(o);
293 0 : if (edge == nullptr) {
294 : // hmph, just some security stuff
295 : return false;
296 : }
297 : const std::vector<MSLane*>& lanes = edge->getLanes();
298 0 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
299 0 : GUILane* l = dynamic_cast<GUILane*>(*j);
300 0 : if (l != nullptr && gSelected.isSelected(GLO_LANE, l->getGlID())) {
301 : return true;
302 : }
303 : }
304 : return false;
305 : } else {
306 : return false;
307 : }
308 : }
309 :
310 :
311 : long
312 0 : GUISUMOViewParent::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
313 0 : myView->onKeyPress(o, sel, ptr);
314 0 : return 0;
315 : }
316 :
317 :
318 : long
319 0 : GUISUMOViewParent::onKeyRelease(FXObject* o, FXSelector sel, void* ptr) {
320 0 : myView->onKeyRelease(o, sel, ptr);
321 0 : return 0;
322 : }
323 :
324 :
325 : void
326 7547 : GUISUMOViewParent::buildSpeedControlToolbar() {
327 7547 : auto toolbar = myGripNavigationToolbar ? myGripNavigationToolbar : myStaticNavigationToolBar;
328 7547 : new FXVerticalSeparator(toolbar, GUIDesignVerticalSeparator);
329 :
330 : //myToolBarDragSpeed = new FXToolBarShell(this, GUIDesignToolBar);
331 : //myToolBarSpeed = new FXToolBar(toolbar, myToolBarDragSpeed, GUIDesignToolBarRaisedSameTop);
332 : //mySpeedFactorSlider = new FXSlider(myToolBarSpeed, this, MID_SPEEDFACTOR, LAYOUT_FIX_WIDTH | SLIDER_ARROW_UP | SLIDER_TICKS_TOP, 0, 0, 300, 10, 0, 0, 5, 0);
333 7547 : mySpeedFactorSlider = new FXSlider(toolbar, this, MID_SPEEDFACTOR, LAYOUT_FIX_WIDTH | SLIDER_ARROW_UP | SLIDER_TICKS_TOP, 0, 0, 200, 10, 0, 0, 5, 0);
334 7547 : mySpeedFactorSlider->setRange(0, 200);
335 7547 : mySpeedFactorSlider->setHeadSize(10);
336 7547 : mySpeedFactorSlider->setIncrement(1);
337 7547 : mySpeedFactorSlider->setTickDelta(100);
338 7547 : mySpeedFactorSlider->setValue(100);
339 15094 : mySpeedFactorSlider->setHelpText("Control speedFactor of tracked object");
340 : //mySpeedFactorSlider->hide();
341 7547 : }
342 :
343 : long
344 0 : GUISUMOViewParent::onCmdSpeedFactor(FXObject*, FXSelector, void*) {
345 0 : if (myView != nullptr && myView->getTrackedID() != GUIGlObject::INVALID_ID) {
346 0 : GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(myView->getTrackedID());
347 0 : if (o != nullptr) {
348 0 : const double speedFactor = mySpeedFactorSlider->getValue() / SPEEDFACTOR_SCALE;
349 0 : if (o->getType() == GLO_VEHICLE) {
350 0 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(o);
351 0 : veh->setChosenSpeedFactor(speedFactor);
352 : } else if (o->getType() == GLO_PERSON) {
353 : //MSPerson* person = dynamic_cast<MSPerson*>(o);
354 : //person->setChosenSpeedFactor(speedFactor);
355 : }
356 0 : mySpeedFactorSlider->setTipText(toString(speedFactor).c_str());
357 : }
358 :
359 : }
360 0 : return 1;
361 : }
362 :
363 : long
364 294694 : GUISUMOViewParent::onUpdSpeedFactor(FXObject* sender, FXSelector, void* ptr) {
365 294694 : bool disable = myView == nullptr || myView->getTrackedID() == GUIGlObject::INVALID_ID;
366 294698 : sender->handle(this, FXSEL(SEL_COMMAND, disable ? ID_DISABLE : ID_ENABLE), ptr);
367 294694 : if (disable) {
368 294690 : mySpeedFactorSlider->hide();
369 : } else {
370 4 : GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(myView->getTrackedID());
371 4 : if (o != nullptr) {
372 4 : if (o->getType() == GLO_VEHICLE) {
373 4 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(o);
374 4 : mySpeedFactorSlider->setValue((int)(veh->getChosenSpeedFactor() * SPEEDFACTOR_SCALE));
375 0 : } else if (o->getType() == GLO_PERSON) {
376 0 : MSPerson* person = dynamic_cast<MSPerson*>(o);
377 0 : mySpeedFactorSlider->setValue((int)(person->getChosenSpeedFactor() * SPEEDFACTOR_SCALE));
378 : }
379 4 : mySpeedFactorSlider->show();
380 : } else {
381 0 : myView->stopTrack();
382 0 : mySpeedFactorSlider->hide();
383 : }
384 : }
385 294694 : return 1;
386 : }
387 :
388 :
389 : /****************************************************************************/
|