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
144void CallStation::Report(const std::string &message)
145{
146 //general reporting function
147 std::string msg = "Call Station " + ToString(GetFloor()) + ":" + ToString(Number) + " - " + message;
148 Object::Report(msg);
149}
150
151bool CallStation::ReportError(const std::string &message)
152{
153 //general reporting function
154 std::string msg = "Call Station " + ToString(GetFloor()) + ":" + ToString(Number) + " - " + message;
155 return Object::ReportError(msg);
156}
157
159{
160 //return floor number this call station is on
161
162 return floor->Number;
163}
164
166{
167 return panel;
168}
169
171{
172 if (panel)
173 {
174 panel->parent_deleting = true;
175 delete panel;
176 }
177 panel = 0;
178}
179
181{
182 //check lock state
183 if (IsLocked() == true)
184 return ReportError("Call station is locked");
185
186 Report("Selecting floor " + ToString(floor));
187
188 if (GetController())
189 return GetController()->RequestRoute(this, GetFloor(), floor);
190 else
191 return ReportError("No controller");
192 return false;
193}
194
196{
197 //assign this call station to a controller, and register with it
198
199 controller = number;
200
201 if (GetController())
203}
204
209
211{
212 position.y += sbs->GetFloor(GetFloor())->GetBase();
213 Object::SetPosition(position);
214}
215
217{
218 if (GetController())
219 return GetController()->ServicesElevator(elevator);
220 return false;
221}
222
223int CallStation::GetElevatorArrived(int starting_floor, int destination_floor)
224{
225 //return the number of the elevator that has arrived, for the specified route
226 //return 0 if no elevator has arrived yet
227
228 if (!GetController())
229 return 0;
230
231 return GetController()->GetElevatorArrived(starting_floor, destination_floor);
232}
233
235{
236 //return the number of the elevator that has arrived, for the specified route
237 //return 0 if no elevator has arrived yet
238
239 if (!GetController())
240 return 0;
241
242 return GetController()->GetElevatorArrivedStandard(floor, direction);
243}
244
246{
247 if (GetController())
248 return GetController()->FireService(value);
249 else
250 return ReportError("No controller");
251 return false;
252}
253
254Indicator* 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)
255{
256 if (indicator)
257 return 0;
258
259 indicator = new Indicator(this, sound, texture_prefix, blank_texture, direction, CenterX, CenterZ, width, height, voffset, timer_duration);
260
261 return indicator;
262}
263
264void CallStation::UpdateIndicator(const std::string &text, bool play_sound)
265{
266 if (indicator)
267 indicator->Update(text, play_sound);
268}
269
270bool CallStation::Input(const std::string &text)
271{
272 //input a keypad character
273
274 //only allow single characters
275 if (text.length() != 1)
276 return false;
277
278 //check lock state
279 if (IsLocked() == true)
280 return ReportError("Call station is locked");
281
282 //erase last character if specified
283 if (text == "<" && InputCache.size() >= 1)
284 InputCache.pop_back();
285
286 //add text to cache
287 InputCache += text;
288
289 //automatically error if multiple special characters were entered and/or combined with numbers
290 int StarCount = std::count(InputCache.begin(), InputCache.end(), '*');
291 int MinCount = std::count(InputCache.begin(), InputCache.end(), '-');
292 if ((StarCount > 1 || MinCount > 1) && InputCache.length() > 1)
293 {
294 timer->Stop();
295 InputCache = "";
296 Error(1);
297 return true;
298 }
299
300 //update indicator display
302
303 //verify that the floor entry is valid, error if not
304 int result = 0;
305 if (GetFloorFromID(InputCache, result) == false && InputCache != "*" && InputCache != "-")
306 {
307 timer->Stop();
308 InputCache = "";
309 Error(1);
310 return true;
311 }
312
313 //start timeout timer
314 timer->Start(TimerDelay * 1000.0f, true);
315
316 return true;
317}
318
320{
321 //process and clear input cache
322
323 //select recall floor if "0"
324 if (InputCache == "0" || InputCache == "*")
325 {
327 InputCache = "";
328 return;
329 }
330
331 if (!IsNumeric(InputCache))
332 {
333 InputCache = "";
334 Error();
335 return;
336 }
337
338 //don't allow input values in the InvalidInput list
339 for (size_t i = 0; i < InvalidInput.size(); i++)
340 {
341 if (InputCache == InvalidInput[i])
342 {
343 InputCache = "";
344 Error();
345 return;
346 }
347 }
348
349 int floor = 0;
352
353 InputCache = "";
354}
355
356bool CallStation::GetFloorFromID(const std::string &floor, int &result)
357{
358 if (!IsNumeric(floor))
359 return false;
360
361 int rawfloor = ToInt(floor);
362
363 //convert back to string, to strip off any leading 0's
364 std::string converted = ToString(rawfloor);
365
366 Floor *floorobj = sbs->GetFloorManager()->GetByNumberID(converted);
367 Floor *floorobj2 = sbs->GetFloorManager()->GetByID(converted);
368 Floor *floorobj3 = sbs->GetFloorManager()->Get(rawfloor);
369
370 if (floorobj)
371 {
372 result = floorobj->Number; //get by number ID first
373 return true;
374 }
375 else if (floorobj2)
376 {
377 result = floorobj2->Number; //next try floor ID
378 return true;
379 }
380 else if (floorobj3)
381 {
382 result = rawfloor; //and last, get by raw floor number
383 return true;
384 }
385
386 return false;
387}
388
389void CallStation::Error(bool type)
390{
391 //if type is 0, standard error
392 //if type is 1, invalid floor
393
394 std::string message = "XX";
395 if (type == 1)
396 message = "??";
397
398 UpdateIndicator(message);
399}
400
402{
403 //get recall floor of elevator group from controller
404
405 if (GetController())
406 return GetController()->GetRecallFloor();
407 return 0;
408}
409
411{
412 //report which elevator is assigned, on indicator
413
414 if (ShowDirection == true)
415 {
416 //update indicator with direction of elevator
417 std::string Direction = this->GetPanel()->Direction;
418 Vector3 ButtonPos = this->GetPanel()->GetPosition();
419 Vector3 ShaftPos = elevator->GetPosition();
420
421 if (Direction == "front")
422 {
423 if (ButtonPos.x > ShaftPos.x)
424 return UpdateIndicator((ButtonPos.z < ShaftPos.z ? "<" : "[]") + elevator->ID);
425 else
426 return UpdateIndicator(elevator->ID + (ButtonPos.z < ShaftPos.z ? ">" : "[]"));
427 }
428 else if (Direction == "back")
429 {
430 if (ButtonPos.x < ShaftPos.x)
431 return UpdateIndicator((ButtonPos.z > ShaftPos.z ? "<" : "[]") + elevator->ID);
432 else
433 return UpdateIndicator(elevator->ID + (ButtonPos.z > ShaftPos.z ? ">" : "[]"));
434 }
435 else if (Direction == "left")
436 {
437 if (ButtonPos.z < ShaftPos.z)
438 return UpdateIndicator((ButtonPos.x < ShaftPos.x ? "<" : "[]") + elevator->ID);
439 else
440 return UpdateIndicator(elevator->ID + (ButtonPos.x < ShaftPos.x ? ">" : "[]"));
441 }
442 else if (Direction == "right")
443 {
444 if (ButtonPos.z > ShaftPos.z)
445 return UpdateIndicator((ButtonPos.x > ShaftPos.x ? "<" : "[]") + elevator->ID);
446 else
447 return UpdateIndicator(elevator->ID + (ButtonPos.x > ShaftPos.x ? ">" : "[]"));
448 }
449 }
450
451 //otherwise update indicator with just elevator ID
452 UpdateIndicator(elevator->ID);
453 return;
454}
455
456bool CallStation::Call(bool direction)
457{
458 //call elevator in the specified direction
459
460 SBS_PROFILE("CallStation::Call");
461
462 //check lock state
463 if (IsLocked() == true)
464 return ReportError("Call station is locked");
465
466 if (!GetController())
467 return ReportError("No controller");
468
469 //turn on button lights
470 if (direction == true)
471 UpLight(true);
472 else
473 DownLight(true);
474
475 if (GetController())
476 return GetController()->CallElevator(this, direction);
477
478 return false;
479}
480
481void CallStation::SetLightsGroup(int up, int down)
482{
483 //set status of call button lights for whole group
484 //values are 0 for no change, 1 for on, and 2 for off
485
486 if (sbs->Verbose)
487 Report("Call: finding grouped call buttons");
488
489 //this call will return at least this call button
490 std::vector<CallStation*> stations;
491 if (GetController())
493
494 //set status on each call button
495 for (size_t i = 0; i < stations.size(); i++)
496 {
497 if (stations[i])
498 stations[i]->SetLights(up, down);
499 }
500}
501
502void CallStation::UpLight(bool value)
503{
504 //turn on the 'up' directional light
505
506 //set light status
507 if (value == true)
508 SetLightsGroup(1, 0);
509 else
510 SetLightsGroup(2, 0);
511}
512
514{
515 //turn on the 'down' directional light
516
517 //set light status
518 if (value == true)
519 SetLightsGroup(0, 1);
520 else
521 SetLightsGroup(0, 2);
522}
523
524void CallStation::SetLights(int up, int down)
525{
526 //set status of call button lights
527 //values are 0 for no change, 1 for on, and 2 for off
528
529 if (up == 1)
530 {
531 if (GetUpStatus() == true)
532 {
533 if (sbs->Verbose)
534 Report("SetLights: up light already in requested status");
535 return;
536 }
537
538 if (sbs->Verbose)
539 Report("SetLights: turning on up light");
540
541 if (GetUpControl())
543 }
544
545 if (up == 2)
546 {
547 if (GetUpStatus() == false)
548 {
549 if (sbs->Verbose)
550 Report("SetLights: up light already in requested status");
551 return;
552 }
553
554 if (sbs->Verbose)
555 Report("SetLights: turning off up light");
556
557 if (GetUpControl())
559 }
560
561 if (down == 1)
562 {
563 if (GetDownStatus() == true)
564 {
565 if (sbs->Verbose)
566 Report("SetLights: down light already in requested status");
567 return;
568 }
569
570 if (sbs->Verbose)
571 Report("SetLights: turning on down light");
572
573 if (GetDownControl())
575 }
576 if (down == 2)
577 {
578 if (GetDownStatus() == false)
579 {
580 if (sbs->Verbose)
581 Report("SetLights: down light already in requested status");
582 return;
583 }
584
585 if (sbs->Verbose)
586 Report("SetLights: turning off down light");
587
588 if (GetDownControl())
590 }
591}
592
594{
595 if (GetUpControl())
596 return (GetUpControl()->GetSelectPosition() == 2);
597 return false;
598}
599
601{
602 if (GetDownControl())
603 return (GetDownControl()->GetSelectPosition() == 2);
604 return false;
605}
606
608{
609 return panel->GetControl("up");
610}
611
613{
614 return panel->GetControl("down");
615}
616
618{
619 //press the related call button (the control object)
620 //which also initiates the call via the Call() function
621
622 bool result = false;
623
624 if (up == true && GetUpControl())
625 result = GetUpControl()->Press();
626 if (up == false && GetDownControl())
627 result = GetDownControl()->Press();
628
629 return result;
630}
631
632bool 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)
633{
634 //creates a panel and call buttons for this call station
635
636 if (!GetController())
637 return false;
638
639 if (ShowBack == false)
640 BackTexture = "";
641
642 int topfloor = GetController()->GetTopFloor();
643 int bottomfloor = GetController()->GetBottomFloor();
644 bool UpExists = false;
645 bool DownExists = false;
646
647 if (floor->Number > bottomfloor && floor->Number < topfloor)
648 {
649 UpExists = true;
650 DownExists = true;
651 }
652 else if (floor->Number == bottomfloor)
653 UpExists = true;
654 else if (floor->Number == topfloor)
655 DownExists = true;
656
657 int rows = 0;
658 if (UpExists == true)
659 rows++;
660 if (DownExists == true)
661 rows++;
662
663 //create button panel
664 Real button_height = BackHeight / 3.5;
665 Real button_width = BackWidth / 2;
666 Real h_spacing = 0.5;
667 Real v_spacing = 1.25;
668 if (UpExists == true && DownExists == true)
669 v_spacing = 0.5;
670
671 panel = new ButtonPanel(this, 1, BackTexture, rows, 1, direction, 0, 0, button_width, button_height, h_spacing, v_spacing, BackHeight / 2, tw, th, false);
672
673 //create controls
674 if (sbs->Verbose)
675 Report("Creating controls");
676
677 if (UpExists == true)
678 {
679 int row = 1;
680 std::vector<std::string> names, textures;
681
682 textures.emplace_back(UpButtonTexture);
683 textures.emplace_back(UpButtonTexture_Lit);
684 sbs->GetTextureManager()->EnableLighting(UpButtonTexture_Lit, false);
685 names.emplace_back("off");
686 names.emplace_back("up");
687
688 panel->AddControl(sound_file_up, row, 1, 1, 1, 0, 0, 1, names, textures);
689 }
690 if (DownExists == true)
691 {
692 int row = 1;
693 if (UpExists == true)
694 row = 2;
695
696 std::vector<std::string> names, textures;
697
698 textures.emplace_back(DownButtonTexture);
699 textures.emplace_back(DownButtonTexture_Lit);
700 sbs->GetTextureManager()->EnableLighting(DownButtonTexture_Lit, false);
701 names.emplace_back("off");
702 names.emplace_back("down");
703
704 panel->AddControl(sound_file_down, row, 1, 1, 1, 0, 0, 1, names, textures);
705 }
706
707 return true;
708}
709
710}
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:90
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:80
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:87
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:1313
int Number
Definition floor.h:36
Real GetBase(bool relative=false)
Definition floor.cpp:1140
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:321
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)
Definition object.cpp:274
FloorManager * GetFloorManager()
Definition sbs.cpp:4533
DispatchController * GetController(int number)
Definition sbs.cpp:1774
Floor * GetFloor(int number)
Definition sbs.cpp:1739
bool FastDelete
Definition sbs.h:188
TextureManager * GetTextureManager()
Definition sbs.cpp:4558
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