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
117 //register this engine, and get it's instance number
118 instance = vm->RegisterEngine(this);
119
120 Report("\nStarting instance " + ToString(instance) + "...");
121
122 //add instance number to reports
124
125 if (parent)
126 parent->AddChild(this);
127
128 StartSim();
129}
130
135
137{
138 //returns true if camera is active in this simulator
139
140 if (!Simcore)
141 return false;
142
143 return Simcore->camera->IsActive();
144}
145
147{
148 //request a shutdown
149
150 shutdown = true;
151}
152
154{
155 //run simulator
156
157 if (!Simcore)
158 return false;
159
160 //run script processor
161 if (processor)
162 {
163 bool in_main = InRunloop();
164 bool result = processor->Run();
165
166 if (loading == true)
167 {
168 prepared = false;
169
170 #ifdef USING_WX
171 if (vm->GetGUI()->ProgressCancelled() == true)
172 result = false;
173 #endif
174
175 if (result == false)
176 {
177 ReportError("Error processing building\n");
178 Shutdown();
179 #ifdef USING_WX
180 if (vm->GetEngineCount(true) == 1)
182 #endif
183 return false;
184 }
185 else if (processor->IsFinished == true)
186 {
187 //building has finished loading
189 }
190
191 if (Simcore->RenderOnStartup == false)
192 return false;
193 }
194 else if (processor->IsFinished == true && result == true)
195 {
196 if (InRunloop() == false && prepared == false)
197 {
198 Simcore->Prepare(false);
199 Simcore->DeleteColliders = false;
200 Simcore->Init(); //initialize any new objects
201 prepared = true;
202 }
203 else
204 {
205 loading = false;
206 }
207 }
208 }
209 else
210 return false;
211
212 //force window raise on startup, and report on missing files, if any
213 if (Simcore->GetCurrentTime() - finish_time > 0 && raised == false && loading == false)
214 {
215#ifdef USING_WX
216 vm->GetGUI()->RaiseWindow();
217#endif
218 raised = true;
219
221 }
222
223 //process internal clock
225 if (running == true)
227
228 //run SBS main loop
230
231 if (loading == false)
232 {
233 //run functions if user enters or leaves this engine
234 if (inside == false && IsInside() == true)
235 OnEnter();
236 if (inside == true && IsInside() == false)
237 OnExit();
238 }
239
240 return true;
241}
242
244{
245 //initialize simulator
246
247 if (!Simcore || !processor)
248 return false;
249
251
252 //load script processor object
253 processor->Reset();
254
255 return true;
256}
257
259{
260 //boot simulator
261 processor->Start();
262}
263
265{
266 //load default simulation
267
268 if (!Simcore || !processor)
269 return false;
270
271 loading = true;
272
273 //initialize simulator
274 InitSim();
275
276 Report("\nLoading default simulation...\n");
277 Simcore->BuildingFilename = "Default";
278
279 //load defaults
281
282 //override SBS startup render option, if specified
283 if (vm->GetRenderOnStartup() == true)
284 Simcore->RenderOnStartup = true;
285
286 return true;
287}
288
289bool EngineContext::Load(std::string filename)
290{
291 //load simulator and data file
292
293 if (!Simcore || !processor)
294 return false;
295
296 //exit if no building specified
297 if (filename == "")
298 return false;
299
300 loading = true;
301
302 //initialize simulator
303 InitSim();
304
305 //load building data file
306 Report("\nLoading building data from " + filename + "...\n");
307 Simcore->BuildingFilename = filename;
308
309 filename.insert(0, "buildings/");
310
311 //load building
312 if (!processor->LoadDataFile(filename))
313 {
314 loading = false;
315 return false;
316 }
317
318 //create progress dialog
319#ifdef USING_WX
320 vm->GetGUI()->CreateProgressDialog(filename);
321#endif
322
323 //override SBS startup render option, if specified
324 if (vm->GetRenderOnStartup() == true)
325 Simcore->RenderOnStartup = true;
326
327 return true;
328}
329
331{
332 //reload the current building
333
334 if (!Simcore)
335 return;
336
337 reloading = true;
338
339 //store camera state information
340 std::string filename = Simcore->BuildingFilename;
342
343 //unload current simulator
344 UnloadSim();
345
346 //start a new simulator
347 StartSim();
348
349 //load building file
350 if (Load(filename) == false)
351 {
352 reloading = false;
353 Reload = false;
354 return;
355 }
356
357 Reload = false;
358}
359
361{
362 if (Simcore)
364 return "";
365}
366
368{
369 //create simulator and script interpreter objects
370
371 //exit if already started
372 if (started == true)
373 return;
374
375 //get offset of parent engine
376 Vector3 offset;
377 if (parent)
378 offset = parent->GetSystem()->GetPosition();
379 else
380 offset = Vector3::ZERO;
381
382 if (position != Vector3::ZERO)
383 Moved = true;
384
385 //Create simulator object
386 if (!Simcore)
388
389 //load script processor
390 if (!processor)
391 processor = new ScriptProcessor(this);
392
393 //if using DirectX11, turn off models in script processor due to shader crashes
395
396 //refresh console to fix banner message on Linux
397#ifdef USING_WX
399#endif
400
401 //override verbose mode if specified
402 if (vm->Verbose == true)
403 Simcore->Verbose = true;
404
405 //Pause for 2 seconds, if first instance
406 if (instance == 0)
407 {
408 vm->Pause = true; //briefly pause frontend to prevent debug panel calls to engine
409#ifdef USING_WX
410 wxYield(); //this allows the banner to be printed before the sleep() call
411#endif
412 vm->Pause = false;
413#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
414 Sleep(2000);
415#else
416 sleep(2);
417#endif
418 }
419}
420
422{
423 //unload simulator
424
425 if (Simcore)
426 {
427 delete Simcore;
428 Report("\nSBS instance " + ToString(instance) + " unloaded");
429 }
430 Simcore = 0;
431
432#ifndef DISABLE_SOUND
433 //reset fmod reverb
434 FMOD_REVERB_PROPERTIES prop = FMOD_PRESET_GENERIC;
435 fmodsystem->setReverbProperties(0, &prop);
436#endif
437
438 //unload script processor
439 if (processor)
440 delete processor;
441 processor = 0;
442
443 loading = false;
444 running = false;
445 raised = false;
446 Moved = false;
447 started = false;
448
449#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
450#ifdef __linux__
451 //release free memory to OS on Linux
452 malloc_trim(0);
453#else
454 //freebsd
455#endif
456
457#endif
458}
459
460bool EngineContext::Start(std::vector<Ogre::Camera*> &cameras)
461{
462 //start simulator
463
464 if (!Simcore)
465 return false;
466
467 //cut outside sim boundaries if specified
469
470 //if this has a parent engine, cut the parent for this new engine
471 if (vm->IsValidEngine(parent) == true)
472 parent->CutForEngine(this);
473
474 //if this has child engines, and has reloaded, cut for the child engines
475 if (children.empty() == false && reloading == true)
476 {
477 for (size_t i = 0; i < children.size(); i++)
478 {
480 }
481 }
482
483 //start simulator
484 if (!Simcore->Start(cameras))
485 return ReportError("Error starting simulator\n");
486
487 //set to saved position if reloading building
488 if (reloading == true)
489 {
490 reloading = false;
492 }
493
494 loading = false;
495 running = true;
496
497 return true;
498}
499
500void EngineContext::Report(const std::string &message)
501{
502 vm->GetHAL()->Report(message, InstancePrompt);
503}
504
505bool EngineContext::ReportError(const std::string &message)
506{
507 return vm->GetHAL()->ReportError(message, InstancePrompt);
508}
509
510bool EngineContext::ReportFatalError(const std::string &message)
511{
512 ReportError(message);
513#ifdef USING_WX
514 vm->GetGUI()->ShowError(message);
515#endif
516 return false;
517}
518
520{
521 //returns true if this engine has finished loading
522
523 if (!processor)
524 return false;
525
526 return (loading == true && processor->IsFinished == true);
527}
528
530{
531 //update progress bar
532
533 progress = percent;
534
535 return vm->UpdateProgress();
536}
537
539{
540 //get camera state data
541
542 return Simcore->camera->GetCameraState();
543}
544
545void EngineContext::SetCameraState(const CameraState &state, bool set_floor)
546{
547 //set camera state data
548
549 Simcore->camera->SetCameraState(state, set_floor);
550}
551
553{
554 //return true if user is inside the boundaries of this engine context
555
556 if (!Simcore)
557 return false;
558
559 if (!vm->GetActiveEngine())
560 return Simcore->IsInside();
561
562 //make sure the global camera's position is actually inside this engine
564}
565
566bool EngineContext::IsInside(const Vector3 &position)
567{
568 //return true if user is inside the boundaries of this engine context
569
570 if (!Simcore)
571 return false;
572
574}
575
576void EngineContext::DetachCamera(bool reset_building)
577{
578 //detach the camera from this engine
579
581
582 if (reset_building == true)
584}
585
586void EngineContext::AttachCamera(std::vector<Ogre::Camera*> &cameras, bool init_state)
587{
588 //attach the camera to this engine
589
590 Simcore->AttachCamera(cameras, init_state);
591
592 //reset camera position if camera is outside of the engine's area when attaching
593 if (IsInside() == false)
594 ResetCamera();
595}
596
601
603{
604 //reset camera position
606}
607
609{
610 //revert camera movement
612}
613
615{
616 //get this engine's camera position, in global positioning
617
619}
620
622{
623 //this function is run on engine entry
624
625 //switch to this engine on entry
626
627 inside = true;
628
629 if (vm->GetActiveEngine())
630 {
631 //if this engine is an ancestor of the active engine, don't switch to this engine
632 if (vm->GetActiveEngine()->IsParent(this) == true)
633 return;
634 }
635
636 //make this engine active
638}
639
641{
642 //this function is run on engine exit
643
644 inside = false;
645}
646
648{
649 //cut holes in this sim engine, for a newly loaded building, if possible
650
651 if (!engine || engine == this)
652 return;
653
654 ::SBS::SBS *newsimcore = engine->GetSystem();
655
656 Vector3 min, max, a, b, c, d, newmin, newmax;
657
658 //get new engine's boundaries
659 newsimcore->GetBounds(min, max);
660
661 if (min == Vector3::ZERO && max == Vector3::ZERO)
662 return;
663
664 //get global positions of engine's boundaries, in 4 points representing a rectangle
665 a = newsimcore->ToGlobal(Vector3(min.x, min.y, min.z));
666 b = newsimcore->ToGlobal(Vector3(min.x, min.y, max.z));
667 c = newsimcore->ToGlobal(Vector3(max.x, max.y, max.z));
668 d = newsimcore->ToGlobal(Vector3(max.x, max.y, min.z));
669
670 //convert global positions to this engine's relative positions
671 a = Simcore->FromGlobal(a);
672 b = Simcore->FromGlobal(b);
673 c = Simcore->FromGlobal(c);
674 d = Simcore->FromGlobal(d);
675
676 //get new cutting bounds (get min/max values)
677 newmin.x = Min(a.x, b.x, c.x, d.x);
678 newmin.y = Min(a.y, b.y, c.y, d.y);
679 newmin.z = Min(a.z, b.z, c.z, d.z);
680 newmax.x = Max(a.x, b.x, c.x, d.x);
681 newmax.y = Max(a.y, b.y, c.y, d.y);
682 newmax.z = Max(a.z, b.z, c.z, d.z);
683
684 //cut for new bounds
685 Simcore->DeleteColliders = true;
687 Simcore->DeleteColliders = false;
688
689 if (IsRunning() == true)
690 Simcore->Prepare();
691
692 //if this has a valid parent, have parent cut for the specified engine
693 if (vm->IsValidEngine(parent) == true)
694 parent->CutForEngine(engine);
695}
696
698{
699 if (engine)
700 children.emplace_back(engine);
701}
702
704{
705 for (size_t i = 0; i < children.size(); i++)
706 {
707 if (children[i] == engine)
708 {
709 children.erase(children.begin() + i);
710 return;
711 }
712 }
713}
714
715void EngineContext::Move(Vector3 &position, bool move_children)
716{
717 //move this engine
718 //if move_children is true, recursively call this function on all children
719
720 this->position += position;
722
723 if (move_children == true)
724 {
725 for (size_t i = 0; i < children.size(); i++)
726 {
727 children[i]->Move(position, move_children);
728 }
729 }
730}
731
732bool EngineContext::IsParent(EngineContext *engine, bool recursive)
733{
734 //returns true if the specified engine is a parent, or ancestor (if recursive is true) of this engine
735
736 if (!engine)
737 return false;
738
739 if (!GetParent())
740 return false;
741
742 //if this engine is the specified engine's parent, return true
743 if (engine == GetParent())
744 return true;
745
746 //ask the parent if recursive
747 if (recursive == true)
748 return GetParent()->IsParent(engine, recursive);
749
750 return false;
751}
752
754{
755 return vm;
756}
757
759{
760 //returns true if the script processor is in a runloop
761
762 if (processor)
763 return processor->InRunloop();
764 return false;
765}
766
768{
769 //returns true if this engine is the root/primary engine (0)
770
771 return (!GetParent());
772}
773
775{
776 //reset a gather operation
777
779}
780
782{
783 //perform a gather operation
784 //this collects timing information since the last reset
785
786 unsigned long last = current_time;
787
788 //get current time
790 if (last == 0)
791 last = current_time;
792
793 time_stat = current_time - last;
794}
795
797{
798 //reset prepared state
799
800 prepared = false;
801}
802
803}
bool IsActive()
Definition camera.h:171
void Refresh()
Definition camera.cpp:1357
void SetCameraState(const CameraState &state, bool set_floor=true)
Definition camera.cpp:1468
void SetToStartPosition(bool disable_current_floor)
Definition camera.cpp:456
CameraState GetCameraState()
Definition camera.cpp:1446
Vector3 GetPosition(bool relative=false)
Definition camera.cpp:250
void RevertMovement()
Definition camera.cpp:1492
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 Init(bool children=true)
Definition object.cpp:492
void Loop(bool loading, bool isready)
Definition sbs.cpp:591
void Initialize()
Definition sbs.cpp:222
Vector3 ToGlobal(const Vector3 &position)
Definition sbs.cpp:4409
bool AttachCamera(std::vector< Ogre::Camera * > &cameras, bool init_state=true)
Definition sbs.cpp:4245
void CutOutsideBoundaries(bool landscape=true, bool buildings=true, bool external=false, bool floors=false)
Definition sbs.cpp:4323
void AdvanceClock()
Definition sbs.cpp:3264
Camera * camera
Definition sbs.h:160
bool IsInside()
Definition sbs.cpp:4287
bool RenderOnStartup
Definition sbs.h:194
void CalculateFrameRate()
Definition sbs.cpp:677
unsigned long GetCurrentTime()
Definition sbs.cpp:3284
bool DetachCamera()
Definition sbs.cpp:4252
std::string BuildingFilename
Definition sbs.h:146
Vector3 FromGlobal(const Vector3 &position)
Definition sbs.cpp:4416
void CutInsideBoundaries(const Vector3 &min, const Vector3 &max, bool landscape=true, bool buildings=true, bool external=false, bool floors=false)
Definition sbs.cpp:4349
bool Start(std::vector< Ogre::Camera * > &cameras)
Definition sbs.cpp:529
void Prepare(bool report=true, bool renderonly=false)
Definition sbs.cpp:3077
bool DeleteColliders
Definition sbs.h:184
void ResetState()
Definition sbs.cpp:4382
bool GetBounds(Vector3 &min, Vector3 &max)
Definition sbs.cpp:4309
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:283
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:291
void CloseProgressDialog()
Definition gui.cpp:253
void RaiseWindow()
Definition gui.cpp:300
bool DX11
Definition hal.h:94
unsigned long GetCurrentTime()
Definition hal.cpp:1019
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:119
bool IsValidEngine(EngineContext *engine)
Definition vm.cpp:506
bool CutBuildings
Definition vm.h:119
GUI * GetGUI()
Definition vm.cpp:142
HAL * GetHAL()
Definition vm.cpp:128
bool Verbose
Definition vm.h:120
void SetActiveEngine(int number, bool switch_engines=false, bool force=false)
Definition vm.cpp:226
int RegisterEngine(EngineContext *engine)
Definition vm.cpp:551
int GetEngineCount(bool loading_only=false)
Definition vm.cpp:442
bool Pause
Definition vm.h:118
bool GetRenderOnStartup()
Definition vm.cpp:972
bool UpdateProgress()
Definition vm.cpp:909
bool ReportMissingFiles(std::vector< std::string > &missing_files)
Definition vm.cpp:931
bool CutExternal
Definition vm.h:119
EngineContext * GetActiveEngine()
Definition vm.h:81
bool CutFloors
Definition vm.h:119
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