Skyscraper 2.0
trigger.cpp
Go to the documentation of this file.
1/*
2 Scalable Building Simulator - Proximity Trigger 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 "OgreAxisAlignedBox.h"
25#include "globals.h"
26#include "sbs.h"
27#include "floor.h"
28#include "elevatorcar.h"
29#include "shaft.h"
30#include "stairs.h"
31#include "camera.h"
32#include "sound.h"
33#include "action.h"
34#include "profiler.h"
35#include "trigger.h"
36
37namespace SBS {
38
39Trigger::Trigger(Object *parent, const std::string &name, bool permanent, const std::string &sound_file, Vector3 area_min, Vector3 area_max, const std::vector<std::string> &action_names) : Object(parent)
40{
41 //create a proximity trigger at the specified location
42
43 //set up SBS object
44 SetValues("Trigger", name, permanent);
45
46 Actions = action_names;
47 is_enabled = true;
49 if (area_min.y == 0 && area_max.y == 0)
50 {
51 area_min.y = -999999.0;
52 area_max.y = 999999.0;
53 }
54 area_box = new Ogre::AxisAlignedBox(area_min, area_max);
55 is_inside = false;
56 sound = 0;
57
58 //create sound object
59 if (sound_file != "")
60 {
61 sound = new Sound(this, name, true);
62 sound->Load(sound_file);
63 }
64
65 EnableLoop(true);
66}
67
69{
70 if (sound)
71 {
72 sound->parent_deleting = true;
73 delete sound;
74 }
75 sound = 0;
76
77 if (area_box)
78 delete area_box;
79 area_box = 0;
80
81 //unregister from parent
82 if (sbs->FastDelete == false)
83 {
84 if (parent_deleting == false)
85 {
86 std::string type = GetParent()->GetType();
87
88 if (type == "ElevatorCar")
89 static_cast<ElevatorCar*>(GetParent())->RemoveTrigger(this);
90 else if (type == "Floor")
91 static_cast<Floor*>(GetParent())->RemoveTrigger(this);
92 else if (type == "Shaft Level")
93 static_cast<Shaft::Level*>(GetParent())->RemoveTrigger(this);
94 else if (type == "Stairwell Level")
95 static_cast<Stairwell::Level*>(GetParent())->RemoveTrigger(this);
96 else if (type == "SBS")
97 sbs->RemoveTrigger(this);
98 }
99 }
100}
101
102void Trigger::Enabled(bool value)
103{
104 //enable or disable trigger
105
106 if (is_enabled == value)
107 return;
108
109 is_enabled = value;
110 EnableLoop(value);
111}
112
114{
115 //set selection position without checking state
116
117 if (position < 1 || position > GetPositions())
118 return false;
119
120 current_position = position;
121
122 return true;
123}
124
126{
127 //set selection position
128
129 if (position == current_position)
130 return false;
131
132 return SetSelectPosition(position);
133}
134
135bool Trigger::NextSelectPosition(bool check_state)
136{
137 //change to the next available trigger selection position
138
139 int position = GetNextSelectPosition();
140
141 if (check_state == false)
142 return SetSelectPosition(position);
143 else
144 return ChangeSelectPosition(position);
145}
146
148{
149 //determine next selection position
150 int pos = current_position;
151 pos++;
152 if (pos > GetPositions())
153 pos = 1;
154 return pos;
155}
156
158{
159 //change to the next available trigger selection position
160
161 int position = GetPreviousSelectPosition();
162
163 if (check_state == false)
164 return SetSelectPosition(position);
165 else
166 return ChangeSelectPosition(position);
167}
168
170{
171 //determine previous selection position
172 int pos = current_position;
173 pos--;
174 if (pos < 1)
175 pos = GetPositions();
176 return pos;
177}
178
180{
181 //play associated sound
182
183 if (sound)
184 {
185 sound->SetLoopState(false);
186 sound->Play();
187 }
188}
189
191{
192 //return selection position
193 return current_position;
194}
195
196std::string Trigger::GetPositionAction(int position)
197{
198 //return action name associated with the specified selection position
199
200 if (Actions.empty() == true)
201 return "";
202
203 std::vector<Action*> actionlist;
204 actionlist = sbs->GetAction(Actions[position - 1]);
205
206 //return command of first action in list
207 if (actionlist.empty() == false)
208 {
209 if (actionlist[0])
210 return actionlist[0]->GetCommandName();
211 }
212 return "";
213}
214
216{
217 //return action name associated with current selection position
219}
220
222{
223 //return number of available positions, based on size of Actions array
224 return (int)Actions.size();
225}
226
227int Trigger::FindActionPosition(const std::string &name)
228{
229 //returns the position number that the specified action name is associated with.
230 //otherwise 0 if not found
231
232 for (int i = 1; i <= GetPositions(); i++)
233 {
234 if (GetPositionAction(i) == name)
235 return i;
236 }
237
238 return 0;
239}
240
242{
243 //perform trigger's action
244 //result is true if at least one action in the list succeeded
245
246 if (Actions.empty() == true)
247 return ReportError("No available actions for trigger '" + GetName() + "'");
248
249 std::vector<Action*> actionlist = sbs->GetAction(Actions[current_position - 1]);
250
251 bool result = false;
252
253 for (size_t i = 0; i < actionlist.size(); i++)
254 {
255 bool result2 = false;
256 bool hold = false; //not used
257
258 if (actionlist[i])
259 result2 = actionlist[i]->DoAction(this, hold);
260
261 if (result2 == true)
262 result = true;
263 }
264 return result;
265}
266
268{
269 //check for action; should be called in a loop by the parent object
270
271 if (is_enabled == false)
272 return;
273
274 SBS_PROFILE("Trigger::Loop");
275
276 Vector3 cam = sbs->camera->GetPosition();
277 bool changed = false;
278 if (IsInside(cam) == true)
279 {
280 if (is_inside == false)
281 changed = true;
282 is_inside = true;
283 }
284 else
285 {
286 if (is_inside == true)
287 changed = true;
288 is_inside = false;
289 }
290
291 if (changed == true)
292 {
293 if (sbs->Verbose == true)
294 {
295 if (is_inside == true)
296 Report("Inside trigger area '" + GetName() + "', parent '" + GetParent()->GetName() + "'");
297 else
298 Report("Outside trigger area '" + GetName() + "', parent '" + GetParent()->GetName() + "'");
299 }
300
301 if (is_inside == true)
302 OnEntry();
303 else
304 OnExit();
305
306 //get action name of next position state
307 std::string name = GetPositionAction(GetNextSelectPosition());
308
309 //exit without changing position if floor button is currently selected
310 if (name == "off" && IsNumeric(GetSelectPositionAction()) == true)
311 return;
312
313 //change to next control position
315
316 //perform selected action
317 bool result = DoAction();
318
319 //play sound if action succeeded
320 //or always if the name is numeric (elevator is on the same floor, and doors are reopened)
321 if (result == true || IsNumeric(name))
322 PlaySound();
323
324 //change back to original selection if result is false
325 if (result == false)
327 }
328}
329
331{
332 //return inside status
333
334 return is_inside;
335}
336
337bool Trigger::IsInside(const Vector3 &position)
338{
339 //return true if the given absolute position is inside the trigger area
340
341 return area_box->contains(position - GetPosition());
342}
343
344Ogre::AxisAlignedBox Trigger::GetBounds(bool relative)
345{
346 //get bounds information for this trigger
347
348 Vector3 min = area_box->getMinimum();
349 Vector3 max = area_box->getMaximum();
350
351 if (relative == false)
352 {
353 min += GetPosition();
354 max += GetPosition();
355 }
356
357 return Ogre::AxisAlignedBox(min, max);
358}
359
361{
362 //return true if the given rectangle is outside of the trigger area
363
364 v1 -= GetPosition();
365 v2 -= GetPosition();
366 Vector3 min = area_box->getMinimum();
367 Vector3 max = area_box->getMaximum();
368
369 if ((v1.x < min.x && v2.x < min.x) ||
370 (v1.y < min.y && v2.y < min.y) ||
371 (v1.z < min.z && v2.z < min.z) ||
372 (v1.x > max.x && v2.x > max.x) ||
373 (v1.y > max.y && v2.y > max.y) ||
374 (v1.z > max.z && v2.z > max.z))
375 return true;
376 return false;
377}
378
380{
381 return area_box->getMinimum();
382}
383
385{
386 return area_box->getMaximum();
387}
388
389}
Vector3 GetPosition(bool relative=false)
Definition camera.cpp:250
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 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
bool FastDelete
Definition sbs.h:188
Camera * camera
Definition sbs.h:160
void RemoveTrigger(Trigger *trigger)
Definition sbs.cpp:2896
std::vector< Action * > GetAction(std::string name)
Definition sbs.cpp:3431
bool Verbose
Definition sbs.h:186
bool Load(const std::string &filename, bool force=false)
Definition sound.cpp:386
bool Play(bool reset=true)
Definition sound.cpp:321
void SetLoopState(bool value)
Definition sound.cpp:204
Trigger(Object *parent, const std::string &name, bool permanent, const std::string &sound_file, Vector3 area_min, Vector3 area_max, const std::vector< std::string > &action_names)
Definition trigger.cpp:39
Ogre::AxisAlignedBox GetBounds(bool relative=false)
Definition trigger.cpp:344
Vector3 GetMax()
Definition trigger.cpp:384
std::string GetPositionAction(int position)
Definition trigger.cpp:196
bool ChangeSelectPosition(int position)
Definition trigger.cpp:125
std::string GetSelectPositionAction()
Definition trigger.cpp:215
bool is_enabled
Definition trigger.h:65
void PlaySound()
Definition trigger.cpp:179
Sound * sound
Definition trigger.h:68
int GetPositions()
Definition trigger.cpp:221
virtual void OnExit()
Definition trigger.h:59
int FindActionPosition(const std::string &name)
Definition trigger.cpp:227
void Enabled(bool value)
Definition trigger.cpp:102
int GetNextSelectPosition()
Definition trigger.cpp:147
bool DoAction()
Definition trigger.cpp:241
bool NextSelectPosition(bool check_state=true)
Definition trigger.cpp:135
bool IsOutside(Vector3 v1, Vector3 v2)
Definition trigger.cpp:360
bool is_inside
Definition trigger.h:64
std::vector< std::string > Actions
Definition trigger.h:66
int current_position
Definition trigger.h:63
int GetSelectPosition()
Definition trigger.cpp:190
bool IsInside()
Definition trigger.cpp:330
bool PreviousSelectPosition(bool check_state=true)
Definition trigger.cpp:157
int GetPreviousSelectPosition()
Definition trigger.cpp:169
Ogre::AxisAlignedBox * area_box
Definition trigger.h:62
bool SetSelectPosition(int position)
Definition trigger.cpp:113
void Loop()
Definition trigger.cpp:267
virtual void OnEntry()
Definition trigger.h:58
Vector3 GetMin()
Definition trigger.cpp:379
Ogre::Vector3 Vector3
Definition globals.h:58
bool IsNumeric(char character)
Definition globals.cpp:48
#define SBS_PROFILE(name)
Definition profiler.h:131