Skyscraper 2.0
enginecontext.cpp
Go to the documentation of this file.
1/*
2 Skyscraper 2.0 - Engine Context
3 Copyright (C)2003-2024 Ryan Thoryk
4 https://www.skyscrapersim.net
5 https://sourceforge.net/projects/skyscraper/
6 Contact - ryan@skyscrapersim.net
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21*/
22
23#ifdef USING_WX
24#include "wx/wx.h"
25#endif
26#ifndef DISABLE_SOUND
27#include <fmod.hpp>
28#endif
29#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
30#include <windows.h>
31#endif
32#include "globals.h"
33#include "sbs.h"
34#include "vm.h"
35#include "hal.h"
36#include "gui.h"
37#include "camera.h"
38#include "scriptproc.h"
39#include "enginecontext.h"
40
41#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
42#include "malloc.h"
43#endif
44
45#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
46#include <unistd.h>
47#endif
48
49using namespace SBS;
50
51namespace Skyscraper {
52
53EngineContext::EngineContext(EngineContext *parent, VM *vm, Ogre::SceneManager* mSceneManager, FMOD::System *fmodsystem, const Vector3 &position, Real rotation, const Vector3 &area_min, const Vector3 &area_max)
54{
55 this->fmodsystem = fmodsystem;
57}
58
59EngineContext::EngineContext(EngineContext *parent, VM *vm, Ogre::SceneManager* mSceneManager, const Vector3 &position, Real rotation, const Vector3 &area_min, const Vector3 &area_max)
60{
62}
63
65{
66 if (vm->IsValidEngine(parent) == true)
67 parent->RemoveChild(this);
68
69 if (children.empty() == false)
70 {
71 for (size_t i = 0; i < children.size(); i++)
72 {
73 children[i]->RemoveParent();
74 }
75 }
76
77 //unload simulator
78 UnloadSim();
79
80 if (reload_state)
81 delete reload_state;
82 reload_state = 0;
83}
84
85void EngineContext::Init(EngineContext *parent, VM *vm, Ogre::SceneManager* mSceneManager, const Vector3 &position, Real rotation, const Vector3 &area_min, const Vector3 &area_max)
86{
87 //initialize this engine context
88
89 this->vm = vm;
90 finish_time = 0;
91 shutdown = false;
92 loading = false;
93 running = false;
94 reloading = false;
95 Reload = false;
98 reload_state->collisions = false;
99 reload_state->gravity = false;
100 reload_state->freelook = false;
101 this->mSceneManager = mSceneManager;
102 this->position = position;
103 this->area_min = area_min;
104 this->area_max = area_max;
105 this->rotation = rotation;
106 this->parent = parent;
107 Simcore = 0;
108 processor = 0;
109 raised = false;
110 progress = 0;
111 inside = false;
112 Moved = false;
113 started = false;
114 prepared = false;
115 NewEngine = true;
116 Paused = false;
117
118 //register this engine, and get it's instance number
119 instance = vm->RegisterEngine(this);
120
121 Report("\nStarting instance " + ToString(instance) + "...");
122
123 //add instance number to reports
125
126 if (parent)
127 parent->AddChild(this);
128
129 StartSim();
130}
131
136
138{
139 //returns true if camera is active in this simulator
140
141 if (!Simcore)
142 return false;
143
144 return Simcore->camera->IsActive();
145}
146
148{
149 //request a shutdown
150
151 shutdown = true;
152}
153
155{
156 //run simulator
157
158 if (!Simcore)
159 return false;
160
161 //exit if paused
162 if (Paused == true)
163 return true;
164
165 //run script processor
166 if (processor)
167 {
168 bool in_main = InRunloop();
169 bool result = processor->Run();
170
171 if (loading == true)
172 {
173 prepared = false;
174
175 #ifdef USING_WX
176 if (vm->GetGUI()->ProgressCancelled() == true)
177 result = false;
178 #endif
179
180 if (result == false)
181 {
182 ReportError("Error processing building\n");
183 Shutdown();
184 #ifdef USING_WX
185 if (vm->GetEngineCount(true) == 1)
187 #endif
188 return false;
189 }
190 else if (processor->IsFinished == true)
191 {
192 //building has finished loading
194 }
195
196 if (Simcore->RenderOnStartup == false)
197 return false;
198 }
199 else if (processor->IsFinished == true && result == true)
200 {
201 if (InRunloop() == false && prepared == false)
202 {
203 Simcore->Prepare(false);
204 Simcore->DeleteColliders = false;
205 Simcore->Init(); //initialize any new objects
206 prepared = true;
207 }
208 else
209 {
210 loading = false;
211 }
212 }
213 }
214 else
215 return false;
216
217 //force window raise on startup, and report on missing files, if any
218 if (Simcore->GetCurrentTime() - finish_time > 0 && raised == false && loading == false)
219 {
220#ifdef USING_WX
221 vm->GetGUI()->RaiseWindow();
222#endif
223 raised = true;
224
226 }
227
228 //process internal clock
230 if (running == true)
232
233 //run SBS main loop
235
236 if (loading == false)
237 {
238 //run functions if user enters or leaves this engine
239 if (inside == false && IsInside() == true)
240 OnEnter();
241 if (inside == true && IsInside() == false)
242 OnExit();
243 }
244
245 return true;
246}
247
249{
250 //initialize simulator
251
252 if (!Simcore || !processor)
253 return false;
254
256
257 //load script processor object
258 processor->Reset();
259
260 return true;
261}
262
264{
265 //boot simulator
266 processor->Start();
267}
268
270{
271 //load default simulation
272
273 if (!Simcore || !processor)
274 return false;
275
276 loading = true;
277
278 //initialize simulator
279 InitSim();
280
281 Report("\nLoading default simulation...\n");
282 Simcore->BuildingFilename = "Default";
283
284 //load defaults
286
287 //override SBS startup render option, if specified
288 if (vm->GetRenderOnStartup() == true)
289 Simcore->RenderOnStartup = true;
290
291 return true;
292}
293
294bool EngineContext::Load(std::string filename)
295{
296 //load simulator and data file
297
298 if (!Simcore || !processor)
299 return false;
300
301 //exit if no building specified
302 if (filename == "")
303 return false;
304
305 loading = true;
306
307 //initialize simulator
308 InitSim();
309
310 //load building data file
311 Report("\nLoading building data from " + filename + "...\n");
312 Simcore->BuildingFilename = filename;
313
314 filename.insert(0, "buildings/");
315
316 //load building
317 if (!processor->LoadDataFile(filename))
318 {
319 loading = false;
320 return false;
321 }
322
323 //create progress dialog
324#ifdef USING_WX
325 vm->GetGUI()->CreateProgressDialog(filename);
326#endif
327
328 //override SBS startup render option, if specified
329 if (vm->GetRenderOnStartup() == true)
330 Simcore->RenderOnStartup = true;
331
332 return true;
333}
334
336{
337 //reload the current building
338
339 if (!Simcore)
340 return;
341
342 reloading = true;
343 Paused = false;
344
345 //store camera state information
346 std::string filename = Simcore->BuildingFilename;
348
349 //unload current simulator
350 UnloadSim();
351
352 //start a new simulator
353 StartSim();
354
355 //load building file
356 if (Load(filename) == false)
357 {
358 reloading = false;
359 Reload = false;
360 return;
361 }
362
363 Reload = false;
364}
365
367{
368 if (Simcore)
370 return "";
371}
372
374{
375 //create simulator and script interpreter objects
376
377 //exit if already started
378 if (started == true)
379 return;
380
381 //get offset of parent engine
382 Vector3 offset;
383 if (parent)
384 offset = parent->GetSystem()->GetPosition();
385 else
386 offset = Vector3::ZERO;
387
388 if (position != Vector3::ZERO)
389 Moved = true;
390
391 //Create simulator object
392 if (!Simcore)
394
395 //load script processor
396 if (!processor)
397 processor = new ScriptProcessor(this);
398
399 //if using DirectX11, turn off models in script processor due to shader crashes
401
402 //refresh console to fix banner message on Linux
403#ifdef USING_WX
405#endif
406
407 //override verbose mode if specified
408 if (vm->Verbose == true)
409 Simcore->Verbose = true;
410
411 //Pause for 2 seconds, if first instance
412 if (instance == 0)
413 {
414 vm->Pause = true; //briefly pause frontend to prevent debug panel calls to engine
415#ifdef USING_WX
416 wxYield(); //this allows the banner to be printed before the sleep() call
417#endif
418 vm->Pause = false;
419#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
420 Sleep(2000);
421#else
422 sleep(2);
423#endif
424 }
425}
426
428{
429 //unload simulator
430
431 if (Simcore)
432 {
433 delete Simcore;
434 Report("\nSBS instance " + ToString(instance) + " unloaded");
435 }
436 Simcore = 0;
437
438#ifndef DISABLE_SOUND
439 //reset fmod reverb
440 FMOD_REVERB_PROPERTIES prop = FMOD_PRESET_GENERIC;
441 fmodsystem->setReverbProperties(0, &prop);
442#endif
443
444 //unload script processor
445 if (processor)
446 delete processor;
447 processor = 0;
448
449 loading = false;
450 running = false;
451 raised = false;
452 Moved = false;
453 started = false;
454
455#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
456#ifdef __linux__
457 //release free memory to OS on Linux
458 malloc_trim(0);
459#else
460 //freebsd
461#endif
462
463#endif
464}
465
466bool EngineContext::Start(std::vector<Ogre::Camera*> &cameras)
467{
468 //start simulator
469
470 if (!Simcore)
471 return false;
472
473 //cut outside sim boundaries if specified
475
476 //if this has a parent engine, cut the parent for this new engine
477 if (vm->IsValidEngine(parent) == true)
478 parent->CutForEngine(this);
479
480 //if this has child engines, and has reloaded, cut for the child engines
481 if (children.empty() == false && reloading == true)
482 {
483 for (size_t i = 0; i < children.size(); i++)
484 {
486 }
487 }
488
489 //start simulator
490 if (!Simcore->Start(cameras))
491 return ReportError("Error starting simulator\n");
492
493 //set to saved position if reloading building
494 if (reloading == true)
495 {
496 reloading = false;
498 }
499
500 loading = false;
501 running = true;
502
503 return true;
504}
505
506void EngineContext::Report(const std::string &message)
507{
508 vm->GetHAL()->Report(message, InstancePrompt);
509}
510
511bool EngineContext::ReportError(const std::string &message)
512{
513 return vm->GetHAL()->ReportError(message, InstancePrompt);
514}
515
516bool EngineContext::ReportFatalError(const std::string &message)
517{
518 ReportError(message);
519#ifdef USING_WX
520 vm->GetGUI()->ShowError(message);
521#endif
522 return false;
523}
524
526{
527 //returns true if this engine has finished loading
528
529 if (!processor)
530 return false;
531
532 return (loading == true && processor->IsFinished == true);
533}
534
536{
537 //update progress bar
538
539 progress = percent;
540
541 return vm->UpdateProgress();
542}
543
545{
546 //get camera state data
547
548 return Simcore->camera->GetCameraState();
549}
550
551void EngineContext::SetCameraState(const CameraState &state, bool set_floor)
552{
553 //set camera state data
554
555 Simcore->camera->SetCameraState(state, set_floor);
556}
557
559{
560 //return true if user is inside the boundaries of this engine context
561
562 if (!Simcore)
563 return false;
564
565 if (!vm->GetActiveEngine())
566 return Simcore->IsInside();
567
568 //make sure the global camera's position is actually inside this engine
570}
571
572bool EngineContext::IsInside(const Vector3 &position)
573{
574 //return true if user is inside the boundaries of this engine context
575
576 if (!Simcore)
577 return false;
578
580}
581
582void EngineContext::DetachCamera(bool reset_building)
583{
584 //detach the camera from this engine
585
587
588 if (reset_building == true)
590}
591
592void EngineContext::AttachCamera(std::vector<Ogre::Camera*> &cameras, bool init_state)
593{
594 //attach the camera to this engine
595
596 Simcore->AttachCamera(cameras, init_state);
597
598 //reset camera position if camera is outside of the engine's area when attaching
599 if (IsInside() == false)
600 ResetCamera();
601}
602
607
609{
610 //reset camera position
612}
613
615{
616 //revert camera movement
618}
619
621{
622 //get this engine's camera position, in global positioning
623
625}
626
628{
629 //this function is run on engine entry
630
631 //switch to this engine on entry
632
633 inside = true;
634
635 if (vm->GetActiveEngine())
636 {
637 //if this engine is an ancestor of the active engine, don't switch to this engine
638 if (vm->GetActiveEngine()->IsParent(this) == true)
639 return;
640 }
641
642 //make this engine active
644}
645
647{
648 //this function is run on engine exit
649
650 inside = false;
651}
652
654{
655 //cut holes in this sim engine, for a newly loaded building, if possible
656
657 if (!engine || engine == this)
658 return;
659
660 ::SBS::SBS *newsimcore = engine->GetSystem();
661
662 Vector3 min, max, a, b, c, d, newmin, newmax;
663
664 //get new engine's boundaries
665 newsimcore->GetBounds(min, max);
666
667 if (min == Vector3::ZERO && max == Vector3::ZERO)
668 return;
669
670 //get global positions of engine's boundaries, in 4 points representing a rectangle
671 a = newsimcore->ToGlobal(Vector3(min.x, min.y, min.z));
672 b = newsimcore->ToGlobal(Vector3(min.x, min.y, max.z));
673 c = newsimcore->ToGlobal(Vector3(max.x, max.y, max.z));
674 d = newsimcore->ToGlobal(Vector3(max.x, max.y, min.z));
675
676 //convert global positions to this engine's relative positions
677 a = Simcore->FromGlobal(a);
678 b = Simcore->FromGlobal(b);
679 c = Simcore->FromGlobal(c);
680 d = Simcore->FromGlobal(d);
681
682 //get new cutting bounds (get min/max values)
683 newmin.x = Min(a.x, b.x, c.x, d.x);
684 newmin.y = Min(a.y, b.y, c.y, d.y);
685 newmin.z = Min(a.z, b.z, c.z, d.z);
686 newmax.x = Max(a.x, b.x, c.x, d.x);
687 newmax.y = Max(a.y, b.y, c.y, d.y);
688 newmax.z = Max(a.z, b.z, c.z, d.z);
689
690 //cut for new bounds
691 Simcore->DeleteColliders = true;
693 Simcore->DeleteColliders = false;
694
695 if (IsRunning() == true)
696 Simcore->Prepare();
697
698 //if this has a valid parent, have parent cut for the specified engine
699 if (vm->IsValidEngine(parent) == true)
700 parent->CutForEngine(engine);
701}
702
704{
705 if (engine)
706 children.emplace_back(engine);
707}
708
710{
711 for (size_t i = 0; i < children.size(); i++)
712 {
713 if (children[i] == engine)
714 {
715 children.erase(children.begin() + i);
716 return;
717 }
718 }
719}
720
721void EngineContext::Move(Vector3 &position, bool move_children)
722{
723 //move this engine
724 //if move_children is true, recursively call this function on all children
725
726 this->position += position;
728
729 if (move_children == true)
730 {
731 for (size_t i = 0; i < children.size(); i++)
732 {
733 children[i]->Move(position, move_children);
734 }
735 }
736}
737
738bool EngineContext::IsParent(EngineContext *engine, bool recursive)
739{
740 //returns true if the specified engine is a parent, or ancestor (if recursive is true) of this engine
741
742 if (!engine)
743 return false;
744
745 if (!GetParent())
746 return false;
747
748 //if this engine is the specified engine's parent, return true
749 if (engine == GetParent())
750 return true;
751
752 //ask the parent if recursive
753 if (recursive == true)
754 return GetParent()->IsParent(engine, recursive);
755
756 return false;
757}
758
760{
761 return vm;
762}
763
765{
766 //returns true if the script processor is in a runloop
767
768 if (processor)
769 return processor->InRunloop();
770 return false;
771}
772
774{
775 //returns true if this engine is the root/primary engine (0)
776
777 return (!GetParent());
778}
779
781{
782 //reset a gather operation
783
785}
786
788{
789 //perform a gather operation
790 //this collects timing information since the last reset
791
792 unsigned long last = current_time;
793
794 //get current time
796 if (last == 0)
797 last = current_time;
798
799 time_stat = current_time - last;
800}
801
803{
804 //reset prepared state
805
806 prepared = false;
807}
808
809}
bool IsActive()
Definition camera.h:171
void Refresh()
Definition camera.cpp:1356
void SetCameraState(const CameraState &state, bool set_floor=true)
Definition camera.cpp:1467
void SetToStartPosition(bool disable_current_floor)
Definition camera.cpp:456
CameraState GetCameraState()
Definition camera.cpp:1445
Vector3 GetPosition(bool relative=false)
Definition camera.cpp:250
void RevertMovement()
Definition camera.cpp:1491
virtual Vector3 GetPosition(bool relative=false)
Definition object.cpp:307
virtual void Move(const Vector3 &vector, Real speed=1.0, bool force=false)
Definition object.cpp:259
void Init(bool children=true)
Definition object.cpp:478
void Loop(bool loading, bool isready)
Definition sbs.cpp:591
void Initialize()
Definition sbs.cpp:221
Vector3 ToGlobal(const Vector3 &position)
Definition sbs.cpp:4439
bool AttachCamera(std::vector< Ogre::Camera * > &cameras, bool init_state=true)
Definition sbs.cpp:4275
void CutOutsideBoundaries(bool landscape=true, bool buildings=true, bool external=false, bool floors=false)
Definition sbs.cpp:4353
void AdvanceClock()
Definition sbs.cpp:3294
Camera * camera
Definition sbs.h:160
bool IsInside()
Definition sbs.cpp:4317
bool RenderOnStartup
Definition sbs.h:194
void CalculateFrameRate()
Definition sbs.cpp:677
unsigned long GetCurrentTime()
Definition sbs.cpp:3314
bool DetachCamera()
Definition sbs.cpp:4282
std::string BuildingFilename
Definition sbs.h:146
Vector3 FromGlobal(const Vector3 &position)
Definition sbs.cpp:4446
void CutInsideBoundaries(const Vector3 &min, const Vector3 &max, bool landscape=true, bool buildings=true, bool external=false, bool floors=false)
Definition sbs.cpp:4379
bool Start(std::vector< Ogre::Camera * > &cameras)
Definition sbs.cpp:528
void Prepare(bool report=true, bool renderonly=false)
Definition sbs.cpp:3107
bool DeleteColliders
Definition sbs.h:184
void ResetState()
Definition sbs.cpp:4412
bool GetBounds(Vector3 &min, Vector3 &max)
Definition sbs.cpp:4339
bool Verbose
Definition sbs.h:186
Ogre::SceneManager * mSceneManager
void AddChild(EngineContext *engine)
bool ReportError(const std::string &message)
std::vector< EngineContext * > children
::SBS::CameraState * reload_state
bool IsParent(EngineContext *engine, bool recursive=false)
ScriptProcessor * processor
void DetachCamera(bool reset_building=false)
void SetCameraState(const ::SBS::CameraState &state, bool set_floor=true)
ScriptProcessor * GetScriptProcessor()
void AttachCamera(std::vector< Ogre::Camera * > &cameras, bool init_state=true)
void CutForEngine(EngineContext *engine)
bool Start(std::vector< Ogre::Camera * > &cameras)
bool UpdateProgress(int percent)
void Move(Vector3 &position, bool move_children=false)
EngineContext * GetParent()
void RemoveChild(EngineContext *engine)
::SBS::CameraState GetCameraState()
bool ReportFatalError(const std::string &message)
bool Load(std::string filename)
void Report(const std::string &message)
EngineContext(EngineContext *parent, VM *vm, Ogre::SceneManager *mSceneManager, FMOD::System *fmodsystem, const Vector3 &position=Vector3::ZERO, Real rotation=0.0, const Vector3 &area_min=Vector3::ZERO, const Vector3 &area_max=Vector3::ZERO)
bool ProgressCancelled()
Definition gui.cpp:285
void ShowError(const std::string &message)
Definition gui.cpp:84
void CreateProgressDialog(const std::string &message)
Definition gui.cpp:225
void RefreshConsole()
Definition gui.cpp:293
void CloseProgressDialog()
Definition gui.cpp:254
void RaiseWindow()
Definition gui.cpp:302
bool DX11
Definition hal.h:94
unsigned long GetCurrentTime()
Definition hal.cpp:1017
void Report(const std::string &message, const std::string &prompt)
Definition hal.cpp:219
bool ReportError(const std::string &message, const std::string &prompt)
Definition hal.cpp:237
std::vector< std::string > nonexistent_files
Definition scriptproc.h:86
bool LoadDataFile(const std::string &filename, bool insert=false, int insert_line=0)
bool CutLandscape
Definition vm.h:120
bool IsValidEngine(EngineContext *engine)
Definition vm.cpp:512
bool CutBuildings
Definition vm.h:120
GUI * GetGUI()
Definition vm.cpp:148
HAL * GetHAL()
Definition vm.cpp:134
bool Verbose
Definition vm.h:121
void SetActiveEngine(int number, bool switch_engines=false, bool force=false)
Definition vm.cpp:232
int RegisterEngine(EngineContext *engine)
Definition vm.cpp:557
int GetEngineCount(bool loading_only=false)
Definition vm.cpp:448
bool Pause
Definition vm.h:119
bool GetRenderOnStartup()
Definition vm.cpp:978
bool UpdateProgress()
Definition vm.cpp:915
bool ReportMissingFiles(std::vector< std::string > &missing_files)
Definition vm.cpp:937
bool CutExternal
Definition vm.h:120
EngineContext * GetActiveEngine()
Definition vm.h:81
bool CutFloors
Definition vm.h:120
Ogre::Vector3 Vector3
Definition globals.h:58
Ogre::Real Real
Definition globals.h:57
Real Min(Real a, Real b, Real c)
Definition globals.cpp:121
Real Max(Real a, Real b, Real c)
Definition globals.cpp:131
std::string ToString(int number)
Definition globals.cpp:279
bool collisions
Definition camera.h:34