OSDN Git Service

Properly initialize step objects
[skyscrapersim/skyscraper.git] / src / sbs / escalator.cpp
1 /* $Id$ */
2
3 /*
4         Scalable Building Simulator - Escalator Object
5         The Skyscraper Project - Version 1.11 Alpha
6         Copyright (C)2004-2016 Ryan Thoryk
7         http://www.skyscrapersim.com
8         http://sourceforge.net/projects/skyscraper
9         Contact - ryan@skyscrapersim.com
10
11         This program is free software; you can redistribute it and/or
12         modify it under the terms of the GNU General Public License
13         as published by the Free Software Foundation; either version 2
14         of the License, or (at your option) any later version.
15
16         This program is distributed in the hope that it will be useful,
17         but WITHOUT ANY WARRANTY; without even the implied warranty of
18         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19         GNU General Public License for more details.
20
21         You should have received a copy of the GNU General Public License
22         along with this program; if not, write to the Free Software
23         Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24 */
25
26 #include "globals.h"
27 #include "sbs.h"
28 #include "mesh.h"
29 #include "floor.h"
30 #include "sound.h"
31 #include "texture.h"
32 #include "profiler.h"
33 #include "dynamicmesh.h"
34 #include "camera.h"
35 #include "escalator.h"
36
37 namespace SBS {
38
39 Escalator::Escalator(Object *parent, const std::string &name, int run, float speed, const std::string &sound_file, const std::string &texture, const std::string &direction, float CenterX, float CenterZ, float width, float risersize, float treadsize, int num_steps, float voffset, float tw, float th) : Object(parent)
40 {
41         //create a new escalator object
42         //run is either 1 for forward motion, -1 for reverse motion, 0 for stop
43         //num_stairs is subtracted by 1 since it includes the floor platform above, but not below
44         //direction is where the stair base is - front, back, left, or right.
45
46         //set up SBS object
47         SetValues("Escalator", name, false);
48
49         is_enabled = true;
50         Run = run;
51         Speed = speed;
52         sbs->IncrementEscalatorCount();
53         start = 0;
54         end = 0;
55
56         StepContainer = new DynamicMesh(this, GetSceneNode(), name + " Step Container", 0, true);
57
58         //move object
59         Move(CenterX, voffset, CenterZ);
60
61         //create step meshes
62         for (int i = 0; i < num_steps; i++)
63         {
64                 Step *mesh = new Step(this, "Step " + ToString(i + 1), StepContainer);
65                 Steps.push_back(mesh);
66         }
67
68         //create sound object
69         sound = new Sound(this, name, true);
70         sound->Load(sound_file);
71
72         //create steps
73         CreateSteps(texture, direction, width, risersize, treadsize, tw, th);
74 }
75
76 Escalator::~Escalator()
77 {
78         if (sound)
79         {
80                 sound->parent_deleting = true;
81                 delete sound;
82         }
83         sound = 0;
84
85         //remove step meshes
86         for (size_t i = 0; i < Steps.size(); i++)
87         {
88                 if (Steps[i])
89                 {
90                         Steps[i]->parent_deleting = true;
91                         delete Steps[i];
92                 }
93                 Steps[i] = 0;
94         }
95
96         if (StepContainer)
97                 delete StepContainer;
98         StepContainer = 0;
99
100         //unregister from parent
101         if (sbs->FastDelete == false)
102         {
103                 sbs->DecrementEscalatorCount();
104
105                 //unregister from parent
106                 if (parent_deleting == false)
107                 {
108                         std::string type = GetParent()->GetType();
109
110                         if (type == "Floor")
111                                 static_cast<Floor*>(GetParent())->RemoveEscalator(this);
112                 }
113         }
114 }
115
116 void Escalator::Enabled(bool value)
117 {
118         //enable or disable escalator
119
120         if (is_enabled == value)
121                 return;
122
123         EnableLoop(value);
124
125         for (size_t i = 0; i < Steps.size(); i++)
126                 Steps[i]->Enabled(value);
127
128         if (value == false && sound->IsPlaying() == true)
129                 sound->Stop();
130
131         is_enabled = value;
132 }
133
134 void Escalator::Report(const std::string &message)
135 {
136         //general reporting function
137         sbs->Report("Escalator " + GetName() + ": " + message);
138 }
139
140 bool Escalator::ReportError(const std::string &message)
141 {
142         //general reporting function
143         return sbs->ReportError("Escalator " + GetName() + ": " + message);
144 }
145
146 void Escalator::Loop()
147 {
148         //run loop
149
150         SBS_PROFILE("Escalator::Loop");
151
152         if (!IsEnabled() || Run == 0)
153         {
154                 if (sound->IsPlaying() == true)
155                         sound->Stop();
156                 return;
157         }
158
159         if (sound->IsPlaying() == false)
160         {
161                 sound->SetLoopState(true);
162                 sound->Play();
163         }
164
165         MoveSteps();
166 }
167
168 void Escalator::CreateSteps(const std::string &texture, const std::string &direction, float width, float risersize, float treadsize, float tw, float th)
169 {
170         //create steps
171         std::string Name = GetName();
172         TrimString(Name);
173         Direction = direction;
174         this->treadsize = treadsize;
175         SetCase(Direction, false);
176         int num_steps = (int)Steps.size();
177
178         sbs->GetTextureManager()->ResetTextureMapping(true);
179         if (Direction == "right" || Direction == "back")
180                 sbs->SetWallOrientation("right");
181         if (Direction == "left" || Direction == "front")
182                 sbs->SetWallOrientation("left");
183
184         for (int i = 1; i <= num_steps; i++)
185         {
186                 float pos = 0;
187                 std::string base = Name + " " + ToString(i);
188
189                 //create wall object
190                 Wall *wall = Steps[i - 1]->CreateWallObject(base);
191
192                 float thickness = treadsize;
193
194                 if (Direction == "right")
195                 {
196                         pos = ((treadsize * (num_steps - 1)) / 2) - (treadsize * i);
197                         sbs->DrawWalls(true, true, true, true, false, true);
198                         sbs->AddWallMain(wall, base + "-riser", texture, thickness, treadsize, -(width / 2), treadsize, width / 2, risersize, risersize, 0, 0, tw, th, true);
199
200                         sbs->DrawWalls(false, true, false, false, false, false);
201                         sbs->AddFloorMain(wall, base + "tread", texture, 0, 0, -(width / 2), treadsize, width / 2, risersize, risersize, false, false, tw, th, true);
202
203                         if (i < 3)
204                                 Steps[i - 1]->Move(Ogre::Vector3(pos, -risersize, 0));
205                         else if (i < num_steps)
206                                 Steps[i - 1]->Move(Ogre::Vector3(pos, risersize * (i - 4), 0));
207                         else if (i == num_steps)
208                                 Steps[i - 1]->Move(Ogre::Vector3(pos, risersize * (i - 5), 0));
209
210                         if (i == 1)
211                                 start = Steps[i - 1]->GetPosition();
212                         if (i == num_steps)
213                                 end = Steps[i - 1]->GetPosition();
214                 }
215                 if (Direction == "left")
216                 {
217                         pos = -((treadsize * (num_steps - 1)) / 2) + (treadsize * i);
218                         sbs->DrawWalls(true, true, true, true, false, true);
219                         sbs->AddWallMain(wall, base + "-riser", texture, thickness, -treadsize, width / 2, -treadsize, -(width / 2), risersize, risersize, 0, 0, tw, th, true);
220
221                         sbs->DrawWalls(false, true, false, false, false, false);
222                         sbs->AddFloorMain(wall, base + "-tread", texture, 0, -treadsize, -(width / 2), 0, width / 2, risersize, risersize, false, false, tw, th, true);
223
224                         if (i < 3)
225                                 Steps[i - 1]->Move(Ogre::Vector3(pos, -risersize, 0));
226                         else if (i < num_steps)
227                                 Steps[i - 1]->Move(Ogre::Vector3(pos, risersize * (i - 4), 0));
228                         else if (i == num_steps)
229                                 Steps[i - 1]->Move(Ogre::Vector3(pos, risersize * (i - 5), 0));
230
231                         if (i == 1)
232                                 start = Steps[i - 1]->GetPosition();
233                         if (i == num_steps)
234                                 end = Steps[i - 1]->GetPosition();
235                 }
236                 if (Direction == "back")
237                 {
238                         pos = ((treadsize * (num_steps - 1)) / 2) - (treadsize * i);
239                         sbs->DrawWalls(true, true, true, true, false, true);
240                         sbs->AddWallMain(wall, base + "-riser", texture, thickness, width / 2, treadsize, -(width / 2), treadsize, risersize, risersize, 0, 0, tw, th, true);
241
242                         sbs->DrawWalls(false, true, false, false, false, false);
243                         sbs->AddFloorMain(wall, base + "-tread", texture, 0, -(width / 2), 0, width / 2, treadsize, risersize, risersize, false, false, tw, th, true);
244
245                         if (i < 3)
246                                 Steps[i - 1]->Move(Ogre::Vector3(0, -risersize, pos));
247                         else if (i < num_steps)
248                                 Steps[i - 1]->Move(Ogre::Vector3(0, risersize * (i - 4), pos));
249                         else if (i == num_steps)
250                                 Steps[i - 1]->Move(Ogre::Vector3(0, risersize * (i - 5), pos));
251
252                         if (i == 1)
253                                 start = Steps[i - 1]->GetPosition();
254                         if (i == num_steps)
255                                 end = Steps[i - 1]->GetPosition();
256                 }
257                 if (Direction == "front")
258                 {
259                         pos = -((treadsize * (num_steps - 1)) / 2) + (treadsize * i);
260                         sbs->DrawWalls(true, true, true, true, false, true);
261                         sbs->AddWallMain(wall, base + "riser", texture, thickness, -(width / 2), -treadsize, width / 2, -treadsize, risersize, risersize, 0, 0, tw, th, true);
262
263                         sbs->DrawWalls(false, true, false, false, false, false);
264                         sbs->AddFloorMain(wall, base + "tread", texture, 0, -(width / 2), -treadsize, width / 2, 0, risersize, risersize, false, false, tw, th, true);
265
266                         if (i < 3)
267                                 Steps[i - 1]->Move(Ogre::Vector3(0, -risersize, pos));
268                         else if (i < num_steps)
269                                 Steps[i - 1]->Move(Ogre::Vector3(0, risersize * (i - 4), pos));
270                         else if (i == num_steps)
271                                 Steps[i - 1]->Move(Ogre::Vector3(0, risersize * (i - 5), pos));
272
273                         if (i == 1)
274                                 start = Steps[i - 1]->GetPosition();
275                         if (i == num_steps)
276                                 end = Steps[i - 1]->GetPosition();
277                 }
278         }
279         sbs->ResetWalls(true);
280         sbs->GetTextureManager()->ResetTextureMapping();
281 }
282
283 void Escalator::MoveSteps()
284 {
285         for (size_t i = 0; i < Steps.size(); i++)
286         {
287                 if (Run == 1)
288                 {
289                         if (Direction == "right")
290                         {
291                                 float pos = Steps[i]->GetPosition().x;
292                                 if (pos < end.x - treadsize)
293                                         Steps[i]->SetPosition(start);
294                                 else if (pos >= start.x - (treadsize * 2) || pos <= end.x + treadsize)
295                                         Steps[i]->Move(Ogre::Vector3(-Run, 0, 0), Speed);
296                                 else if (pos > end.x + treadsize)
297                                         Steps[i]->Move(Ogre::Vector3(-Run, Run, 0), Speed);
298                         }
299                         if (Direction == "left")
300                         {
301                                 float pos = Steps[i]->GetPosition().x;
302                                 if (pos > end.x + treadsize)
303                                         Steps[i]->SetPosition(start);
304                                 else if (pos <= start.x + (treadsize * 2) || pos >= end.x - treadsize)
305                                         Steps[i]->Move(Ogre::Vector3(Run, 0, 0), Speed);
306                                 else if (pos < end.x - treadsize)
307                                         Steps[i]->Move(Ogre::Vector3(Run, Run, 0), Speed);
308                         }
309                         if (Direction == "back")
310                         {
311                                 float pos = Steps[i]->GetPosition().z;
312                                 if (pos < end.z - treadsize)
313                                         Steps[i]->SetPosition(start);
314                                 else if (pos >= start.z - (treadsize * 2) || pos <= end.z + treadsize)
315                                         Steps[i]->Move(Ogre::Vector3(0, 0, -Run), Speed);
316                                 else if (pos > end.z + treadsize)
317                                         Steps[i]->Move(Ogre::Vector3(0, Run, -Run), Speed);
318                         }
319                         if (Direction == "front")
320                         {
321                                 float pos = Steps[i]->GetPosition().z;
322                                 if (pos > end.z + treadsize)
323                                         Steps[i]->SetPosition(start);
324                                 else if (pos <= start.z + (treadsize * 2) || pos >= end.z - treadsize)
325                                         Steps[i]->Move(Ogre::Vector3(0, 0, Run), Speed);
326                                 else if (pos < end.z - treadsize)
327                                         Steps[i]->Move(Ogre::Vector3(0, Run, Run), Speed);
328                         }
329                 }
330                 else if (Run == -1)
331                 {
332                         if (Direction == "right")
333                         {
334                                 float pos = Steps[i]->GetPosition().x;
335                                 if (pos > start.x)
336                                         Steps[i]->SetPosition(end);
337                                 else if (pos <= end.x + treadsize || pos >= start.x - (treadsize * 2))
338                                         Steps[i]->Move(Ogre::Vector3(-Run, 0, 0), Speed);
339                                 else if (pos < start.x - treadsize)
340                                         Steps[i]->Move(Ogre::Vector3(-Run, Run, 0), Speed);
341                         }
342                         if (Direction == "left")
343                         {
344                                 float pos = Steps[i]->GetPosition().x;
345                                 if (pos < start.x)
346                                         Steps[i]->SetPosition(end);
347                                 else if (pos >= end.x - treadsize || pos <= start.x + (treadsize * 2))
348                                         Steps[i]->Move(Ogre::Vector3(Run, 0, 0), Speed);
349                                 else if (pos > start.x + treadsize)
350                                         Steps[i]->Move(Ogre::Vector3(Run, Run, 0), Speed);
351                         }
352                         if (Direction == "back")
353                         {
354                                 float pos = Steps[i]->GetPosition().z;
355                                 if (pos > start.z)
356                                         Steps[i]->SetPosition(end);
357                                 else if (pos <= end.z + treadsize || pos >= start.z - (treadsize * 2))
358                                         Steps[i]->Move(Ogre::Vector3(0, 0, -Run), Speed);
359                                 else if (pos < start.z - treadsize)
360                                         Steps[i]->Move(Ogre::Vector3(0, Run, -Run), Speed);
361                         }
362                         if (Direction == "front")
363                         {
364                                 float pos = Steps[i]->GetPosition().z;
365                                 if (pos < start.z)
366                                         Steps[i]->SetPosition(end);
367                                 else if (pos >= end.z - treadsize || pos <= start.z + (treadsize * 2))
368                                         Steps[i]->Move(Ogre::Vector3(0, 0, Run), Speed);
369                                 else if (pos > start.z + treadsize)
370                                         Steps[i]->Move(Ogre::Vector3(0, Run, Run), Speed);
371                         }
372                 }
373         }
374 }
375
376 void Escalator::OnClick(Ogre::Vector3 &position, bool shift, bool ctrl, bool alt, bool right)
377 {
378         //cycle run stages if shift-click is performed
379
380         if (shift == true)
381         {
382                 if (Run == 1)
383                 {
384                         Run = 0;
385                         for (size_t i = 0; i < Steps.size(); i++)
386                         {
387                                 Steps[i]->vector = 0;
388                                 Steps[i]->speed = 0;
389                         }
390                 }
391                 else if (Run == 0)
392                         Run = -1;
393                 else if (Run == -1)
394                         Run = 1;
395         }
396 }
397
398 Escalator::Step::Step(Object* parent, const std::string &name, DynamicMesh* wrapper) : MeshObject(parent, name, wrapper)
399 {
400         vector = Ogre::Vector3::ZERO;
401         speed = 0;
402 }
403
404 void Escalator::Step::Move(const Ogre::Vector3 &vector, float speed)
405 {
406         MeshObject::Move(vector, speed);
407         this->vector = vector;
408         this->speed = speed;
409 }
410
411 void Escalator::Step::OnHit()
412 {
413         sbs->camera->MovePosition(vector * 1.675, speed);
414 }
415
416 }