| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  | // Copyright (c) 2016-2018 Kiwano - Nomango
 | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | // Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					
						
							|  |  |  | // of this software and associated documentation files (the "Software"), to deal
 | 
					
						
							|  |  |  | // in the Software without restriction, including without limitation the rights
 | 
					
						
							|  |  |  | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					
						
							|  |  |  | // copies of the Software, and to permit persons to whom the Software is
 | 
					
						
							|  |  |  | // furnished to do so, subject to the following conditions:
 | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | // The above copyright notice and this permission notice shall be included in
 | 
					
						
							|  |  |  | // all copies or substantial portions of the Software.
 | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					
						
							|  |  |  | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					
						
							|  |  |  | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					
						
							|  |  |  | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					
						
							|  |  |  | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					
						
							|  |  |  | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					
						
							|  |  |  | // THE SOFTWARE.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | #include <kiwano/platform/Application.h>
 | 
					
						
							|  |  |  | #include <kiwano/platform/Input.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:12:13 +08:00
										 |  |  | #include <kiwano/core/Director.h>
 | 
					
						
							|  |  |  | #include <kiwano/core/Logger.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  | #include <kiwano/render/Renderer.h>
 | 
					
						
							| 
									
										
										
										
											2020-01-17 16:55:47 +08:00
										 |  |  | #include <kiwano/render/TextureCache.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-11 21:55:29 +08:00
										 |  |  | #include <kiwano/utils/ResourceCache.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-10 15:09:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-24 13:33:19 +08:00
										 |  |  | namespace kiwano | 
					
						
							| 
									
										
										
										
											2019-03-31 13:08:59 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Application::Application() | 
					
						
							| 
									
										
										
										
											2020-02-14 17:12:13 +08:00
										 |  |  |     : quiting_(false) | 
					
						
							|  |  |  |     , time_scale_(1.f) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     Use(Renderer::GetInstance()); | 
					
						
							|  |  |  |     Use(Input::GetInstance()); | 
					
						
							|  |  |  |     Use(Director::GetInstance()); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:12:13 +08:00
										 |  |  | Application::~Application() {} | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-17 13:23:46 +08:00
										 |  |  | int Application::GetVersion() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return KGE_VERSION; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 22:59:29 +08:00
										 |  |  | void Application::Run(RunnerPtr runner, bool debug) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  |     KGE_ASSERT(runner); | 
					
						
							|  |  |  |     runner_ = runner; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     // Setup all modules
 | 
					
						
							|  |  |  |     for (auto c : modules_) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |         c->SetupModule(); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (debug) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-08 09:59:17 +08:00
										 |  |  |         Director::GetInstance().ShowDebugInfo(true); | 
					
						
							|  |  |  |         Renderer::GetInstance().GetContext().SetCollectingStatus(true); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Everything is ready
 | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  |     runner->OnReady(); | 
					
						
							|  |  |  |     runner->SetLastUpdateTime(Time::Now()); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  |     quiting_ = false; | 
					
						
							| 
									
										
										
										
											2020-02-14 17:12:13 +08:00
										 |  |  |     while (!quiting_) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  |         quiting_ = !runner->MainLoop(); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-14 17:12:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Destroy all resources
 | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  |     runner->OnDestroy(); | 
					
						
							| 
									
										
										
										
											2020-02-14 17:12:13 +08:00
										 |  |  |     this->Destroy(); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Application::Quit() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:12:13 +08:00
										 |  |  |     quiting_ = true; | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Application::Destroy() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Clear all resources
 | 
					
						
							| 
									
										
										
										
											2020-02-08 09:59:17 +08:00
										 |  |  |     Director::GetInstance().ClearStages(); | 
					
						
							|  |  |  |     ResourceCache::GetInstance().Clear(); | 
					
						
							|  |  |  |     TextureCache::GetInstance().Clear(); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     for (auto iter = modules_.rbegin(); iter != modules_.rend(); ++iter) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |         (*iter)->DestroyModule(); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  | void Application::Use(Module& module) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  | #if defined(KGE_DEBUG)
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     if (std::find(modules_.begin(), modules_.end(), &module) != modules_.end()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         KGE_ASSERT(false && "Module already exists!"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     modules_.push_back(&module); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Application::SetTimeScale(float scale_factor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     time_scale_ = scale_factor; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  | void Application::Update(Duration dt) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     // Before update
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     for (auto comp : modules_) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |         if (auto update_comp = comp->Cast<UpdateModule>()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             update_comp->BeforeUpdate(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // perform functions
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!functions_to_perform_.empty()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             perform_mutex_.lock(); | 
					
						
							|  |  |  |             auto functions = std::move(functions_to_perform_); | 
					
						
							|  |  |  |             perform_mutex_.unlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             while (!functions.empty()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 auto& func = functions.front(); | 
					
						
							|  |  |  |                 if (func) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     func(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 functions.pop(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Updating
 | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  |     Duration scaled_dt = dt * time_scale_; | 
					
						
							|  |  |  |     for (auto comp : modules_) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  |         if (auto update_comp = comp->Cast<UpdateModule>()) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-02-14 22:01:56 +08:00
										 |  |  |             update_comp->OnUpdate(scaled_dt); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // After update
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     for (auto rit = modules_.rbegin(); rit != modules_.rend(); ++rit) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |         if (auto update_comp = (*rit)->Cast<UpdateModule>()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             update_comp->AfterUpdate(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Application::Render() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-08 09:59:17 +08:00
										 |  |  |     Renderer& renderer = Renderer::GetInstance(); | 
					
						
							| 
									
										
										
										
											2020-02-03 14:15:30 +08:00
										 |  |  |     renderer.Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     // Before render
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     for (auto comp : modules_) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |         if (auto render_comp = comp->Cast<RenderModule>()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             render_comp->BeforeRender(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Rendering
 | 
					
						
							| 
									
										
										
										
											2020-02-03 14:15:30 +08:00
										 |  |  |     renderer.BeginDraw(); | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     for (auto comp : modules_) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |         if (auto render_comp = comp->Cast<RenderModule>()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             render_comp->OnRender(renderer.GetContext()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-03 14:15:30 +08:00
										 |  |  |     renderer.EndDraw(); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // After render
 | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     for (auto rit = modules_.rbegin(); rit != modules_.rend(); ++rit) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |         if (auto render_comp = (*rit)->Cast<RenderModule>()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             render_comp->AfterRender(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-03 14:15:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     renderer.Present(); | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Application::DispatchEvent(Event* evt) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |     for (auto comp : modules_) | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-14 17:56:50 +08:00
										 |  |  |         if (auto event_comp = comp->Cast<EventModule>()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             event_comp->HandleEvent(evt); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-21 10:09:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Application::PreformInMainThread(Function<void()> func) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     std::lock_guard<std::mutex> lock(perform_mutex_); | 
					
						
							|  |  |  |     functions_to_perform_.push(func); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace kiwano
 |