| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  | // Copyright (c) 2016-2018 Kiwano - Nomango
 | 
					
						
							| 
									
										
										
										
											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:
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // The above copyright notice and this permission notice shall be included in
 | 
					
						
							|  |  |  | // all copies or substantial portions of the Software.
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // 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.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-10 15:09:38 +08:00
										 |  |  | #include <mutex>
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  | #include <kiwano/platform/Application.h>
 | 
					
						
							| 
									
										
										
										
											2019-11-13 14:33:15 +08:00
										 |  |  | #include <kiwano/platform/Input.h>
 | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | #include <kiwano/core/Director.h>
 | 
					
						
							|  |  |  | #include <kiwano/core/Logger.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-11 21:55:29 +08:00
										 |  |  | #include <kiwano/renderer/TextureCache.h>
 | 
					
						
							|  |  |  | #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
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-24 13:33:19 +08:00
										 |  |  | 	namespace | 
					
						
							| 
									
										
										
										
											2019-03-31 13:08:59 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  | 		using FunctionToPerform = Function<void()>; | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-24 13:33:19 +08:00
										 |  |  | 		std::mutex				 perform_mutex_; | 
					
						
							|  |  |  | 		Queue<FunctionToPerform> functions_to_perform_; | 
					
						
							| 
									
										
										
										
											2019-03-31 13:08:59 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-12 11:26:41 +08:00
										 |  |  | 	Config::Config(String const& title, uint32_t width, uint32_t height, uint32_t icon) | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  | 		: debug(false) | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		window.title = title; | 
					
						
							|  |  |  | 		window.width = width; | 
					
						
							|  |  |  | 		window.height = height; | 
					
						
							|  |  |  | 		window.icon = icon; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config) | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  | 		: debug(false) | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		window = wnd_config; | 
					
						
							|  |  |  | 		render = render_config; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-31 13:08:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  | namespace kiwano | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | { | 
					
						
							|  |  |  | 	Application::Application() | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 		: time_scale_(1.f) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  | 		Use(&Renderer::instance()); | 
					
						
							|  |  |  | 		Use(&Input::instance()); | 
					
						
							|  |  |  | 		Use(&Director::instance()); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Application::~Application() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		Destroy(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 	void Application::Run(const Config& config) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 		Window::instance().Init(config.window); | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  | 		Renderer::instance().Init(config.render); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Setup all components
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 		for (auto c : comps_) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 			c->SetupComponent(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		if (config.debug) | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  | 			Director::instance().ShowDebugInfo(true); | 
					
						
							|  |  |  | 			Renderer::instance().SetCollectingStatus(true); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Everything is ready
 | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 		OnReady(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 		last_update_time_ = Time::Now(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 		Window& window = Window::instance(); | 
					
						
							|  |  |  | 		while (!window.ShouldClose()) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 			while (EventPtr evt = window.PollEvent()) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				DispatchEvent(evt.get()); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Update(); | 
					
						
							|  |  |  | 			Render(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void Application::Quit() | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 		Window::instance().Destroy(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void Application::Destroy() | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		// Clear all resources
 | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  | 		Director::instance().ClearStages(); | 
					
						
							|  |  |  | 		ResourceCache::instance().Clear(); | 
					
						
							|  |  |  | 		TextureCache::instance().Clear(); | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 		for (auto iter = comps_.rbegin(); iter != comps_.rend(); ++iter) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 			(*iter)->DestroyComponent(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 		comps_.clear(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 	void Application::Use(ComponentBase* component) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		if (component) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  | #if defined(KGE_DEBUG)
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 			if (comps_.contains(component)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  | 				KGE_ASSERT(false && "Component already exists!"); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 			comps_.push_back(component); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 			if (component->Check(RenderComponent::flag)) | 
					
						
							|  |  |  | 				render_comps_.push_back(dynamic_cast<RenderComponent*>(component)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (component->Check(UpdateComponent::flag)) | 
					
						
							|  |  |  | 				update_comps_.push_back(dynamic_cast<UpdateComponent*>(component)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (component->Check(EventComponent::flag)) | 
					
						
							|  |  |  | 				event_comps_.push_back(dynamic_cast<EventComponent*>(component)); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-29 22:23:13 +08:00
										 |  |  | 	void Application::SetTimeScale(float scale_factor) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		time_scale_ = scale_factor; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void Application::Update() | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  | 		// Before update
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 		for (auto c : update_comps_) | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 			c->BeforeUpdate(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +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(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 		// Updating
 | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 			const Time now = Time::Now(); | 
					
						
							|  |  |  | 			const Duration dt = (now - last_update_time_) * time_scale_; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 			last_update_time_ = now; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 			for (auto c : update_comps_) | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				c->OnUpdate(dt); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  | 		// After update
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 		for (auto rit = update_comps_.rbegin(); rit != update_comps_.rend(); ++rit) | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			(*rit)->AfterUpdate(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void Application::Render() | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  | 		// Before render
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 		for (auto c : render_comps_) | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			c->BeforeRender(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  | 		// Rendering
 | 
					
						
							| 
									
										
										
										
											2020-01-10 15:22:12 +08:00
										 |  |  | 		Renderer& renderer = Renderer::instance(); | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 		for (auto c : render_comps_) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-14 00:28:25 +08:00
										 |  |  | 			c->OnRender(renderer); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  | 		// After render
 | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 		for (auto rit = render_comps_.rbegin(); rit != render_comps_.rend(); ++rit) | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			(*rit)->AfterRender(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 18:33:42 +08:00
										 |  |  | 	void Application::DispatchEvent(Event* evt) | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-09-10 13:17:47 +08:00
										 |  |  | 		for (auto c : event_comps_) | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			c->HandleEvent(evt); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-20 17:49:16 +08:00
										 |  |  | 	void Application::PreformInMainThread(Function<void()> func) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		std::lock_guard<std::mutex> lock(perform_mutex_); | 
					
						
							| 
									
										
										
										
											2019-12-20 17:49:16 +08:00
										 |  |  | 		functions_to_perform_.push(func); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } |