Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/frames/network/GNEAdditionalFrame.cpp
169685 views
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 GNEAdditionalFrame.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Dec 2015
17
///
18
// The Widget for add additional elements
19
/****************************************************************************/
20
21
#include <netedit/GNEApplicationWindow.h>
22
#include <netedit/GNENet.h>
23
#include <netedit/GNEViewParent.h>
24
#include <netedit/elements/additional/GNEAdditionalHandler.h>
25
#include <netedit/frames/GNEAttributesEditor.h>
26
#include <netedit/frames/GNEConsecutiveSelector.h>
27
#include <netedit/frames/GNEViewObjectSelector.h>
28
#include <netedit/frames/GNESelectorParent.h>
29
#include <netedit/frames/GNETagSelector.h>
30
#include <utils/gui/div/GUIDesigns.h>
31
32
#include "GNEAdditionalFrame.h"
33
34
// ===========================================================================
35
// method definitions
36
// ===========================================================================
37
38
// ---------------------------------------------------------------------------
39
// GNEAdditionalFrame::E2MultilaneLegendModule - methods
40
// ---------------------------------------------------------------------------
41
42
GNEAdditionalFrame::E2MultilaneLegendModule::E2MultilaneLegendModule(GNEFrame* frameParent) :
43
MFXGroupBoxModule(frameParent, TL("Legend")) {
44
// declare label
45
FXLabel* legendLabel = nullptr;
46
// edge candidate
47
legendLabel = new FXLabel(getCollapsableFrame(), TL(" edge candidate"), 0, GUIDesignLabel(JUSTIFY_LEFT));
48
legendLabel->setBackColor(MFXUtils::getFXColor(frameParent->getViewNet()->getVisualisationSettings().candidateColorSettings.possible));
49
legendLabel->setTextColor(MFXUtils::getFXColor(RGBColor::WHITE));
50
// last edge selected
51
legendLabel = new FXLabel(getCollapsableFrame(), TL(" last edge selected"), 0, GUIDesignLabel(JUSTIFY_LEFT));
52
legendLabel->setBackColor(MFXUtils::getFXColor(frameParent->getViewNet()->getVisualisationSettings().candidateColorSettings.target));
53
// edge selected
54
legendLabel = new FXLabel(getCollapsableFrame(), TL(" edge selected"), 0, GUIDesignLabel(JUSTIFY_LEFT));
55
legendLabel->setBackColor(MFXUtils::getFXColor(frameParent->getViewNet()->getVisualisationSettings().candidateColorSettings.source));
56
// edge disconnected
57
legendLabel = new FXLabel(getCollapsableFrame(), TL(" edge disconnected"), 0, GUIDesignLabel(JUSTIFY_LEFT));
58
legendLabel->setBackColor(MFXUtils::getFXColor(frameParent->getViewNet()->getVisualisationSettings().candidateColorSettings.conflict));
59
}
60
61
62
GNEAdditionalFrame::E2MultilaneLegendModule::~E2MultilaneLegendModule() {}
63
64
65
void
66
GNEAdditionalFrame::E2MultilaneLegendModule::showE2MultilaneLegend() {
67
show();
68
}
69
70
71
void
72
GNEAdditionalFrame::E2MultilaneLegendModule::hideE2MultilaneLegend() {
73
hide();
74
}
75
76
// ---------------------------------------------------------------------------
77
// GNEAdditionalFrame::HelpCreationModule - methods
78
// ---------------------------------------------------------------------------
79
80
#define TLSX(string) std::string(gettext((string)))
81
82
83
84
GNEAdditionalFrame::HelpCreationModule::HelpCreationModule(GNEFrame* frameParent) :
85
MFXGroupBoxModule(frameParent, TL("Help")) {
86
// edge candidate
87
myHelpLabel = new FXLabel(getCollapsableFrame(), "", 0, GUIDesignLabelFrameInformation);
88
// fill map
89
//addTLString(TL("-Requires EntryExitDetector\n")) +
90
// E1
91
myHelpMap[SUMO_TAG_INDUCTION_LOOP] = addTLString(TL("-Click over lane to create it"));
92
// E1 Instant
93
myHelpMap[SUMO_TAG_INSTANT_INDUCTION_LOOP] = addTLString(TL("-Click over lane to create it"));
94
// E2
95
myHelpMap[SUMO_TAG_LANE_AREA_DETECTOR] = addTLString(TL("-Click over lane to create it"));
96
// E3
97
myHelpMap[SUMO_TAG_ENTRY_EXIT_DETECTOR] = addTLString(TL("-Click over view to create it")) +
98
addTLString(TL("-Requires at least one Entry\n and one Exit"));
99
// E3 Entry
100
myHelpMap[SUMO_TAG_DET_ENTRY] = addTLString(TL("-Requires EntryExitDetector\n parent\n")) +
101
addTLString(TL("-Select EntryExitDetector\n before creating either\n clicking over one in view\n or by selecting from list"));
102
// E3 Exit
103
myHelpMap[SUMO_TAG_DET_EXIT] = addTLString(TL("-Requires EntryExitDetector\n parent\n")) +
104
addTLString(TL("-Select EntryExitDetector\n before creating either\n clicking over one in view\n or by selecting from list"));
105
}
106
107
108
GNEAdditionalFrame::HelpCreationModule::~HelpCreationModule() {}
109
110
111
void
112
GNEAdditionalFrame::HelpCreationModule::showHelpCreationModule(SumoXMLTag XMLTag) {
113
if (myHelpMap.count(XMLTag) > 0) {
114
myHelpLabel->setText(myHelpMap.at(XMLTag).c_str());
115
show();
116
} else {
117
hide();
118
}
119
}
120
121
122
void
123
GNEAdditionalFrame::HelpCreationModule::hideHelpCreationModule() {
124
hide();
125
}
126
127
128
std::string
129
GNEAdditionalFrame::HelpCreationModule::addTLString(const std::string& str) {
130
return std::string(str.c_str());
131
}
132
133
// ---------------------------------------------------------------------------
134
// GNEAdditionalFrame: - methods
135
// ---------------------------------------------------------------------------
136
137
GNEAdditionalFrame::GNEAdditionalFrame(GNEViewParent* viewParent, GNEViewNet* viewNet) :
138
GNEFrame(viewParent, viewNet, TL("Additionals")) {
139
140
// create item Selector module for additionals
141
myAdditionalTagSelector = new GNETagSelector(this, GNETagProperties::Type::ADDITIONALELEMENT, SUMO_TAG_BUS_STOP);
142
143
// Create additional parameters
144
myAdditionalAttributesEditor = new GNEAttributesEditor(this, GNEAttributesEditorType::EditorType::CREATOR);
145
146
// Create selector parent
147
mySelectorAdditionalParent = new GNESelectorParent(this);
148
149
// Create selector child edges
150
myViewObjetsSelector = new GNEViewObjectSelector(this);
151
152
// Create list for E2Multilane lane selector
153
myConsecutiveLaneSelector = new GNEConsecutiveSelector(this, false);
154
155
// create help creation module
156
myHelpCreationModule = new HelpCreationModule(this);
157
158
// Create legend for E2 detector
159
myE2MultilaneLegendModule = new E2MultilaneLegendModule(this);
160
}
161
162
163
GNEAdditionalFrame::~GNEAdditionalFrame() {
164
// check if we have to delete base additional object
165
if (myBaseAdditional) {
166
delete myBaseAdditional;
167
}
168
}
169
170
171
void
172
GNEAdditionalFrame::show() {
173
// refresh tag selector
174
myAdditionalTagSelector->refreshTagSelector();
175
// reset last position
176
myLastClickedPosition = Position::INVALID;
177
// show frame
178
GNEFrame::show();
179
}
180
181
182
bool
183
GNEAdditionalFrame::addAdditional(const GNEViewNetHelper::ViewObjectsSelector& viewObjects) {
184
// first check that current selected additional is valid
185
if (myAdditionalTagSelector->getCurrentTemplateAC() == nullptr) {
186
myViewNet->setStatusBarText(TL("Current selected additional isn't valid."));
187
return false;
188
}
189
// obtain tagproperty (only for improve code legibility)
190
const auto& tagProperties = myAdditionalTagSelector->getCurrentTemplateAC()->getTagProperty();
191
// check if toogle selection
192
if ((viewObjects.getAttributeCarrierFront() == viewObjects.getLaneFront()) &&
193
(myViewObjetsSelector->toggleSelectedLane(viewObjects.getLaneFront()))) {
194
return true;
195
}
196
if (myViewObjetsSelector->toggleSelectedElement(viewObjects.getAttributeCarrierFront())) {
197
return true;
198
}
199
// check if add a lane in consecutive lane selector
200
if (tagProperties->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {
201
return myConsecutiveLaneSelector->addLane(viewObjects.getLaneFront());
202
}
203
// disable rerouter elements (temporal)
204
if ((tagProperties->getTag() == SUMO_TAG_INTERVAL) ||
205
(tagProperties->getTag() == SUMO_TAG_DEST_PROB_REROUTE) ||
206
(tagProperties->getTag() == SUMO_TAG_CLOSING_REROUTE) ||
207
(tagProperties->getTag() == SUMO_TAG_CLOSING_LANE_REROUTE) ||
208
(tagProperties->getTag() == SUMO_TAG_ROUTE_PROB_REROUTE) ||
209
(tagProperties->getTag() == SUMO_TAG_PARKING_AREA_REROUTE)) {
210
WRITE_WARNING(TL("Currently unsupported. Create rerouter elements using rerouter dialog"));
211
return false;
212
}
213
// disable steps (temporal)
214
if (tagProperties->getTag() == SUMO_TAG_STEP) {
215
WRITE_WARNING(TL("Currently unsupported. Create VSS steps using VSS dialog"));
216
return false;
217
}
218
// disable flows (temporal)
219
if (tagProperties->getTag() == GNE_TAG_CALIBRATOR_FLOW) {
220
WRITE_WARNING(TL("Currently unsupported. Create calibratorFlows using calibrator dialog"));
221
return false;
222
}
223
// check last position
224
if ((myViewNet->getPositionInformation() == myLastClickedPosition) && !myViewNet->getMouseButtonKeyPressed().shiftKeyPressed()) {
225
WRITE_WARNING(TL("Shift + click to create two additionals in the same position"));
226
return false;
227
}
228
// check if additional attributes are valid
229
if (!myAdditionalAttributesEditor->checkAttributes(true)) {
230
return false;
231
}
232
// reset base additional
233
resetBaseAdditionalObject();
234
// init base additional object
235
if (!initBaseAdditionalObject(tagProperties, viewObjects)) {
236
return false;
237
}
238
// parse common attributes
239
if (!myViewObjetsSelector->fillSumoBaseObject(myBaseAdditional)) {
240
return false;
241
}
242
// add basic attributes and values
243
myAdditionalAttributesEditor->fillSumoBaseObject(myBaseAdditional);
244
// declare additional handler
245
GNEAdditionalHandler additionalHandler(myViewNet->getNet(), myBaseAdditional->hasStringAttribute(GNE_ATTR_ADDITIONAL_FILE) ?
246
myBaseAdditional->getStringAttribute(GNE_ATTR_ADDITIONAL_FILE) : "",
247
myViewNet->getViewParent()->getGNEAppWindows()->isUndoRedoAllowed());
248
// build additional
249
additionalHandler.parseSumoBaseObject(myBaseAdditional);
250
// Refresh additional Parent Selector (For additionals that have a limited number of children)
251
mySelectorAdditionalParent->refreshSelectorParentModule();
252
// clear selected view objects
253
myViewObjetsSelector->clearSelection();
254
myAdditionalAttributesEditor->refreshAttributesEditor();
255
return true;
256
}
257
258
259
GNETagSelector*
260
GNEAdditionalFrame::getAdditionalTagSelector() const {
261
return myAdditionalTagSelector;
262
}
263
264
265
GNEConsecutiveSelector*
266
GNEAdditionalFrame::getConsecutiveLaneSelector() const {
267
return myConsecutiveLaneSelector;
268
}
269
270
271
GNEAttributesEditor*
272
GNEAdditionalFrame::getAttributesEditor() const {
273
return myAdditionalAttributesEditor;
274
}
275
276
277
GNEViewObjectSelector*
278
GNEAdditionalFrame::getViewObjetsSelector() const {
279
return myViewObjetsSelector;
280
}
281
282
283
bool
284
GNEAdditionalFrame::createPath(const bool /* useLastRoute */) {
285
// obtain tagproperty (only for improve code legibility)
286
const auto tagProperty = myAdditionalTagSelector->getCurrentTemplateAC()->getTagProperty();
287
// first check that current tag is valid (currently only for E2 multilane detectors)
288
if (tagProperty->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {
289
// now check number of lanes
290
if (myConsecutiveLaneSelector->getLanePath().size() < 2) {
291
WRITE_WARNING(TL("E2 multilane detectors need at least two consecutive lanes"));
292
} else {
293
// reset base object
294
resetBaseAdditionalObject();
295
// set tag
296
myBaseAdditional->setTag(SUMO_TAG_LANE_AREA_DETECTOR);
297
// get attributes and values
298
myAdditionalAttributesEditor->fillSumoBaseObject(myBaseAdditional);
299
// add lane IDs
300
myBaseAdditional->addStringListAttribute(SUMO_ATTR_LANES, myConsecutiveLaneSelector->getLaneIDPath());
301
// set positions
302
myBaseAdditional->addDoubleAttribute(SUMO_ATTR_POSITION, myConsecutiveLaneSelector->getLanePath().front().second);
303
myBaseAdditional->addDoubleAttribute(SUMO_ATTR_ENDPOS, myConsecutiveLaneSelector->getLanePath().back().second);
304
// parse common attributes
305
if (myViewObjetsSelector->fillSumoBaseObject(myBaseAdditional)) {
306
// show warning dialogbox and stop check if input parameters are valid
307
if (myAdditionalAttributesEditor->checkAttributes(true)) {
308
// declare additional handler
309
GNEAdditionalHandler additionalHandler(myViewNet->getNet(), myBaseAdditional->hasStringAttribute(GNE_ATTR_ADDITIONAL_FILE) ?
310
myBaseAdditional->getStringAttribute(GNE_ATTR_ADDITIONAL_FILE) : "",
311
myViewNet->getViewParent()->getGNEAppWindows()->isUndoRedoAllowed());
312
// build additional
313
additionalHandler.parseSumoBaseObject(myBaseAdditional);
314
// Refresh additional Parent Selector (For additionals that have a limited number of children)
315
mySelectorAdditionalParent->refreshSelectorParentModule();
316
// abort E2 creation
317
myConsecutiveLaneSelector->abortPathCreation();
318
return true;
319
}
320
}
321
}
322
}
323
return false;
324
}
325
326
327
void
328
GNEAdditionalFrame::tagSelected() {
329
// get template AC
330
const auto templateAC = myAdditionalTagSelector->getCurrentTemplateAC();
331
if (templateAC) {
332
// show parameters
333
myAdditionalAttributesEditor->showAttributesEditor(templateAC, true);
334
// Show myAdditionalFrameParent if we're adding an slave element
335
if (templateAC->getTagProperty()->isChild()) {
336
mySelectorAdditionalParent->showSelectorParentModule(templateAC->getTagProperty()->getXMLParentTags());
337
} else {
338
mySelectorAdditionalParent->hideSelectorParentModule();
339
}
340
// Show EdgesSelector if we're adding an additional that own the attribute SUMO_ATTR_EDGES
341
if (templateAC->getTagProperty()->hasAttribute(SUMO_ATTR_EDGES)) {
342
myViewObjetsSelector->showNetworkElementsSelector(SUMO_TAG_EDGE, SUMO_ATTR_EDGES);
343
} else {
344
myViewObjetsSelector->hideNetworkElementsSelector();
345
}
346
// show help creation modul
347
myHelpCreationModule->showHelpCreationModule(templateAC->getTagProperty()->getTag());
348
// check if we must show consecutive lane selector
349
if (templateAC->getTagProperty()->getTag() == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {
350
myConsecutiveLaneSelector->showConsecutiveLaneSelectorModule();
351
myE2MultilaneLegendModule->showE2MultilaneLegend();
352
myViewObjetsSelector->hideNetworkElementsSelector();
353
// recompute network
354
myViewNet->getNet()->computeNetwork(myViewNet->getViewParent()->getGNEAppWindows());
355
} else if (templateAC->getTagProperty()->hasAttribute(SUMO_ATTR_LANES)) {
356
myConsecutiveLaneSelector->hideConsecutiveLaneSelectorModule();
357
myE2MultilaneLegendModule->hideE2MultilaneLegend();
358
myViewObjetsSelector->showNetworkElementsSelector(SUMO_TAG_LANE, SUMO_ATTR_LANES);
359
} else {
360
myConsecutiveLaneSelector->hideConsecutiveLaneSelectorModule();
361
myE2MultilaneLegendModule->hideE2MultilaneLegend();
362
}
363
// reset last position
364
myLastClickedPosition = Position::INVALID;
365
} else {
366
// hide all modules if additional isn't valid
367
myAdditionalAttributesEditor->hideAttributesEditor();
368
mySelectorAdditionalParent->hideSelectorParentModule();
369
myViewObjetsSelector->hideNetworkElementsSelector();
370
myConsecutiveLaneSelector->hideConsecutiveLaneSelectorModule();
371
myHelpCreationModule->hideHelpCreationModule();
372
myE2MultilaneLegendModule->hideE2MultilaneLegend();
373
}
374
}
375
376
377
void
378
GNEAdditionalFrame::resetBaseAdditionalObject() {
379
// check if baseAdditional exist, and if yes, delete it
380
if (myBaseAdditional) {
381
// go to base additional root
382
while (myBaseAdditional->getParentSumoBaseObject()) {
383
myBaseAdditional = myBaseAdditional->getParentSumoBaseObject();
384
}
385
// delete baseAdditional (and all children)
386
delete myBaseAdditional;
387
// reset baseAdditional
388
myBaseAdditional = nullptr;
389
}
390
// create an new base additional
391
myBaseAdditional = new CommonXMLStructure::SumoBaseObject(nullptr);
392
}
393
394
395
bool
396
GNEAdditionalFrame::initBaseAdditionalObject(const GNETagProperties* tagProperty, const GNEViewNetHelper::ViewObjectsSelector& viewObjects) {
397
// declare tag for base additional
398
auto baseAdditionalTag = tagProperty->getTag();
399
// check if tag has to be updated
400
if (baseAdditionalTag == GNE_TAG_MULTI_LANE_AREA_DETECTOR) {
401
baseAdditionalTag = SUMO_TAG_LANE_AREA_DETECTOR;
402
} else if (baseAdditionalTag == GNE_TAG_CALIBRATOR_FLOW) {
403
baseAdditionalTag = SUMO_TAG_FLOW;
404
}
405
// update view objects parents
406
viewObjects.fillSumoBaseObject(myBaseAdditional);
407
// check if additional is child of other element
408
if (tagProperty->isChild()) {
409
// check if we clicked over a parent
410
SumoXMLTag parentTag = SUMO_TAG_NOTHING;
411
for (const auto& pTag : tagProperty->getXMLParentTags()) {
412
if (myBaseAdditional->hasParentID(pTag)) {
413
parentTag = pTag;
414
}
415
}
416
// update selector additional parent
417
if (parentTag != SUMO_TAG_NOTHING) {
418
// update parent additional selected
419
mySelectorAdditionalParent->setIDSelected(myBaseAdditional->getParentID(parentTag));
420
}
421
// continue depending of parents
422
if (mySelectorAdditionalParent->getIdSelected().empty()) {
423
std::string messageError = toString(tagProperty->getXMLParentTags().front());
424
if (tagProperty->getXMLParentTags().size() > 1) {
425
const int numParents = (int)tagProperty->getXMLParentTags().size();
426
messageError.clear();
427
for (int i = 0; i < numParents; i++) {
428
messageError.append(toString(tagProperty->getXMLParentTags().at(i)));
429
if (i == numParents - 2) {
430
messageError.append(" or ");
431
} else if (i < (numParents - 2)) {
432
messageError.append(", ");
433
}
434
}
435
}
436
WRITE_WARNING(TLF("A % must be selected before insertion of %.", messageError, tagProperty->getTagStr()));
437
return false;
438
} else {
439
// set parent tag // POSSIBLE ERROR WITH ACCESS AND BUSSTOPS!
440
myBaseAdditional->setTag(tagProperty->getXMLParentTags().front());
441
// add ID
442
myBaseAdditional->addStringAttribute(SUMO_ATTR_ID, mySelectorAdditionalParent->getIdSelected());
443
// create base additional again as child of current base additional
444
myBaseAdditional = new CommonXMLStructure::SumoBaseObject(myBaseAdditional);
445
}
446
}
447
// set baseAdditional tag
448
myBaseAdditional->setTag(baseAdditionalTag);
449
// Obtain position as the clicked position over view
450
const Position viewPosSnapped = myViewNet->snapToActiveGrid(myViewNet->getPositionInformation());
451
// add position and X-Y-Z attributes
452
myBaseAdditional->addPositionAttribute(SUMO_ATTR_POSITION, viewPosSnapped);
453
myBaseAdditional->addDoubleAttribute(SUMO_ATTR_X, viewPosSnapped.x());
454
myBaseAdditional->addDoubleAttribute(SUMO_ATTR_Y, viewPosSnapped.y());
455
myBaseAdditional->addDoubleAttribute(SUMO_ATTR_Z, viewPosSnapped.z());
456
// check if add edge attributes
457
if (tagProperty->hasAttribute(SUMO_ATTR_EDGE)) {
458
if (viewObjects.getEdgeFront() == nullptr) {
459
return false;
460
} else {
461
myBaseAdditional->addStringAttribute(SUMO_ATTR_EDGE, viewObjects.getEdgeFront()->getID());
462
// Obtain position of the mouse over lane (limited over grid)
463
const auto firstLane = viewObjects.getEdgeFront()->getChildLanes().front();
464
const double mousePositionOverLane = firstLane->getLaneShape().nearest_offset_to_point2D(viewPosSnapped) / firstLane->getLengthGeometryFactor();
465
myBaseAdditional->addDoubleAttribute(SUMO_ATTR_POSITION, mousePositionOverLane);
466
}
467
} else if (tagProperty->getTag() == SUMO_TAG_VAPORIZER) {
468
// special case for vaporizers
469
if (viewObjects.getEdgeFront() == nullptr) {
470
return false;
471
} else {
472
myBaseAdditional->addStringAttribute(SUMO_ATTR_ID, viewObjects.getEdgeFront()->getID());
473
}
474
}
475
// check if add lane attributes
476
if (tagProperty->hasAttribute(SUMO_ATTR_LANE)) {
477
if (viewObjects.getLaneFront() == nullptr) {
478
return false;
479
} else {
480
myBaseAdditional->addStringAttribute(SUMO_ATTR_LANE, viewObjects.getLaneFront()->getID());
481
myBaseAdditional->addDoubleAttribute(GNE_ATTR_LANELENGTH, viewObjects.getLaneFront()->getLaneShapeLength() / viewObjects.getLaneFront()->getLengthGeometryFactor());
482
// Obtain position of the mouse over lane (limited over grid)
483
const double mousePositionOverLane = viewObjects.getLaneFront()->getLaneShape().nearest_offset_to_point2D(viewPosSnapped) / viewObjects.getLaneFront()->getLengthGeometryFactor();
484
// special case for access
485
if (tagProperty->getTag() == SUMO_TAG_ACCESS) {
486
myBaseAdditional->addStringAttribute(SUMO_ATTR_POSITION, toString(mousePositionOverLane));
487
} else {
488
myBaseAdditional->addDoubleAttribute(SUMO_ATTR_POSITION, mousePositionOverLane);
489
}
490
}
491
}
492
// BaseAdditional created, then return true
493
return true;
494
}
495
496
/****************************************************************************/
497
498