Skyscraper 2.0
door.cpp
Go to the documentation of this file.
1/*
2 Scalable Building Simulator - Door 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 "manager.h"
27#include "mesh.h"
28#include "floor.h"
29#include "elevatorcar.h"
30#include "shaft.h"
31#include "stairs.h"
32#include "texture.h"
33#include "sound.h"
34#include "timer.h"
35#include "doorsystem.h"
36#include "profiler.h"
37#include "door.h"
38
39namespace SBS {
40
41//auto-close timer
43{
44public:
46 Timer(const std::string &name, Door *parent) : TimerObject(parent, name)
47 {
48 door = parent;
49 }
50 virtual void Notify();
51};
52
53Door::Door(Object *parent, DynamicMesh *wrapper, const std::string &name, const std::string &open_sound, const std::string &close_sound, bool rotate) : Object(parent), DoorLock(this)
54{
55 //creates a door, the 'direction' parameter is for the lock direction
56 //wall cuts must be performed by the calling (parent) function
57
58 //set up SBS object
59 SetValues("Door", name, false);
60
61 is_enabled = true;
62
63 OpenState = false;
64 IsMoving = false;
65 OpenDoor = false;
66 OpenSound = open_sound;
67 CloseSound = close_sound;
68 sound = 0;
69 door_changed = false;
70 previous_open = false;
71 this->wrapper = wrapper;
72 running = false;
73 DoorDirection = false;
74 timer = new Timer("Auto-close Timer", this);
76
77 //create door wrapper
78 door = new DoorWrapper(this, rotate);
79
80 //create sound object
81 if (open_sound != "" || close_sound != "")
82 sound = new Sound(this, "DoorSound", true);
83}
84
86{
87 //destructor
88
89 if (timer)
90 {
91 timer->parent_deleting = true;
92 delete timer;
93 }
94 timer = 0;
95
96 if (sound)
97 {
98 sound->parent_deleting = true;
99 delete sound;
100 }
101 sound = 0;
102
103 if (door)
104 {
105 door->parent_deleting = true;
106 delete door;
107 }
108 door = 0;
109
110 //unregister from parent
111 if (sbs->FastDelete == false)
112 {
113 if (parent_deleting == false)
114 {
115 std::string type = GetParent()->GetType();
116
117 if (type == "ElevatorCar")
118 static_cast<ElevatorCar*>(GetParent())->RemoveDoor(this);
119 else if (type == "Floor")
120 static_cast<Floor*>(GetParent())->RemoveDoor(this);
121 else if (type == "Shaft Level")
122 static_cast<Shaft::Level*>(GetParent())->RemoveDoor(this);
123 else if (type == "Stairwell Level")
124 static_cast<Stairwell::Level*>(GetParent())->RemoveDoor(this);
125 else if (type == "DoorManager")
126 sbs->GetDoorManager()->RemoveDoor(this);
127 }
128 }
129}
130
131bool Door::Open(Vector3 &position, bool playsound, bool force)
132{
133 //position is the camera position, used to check if the door is locked
134 //if force is true, locking/position check will be bypassed
135
136 Report("Opening");
137
138 EnableLoop(true);
139
140 if (force == false)
141 {
142 //check lock state
143 if (IsLocked(position) == true)
144 return ReportError("Is locked");
145 }
146
147 OpenDoor = true;
148
149 if (playsound == true && sound)
150 {
152 sound->Play();
153 }
154
155 OpenState = false;
156 IsMoving = true;
158
159 //enable autoclose timer if needed
161
162 return true;
163}
164
165void Door::Close(bool playsound)
166{
167 Report("Closing");
168
169 EnableLoop(true);
170
171 OpenDoor = false;
172
173 if (playsound == true && sound)
174 {
176 sound->Play();
177 }
178
179 OpenState = true;
180 IsMoving = true;
182}
183
185{
186 return OpenState;
187}
188
189void Door::Enabled(bool value)
190{
191 if (is_enabled == value)
192 return;
193
194 door->Enabled(value);
195 is_enabled = value;
196}
197
199{
200 SBS_PROFILE("Door::Loop");
201
202 if (IsMoving == true)
203 MoveDoor();
204 else
205 EnableLoop(false);
206}
207
209{
210 //door movement callback function
211
212 //if a different direction was specified during movement
213 if (running == true && previous_open != OpenDoor && door_changed == false)
214 door_changed = true;
215
216 running = true;
217
218 //perform door movement and get open state of each door
220
222
223 //wait until all door components are finished moving
225 if (door->IsFinished() == false)
226 return;
227
228 //the doors are open or closed now
229 door_changed = false;
230 IsMoving = false;
231 running = false;
232
233 if (OpenDoor == true)
234 OpenState = true;
235 else
236 OpenState = false;
237}
238
240{
241 //code that runs when a user clicks on a door
242
243 //open and close doors
244 if (IsOpen() == false)
245 {
246 if (IsMoving == false)
247 Open(position);
248 else
249 Close();
250 }
251 else
252 {
253 if (IsMoving == false)
254 Close();
255 else
256 Open(position);
257 }
258}
259
260void Door::OnClick(Vector3 &position, bool shift, bool ctrl, bool alt, bool right)
261{
262 if (right == false)
263 {
264 //toggle lock status if ctrl and shift are pressed
265 if (ctrl == true && shift == true)
266 ToggleLock(position);
267 else
268 ClickDoor(position);
269 }
270}
271
272void Door::Report(const std::string &message)
273{
274 //general reporting function
275 Object::Report("Door " + GetName() + ": " + message);
276}
277
278bool Door::ReportError(const std::string &message)
279{
280 //general error reporting function
281 return Object::ReportError("Door " + GetName() + ": " + message);
282}
283
285{
286 return door_changed;
287}
288
290{
291 return previous_open;
292}
293
294DoorWrapper* Door::CreateDoor(bool open_state, const std::string &texture, const std::string &side_texture, Real thickness, const std::string &face_direction, const std::string &open_direction, Real open_speed, Real close_speed, Real CenterX, Real CenterZ, Real width, Real height, Real voffset, Real tw, Real th, Real side_tw, Real side_th)
295{
296 //create a door
297
298 Vector3 position;
299 Real x1 = 0, z1 = 0, x2 = 0, z2 = 0;
300
301 //set speed to default value if invalid
302 if (open_speed <= 0)
303 open_speed = sbs->GetConfigFloat("Skyscraper.SBS.DoorSpeed", 75.0);
304
305 if (open_speed <= 0)
306 open_speed = 75;
307
308 if (close_speed <= 0)
309 close_speed = open_speed;
310
311 //set origin to location of the door's hinge/pivot point and set up door coordinates
312 if (face_direction == "left")
313 {
314 position = Vector3(CenterX, voffset, CenterZ - (width / 2)); //front
315 x1 = 0;
316 x2 = 0;
317 z1 = 0;
318 z2 = width;
319 }
320 if (face_direction == "right")
321 {
322 position = Vector3(CenterX, voffset, CenterZ + (width / 2)); //back
323 x1 = 0;
324 x2 = 0;
325 z1 = -width;
326 z2 = 0;
327 }
328 if (face_direction == "front")
329 {
330 position = Vector3(CenterX + (width / 2), voffset, CenterZ); //right
331 x1 = -width;
332 x2 = 0;
333 z1 = 0;
334 z2 = 0;
335 }
336 if (face_direction == "back")
337 {
338 position = Vector3(CenterX - (width / 2), voffset, CenterZ); //left
339 x1 = 0;
340 x2 = width;
341 z1 = 0;
342 z2 = 0;
343 }
344
345 bool Clockwise = true;
346 if (face_direction == open_direction)
347 Clockwise = false;
348
349 //create door
350 AddDoorComponent(GetName(), texture, side_texture, thickness, face_direction, open_direction, Clockwise, open_speed, close_speed, x1, z1, x2, z2, height, 0, tw, th, 0, 0);
351 FinishDoor(open_state);
352 Move(position);
353
354 return door;
355}
356
357DoorWrapper* Door::AddDoorComponent(const std::string &name, const std::string &texture, const std::string &sidetexture, Real thickness, const std::string &face_direction, const std::string &open_direction, bool OpenClockwise, Real OpenSpeed, Real CloseSpeed, Real x1, Real z1, Real x2, Real z2, Real height, Real voffset, Real tw, Real th, Real side_tw, Real side_th)
358{
359 //create door component
360
361 bool direction = false;
362 if (face_direction == "right" || face_direction == "back")
363 direction = true;
364
365 DoorComponent *component = door->CreateDoor(name, open_direction, OpenClockwise, OpenSpeed, CloseSpeed, wrapper);
366
368 if (direction == false)
369 sbs->GetTextureManager()->SetTextureFlip(0, 1, 0, 0, 0, 0); //flip texture on rear side of door
370 else
371 sbs->GetTextureManager()->SetTextureFlip(1, 0, 0, 0, 0, 0); //flip texture on rear side of door
372
373 //add main walls
374 sbs->DrawWalls(true, true, false, false, false, false);
375 Wall *wall;
376 wall = component->mesh->CreateWallObject(name);
377 sbs->AddWallMain(wall, name, texture, thickness, x1, z1, x2, z2, height, height, voffset, voffset, tw, th, false);
378 sbs->ResetWalls();
380
381 //add side walls
382 sbs->DrawWalls(false, false, true, true, true, true);
383 wall = component->mesh->CreateWallObject(name);
384 sbs->AddWallMain(wall, name, sidetexture, thickness, x1, z1, x2, z2, height, height, voffset, voffset, side_tw, side_th, false);
385 sbs->ResetWalls();
386
387 //store extents
388 if (x1 < x2)
389 {
390 component->extents_min.x = x1;
391 component->extents_max.x = x2;
392 }
393 else
394 {
395 component->extents_min.x = x2;
396 component->extents_max.x = x1;
397 }
398 if (z1 < z2)
399 {
400 component->extents_min.z = z1;
401 component->extents_max.z = z2;
402 }
403 else
404 {
405 component->extents_min.z = z2;
406 component->extents_max.z = z1;
407 }
408 component->extents_min.y = voffset;
409 component->extents_max.y = voffset + height;
410
411 return door;
412}
413
415{
416 //finishes a door creation
417
418 //exit if no doors exist
419 if (door->doors.empty() == true)
420 {
421 ReportError("FinishDoors: no door components have been created");
422 return 0;
423 }
424
425 //get full width and height of doors
426 Real x1 = 0, x2 = 0, y1 = 0, y2 = 0, z1 = 0, z2 = 0;
427 bool firstrun = true;
428 for (size_t i = 0; i < door->doors.size(); i++)
429 {
430 for (int j = 1; j <= 3; j++)
431 {
432 Vector2 extents = door->doors[i]->mesh->GetExtents(j, true);
433 extents.x = sbs->ToLocal(extents.x);
434 extents.y = sbs->ToLocal(extents.y);
435
436 if (j == 1)
437 {
438 if (extents.x < x1 || firstrun == true)
439 x1 = extents.x;
440 if (extents.y > x2 || firstrun == true)
441 x2 = extents.y;
442 }
443 if (j == 2)
444 {
445 if (extents.x < y1 || firstrun == true)
446 y1 = extents.x;
447 if (extents.y > y2 || firstrun == true)
448 y2 = extents.y;
449 }
450 if (j == 3)
451 {
452 if (extents.x < z1 || firstrun == true)
453 z1 = extents.x;
454 if (extents.y > z2 || firstrun == true)
455 z2 = extents.y;
456 firstrun = false;
457 }
458 }
459 }
460
461 if (x2 - x1 > z2 - z1)
462 {
463 door->Width = x2 - x1;
464 door->Thickness = z2 - z1;
465 door->Shift = x2 - (door->Width / 2);
466 SetDirection(true);
467 DoorDirection = true;
468 }
469 else
470 {
471 door->Width = z2 - z1;
472 door->Thickness = x2 - x1;
473 door->Shift = z2 - (door->Width / 2);
474 SetDirection(false);
475 DoorDirection = false;
476 }
477 door->Height = y2 - y1;
478 if (y2 < y1)
479 door->voffset = y2;
480 else
481 door->voffset = y1;
482
483 //open door on startup (without sound) if specified
484 if (open_state == true)
485 {
486 Vector3 pos = GetPosition();
487 Open(pos, false, true);
488 }
489
490 return door;
491}
492
493void Door::AutoClose(int interval)
494{
495 //start or stop autoclose timer
496
497 if (interval <= 0)
498 timer->Stop();
499 else
500 timer->Start(interval * 1000, true);
501
502 timer_interval = interval;
503}
504
506{
507 //when auto-close timer triggers, close door
508
509 //close door
510 door->Close();
511}
512
513}
bool ToggleLock(const Vector3 &position, bool force=false)
Definition lock.cpp:106
void SetDirection(bool direction)
Definition lock.cpp:86
bool IsLocked(const Vector3 &position)
Definition lock.cpp:178
void RemoveDoor(Door *door)
Definition manager.cpp:760
Door * door
Definition door.cpp:45
virtual void Notify()
Definition door.cpp:505
Timer(const std::string &name, Door *parent)
Definition door.cpp:46
bool OpenDoor
Definition door.h:40
void Report(const std::string &message)
Definition door.cpp:272
bool GetPreviousOpen()
Definition door.cpp:289
bool door_changed
Definition door.h:73
bool running
Definition door.h:75
~Door()
Definition door.cpp:85
bool OpenState
Definition door.h:38
bool DoorDirection
Definition door.h:37
void MoveDoor()
Definition door.cpp:208
DoorWrapper * FinishDoor(bool open_state)
Definition door.cpp:414
void Close(bool playsound=true)
Definition door.cpp:165
DoorWrapper * door
Definition door.h:66
bool GetDoorChanged()
Definition door.cpp:284
DoorWrapper * CreateDoor(bool open_state, const std::string &texture, const std::string &side_texture, Real thickness, const std::string &face_direction, const std::string &open_direction, Real open_speed, Real close_speed, Real CenterX, Real CenterZ, Real width, Real height, Real voffset, Real tw, Real th, Real side_tw, Real side_th)
Definition door.cpp:294
DynamicMesh * wrapper
Definition door.h:67
bool ReportError(const std::string &message)
Definition door.cpp:278
bool Open(Vector3 &position, bool playsound=true, bool force=false)
Definition door.cpp:131
void AutoClose(int interval)
Definition door.cpp:493
bool previous_open
Definition door.h:74
Timer * timer
Definition door.h:79
std::string CloseSound
Definition door.h:42
DoorWrapper * AddDoorComponent(const std::string &name, const std::string &texture, const std::string &sidetexture, Real thickness, const std::string &face_direction, const std::string &open_direction, bool OpenClockwise, Real OpenSpeed, Real CloseSpeed, Real x1, Real z1, Real x2, Real z2, Real height, Real voffset, Real tw, Real th, Real side_tw, Real side_th)
Definition door.cpp:357
Door(Object *parent, DynamicMesh *wrapper, const std::string &name, const std::string &open_sound, const std::string &close_sound, bool rotate)
Definition door.cpp:53
bool IsMoving
Definition door.h:39
void ClickDoor(Vector3 &position)
Definition door.cpp:239
void OnClick(Vector3 &position, bool shift, bool ctrl, bool alt, bool right)
Definition door.cpp:260
void Loop()
Definition door.cpp:198
bool IsOpen()
Definition door.cpp:184
std::string OpenSound
Definition door.h:41
int timer_interval
Definition door.h:80
Sound * sound
Definition door.h:70
bool is_enabled
Definition door.h:72
void Enabled(bool value)
Definition door.cpp:189
Wall * CreateWallObject(const std::string &name)
Definition mesh.cpp:208
const std::string & GetName()
Definition object.cpp:53
virtual bool ReportError(const std::string &message)
Definition object.cpp:84
Object * GetParent()
Definition object.cpp:42
virtual void Report(const std::string &message)
Definition object.cpp:78
bool parent_deleting
Definition object.h:64
virtual void Move(const Vector3 &vector, Real speed=1.0)
Definition object.cpp:253
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
void EnableLoop(bool value)
Definition object.cpp:521
const std::string & GetType()
Definition object.cpp:177
Real GetConfigFloat(const std::string &key, Real default_value)
Definition sbs.cpp:3249
DoorManager * GetDoorManager()
Definition sbs.cpp:4553
bool AddWallMain(Wall *wallobject, const std::string &name, const std::string &texture, Real thickness, Real x1, Real z1, Real x2, Real z2, Real height_in1, Real height_in2, Real altitude1, Real altitude2, Real tw, Real th, bool autosize)
Definition sbs.cpp:690
void ResetWalls(bool ToDefaults=false)
Definition sbs.cpp:1854
bool FastDelete
Definition sbs.h:188
TextureManager * GetTextureManager()
Definition sbs.cpp:4558
Real ToLocal(Real remote_value)
Definition sbs.cpp:2367
void DrawWalls(bool MainN, bool MainP, bool SideN, bool SideP, bool Top, bool Bottom)
Definition sbs.cpp:1833
bool Load(const std::string &filename, bool force=false)
Definition sound.cpp:386
bool Play(bool reset=true)
Definition sound.cpp:321
void SetTextureFlip(int mainneg, int mainpos, int sideneg, int sidepos, int top, int bottom)
Definition texture.cpp:1569
void ResetTextureMapping(bool todefaults=false)
Definition texture.cpp:1444
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
Ogre::Vector2 Vector2
Definition globals.h:59
#define SBS_PROFILE(name)
Definition profiler.h:131
MeshObject * mesh
Definition doorsystem.h:41
void MoveDoors(bool open, bool manual=false)
void Enabled(bool value)
std::vector< DoorComponent * > doors
Definition doorsystem.h:86
DoorComponent * CreateDoor(const std::string &doorname, const std::string &Direction, bool OpenClockwise, Real OpenSpeed, Real CloseSpeed, DynamicMesh *dynmesh)