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 GUIGlObject.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @author Laura Bieker
19 : /// @date Sept 2002
20 : ///
21 : // Base class for all objects that may be displayed within the openGL-gui
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <string>
26 : #include <stack>
27 : #include <utils/common/MsgHandler.h>
28 : #include <utils/common/ToString.h>
29 : #include <utils/geom/GeoConvHelper.h>
30 : #include <utils/gui/windows/GUISUMOAbstractView.h>
31 : #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
32 : #include <utils/gui/div/GUIParameterTableWindow.h>
33 : #include <utils/foxtools/MFXMenuHeader.h>
34 : #include <utils/gui/images/GUIIconSubSys.h>
35 : #include <utils/gui/windows/GUIAppEnum.h>
36 : #include <utils/gui/windows/GUIMainWindow.h>
37 : #include <utils/gui/div/GUIGlobalSelection.h>
38 : #include <utils/gui/div/GLHelper.h>
39 : #include <utils/gui/div/GLObjectValuePassConnector.h>
40 : #include <utils/gui/div/GUIDesigns.h>
41 : #include <utils/geom/GeomHelper.h>
42 : #include <utils/gui/div/GUIGlobalViewObjectsHandler.h>
43 : #include <utils/options/OptionsCont.h>
44 :
45 : #include "GUIGlObject.h"
46 : #include "GUIGlObjectStorage.h"
47 :
48 : // ===========================================================================
49 : // static members
50 : // ===========================================================================
51 :
52 : StringBijection<GUIGlObjectType>::Entry GUIGlObject::GUIGlObjectTypeNamesInitializer[] = {
53 : {"network", GLO_NETWORK},
54 : //
55 : {"networkElement", GLO_NETWORKELEMENT},
56 : {"edge", GLO_EDGE},
57 : {"lane", GLO_LANE},
58 : {"junction", GLO_JUNCTION},
59 : {"connection", GLO_CONNECTION},
60 : {"crossing", GLO_CROSSING},
61 : {"walkingArea", GLO_WALKINGAREA},
62 : {"tlLogic", GLO_TLLOGIC},
63 : {"edgeType", GLO_EDGETYPE},
64 : {"laneType", GLO_LANETYPE},
65 : //
66 : {"parentChildLine", GLO_PARENTCHILDLINE},
67 : //
68 : {"additional", GLO_ADDITIONALELEMENT},
69 : {"stoppingPlace", GLO_STOPPING_PLACE},
70 : {"busStop", GLO_BUS_STOP},
71 : {"trainStop", GLO_TRAIN_STOP},
72 : {"access", GLO_ACCESS},
73 : {"taz", GLO_TAZ},
74 : {"containerStop", GLO_CONTAINER_STOP},
75 : {"chargingStation", GLO_CHARGING_STATION},
76 : {"parkingArea", GLO_PARKING_AREA},
77 : {"stoppingPlaceLast", GLO_STOPPING_PLACE_LAST},
78 : {"parkingSpace", GLO_PARKING_SPACE},
79 : {"e1Detector", GLO_E1DETECTOR},
80 : {"e1DetectorME", GLO_E1DETECTOR_ME},
81 : {"e1DetectorInstant", GLO_E1DETECTOR_INSTANT},
82 : {"e2Detector", GLO_E2DETECTOR},
83 : {"e3Detector", GLO_E3DETECTOR},
84 : {"entryDetector", GLO_DET_ENTRY},
85 : {"exitDetector", GLO_DET_EXIT},
86 : {"rerouter", GLO_REROUTER},
87 : {"rerouterInterval", GLO_REROUTER_INTERVAL},
88 : {"closingreroute", GLO_REROUTER_CLOSINGREROUTE},
89 : {"closingLaneReroute", GLO_REROUTER_CLOSINGLANEREROUTE},
90 : {"parkingAreaReroute", GLO_REROUTER_PARKINGAREAREROUTE},
91 : {"destProbReroute", GLO_REROUTER_DESTPROBREROUTE},
92 : {"routeProbReroute", GLO_REROUTER_ROUTEPROBREROUTE},
93 : {"rerouterEdge", GLO_REROUTER_EDGE},
94 : {"variableSpeedSign", GLO_VSS},
95 : {"variableSpeedSignStep", GLO_VSS_STEP},
96 : {"calibrator", GLO_CALIBRATOR},
97 : {"routeProbe", GLO_ROUTEPROBE},
98 : {"vaporizer", GLO_VAPORIZER},
99 : {"wire", GLO_WIRE},
100 : {"overheadWireSegment", GLO_OVERHEAD_WIRE_SEGMENT},
101 : {"tractionsubstation", GLO_TRACTIONSUBSTATION},
102 : {"additionalLast", GLO_ADDITIONALELEMENT_LAST},
103 : //
104 : {"laneArrows", GLO_LANEARROWS},
105 : //
106 : {"shape", GLO_SHAPE},
107 : {"polygon", GLO_POLYGON},
108 : {"poi", GLO_POI},
109 : {"jupedsim.walkable_area", GLO_JPS_WALKABLEAREA},
110 : {"jupedsim.obstacle", GLO_JPS_OBSTACLE},
111 : {"shapeLast", GLO_SHAPE_LAST},
112 : //
113 : {"routeElement", GLO_ROUTEELEMENT},
114 : {"vType", GLO_VTYPE},
115 : //
116 : {"route", GLO_ROUTE},
117 : {"routeEmbedded", GLO_ROUTE_EMBEDDED},
118 : //
119 : {"ride", GLO_RIDE},
120 : {"walk", GLO_WALK},
121 : {"personTrip", GLO_PERSONTRIP},
122 : {"transport", GLO_TRANSPORT},
123 : {"tranship", GLO_TRANSHIP},
124 : //
125 : {"stop", GLO_STOP},
126 : {"stopPlan", GLO_STOP_PLAN},
127 : //
128 : {"vehicle", GLO_VEHICLE},
129 : {"trip", GLO_TRIP},
130 : {"flow", GLO_FLOW},
131 : {"routeFlow", GLO_ROUTEFLOW},
132 : //
133 : {"container", GLO_CONTAINER},
134 : {"containerFlow", GLO_CONTAINERFLOW},
135 : //
136 : {"person", GLO_PERSON},
137 : {"personFlow", GLO_PERSONFLOW},
138 : //
139 : {"edgeData", GLO_EDGEDATA},
140 : {"edgeRelData", GLO_EDGERELDATA},
141 : {"TAZRelData", GLO_TAZRELDATA},
142 : //
143 : {"lockIcon", GLO_LOCKICON},
144 : {"textName", GLO_TEXTNAME},
145 : {"frontElement", GLO_FRONTELEMENT},
146 : {"geometryPoint", GLO_GEOMETRYPOINT},
147 : {"dottedContour", GLO_DOTTEDCONTOUR},
148 : {"temporalShape", GLO_TEMPORALSHAPE},
149 : {"rectangleSelection", GLO_RECTANGLESELECTION},
150 : {"testElement", GLO_TESTELEMENT},
151 : //
152 : {"undefined", GLO_MAX}
153 : };
154 :
155 :
156 : StringBijection<GUIGlObjectType> GUIGlObject::TypeNames(GUIGlObjectTypeNamesInitializer, GLO_MAX);
157 : const GUIGlID GUIGlObject::INVALID_ID = 0;
158 : const double GUIGlObject::INVALID_PRIORITY(-std::numeric_limits<double>::max());
159 :
160 : // ===========================================================================
161 : // method definitions
162 : // ===========================================================================
163 :
164 1573610 : GUIGlObject::GUIGlObject(GUIGlObjectType type, const std::string& microsimID, FXIcon* icon) :
165 3147220 : myGlID(GUIGlObjectStorage::gIDStorage.registerObject(this)),
166 1573610 : myGLObjectType(type),
167 1573610 : myMicrosimID(microsimID),
168 3147220 : myIcon(icon) {
169 : // make sure that reserved GLO_ADDITIONALELEMENT isn't used
170 : assert(myGLObjectType != GLO_ADDITIONALELEMENT);
171 1573610 : myFullName = createFullName();
172 1573610 : GUIGlObjectStorage::gIDStorage.changeName(this, myFullName);
173 1573610 : }
174 :
175 :
176 1572124 : GUIGlObject::~GUIGlObject() {
177 : // remove all paramWindow related with this object
178 1572124 : for (const auto& paramWindow : myParamWindows) {
179 0 : paramWindow->removeObject(this);
180 : }
181 : // remove object from GLObjectValuePassConnector and GUIGlObjectStorage
182 1572124 : GLObjectValuePassConnector<double>::removeObject(*this);
183 1572124 : GUIGlObjectStorage::gIDStorage.remove(getGlID());
184 1572124 : }
185 :
186 :
187 : std::string
188 0 : GUIGlObject::getParentName() const {
189 0 : return StringUtils::emptyString;
190 : }
191 :
192 :
193 : FXIcon*
194 0 : GUIGlObject::getGLIcon() const {
195 0 : return myIcon;
196 : }
197 :
198 :
199 : GUIParameterTableWindow*
200 0 : GUIGlObject::getTypeParameterWindow(GUIMainWindow& app, GUISUMOAbstractView& parent) {
201 : UNUSED_PARAMETER(&app);
202 : UNUSED_PARAMETER(&parent);
203 0 : return nullptr;
204 : }
205 :
206 :
207 : bool
208 0 : GUIGlObject::isGLObjectLocked() const {
209 : // by default unlocked
210 0 : return false;
211 : }
212 :
213 :
214 : void
215 0 : GUIGlObject::markAsFrontElement() {
216 : // by default nothing to do
217 0 : }
218 :
219 :
220 : void
221 0 : GUIGlObject::deleteGLObject() {
222 : // by default nothing to do
223 0 : }
224 :
225 :
226 : void
227 0 : GUIGlObject::selectGLObject() {
228 : // by default nothing to do
229 0 : }
230 :
231 :
232 : void
233 0 : GUIGlObject::updateGLObject() {
234 : // by default nothing to update
235 0 : }
236 :
237 :
238 : const std::string
239 0 : GUIGlObject::getOptionalName() const {
240 0 : return "";
241 : }
242 :
243 :
244 : void
245 0 : GUIGlObject::setMicrosimID(const std::string& newID) {
246 0 : myMicrosimID = newID;
247 0 : GUIGlObjectStorage::gIDStorage.changeName(this, createFullName());
248 0 : myFullName = createFullName();
249 0 : }
250 :
251 :
252 : void
253 0 : GUIGlObject::drawGLAdditional(GUISUMOAbstractView* const parent, const GUIVisualizationSettings& s) const {
254 : UNUSED_PARAMETER(&s);
255 : UNUSED_PARAMETER(parent);
256 0 : }
257 :
258 : #ifdef HAVE_OSG
259 :
260 : osg::Node*
261 0 : GUIGlObject::getNode() const {
262 0 : return myOSGNode;
263 : }
264 :
265 :
266 : void
267 39033 : GUIGlObject::setNode(osg::Node* node) {
268 39033 : myOSGNode = node;
269 39033 : }
270 :
271 : #endif
272 :
273 : void
274 0 : GUIGlObject::buildPopupHeader(GUIGLObjectPopupMenu* ret, GUIMainWindow& app, bool addSeparator) {
275 0 : new MFXMenuHeader(ret, app.getBoldFont(), getFullName().c_str(), myIcon, nullptr, 0);
276 0 : if (OptionsCont::getOptions().getBool("gui-testing")) {
277 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Copy test coordinates to clipboard"), nullptr, ret, MID_COPY_TEST_COORDINATES);
278 : }
279 0 : if (addSeparator) {
280 0 : new FXMenuSeparator(ret);
281 : }
282 0 : }
283 :
284 :
285 : void
286 0 : GUIGlObject::buildCenterPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
287 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Center"), GUIIconSubSys::getIcon(GUIIcon::RECENTERVIEW), ret, MID_CENTER);
288 0 : if (addSeparator) {
289 0 : new FXMenuSeparator(ret);
290 : }
291 0 : }
292 :
293 :
294 : void
295 0 : GUIGlObject::buildNameCopyPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
296 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Copy name to clipboard"), nullptr, ret, MID_COPY_NAME);
297 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Copy typed name to clipboard"), nullptr, ret, MID_COPY_TYPED_NAME);
298 0 : if (addSeparator) {
299 0 : new FXMenuSeparator(ret);
300 : }
301 0 : }
302 :
303 :
304 : void
305 0 : GUIGlObject::buildSelectionPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
306 0 : if (gSelected.isSelected(getType(), getGlID())) {
307 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Remove From Selected"), GUIIconSubSys::getIcon(GUIIcon::FLAG_MINUS), ret, MID_REMOVESELECT);
308 : } else {
309 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Add to Selected"), GUIIconSubSys::getIcon(GUIIcon::FLAG_PLUS), ret, MID_ADDSELECT);
310 : }
311 0 : if (addSeparator) {
312 0 : new FXMenuSeparator(ret);
313 : }
314 0 : }
315 :
316 :
317 : void
318 0 : GUIGlObject::buildShowParamsPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
319 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Show Parameter"), GUIIconSubSys::getIcon(GUIIcon::APP_TABLE), ret, MID_SHOWPARS);
320 0 : if (addSeparator) {
321 0 : new FXMenuSeparator(ret);
322 : }
323 0 : }
324 :
325 :
326 : void
327 0 : GUIGlObject::buildShowTypeParamsPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
328 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Show Type Parameter"), GUIIconSubSys::getIcon(GUIIcon::APP_TABLE), ret, MID_SHOWTYPEPARS);
329 0 : if (addSeparator) {
330 0 : new FXMenuSeparator(ret);
331 : }
332 0 : }
333 :
334 :
335 : void
336 0 : GUIGlObject::buildPositionCopyEntry(GUIGLObjectPopupMenu* ret, const GUIMainWindow& app) const {
337 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Copy cursor position to clipboard"), nullptr, ret, MID_COPY_CURSOR_POSITION);
338 0 : if (GeoConvHelper::getFinal().usingGeoProjection()) {
339 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Copy cursor geo-position to clipboard"), nullptr, ret, MID_COPY_CURSOR_GEOPOSITION);
340 : // create menu pane for edge operations
341 0 : FXMenuPane* showCursorGeoPositionPane = new FXMenuPane(ret);
342 0 : ret->insertMenuPaneChild(showCursorGeoPositionPane);
343 0 : new FXMenuCascade(ret, TL("Show cursor geo-position in "), nullptr, showCursorGeoPositionPane);
344 0 : for (const auto& mapper : app.getOnlineMaps()) {
345 0 : if (mapper.first == "GeoHack") {
346 0 : GUIDesigns::buildFXMenuCommand(showCursorGeoPositionPane, mapper.first, GUIIconSubSys::getIcon(GUIIcon::GEOHACK), ret, MID_SHOW_GEOPOSITION_ONLINE);
347 0 : } else if (mapper.first == "Google Maps") {
348 0 : GUIDesigns::buildFXMenuCommand(showCursorGeoPositionPane, mapper.first, GUIIconSubSys::getIcon(GUIIcon::GOOGLEMAPS), ret, MID_SHOW_GEOPOSITION_ONLINE);
349 0 : } else if (mapper.first == "OSM") {
350 0 : GUIDesigns::buildFXMenuCommand(showCursorGeoPositionPane, mapper.first, GUIIconSubSys::getIcon(GUIIcon::OSM), ret, MID_SHOW_GEOPOSITION_ONLINE);
351 : } else {
352 0 : GUIDesigns::buildFXMenuCommand(showCursorGeoPositionPane, mapper.first, nullptr, ret, MID_SHOW_GEOPOSITION_ONLINE);
353 : }
354 : }
355 : }
356 0 : }
357 :
358 :
359 : void
360 0 : GUIGlObject::buildShowManipulatorPopupEntry(GUIGLObjectPopupMenu* ret, bool addSeparator) {
361 0 : GUIDesigns::buildFXMenuCommand(ret, TL("Open Manipulator..."), GUIIconSubSys::getIcon(GUIIcon::MANIP), ret, MID_MANIP);
362 0 : if (addSeparator) {
363 0 : new FXMenuSeparator(ret);
364 : }
365 0 : }
366 :
367 :
368 : void
369 0 : GUIGlObject::addParameterTable(GUIParameterTableWindow* t) {
370 : myParamWindows.insert(t);
371 0 : }
372 :
373 :
374 : void
375 0 : GUIGlObject::removeParameterTable(GUIParameterTableWindow* t) {
376 : std::set<GUIParameterTableWindow*>::iterator i = myParamWindows.find(t);
377 0 : if (i != myParamWindows.end()) {
378 : myParamWindows.erase(i);
379 : }
380 0 : }
381 :
382 :
383 : void
384 0 : GUIGlObject::buildShapePopupOptions(GUIMainWindow& app, GUIGLObjectPopupMenu* ret, const std::string& type) {
385 : assert(ret);
386 : // build header (<tag>:<ID>
387 0 : buildPopupHeader(ret, app, false);
388 : // build center
389 0 : buildCenterPopupEntry(ret);
390 : // build copy name
391 0 : buildNameCopyPopupEntry(ret);
392 : // build select/unselect
393 0 : buildSelectionPopupEntry(ret);
394 : // build show parameters
395 0 : buildShowParamsPopupEntry(ret, false);
396 : // build copy cursor position to clipboard
397 0 : buildPositionCopyEntry(ret, app);
398 : // only show type if isn't empty
399 0 : if (type != "") {
400 0 : GUIDesigns::buildFXMenuCommand(ret, TLF("type: %", type).c_str(), nullptr, nullptr, 0);
401 0 : new FXMenuSeparator(ret);
402 : }
403 0 : }
404 :
405 :
406 : void
407 0 : GUIGlObject::buildAdditionalsPopupOptions(GUIMainWindow& app, GUIGLObjectPopupMenu* ret, const std::string& type) {
408 : assert(ret);
409 : // build header (<tag>:<ID>
410 0 : buildPopupHeader(ret, app, false);
411 : // build center
412 0 : buildCenterPopupEntry(ret);
413 : // build copy name
414 0 : buildNameCopyPopupEntry(ret);
415 : // build select/unselect
416 0 : buildSelectionPopupEntry(ret);
417 : // build show parameters
418 0 : buildShowParamsPopupEntry(ret, false);
419 : // build copy cursor position to clipboard
420 0 : buildPositionCopyEntry(ret, app);
421 : // only show type if isn't empty
422 0 : if (type != "") {
423 0 : GUIDesigns::buildFXMenuCommand(ret, TLF("type: %", type).c_str(), nullptr, nullptr, 0);
424 0 : new FXMenuSeparator(ret);
425 : }
426 0 : }
427 :
428 :
429 : std::string
430 1573610 : GUIGlObject::createFullName() const {
431 3147220 : return TypeNames.getString(myGLObjectType) + ":" + getMicrosimID();
432 : }
433 :
434 :
435 : void
436 18560880 : GUIGlObject::drawName(const Position& pos, const double scale, const GUIVisualizationTextSettings& settings, const double angle, bool forceShow) const {
437 18560880 : if (settings.show(this) || forceShow) {
438 0 : GLHelper::drawTextSettings(settings, getMicrosimID(), pos, scale, angle);
439 : }
440 18560880 : }
441 :
442 :
443 : /****************************************************************************/
|