| 
									
										
										
										
											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-11 21:55:29 +08:00
										 |  |  |  | #include <kiwano/renderer/Renderer.h>
 | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | #include <kiwano/renderer/GeometrySink.h>
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | #include <kiwano/core/Logger.h>
 | 
					
						
							| 
									
										
										
										
											2019-11-13 14:33:15 +08:00
										 |  |  |  | #include <kiwano/platform/Window.h>
 | 
					
						
							|  |  |  |  | #include <kiwano/platform/FileSystem.h>
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  |  | namespace kiwano | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 	RenderConfig::RenderConfig(Color clear_color, bool vsync) | 
					
						
							|  |  |  |  | 		: clear_color(clear_color) | 
					
						
							|  |  |  |  | 		, vsync(vsync) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	Renderer::Renderer() | 
					
						
							|  |  |  |  | 		: hwnd_(nullptr) | 
					
						
							|  |  |  |  | 		, vsync_(true) | 
					
						
							|  |  |  |  | 		, clear_color_(Color::Black) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	Renderer::~Renderer() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 	void Renderer::Init(RenderConfig const& config) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		SetClearColor(config.clear_color); | 
					
						
							|  |  |  |  | 		SetVSyncEnabled(config.vsync); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  |  | 	void Renderer::SetupComponent() | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-25 18:07:57 +08:00
										 |  |  |  | 		KGE_SYS_LOG(L"Creating device resources"); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 		hwnd_ = Window::instance().GetHandle(); | 
					
						
							|  |  |  |  | 		output_size_ = Window::instance().GetSize(); | 
					
						
							| 
									
										
										
										
											2019-04-22 13:21:12 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 		d2d_res_ = nullptr; | 
					
						
							|  |  |  |  | 		d3d_res_ = nullptr; | 
					
						
							| 
									
										
										
										
											2019-04-22 13:21:12 +08:00
										 |  |  |  | 		drawing_state_block_ = nullptr; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		HRESULT hr = hwnd_ ? S_OK : E_FAIL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		// Direct3D device resources
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 			hr = ID3DDeviceResources::Create(&d3d_res_, hwnd_); | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | 			// Direct2D device resources
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				hr = ID2DDeviceResources::Create(&d2d_res_, d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain()); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | 				// DrawingStateBlock
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hr = d2d_res_->GetFactory()->CreateDrawingStateBlock(&drawing_state_block_); | 
					
						
							|  |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | 				// Other device resources
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); | 
					
						
							|  |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | 				// FontFileLoader and FontCollectionLoader
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hr = IFontCollectionLoader::Create(&font_collection_loader_); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.get()); | 
					
						
							|  |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | 				// ResourceFontFileLoader and ResourceFontCollectionLoader
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hr = IResourceFontFileLoader::Create(&res_font_file_loader_); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.get()); | 
					
						
							|  |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, res_font_file_loader_.get()); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 						if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 						{ | 
					
						
							|  |  |  |  | 							hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(res_font_collection_loader_.get()); | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::DestroyComponent() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-25 18:07:57 +08:00
										 |  |  |  | 		KGE_SYS_LOG(L"Destroying device resources"); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		DiscardDeviceResources(); | 
					
						
							| 
									
										
										
										
											2019-08-20 19:32:36 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get()); | 
					
						
							|  |  |  |  | 		res_font_file_loader_.reset(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.get()); | 
					
						
							|  |  |  |  | 		res_font_collection_loader_.reset(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  |  | 		drawing_state_block_.reset(); | 
					
						
							|  |  |  |  | 		d2d_res_.reset(); | 
					
						
							|  |  |  |  | 		d3d_res_.reset(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 	void Renderer::BeforeRender() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		KGE_ASSERT(d3d_res_ && IsValid()); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		HRESULT hr = d3d_res_->ClearRenderTarget(clear_color_); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-23 18:05:08 +08:00
										 |  |  |  | 			GetRenderTarget()->SaveDrawingState(drawing_state_block_.get()); | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 			BeginDraw(); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::AfterRender() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		KGE_ASSERT(d3d_res_ && IsValid()); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		EndDraw(); | 
					
						
							|  |  |  |  | 		GetRenderTarget()->RestoreDrawingState(drawing_state_block_.get()); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		HRESULT hr = d3d_res_->Present(vsync_); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			// <20><><EFBFBD><EFBFBD> Direct3D <20>豸<EFBFBD><E8B1B8>ִ<EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>豸<EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
 | 
					
						
							|  |  |  |  | 			hr = HandleDeviceLost(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-29 22:23:13 +08:00
										 |  |  |  | 	void Renderer::HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		switch (msg) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 		case WM_SIZE: | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-10-12 11:26:41 +08:00
										 |  |  |  | 			uint32_t width = LOWORD(lparam); | 
					
						
							|  |  |  |  | 			uint32_t height = HIWORD(lparam); | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 			ResizeTarget(width, height); | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	HRESULT Renderer::HandleDeviceLost() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		KGE_ASSERT(d3d_res_ && d2d_res_ && render_target_); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 		HRESULT hr = d3d_res_->HandleDeviceLost(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 			hr = d2d_res_->HandleDeviceLost(d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain()); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-21 16:33:41 +08:00
										 |  |  |  | 	void Renderer::CreateTexture(Texture& texture, String const& file_path) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 		if (!FileSystem::instance().IsFileExists(file_path)) | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 			KGE_WARN(L"Texture file '%s' not found!", file_path.c_str()); | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 			hr = E_FAIL; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 			String full_path = FileSystem::instance().GetFullPathForFile(file_path); | 
					
						
							| 
									
										
										
										
											2019-10-11 21:12:29 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 			ComPtr<IWICBitmapDecoder> decoder; | 
					
						
							| 
									
										
										
										
											2019-10-11 21:12:29 +08:00
										 |  |  |  | 			hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 				ComPtr<IWICBitmapFrameDecode> source; | 
					
						
							|  |  |  |  | 				hr = decoder->GetFrame(0, &source); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					ComPtr<IWICFormatConverter> converter; | 
					
						
							|  |  |  |  | 					hr = d2d_res_->CreateBitmapConverter( | 
					
						
							|  |  |  |  | 						converter, | 
					
						
							|  |  |  |  | 						source, | 
					
						
							|  |  |  |  | 						GUID_WICPixelFormat32bppPBGRA, | 
					
						
							|  |  |  |  | 						WICBitmapDitherTypeNone, | 
					
						
							|  |  |  |  | 						nullptr, | 
					
						
							|  |  |  |  | 						0.f, | 
					
						
							|  |  |  |  | 						WICBitmapPaletteTypeMedianCut | 
					
						
							|  |  |  |  | 					); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						ComPtr<ID2D1Bitmap> bitmap; | 
					
						
							|  |  |  |  | 						hr = d2d_res_->CreateBitmapFromConverter( | 
					
						
							|  |  |  |  | 							bitmap, | 
					
						
							|  |  |  |  | 							nullptr, | 
					
						
							|  |  |  |  | 							converter | 
					
						
							|  |  |  |  | 						); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 						if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 						{ | 
					
						
							|  |  |  |  | 							texture.SetBitmap(bitmap); | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-07-29 09:40:39 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (FAILED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 			KGE_WARN(L"Load texture failed with HRESULT of %08X!", hr); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 	void Renderer::CreateTexture(Texture& texture, Resource const& resource) | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 			ComPtr<IWICBitmapDecoder> decoder; | 
					
						
							|  |  |  |  | 			hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 				ComPtr<IWICBitmapFrameDecode> source; | 
					
						
							|  |  |  |  | 				hr = decoder->GetFrame(0, &source); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					ComPtr<IWICFormatConverter> converter; | 
					
						
							|  |  |  |  | 					hr = d2d_res_->CreateBitmapConverter( | 
					
						
							|  |  |  |  | 						converter, | 
					
						
							|  |  |  |  | 						source, | 
					
						
							|  |  |  |  | 						GUID_WICPixelFormat32bppPBGRA, | 
					
						
							|  |  |  |  | 						WICBitmapDitherTypeNone, | 
					
						
							|  |  |  |  | 						nullptr, | 
					
						
							|  |  |  |  | 						0.f, | 
					
						
							|  |  |  |  | 						WICBitmapPaletteTypeMedianCut | 
					
						
							|  |  |  |  | 					); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						ComPtr<ID2D1Bitmap> bitmap; | 
					
						
							|  |  |  |  | 						hr = d2d_res_->CreateBitmapFromConverter( | 
					
						
							|  |  |  |  | 							bitmap, | 
					
						
							|  |  |  |  | 							nullptr, | 
					
						
							|  |  |  |  | 							converter | 
					
						
							|  |  |  |  | 						); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 						if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 						{ | 
					
						
							|  |  |  |  | 							texture.SetBitmap(bitmap); | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (FAILED(hr)) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 			KGE_WARN(L"Load texture failed with HRESULT of %08X!", hr); | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 	void Renderer::CreateGifImage(GifImage& gif, String const& file_path) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 		if (!FileSystem::instance().IsFileExists(file_path)) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 			KGE_WARN(L"Gif texture file '%s' not found!", file_path.c_str()); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			hr = E_FAIL; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 			String full_path = FileSystem::instance().GetFullPathForFile(file_path); | 
					
						
							| 
									
										
										
										
											2019-10-11 21:12:29 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			ComPtr<IWICBitmapDecoder> decoder; | 
					
						
							| 
									
										
										
										
											2019-10-11 21:12:29 +08:00
										 |  |  |  | 			hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 				gif.SetDecoder(decoder); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (FAILED(hr)) | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 			KGE_WARN(L"Load GIF texture failed with HRESULT of %08X!", hr); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 	void Renderer::CreateGifImage(GifImage& gif, Resource const& resource) | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			ComPtr<IWICBitmapDecoder> decoder; | 
					
						
							|  |  |  |  | 			hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				gif.SetDecoder(decoder); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (FAILED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 			KGE_WARN(L"Load GIF texture failed with HRESULT of %08X!", hr); | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-12 11:26:41 +08:00
										 |  |  |  | 	void Renderer::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index) | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (gif.GetDecoder() == nullptr) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_INVALIDARG; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 			ComPtr<IWICBitmapFrameDecode> wic_frame; | 
					
						
							| 
									
										
										
										
											2019-09-29 22:23:13 +08:00
										 |  |  |  | 			HRESULT hr = gif.GetDecoder()->GetFrame(UINT(frame_index), &wic_frame); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 				ComPtr<IWICFormatConverter> converter; | 
					
						
							|  |  |  |  | 				d2d_res_->CreateBitmapConverter( | 
					
						
							|  |  |  |  | 					converter, | 
					
						
							|  |  |  |  | 					wic_frame, | 
					
						
							|  |  |  |  | 					GUID_WICPixelFormat32bppPBGRA, | 
					
						
							|  |  |  |  | 					WICBitmapDitherTypeNone, | 
					
						
							|  |  |  |  | 					nullptr, | 
					
						
							|  |  |  |  | 					0.f, | 
					
						
							|  |  |  |  | 					WICBitmapPaletteTypeCustom | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					ComPtr<ID2D1Bitmap> raw_bitmap; | 
					
						
							|  |  |  |  | 					hr = d2d_res_->CreateBitmapFromConverter( | 
					
						
							|  |  |  |  | 						raw_bitmap, | 
					
						
							|  |  |  |  | 						nullptr, | 
					
						
							|  |  |  |  | 						converter | 
					
						
							|  |  |  |  | 					); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | 						frame.texture = new Texture; | 
					
						
							|  |  |  |  | 						frame.texture->SetBitmap(raw_bitmap); | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 				PROPVARIANT prop_val; | 
					
						
							|  |  |  |  | 				PropVariantInit(&prop_val); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// Get Metadata Query Reader from the frame
 | 
					
						
							|  |  |  |  | 				ComPtr<IWICMetadataQueryReader> metadata_reader; | 
					
						
							|  |  |  |  | 				hr = wic_frame->GetMetadataQueryReader(&metadata_reader); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// Get the Metadata for the current frame
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hr = metadata_reader->GetMetadataByName(L"/imgdesc/Left", &prop_val); | 
					
						
							|  |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); | 
					
						
							|  |  |  |  | 						if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2019-09-29 22:23:13 +08:00
										 |  |  |  | 							frame.rect.left_top.x = static_cast<float>(prop_val.uiVal); | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 						} | 
					
						
							|  |  |  |  | 						PropVariantClear(&prop_val); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 					hr = metadata_reader->GetMetadataByName(L"/imgdesc/Top", &prop_val); | 
					
						
							|  |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); | 
					
						
							|  |  |  |  | 						if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2019-09-29 22:23:13 +08:00
										 |  |  |  | 							frame.rect.left_top.y = static_cast<float>(prop_val.uiVal); | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 						} | 
					
						
							|  |  |  |  | 						PropVariantClear(&prop_val); | 
					
						
							|  |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hr = metadata_reader->GetMetadataByName(L"/imgdesc/Width", &prop_val); | 
					
						
							|  |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); | 
					
						
							|  |  |  |  | 						if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2019-09-29 22:23:13 +08:00
										 |  |  |  | 							frame.rect.right_bottom.x = frame.rect.left_top.x + static_cast<float>(prop_val.uiVal); | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 						} | 
					
						
							|  |  |  |  | 						PropVariantClear(&prop_val); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hr = metadata_reader->GetMetadataByName(L"/imgdesc/Height", &prop_val); | 
					
						
							|  |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); | 
					
						
							|  |  |  |  | 						if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2019-09-29 22:23:13 +08:00
										 |  |  |  | 							frame.rect.right_bottom.y = frame.rect.left_top.y + static_cast<float>(prop_val.uiVal); | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 						} | 
					
						
							|  |  |  |  | 						PropVariantClear(&prop_val); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hr = metadata_reader->GetMetadataByName(L"/grctlext/Delay", &prop_val); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 						if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2019-10-12 11:26:41 +08:00
										 |  |  |  | 							uint32_t udelay = 0; | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  |  | 							hr = UIntMult(prop_val.uiVal, 10, &udelay); | 
					
						
							|  |  |  |  | 							if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 							{ | 
					
						
							|  |  |  |  | 								frame.delay.SetMilliseconds(static_cast<long>(udelay)); | 
					
						
							|  |  |  |  | 							} | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 						PropVariantClear(&prop_val); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					else | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						frame.delay = 0; | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hr = metadata_reader->GetMetadataByName(L"/grctlext/Disposal", &prop_val); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL; | 
					
						
							|  |  |  |  | 						if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 						{ | 
					
						
							|  |  |  |  | 							frame.disposal_type = GifImage::DisposalType(prop_val.bVal); | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 						::PropVariantClear(&prop_val); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					else | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						frame.disposal_type = GifImage::DisposalType::Unknown; | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				::PropVariantClear(&prop_val); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (FAILED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 			KGE_WARN(L"Load GIF frame failed with HRESULT of %08X!", hr); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-26 19:25:43 +08:00
										 |  |  |  | 	void Renderer::CreateFontCollection(Font& font, Vector<String> const& file_paths) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-11 21:12:29 +08:00
										 |  |  |  | 		Vector<String> full_paths(file_paths); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-10-11 21:12:29 +08:00
										 |  |  |  | 			for (auto& file_path : full_paths) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 				if (!FileSystem::instance().IsFileExists(file_path)) | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 					KGE_WARN(L"Font file '%s' not found!", file_path.c_str()); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 					hr = E_FAIL; | 
					
						
							|  |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-10-11 21:12:29 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 				file_path = FileSystem::instance().GetFullPathForFile(file_path); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			LPVOID collection_key = nullptr; | 
					
						
							| 
									
										
										
										
											2019-10-12 11:26:41 +08:00
										 |  |  |  | 			uint32_t collection_key_size = 0; | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-11 21:12:29 +08:00
										 |  |  |  | 			hr = font_collection_loader_->AddFilePaths(full_paths, &collection_key, &collection_key_size); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				ComPtr<IDWriteFontCollection> font_collection; | 
					
						
							|  |  |  |  | 				hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection( | 
					
						
							|  |  |  |  | 					font_collection_loader_.get(), | 
					
						
							|  |  |  |  | 					collection_key, | 
					
						
							|  |  |  |  | 					collection_key_size, | 
					
						
							|  |  |  |  | 					&font_collection | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-12-26 19:25:43 +08:00
										 |  |  |  | 					font.SetCollection(font_collection); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-26 19:25:43 +08:00
										 |  |  |  | 	void Renderer::CreateFontCollection(Font& font, Vector<Resource> const& res_arr) | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			LPVOID collection_key = nullptr; | 
					
						
							| 
									
										
										
										
											2019-10-12 11:26:41 +08:00
										 |  |  |  | 			uint32_t collection_key_size = 0; | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			hr = res_font_collection_loader_->AddResources(res_arr, &collection_key, &collection_key_size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				ComPtr<IDWriteFontCollection> font_collection; | 
					
						
							|  |  |  |  | 				hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection( | 
					
						
							|  |  |  |  | 					res_font_collection_loader_.get(), | 
					
						
							|  |  |  |  | 					collection_key, | 
					
						
							|  |  |  |  | 					collection_key_size, | 
					
						
							|  |  |  |  | 					&font_collection | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-12-26 19:25:43 +08:00
										 |  |  |  | 					font.SetCollection(font_collection); | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-26 19:25:43 +08:00
										 |  |  |  | 	void Renderer::CreateTextFormat(TextLayout& layout) | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<IDWriteTextFormat> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-26 19:25:43 +08:00
										 |  |  |  | 			const TextStyle& style = layout.GetStyle(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			hr = d2d_res_->CreateTextFormat( | 
					
						
							|  |  |  |  | 				output, | 
					
						
							|  |  |  |  | 				style.font_family, | 
					
						
							|  |  |  |  | 				style.font ? style.font->GetCollection() : nullptr, | 
					
						
							|  |  |  |  | 				DWRITE_FONT_WEIGHT(style.font_weight), | 
					
						
							|  |  |  |  | 				style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, | 
					
						
							|  |  |  |  | 				DWRITE_FONT_STRETCH_NORMAL, | 
					
						
							|  |  |  |  | 				style.font_size | 
					
						
							|  |  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-26 19:25:43 +08:00
										 |  |  |  | 			layout.SetTextFormat(output); | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-26 19:25:43 +08:00
										 |  |  |  | 	void Renderer::CreateTextLayout(TextLayout& layout) | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<IDWriteTextLayout> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->CreateTextLayout( | 
					
						
							|  |  |  |  | 				output, | 
					
						
							| 
									
										
										
										
											2019-12-26 19:25:43 +08:00
										 |  |  |  | 				layout.GetText(), | 
					
						
							|  |  |  |  | 				layout.GetTextFormat() | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			layout.SetTextLayout(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	void Renderer::CreateLineGeometry(Geometry& geo, Point const& begin_pos, Point const& end_pos) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1PathGeometry> path_geo; | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1GeometrySink> path_sink; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreatePathGeometry(&path_geo); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = path_geo->Open(&path_sink); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			path_sink->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED); | 
					
						
							|  |  |  |  | 			path_sink->AddLine(DX::ConvertToPoint2F(end_pos)); | 
					
						
							|  |  |  |  | 			path_sink->EndFigure(D2D1_FIGURE_END_OPEN); | 
					
						
							|  |  |  |  | 			hr = path_sink->Close(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			geo.SetGeometry(path_geo); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateRectGeometry(Geometry& geo, Rect const& rect) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1RectangleGeometry> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreateRectangleGeometry(DX::ConvertToRectF(rect), &output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			geo.SetGeometry(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateRoundedRectGeometry(Geometry& geo, Rect const& rect, Vec2 const& radius) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1RoundedRectangleGeometry> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreateRoundedRectangleGeometry( | 
					
						
							|  |  |  |  | 				D2D1::RoundedRect( | 
					
						
							|  |  |  |  | 					DX::ConvertToRectF(rect), | 
					
						
							|  |  |  |  | 					radius.x, | 
					
						
							|  |  |  |  | 					radius.y | 
					
						
							|  |  |  |  | 				), | 
					
						
							|  |  |  |  | 				&output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			geo.SetGeometry(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateEllipseGeometry(Geometry& geo, Point const& center, Vec2 const& radius) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1EllipseGeometry> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreateEllipseGeometry( | 
					
						
							|  |  |  |  | 				D2D1::Ellipse( | 
					
						
							|  |  |  |  | 					DX::ConvertToPoint2F(center), | 
					
						
							|  |  |  |  | 					radius.x, | 
					
						
							|  |  |  |  | 					radius.y | 
					
						
							|  |  |  |  | 				), | 
					
						
							|  |  |  |  | 				&output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			geo.SetGeometry(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-27 10:51:34 +08:00
										 |  |  |  | 	void Renderer::CreateGeometrySink(GeometrySink& sink) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1PathGeometry> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreatePathGeometry(&output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			sink.SetPathGeometry(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-27 10:51:34 +08:00
										 |  |  |  | 	void Renderer::CreateTextureRenderTarget(TextureRenderTargetPtr& render_target) | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-27 10:51:34 +08:00
										 |  |  |  | 		TextureRenderTargetPtr output; | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-27 10:51:34 +08:00
										 |  |  |  | 			ComPtr<ID2D1BitmapRenderTarget> bitmap_rt; | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(&bitmap_rt); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				output = new TextureRenderTarget; | 
					
						
							| 
									
										
										
										
											2019-12-29 18:58:22 +08:00
										 |  |  |  | 				hr = output->CreateDeviceResources(d2d_res_->GetFactory(), bitmap_rt); | 
					
						
							| 
									
										
										
										
											2019-12-27 10:51:34 +08:00
										 |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				output->SetBitmapRenderTarget(bitmap_rt); | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-12-27 10:51:34 +08:00
										 |  |  |  | 			render_target = output; | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 	void Renderer::CreateSolidBrush(Brush& brush, Color const& color) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-09 08:45:00 +08:00
										 |  |  |  | 			ComPtr<ID2D1SolidColorBrush> output; | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 			hr = d2d_res_->GetDeviceContext()->CreateSolidColorBrush(DX::ConvertToColorF(color), &output); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 08:45:00 +08:00
										 |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				brush.SetBrush(output, Brush::Type::SolidColor); | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 09:30:30 +08:00
										 |  |  |  | 	void Renderer::CreateLinearGradientBrush(Brush& brush, LinearGradientStyle const& style) | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-09 08:45:00 +08:00
										 |  |  |  | 			ComPtr<ID2D1GradientStopCollection> collection; | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 			hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection( | 
					
						
							| 
									
										
										
										
											2020-01-10 09:30:30 +08:00
										 |  |  |  | 				reinterpret_cast<const D2D1_GRADIENT_STOP*>(&style.stops[0]), | 
					
						
							|  |  |  |  | 				UINT32(style.stops.size()), | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 				D2D1_GAMMA_2_2, | 
					
						
							| 
									
										
										
										
											2020-01-10 09:30:30 +08:00
										 |  |  |  | 				D2D1_EXTEND_MODE(style.extend_mode), | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 				&collection | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				ComPtr<ID2D1LinearGradientBrush> output; | 
					
						
							|  |  |  |  | 				hr = d2d_res_->GetDeviceContext()->CreateLinearGradientBrush( | 
					
						
							|  |  |  |  | 					D2D1::LinearGradientBrushProperties( | 
					
						
							| 
									
										
										
										
											2020-01-10 09:30:30 +08:00
										 |  |  |  | 						DX::ConvertToPoint2F(style.begin), | 
					
						
							|  |  |  |  | 						DX::ConvertToPoint2F(style.end) | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 					), | 
					
						
							| 
									
										
										
										
											2020-01-09 08:45:00 +08:00
										 |  |  |  | 					collection.get(), | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 					&output | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-12-27 23:42:51 +08:00
										 |  |  |  | 					brush.SetBrush(output, Brush::Type::LinearGradient); | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 09:30:30 +08:00
										 |  |  |  | 	void Renderer::CreateRadialGradientBrush(Brush& brush, RadialGradientStyle const& style) | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-01-09 08:45:00 +08:00
										 |  |  |  | 			ComPtr<ID2D1GradientStopCollection> collection; | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 			hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection( | 
					
						
							| 
									
										
										
										
											2020-01-10 09:30:30 +08:00
										 |  |  |  | 				reinterpret_cast<const D2D1_GRADIENT_STOP*>(&style.stops[0]), | 
					
						
							|  |  |  |  | 				UINT32(style.stops.size()), | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 				D2D1_GAMMA_2_2, | 
					
						
							| 
									
										
										
										
											2020-01-10 09:30:30 +08:00
										 |  |  |  | 				D2D1_EXTEND_MODE(style.extend_mode), | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 				&collection | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				ComPtr<ID2D1RadialGradientBrush> output; | 
					
						
							|  |  |  |  | 				hr = d2d_res_->GetDeviceContext()->CreateRadialGradientBrush( | 
					
						
							|  |  |  |  | 					D2D1::RadialGradientBrushProperties( | 
					
						
							| 
									
										
										
										
											2020-01-10 09:30:30 +08:00
										 |  |  |  | 						DX::ConvertToPoint2F(style.center), | 
					
						
							|  |  |  |  | 						DX::ConvertToPoint2F(style.offset), | 
					
						
							|  |  |  |  | 						style.radius.x, | 
					
						
							|  |  |  |  | 						style.radius.y | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 					), | 
					
						
							| 
									
										
										
										
											2020-01-09 08:45:00 +08:00
										 |  |  |  | 					collection.get(), | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 					&output | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-12-27 23:42:51 +08:00
										 |  |  |  | 					brush.SetBrush(output, Brush::Type::RadialGradient); | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-09-09 22:02:53 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 	void Renderer::SetDpi(float dpi) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		KGE_ASSERT(d3d_res_ && d2d_res_); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		HRESULT hr = d3d_res_->SetDpi(dpi); | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->SetDpi(dpi); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	void Renderer::SetVSyncEnabled(bool enabled) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		vsync_ = enabled; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 	void Renderer::SetClearColor(const Color& color) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		clear_color_ = color; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-12 11:26:41 +08:00
										 |  |  |  | 	void Renderer::ResizeTarget(uint32_t width, uint32_t height) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (!d3d_res_) | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-09-29 22:23:13 +08:00
										 |  |  |  | 			output_size_.x = static_cast<float>(width); | 
					
						
							|  |  |  |  | 			output_size_.y = static_cast<float>(height); | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 			hr = d3d_res_->SetLogicalSize(output_size_); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->SetLogicalSize(output_size_); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:04:08 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			Resize(reinterpret_cast<const Size&>(GetRenderTarget()->GetSize())); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-30 14:24:29 +08:00
										 |  |  |  | 		win32::ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-12-17 20:47:55 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | } |