Skyscraper 2.0
callstation.cpp
Go to the documentation of this file.
1/*
2 Scalable Building Simulator - Call Station Object
3 The Skyscraper Project - Version 2.0
4 Copyright (C)2004-2024 Ryan Thoryk
5 https://www.skyscrapersim.net
6 https://sourceforge.net/projects/skyscraper/
7 Contact - ryan@skyscrapersim.net
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22*/
23
24#include "globals.h"
25#include "sbs.h"
26#include "buttonpanel.h"
27#include "floor.h"
28#include "controller.h"
29#include "indicator.h"
30#include "timer.h"
31#include "manager.h"
32#include "texture.h"
33#include "control.h"
34#include "callstation.h"
35#include "profiler.h"
36#include "elevator.h"
37
38namespace SBS {
39
41{
42public:
44 Timer(const std::string &name, CallStation *parent) : TimerObject(parent, name)
45 {
46 this->parent = parent;
47 }
48 virtual void Notify();
49};
50
51CallStation::CallStation(Object *parent, int floornum, int number) : Object(parent), Lock(this)
52{
53 floor = sbs->GetFloor(floornum);
54 if (!floor)
55 return;
56
57 //set up SBS object
58 SetValues("CallStation", "", false);
59
60 is_enabled = true;
61
62 std::string base = "Call Station " + ToString(number);
63 SetName(base);
64
65 //set variables
66 Number = number;
67 Locked = false;
68 KeyID = 0;
69 panel = 0;
70 controller = 0;
71 indicator = 0;
72 TimerDelay = 2;
73 ShowDirection = true;
74
75 //create timer
76 timer = new Timer("Input Timeout Timer", this);
77
78 if (sbs->Verbose)
79 Report("Created");
80}
81
83{
85
86 if (indicator)
87 delete indicator;
88 indicator = 0;
89
90 if (sbs->FastDelete == false)
91 {
92 //unregister with controller
93 if (GetController())
95
96 //unregister with parent floor object
97 if (parent_deleting == false)
99 }
100}
101
103{
104 //input timeout timer
105
107}
108
109ButtonPanel* CallStation::CreateButtonPanel(const std::string &texture, int rows, int columns, const std::string &direction, Real buttonwidth, Real buttonheight, Real spacingX, Real spacingY, Real tw, Real th)
110{
111 //create a new button panel object
112
113 if (panel)
114 return 0;
115
116 if (sbs->Verbose)
117 Report("Creating button panel");
118
119 panel = new ButtonPanel(this, 1, texture, rows, columns, direction, 0, 0, buttonwidth, buttonheight, spacingX, spacingY, 0, tw, th);
120 return panel;
121}
122
123void CallStation::Enabled(bool value)
124{
125 //turns station on/off
126 if (is_enabled == value)
127 return;
128
129 is_enabled = value;
130
131 //enable or disable the button panel
132 if (panel)
133 panel->Enabled(value);
134
135 if (sbs->Verbose)
136 {
137 if (value == true)
138 Report("Enabled");
139 else
140 Report("Disabled");
141 }
142}
143
145{
146 return is_enabled;
147}
148
149void CallStation::Report(const std::string &message)
150{
151 //general reporting function
152 std::string msg = "Call Station " + ToString(GetFloor()) + ":" + ToString(Number) + " - " + message;
153 Object::Report(msg);
154}
155
156bool CallStation::ReportError(const std::string &message)
157{
158 //general reporting function
159 std::string msg = "Call Station " + ToString(GetFloor()) + ":" + ToString(Number) + " - " + message;
160 return Object::ReportError(msg);
161}
162
164{
165 //return floor number this call station is on
166
167 return floor->Number;
168}
169
171{
172 return panel;
173}
174
176{
177 if (panel)
178 {
179 panel->parent_deleting = true;
180 delete panel;
181 }
182 panel = 0;
183}
184
186{
187 //check lock state
188 if (IsLocked() == true)
189 return ReportError("Call station is locked");
190
191 Report("Selecting floor " + ToString(floor));
192
193 if (GetController())
194 return GetController()->RequestRoute(this, GetFloor(), floor);
195 else
196 return ReportError("No controller");
197 return false;
198}
199
201{
202 //assign this call station to a controller, and register with it
203
204 controller = number;
205
206 if (GetController())
208}
209
214
216{
217 position.y += sbs->GetFloor(GetFloor())->GetBase();
218 Object::SetPosition(position);
219}
220
222{
223 if (GetController())
224 return GetController()->ServicesElevator(elevator);
225 return false;
226}
227
228int CallStation::GetElevatorArrived(int starting_floor, int destination_floor)
229{
230 //return the number of the elevator that has arrived, for the specified route
231 //return 0 if no elevator has arrived yet
232
233 if (!GetController())
234 return 0;
235
236 return GetController()->GetElevatorArrived(starting_floor, destination_floor);
237}
238
240{
241 //return the number of the elevator that has arrived, for the specified route
242 //return 0 if no elevator has arrived yet
243
244 if (!GetController())
245 return 0;
246
247 return GetController()->GetElevatorArrivedStandard(floor, direction);
248}
249
251{
252 if (GetController())
253 return GetController()->FireService(value);
254 else
255 return ReportError("No controller");
256 return false;
257}
258
259Indicator* CallStation::AddIndicator(const std::string &sound, const std::string &texture_prefix, const std::string &blank_texture, const std::string &direction, Real CenterX, Real CenterZ, Real width, Real height, Real voffset, Real timer_duration)
260{
261 if (indicator)
262 return 0;
263
264 indicator = new Indicator(this, sound, texture_prefix, blank_texture, direction, CenterX, CenterZ, width, height, voffset, timer_duration);
265
266 return indicator;
267}
268
269void CallStation::UpdateIndicator(const std::string &text, bool play_sound)
270{
271 if (indicator)
272 indicator->Update(text, play_sound);
273}
274
275bool CallStation::Input(const std::string &text)
276{
277 //input a keypad character
278
279 //only allow single characters
280 if (text.length() != 1)
281 return false;
282
283 //check lock state
284 if (IsLocked() == true)
285 return ReportError("Call station is locked");
286
287 //erase last character if specified
288 if (text == "<" && InputCache.size() >= 1)
289 InputCache.pop_back();
290
291 //add text to cache
292 InputCache += text;
293
294 //automatically error if multiple special characters were entered and/or combined with numbers
295 int StarCount = std::count(InputCache.begin(), InputCache.end(), '*');
296 int MinCount = std::count(InputCache.begin(), InputCache.end(), '-');
297 if ((StarCount > 1 || MinCount > 1) && InputCache.length() > 1)
298 {
299 timer->Stop();
300 InputCache = "";
301 Error(1);
302 return true;
303 }
304
305 //update indicator display
307
308 //verify that the floor entry is valid, error if not
309 int result = 0;
310 if (GetFloorFromID(InputCache, result) == false && InputCache != "*" && InputCache != "-")
311 {
312 timer->Stop();
313 InputCache = "";
314 Error(1);
315 return true;
316 }
317
318 //start timeout timer
319 timer->Start(TimerDelay * 1000.0f, true);
320
321 return true;
322}
323
325{
326 //process and clear input cache
327
328 //select recall floor if "0"
329 if (InputCache == "0" || InputCache == "*")
330 {
332 InputCache = "";
333 return;
334 }
335
336 if (!IsNumeric(InputCache))
337 {
338 InputCache = "";
339 Error();
340 return;
341 }
342
343 //don't allow input values in the InvalidInput list
344 for (size_t i = 0; i < InvalidInput.size(); i++)
345 {
346 if (InputCache == InvalidInput[i])
347 {
348 InputCache = "";
349 Error();
350 return;
351 }
352 }
353
354 int floor = 0;
357
358 InputCache = "";
359}
360
361bool CallStation::GetFloorFromID(const std::string &floor, int &result)
362{
363 if (!IsNumeric(floor))
364 return false;
365
366 int rawfloor = ToInt(floor);
367
368 //convert back to string, to strip off any leading 0's
369 std::string converted = ToString(rawfloor);
370
371 Floor *floorobj = sbs->GetFloorManager()->GetByNumberID(converted);
372 Floor *floorobj2 = sbs->GetFloorManager()->GetByID(converted);
373 Floor *floorobj3 = sbs->GetFloorManager()->Get(rawfloor);
374
375 if (floorobj)
376 {
377 result = floorobj->Number; //get by number ID first
378 return true;
379 }
380 else if (floorobj2)
381 {
382 result = floorobj2->Number; //next try floor ID
383 return true;
384 }
385 else if (floorobj3)
386 {
387 result = rawfloor; //and last, get by raw floor number
388 return true;
389 }
390
391 return false;
392}
393
394void CallStation::Error(bool type)
395{
396 //if type is 0, standard error
397 //if type is 1, invalid floor
398
399 std::string message = "XX";
400 if (type == 1)
401 message = "??";
402
403 UpdateIndicator(message);
404}
405
407{
408 //get recall floor of elevator group from controller
409
410 if (GetController())
411 return GetController()->GetRecallFloor();
412 return 0;
413}
414
416{
417 //report which elevator is assigned, on indicator
418
419 if (ShowDirection == true)
420 {
421 //update indicator with direction of elevator
422 std::string Direction = this->GetPanel()->Direction;
423 Vector3 ButtonPos = this->GetPanel()->GetPosition();
424 Vector3 ShaftPos = elevator->GetPosition();
425
426 if (Direction == "front")
427 {
428 if (ButtonPos.x > ShaftPos.x)
429 return UpdateIndicator((ButtonPos.z < ShaftPos.z ? "<" : "[]") + elevator->ID);
430 else
431 return UpdateIndicator(elevator->ID + (ButtonPos.z < ShaftPos.z ? ">" : "[]"));
432 }
433 else if (Direction == "back")
434 {
435 if (ButtonPos.x < ShaftPos.x)
436 return UpdateIndicator((ButtonPos.z > ShaftPos.z ? "<" : "[]") + elevator->ID);
437 else
438 return UpdateIndicator(elevator->ID + (ButtonPos.z > ShaftPos.z ? ">" : "[]"));
439 }
440 else if (Direction == "left")
441 {
442 if (ButtonPos.z < ShaftPos.z)
443 return UpdateIndicator((ButtonPos.x < ShaftPos.x ? "<" : "[]") + elevator->ID);
444 else
445 return UpdateIndicator(elevator->ID + (ButtonPos.x < ShaftPos.x ? ">" : "[]"));
446 }
447 else if (Direction == "right")
448 {
449 if (ButtonPos.z > ShaftPos.z)
450 return UpdateIndicator((ButtonPos.x > ShaftPos.x ? "<" : "[]") + elevator->ID);
451 else
452 return UpdateIndicator(elevator->ID + (ButtonPos.x > ShaftPos.x ? ">" : "[]"));
453 }
454 }
455
456 //otherwise update indicator with just elevator ID
457 UpdateIndicator(elevator->ID);
458 return;
459}
460
461bool CallStation::Call(bool direction)
462{
463 //call elevator in the specified direction
464
465 SBS_PROFILE("CallStation::Call");
466
467 //check lock state
468 if (IsLocked() == true)
469 return ReportError("Call station is locked");
470
471 if (!GetController())
472 return ReportError("No controller");
473
474 //turn on button lights
475 if (direction == true)
476 UpLight(true);
477 else
478 DownLight(true);
479
480 if (GetController())
481 return GetController()->CallElevator(this, direction);
482
483 return false;
484}
485
486void CallStation::SetLightsGroup(int up, int down)
487{
488 //set status of call button lights for whole group
489 //values are 0 for no change, 1 for on, and 2 for off
490
491 if (sbs->Verbose)
492 Report("Call: finding grouped call buttons");
493
494 //this call will return at least this call button
495 std::vector<CallStation*> stations;
496 if (GetController())
498
499 //set status on each call button
500 for (size_t i = 0; i < stations.size(); i++)
501 {
502 if (stations[i])
503 stations[i]->SetLights(up, down);
504 }
505}
506
507void CallStation::UpLight(bool value)
508{
509 //turn on the 'up' directional light
510
511 //set light status
512 if (value == true)
513 SetLightsGroup(1, 0);
514 else
515 SetLightsGroup(2, 0);
516}
517
519{
520 //turn on the 'down' directional light
521
522 //set light status
523 if (value == true)
524 SetLightsGroup(0, 1);
525 else
526 SetLightsGroup(0, 2);
527}
528
529void CallStation::SetLights(int up, int down)
530{
531 //set status of call button lights
532 //values are 0 for no change, 1 for on, and 2 for off
533
534 if (up == 1)
535 {
536 if (GetUpStatus() == true)
537 {
538 if (sbs->Verbose)
539 Report("SetLights: up light already in requested status");
540 return;
541 }
542
543 if (sbs->Verbose)
544 Report("SetLights: turning on up light");
545
546 if (GetUpControl())
548 }
549
550 if (up == 2)
551 {
552 if (GetUpStatus() == false)
553 {
554 if (sbs->Verbose)
555 Report("SetLights: up light already in requested status");
556 return;
557 }
558
559 if (sbs->Verbose)
560 Report("SetLights: turning off up light");
561
562 if (GetUpControl())
564 }
565
566 if (down == 1)
567 {
568 if (GetDownStatus() == true)
569 {
570 if (sbs->Verbose)
571 Report("SetLights: down light already in requested status");
572 return;
573 }
574
575 if (sbs->Verbose)
576 Report("SetLights: turning on down light");
577
578 if (GetDownControl())
580 }
581 if (down == 2)
582 {
583 if (GetDownStatus() == false)
584 {
585 if (sbs->Verbose)
586 Report("SetLights: down light already in requested status");
587 return;
588 }
589
590 if (sbs->Verbose)
591 Report("SetLights: turning off down light");
592
593 if (GetDownControl())
595 }
596}
597
599{
600 if (GetUpControl())
601 return (GetUpControl()->GetSelectPosition() == 2);
602 return false;
603}
604
606{
607 if (GetDownControl())
608 return (GetDownControl()->GetSelectPosition() == 2);
609 return false;
610}
611
613{
614 return panel->GetControl("up");
615}
616
618{
619 return panel->GetControl("down");
620}
621
623{
624 //press the related call button (the control object)
625 //which also initiates the call via the Call() function
626
627 bool result = false;
628
629 if (up == true && GetUpControl())
630 result = GetUpControl()->Press();
631 if (up == false && GetDownControl())
632 result = GetDownControl()->Press();
633
634 return result;
635}
636
637bool CallStation::CreateCallButtons(const std::string &sound_file_up, const std::string &sound_file_down, std::string BackTexture, const std::string &UpButtonTexture, const std::string &UpButtonTexture_Lit, const std::string &DownButtonTexture, const std::string &DownButtonTexture_Lit, const std::string &direction, Real BackWidth, Real BackHeight, bool ShowBack, Real tw, Real th)
638{
639 //creates a panel and call buttons for this call station
640
641 if (!GetController())
642 return false;
643
644 if (ShowBack == false)
645 BackTexture = "";
646
647 int topfloor = GetController()->GetTopFloor();
648 int bottomfloor = GetController()->GetBottomFloor();
649 bool UpExists = false;
650 bool DownExists = false;
651
652 if (floor->Number > bottomfloor && floor->Number < topfloor)
653 {
654 UpExists = true;
655 DownExists = true;
656 }
657 else if (floor->Number == bottomfloor)
658 UpExists = true;
659 else if (floor->Number == topfloor)
660 DownExists = true;
661
662 int rows = 0;
663 if (UpExists == true)
664 rows++;
665 if (DownExists == true)
666 rows++;
667
668 //create button panel
669 Real button_height = BackHeight / 3.5;
670 Real button_width = BackWidth / 2;
671 Real h_spacing = 0.5;
672 Real v_spacing = 1.25;
673 if (UpExists == true && DownExists == true)
674 v_spacing = 0.5;
675
676 panel = new ButtonPanel(this, 1, BackTexture, rows, 1, direction, 0, 0, button_width, button_height, h_spacing, v_spacing, BackHeight / 2, tw, th, false);
677
678 //create controls
679 if (sbs->Verbose)
680 Report("Creating controls");
681
682 if (UpExists == true)
683 {
684 int row = 1;
685 std::vector<std::string> names, textures;
686
687 textures.emplace_back(UpButtonTexture);
688 textures.emplace_back(UpButtonTexture_Lit);
689 sbs->GetTextureManager()->EnableLighting(UpButtonTexture_Lit, false);
690 names.emplace_back("off");
691 names.emplace_back("up");
692
693 panel->AddControl(sound_file_up, row, 1, 1, 1, 0, 0, 1, names, textures);
694 }
695 if (DownExists == true)
696 {
697 int row = 1;
698 if (UpExists == true)
699 row = 2;
700
701 std::vector<std::string> names, textures;
702
703 textures.emplace_back(DownButtonTexture);
704 textures.emplace_back(DownButtonTexture_Lit);
705 sbs->GetTextureManager()->EnableLighting(DownButtonTexture_Lit, false);
706 names.emplace_back("off");
707 names.emplace_back("down");
708
709 panel->AddControl(sound_file_down, row, 1, 1, 1, 0, 0, 1, names, textures);
710 }
711
712 return true;
713}
714
715}
std::string Direction
Definition buttonpanel.h:34
void Enabled(bool value)
Control * AddControl(const std::string &sound, int row, int column, Real bwidth, Real bheight, Real hoffset, Real voffset, int selection_position, std::vector< std::string > &action_names, std::vector< std::string > &textures)
Control * GetControl(int index)
Timer(const std::string &name, CallStation *parent)
std::string InputCache
Definition callstation.h:91
ButtonPanel * GetPanel()
void ReportElevator(Elevator *elevator)
bool Press(bool up)
bool SelectFloor(int floor)
void SetLightsGroup(int up, int down)
Control * GetUpControl()
bool GetFloorFromID(const std::string &floor, int &result)
void UpdateIndicator(const std::string &text, bool play_sound=true)
void Enabled(bool value)
std::vector< std::string > InvalidInput
Definition callstation.h:37
DispatchController * GetController()
void SetController(int number)
ButtonPanel * panel
Definition callstation.h:81
bool ServicesElevator(int elevator)
void DownLight(bool value)
ButtonPanel * CreateButtonPanel(const std::string &texture, int rows, int columns, const std::string &direction, Real width, Real height, Real spacingX, Real spacingY, Real tw, Real th)
bool Input(const std::string &text)
bool ReportError(const std::string &message)
Control * GetDownControl()
void Report(const std::string &message)
int GetElevatorArrived(int starting_floor, int destination_floor)
void UpLight(bool value)
int GetElevatorArrivedStandard(int floor, bool direction)
CallStation(Object *parent, int floornum, int number)
void SetLights(int up, int down)
void SetPosition(Vector3 &position)
void Error(bool type=0)
bool FireService(int value)
bool Call(bool direction)
Indicator * indicator
Definition callstation.h:88
Indicator * AddIndicator(const std::string &sound, const std::string &texture_prefix, const std::string &blank_texture, const std::string &direction, Real CenterX, Real CenterZ, Real width, Real height, Real voffset, Real timer_duration)
bool CreateCallButtons(const std::string &sound_file_up, const std::string &sound_file_down, std::string BackTexture, const std::string &UpButtonTexture, const std::string &UpButtonTexture_Lit, const std::string &DownButtonTexture, const std::string &DownButtonTexture_Lit, const std::string &direction, Real BackWidth, Real BackHeight, bool ShowBack, Real tw, Real th)
bool Press(bool reverse=false)
Definition control.cpp:386
bool SetSelectPosition(int position)
Definition control.cpp:190
bool ServicesElevator(int elevator)
std::vector< CallStation * > GetCallStations(int floor)
bool FireService(int value)
int GetElevatorArrived(int starting_floor, int destination_floor)
bool CallElevator(CallStation *station, bool direction)
void UnregisterCallStation(CallStation *station)
int GetElevatorArrivedStandard(int floor, bool direction)
void RegisterCallStation(CallStation *station)
bool RequestRoute(CallStation *station, int starting_floor, int destination_floor)
std::string ID
Definition elevator.h:37
Floor * GetByID(const std::string &id)
Definition manager.cpp:185
Floor * GetByNumberID(const std::string &id)
Definition manager.cpp:198
Floor * Get(int number)
Definition manager.cpp:108
void RemoveCallStation(CallStation *station)
Definition floor.cpp:1319
int Number
Definition floor.h:36
Real GetBase(bool relative=false)
Definition floor.cpp:1146
void Update(const std::string &text, bool play_sound=true)
bool IsLocked()
Definition lock.cpp:66
virtual bool ReportError(const std::string &message)
Definition object.cpp:84
virtual void Report(const std::string &message)
Definition object.cpp:78
void SetName(const std::string &name)
Definition object.cpp:72
bool parent_deleting
Definition object.h:64
virtual Vector3 GetPosition(bool relative=false)
Definition object.cpp:307
void SetValues(const std::string &type, const std::string &name, bool is_permanent, bool is_movable=true)
Definition object.cpp:144
virtual void SetPosition(const Vector3 &position, bool relative=false, bool force=false)
Definition object.cpp:280
FloorManager * GetFloorManager()
Definition sbs.cpp:4563
DispatchController * GetController(int number)
Definition sbs.cpp:1804
Floor * GetFloor(int number)
Definition sbs.cpp:1769
bool FastDelete
Definition sbs.h:188
TextureManager * GetTextureManager()
Definition sbs.cpp:4588
bool Verbose
Definition sbs.h:186
void EnableLighting(const std::string &material_name, bool value)
Definition texture.cpp:2207
void Start(int milliseconds=-1, bool oneshot=false)
Definition timer.cpp:49
Ogre::Vector3 Vector3
Definition globals.h:58
Ogre::Real Real
Definition globals.h:57
int ToInt(const std::string &string)
Definition globals.cpp:402
std::string ToString(int number)
Definition globals.cpp:279
bool IsNumeric(char character)
Definition globals.cpp:48
#define SBS_PROFILE(name)
Definition profiler.h:131