OSDN Git Service

-use separate meshes for escalator steps
[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-2017 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 "camera.h"
29 #include "mesh.h"
30 #include "floor.h"
31 #include "sound.h"
32 #include "texture.h"
33 #include "profiler.h"
34 #include "dynamicmesh.h"
35 #include "step.h"
36 #include "escalator.h"
37
38 namespace SBS {
39
40 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)
41 {
42         //create a new escalator object
43         //run is either 1 for forward motion, -1 for reverse motion, 0 for stop
44         //direction is where the step base is - front, back, left, or right.
45
46         std::string Name;
47
48         //set up SBS object
49         SetValues("Escalator", "", false);
50
51         Floor *floor = dynamic_cast<Floor*>(parent);
52         if (floor)
53                 Name = "Floor" + ToString(floor->Number) + ":"+ name;
54         else
55                 Name = name;
56         SetName(Name);
57
58         is_enabled = true;
59         SetRun(run);
60         Speed = speed;
61         sbs->IncrementEscalatorCount();
62         start = 0;
63         end = 0;
64         buffer_zone_steps = 2;
65
66         //move object
67         Move(CenterX, voffset, CenterZ);
68
69         //create step meshes
70         for (int i = 0; i < num_steps; i++)
71         {
72                 Step *mesh = new Step(this, "Step " + ToString(i + 1), 0, 100);
73                 Steps.push_back(mesh);
74         }
75
76         //create sound object
77         sound = new Sound(this, name, true);
78         sound->Load(sound_file);
79         sound->SetPosition(CenterX, voffset, CenterZ);
80
81         //create steps
82         CreateSteps(texture, direction, width, risersize, treadsize, tw, th);
83 }
84
85 Escalator::~Escalator()
86 {
87         if (sound)
88         {
89                 sound->parent_deleting = true;
90                 delete sound;
91         }
92         sound = 0;
93
94         //remove step meshes
95         for (size_t i = 0; i < Steps.size(); i++)
96         {
97                 if (Steps[i])
98                 {
99                         Steps[i]->parent_deleting = true;
100                         delete Steps[i];
101                 }
102                 Steps[i] = 0;
103         }
104
105         //unregister from parent
106         if (sbs->FastDelete == false)
107         {
108                 sbs->DecrementEscalatorCount();
109
110                 //unregister from parent
111                 if (parent_deleting == false)
112                 {
113                         std::string type = GetParent()->GetType();
114
115                         if (type == "Floor")
116                                 static_cast<Floor*>(GetParent())->RemoveEscalator(this);
117                 }
118         }
119 }
120
121 void Escalator::Enabled(bool value)
122 {
123         //enable or disable escalator
124
125         if (is_enabled == value)
126                 return;
127
128         EnableLoop(value);
129
130         for (size_t i = 0; i < Steps.size(); i++)
131                 Steps[i]->Enabled(value);
132
133         if (value == false && sound->IsPlaying() == true)
134                 sound->Stop();
135
136         is_enabled = value;
137 }
138
139 void Escalator::SetRun(int value)
140 {
141         if (value == 0)
142         {
143                 for (size_t i = 0; i < Steps.size(); i++)
144                 {
145                         Steps[i]->vector = Ogre::Vector3::ZERO;
146                         Steps[i]->speed = 0;
147                 }
148         }
149
150         Run = value;
151 }
152
153 void Escalator::Report(const std::string &message)
154 {
155         //general reporting function
156         Object::Report("Escalator " + GetName() + ": " + message);
157 }
158
159 bool Escalator::ReportError(const std::string &message)
160 {
161         //general reporting function
162         return Object::ReportError("Escalator " + GetName() + ": " + message);
163 }
164
165 void Escalator::Loop()
166 {
167         //run loop
168
169         SBS_PROFILE("Escalator::Loop");
170
171         if (!IsEnabled() || Run == 0)
172         {
173                 if (sound->IsPlaying() == true)
174                         sound->Stop();
175                 return;
176         }
177
178         if (sound->IsPlaying() == false)
179         {
180                 sound->SetLoopState(true);
181                 sound->Play();
182         }
183
184         MoveSteps();
185 }
186
187 void Escalator::CreateSteps(const std::string &texture, const std::string &direction, float width, float risersize, float treadsize, float tw, float th)
188 {
189         //create steps
190         std::string Name = GetName();
191         TrimString(Name);
192         Direction = direction;
193         this->treadsize = treadsize;
194         this->risersize = risersize;
195         SetCase(Direction, false);
196         int num_steps = (int)Steps.size();
197
198         sbs->GetTextureManager()->ResetTextureMapping(true);
199         if (Direction == "right" || Direction == "back")
200                 sbs->SetWallOrientation("right");
201         if (Direction == "left" || Direction == "front")
202                 sbs->SetWallOrientation("left");
203
204         for (int i = 1; i <= num_steps; i++)
205         {
206                 float pos = 0;
207                 std::string base = Name + ":" + ToString(i);
208
209                 //create wall object
210                 Wall *wall = Steps[i - 1]->CreateWallObject(base);
211
212                 float thickness = treadsize;
213
214                 if (Direction == "right")
215                 {
216                         pos = ((treadsize * num_steps + 1) / 2) - (treadsize * i);
217                         sbs->DrawWalls(true, true, true, true, false, true);
218                         sbs->AddWallMain(wall, base + "-riser", texture, thickness, treadsize, -(width / 2), treadsize, width / 2, risersize, risersize, 0, 0, tw, th, true);
219
220                         sbs->DrawWalls(false, true, false, false, false, false);
221                         sbs->AddFloorMain(wall, base + "-tread", texture, 0, 0, -(width / 2), treadsize, width / 2, risersize, risersize, false, false, tw, th, true);
222
223                         if (i < (buffer_zone_steps + 1))
224                                 Steps[i - 1]->Move(Ogre::Vector3(pos, -risersize, 0));
225                         else if (i > num_steps - buffer_zone_steps)
226                                 Steps[i - 1]->Move(Ogre::Vector3(pos, risersize * (i - (((buffer_zone_steps * 2) + 1) - (num_steps - i))), 0));
227                         else
228                                 Steps[i - 1]->Move(Ogre::Vector3(pos, risersize * (i - (buffer_zone_steps * 2)), 0));
229                         Steps[i - 1]->vector = Ogre::Vector3::ZERO;
230                         Steps[1 - 1]->speed = 0;
231
232                         if (i == 1)
233                                 start = Steps[i - 1]->GetPosition();
234                         if (i == num_steps)
235                                 end = Steps[i - 1]->GetPosition();
236                         Steps[i - 1]->start = Steps[i - 1]->GetPosition();
237                 }
238                 if (Direction == "left")
239                 {
240                         pos = -((treadsize * num_steps + 1) / 2) + (treadsize * i);
241                         sbs->DrawWalls(true, true, true, true, false, true);
242                         sbs->AddWallMain(wall, base + "-riser", texture, thickness, -treadsize, width / 2, -treadsize, -(width / 2), risersize, risersize, 0, 0, tw, th, true);
243
244                         sbs->DrawWalls(false, true, false, false, false, false);
245                         sbs->AddFloorMain(wall, base + "-tread", texture, 0, -treadsize, -(width / 2), 0, width / 2, risersize, risersize, false, false, tw, th, true);
246
247                         if (i < (buffer_zone_steps + 1))
248                                 Steps[i - 1]->Move(Ogre::Vector3(pos, -risersize, 0));
249                         else if (i > num_steps - buffer_zone_steps)
250                                 Steps[i - 1]->Move(Ogre::Vector3(pos, risersize * (i - (((buffer_zone_steps * 2) + 1) - (num_steps - i))), 0));
251                         else
252                                 Steps[i - 1]->Move(Ogre::Vector3(pos, risersize * (i - (buffer_zone_steps * 2)), 0));
253                         Steps[i - 1]->vector = Ogre::Vector3::ZERO;
254                         Steps[1 - 1]->speed = 0;
255
256                         if (i == 1)
257                                 start = Steps[i - 1]->GetPosition();
258                         if (i == num_steps)
259                                 end = Steps[i - 1]->GetPosition();
260                         Steps[i - 1]->start = Steps[i - 1]->GetPosition();
261                 }
262                 if (Direction == "back")
263                 {
264                         pos = ((treadsize * num_steps + 1) / 2) - (treadsize * i);
265                         sbs->DrawWalls(true, true, true, true, false, true);
266                         sbs->AddWallMain(wall, base + "-riser", texture, thickness, width / 2, treadsize, -(width / 2), treadsize, risersize, risersize, 0, 0, tw, th, true);
267
268                         sbs->DrawWalls(false, true, false, false, false, false);
269                         sbs->AddFloorMain(wall, base + "-tread", texture, 0, -(width / 2), 0, width / 2, treadsize, risersize, risersize, false, false, tw, th, true);
270
271                         if (i < (buffer_zone_steps + 1))
272                                 Steps[i - 1]->Move(Ogre::Vector3(0, -risersize, pos));
273                         else if (i > num_steps - buffer_zone_steps)
274                                 Steps[i - 1]->Move(Ogre::Vector3(0, risersize * (i - (((buffer_zone_steps * 2) + 1) - (num_steps - i))), pos));
275                         else
276                                 Steps[i - 1]->Move(Ogre::Vector3(0, risersize * (i - (buffer_zone_steps * 2)), pos));
277                         Steps[i - 1]->vector = Ogre::Vector3::ZERO;
278                         Steps[1 - 1]->speed = 0;
279
280                         if (i == 1)
281                                 start = Steps[i - 1]->GetPosition();
282                         if (i == num_steps)
283                                 end = Steps[i - 1]->GetPosition();
284                         Steps[i - 1]->start = Steps[i - 1]->GetPosition();
285                 }
286                 if (Direction == "front")
287                 {
288                         pos = -((treadsize * num_steps + 1) / 2) + (treadsize * i);
289                         sbs->DrawWalls(true, true, true, true, false, true);
290                         sbs->AddWallMain(wall, base + "-riser", texture, thickness, -(width / 2), -treadsize, width / 2, -treadsize, risersize, risersize, 0, 0, tw, th, true);
291
292                         sbs->DrawWalls(false, true, false, false, false, false);
293                         sbs->AddFloorMain(wall, base + "-tread", texture, 0, -(width / 2), -treadsize, width / 2, 0, risersize, risersize, false, false, tw, th, true);
294
295                         if (i < (buffer_zone_steps + 1))
296                                 Steps[i - 1]->Move(Ogre::Vector3(0, -risersize, pos));
297                         else if (i > num_steps - buffer_zone_steps)
298                                 Steps[i - 1]->Move(Ogre::Vector3(0, risersize * (i - (((buffer_zone_steps * 2) + 1) - (num_steps - i))), pos));
299                         else
300                                 Steps[i - 1]->Move(Ogre::Vector3(0, risersize * (i - (buffer_zone_steps * 2)), pos));
301                         Steps[i - 1]->vector = Ogre::Vector3::ZERO;
302                         Steps[1 - 1]->speed = 0;
303
304                         if (i == 1)
305                                 start = Steps[i - 1]->GetPosition();
306                         if (i == num_steps)
307                                 end = Steps[i - 1]->GetPosition();
308                         Steps[i - 1]->start = Steps[i - 1]->GetPosition();
309                 }
310         }
311         sbs->ResetWalls(true);
312         sbs->GetTextureManager()->ResetTextureMapping();
313 }
314
315 void Escalator::MoveSteps()
316 {
317         if (GetPosition().distance(sbs->camera->GetPosition()) > 100)
318                 return;
319
320         for (size_t i = 0; i < Steps.size(); i++)
321         {
322                 if (Run == 1)
323                 {
324                         if (Direction == "right")
325                         {
326                                 float pos = Steps[i]->GetPosition().x;
327                                 if (pos < end.x - treadsize)
328                                         Steps[i]->SetPosition(start);
329                                 else if (pos >= start.x - (treadsize * 2) || pos <= end.x + treadsize)
330                                         Steps[i]->Move(Ogre::Vector3(-Run, 0, 0), Speed * sbs->delta);
331                                 else if (pos > end.x + treadsize)
332                                         Steps[i]->Move(Ogre::Vector3(-Run, Run * (risersize / treadsize), 0), Speed * sbs->delta);
333                         }
334                         if (Direction == "left")
335                         {
336                                 float pos = Steps[i]->GetPosition().x;
337                                 if (pos > end.x + treadsize)
338                                         Steps[i]->SetPosition(start);
339                                 else if (pos <= start.x + (treadsize * 2) || pos >= end.x - treadsize)
340                                         Steps[i]->Move(Ogre::Vector3(Run, 0, 0), Speed * sbs->delta);
341                                 else if (pos < end.x - treadsize)
342                                         Steps[i]->Move(Ogre::Vector3(Run, Run * (risersize / treadsize), 0), Speed * sbs->delta);
343                         }
344                         if (Direction == "back")
345                         {
346                                 float pos = Steps[i]->GetPosition().z;
347                                 if (pos < end.z - treadsize)
348                                         Steps[i]->SetPosition(start);
349                                 else if (pos >= start.z - (treadsize * 2) || pos <= end.z + treadsize)
350                                         Steps[i]->Move(Ogre::Vector3(0, 0, -Run), Speed * sbs->delta);
351                                 else if (pos > end.z + treadsize)
352                                         Steps[i]->Move(Ogre::Vector3(0, Run * (risersize / treadsize), -Run), Speed * sbs->delta);
353                         }
354                         if (Direction == "front")
355                         {
356                                 float pos = Steps[i]->GetPosition().z;
357                                 if (pos > end.z + treadsize)
358                                         Steps[i]->SetPosition(start);
359                                 else if (pos <= start.z + (treadsize * 2) || pos >= end.z - treadsize)
360                                         Steps[i]->Move(Ogre::Vector3(0, 0, Run), Speed * sbs->delta);
361                                 else if (pos < end.z - treadsize)
362                                         Steps[i]->Move(Ogre::Vector3(0, Run * (risersize / treadsize), Run), Speed * sbs->delta);
363                         }
364                 }
365                 else if (Run == -1)
366                 {
367                         if (Direction == "right")
368                         {
369                                 float pos = Steps[i]->GetPosition().x;
370                                 if (pos > start.x)
371                                         Steps[i]->SetPosition(Ogre::Vector3(end.x - treadsize, end.y, end.z));
372                                 else if (pos <= end.x + treadsize || pos >= start.x - (treadsize * 2))
373                                         Steps[i]->Move(Ogre::Vector3(-Run, 0, 0), Speed * sbs->delta);
374                                 else if (pos < start.x - treadsize)
375                                         Steps[i]->Move(Ogre::Vector3(-Run, Run * (risersize / treadsize), 0), Speed * sbs->delta);
376                         }
377                         if (Direction == "left")
378                         {
379                                 float pos = Steps[i]->GetPosition().x;
380                                 if (pos < start.x)
381                                         Steps[i]->SetPosition(Ogre::Vector3(end.x + treadsize, end.y, end.z));
382                                 else if (pos >= end.x - treadsize || pos <= start.x + (treadsize * 2))
383                                         Steps[i]->Move(Ogre::Vector3(Run, 0, 0), Speed * sbs->delta);
384                                 else if (pos > start.x + treadsize)
385                                         Steps[i]->Move(Ogre::Vector3(Run, Run * (risersize / treadsize), 0), Speed * sbs->delta);
386                         }
387                         if (Direction == "back")
388                         {
389                                 float pos = Steps[i]->GetPosition().z;
390                                 if (pos > start.z)
391                                         Steps[i]->SetPosition(Ogre::Vector3(end.x, end.y, end.z - treadsize));
392                                 else if (pos <= end.z + treadsize || pos >= start.z - (treadsize * 2))
393                                         Steps[i]->Move(Ogre::Vector3(0, 0, -Run), Speed * sbs->delta);
394                                 else if (pos < start.z - treadsize)
395                                         Steps[i]->Move(Ogre::Vector3(0, Run * (risersize / treadsize), -Run), Speed * sbs->delta);
396                         }
397                         if (Direction == "front")
398                         {
399                                 float pos = Steps[i]->GetPosition().z;
400                                 if (pos < start.z)
401                                         Steps[i]->SetPosition(Ogre::Vector3(end.x, end.y, end.z + treadsize));
402                                 else if (pos >= end.z - treadsize || pos <= start.z + (treadsize * 2))
403                                         Steps[i]->Move(Ogre::Vector3(0, 0, Run), Speed * sbs->delta);
404                                 else if (pos > start.z + treadsize)
405                                         Steps[i]->Move(Ogre::Vector3(0, Run * (risersize / treadsize), Run), Speed * sbs->delta);
406                         }
407                 }
408         }
409 }
410
411 void Escalator::OnClick(Ogre::Vector3 &position, bool shift, bool ctrl, bool alt, bool right)
412 {
413         //cycle run stages if shift-click is performed
414
415         if (shift == true)
416         {
417                 if (Run == 1)
418                 {
419                         Run = 0;
420                         for (size_t i = 0; i < Steps.size(); i++)
421                         {
422                                 Steps[i]->vector = 0;
423                                 Steps[i]->speed = 0;
424                         }
425                 }
426                 else if (Run == 0)
427                         Run = -1;
428                 else if (Run == -1)
429                         Run = 1;
430         }
431 }
432
433 void Escalator::ResetState()
434 {
435         //reset escalator state
436
437         Run = 0;
438         for (size_t i = 0; i < Steps.size(); i++)
439         {
440                 Steps[i]->SetPosition(Steps[i]->start);
441         }
442 }
443
444 }