[deploy] Merge pull request #55 from KiwanoEngine/dev
Merge develop branch
This commit is contained in:
		
						commit
						a8c13b49c1
					
				|  | @ -28,7 +28,7 @@ void ImGuiModule::SetupModule() | ||||||
|     // Setup Dear ImGui style
 |     // Setup Dear ImGui style
 | ||||||
|     ImGui::StyleColorsDark(); |     ImGui::StyleColorsDark(); | ||||||
| 
 | 
 | ||||||
|     window_ = Application::GetInstance().GetMainWindow(); |     window_ = Application::GetInstance().GetWindow(); | ||||||
| 
 | 
 | ||||||
|     // Setup Platform/Renderer bindings
 |     // Setup Platform/Renderer bindings
 | ||||||
|     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;  // We can honor GetMouseCursor() values (optional)
 |     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;  // We can honor GetMouseCursor() values (optional)
 | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| CanvasPtr Canvas::Create(const Size& size) | CanvasPtr Canvas::Create(const Size& size) | ||||||
| { | { | ||||||
|     void*     mem = memory::Alloc<Canvas>(); |     void*     mem = memory::Alloc(sizeof(Canvas)); | ||||||
|     CanvasPtr ptr = ::new (mem) Canvas; |     CanvasPtr ptr = ::new (mem) Canvas; | ||||||
|     if (ptr) |     if (ptr) | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -62,14 +62,14 @@ void Button::SetStatus(Status status) | ||||||
| 
 | 
 | ||||||
|         if (status == Status::Normal) |         if (status == Status::Normal) | ||||||
|         { |         { | ||||||
|             Application::GetInstance().GetMainWindow()->SetCursor(CursorType::Arrow); |             Application::GetInstance().GetWindow()->SetCursor(CursorType::Arrow); | ||||||
| 
 | 
 | ||||||
|             if (mouse_out_callback_) |             if (mouse_out_callback_) | ||||||
|                 mouse_out_callback_(this, GetBoundActor()); |                 mouse_out_callback_(this, GetBoundActor()); | ||||||
|         } |         } | ||||||
|         else if (status == Status::Hover) |         else if (status == Status::Hover) | ||||||
|         { |         { | ||||||
|             Application::GetInstance().GetMainWindow()->SetCursor(CursorType::Hand); |             Application::GetInstance().GetWindow()->SetCursor(CursorType::Hand); | ||||||
| 
 | 
 | ||||||
|             if (old_status != Status::Pressed) |             if (old_status != Status::Pressed) | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -27,6 +27,26 @@ namespace memory | ||||||
| 
 | 
 | ||||||
| MemoryAllocator* current_allocator_ = nullptr; | MemoryAllocator* current_allocator_ = nullptr; | ||||||
| 
 | 
 | ||||||
|  | MemoryAllocator* GetGlobalAllocator() | ||||||
|  | { | ||||||
|  |     class KGE_API GlobalAllocator : public MemoryAllocator | ||||||
|  |     { | ||||||
|  |     public: | ||||||
|  |         virtual void* Alloc(size_t size) override | ||||||
|  |         { | ||||||
|  |             return ::operator new(size); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         virtual void Free(void* ptr, size_t size) override | ||||||
|  |         { | ||||||
|  |             ::operator delete(ptr, size); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     static GlobalAllocator global_allocator; | ||||||
|  |     return &global_allocator; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| MemoryAllocator* GetAllocator() | MemoryAllocator* GetAllocator() | ||||||
| { | { | ||||||
|     if (!current_allocator_) |     if (!current_allocator_) | ||||||
|  | @ -42,21 +62,5 @@ void SetAllocator(MemoryAllocator* allocator) | ||||||
|     current_allocator_ = allocator; |     current_allocator_ = allocator; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| GlobalAllocator* GetGlobalAllocator() |  | ||||||
| { |  | ||||||
|     static GlobalAllocator global_allocator; |  | ||||||
|     return &global_allocator; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void* GlobalAllocator::Alloc(size_t size) |  | ||||||
| { |  | ||||||
|     return ::malloc(size); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GlobalAllocator::Free(void* ptr) |  | ||||||
| { |  | ||||||
|     ::free(ptr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| }  // namespace memory
 | }  // namespace memory
 | ||||||
| }  // namespace kiwano
 | }  // namespace kiwano
 | ||||||
|  |  | ||||||
|  | @ -19,8 +19,9 @@ | ||||||
| // THE SOFTWARE.
 | // THE SOFTWARE.
 | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #include <utility> | #include <utility>  // std::forward | ||||||
| #include <type_traits> | #include <limits>  // std::numeric_limits | ||||||
|  | #include <memory>  // std::addressof | ||||||
| #include <kiwano/macros.h> | #include <kiwano/macros.h> | ||||||
| 
 | 
 | ||||||
| namespace kiwano | namespace kiwano | ||||||
|  | @ -39,7 +40,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief 释放内存
 |     /// @brief 释放内存
 | ||||||
|     virtual void Free(void* ptr) = 0; |     virtual void Free(void* ptr, size_t size) = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// \~chinese
 | /// \~chinese
 | ||||||
|  | @ -52,30 +53,32 @@ void SetAllocator(MemoryAllocator* allocator); | ||||||
| 
 | 
 | ||||||
| /// \~chinese
 | /// \~chinese
 | ||||||
| /// @brief 使用当前内存分配器分配内存
 | /// @brief 使用当前内存分配器分配内存
 | ||||||
| template <typename _Ty> | inline void* Alloc(size_t size) | ||||||
| inline void* Alloc() |  | ||||||
| { | { | ||||||
|     return memory::GetAllocator()->Alloc(sizeof(_Ty)); |     return memory::GetAllocator()->Alloc(size); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// \~chinese
 | /// \~chinese
 | ||||||
| /// @brief 使用当前内存分配器释放内存
 | /// @brief 使用当前内存分配器释放内存
 | ||||||
| inline void Free(void* ptr) | inline void Free(void* ptr, size_t size) | ||||||
| { | { | ||||||
|     return memory::GetAllocator()->Free(ptr); |     memory::GetAllocator()->Free(ptr, size); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// \~chinese
 | /// \~chinese
 | ||||||
| /// @brief 使用当前内存分配器创建对象
 | /// @brief 构造对象
 | ||||||
| template <typename _Ty> | template <typename _Ty, typename... _Args> | ||||||
| inline _Ty* New() | inline _Ty* Construct(void* ptr, _Args&&... args) | ||||||
| { | { | ||||||
|     void* ptr = memory::Alloc<_Ty>(); |     return ::new (ptr) _Ty(std::forward<_Args>(args)...); | ||||||
|     if (ptr) | } | ||||||
|     { | 
 | ||||||
|         return ::new (ptr) _Ty; | /// \~chinese
 | ||||||
|     } | /// @brief 销毁对象
 | ||||||
|     return nullptr; | template <typename _Ty, typename... _Args> | ||||||
|  | inline void Destroy(_Ty* ptr) | ||||||
|  | { | ||||||
|  |     ptr->~_Ty(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// \~chinese
 | /// \~chinese
 | ||||||
|  | @ -83,10 +86,10 @@ inline _Ty* New() | ||||||
| template <typename _Ty, typename... _Args> | template <typename _Ty, typename... _Args> | ||||||
| inline _Ty* New(_Args&&... args) | inline _Ty* New(_Args&&... args) | ||||||
| { | { | ||||||
|     void* ptr = memory::Alloc<_Ty>(); |     void* ptr = memory::Alloc(sizeof(_Ty)); | ||||||
|     if (ptr) |     if (ptr) | ||||||
|     { |     { | ||||||
|         return ::new (ptr) _Ty(std::forward<_Args>(args)...); |         return memory::Construct<_Ty>(ptr, std::forward<_Args>(args)...); | ||||||
|     } |     } | ||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
|  | @ -98,28 +101,119 @@ inline void Delete(_Ty* ptr) | ||||||
| { | { | ||||||
|     if (ptr) |     if (ptr) | ||||||
|     { |     { | ||||||
|         ptr->~_Ty(); |         memory::Destroy<_Ty>(ptr); | ||||||
|         memory::Free(ptr); |         memory::Free(ptr, sizeof(_Ty)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| /// \~chinese
 | /// \~chinese
 | ||||||
| /// @brief 全局内存分配器,使用malloc和free分配内存
 | /// @brief 分配器
 | ||||||
| class KGE_API GlobalAllocator : public MemoryAllocator | template <typename _Ty> | ||||||
|  | class Allocator | ||||||
| { | { | ||||||
| public: | public: | ||||||
|     /// \~chinese
 |     typedef _Ty        value_type; | ||||||
|     /// @brief 申请内存
 |     typedef _Ty*       pointer; | ||||||
|     virtual void* Alloc(size_t size) override; |     typedef const _Ty* const_pointer; | ||||||
|  |     typedef _Ty&       reference; | ||||||
|  |     typedef const _Ty& const_reference; | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |     using size_type       = size_t; | ||||||
|     /// @brief 释放内存
 |     using difference_type = ptrdiff_t; | ||||||
|     virtual void Free(void* ptr) override; | 
 | ||||||
|  |     template <class _Other> | ||||||
|  |     struct rebind | ||||||
|  |     { | ||||||
|  |         using other = Allocator<_Other>; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     Allocator() noexcept {} | ||||||
|  | 
 | ||||||
|  |     Allocator(const Allocator&) noexcept = default; | ||||||
|  | 
 | ||||||
|  |     template <class _Other> | ||||||
|  |     Allocator(const Allocator<_Other>&) noexcept | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline _Ty* allocate(size_t count) | ||||||
|  |     { | ||||||
|  |         if (count > 0) | ||||||
|  |         { | ||||||
|  |             return static_cast<_Ty*>(memory::Alloc(sizeof(_Ty) * count)); | ||||||
|  |         } | ||||||
|  |         return nullptr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline void* allocate(size_t count, const void*) | ||||||
|  |     { | ||||||
|  |         return allocate(count); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline void deallocate(void* ptr, size_t count) | ||||||
|  |     { | ||||||
|  |         memory::Free(ptr, sizeof(_Ty) * count); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     template <typename _UTy, typename... _Args> | ||||||
|  |     inline void construct(_UTy* ptr, _Args&&... args) | ||||||
|  |     { | ||||||
|  |         memory::Construct<_UTy>(ptr, std::forward<_Args>(args)...); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     template <typename _UTy> | ||||||
|  |     inline void destroy(_UTy* ptr) | ||||||
|  |     { | ||||||
|  |         memory::Destroy<_UTy>(ptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     size_t max_size() const noexcept | ||||||
|  |     { | ||||||
|  |         return std::numeric_limits<size_t>::max() / sizeof(_Ty); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     _Ty* address(_Ty& val) const noexcept | ||||||
|  |     { | ||||||
|  |         return std::addressof(val); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const _Ty* address(const _Ty& val) const noexcept | ||||||
|  |     { | ||||||
|  |         return std::addressof(val); | ||||||
|  |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// \~chinese
 | // Allocator<void>
 | ||||||
| /// @brief 获取全局内存分配器
 | template <> | ||||||
| GlobalAllocator* GetGlobalAllocator(); | class Allocator<void> | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     using value_type = void; | ||||||
|  |     typedef void*       pointer; | ||||||
|  |     typedef const void* const_pointer; | ||||||
|  | 
 | ||||||
|  |     using size_type       = size_t; | ||||||
|  |     using difference_type = ptrdiff_t; | ||||||
|  | 
 | ||||||
|  |     template <class _Other> | ||||||
|  |     struct rebind | ||||||
|  |     { | ||||||
|  |         using other = Allocator<_Other>; | ||||||
|  |     }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | template <class _Ty, class _Other> | ||||||
|  | bool operator==(const Allocator<_Ty>&, const Allocator<_Other>&) noexcept | ||||||
|  | { | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <class _Ty, class _Other> | ||||||
|  | bool operator!=(const Allocator<_Ty>&, const Allocator<_Other>&) noexcept | ||||||
|  | { | ||||||
|  |     return false; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| }  // namespace memory
 | }  // namespace memory
 | ||||||
| }  // namespace kiwano
 | }  // namespace kiwano
 | ||||||
|  |  | ||||||
|  | @ -19,9 +19,8 @@ | ||||||
| // THE SOFTWARE.
 | // THE SOFTWARE.
 | ||||||
| 
 | 
 | ||||||
| #include <kiwano/platform/Application.h> | #include <kiwano/platform/Application.h> | ||||||
| #include <kiwano/platform/Input.h> |  | ||||||
| #include <kiwano/base/Director.h> |  | ||||||
| #include <kiwano/utils/Logger.h> | #include <kiwano/utils/Logger.h> | ||||||
|  | #include <kiwano/base/Director.h> | ||||||
| #include <kiwano/render/Renderer.h> | #include <kiwano/render/Renderer.h> | ||||||
| #include <kiwano/render/TextureCache.h> | #include <kiwano/render/TextureCache.h> | ||||||
| #include <kiwano/utils/ResourceCache.h> | #include <kiwano/utils/ResourceCache.h> | ||||||
|  | @ -39,9 +38,6 @@ Application::Application() | ||||||
|     , is_paused_(false) |     , is_paused_(false) | ||||||
|     , time_scale_(1.f) |     , time_scale_(1.f) | ||||||
| { | { | ||||||
|     Use(Renderer::GetInstance()); |  | ||||||
|     Use(Input::GetInstance()); |  | ||||||
|     Use(Director::GetInstance()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Application::~Application() | Application::~Application() | ||||||
|  | @ -49,25 +45,22 @@ Application::~Application() | ||||||
|     this->Destroy(); |     this->Destroy(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Application::Run(RunnerPtr runner, bool debug) | void Application::Run(RunnerPtr runner) | ||||||
| { | { | ||||||
|     KGE_ASSERT(runner); |     KGE_ASSERT(runner); | ||||||
|     runner_ = runner; |     runner_ = runner; | ||||||
|     running_ = true; |     running_ = true; | ||||||
|     is_paused_ = false; |     is_paused_ = false; | ||||||
| 
 | 
 | ||||||
|  |     // Initialize runner
 | ||||||
|  |     runner->InitSettings(); | ||||||
|  | 
 | ||||||
|     // Setup all modules
 |     // Setup all modules
 | ||||||
|     for (auto c : modules_) |     for (auto c : modules_) | ||||||
|     { |     { | ||||||
|         c->SetupModule(); |         c->SetupModule(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (debug) |  | ||||||
|     { |  | ||||||
|         Director::GetInstance().ShowDebugInfo(true); |  | ||||||
|         Renderer::GetInstance().GetContext().SetCollectingStatus(true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Everything is ready
 |     // Everything is ready
 | ||||||
|     runner->OnReady(); |     runner->OnReady(); | ||||||
| 
 | 
 | ||||||
|  | @ -128,16 +121,19 @@ void Application::Destroy() | ||||||
|         runner_ = nullptr; |         runner_ = nullptr; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Clear all resources
 |     // Clear user resources
 | ||||||
|     Director::GetInstance().ClearStages(); |     Director::GetInstance().ClearStages(); | ||||||
|     ResourceCache::GetInstance().Clear(); |     ResourceCache::GetInstance().Clear(); | ||||||
|     TextureCache::GetInstance().Clear(); |  | ||||||
| 
 | 
 | ||||||
|     for (auto iter = modules_.rbegin(); iter != modules_.rend(); ++iter) |     for (auto iter = modules_.rbegin(); iter != modules_.rend(); ++iter) | ||||||
|     { |     { | ||||||
|         (*iter)->DestroyModule(); |         (*iter)->DestroyModule(); | ||||||
|     } |     } | ||||||
|     modules_.clear(); |     modules_.clear(); | ||||||
|  | 
 | ||||||
|  |     // Clear device resources
 | ||||||
|  |     TextureCache::GetInstance().Clear(); | ||||||
|  |     Renderer::GetInstance().Destroy(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Application::Use(Module& module) | void Application::Use(Module& module) | ||||||
|  |  | ||||||
|  | @ -58,7 +58,7 @@ public: | ||||||
|      * @param debug 是否启用调试模式 |      * @param debug 是否启用调试模式 | ||||||
|      * @note 该函数是阻塞的,应用程序结束时函数返回 |      * @note 该函数是阻塞的,应用程序结束时函数返回 | ||||||
|      */ |      */ | ||||||
|     void Run(RunnerPtr runner, bool debug = false); |     void Run(RunnerPtr runner); | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * \~chinese |      * \~chinese | ||||||
|  | @ -99,9 +99,9 @@ public: | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * \~chinese |      * \~chinese | ||||||
|      * @brief »ñÈ¡Ö÷´°¿Ú |      * @brief »ñÈ¡´°¿Ú | ||||||
|      */ |      */ | ||||||
|     WindowPtr GetMainWindow() const; |     WindowPtr GetWindow() const; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * \~chinese |      * \~chinese | ||||||
|  | @ -183,10 +183,10 @@ inline RunnerPtr Application::GetRunner() const | ||||||
|     return runner_; |     return runner_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline WindowPtr Application::GetMainWindow() const | inline WindowPtr Application::GetWindow() const | ||||||
| { | { | ||||||
|     KGE_ASSERT(runner_); |     KGE_ASSERT(runner_); | ||||||
|     return runner_->GetMainWindow(); |     return runner_->GetWindow(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline TickerPtr Application::GetFrameTicker() const | inline TickerPtr Application::GetFrameTicker() const | ||||||
|  |  | ||||||
|  | @ -20,24 +20,25 @@ | ||||||
| 
 | 
 | ||||||
| #include <kiwano/utils/Logger.h> | #include <kiwano/utils/Logger.h> | ||||||
| #include <kiwano/platform/Runner.h> | #include <kiwano/platform/Runner.h> | ||||||
|  | #include <kiwano/platform/Input.h> | ||||||
| #include <kiwano/platform/Application.h> | #include <kiwano/platform/Application.h> | ||||||
| 
 | #include <kiwano/render/Renderer.h> | ||||||
| #define KGE_MAX_SKIP_FRAMES 10 | #include <kiwano/base/Director.h> | ||||||
| 
 | 
 | ||||||
| namespace kiwano | namespace kiwano | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| RunnerPtr Runner::Create(WindowPtr main_window) | RunnerPtr Runner::Create(Settings settings) | ||||||
| { | { | ||||||
|     RunnerPtr ptr = memory::New<Runner>(); |     RunnerPtr ptr = memory::New<Runner>(); | ||||||
|     if (ptr) |     if (ptr) | ||||||
|     { |     { | ||||||
|         ptr->SetMainWindow(main_window); |         ptr->SetSettings(settings); | ||||||
|     } |     } | ||||||
|     return ptr; |     return ptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RunnerPtr Runner::Create(WindowPtr main_window, Function<void()> on_ready, Function<void()> on_destroy) | RunnerPtr Runner::Create(Settings settings, Function<void()> on_ready, Function<void()> on_destroy) | ||||||
| { | { | ||||||
|     class CallbackRunner : public Runner |     class CallbackRunner : public Runner | ||||||
|     { |     { | ||||||
|  | @ -63,7 +64,7 @@ RunnerPtr Runner::Create(WindowPtr main_window, Function<void()> on_ready, Funct | ||||||
|     { |     { | ||||||
|         ptr->on_ready   = on_ready; |         ptr->on_ready   = on_ready; | ||||||
|         ptr->on_destroy = on_destroy; |         ptr->on_destroy = on_destroy; | ||||||
|         ptr->SetMainWindow(main_window); |         ptr->SetSettings(settings); | ||||||
|     } |     } | ||||||
|     return ptr; |     return ptr; | ||||||
| } | } | ||||||
|  | @ -72,6 +73,36 @@ Runner::Runner() {} | ||||||
| 
 | 
 | ||||||
| Runner::~Runner() {} | Runner::~Runner() {} | ||||||
| 
 | 
 | ||||||
|  | void Runner::InitSettings() | ||||||
|  | { | ||||||
|  |     if (settings_.debug_mode) | ||||||
|  |     { | ||||||
|  |         // Show console window before creating main window
 | ||||||
|  |         Logger::GetInstance().ShowConsole(true); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Create game window
 | ||||||
|  |     WindowPtr window = | ||||||
|  |         Window::Create(settings_.title, settings_.width, settings_.height, settings_.icon, settings_.resizable); | ||||||
|  |     SetWindow(window); | ||||||
|  | 
 | ||||||
|  |     // Update renderer settings
 | ||||||
|  |     Renderer::GetInstance().MakeContextForWindow(window); | ||||||
|  |     Renderer::GetInstance().SetClearColor(settings_.bg_color); | ||||||
|  |     Renderer::GetInstance().SetVSyncEnabled(settings_.vsync_enabled); | ||||||
|  | 
 | ||||||
|  |     // Use defaut modules
 | ||||||
|  |     Application::GetInstance().Use(Input::GetInstance()); | ||||||
|  |     Application::GetInstance().Use(Director::GetInstance()); | ||||||
|  | 
 | ||||||
|  |     // Enable debug mode
 | ||||||
|  |     if (settings_.debug_mode) | ||||||
|  |     { | ||||||
|  |         Director::GetInstance().ShowDebugInfo(true); | ||||||
|  |         Renderer::GetInstance().GetContext().SetCollectingStatus(true); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool Runner::MainLoop(Duration dt) | bool Runner::MainLoop(Duration dt) | ||||||
| { | { | ||||||
|     if (!main_window_) |     if (!main_window_) | ||||||
|  | @ -79,7 +110,7 @@ bool Runner::MainLoop(Duration dt) | ||||||
| 
 | 
 | ||||||
|     if (main_window_->ShouldClose()) |     if (main_window_->ShouldClose()) | ||||||
|     { |     { | ||||||
|         if (this->OnClosing()) |         if (this->OnClose()) | ||||||
|             return false; |             return false; | ||||||
| 
 | 
 | ||||||
|         main_window_->SetShouldClose(false); |         main_window_->SetShouldClose(false); | ||||||
|  |  | ||||||
|  | @ -22,6 +22,8 @@ | ||||||
| #include <kiwano/core/Common.h> | #include <kiwano/core/Common.h> | ||||||
| #include <kiwano/core/Time.h> | #include <kiwano/core/Time.h> | ||||||
| #include <kiwano/platform/Window.h> | #include <kiwano/platform/Window.h> | ||||||
|  | #include <kiwano/render/Color.h> | ||||||
|  | #include <kiwano/render/Texture.h> | ||||||
| 
 | 
 | ||||||
| namespace kiwano | namespace kiwano | ||||||
| { | { | ||||||
|  | @ -30,26 +32,52 @@ class Application; | ||||||
| 
 | 
 | ||||||
| KGE_DECLARE_SMART_PTR(Runner); | KGE_DECLARE_SMART_PTR(Runner); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * \~chinese | ||||||
|  |  * @brief 游戏设置 | ||||||
|  |  */ | ||||||
|  | struct Settings | ||||||
|  | { | ||||||
|  |     uint32_t width;          ///< 窗口宽度
 | ||||||
|  |     uint32_t height;         ///< 窗口高度
 | ||||||
|  |     String   title;          ///< 窗口标题
 | ||||||
|  |     uint32_t icon;           ///< 窗口图标
 | ||||||
|  |     bool     resizable;      ///< 窗口大小可调整
 | ||||||
|  |     Color    bg_color;       ///< 窗口背景色
 | ||||||
|  |     bool     vsync_enabled;  ///< 垂直同步
 | ||||||
|  |     bool     debug_mode;     ///< 调试模式
 | ||||||
|  | 
 | ||||||
|  |     Settings() | ||||||
|  |         : width(800) | ||||||
|  |         , height(600) | ||||||
|  |         , title("Kiwano") | ||||||
|  |         , icon() | ||||||
|  |         , resizable(false) | ||||||
|  |         , bg_color(Color::Black) | ||||||
|  |         , vsync_enabled(true) | ||||||
|  |         , debug_mode(false) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * \~chinese |  * \~chinese | ||||||
|  * @brief 程序运行器 |  * @brief 程序运行器 | ||||||
|  */ |  */ | ||||||
| class KGE_API Runner : public ObjectBase | class KGE_API Runner : public ObjectBase | ||||||
| { | { | ||||||
|     friend class Application; |  | ||||||
| 
 |  | ||||||
| public: | public: | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief 创建程序运行器
 |     /// @brief 创建程序运行器
 | ||||||
|     /// @param main_window 主窗口
 |     /// @param main_window 主窗口
 | ||||||
|     static RunnerPtr Create(WindowPtr main_window); |     static RunnerPtr Create(Settings settings); | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief 创建程序运行器
 |     /// @brief 创建程序运行器
 | ||||||
|     /// @param main_window 主窗口
 |     /// @param main_window 主窗口
 | ||||||
|     /// @param on_ready 应用程序初始化完成后执行的回调函数
 |     /// @param on_ready 应用程序初始化完成后执行的回调函数
 | ||||||
|     /// @param on_destroy 应用程序销毁时执行的回调函数
 |     /// @param on_destroy 应用程序销毁时执行的回调函数
 | ||||||
|     static RunnerPtr Create(WindowPtr main_window, Function<void()> on_ready, Function<void()> on_destroy = nullptr); |     static RunnerPtr Create(Settings settings, Function<void()> on_ready, Function<void()> on_destroy = nullptr); | ||||||
| 
 | 
 | ||||||
|     Runner(); |     Runner(); | ||||||
| 
 | 
 | ||||||
|  | @ -69,7 +97,7 @@ public: | ||||||
|     /// @brief 应用程序关闭处理
 |     /// @brief 应用程序关闭处理
 | ||||||
|     /// @details 重载该函数以处理用户关闭应用程序时的行为,如保存用户数据等
 |     /// @details 重载该函数以处理用户关闭应用程序时的行为,如保存用户数据等
 | ||||||
|     /// @return 返回true允许用户关闭程序,否则阻止程序关闭
 |     /// @return 返回true允许用户关闭程序,否则阻止程序关闭
 | ||||||
|     virtual bool OnClosing(); |     virtual bool OnClose(); | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief 应用程序主循环
 |     /// @brief 应用程序主循环
 | ||||||
|  | @ -79,14 +107,29 @@ public: | ||||||
|     virtual bool MainLoop(Duration dt); |     virtual bool MainLoop(Duration dt); | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief »ñÈ¡Ö÷´°¿Ú
 |     /// @brief 获取窗口
 | ||||||
|     WindowPtr GetMainWindow() const; |     WindowPtr GetWindow() const; | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief ÉèÖÃÖ÷´°¿Ú
 |     /// @brief 设置窗口
 | ||||||
|     void SetMainWindow(WindowPtr window); |     void SetWindow(WindowPtr window); | ||||||
|  | 
 | ||||||
|  |     /// \~chinese
 | ||||||
|  |     /// @brief 获取设置
 | ||||||
|  |     Settings GetSettings() const; | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |     /// \~chinese
 | ||||||
|  |     /// @brief 修改设置
 | ||||||
|  |     void SetSettings(Settings settings); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     friend class Application; | ||||||
|  | 
 | ||||||
|  |     void InitSettings(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     Settings  settings_; | ||||||
|     WindowPtr main_window_; |     WindowPtr main_window_; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -94,19 +137,29 @@ inline void Runner::OnReady() {} | ||||||
| 
 | 
 | ||||||
| inline void Runner::OnDestroy() {} | inline void Runner::OnDestroy() {} | ||||||
| 
 | 
 | ||||||
| inline bool Runner::OnClosing() | inline bool Runner::OnClose() | ||||||
| { | { | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline WindowPtr Runner::GetMainWindow() const | inline WindowPtr Runner::GetWindow() const | ||||||
| { | { | ||||||
|     return main_window_; |     return main_window_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline void Runner::SetMainWindow(WindowPtr window) | inline void Runner::SetWindow(WindowPtr window) | ||||||
| { | { | ||||||
|     main_window_ = window; |     main_window_ = window; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | inline Settings Runner::GetSettings() const | ||||||
|  | { | ||||||
|  |     return settings_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline void Runner::SetSettings(Settings settings) | ||||||
|  | { | ||||||
|  |     settings_ = settings; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }  // namespace kiwano
 | }  // namespace kiwano
 | ||||||
|  |  | ||||||
|  | @ -269,21 +269,6 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, | ||||||
| 
 | 
 | ||||||
|     ::ShowWindow(handle_, SW_SHOWNORMAL); |     ::ShowWindow(handle_, SW_SHOWNORMAL); | ||||||
|     ::UpdateWindow(handle_); |     ::UpdateWindow(handle_); | ||||||
| 
 |  | ||||||
|     // Initialize Direct3D resources
 |  | ||||||
|     auto d3d_res = graphics::directx::GetD3DDeviceResources(); |  | ||||||
| 
 |  | ||||||
|     HRESULT hr = d3d_res->Initialize(handle_); |  | ||||||
| 
 |  | ||||||
|     // Initialize Direct2D resources
 |  | ||||||
|     if (SUCCEEDED(hr)) |  | ||||||
|     { |  | ||||||
|         auto d2d_res = graphics::directx::GetD2DDeviceResources(); |  | ||||||
| 
 |  | ||||||
|         hr = d2d_res->Initialize(d3d_res->GetDXGIDevice(), d3d_res->GetDXGISwapChain()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     KGE_THROW_IF_FAILED(hr, "Create DirectX resources failed"); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WindowWin32Impl::PumpEvents() | void WindowWin32Impl::PumpEvents() | ||||||
|  |  | ||||||
|  | @ -58,11 +58,41 @@ void RendererImpl::MakeContextForWindow(WindowPtr window) | ||||||
|     HWND target_window = window->GetHandle(); |     HWND target_window = window->GetHandle(); | ||||||
|     output_size_       = window->GetSize(); |     output_size_       = window->GetSize(); | ||||||
| 
 | 
 | ||||||
|     d2d_res_ = graphics::directx::GetD2DDeviceResources(); |  | ||||||
|     d3d_res_ = graphics::directx::GetD3DDeviceResources(); |  | ||||||
| 
 |  | ||||||
|     HRESULT hr = target_window ? S_OK : E_FAIL; |     HRESULT hr = target_window ? S_OK : E_FAIL; | ||||||
| 
 | 
 | ||||||
|  |     // Initialize Direct3D resources
 | ||||||
|  |     if (SUCCEEDED(hr)) | ||||||
|  |     { | ||||||
|  |         auto d3d_res = graphics::directx::GetD3DDeviceResources(); | ||||||
|  | 
 | ||||||
|  |         hr = d3d_res->Initialize(target_window); | ||||||
|  |         if (FAILED(hr)) | ||||||
|  |         { | ||||||
|  |             d3d_res->DiscardResources(); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             d3d_res_ = d3d_res; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Initialize Direct2D resources
 | ||||||
|  |     if (SUCCEEDED(hr)) | ||||||
|  |     { | ||||||
|  |         auto d2d_res = graphics::directx::GetD2DDeviceResources(); | ||||||
|  | 
 | ||||||
|  |         hr = d2d_res->Initialize(d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain()); | ||||||
|  |         if (FAILED(hr)) | ||||||
|  |         { | ||||||
|  |             d2d_res->DiscardResources(); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             d2d_res_ = d2d_res; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     // Initialize other device resources
 |     // Initialize other device resources
 | ||||||
|     if (SUCCEEDED(hr)) |     if (SUCCEEDED(hr)) | ||||||
|     { |     { | ||||||
|  | @ -114,6 +144,8 @@ void RendererImpl::Destroy() | ||||||
| { | { | ||||||
|     KGE_SYS_LOG("Destroying device resources"); |     KGE_SYS_LOG("Destroying device resources"); | ||||||
| 
 | 
 | ||||||
|  |     if (d2d_res_) | ||||||
|  |     { | ||||||
|         d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.Get()); |         d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.Get()); | ||||||
|         res_font_file_loader_.Reset(); |         res_font_file_loader_.Reset(); | ||||||
| 
 | 
 | ||||||
|  | @ -121,8 +153,14 @@ void RendererImpl::Destroy() | ||||||
|         res_font_collection_loader_.Reset(); |         res_font_collection_loader_.Reset(); | ||||||
| 
 | 
 | ||||||
|         render_ctx_.Reset(); |         render_ctx_.Reset(); | ||||||
|     d2d_res_.Reset(); |         d2d_res_->DiscardResources(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (d3d_res_) | ||||||
|  |     { | ||||||
|  |         d3d_res_->DiscardResources(); | ||||||
|         d3d_res_.Reset(); |         d3d_res_.Reset(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     ::CoUninitialize(); |     ::CoUninitialize(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -79,13 +79,13 @@ public: | ||||||
| 
 | 
 | ||||||
|     void Resize(uint32_t width, uint32_t height) override; |     void Resize(uint32_t width, uint32_t height) override; | ||||||
| 
 | 
 | ||||||
| protected: |  | ||||||
|     RendererImpl(); |  | ||||||
| 
 |  | ||||||
|     void MakeContextForWindow(WindowPtr window) override; |     void MakeContextForWindow(WindowPtr window) override; | ||||||
| 
 | 
 | ||||||
|     void Destroy() override; |     void Destroy() override; | ||||||
| 
 | 
 | ||||||
|  | protected: | ||||||
|  |     RendererImpl(); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     using ID2DDeviceResources = kiwano::graphics::directx::ID2DDeviceResources; |     using ID2DDeviceResources = kiwano::graphics::directx::ID2DDeviceResources; | ||||||
|     using ID3DDeviceResources = kiwano::graphics::directx::ID3DDeviceResources; |     using ID3DDeviceResources = kiwano::graphics::directx::ID3DDeviceResources; | ||||||
|  |  | ||||||
|  | @ -31,22 +31,6 @@ Renderer::Renderer() | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Renderer::SetupModule() |  | ||||||
| { |  | ||||||
|     WindowPtr window = Application::GetInstance().GetMainWindow(); |  | ||||||
|     MakeContextForWindow(window); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Renderer::DestroyModule() |  | ||||||
| { |  | ||||||
|     Destroy(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Renderer::HandleEvent(Event* evt) |  | ||||||
| { |  | ||||||
|     // DO NOTHING
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Renderer::BeginDraw() | void Renderer::BeginDraw() | ||||||
| { | { | ||||||
|     KGE_ASSERT(render_ctx_); |     KGE_ASSERT(render_ctx_); | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ namespace kiwano | ||||||
|  * \~chinese |  * \~chinese | ||||||
|  * @brief 渲染器 |  * @brief 渲染器 | ||||||
|  */ |  */ | ||||||
| class KGE_API Renderer : public EventModule | class KGE_API Renderer : public Noncopyable | ||||||
| { | { | ||||||
| public: | public: | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|  | @ -235,20 +235,17 @@ public: | ||||||
|     /// @throw kiwano::SystemError 呈现失败时抛出
 |     /// @throw kiwano::SystemError 呈现失败时抛出
 | ||||||
|     virtual void Present() = 0; |     virtual void Present() = 0; | ||||||
| 
 | 
 | ||||||
| public: |     /// \~chinese
 | ||||||
|     void SetupModule() override; |     /// @brief 为窗口创建渲染上下文
 | ||||||
|  |     virtual void MakeContextForWindow(WindowPtr window) = 0; | ||||||
| 
 | 
 | ||||||
|     void DestroyModule() override; |     /// \~chinese
 | ||||||
| 
 |     /// @brief 销毁渲染器资源
 | ||||||
|     void HandleEvent(Event* evt) override; |     virtual void Destroy() = 0; | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     Renderer(); |     Renderer(); | ||||||
| 
 | 
 | ||||||
|     virtual void MakeContextForWindow(WindowPtr window) = 0; |  | ||||||
| 
 |  | ||||||
|     virtual void Destroy() = 0; |  | ||||||
| 
 |  | ||||||
| protected: | protected: | ||||||
|     bool             vsync_; |     bool             vsync_; | ||||||
|     Color            clear_color_; |     Color            clear_color_; | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ StringView Trim(StringView str) | ||||||
|         while (std::isspace(str[end - 1])) |         while (std::isspace(str[end - 1])) | ||||||
|             --end; |             --end; | ||||||
| 
 | 
 | ||||||
|         if (end - start) |         if (end > start) | ||||||
|             return StringView(str.Data() + start, end - start); |             return StringView(str.Data() + start, end - start); | ||||||
|     } |     } | ||||||
|     return StringView(); |     return StringView(); | ||||||
|  | @ -158,6 +158,9 @@ bool ConfigIni::Save(std::ostream& os) | ||||||
|     std::sort(keys.begin(), keys.end()); |     std::sort(keys.begin(), keys.end()); | ||||||
| 
 | 
 | ||||||
|     // Output to ini
 |     // Output to ini
 | ||||||
|  |     std::ostream::sentry ok(os); | ||||||
|  |     if (ok) | ||||||
|  |     { | ||||||
|         for (const auto& key : keys) |         for (const auto& key : keys) | ||||||
|         { |         { | ||||||
|             os << '[' << key << ']' << std::endl; |             os << '[' << key << ']' << std::endl; | ||||||
|  | @ -167,7 +170,8 @@ bool ConfigIni::Save(std::ostream& os) | ||||||
|             } |             } | ||||||
|             os << std::endl; |             os << std::endl; | ||||||
|         } |         } | ||||||
|     return false; |     } | ||||||
|  |     return !os.fail(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ConfigIni::SectionMap ConfigIni::GetSectionMap() const | ConfigIni::SectionMap ConfigIni::GetSectionMap() const | ||||||
|  | @ -177,23 +181,20 @@ ConfigIni::SectionMap ConfigIni::GetSectionMap() const | ||||||
| 
 | 
 | ||||||
| ConfigIni::ValueMap ConfigIni::GetSection(const String& section) const | ConfigIni::ValueMap ConfigIni::GetSection(const String& section) const | ||||||
| { | { | ||||||
|     auto iter = sections_.find(section); |     if (HasSection(section)) | ||||||
|     if (iter != sections_.end()) |     { | ||||||
|         return iter->second; |         return sections_.at(section); | ||||||
|  |     } | ||||||
|     return ValueMap(); |     return ValueMap(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| String ConfigIni::GetString(const String& section_name, const String& key) const | String ConfigIni::GetString(const String& section, const String& key, const String& default_value) const | ||||||
| { | { | ||||||
|     if (HasSection(section_name)) |     if (HasKey(section, key)) | ||||||
|     { |     { | ||||||
|         const auto& section = sections_.at(section_name); |         return sections_.at(section).at(key); | ||||||
| 
 |  | ||||||
|         auto iter_key = section.find(key); |  | ||||||
|         if (iter_key != section.end()) |  | ||||||
|             return iter_key->second; |  | ||||||
|     } |     } | ||||||
|     return String(); |     return default_value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| float ConfigIni::GetFloat(const String& section, const String& key, float default_value) const | float ConfigIni::GetFloat(const String& section, const String& key, float default_value) const | ||||||
|  | @ -274,7 +275,7 @@ bool ConfigIni::HasSection(const String& section) const | ||||||
|     return !!sections_.count(section); |     return !!sections_.count(section); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ConfigIni::HasValue(const String& section, const String& key) const | bool ConfigIni::HasKey(const String& section, const String& key) const | ||||||
| { | { | ||||||
|     if (HasSection(section)) |     if (HasSection(section)) | ||||||
|     { |     { | ||||||
|  | @ -324,6 +325,22 @@ void ConfigIni::SetBool(const String& section, const String& key, bool value) | ||||||
|     SetString(section, key, value ? "true" : "false"); |     SetString(section, key, value ? "true" : "false"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ConfigIni::DeleteSection(const String& section) | ||||||
|  | { | ||||||
|  |     if (HasSection(section)) | ||||||
|  |     { | ||||||
|  |         sections_.erase(section); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ConfigIni::DeleteKey(const String& section, const String& key) | ||||||
|  | { | ||||||
|  |     if (HasKey(section, key)) | ||||||
|  |     { | ||||||
|  |         sections_.at(section).erase(key); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ConfigIni::ValueMap& ConfigIni::operator[](const String& section) | ConfigIni::ValueMap& ConfigIni::operator[](const String& section) | ||||||
| { | { | ||||||
|     if (!HasSection(section)) |     if (!HasSection(section)) | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief 键值字典
 |     /// @brief 键值字典
 | ||||||
|     typedef Map<String, String> ValueMap; |     typedef UnorderedMap<String, String> ValueMap; | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief Section字典
 |     /// @brief Section字典
 | ||||||
|  | @ -65,6 +65,17 @@ public: | ||||||
|     /// @param os 输出流
 |     /// @param os 输出流
 | ||||||
|     bool Save(std::ostream& os); |     bool Save(std::ostream& os); | ||||||
| 
 | 
 | ||||||
|  |     /// \~chinese
 | ||||||
|  |     /// @brief 是否存在section
 | ||||||
|  |     /// @param section section的名称
 | ||||||
|  |     bool HasSection(const String& section) const; | ||||||
|  | 
 | ||||||
|  |     /// \~chinese
 | ||||||
|  |     /// @brief 是否存在值
 | ||||||
|  |     /// @param section section的名称
 | ||||||
|  |     /// @param key key的名称
 | ||||||
|  |     bool HasKey(const String& section, const String& key) const; | ||||||
|  | 
 | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief 获取所有section
 |     /// @brief 获取所有section
 | ||||||
|     SectionMap GetSectionMap() const; |     SectionMap GetSectionMap() const; | ||||||
|  | @ -78,7 +89,7 @@ public: | ||||||
|     /// @brief 获取值
 |     /// @brief 获取值
 | ||||||
|     /// @param section section的名称
 |     /// @param section section的名称
 | ||||||
|     /// @param key key的名称
 |     /// @param key key的名称
 | ||||||
|     String GetString(const String& section, const String& key) const; |     String GetString(const String& section, const String& key, const String& default_value = String()) const; | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief 获取值
 |     /// @brief 获取值
 | ||||||
|  | @ -108,17 +119,6 @@ public: | ||||||
|     /// @param default_value 不存在时的默认值
 |     /// @param default_value 不存在时的默认值
 | ||||||
|     bool GetBool(const String& section, const String& key, bool default_value = false) const; |     bool GetBool(const String& section, const String& key, bool default_value = false) const; | ||||||
| 
 | 
 | ||||||
|     /// \~chinese
 |  | ||||||
|     /// @brief 是否存在section
 |  | ||||||
|     /// @param section section的名称
 |  | ||||||
|     bool HasSection(const String& section) const; |  | ||||||
| 
 |  | ||||||
|     /// \~chinese
 |  | ||||||
|     /// @brief 是否存在值
 |  | ||||||
|     /// @param section section的名称
 |  | ||||||
|     /// @param key key的名称
 |  | ||||||
|     bool HasValue(const String& section, const String& key) const; |  | ||||||
| 
 |  | ||||||
|     /// \~chinese
 |     /// \~chinese
 | ||||||
|     /// @brief 设置所有section
 |     /// @brief 设置所有section
 | ||||||
|     /// @param sections section字典
 |     /// @param sections section字典
 | ||||||
|  | @ -165,6 +165,17 @@ public: | ||||||
|     /// @param value 值
 |     /// @param value 值
 | ||||||
|     void SetBool(const String& section, const String& key, bool value); |     void SetBool(const String& section, const String& key, bool value); | ||||||
| 
 | 
 | ||||||
|  |     /// \~chinese
 | ||||||
|  |     /// @brief 删除section
 | ||||||
|  |     /// @param section section的名称
 | ||||||
|  |     void DeleteSection(const String& section); | ||||||
|  | 
 | ||||||
|  |     /// \~chinese
 | ||||||
|  |     /// @brief 删除值
 | ||||||
|  |     /// @param section section的名称
 | ||||||
|  |     /// @param key key的名称
 | ||||||
|  |     void DeleteKey(const String& section, const String& key); | ||||||
|  | 
 | ||||||
|     ValueMap& operator[](const String& section); |     ValueMap& operator[](const String& section); | ||||||
| 
 | 
 | ||||||
|     const ValueMap& operator[](const String& section) const; |     const ValueMap& operator[](const String& section) const; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue