diff --git a/.gitignore b/.gitignore index e430d78f..7c3945ca 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,13 @@ x64/ Debug/ Release/ +# CMake folders +/cmake-build-release/ +/cmake-build-debug/ + # Application folders .vs -.vscode +.idea # vs2010 ipch/ @@ -28,4 +32,8 @@ packages/ # Resources bin *.aps -docs/ \ No newline at end of file +# Mac cache files +.DS_Store + +# Documents +docs/ diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..de7425e9 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,32 @@ +{ + "configurations": [ + { + "name": "Mac", + "includePath": [ + "${workspaceFolder}/src/**" + ], + "defines": [ + "TARGET_OS_MAC" + ], + "macFrameworkPath": [ + "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks" + ], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++14", + "intelliSenseMode": "clang-x64" + }, + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/src/**" + ], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c11", + "cppStandard": "c++14", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..cfc8e1f0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "files.autoGuessEncoding": true, + "files.encoding": "gb2312" +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..cd27226e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.16) +project(Kiwano C CXX) + +set(CMAKE_CXX_STANDARD 17) + +if (WIN32) + message(STATUS "Building on Windows platform.") +elseif (APPLE) + message(STATUS "Building on MacOS platform.") + add_compile_definitions(TARGET_OS_MAC) +elseif (UNIX) + message(STATUS "Building on UNIX-like OS platform.") +endif () + +include_directories(src/3rd-party) +include_directories(src) + +add_subdirectory(src/kiwano) +add_subdirectory(src/kiwano-audio) +add_subdirectory(src/kiwano-imgui) +add_subdirectory(src/kiwano-network) +add_subdirectory(src/kiwano-physics) +add_subdirectory(src/3rd-party/Box2D) +add_subdirectory(src/3rd-party/curl) +add_subdirectory(src/3rd-party/nlohmann) +add_subdirectory(src/3rd-party/pugixml) diff --git a/Doxyfile b/Doxyfile index 8d683bfe..56599aa5 100644 --- a/Doxyfile +++ b/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- PROJECT_NAME = "Kiwano Engine" -PROJECT_NUMBER = v1.0.14 +PROJECT_NUMBER = v1.0.x PROJECT_BRIEF = PROJECT_LOGO = logo/logo_tiny.png @@ -81,6 +81,7 @@ HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = logo/favicon.ico GENERATE_TREEVIEW = YES ENUM_VALUES_PER_LINE = 4 diff --git a/logo/icon.ico b/logo/favicon.ico similarity index 100% rename from logo/icon.ico rename to logo/favicon.ico diff --git a/projects/kiwano/cpp.hint b/projects/kiwano/cpp.hint deleted file mode 100644 index 6e489168..00000000 --- a/projects/kiwano/cpp.hint +++ /dev/null @@ -1,5 +0,0 @@ -// 提示文件帮助 Visual Studio IDE 解释 Visual C++ 标识符, -// 如函数和宏的名称。 -// 有关详细信息,请参见 https://go.microsoft.com/fwlink/?linkid=865984 - -#define KGE_API diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index 06c49d61..06fa487e 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -5,58 +5,53 @@ - + - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - @@ -78,6 +73,7 @@ + @@ -86,6 +82,8 @@ + + @@ -98,51 +96,55 @@ + + + + + + + + - + - + - - - - + + + + + + + - - - - - - - - - - - - - + + + + + + @@ -160,6 +162,8 @@ + + @@ -170,8 +174,14 @@ + + + + + + @@ -185,7 +195,7 @@ - + {FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF} diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index 034a860a..9a950f94 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -22,15 +22,21 @@ {e84dcf9a-e650-473e-8c9c-193804ab9e76} - - {c629aedd-ffb9-4bc1-82c3-f50e77c82e77} - {adb44ca9-674a-4b77-993f-d65193d8ab06} {fd281702-0006-46d2-8fd1-28c502464164} + + {f514ae4f-2f6a-4d47-aa38-245628d6e01c} + + + {b0d28d20-bfaf-4816-8415-28c20ecf9fac} + + + {d15f4de1-7c2c-40d6-a3ce-68860b95a61e} + @@ -42,12 +48,6 @@ 2d - - core - - - core - core @@ -69,24 +69,12 @@ core - - core - - - core - 2d - - 2d - 2d - - 2d - 2d\action @@ -99,18 +87,12 @@ 2d\action - - 2d\action - 2d\action utils - - 2d - 2d @@ -123,12 +105,6 @@ 2d\action - - core - - - core - utils @@ -150,36 +126,12 @@ 2d - - core - platform\win32 platform\win32 - - core\event - - - core\event - - - core\event - - - core\event - - - core\event - - - 2d - - - core - core @@ -282,9 +234,6 @@ render - - core - platform @@ -297,12 +246,6 @@ core - - core - - - core - core @@ -315,9 +258,6 @@ render - - 2d - core @@ -327,6 +267,90 @@ core + + render + + + render + + + utils + + + utils + + + utils + + + utils + + + utils + + + utils + + + utils + + + 2d\action + + + render\DirectX + + + utils + + + base + + + base + + + base + + + base + + + event + + + event + + + event + + + event + + + event + + + event + + + event + + + event + + + 2d + + + base\component + + + base\component + + + base\component + @@ -338,36 +362,18 @@ 2d - - core - - - core - core platform - - core - - - core - 2d - - 2d - 2d - - 2d - 2d\action @@ -377,18 +383,12 @@ 2d\action - - 2d\action - 2d\action utils - - 2d - 2d @@ -401,12 +401,6 @@ 2d\action - - core - - - core - utils @@ -428,30 +422,9 @@ 2d - - core - platform\win32 - - core\event - - - core\event - - - core\event - - - core\event - - - 2d - - - core - platform\win32 @@ -521,9 +494,6 @@ render - - core - platform @@ -533,14 +503,80 @@ render - - 2d - core + + render + + + render + + + utils + + + utils + + + utils + + + utils + + + utils + + + 2d\action + + + utils + + + base + + + base + + + base + + + base + + + event + + + event + + + event + + + event + + + event + + + event + + + 2d + + + base\component + + + base\component + + + base\component + - + \ No newline at end of file diff --git a/projects/kiwano/suppress_warning.ruleset b/projects/kiwano/suppress_warning.ruleset new file mode 100644 index 00000000..f2abaa0a --- /dev/null +++ b/projects/kiwano/suppress_warning.ruleset @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/3rd-party/Box2D/CMakeLists.txt b/src/3rd-party/Box2D/CMakeLists.txt new file mode 100644 index 00000000..17f90b54 --- /dev/null +++ b/src/3rd-party/Box2D/CMakeLists.txt @@ -0,0 +1,98 @@ +include_directories(..) + +set(SOURCE_FILES + Collision/Shapes/b2ChainShape.cpp + Collision/Shapes/b2ChainShape.h + Collision/Shapes/b2CircleShape.cpp + Collision/Shapes/b2CircleShape.h + Collision/Shapes/b2EdgeShape.cpp + Collision/Shapes/b2EdgeShape.h + Collision/Shapes/b2PolygonShape.cpp + Collision/Shapes/b2PolygonShape.h + Collision/Shapes/b2Shape.h + Collision/b2BroadPhase.cpp + Collision/b2BroadPhase.h + Collision/b2CollideCircle.cpp + Collision/b2CollideEdge.cpp + Collision/b2CollidePolygon.cpp + Collision/b2Collision.cpp + Collision/b2Collision.h + Collision/b2Distance.cpp + Collision/b2Distance.h + Collision/b2DynamicTree.cpp + Collision/b2DynamicTree.h + Collision/b2TimeOfImpact.cpp + Collision/b2TimeOfImpact.h + Common/b2BlockAllocator.cpp + Common/b2BlockAllocator.h + Common/b2Draw.cpp + Common/b2Draw.h + Common/b2GrowableStack.h + Common/b2Math.cpp + Common/b2Math.h + Common/b2Settings.cpp + Common/b2Settings.h + Common/b2StackAllocator.cpp + Common/b2StackAllocator.h + Common/b2Timer.cpp + Common/b2Timer.h + Dynamics/Contacts/b2ChainAndCircleContact.cpp + Dynamics/Contacts/b2ChainAndCircleContact.h + Dynamics/Contacts/b2ChainAndPolygonContact.cpp + Dynamics/Contacts/b2ChainAndPolygonContact.h + Dynamics/Contacts/b2CircleContact.cpp + Dynamics/Contacts/b2CircleContact.h + Dynamics/Contacts/b2Contact.cpp + Dynamics/Contacts/b2Contact.h + Dynamics/Contacts/b2ContactSolver.cpp + Dynamics/Contacts/b2ContactSolver.h + Dynamics/Contacts/b2EdgeAndCircleContact.cpp + Dynamics/Contacts/b2EdgeAndCircleContact.h + Dynamics/Contacts/b2EdgeAndPolygonContact.cpp + Dynamics/Contacts/b2EdgeAndPolygonContact.h + Dynamics/Contacts/b2PolygonAndCircleContact.cpp + Dynamics/Contacts/b2PolygonAndCircleContact.h + Dynamics/Contacts/b2PolygonContact.cpp + Dynamics/Contacts/b2PolygonContact.h + Dynamics/Joints/b2DistanceJoint.cpp + Dynamics/Joints/b2DistanceJoint.h + Dynamics/Joints/b2FrictionJoint.cpp + Dynamics/Joints/b2FrictionJoint.h + Dynamics/Joints/b2GearJoint.cpp + Dynamics/Joints/b2GearJoint.h + Dynamics/Joints/b2Joint.cpp + Dynamics/Joints/b2Joint.h + Dynamics/Joints/b2MotorJoint.cpp + Dynamics/Joints/b2MotorJoint.h + Dynamics/Joints/b2MouseJoint.cpp + Dynamics/Joints/b2MouseJoint.h + Dynamics/Joints/b2PrismaticJoint.cpp + Dynamics/Joints/b2PrismaticJoint.h + Dynamics/Joints/b2PulleyJoint.cpp + Dynamics/Joints/b2PulleyJoint.h + Dynamics/Joints/b2RevoluteJoint.cpp + Dynamics/Joints/b2RevoluteJoint.h + Dynamics/Joints/b2RopeJoint.cpp + Dynamics/Joints/b2RopeJoint.h + Dynamics/Joints/b2WeldJoint.cpp + Dynamics/Joints/b2WeldJoint.h + Dynamics/Joints/b2WheelJoint.cpp + Dynamics/Joints/b2WheelJoint.h + Dynamics/b2Body.cpp + Dynamics/b2Body.h + Dynamics/b2ContactManager.cpp + Dynamics/b2ContactManager.h + Dynamics/b2Fixture.cpp + Dynamics/b2Fixture.h + Dynamics/b2Island.cpp + Dynamics/b2Island.h + Dynamics/b2TimeStep.h + Dynamics/b2World.cpp + Dynamics/b2World.h + Dynamics/b2WorldCallbacks.cpp + Dynamics/b2WorldCallbacks.h + Rope/b2Rope.cpp + Rope/b2Rope.h + Box2D.h) + +add_library(libbox2d ${SOURCE_FILES}) diff --git a/src/3rd-party/Box2D/Common/b2Math.h b/src/3rd-party/Box2D/Common/b2Math.h index 236c1a4a..ee6d56d7 100644 --- a/src/3rd-party/Box2D/Common/b2Math.h +++ b/src/3rd-party/Box2D/Common/b2Math.h @@ -20,7 +20,7 @@ #define B2_MATH_H #include "b2Settings.h" -#include +#include /// This function is used to ensure that a floating point number is not a NaN or infinity. inline bool b2IsValid(float32 x) diff --git a/src/3rd-party/curl/CMakeLists.txt b/src/3rd-party/curl/CMakeLists.txt new file mode 100644 index 00000000..523ca79c --- /dev/null +++ b/src/3rd-party/curl/CMakeLists.txt @@ -0,0 +1,18 @@ +include_directories(..) + +set(SOURCE_FILES + curl.h + curlbuild.h + curlrules.h + curlver.h + easy.h + mprintf.h + multi.h + stdcheaders.h + typecheck-gcc.h) + +add_library(libcurl ${SOURCE_FILES}) + +target_link_libraries(libcurl ./libs/libcurl.lib) + +set_target_properties(libcurl PROPERTIES LINKER_LANGUAGE CXX) diff --git a/src/3rd-party/imgui/CMakeLists.txt b/src/3rd-party/imgui/CMakeLists.txt new file mode 100644 index 00000000..50957205 --- /dev/null +++ b/src/3rd-party/imgui/CMakeLists.txt @@ -0,0 +1,15 @@ +include_directories(..) + +set(SOURCE_FILES + imconfig.h + imgui.cpp + imgui.h + imgui_demo.cpp + imgui_draw.cpp + imgui_internal.h + imgui_widgets.cpp + imstb_rectpack.h + imstb_textedit.h + imstb_truetype.h) + +add_library(libimgui ${SOURCE_FILES}) diff --git a/src/3rd-party/nlohmann/CMakeLists.txt b/src/3rd-party/nlohmann/CMakeLists.txt new file mode 100644 index 00000000..5d706720 --- /dev/null +++ b/src/3rd-party/nlohmann/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(..) + +set(SOURCE_FILES + json.hpp) + +add_library(libnlohmann ${SOURCE_FILES}) + +set_target_properties(libnlohmann PROPERTIES LINKER_LANGUAGE CXX) + diff --git a/src/3rd-party/pugixml/CMakeLists.txt b/src/3rd-party/pugixml/CMakeLists.txt new file mode 100644 index 00000000..d6a7efaf --- /dev/null +++ b/src/3rd-party/pugixml/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(..) + +set(SOURCE_FILES + pugiconfig.hpp + pugixml-impl.hpp + pugixml.hpp) + +add_library(libpugixml ${SOURCE_FILES}) + +set_target_properties(libpugixml PROPERTIES LINKER_LANGUAGE CXX) diff --git a/src/kiwano-audio/AudioModule.cpp b/src/kiwano-audio/AudioModule.cpp index 8b0fbeb2..d8d2c189 100644 --- a/src/kiwano-audio/AudioModule.cpp +++ b/src/kiwano-audio/AudioModule.cpp @@ -20,8 +20,8 @@ #include #include -#include #include +#include namespace kiwano { diff --git a/src/kiwano-audio/AudioModule.h b/src/kiwano-audio/AudioModule.h index 9d69c4de..a97e4078 100644 --- a/src/kiwano-audio/AudioModule.h +++ b/src/kiwano-audio/AudioModule.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include namespace kiwano diff --git a/src/kiwano-audio/CMakeLists.txt b/src/kiwano-audio/CMakeLists.txt new file mode 100644 index 00000000..eea58eeb --- /dev/null +++ b/src/kiwano-audio/CMakeLists.txt @@ -0,0 +1,16 @@ +include_directories(..) + +set(SOURCE_FILES + AudioModule.cpp + AudioModule.h + kiwano-audio.h + libraries.cpp + libraries.h + Sound.cpp + Sound.h + SoundPlayer.cpp + SoundPlayer.h + Transcoder.cpp + Transcoder.h) + +add_library(libkiwanoaudio ${SOURCE_FILES}) diff --git a/src/kiwano-audio/Sound.cpp b/src/kiwano-audio/Sound.cpp index f344e118..99a590c3 100644 --- a/src/kiwano-audio/Sound.cpp +++ b/src/kiwano-audio/Sound.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include namespace kiwano diff --git a/src/kiwano-audio/Sound.h b/src/kiwano-audio/Sound.h index 375da28d..299d9083 100644 --- a/src/kiwano-audio/Sound.h +++ b/src/kiwano-audio/Sound.h @@ -20,8 +20,8 @@ #pragma once #include -#include #include +#include #include #include diff --git a/src/kiwano-audio/SoundPlayer.h b/src/kiwano-audio/SoundPlayer.h index 62d4e25c..789c66b5 100644 --- a/src/kiwano-audio/SoundPlayer.h +++ b/src/kiwano-audio/SoundPlayer.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include namespace kiwano { diff --git a/src/kiwano-audio/Transcoder.cpp b/src/kiwano-audio/Transcoder.cpp index 64af27c7..448e999e 100644 --- a/src/kiwano-audio/Transcoder.cpp +++ b/src/kiwano-audio/Transcoder.cpp @@ -25,9 +25,8 @@ #include #include #include -#include #include -#include +#include #include #include diff --git a/src/kiwano-audio/libraries.cpp b/src/kiwano-audio/libraries.cpp index 9c124cd9..dc954079 100644 --- a/src/kiwano-audio/libraries.cpp +++ b/src/kiwano-audio/libraries.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include #include namespace kiwano diff --git a/src/kiwano-imgui/CMakeLists.txt b/src/kiwano-imgui/CMakeLists.txt new file mode 100644 index 00000000..6296cac1 --- /dev/null +++ b/src/kiwano-imgui/CMakeLists.txt @@ -0,0 +1,15 @@ +include_directories(..) + +set(SOURCE_FILES + imgui_impl/imgui_impl.h + imgui_impl/imgui_impl_dx10.cpp + imgui_impl/imgui_impl_dx10.h + imgui_impl/imgui_impl_dx11.cpp + imgui_impl/imgui_impl_dx11.h + ImGuiLayer.cpp + ImGuiLayer.h + ImGuiModule.cpp + ImGuiModule.h + kiwano-imgui.h) + +add_library(libkiwanoimgui ${SOURCE_FILES}) diff --git a/src/kiwano-imgui/ImGuiModule.cpp b/src/kiwano-imgui/ImGuiModule.cpp index 4d9763f9..d5025254 100644 --- a/src/kiwano-imgui/ImGuiModule.cpp +++ b/src/kiwano-imgui/ImGuiModule.cpp @@ -2,8 +2,7 @@ #include -#include -#include +#include #include #include #include diff --git a/src/kiwano-imgui/ImGuiModule.h b/src/kiwano-imgui/ImGuiModule.h index ce4ac610..b5c2d159 100644 --- a/src/kiwano-imgui/ImGuiModule.h +++ b/src/kiwano-imgui/ImGuiModule.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include namespace kiwano diff --git a/src/kiwano-imgui/imgui_impl/imgui_impl.h b/src/kiwano-imgui/imgui_impl/imgui_impl.h index bd98a2c5..24008337 100644 --- a/src/kiwano-imgui/imgui_impl/imgui_impl.h +++ b/src/kiwano-imgui/imgui_impl/imgui_impl.h @@ -7,13 +7,12 @@ #if !defined(KGE_USE_DIRECTX10) #include -#include +#include inline bool ImGui_Impl_Init() { - ::kiwano::RendererImpl& renderer = ::kiwano::RendererImpl::GetInstance(); - return ImGui_ImplDX11_Init(renderer.GetD3DDeviceResources()->GetDevice(), - renderer.GetD3DDeviceResources()->GetDeviceContext()); + auto d3d = kiwano::graphics::directx::GetD3DDeviceResources(); + return ImGui_ImplDX11_Init(d3d->GetDevice(), d3d->GetDeviceContext()); } inline void ImGui_Impl_Shutdown() @@ -44,11 +43,12 @@ inline bool ImGui_Impl_CreateDeviceObjects() #else #include +#include inline bool ImGui_Impl_Init() { - ::kiwano::RendererImpl& renderer = ::kiwano::RendererImpl::GetInstance(); - return ImGui_ImplDX10_Init(renderer.GetD3DDeviceResources()->GetDevice()); + auto d3d = kiwano::graphics::directx::GetD3DDeviceResources(); + return ImGui_ImplDX10_Init(d3d->GetDevice()); } inline void ImGui_Impl_Shutdown() diff --git a/src/kiwano-network/CMakeLists.txt b/src/kiwano-network/CMakeLists.txt new file mode 100644 index 00000000..f804e7ff --- /dev/null +++ b/src/kiwano-network/CMakeLists.txt @@ -0,0 +1,11 @@ +include_directories(..) + +set(SOURCE_FILES + HttpModule.cpp + HttpModule.h + HttpRequest.cpp + HttpRequest.h + HttpResponse.hpp + kiwano-network.h) + +add_library(libkiwanonetwork ${SOURCE_FILES}) diff --git a/src/kiwano-network/HttpModule.cpp b/src/kiwano-network/HttpModule.cpp index 6b3865e2..7bd9f26a 100644 --- a/src/kiwano-network/HttpModule.cpp +++ b/src/kiwano-network/HttpModule.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/kiwano-network/HttpModule.h b/src/kiwano-network/HttpModule.h index 59264e64..60d326d2 100644 --- a/src/kiwano-network/HttpModule.h +++ b/src/kiwano-network/HttpModule.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include namespace kiwano { diff --git a/src/kiwano-network/HttpRequest.h b/src/kiwano-network/HttpRequest.h index fe8bdd6c..1760c3ea 100644 --- a/src/kiwano-network/HttpRequest.h +++ b/src/kiwano-network/HttpRequest.h @@ -20,8 +20,8 @@ #pragma once #include -#include -#include +#include +#include namespace kiwano { diff --git a/src/kiwano-physics/CMakeLists.txt b/src/kiwano-physics/CMakeLists.txt new file mode 100644 index 00000000..7dabf36d --- /dev/null +++ b/src/kiwano-physics/CMakeLists.txt @@ -0,0 +1,25 @@ +include_directories(..) +include_directories(../3rd-party) + +set(SOURCE_FILES + Contact.cpp + Contact.h + ContactEdge.cpp + ContactEdge.h + ContactEvent.cpp + ContactEvent.h + Fixture.cpp + Fixture.h + Global.cpp + Global.h + Joint.cpp + Joint.h + kiwano-physics.h + PhysicBody.cpp + PhysicBody.h + PhysicWorld.cpp + PhysicWorld.h) + +add_library(libkiwanophysics ${SOURCE_FILES}) + +target_link_libraries(libkiwanophysics libbox2d) diff --git a/src/kiwano-physics/Global.cpp b/src/kiwano-physics/Global.cpp index ce6eeeba..4c6ee2da 100644 --- a/src/kiwano-physics/Global.cpp +++ b/src/kiwano-physics/Global.cpp @@ -18,7 +18,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#pragma once #include namespace kiwano diff --git a/src/kiwano-physics/PhysicWorld.cpp b/src/kiwano-physics/PhysicWorld.cpp index afe7406e..e97384b7 100644 --- a/src/kiwano-physics/PhysicWorld.cpp +++ b/src/kiwano-physics/PhysicWorld.cpp @@ -32,25 +32,23 @@ public: DebugDrawer(const Size& size) { canvas_ = Canvas::Create(size); + ctx_ = canvas_->GetContext2D(); fill_brush_ = Brush::Create(Color::White); line_brush_ = Brush::Create(Color::White); - canvas_->SetFillBrush(fill_brush_); - canvas_->SetStrokeBrush(line_brush_); - b2Draw::SetFlags(b2Draw::e_shapeBit | b2Draw::e_jointBit | b2Draw::e_jointBit | b2Draw::e_centerOfMassBit); } void BeginDraw() { - canvas_->BeginDraw(); - canvas_->Clear(); + ctx_->BeginDraw(); + ctx_->Clear(); } void EndDraw() { - canvas_->EndDraw(); + ctx_->EndDraw(); } void Render(RenderContext& ctx) @@ -61,11 +59,13 @@ public: void SetFillColor(const b2Color& color) { fill_brush_->SetColor(reinterpret_cast(color)); + ctx_->SetCurrentBrush(fill_brush_); } void SetLineColor(const b2Color& color) { line_brush_->SetColor(reinterpret_cast(color)); + ctx_->SetCurrentBrush(line_brush_); } void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override @@ -76,7 +76,7 @@ public: for (int32 i = 0; i < vertexCount; ++i) { b2Vec2 p2 = vertices[i]; - canvas_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2)); + ctx_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2)); p1 = p2; } } @@ -92,25 +92,25 @@ public: maker.EndPath(true); SetFillColor(color); - canvas_->FillShape(maker.GetShape()); + ctx_->FillShape(*maker.GetShape()); } void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) override { SetLineColor(color); - canvas_->DrawCircle(global::WorldToLocal(center), global::WorldToLocal(radius)); + ctx_->DrawCircle(global::WorldToLocal(center), global::WorldToLocal(radius)); } void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) override { SetFillColor(color); - canvas_->FillCircle(global::WorldToLocal(center), global::WorldToLocal(radius)); + ctx_->FillCircle(global::WorldToLocal(center), global::WorldToLocal(radius)); } void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override { SetLineColor(color); - canvas_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2)); + ctx_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2)); } void DrawTransform(const b2Transform& xf) override @@ -124,24 +124,25 @@ public: p2 = p1 + k_axisScale * xf.q.GetXAxis(); SetLineColor(red); - canvas_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2)); + ctx_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2)); p2 = p1 + k_axisScale * xf.q.GetYAxis(); SetLineColor(green); - canvas_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2)); + ctx_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2)); } void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color) override { SetFillColor(color); - canvas_->FillCircle(global::WorldToLocal(p), global::WorldToLocal(size)); + ctx_->FillCircle(global::WorldToLocal(p), global::WorldToLocal(size)); } private: - CanvasPtr canvas_; - BrushPtr fill_brush_; - BrushPtr line_brush_; + CanvasPtr canvas_; + RenderContextPtr ctx_; + BrushPtr fill_brush_; + BrushPtr line_brush_; }; class DestructionListener : public b2DestructionListener diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index 3eca99a6..5f54647c 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include namespace kiwano @@ -46,7 +46,8 @@ ActorPtr Actor::Create() } Actor::Actor() - : visible_(true) + : ComponentManager(this) + , visible_(true) , visible_in_rt_(true) , update_pausing_(false) , hover_(false) @@ -77,9 +78,9 @@ Actor::~Actor() void Actor::Update(Duration dt) { - UpdateActions(this, dt); - UpdateComponents(dt); - UpdateTimers(dt); + ActionScheduler::Update(this, dt); + TaskScheduler::Update(dt); + ComponentManager::Update(dt); if (!update_pausing_) { @@ -112,7 +113,7 @@ void Actor::Render(RenderContext& ctx) if (CheckVisibility(ctx)) { PrepareToRender(ctx); - RenderComponents(ctx); + ComponentManager::Render(ctx); OnRender(ctx); } } @@ -132,7 +133,7 @@ void Actor::Render(RenderContext& ctx) if (CheckVisibility(ctx)) { PrepareToRender(ctx); - RenderComponents(ctx); + ComponentManager::Render(ctx); OnRender(ctx); } @@ -242,19 +243,7 @@ void Actor::DoDeserialize(Deserializer* deserializer) bool Actor::HandleEvent(Event* evt) { - if (!components_.IsEmpty()) - { - ComponentPtr next; - for (auto component = components_.GetFirst(); component; component = next) - { - next = component->GetNext(); - - if (component->IsEnable()) - { - component->HandleEvent(evt); - } - } - } + ComponentManager::DispatchToComponents(evt); if (!EventDispatcher::DispatchEvent(evt)) return false; @@ -304,40 +293,6 @@ bool Actor::HandleEvent(Event* evt) return true; } -void Actor::UpdateComponents(Duration dt) -{ - if (!components_.IsEmpty()) - { - ComponentPtr next; - for (auto component = components_.GetFirst(); component; component = next) - { - next = component->GetNext(); - - if (component->IsEnable()) - { - component->OnUpdate(dt); - } - } - } -} - -void Actor::RenderComponents(RenderContext& ctx) -{ - if (!components_.IsEmpty()) - { - ComponentPtr next; - for (auto component = components_.GetFirst(); component; component = next) - { - next = component->GetNext(); - - if (component->IsEnable()) - { - component->OnRender(ctx); - } - } - } -} - const Matrix3x2& Actor::GetTransformMatrix() const { UpdateTransform(); @@ -657,72 +612,6 @@ void Actor::RemoveFromParent() } } -Component* Actor::AddComponent(ComponentPtr component) -{ - KGE_ASSERT(component && "AddComponent failed, NULL pointer exception"); - - if (component) - { - component->InitComponent(this); - components_.PushBack(component); - } - return component.Get(); -} - -ComponentList& Actor::GetAllComponents() -{ - return components_; -} - -const ComponentList& Actor::GetAllComponents() const -{ - return components_; -} - -void Actor::RemoveComponent(ComponentPtr component) -{ - auto iter = std::find(components_.begin(), components_.end(), component); - if (iter != components_.end()) - { - component->DestroyComponent(); - components_.Remove(component); - } -} - -void Actor::RemoveComponents(const String& name) -{ - if (!components_.IsEmpty()) - { - ComponentPtr next; - for (auto component = components_.GetFirst(); component; component = next) - { - next = component->GetNext(); - - if (component->IsName(name)) - { - component->DestroyComponent(); - components_.Remove(component); - } - } - } -} - -void Actor::RemoveAllComponents() -{ - // Destroy all components - if (!components_.IsEmpty()) - { - ComponentPtr next; - for (auto component = components_.GetFirst(); component; component = next) - { - next = component->GetNext(); - - component->DestroyComponent(); - } - } - components_.Clear(); -} - void Actor::RemoveChild(ActorPtr child) { KGE_ASSERT(child && "Actor::RemoveChild failed, NULL pointer exception"); diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h index 459f1f34..f0e258a0 100644 --- a/src/kiwano/2d/Actor.h +++ b/src/kiwano/2d/Actor.h @@ -19,13 +19,13 @@ // THE SOFTWARE. #pragma once -#include -#include -#include -#include #include -#include -#include +#include +#include +#include +#include +#include +#include namespace kiwano { @@ -58,13 +58,14 @@ typedef IntrusiveList ActorList; * \~chinese * @brief ɫ * @details - * ɫ̨ԪأȾ¡¼ַȹܵСλҲǶʱ¼ȹܵ + * ɫ̨ԪأȾ¡¼ַȹܵСλҲǶ¼ȹܵ */ class KGE_API Actor : public ObjectBase - , public TimerManager - , public ActionManager + , public TaskScheduler + , public ActionScheduler , public EventDispatcher + , public ComponentManager , protected IntrusiveListValue { friend class Director; @@ -370,32 +371,6 @@ public: /// @brief ӸɫƳ void RemoveFromParent(); - /// \~chinese - /// @brief - /// @param component - Component* AddComponent(ComponentPtr component); - - /// \~chinese - /// @brief ȡ - ComponentList& GetAllComponents(); - - /// \~chinese - /// @brief ȡ - const ComponentList& GetAllComponents() const; - - /// \~chinese - /// @brief Ƴ - void RemoveComponent(ComponentPtr component); - - /// \~chinese - /// @brief Ƴ - /// @param name - void RemoveComponents(const String& name); - - /// \~chinese - /// @brief Ƴ - void RemoveAllComponents(); - /// \~chinese /// @brief ͣɫ void PauseUpdating(); @@ -499,14 +474,6 @@ protected: /// @brief ¼ bool HandleEvent(Event* evt); - /// \~chinese - /// @brief - void UpdateComponents(Duration dt); - - /// \~chinese - /// @brief Ⱦ - void RenderComponents(RenderContext& ctx); - private: bool visible_; bool update_pausing_; @@ -524,7 +491,6 @@ private: Point anchor_; Size size_; ActorList children_; - ComponentList components_; UpdateCallback cb_update_; Transform transform_; diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp index 661c4e60..aa9a0694 100644 --- a/src/kiwano/2d/Canvas.cpp +++ b/src/kiwano/2d/Canvas.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include namespace kiwano { @@ -42,20 +42,11 @@ CanvasPtr Canvas::Create(const Size& size) return ptr; } -Canvas::Canvas() -{ -} +Canvas::Canvas() {} -void Canvas::BeginDraw() +RenderContextPtr Canvas::GetContext2D() const { - KGE_ASSERT(render_ctx_); - render_ctx_->BeginDraw(); -} - -void Canvas::EndDraw() -{ - KGE_ASSERT(render_ctx_); - render_ctx_->EndDraw(); + return render_ctx_; } void Canvas::OnRender(RenderContext& ctx) @@ -66,232 +57,6 @@ void Canvas::OnRender(RenderContext& ctx) } } -void Canvas::SetBrush(BrushPtr brush) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(brush); -} - -void Canvas::SetBrushTransform(const Transform& transform) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetTransform(transform.ToMatrix()); -} - -void Canvas::SetBrushTransform(const Matrix3x2& transform) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetTransform(transform); -} - -void Canvas::PushLayer(LayerPtr layer) -{ - KGE_ASSERT(render_ctx_); - if (layer) - { - render_ctx_->PushLayer(*layer); - } -} - -void Canvas::PopLayer() -{ - KGE_ASSERT(render_ctx_); - render_ctx_->PopLayer(); -} - -void Canvas::PushClipRect(const Rect& clip_rect) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->PushClipRect(clip_rect); -} - -void Canvas::PopClipRect() -{ - KGE_ASSERT(render_ctx_); - render_ctx_->PopClipRect(); -} - -void Canvas::DrawShape(ShapePtr shape) -{ - KGE_ASSERT(render_ctx_); - if (shape) - { - render_ctx_->SetCurrentBrush(stroke_brush_); - render_ctx_->SetCurrentStrokeStyle(stroke_style_); - render_ctx_->DrawShape(*shape); - } -} - -void Canvas::DrawLine(const Point& begin, const Point& end) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(stroke_brush_); - render_ctx_->SetCurrentStrokeStyle(stroke_style_); - render_ctx_->DrawLine(begin, end); -} - -void Canvas::DrawCircle(const Point& center, float radius) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(stroke_brush_); - render_ctx_->SetCurrentStrokeStyle(stroke_style_); - render_ctx_->DrawEllipse(center, Vec2(radius, radius)); -} - -void Canvas::DrawEllipse(const Point& center, const Vec2& radius) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(stroke_brush_); - render_ctx_->SetCurrentStrokeStyle(stroke_style_); - render_ctx_->DrawEllipse(center, radius); -} - -void Canvas::DrawRect(const Rect& rect) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(stroke_brush_); - render_ctx_->SetCurrentStrokeStyle(stroke_style_); - render_ctx_->DrawRectangle(rect); -} - -void Canvas::DrawRoundedRect(const Rect& rect, const Vec2& radius) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(stroke_brush_); - render_ctx_->SetCurrentStrokeStyle(stroke_style_); - render_ctx_->DrawRoundedRectangle(rect, radius); -} - -void Canvas::FillShape(ShapePtr shape) -{ - KGE_ASSERT(render_ctx_); - if (shape) - { - render_ctx_->SetCurrentBrush(fill_brush_); - render_ctx_->FillShape(*shape); - } -} - -void Canvas::FillCircle(const Point& center, float radius) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(fill_brush_); - render_ctx_->FillEllipse(center, Vec2(radius, radius)); -} - -void Canvas::FillEllipse(const Point& center, const Vec2& radius) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(fill_brush_); - render_ctx_->FillEllipse(center, radius); -} - -void Canvas::FillRect(const Rect& rect) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(fill_brush_); - render_ctx_->FillRectangle(rect); -} - -void Canvas::FillRoundedRect(const Rect& rect, const Vec2& radius) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(fill_brush_); - render_ctx_->FillRoundedRectangle(rect, radius); -} - -void Canvas::DrawFrame(FramePtr frame, const Point& pos) -{ - KGE_ASSERT(render_ctx_); - if (frame && frame->IsValid()) - { - render_ctx_->DrawTexture(*frame->GetTexture(), &frame->GetCropRect(), &Rect(pos, frame->GetSize())); - } -} - -void Canvas::DrawFrame(FramePtr frame, const Point& pos, const Size& size) -{ - KGE_ASSERT(render_ctx_); - if (frame && frame->IsValid()) - { - render_ctx_->DrawTexture(*frame->GetTexture(), &frame->GetCropRect(), &Rect(pos, size)); - } -} - -void Canvas::DrawTextLayout(const String& text, const TextStyle& style, const Point& point) -{ - if (text.empty()) - return; - - DrawTextLayout(TextLayout::Create(text, style), point); -} - -void Canvas::DrawTextLayout(TextLayoutPtr layout, const Point& point) -{ - KGE_ASSERT(render_ctx_); - if (layout) - { - render_ctx_->DrawTextLayout(*layout, point); - } -} - -void Canvas::BeginPath(const Point& begin_pos) -{ - shape_maker_.BeginPath(begin_pos); -} - -void Canvas::EndPath(bool closed) -{ - shape_maker_.EndPath(closed); -} - -void Canvas::AddLine(const Point& point) -{ - shape_maker_.AddLine(point); -} - -void Canvas::AddLines(const Vector& points) -{ - shape_maker_.AddLines(points); -} - -void Canvas::AddBezier(const Point& point1, const Point& point2, const Point& point3) -{ - shape_maker_.AddBezier(point1, point2, point3); -} - -void Canvas::AddArc(const Point& point, const Size& radius, float rotation, bool clockwise, bool is_small) -{ - shape_maker_.AddArc(point, radius, rotation, clockwise, is_small); -} - -void Canvas::StrokePath() -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(stroke_brush_); - render_ctx_->SetCurrentStrokeStyle(stroke_style_); - render_ctx_->DrawShape(*shape_maker_.GetShape()); -} - -void Canvas::FillPath() -{ - KGE_ASSERT(render_ctx_); - render_ctx_->SetCurrentBrush(fill_brush_); - render_ctx_->FillShape(*shape_maker_.GetShape()); -} - -void Canvas::Clear() -{ - KGE_ASSERT(render_ctx_); - render_ctx_->Clear(); -} - -void Canvas::Clear(const Color& clear_color) -{ - KGE_ASSERT(render_ctx_); - render_ctx_->Clear(clear_color); -} - void Canvas::ResizeAndClear(Size size) { texture_cached_ = memory::New(); diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h index 2c8b46b2..f0f147f0 100644 --- a/src/kiwano/2d/Canvas.h +++ b/src/kiwano/2d/Canvas.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include #include @@ -48,222 +48,12 @@ public: static CanvasPtr Create(const Size& size); /// \~chinese - /// @brief ʼͼ - void BeginDraw(); - - /// \~chinese - /// @brief ͼ - void EndDraw(); - - /// \~chinese - /// @brief ״ - /// @param shape ״ - void DrawShape(ShapePtr shape); - - /// \~chinese - /// @brief ߶ - /// @param begin ߶ - /// @param end ߶յ - void DrawLine(const Point& begin, const Point& end); - - /// \~chinese - /// @brief Բα߿ - /// @param center Բԭ - /// @param radius Բΰ뾶 - void DrawCircle(const Point& center, float radius); - - /// \~chinese - /// @brief Բα߿ - /// @param center Բԭ - /// @param radius Բ뾶 - void DrawEllipse(const Point& center, const Vec2& radius); - - /// \~chinese - /// @brief α߿ - /// @param rect - void DrawRect(const Rect& rect); - - /// \~chinese - /// @brief ԲǾα߿ - /// @param rect - /// @param radius Բǰ뾶 - void DrawRoundedRect(const Rect& rect, const Vec2& radius); - - /// \~chinese - /// @brief ״ - /// @param shape ״ - void FillShape(ShapePtr shape); - - /// \~chinese - /// @brief Բ - /// @param center Բԭ - /// @param radius Բΰ뾶 - void FillCircle(const Point& center, float radius); - - /// \~chinese - /// @brief Բ - /// @param center Բԭ - /// @param radius Բ뾶 - void FillEllipse(const Point& center, const Vec2& radius); - - /// \~chinese - /// @brief - /// @param rect - void FillRect(const Rect& rect); - - /// \~chinese - /// @brief ԲǾ - /// @param rect - /// @param radius Բǰ뾶 - void FillRoundedRect(const Rect& rect, const Vec2& radius); - - /// \~chinese - /// @brief ͼ֡ - /// @param frame ͼ֡ - /// @param pos ͼλ - void DrawFrame(FramePtr frame, const Point& pos); - - /// \~chinese - /// @brief ͼ֡ - /// @param frame ͼ֡ - /// @param pos ͼλ - /// @param size ȾͼС - void DrawFrame(FramePtr frame, const Point& pos, const Size& size); - - /// \~chinese - /// @brief ֲ - /// @param text - /// @param style ʽ - /// @param point ֵλ - void DrawTextLayout(const String& text, const TextStyle& style, const Point& point); - - /// \~chinese - /// @brief ֲ - /// @param layout ֲ - /// @param point Ʋֵλ - void DrawTextLayout(TextLayoutPtr layout, const Point& point); - - /// \~chinese - /// @brief ʼ· - /// @param begin_pos ·ʼ - void BeginPath(const Point& begin_pos); - - /// \~chinese - /// @brief · - /// @param closed ·Ƿպ - void EndPath(bool closed = false); - - /// \~chinese - /// @brief һ߶ - /// @param point ˵ - void AddLine(const Point& point); - - /// \~chinese - /// @brief Ӷ߶ - /// @param points ˵㼯 - void AddLines(const Vector& points); - - /// \~chinese - /// @brief һη - /// @param point1 ߵĵһƵ - /// @param point2 ߵĵڶƵ - /// @param point3 ߵյ - void AddBezier(const Point& point1, const Point& point2, const Point& point3); - - /// \~chinese - /// @brief ӻ - /// @param point յ - /// @param radius Բ뾶 - /// @param rotation ԲתǶ - /// @param clockwise ˳ʱ or ʱ - /// @param is_small ǷȡС 180 Ļ - void AddArc(const Point& point, const Size& radius, float rotation, bool clockwise = true, bool is_small = true); - - /// \~chinese - /// @brief ߵķʽ· - void StrokePath(); - - /// \~chinese - /// @brief ķʽ· - void FillPath(); - - /// \~chinese - /// @brief ջ - void Clear(); - - /// \~chinese - /// @brief ջ - /// @param clear_color ɫ - void Clear(const Color& clear_color); - - /// \~chinese - /// @brief ɫ - /// @param color ɫ - void SetFillColor(const Color& color); - - /// \~chinese - /// @brief 仭ˢ - /// @param[in] brush 仭ˢ - void SetFillBrush(BrushPtr brush); - - /// \~chinese - /// @brief ɫ - /// @param color ɫ - void SetStrokeColor(const Color& color); - - /// \~chinese - /// @brief ˢ - /// @param[in] brush ˢ - void SetStrokeBrush(BrushPtr brush); - - /// \~chinese - /// @brief ʽ - /// @param stroke_style ʽ - void SetStrokeStyle(StrokeStylePtr stroke_style); - - /// \~chinese - /// @brief ûˢ - /// @param[in] brush ˢ - void SetBrush(BrushPtr brush); - - /// \~chinese - /// @brief ûˢά任 - /// @param transform ά任 - void SetBrushTransform(const Transform& transform); - - /// \~chinese - /// @brief ûˢά任 - /// @param transform ά任 - void SetBrushTransform(const Matrix3x2& transform); - - /// \~chinese - /// @brief һͼ - /// @param layer ͼ - void PushLayer(LayerPtr layer); - - /// \~chinese - /// @brief ɾӵͼ - void PopLayer(); - - /// \~chinese - /// @brief һü - /// @param clip_rect ü - void PushClipRect(const Rect& clip_rect); - - /// \~chinese - /// @brief ɾӵIJü - void PopClipRect(); - - /// \~chinese - /// @brief ȡ仭ˢ - BrushPtr GetFillBrush() const; - - /// \~chinese - /// @brief ȡˢ - BrushPtr GetStrokeBrush() const; + /// @brief ȡ2Dͼ + RenderContextPtr GetContext2D() const; /// \~chinese /// @brief ջС軭С + /// @warning úᵼԭͼʧЧ void ResizeAndClear(Size size); /// \~chinese @@ -276,57 +66,10 @@ private: Canvas(); private: - StrokeStylePtr stroke_style_; - ShapeMaker shape_maker_; - BrushPtr fill_brush_; - BrushPtr stroke_brush_; TexturePtr texture_cached_; RenderContextPtr render_ctx_; }; /** @} */ -inline void Canvas::SetStrokeStyle(StrokeStylePtr stroke_style) -{ - stroke_style_ = stroke_style; -} - -inline void Canvas::SetStrokeColor(const Color& color) -{ - if (!stroke_brush_) - { - stroke_brush_ = memory::New(); - } - stroke_brush_->SetColor(color); -} - -inline void Canvas::SetFillColor(const Color& color) -{ - if (!fill_brush_) - { - fill_brush_ = memory::New(); - } - fill_brush_->SetColor(color); -} - -inline void Canvas::SetFillBrush(BrushPtr brush) -{ - fill_brush_ = brush; -} - -inline void Canvas::SetStrokeBrush(BrushPtr brush) -{ - stroke_brush_ = brush; -} - -inline BrushPtr Canvas::GetFillBrush() const -{ - return fill_brush_; -} - -inline BrushPtr Canvas::GetStrokeBrush() const -{ - return stroke_brush_; -} - } // namespace kiwano diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index 65d78975..9e39f268 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include #include #include diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp index a9714e48..5186451a 100644 --- a/src/kiwano/2d/ShapeActor.cpp +++ b/src/kiwano/2d/ShapeActor.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include #include namespace kiwano diff --git a/src/kiwano/2d/Sprite.h b/src/kiwano/2d/Sprite.h index dbadbc6f..934abbac 100644 --- a/src/kiwano/2d/Sprite.h +++ b/src/kiwano/2d/Sprite.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include namespace kiwano { diff --git a/src/kiwano/2d/Stage.cpp b/src/kiwano/2d/Stage.cpp index 24ae8606..ad4b3d36 100644 --- a/src/kiwano/2d/Stage.cpp +++ b/src/kiwano/2d/Stage.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include #include namespace kiwano diff --git a/src/kiwano/2d/TextActor.cpp b/src/kiwano/2d/TextActor.cpp index 5c8b7ea4..dfe0010d 100644 --- a/src/kiwano/2d/TextActor.cpp +++ b/src/kiwano/2d/TextActor.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include #include namespace kiwano diff --git a/src/kiwano/2d/Transition.cpp b/src/kiwano/2d/Transition.cpp index d831bc10..acf0c722 100644 --- a/src/kiwano/2d/Transition.cpp +++ b/src/kiwano/2d/Transition.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/kiwano/2d/action/Action.cpp b/src/kiwano/2d/action/Action.cpp index 6dc75105..796fc25b 100644 --- a/src/kiwano/2d/action/Action.cpp +++ b/src/kiwano/2d/action/Action.cpp @@ -65,6 +65,9 @@ void Action::UpdateStep(Actor* target, Duration dt) case Status::Started: Update(target, dt); break; + + default: + break; } if (status_ == Status::Done) diff --git a/src/kiwano/2d/action/Action.h b/src/kiwano/2d/action/Action.h index f8d79e4a..0de9a0a4 100644 --- a/src/kiwano/2d/action/Action.h +++ b/src/kiwano/2d/action/Action.h @@ -21,7 +21,7 @@ #pragma once #include #include -#include +#include #include #include #include @@ -30,14 +30,10 @@ namespace kiwano { class Actor; -class ActionManager; +class ActionScheduler; KGE_DECLARE_SMART_PTR(Action); -/// \~chinese -/// @brief б -typedef IntrusiveList ActionList; - /** * \~chinese * \defgroup Actions @@ -55,7 +51,7 @@ class KGE_API Action , public Cloneable , protected IntrusiveListValue { - friend class ActionManager; + friend class ActionScheduler; friend class ActionGroup; friend IntrusiveList; diff --git a/src/kiwano/2d/action/ActionGroup.cpp b/src/kiwano/2d/action/ActionGroup.cpp index 520065c3..3aa633d5 100644 --- a/src/kiwano/2d/action/ActionGroup.cpp +++ b/src/kiwano/2d/action/ActionGroup.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include namespace kiwano { diff --git a/src/kiwano/2d/action/ActionManager.cpp b/src/kiwano/2d/action/ActionScheduler.cpp similarity index 84% rename from src/kiwano/2d/action/ActionManager.cpp rename to src/kiwano/2d/action/ActionScheduler.cpp index 8c79bfe2..4e1fb3fb 100644 --- a/src/kiwano/2d/action/ActionManager.cpp +++ b/src/kiwano/2d/action/ActionScheduler.cpp @@ -19,12 +19,13 @@ // THE SOFTWARE. #include -#include -#include +#include +#include namespace kiwano { -void ActionManager::UpdateActions(Actor* target, Duration dt) + +void ActionScheduler::Update(Actor* target, Duration dt) { if (actions_.IsEmpty() || !target) return; @@ -42,7 +43,7 @@ void ActionManager::UpdateActions(Actor* target, Duration dt) } } -Action* ActionManager::AddAction(ActionPtr action) +Action* ActionScheduler::AddAction(ActionPtr action) { KGE_ASSERT(action && "AddAction failed, NULL pointer exception"); @@ -53,7 +54,7 @@ Action* ActionManager::AddAction(ActionPtr action) return action.Get(); } -void ActionManager::ResumeAllActions() +void ActionScheduler::ResumeAllActions() { if (actions_.IsEmpty()) return; @@ -64,7 +65,7 @@ void ActionManager::ResumeAllActions() } } -void ActionManager::PauseAllActions() +void ActionScheduler::PauseAllActions() { if (actions_.IsEmpty()) return; @@ -75,7 +76,7 @@ void ActionManager::PauseAllActions() } } -void ActionManager::StopAllActions() +void ActionScheduler::StopAllActions() { if (actions_.IsEmpty()) return; @@ -86,7 +87,7 @@ void ActionManager::StopAllActions() } } -ActionPtr ActionManager::GetAction(const String& name) +ActionPtr ActionScheduler::GetAction(const String& name) { if (actions_.IsEmpty()) return nullptr; @@ -97,7 +98,7 @@ ActionPtr ActionManager::GetAction(const String& name) return nullptr; } -const ActionList& ActionManager::GetAllActions() const +const ActionList& ActionScheduler::GetAllActions() const { return actions_; } diff --git a/src/kiwano/2d/action/ActionManager.h b/src/kiwano/2d/action/ActionScheduler.h similarity index 91% rename from src/kiwano/2d/action/ActionManager.h rename to src/kiwano/2d/action/ActionScheduler.h index 841a4611..1cc4f26f 100644 --- a/src/kiwano/2d/action/ActionManager.h +++ b/src/kiwano/2d/action/ActionScheduler.h @@ -23,16 +23,21 @@ namespace kiwano { + /** * \addtogroup Actions * @{ */ +/// \~chinese +/// @brief б +typedef IntrusiveList ActionList; + /** * \~chinese - * @brief + * @brief */ -class KGE_API ActionManager +class KGE_API ActionScheduler { public: /// \~chinese @@ -60,10 +65,9 @@ public: /// @brief ȡж const ActionList& GetAllActions() const; -protected: /// \~chinese /// @brief ¶ - void UpdateActions(Actor* target, Duration dt); + void Update(Actor* target, Duration dt); private: ActionList actions_; diff --git a/src/kiwano/2d/action/ActionTween.h b/src/kiwano/2d/action/ActionTween.h index 6f271cd9..82b777ed 100644 --- a/src/kiwano/2d/action/ActionTween.h +++ b/src/kiwano/2d/action/ActionTween.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include namespace kiwano { diff --git a/src/kiwano/2d/action/Animation.cpp b/src/kiwano/2d/action/Animation.cpp index 1abdaae1..bb52344a 100644 --- a/src/kiwano/2d/action/Animation.cpp +++ b/src/kiwano/2d/action/Animation.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include #include diff --git a/src/kiwano/2d/action/Animation.h b/src/kiwano/2d/action/Animation.h index 769b7386..7e991c72 100644 --- a/src/kiwano/2d/action/Animation.h +++ b/src/kiwano/2d/action/Animation.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include #include namespace kiwano diff --git a/src/kiwano/CMakeLists.txt b/src/kiwano/CMakeLists.txt new file mode 100644 index 00000000..cbb8d953 --- /dev/null +++ b/src/kiwano/CMakeLists.txt @@ -0,0 +1,175 @@ +include_directories(..) + +set(SOURCE_FILES + 2d/action/Action.cpp + 2d/action/Action.h + 2d/action/ActionDelay.cpp + 2d/action/ActionDelay.h + 2d/action/ActionGroup.cpp + 2d/action/ActionGroup.h + 2d/action/ActionHelper.h + 2d/action/ActionManager.cpp + 2d/action/ActionManager.h + 2d/action/ActionTween.cpp + 2d/action/ActionTween.h + 2d/action/ActionWalk.cpp + 2d/action/ActionWalk.h + 2d/action/Animation.cpp + 2d/action/Animation.h + 2d/Actor.cpp + 2d/Actor.h + 2d/Button.cpp + 2d/Button.h + 2d/Canvas.cpp + 2d/Canvas.h + 2d/Component.cpp + 2d/Component.h + 2d/DebugActor.cpp + 2d/DebugActor.h + 2d/GifSprite.cpp + 2d/GifSprite.h + 2d/LayerActor.cpp + 2d/LayerActor.h + 2d/ShapeActor.cpp + 2d/ShapeActor.h + 2d/Sprite.cpp + 2d/Sprite.h + 2d/Stage.cpp + 2d/Stage.h + 2d/TextActor.cpp + 2d/TextActor.h + 2d/Transition.cpp + 2d/Transition.h + core/event/Event.cpp + core/event/Event.h + core/event/EventType.h + core/event/KeyEvent.cpp + core/event/KeyEvent.h + core/event/MouseEvent.cpp + core/event/MouseEvent.h + core/event/WindowEvent.cpp + core/event/WindowEvent.h + core/Allocator.cpp + core/Allocator.h + core/Any.h + core/Cloneable.h + core/Common.h + core/Director.cpp + core/Director.h + core/EventDispatcher.cpp + core/EventDispatcher.h + core/EventListener.cpp + core/EventListener.h + core/Exception.cpp + core/Exception.h + core/Function.h + core/IntrusiveList.h + core/Json.h + core/Keys.h + core/Library.cpp + core/Library.h + core/Logger.cpp + core/Logger.h + core/Module.cpp + core/Module.h + core/ObjectBase.cpp + core/ObjectBase.h + core/RefCounter.cpp + core/RefCounter.h + core/Resource.cpp + core/Resource.h + core/Serializable.h + core/Singleton.h + core/SmartPtr.hpp + core/String.cpp + core/String.h + core/Time.cpp + core/Time.h + core/Timer.cpp + core/Timer.h + core/TimerManager.cpp + core/TimerManager.h + core/Xml.h + math/Constants.h + math/EaseFunctions.h + math/Math.h + math/Matrix.hpp + math/Random.h + math/Rect.hpp + math/Scalar.h + math/Transform.hpp + math/Vec2.hpp + platform/win32/ComPtr.hpp + platform/win32/libraries.cpp + platform/win32/libraries.h + platform/win32/WindowImpl.cpp + platform/Application.cpp + platform/Application.h + platform/FileSystem.cpp + platform/FileSystem.h + platform/Input.cpp + platform/Input.h + platform/Runner.cpp + platform/Runner.h + platform/Window.cpp + platform/Window.h + render/DirectX/D2DDeviceResources.cpp + render/DirectX/D2DDeviceResources.h + render/DirectX/D3D10DeviceResources.cpp + render/DirectX/D3D10DeviceResources.h + render/DirectX/D3D11DeviceResources.cpp + render/DirectX/D3D11DeviceResources.h + render/DirectX/D3DDeviceResourcesBase.h + render/DirectX/FontCollectionLoader.cpp + render/DirectX/FontCollectionLoader.h + render/DirectX/helper.h + render/DirectX/NativePtr.h + render/DirectX/RenderContextImpl.cpp + render/DirectX/RenderContextImpl.h + render/DirectX/RendererImpl.cpp + render/DirectX/RendererImpl.h + render/DirectX/TextRenderer.cpp + render/DirectX/TextRenderer.h + render/Brush.cpp + render/Brush.h + render/Color.cpp + render/Color.h + render/Font.cpp + render/Font.h + render/Frame.cpp + render/Frame.h + render/FrameSequence.cpp + render/FrameSequence.h + render/GifImage.cpp + render/GifImage.h + render/Layer.cpp + render/Layer.h + render/NativeObject.h + render/RenderContext.cpp + render/RenderContext.h + render/Renderer.cpp + render/Renderer.h + render/Shape.cpp + render/Shape.h + render/ShapeMaker.cpp + render/ShapeMaker.h + render/StrokeStyle.cpp + render/StrokeStyle.h + render/TextLayout.cpp + render/TextLayout.h + render/TextStyle.hpp + render/Texture.cpp + render/Texture.h + render/TextureCache.cpp + render/TextureCache.h + utils/LocalStorage.cpp + utils/LocalStorage.h + utils/ResourceCache.cpp + utils/ResourceCache.h + utils/UserData.cpp + utils/UserData.h + config.h + kiwano.h + macros.h) + +add_library(libkiwano ${SOURCE_FILES}) diff --git a/src/kiwano/core/Director.cpp b/src/kiwano/base/Director.cpp similarity index 99% rename from src/kiwano/core/Director.cpp rename to src/kiwano/base/Director.cpp index 84f4612f..6b221030 100644 --- a/src/kiwano/core/Director.cpp +++ b/src/kiwano/base/Director.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include namespace kiwano diff --git a/src/kiwano/core/Director.h b/src/kiwano/base/Director.h similarity index 98% rename from src/kiwano/core/Director.h rename to src/kiwano/base/Director.h index 8aca9387..fd054672 100644 --- a/src/kiwano/core/Director.h +++ b/src/kiwano/base/Director.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include namespace kiwano { diff --git a/src/kiwano/core/Module.cpp b/src/kiwano/base/Module.cpp similarity index 97% rename from src/kiwano/core/Module.cpp rename to src/kiwano/base/Module.cpp index 38a3182b..009100bb 100644 --- a/src/kiwano/core/Module.cpp +++ b/src/kiwano/base/Module.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include namespace kiwano { diff --git a/src/kiwano/core/Module.h b/src/kiwano/base/Module.h similarity index 100% rename from src/kiwano/core/Module.h rename to src/kiwano/base/Module.h diff --git a/src/kiwano/core/ObjectBase.cpp b/src/kiwano/base/ObjectBase.cpp similarity index 97% rename from src/kiwano/core/ObjectBase.cpp rename to src/kiwano/base/ObjectBase.cpp index 9423407c..588e0a6e 100644 --- a/src/kiwano/core/ObjectBase.cpp +++ b/src/kiwano/base/ObjectBase.cpp @@ -18,9 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include -#include -#include +#include +#include +#include #include namespace kiwano diff --git a/src/kiwano/core/ObjectBase.h b/src/kiwano/base/ObjectBase.h similarity index 98% rename from src/kiwano/core/ObjectBase.h rename to src/kiwano/base/ObjectBase.h index 38f3d653..6761c77c 100644 --- a/src/kiwano/core/ObjectBase.h +++ b/src/kiwano/base/ObjectBase.h @@ -19,11 +19,11 @@ // THE SOFTWARE. #pragma once +#include #include #include -#include #include -#include +#include namespace kiwano { diff --git a/src/kiwano/core/RefCounter.cpp b/src/kiwano/base/RefCounter.cpp similarity index 97% rename from src/kiwano/core/RefCounter.cpp rename to src/kiwano/base/RefCounter.cpp index dec905ba..27e44e5e 100644 --- a/src/kiwano/core/RefCounter.cpp +++ b/src/kiwano/base/RefCounter.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include namespace kiwano { diff --git a/src/kiwano/core/RefCounter.h b/src/kiwano/base/RefCounter.h similarity index 100% rename from src/kiwano/core/RefCounter.h rename to src/kiwano/base/RefCounter.h diff --git a/src/kiwano/2d/Button.cpp b/src/kiwano/base/component/Button.cpp similarity index 98% rename from src/kiwano/2d/Button.cpp rename to src/kiwano/base/component/Button.cpp index 061c87fb..c37e207b 100644 --- a/src/kiwano/2d/Button.cpp +++ b/src/kiwano/base/component/Button.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include #include diff --git a/src/kiwano/2d/Button.h b/src/kiwano/base/component/Button.h similarity index 98% rename from src/kiwano/2d/Button.h rename to src/kiwano/base/component/Button.h index 946f40dc..197be05b 100644 --- a/src/kiwano/2d/Button.h +++ b/src/kiwano/base/component/Button.h @@ -26,6 +26,11 @@ namespace kiwano KGE_DECLARE_SMART_PTR(Button); +/** + * \addtogroup Component + * @{ + */ + /** * \~chinese * @brief ť @@ -109,6 +114,8 @@ private: Callback mouse_out_callback_; }; +/** @} */ + inline void Button::SetClickCallback(const Callback& func) { click_callback_ = func; diff --git a/src/kiwano/2d/Component.cpp b/src/kiwano/base/component/Component.cpp similarity index 97% rename from src/kiwano/2d/Component.cpp rename to src/kiwano/base/component/Component.cpp index a22a9c22..7fbdb59e 100644 --- a/src/kiwano/2d/Component.cpp +++ b/src/kiwano/base/component/Component.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include namespace kiwano diff --git a/src/kiwano/2d/Component.h b/src/kiwano/base/component/Component.h similarity index 93% rename from src/kiwano/2d/Component.h rename to src/kiwano/base/component/Component.h index 8e62ca30..c48a168a 100644 --- a/src/kiwano/2d/Component.h +++ b/src/kiwano/base/component/Component.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include #include @@ -29,12 +29,19 @@ namespace kiwano class Actor; class Event; +class ComponentManager; KGE_DECLARE_SMART_PTR(Component); -/// \~chinese -/// @brief б -typedef IntrusiveList ComponentList; +/** + * \~chinese + * \defgroup Component + */ + +/** + * \addtogroup Component + * @{ + */ /** * \~chinese @@ -44,7 +51,7 @@ class KGE_API Component : public ObjectBase , protected IntrusiveListValue { - friend class Actor; + friend class ComponentManager; friend IntrusiveList; public: @@ -94,6 +101,8 @@ private: Actor* actor_; }; +/** @} */ + inline bool Component::IsEnable() const { return enabled_; diff --git a/src/kiwano/base/component/ComponentManager.cpp b/src/kiwano/base/component/ComponentManager.cpp new file mode 100644 index 00000000..8f99ce75 --- /dev/null +++ b/src/kiwano/base/component/ComponentManager.cpp @@ -0,0 +1,148 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#include + +namespace kiwano +{ + +ComponentManager::ComponentManager(Actor* target) + : target_(target) +{ +} + +Component* ComponentManager::AddComponent(ComponentPtr component) +{ + KGE_ASSERT(component && "AddComponent failed, NULL pointer exception"); + + if (component) + { + component->InitComponent(target_); + components_.PushBack(component); + } + return component.Get(); +} + +ComponentList& ComponentManager::GetAllComponents() +{ + return components_; +} + +const ComponentList& ComponentManager::GetAllComponents() const +{ + return components_; +} + +void ComponentManager::RemoveComponent(ComponentPtr component) +{ + auto iter = std::find(components_.begin(), components_.end(), component); + if (iter != components_.end()) + { + component->DestroyComponent(); + components_.Remove(component); + } +} + +void ComponentManager::RemoveComponents(const String& name) +{ + if (!components_.IsEmpty()) + { + ComponentPtr next; + for (auto component = components_.GetFirst(); component; component = next) + { + next = component->GetNext(); + + if (component->IsName(name)) + { + component->DestroyComponent(); + components_.Remove(component); + } + } + } +} + +void ComponentManager::RemoveAllComponents() +{ + // Destroy all components + if (!components_.IsEmpty()) + { + ComponentPtr next; + for (auto component = components_.GetFirst(); component; component = next) + { + next = component->GetNext(); + + component->DestroyComponent(); + } + } + components_.Clear(); +} + +void ComponentManager::Update(Duration dt) +{ + if (!components_.IsEmpty()) + { + ComponentPtr next; + for (auto component = components_.GetFirst(); component; component = next) + { + next = component->GetNext(); + + if (component->IsEnable()) + { + component->OnUpdate(dt); + } + } + } +} + +void ComponentManager::Render(RenderContext& ctx) +{ + if (!components_.IsEmpty()) + { + ComponentPtr next; + for (auto component = components_.GetFirst(); component; component = next) + { + next = component->GetNext(); + + if (component->IsEnable()) + { + component->OnRender(ctx); + } + } + } +} + +void ComponentManager::DispatchToComponents(Event* evt) +{ + if (!components_.IsEmpty()) + { + ComponentPtr next; + for (auto component = components_.GetFirst(); component; component = next) + { + next = component->GetNext(); + + if (component->IsEnable()) + { + component->HandleEvent(evt); + } + } + } +} + +} // namespace kiwano diff --git a/src/kiwano/core/TimerManager.h b/src/kiwano/base/component/ComponentManager.h similarity index 53% rename from src/kiwano/core/TimerManager.h rename to src/kiwano/base/component/ComponentManager.h index 5834e424..469e7eaa 100644 --- a/src/kiwano/core/TimerManager.h +++ b/src/kiwano/base/component/ComponentManager.h @@ -19,70 +19,74 @@ // THE SOFTWARE. #pragma once -#include +#include +#include namespace kiwano { + +/** + * \addtogroup Component + * @{ + */ + +/// \~chinese +/// @brief б +typedef IntrusiveList ComponentList; + /** * \~chinese - * @brief ʱ + * @brief */ -class KGE_API TimerManager +class KGE_API ComponentManager { public: /// \~chinese - /// @brief Ӷʱ - /// @param cb ص - /// @param interval ʱ - /// @param times ִд -1 ΪִУ - Timer* AddTimer(const Timer::Callback& cb, Duration interval, int times = -1); + /// @brief + /// @param component + Component* AddComponent(ComponentPtr component); /// \~chinese - /// @brief Ӷʱ - /// @param name ʱ - /// @param cb ص - /// @param interval ʱ - /// @param times ִд -1 ΪִУ - Timer* AddTimer(const String& name, const Timer::Callback& cb, Duration interval, int times = -1); + /// @brief ȡ + ComponentList& GetAllComponents(); /// \~chinese - /// @brief Ӷʱ - Timer* AddTimer(TimerPtr timer); + /// @brief ȡ + const ComponentList& GetAllComponents() const; /// \~chinese - /// @brief ʱ - void StartTimers(const String& timer_name); + /// @brief Ƴ + void RemoveComponent(ComponentPtr component); /// \~chinese - /// @brief ֹͣʱ - void StopTimers(const String& timer_name); + /// @brief Ƴ + /// @param name + void RemoveComponents(const String& name); /// \~chinese - /// @brief Ƴʱ - void RemoveTimers(const String& timer_name); + /// @brief Ƴ + void RemoveAllComponents(); /// \~chinese - /// @brief жʱ - void StartAllTimers(); + /// @brief + void Update(Duration dt); /// \~chinese - /// @brief ֹͣжʱ - void StopAllTimers(); + /// @brief Ⱦ + void Render(RenderContext& ctx); /// \~chinese - /// @brief Ƴжʱ - void RemoveAllTimers(); - - /// \~chinese - /// @brief ȡжʱ - const TimerList& GetAllTimers() const; + /// @brief ַ¼ + void DispatchToComponents(Event* evt); protected: - /// \~chinese - /// @brief ¶ʱ - void UpdateTimers(Duration dt); + ComponentManager(Actor* target); private: - TimerList timers_; + Actor* target_; + ComponentList components_; }; + +/** @} */ + } // namespace kiwano diff --git a/src/kiwano/core/Allocator.cpp b/src/kiwano/core/Allocator.cpp index 7b890e6a..99c37088 100644 --- a/src/kiwano/core/Allocator.cpp +++ b/src/kiwano/core/Allocator.cpp @@ -25,10 +25,14 @@ namespace kiwano namespace memory { -MemoryAllocator* current_allocator_ = GetGlobalAllocator(); +MemoryAllocator* current_allocator_ = nullptr; MemoryAllocator* GetAllocator() { + if (!current_allocator_) + { + current_allocator_ = GetGlobalAllocator(); + } return current_allocator_; } diff --git a/src/kiwano/core/Any.h b/src/kiwano/core/Any.h index f530ddb1..461895bf 100644 --- a/src/kiwano/core/Any.h +++ b/src/kiwano/core/Any.h @@ -73,9 +73,9 @@ public: /// \~chinese /// @brief ȡж - inline const type_info& GetType() const noexcept + inline const std::type_info& GetType() const noexcept { - const type_info* const info = GetTypeinfo(); + const std::type_info* const info = GetTypeinfo(); if (info) { return *info; @@ -132,7 +132,7 @@ public: { static_assert(!std::is_void<_Ty>::value, "oc::Any cannot contain void"); - const type_info* const info = GetTypeinfo(); + const std::type_info* const info = GetTypeinfo(); if (info && (*info == typeid(std::decay<_Ty>::type))) { if (HasSmallType()) @@ -193,12 +193,12 @@ public: } private: - const type_info*& GetTypeinfo() + const std::type_info*& GetTypeinfo() { return storage_.small_.info_; } - const type_info* GetTypeinfo() const + const std::type_info* GetTypeinfo() const { return storage_.small_.info_; } @@ -430,14 +430,14 @@ private: private: struct SmallStorage { - const type_info* info_; + const std::type_info* info_; SmallStorageRTTI rtti_; char buffer_[ANY_SMALL_SPACE_SIZE]; }; struct BigStorage { - const type_info* info_; + const std::type_info* info_; BigStorageRTTI rtti_; void* ptr_; }; diff --git a/src/kiwano/core/Exception.cpp b/src/kiwano/core/Exception.cpp index 09f454ac..f5346406 100644 --- a/src/kiwano/core/Exception.cpp +++ b/src/kiwano/core/Exception.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #if defined(KGE_PLATFORM_WINDOWS) #include diff --git a/src/kiwano/core/Exception.h b/src/kiwano/core/Exception.h index 91cbfda4..3ad24cfc 100644 --- a/src/kiwano/core/Exception.h +++ b/src/kiwano/core/Exception.h @@ -20,19 +20,22 @@ #pragma once #include +#include #include #include -#define KGE_THROW(MESSAGE) \ - do \ - { \ - kiwano::StackTracer().Print(); \ - throw kiwano::RuntimeError(MESSAGE); \ +#define KGE_THROW(MESSAGE) \ + do \ + { \ + KGE_ERROR("An exception occurred: %s", MESSAGE); \ + kiwano::StackTracer().Print(); \ + throw kiwano::RuntimeError(MESSAGE); \ } while (0) #define KGE_THROW_SYSTEM_ERROR(ERRCODE, MESSAGE) \ do \ { \ + KGE_ERROR("An exception occurred (%#x): %s", ERRCODE, MESSAGE); \ kiwano::StackTracer().Print(); \ throw kiwano::SystemError(std::error_code(kiwano::error_enum(ERRCODE)), MESSAGE); \ } while (0) diff --git a/src/kiwano/core/Function.h b/src/kiwano/core/Function.h index 0f85e1af..8cfcce51 100644 --- a/src/kiwano/core/Function.h +++ b/src/kiwano/core/Function.h @@ -75,9 +75,9 @@ public: virtual void Release() = 0; virtual _Ret Invoke(_Args&&... args) const = 0; - virtual const type_info& TargetType() const noexcept = 0; + virtual const std::type_info& TargetType() const noexcept = 0; - virtual const void* Target(const type_info& type) const noexcept = 0; + virtual const void* Target(const std::type_info& type) const noexcept = 0; }; template @@ -121,12 +121,12 @@ public: return std::invoke(callee_, std::forward<_Args>(args)...); } - virtual const type_info& TargetType() const noexcept + virtual const std::type_info& TargetType() const noexcept { return typeid(_Ty); } - virtual const void* Target(const type_info& type) const noexcept + virtual const void* Target(const std::type_info& type) const noexcept { if (type == this->TargetType()) return &callee_; @@ -153,12 +153,12 @@ public: return std::invoke(func_, ptr_, std::forward<_Args>(args)...); } - virtual const type_info& TargetType() const noexcept + virtual const std::type_info& TargetType() const noexcept { return typeid(ProxyMemCallable); } - virtual const void* Target(const type_info& type) const noexcept + virtual const void* Target(const std::type_info& type) const noexcept { if (type == this->TargetType()) return this; @@ -193,12 +193,12 @@ public: return std::invoke(func_, ptr_, std::forward<_Args>(args)...); } - virtual const type_info& TargetType() const noexcept + virtual const std::type_info& TargetType() const noexcept { return typeid(ProxyConstMemCallable); } - virtual const void* Target(const type_info& type) const noexcept + virtual const void* Target(const std::type_info& type) const noexcept { if (type == this->TargetType()) return this; @@ -321,7 +321,7 @@ public: std::swap(callable_, rhs.callable_); } - const type_info& target_type() const noexcept + const std::type_info& target_type() const noexcept { return callable_->TargetType(); } diff --git a/src/kiwano/core/IntrusiveList.h b/src/kiwano/core/IntrusiveList.h index 3fe724ed..651e2830 100644 --- a/src/kiwano/core/IntrusiveList.h +++ b/src/kiwano/core/IntrusiveList.h @@ -246,13 +246,13 @@ public: } public: - template + template struct Iterator { using iterator_category = std::bidirectional_iterator_tag; - using value_type = _PtrTy; - using pointer = _PtrTy*; - using reference = _PtrTy&; + using value_type = _IterPtrTy; + using pointer = _IterPtrTy*; + using reference = _IterPtrTy&; using difference_type = ptrdiff_t; inline Iterator(value_type ptr = nullptr, bool is_end = false) diff --git a/src/kiwano/core/Resource.cpp b/src/kiwano/core/Resource.cpp index ad44a5ff..99424288 100644 --- a/src/kiwano/core/Resource.cpp +++ b/src/kiwano/core/Resource.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include #include namespace kiwano diff --git a/src/kiwano/core/Serializable.h b/src/kiwano/core/Serializable.h index 821865cc..c160cf7d 100644 --- a/src/kiwano/core/Serializable.h +++ b/src/kiwano/core/Serializable.h @@ -24,6 +24,15 @@ namespace kiwano { +/** + * \~chinese + * \defgroup Serialization л + */ + +/** + * \addtogroup Serialization + * @{ + */ /// \~chinese /// @brief л @@ -230,7 +239,7 @@ class Serializable { public: /// \~chinese - /// @brief лΪַ + /// @brief лΪֽڴ inline Vector Serialize() const { Vector data; @@ -240,7 +249,7 @@ public: } /// \~chinese - /// @brief ַл + /// @brief ֽڴл inline void Deserialize(const Vector& data) { ByteDeserializer deserializer(data); @@ -438,4 +447,7 @@ inline Deserializer& operator>>(Deserializer& deserializer, math::TransformT> transform.position >> transform.rotation >> transform.scale >> transform.skew; } +/** @} */ + + } // namespace kiwano diff --git a/src/kiwano/core/SmartPtr.hpp b/src/kiwano/core/SmartPtr.hpp index ba73c09a..f569bb2b 100644 --- a/src/kiwano/core/SmartPtr.hpp +++ b/src/kiwano/core/SmartPtr.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include namespace kiwano { @@ -73,13 +73,13 @@ public: SmartPtr(pointer_type p) : ptr_(p) { - typename _ProxyTy::Retain(ptr_); + _ProxyTy::Retain(ptr_); } SmartPtr(const SmartPtr& other) : ptr_(other.ptr_) { - typename _ProxyTy::Retain(ptr_); + _ProxyTy::Retain(ptr_); } SmartPtr(SmartPtr&& other) noexcept @@ -97,7 +97,7 @@ public: SmartPtr(const SmartPtr<_UTy, _ProxyTy>& other) { ptr_ = const_cast(dynamic_cast(other.Get())); - typename _ProxyTy::Retain(ptr_); + _ProxyTy::Retain(ptr_); } inline pointer_type Get() noexcept @@ -193,7 +193,7 @@ public: private: void Tidy() { - typename _ProxyTy::Release(ptr_); + _ProxyTy::Release(ptr_); ptr_ = nullptr; } @@ -268,7 +268,7 @@ inline bool operator<(const SmartPtr<_Ty, _ProxyTy>& lhs, const SmartPtr<_UTy, _ } // template class cannot specialize std::swap, -// so implement a Swap Function in kiwano namespace +// so implement a swap function in kiwano namespace template inline void swap(SmartPtr<_Ty, _ProxyTy>& lhs, SmartPtr<_Ty, _ProxyTy>& rhs) noexcept { diff --git a/src/kiwano/core/Time.cpp b/src/kiwano/core/Time.cpp index 49a31ee5..33b120d8 100644 --- a/src/kiwano/core/Time.cpp +++ b/src/kiwano/core/Time.cpp @@ -19,10 +19,12 @@ // THE SOFTWARE. #include -#include +#include #include #include #include +#include +#include namespace kiwano { @@ -35,7 +37,7 @@ Time::Time() { } -Time::Time(long dur) +Time::Time(int64_t dur) : dur_(dur) { } @@ -69,19 +71,114 @@ const Duration Time::operator-(const Time& other) const Time Time::Now() noexcept { - static LARGE_INTEGER freq = {}; - if (freq.QuadPart == 0LL) +#if defined(KGE_PLATFORM_WINDOWS) + + static double millisecs_per_count = {}; + if (millisecs_per_count == 0) { + LARGE_INTEGER freq = {}; // the Function will always succceed on systems that run Windows XP or later QueryPerformanceFrequency(&freq); + millisecs_per_count = 1000.0 / static_cast(freq.QuadPart); } LARGE_INTEGER count; QueryPerformanceCounter(&count); + return Time{ static_cast(count.QuadPart * millisecs_per_count) }; - const long long whole = (count.QuadPart / freq.QuadPart) * 1000LL; - const long long part = (count.QuadPart % freq.QuadPart) * 1000LL / freq.QuadPart; - return Time{ static_cast(whole + part) }; +#else + + using std::chrono::steady_clock; + using std::chrono::duration_cast; + using std::chrono::milliseconds; + + const auto now = steady_clock::now(); + const auto count = duration_cast(now.time_since_epoch()).count(); + return Time{ static_cast(count) }; + +#endif +} + +//------------------------------------------------------- +// ClockTime +//------------------------------------------------------- + +ClockTime::ClockTime() + : ms_since_epoch_(0) +{ +} + +int64_t ClockTime::GetTimeStamp() const +{ + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::seconds; + + const auto timestamp = duration_cast(milliseconds(ms_since_epoch_)).count(); + return static_cast(timestamp); +} + +int64_t ClockTime::GetMillisecondsSinceEpoch() const +{ + return ms_since_epoch_; +} + +std::time_t ClockTime::GetCTime() const +{ + return static_cast(GetTimeStamp()); +} + +ClockTime::ClockTime(int64_t ms_since_epoch) + : ms_since_epoch_(ms_since_epoch) +{ +} + +ClockTime ClockTime::FromTimeStamp(int64_t timestamp) noexcept +{ + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::seconds; + + const auto ms = duration_cast(seconds(timestamp)).count(); + return ClockTime(static_cast(ms)); +} + +ClockTime ClockTime::Now() noexcept +{ + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::system_clock; + + const auto now = system_clock::now(); + const auto count = duration_cast(now.time_since_epoch()).count(); + return ClockTime{ static_cast(count) }; +} + +const Duration ClockTime::operator-(const ClockTime& other) const +{ + return Duration(ms_since_epoch_ - other.ms_since_epoch_); +} + +const ClockTime ClockTime::operator+(const Duration& dur) const +{ + return ClockTime{ ms_since_epoch_ + dur.Milliseconds() }; +} + +const ClockTime ClockTime::operator-(const Duration& dur) const +{ + return ClockTime{ ms_since_epoch_ - dur.Milliseconds() }; +} + +ClockTime& ClockTime::operator+=(const Duration& other) +{ + ms_since_epoch_ += other.Milliseconds(); + return (*this); +} + +ClockTime& ClockTime::operator-=(const Duration& other) +{ + ms_since_epoch_ -= other.Milliseconds(); + return (*this); } //------------------------------------------------------- @@ -109,30 +206,41 @@ Duration::Duration() { } -Duration::Duration(long milliseconds) +Duration::Duration(int64_t milliseconds) : milliseconds_(milliseconds) { } float Duration::Seconds() const { - long sec = milliseconds_ / Second.milliseconds_; - long ms = milliseconds_ % Second.milliseconds_; - return static_cast(sec) + static_cast(ms) / 1000.f; + auto sec = milliseconds_ / Second.milliseconds_; + auto ms = milliseconds_ % Second.milliseconds_; + return static_cast(sec + ms) / 1000.f; } float Duration::Minutes() const { - long min = milliseconds_ / Minute.milliseconds_; - long ms = milliseconds_ % Minute.milliseconds_; - return static_cast(min) + static_cast(ms) / (60 * 1000.f); + auto min = milliseconds_ / Minute.milliseconds_; + auto ms = milliseconds_ % Minute.milliseconds_; + return static_cast(min + ms) / (60 * 1000.f); } float Duration::Hours() const { - long hour = milliseconds_ / Hour.milliseconds_; - long ms = milliseconds_ % Hour.milliseconds_; - return static_cast(hour) + static_cast(ms) / (60 * 60 * 1000.f); + auto hour = milliseconds_ / Hour.milliseconds_; + auto ms = milliseconds_ % Hour.milliseconds_; + return static_cast(hour + ms) / (60 * 60 * 1000.f); +} + +void Duration::Sleep() const +{ + using std::chrono::milliseconds; + using std::this_thread::sleep_for; + + if (milliseconds_) + { + sleep_for(milliseconds(milliseconds_)); + } } String Duration::ToString() const @@ -142,18 +250,18 @@ String Duration::ToString() const return String("0s"); } - String result; - long total_ms = milliseconds_; + String result; + int64_t total_ms = milliseconds_; if (total_ms < 0) { result.append("-"); total_ms = -total_ms; } - long hour = total_ms / Hour.milliseconds_; - long min = total_ms / Minute.milliseconds_ - hour * 60; - long sec = total_ms / Second.milliseconds_ - (hour * 60 * 60 + min * 60); - long ms = total_ms % Second.milliseconds_; + int64_t hour = total_ms / Hour.milliseconds_; + int64_t min = total_ms / Minute.milliseconds_ - hour * 60; + int64_t sec = total_ms / Second.milliseconds_ - (hour * 60 * 60 + min * 60); + int64_t ms = total_ms % Second.milliseconds_; if (hour) { @@ -167,7 +275,7 @@ String Duration::ToString() const if (ms != 0) { - result.append(std::to_string(static_cast(sec) + static_cast(ms) / 1000.f)).append("s"); + result.append(std::to_string(static_cast(sec + ms) / 1000.f)).append("s"); } else if (sec != 0) { @@ -233,22 +341,22 @@ const Duration Duration::operator*(int val) const const Duration Duration::operator*(unsigned long long val) const { - return Duration(static_cast(milliseconds_ * val)); + return Duration(static_cast(milliseconds_ * val)); } const Duration Duration::operator*(float val) const { - return Duration(static_cast(milliseconds_ * val)); + return Duration(static_cast(milliseconds_ * val)); } const Duration Duration::operator*(double val) const { - return Duration(static_cast(milliseconds_ * val)); + return Duration(static_cast(milliseconds_ * val)); } const Duration Duration::operator*(long double val) const { - return Duration(static_cast(milliseconds_ * val)); + return Duration(static_cast(milliseconds_ * val)); } const Duration Duration::operator/(int val) const @@ -258,12 +366,12 @@ const Duration Duration::operator/(int val) const const Duration Duration::operator/(float val) const { - return Duration(static_cast(milliseconds_ / val)); + return Duration(static_cast(milliseconds_ / val)); } const Duration Duration::operator/(double val) const { - return Duration(static_cast(milliseconds_ / val)); + return Duration(static_cast(milliseconds_ / val)); } Duration& Duration::operator+=(const Duration& other) @@ -286,31 +394,31 @@ Duration& Duration::operator*=(int val) Duration& Duration::operator/=(int val) { - milliseconds_ = static_cast(milliseconds_ / val); + milliseconds_ = static_cast(milliseconds_ / val); return (*this); } Duration& Duration::operator*=(float val) { - milliseconds_ = static_cast(milliseconds_ * val); + milliseconds_ = static_cast(milliseconds_ * val); return (*this); } Duration& Duration::operator/=(float val) { - milliseconds_ = static_cast(milliseconds_ / val); + milliseconds_ = static_cast(milliseconds_ / val); return (*this); } Duration& Duration::operator*=(double val) { - milliseconds_ = static_cast(milliseconds_ * val); + milliseconds_ = static_cast(milliseconds_ * val); return (*this); } Duration& Duration::operator/=(double val) { - milliseconds_ = static_cast(milliseconds_ / val); + milliseconds_ = static_cast(milliseconds_ / val); return (*this); } diff --git a/src/kiwano/core/Time.h b/src/kiwano/core/Time.h index e563c440..1cf09285 100644 --- a/src/kiwano/core/Time.h +++ b/src/kiwano/core/Time.h @@ -20,6 +20,7 @@ #pragma once #include +#include namespace kiwano { @@ -52,11 +53,11 @@ struct KGE_API Duration /// \~chinese /// @brief ʱ /// @param milliseconds - Duration(long milliseconds); + Duration(int64_t milliseconds); /// \~chinese /// @brief ȡ - long Milliseconds() const; + int64_t Milliseconds() const; /// \~chinese /// @brief ȡ @@ -78,7 +79,7 @@ struct KGE_API Duration /// \~chinese /// @brief ú /// @param ms - void SetMilliseconds(long ms); + void SetMilliseconds(int64_t ms); /// \~chinese /// @brief @@ -95,6 +96,10 @@ struct KGE_API Duration /// @param hours Сʱ void SetHours(float hours); + /// \~chinese + /// @brief + void Sleep() const; + /// \~chinese /// @brief תΪַ String ToString() const; @@ -154,7 +159,7 @@ struct KGE_API Duration friend const Duration operator/(double, const Duration&); private: - long milliseconds_; + int64_t milliseconds_; }; /** @@ -192,13 +197,56 @@ struct KGE_API Time Time& operator-=(const Duration&); private: - Time(long ms); + Time(int64_t ms); private: - long dur_; + int64_t dur_; }; -inline long Duration::Milliseconds() const +/** + * \~chinese + * @brief ʱʱ + */ +struct KGE_API ClockTime +{ + ClockTime(); + + /// \~chinese + /// @brief ȡǰʱ + int64_t GetTimeStamp() const; + + /// \~chinese + /// @brief ȡԼԪĺ + int64_t GetMillisecondsSinceEpoch() const; + + /// \~chinese + /// @brief ȡ C ʱ + std::time_t GetCTime() const; + + /// \~chinese + /// @brief ȡǰʱ + static ClockTime Now() noexcept; + + /// \~chinese + /// @brief ʱתΪʱ + static ClockTime FromTimeStamp(int64_t timestamp) noexcept; + + const Duration operator-(const ClockTime&) const; + + const ClockTime operator+(const Duration&) const; + const ClockTime operator-(const Duration&) const; + + ClockTime& operator+=(const Duration&); + ClockTime& operator-=(const Duration&); + +private: + ClockTime(int64_t ms_since_epoch); + +private: + int64_t ms_since_epoch_; +}; + +inline int64_t Duration::Milliseconds() const { return milliseconds_; } @@ -208,7 +256,7 @@ inline bool Duration::IsZero() const return milliseconds_ == 0LL; } -inline void Duration::SetMilliseconds(long ms) +inline void Duration::SetMilliseconds(int64_t ms) { milliseconds_ = ms; } @@ -232,6 +280,7 @@ inline bool Time::IsZero() const { return dur_ == 0; } + } // namespace kiwano #if defined(KGE_HAS_LITERALS) diff --git a/src/kiwano/core/Timer.h b/src/kiwano/core/Timer.h deleted file mode 100644 index 07a9480f..00000000 --- a/src/kiwano/core/Timer.h +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) 2016-2018 Kiwano - Nomango -// -// 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. - -#pragma once -#include -#include -#include - -namespace kiwano -{ -class TimerManager; - -KGE_DECLARE_SMART_PTR(Timer); - -/// \~chinese -/// @brief ʱб -typedef IntrusiveList TimerList; - -/// \~chinese -/// @brief ʱ -/// @details ʱÿһʱִһλصҿִָܴ -class KGE_API Timer - : public ObjectBase - , protected IntrusiveListValue -{ - friend class TimerManager; - friend IntrusiveList; - -public: - /// \~chinese - /// @brief ʱص - /// @details - /// صһǶʱڶǾϴθµʱ - using Callback = Function; - - /// \~chinese - /// @brief ʱ - /// @param cb ص - /// @param interval ʱ - /// @param times ִд -1 ΪִУ - static TimerPtr Create(const Callback& cb, Duration interval, int times = -1); - - /// \~chinese - /// @brief ʱ - /// @param name - /// @param cb ص - /// @param interval ʱ - /// @param times ִд -1 ΪִУ - static TimerPtr Create(const String& name, const Callback& cb, Duration interval, int times = -1); - - /// \~chinese - /// @brief նʱ - Timer(); - - /// \~chinese - /// @brief ʱ - void Start(); - - /// \~chinese - /// @brief ֹͣʱ - void Stop(); - - /// \~chinese - /// @brief Ƴʱ - void Remove(); - - /// \~chinese - /// @brief ʱǷ - bool IsRunning() const; - - /// \~chinese - /// @brief ʱǷƳ - bool IsRemoveable() const; - - /// \~chinese - /// @brief ȡʱִйصĴ - int GetRunTimes() const; - - /// \~chinese - /// @brief ȡʱִлصܴ - int GetTotalRunTimes() const; - - /// \~chinese - /// @brief öʱִлصܴ - void SetTotalRunTimes(int times); - - /// \~chinese - /// @brief ȡʱִʱ - Duration GetInterval() const; - - /// \~chinese - /// @brief öʱִʱ - void SetInterval(Duration interval); - - /// \~chinese - /// @brief ȡʱص - Callback GetCallback() const; - - /// \~chinese - /// @brief öʱص - void SetCallback(const Callback& callback); - -private: - /// \~chinese - /// @brief ¶ʱ - void Update(Duration dt); - - /// \~chinese - /// @brief öʱ - void Reset(); - -private: - bool running_; - bool removeable_; - int run_times_; - int total_times_; - Duration interval_; - Duration elapsed_; - Callback callback_; -}; - -inline void Timer::Start() -{ - running_ = true; -} - -inline void Timer::Stop() -{ - running_ = false; -} - -inline void Timer::Remove() -{ - removeable_ = true; -} - -inline bool Timer::IsRunning() const -{ - return running_; -} - -inline bool Timer::IsRemoveable() const -{ - return removeable_; -} - -inline int Timer::GetRunTimes() const -{ - return run_times_; -} - -inline int Timer::GetTotalRunTimes() const -{ - return total_times_; -} - -inline void Timer::SetTotalRunTimes(int times) -{ - total_times_ = times; -} - -inline Duration Timer::GetInterval() const -{ - return interval_; -} - -inline void Timer::SetInterval(Duration interval) -{ - interval_ = interval; -} - -inline Timer::Callback Timer::GetCallback() const -{ - return callback_; -} - -inline void Timer::SetCallback(const Timer::Callback& callback) -{ - callback_ = callback; -} -} // namespace kiwano diff --git a/src/kiwano/core/TimerManager.cpp b/src/kiwano/core/TimerManager.cpp deleted file mode 100644 index bf4d5c92..00000000 --- a/src/kiwano/core/TimerManager.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2016-2018 Kiwano - Nomango -// -// 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. - -#include -#include - -namespace kiwano -{ -void TimerManager::UpdateTimers(Duration dt) -{ - if (timers_.IsEmpty()) - return; - - TimerPtr next; - for (auto timer = timers_.GetFirst(); timer; timer = next) - { - next = timer->GetNext(); - - timer->Update(dt); - - if (timer->IsRemoveable()) - timers_.Remove(timer); - } -} - -Timer* TimerManager::AddTimer(const Timer::Callback& cb, Duration interval, int times) -{ - return AddTimer(String(), cb, interval, times); -} - -Timer* TimerManager::AddTimer(const String& name, const Timer::Callback& cb, Duration interval, int times) -{ - TimerPtr timer = Timer::Create(name, cb, interval, times); - return AddTimer(timer); -} - -Timer* TimerManager::AddTimer(TimerPtr timer) -{ - KGE_ASSERT(timer && "AddTimer failed, NULL pointer exception"); - - if (timer) - { - timer->Reset(); - timers_.PushBack(timer); - } - - return timer.Get(); -} - -void TimerManager::StopTimers(const String& name) -{ - if (timers_.IsEmpty()) - return; - - for (auto& timer : timers_) - { - if (timer->IsName(name)) - { - timer->Stop(); - } - } -} - -void TimerManager::StartTimers(const String& name) -{ - if (timers_.IsEmpty()) - return; - - for (auto& timer : timers_) - { - if (timer->IsName(name)) - { - timer->Start(); - } - } -} - -void TimerManager::RemoveTimers(const String& name) -{ - if (timers_.IsEmpty()) - return; - - for (auto& timer : timers_) - { - if (timer->IsName(name)) - { - timer->Remove(); - } - } -} - -void TimerManager::StopAllTimers() -{ - if (timers_.IsEmpty()) - return; - - for (auto& timer : timers_) - { - timer->Stop(); - } -} - -void TimerManager::StartAllTimers() -{ - if (timers_.IsEmpty()) - return; - - for (auto& timer : timers_) - { - timer->Start(); - } -} - -void TimerManager::RemoveAllTimers() -{ - timers_.Clear(); -} - -const TimerList& TimerManager::GetAllTimers() const -{ - return timers_; -} -} // namespace kiwano diff --git a/src/kiwano/core/event/Event.cpp b/src/kiwano/event/Event.cpp similarity index 76% rename from src/kiwano/core/event/Event.cpp rename to src/kiwano/event/Event.cpp index d793f723..b39e0fb0 100644 --- a/src/kiwano/core/event/Event.cpp +++ b/src/kiwano/event/Event.cpp @@ -1,4 +1,4 @@ -#include +#include namespace kiwano { diff --git a/src/kiwano/core/event/Event.h b/src/kiwano/event/Event.h similarity index 98% rename from src/kiwano/core/event/Event.h rename to src/kiwano/event/Event.h index 09d182e4..16242d27 100644 --- a/src/kiwano/core/event/Event.h +++ b/src/kiwano/event/Event.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include namespace kiwano diff --git a/src/kiwano/core/EventDispatcher.cpp b/src/kiwano/event/EventDispatcher.cpp similarity index 98% rename from src/kiwano/core/EventDispatcher.cpp rename to src/kiwano/event/EventDispatcher.cpp index 8bde41f2..fa97b779 100644 --- a/src/kiwano/core/EventDispatcher.cpp +++ b/src/kiwano/event/EventDispatcher.cpp @@ -18,8 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include -#include +#include +#include namespace kiwano { diff --git a/src/kiwano/core/EventDispatcher.h b/src/kiwano/event/EventDispatcher.h similarity index 96% rename from src/kiwano/core/EventDispatcher.h rename to src/kiwano/event/EventDispatcher.h index 2eff0bf2..6e5a0861 100644 --- a/src/kiwano/core/EventDispatcher.h +++ b/src/kiwano/event/EventDispatcher.h @@ -19,13 +19,18 @@ // THE SOFTWARE. #pragma once -#include +#include namespace kiwano { + +/// \~chinese +/// @brief б +typedef IntrusiveList ListenerList; + /** * \~chinese - * @brief ¼ַϵͳ + * @brief ¼ַ */ class KGE_API EventDispatcher { diff --git a/src/kiwano/core/EventListener.cpp b/src/kiwano/event/EventListener.cpp similarity index 97% rename from src/kiwano/core/EventListener.cpp rename to src/kiwano/event/EventListener.cpp index 79846f30..1549d5d3 100644 --- a/src/kiwano/core/EventListener.cpp +++ b/src/kiwano/event/EventListener.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include namespace kiwano { diff --git a/src/kiwano/core/EventListener.h b/src/kiwano/event/EventListener.h similarity index 94% rename from src/kiwano/core/EventListener.h rename to src/kiwano/event/EventListener.h index 2aee0e19..d179ba11 100644 --- a/src/kiwano/core/EventListener.h +++ b/src/kiwano/event/EventListener.h @@ -20,13 +20,10 @@ #pragma once #include -#include +#include #include #include -#include -#include -#include -#include +#include namespace kiwano { @@ -34,10 +31,6 @@ class EventDispatcher; KGE_DECLARE_SMART_PTR(EventListener); -/// \~chinese -/// @brief б -typedef IntrusiveList ListenerList; - /** * \~chinese * @brief ¼ diff --git a/src/kiwano/core/event/EventType.h b/src/kiwano/event/EventType.h similarity index 100% rename from src/kiwano/core/event/EventType.h rename to src/kiwano/event/EventType.h diff --git a/src/kiwano/event/Events.h b/src/kiwano/event/Events.h new file mode 100644 index 00000000..13312ad8 --- /dev/null +++ b/src/kiwano/event/Events.h @@ -0,0 +1,26 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#pragma once + +#include +#include +#include +#include diff --git a/src/kiwano/core/event/KeyEvent.cpp b/src/kiwano/event/KeyEvent.cpp similarity index 90% rename from src/kiwano/core/event/KeyEvent.cpp rename to src/kiwano/event/KeyEvent.cpp index 0d60eb22..f654ffd1 100644 --- a/src/kiwano/core/event/KeyEvent.cpp +++ b/src/kiwano/event/KeyEvent.cpp @@ -1,4 +1,4 @@ -#include +#include namespace kiwano { diff --git a/src/kiwano/core/event/KeyEvent.h b/src/kiwano/event/KeyEvent.h similarity index 98% rename from src/kiwano/core/event/KeyEvent.h rename to src/kiwano/event/KeyEvent.h index 66ac2cb7..a56ed119 100644 --- a/src/kiwano/core/event/KeyEvent.h +++ b/src/kiwano/event/KeyEvent.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include namespace kiwano { diff --git a/src/kiwano/core/event/MouseEvent.cpp b/src/kiwano/event/MouseEvent.cpp similarity index 94% rename from src/kiwano/core/event/MouseEvent.cpp rename to src/kiwano/event/MouseEvent.cpp index 81c84d1d..7833bea4 100644 --- a/src/kiwano/core/event/MouseEvent.cpp +++ b/src/kiwano/event/MouseEvent.cpp @@ -1,4 +1,4 @@ -#include +#include namespace kiwano { diff --git a/src/kiwano/core/event/MouseEvent.h b/src/kiwano/event/MouseEvent.h similarity index 98% rename from src/kiwano/core/event/MouseEvent.h rename to src/kiwano/event/MouseEvent.h index b6371797..29731d39 100644 --- a/src/kiwano/core/event/MouseEvent.h +++ b/src/kiwano/event/MouseEvent.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include namespace kiwano diff --git a/src/kiwano/core/event/WindowEvent.cpp b/src/kiwano/event/WindowEvent.cpp similarity index 94% rename from src/kiwano/core/event/WindowEvent.cpp rename to src/kiwano/event/WindowEvent.cpp index 37cafb2b..1d07214d 100644 --- a/src/kiwano/core/event/WindowEvent.cpp +++ b/src/kiwano/event/WindowEvent.cpp @@ -1,4 +1,4 @@ -#include +#include namespace kiwano { diff --git a/src/kiwano/core/event/WindowEvent.h b/src/kiwano/event/WindowEvent.h similarity index 98% rename from src/kiwano/core/event/WindowEvent.h rename to src/kiwano/event/WindowEvent.h index 26a28e0d..4370422d 100644 --- a/src/kiwano/core/event/WindowEvent.h +++ b/src/kiwano/event/WindowEvent.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include namespace kiwano { diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h index cc1877cf..50ef674e 100644 --- a/src/kiwano/kiwano.h +++ b/src/kiwano/kiwano.h @@ -44,20 +44,33 @@ // #include -#include -#include -#include -#include -#include #include #include #include -#include -#include -#include -#include -#include -#include + +// +// base +// + +#include +#include +#include +#include +#include +#include +#include + + +// +// event +// + +#include +#include +#include +#include +#include +#include // // renderer @@ -68,6 +81,8 @@ #include #include #include +#include +#include #include #include #include @@ -79,11 +94,8 @@ // #include -#include #include #include -#include -#include #include #include #include @@ -95,7 +107,7 @@ #include #include #include -#include +#include #include #include #include @@ -114,6 +126,12 @@ // utils // +#include #include #include #include +#include +#include +#include +#include +#include diff --git a/src/kiwano/macros.h b/src/kiwano/macros.h index fd5ab8a7..27d54fb3 100644 --- a/src/kiwano/macros.h +++ b/src/kiwano/macros.h @@ -77,7 +77,7 @@ // ///////////////////////////////////////////////////////////// -#ifdef KGE_PLATFORM_WINDOWS +#if defined(KGE_PLATFORM_WINDOWS) #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_NONE # undef KGE_RENDER_ENGINE @@ -157,6 +157,32 @@ KGE_SUPPRESS_WARNING(4251) #include #include +#elif defined(KGE_PLATFORM_MACOS) + +#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_NONE +# undef KGE_RENDER_ENGINE +# define KGE_RENDER_ENGINE KGE_RENDER_ENGINE_OPENGL +#endif + +#define KGE_DEPRECATED(...) + +#define KGE_SUPPRESS_WARNING_PUSH +#define KGE_SUPPRESS_WARNING(CODE) +#define KGE_SUPPRESS_WARNING_POP + +#ifndef KGE_API +# if defined(KGE_USE_DLL) +# define KGE_API +# elif defined(KGE_EXPORT_DLL) +# define KGE_API +# endif +#endif + +#ifndef KGE_API +/* Building or calling Kiwano as a static library */ +# define KGE_API +#endif + #else #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index 064f1d94..52a1533f 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -20,8 +20,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -35,20 +35,29 @@ int GetVersion() } Application::Application() - : quiting_(false) + : running_(false) + , is_paused_(false) , time_scale_(1.f) { Use(Renderer::GetInstance()); Use(Input::GetInstance()); Use(Director::GetInstance()); + + ticker_ = Ticker::Create(0); + ticker_->Tick(); } -Application::~Application() {} +Application::~Application() +{ + this->Destroy(); +} void Application::Run(RunnerPtr runner, bool debug) { KGE_ASSERT(runner); runner_ = runner; + running_ = true; + is_paused_ = false; // Setup all modules for (auto c : modules_) @@ -65,30 +74,49 @@ void Application::Run(RunnerPtr runner, bool debug) // Everything is ready runner->OnReady(); - quiting_ = false; - last_update_time_ = Time::Now(); - while (!quiting_) + while (running_) { - const Time now = Time::Now(); - const Duration dt = (now - last_update_time_); - last_update_time_ = now; - - if (!runner->MainLoop(dt)) - quiting_ = true; + if (ticker_->Tick()) + { + if (!runner->MainLoop(ticker_->GetDeltaTime())) + running_ = false; + } } - // Destroy all resources - runner->OnDestroy(); this->Destroy(); } +void Application::Pause() +{ + is_paused_ = true; + if (ticker_) + { + ticker_->Pause(); + } +} + +void Application::Resume() +{ + is_paused_ = false; + if (ticker_) + { + ticker_->Resume(); + } +} + void Application::Quit() { - quiting_ = true; + running_ = false; } void Application::Destroy() { + if (runner_) + { + runner_->OnDestroy(); + runner_ = nullptr; + } + // Clear all resources Director::GetInstance().ClearStages(); ResourceCache::GetInstance().Clear(); @@ -98,6 +126,7 @@ void Application::Destroy() { (*iter)->DestroyModule(); } + modules_.clear(); } void Application::Use(Module& module) @@ -124,6 +153,9 @@ void Application::DispatchEvent(EventPtr evt) void Application::DispatchEvent(Event* evt) { + if (!running_ /* Dispatch events even if application is paused */) + return; + for (auto comp : modules_) { if (auto event_comp = comp->Cast()) @@ -135,6 +167,9 @@ void Application::DispatchEvent(Event* evt) void Application::Update(Duration dt) { + if (!running_ || is_paused_) + return; + // Before update for (auto comp : modules_) { @@ -186,6 +221,9 @@ void Application::Update(Duration dt) void Application::Render() { + if (!running_ /* Render even if application is paused */) + return; + Renderer& renderer = Renderer::GetInstance(); renderer.Clear(); diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h index 1ca1bce2..10765c55 100644 --- a/src/kiwano/platform/Application.h +++ b/src/kiwano/platform/Application.h @@ -21,12 +21,13 @@ #pragma once #include #include -#include +#include #include #include -#include +#include #include #include +#include namespace kiwano { @@ -59,6 +60,18 @@ public: */ void Run(RunnerPtr runner, bool debug = false); + /** + * \~chinese + * @brief ͣӦó + */ + void Pause(); + + /** + * \~chinese + * @brief Ӧó + */ + void Resume(); + /** * \~chinese * @brief ֹӦó @@ -77,6 +90,18 @@ public: */ WindowPtr GetMainWindow() const; + /** + * \~chinese + * @brief ȡʱ + */ + TickerPtr GetTicker() const; + + /** + * \~chinese + * @brief ȡͣ״̬ + */ + bool IsPaused() const; + /** * \~chinese * @brief ģ @@ -136,17 +161,12 @@ public: */ void Destroy(); - /** - * \~chinese - * @brief ȡһθʱ - */ - Time GetLastUpdateTime() const; - private: - bool quiting_; + bool running_; + bool is_paused_; float time_scale_; RunnerPtr runner_; - Time last_update_time_; + TickerPtr ticker_; List modules_; std::mutex perform_mutex_; Queue> functions_to_perform_; @@ -163,9 +183,14 @@ inline WindowPtr Application::GetMainWindow() const return runner_->GetMainWindow(); } -inline Time Application::GetLastUpdateTime() const +inline TickerPtr Application::GetTicker() const { - return last_update_time_; + return ticker_; +} + +inline bool Application::IsPaused() const +{ + return is_paused_; } } // namespace kiwano diff --git a/src/kiwano/platform/Input.cpp b/src/kiwano/platform/Input.cpp index d79c49a5..8dd82307 100644 --- a/src/kiwano/platform/Input.cpp +++ b/src/kiwano/platform/Input.cpp @@ -18,9 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include -#include -#include +#include +#include #include namespace kiwano diff --git a/src/kiwano/platform/Input.h b/src/kiwano/platform/Input.h index 0759bc55..d2a72793 100644 --- a/src/kiwano/platform/Input.h +++ b/src/kiwano/platform/Input.h @@ -21,9 +21,9 @@ #pragma once #include #include -#include +#include #include -#include +#include #include #include diff --git a/src/kiwano/platform/Runner.cpp b/src/kiwano/platform/Runner.cpp index 1c261f3e..333df2da 100644 --- a/src/kiwano/platform/Runner.cpp +++ b/src/kiwano/platform/Runner.cpp @@ -18,9 +18,12 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#include #include #include +#define KGE_MAX_SKIP_FRAMES 10 + namespace kiwano { @@ -71,6 +74,9 @@ Runner::~Runner() {} bool Runner::MainLoop(Duration dt) { + if (!main_window_) + return false; + if (main_window_->ShouldClose()) { if (this->OnClosing()) @@ -81,15 +87,25 @@ bool Runner::MainLoop(Duration dt) Application& app = Application::GetInstance(); + KGE_LOG(dt.Milliseconds()); + + // Update modules before poll events + app.Update(dt); + // Poll events + main_window_->PumpEvents(); while (EventPtr evt = main_window_->PollEvent()) { app.DispatchEvent(evt.Get()); } - // Update & render - app.Update(dt); app.Render(); + + if (app.IsPaused()) + { + // Slow down when the application is paused + Duration(5).Sleep(); + } return true; } diff --git a/src/kiwano/platform/Runner.h b/src/kiwano/platform/Runner.h index a156b8a9..c21801a9 100644 --- a/src/kiwano/platform/Runner.h +++ b/src/kiwano/platform/Runner.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include namespace kiwano diff --git a/src/kiwano/platform/Window.cpp b/src/kiwano/platform/Window.cpp index e784c7cb..e92b7212 100644 --- a/src/kiwano/platform/Window.cpp +++ b/src/kiwano/platform/Window.cpp @@ -26,8 +26,13 @@ namespace kiwano Window::Window() : handle_(nullptr) , should_close_(false) + , is_fullscreen_(false) , width_(0) , height_(0) + , min_width_(0) + , min_height_(0) + , max_width_(0) + , max_height_(0) { } @@ -37,8 +42,6 @@ Window::~Window() EventPtr Window::PollEvent() { - PumpEvents(); - EventPtr evt; if (!event_queue_.empty()) { @@ -88,9 +91,4 @@ void Window::PushEvent(EventPtr evt) event_queue_.push(evt); } -void Window::Destroy() -{ - should_close_ = true; -} - } // namespace kiwano diff --git a/src/kiwano/platform/Window.h b/src/kiwano/platform/Window.h index c4b24208..08b9d25a 100644 --- a/src/kiwano/platform/Window.h +++ b/src/kiwano/platform/Window.h @@ -20,8 +20,8 @@ #pragma once #include -#include -#include +#include +#include #include namespace kiwano @@ -45,6 +45,17 @@ enum class CursorType SizeNWSE, ///< ָϵ·ļͷ }; +/** + * \~chinese + * @brief ֱ + */ +struct Resolution +{ + uint32_t width; ///< ֱʿ + uint32_t height; ///< ֱʸ߶ + uint32_t refresh_rate; ///< ˢ +}; + #if defined(KGE_PLATFORM_WINDOWS) typedef HWND WindowHandle; @@ -66,11 +77,10 @@ public: * @param height ߶ * @param icon ͼԴID * @param resizable ڴС - * @param fullscreen ȫģʽ * @throw kiwano::SystemError ڴʧʱ׳ */ static WindowPtr Create(const String& title, uint32_t width, uint32_t height, uint32_t icon = 0, - bool resizable = false, bool fullscreen = false); + bool resizable = false); /** * \~chinese @@ -106,6 +116,12 @@ public: */ WindowHandle GetHandle() const; + /** + * \~chinese + * @brief ȡֵ֧Ļֱб + */ + virtual Vector GetResolutions() = 0; + /** * \~chinese * @brief ñ @@ -122,20 +138,28 @@ public: /** * \~chinese - * @brief 贰ڴС - * @param width ڿ - * @param height ڸ߶ + * @brief ôڷֱ + * @param width ֱʿ + * @param height ֱʸ߶ + * @param fullscreen Ƿȫ */ - virtual void Resize(uint32_t width, uint32_t height) = 0; + virtual void SetResolution(uint32_t width, uint32_t height, bool fullscreen) = 0; /** * \~chinese - * @brief ȫģʽ - * @param fullscreen Ƿȫ - * @param width ڿ - * @param height ڸ߶ + * @brief ôСС + * @param width Сڿ + * @param height Сڸ߶ */ - virtual void SetFullscreen(bool fullscreen) = 0; + virtual void SetMinimumSize(uint32_t width, uint32_t height) = 0; + + /** + * \~chinese + * @brief ôС + * @param width 󴰿ڿ + * @param height 󴰿ڸ߶ + */ + virtual void SetMaximumSize(uint32_t width, uint32_t height) = 0; /** * \~chinese @@ -147,8 +171,7 @@ public: /** * \~chinese * @brief ѯ¼ - * @return ¼еĵһ¼ӶƳ\n - * ¼Ϊ򷵻ؿָ + * @return ¼еĵһ¼ӶƳ, Ϊ򷵻ؿָ */ EventPtr PollEvent(); @@ -177,12 +200,6 @@ public: */ void SetShouldClose(bool should); - /** - * \~chinese - * @brief ٴ - */ - virtual void Destroy(); - protected: Window(); @@ -190,8 +207,13 @@ protected: protected: bool should_close_; + bool is_fullscreen_; uint32_t width_; uint32_t height_; + uint32_t min_width_; + uint32_t min_height_; + uint32_t max_width_; + uint32_t max_height_; WindowHandle handle_; String title_; std::queue event_queue_; diff --git a/src/kiwano/platform/win32/WindowImpl.cpp b/src/kiwano/platform/win32/WindowImpl.cpp index 9f7c8e05..be5ae065 100644 --- a/src/kiwano/platform/win32/WindowImpl.cpp +++ b/src/kiwano/platform/win32/WindowImpl.cpp @@ -26,11 +26,11 @@ #include #include #include -#include -#include -#include -#include +#include +#include #include +#include +#include #include // GET_X_LPARAM, GET_Y_LPARAM #include // ImmAssociateContext #pragma comment(lib, "imm32.lib") @@ -47,19 +47,21 @@ public: virtual ~WindowWin32Impl(); - void Init(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, bool fullscreen); + void Init(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable); void SetTitle(const String& title) override; void SetIcon(uint32_t icon_resource) override; - void Resize(uint32_t width, uint32_t height) override; + void SetMinimumSize(uint32_t width, uint32_t height) override; - void SetFullscreen(bool fullscreen) override; + void SetMaximumSize(uint32_t width, uint32_t height) override; void SetCursor(CursorType cursor) override; - void Destroy() override; + void SetResolution(uint32_t width, uint32_t height, bool fullscreen) override; + + Vector GetResolutions() override; void PumpEvents() override; @@ -67,28 +69,27 @@ public: void UpdateCursor(); - void SetActive(bool actived); - LRESULT MessageProc(HWND, UINT32, WPARAM, LPARAM); static LRESULT CALLBACK StaticWndProc(HWND, UINT32, WPARAM, LPARAM); private: bool resizable_; - bool is_fullscreen_; + bool is_resizing_; + bool is_minimized_; CursorType mouse_cursor_; String device_name_; + Vector resolutions_; std::array key_map_; }; -WindowPtr Window::Create(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, - bool fullscreen) +WindowPtr Window::Create(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable) { WindowWin32ImplPtr ptr = memory::New(); if (ptr) { - ptr->Init(title, width, height, icon, resizable, fullscreen); + ptr->Init(title, width, height, icon, resizable); } return ptr; } @@ -100,7 +101,6 @@ namespace kiwano #define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX #define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX -#define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP namespace { @@ -136,36 +136,12 @@ void AdjustWindow(uint32_t width, uint32_t height, DWORD style, uint32_t* win_wi *win_height = screenh; } -void ChangeFullScreenResolution(uint32_t width, uint32_t height, const CHAR* device_name) -{ - DEVMODEA mode; - - memset(&mode, 0, sizeof(mode)); - mode.dmSize = sizeof(mode); - mode.dmPelsWidth = width; - mode.dmPelsHeight = height; - mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; - - LONG ret = ::ChangeDisplaySettingsExA(device_name, &mode, NULL, CDS_FULLSCREEN, NULL); - if (ret != DISP_CHANGE_SUCCESSFUL) - { - KGE_ERROR("ChangeDisplaySettings failed with error code %d", ret); - } -} - -void RestoreResolution(const CHAR* device_name) -{ - LONG ret = ::ChangeDisplaySettingsExA(device_name, NULL, NULL, 0, NULL); - if (ret != DISP_CHANGE_SUCCESSFUL) - { - KGE_ERROR("ChangeDisplaySettings failed with error code %d", ret); - } -} } // namespace WindowWin32Impl::WindowWin32Impl() - : is_fullscreen_(false) - , resizable_(false) + : resizable_(false) + , is_resizing_(false) + , is_minimized_(false) , mouse_cursor_(CursorType::Arrow) , key_map_{} { @@ -213,11 +189,14 @@ WindowWin32Impl::WindowWin32Impl() WindowWin32Impl::~WindowWin32Impl() { - this->Destroy(); + if (handle_) + { + ::DestroyWindow(handle_); + handle_ = nullptr; + } } -void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, - bool fullscreen) +void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable) { HINSTANCE hinst = GetModuleHandle(nullptr); WNDCLASSEXA wcex = { 0 }; @@ -253,38 +232,22 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, // Save the device name device_name_ = monitor_info_ex.szDevice; - int left = -1, top = -1; + uint32_t screenw = monitor_info_ex.rcWork.right - monitor_info_ex.rcWork.left; + uint32_t screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top; - resizable_ = resizable; - is_fullscreen_ = fullscreen; + uint32_t win_width, win_height; + AdjustWindow(width, height, GetStyle(), &win_width, &win_height); - if (is_fullscreen_) - { - top = monitor_info_ex.rcMonitor.top; - left = monitor_info_ex.rcMonitor.left; + int left = monitor_info_ex.rcWork.left + (screenw - win_width) / 2; + int top = monitor_info_ex.rcWork.top + (screenh - win_height) / 2; + width = win_width; + height = win_height; - if (width > static_cast(monitor_info_ex.rcWork.right - left)) - width = static_cast(monitor_info_ex.rcWork.right - left); - - if (height > static_cast(monitor_info_ex.rcWork.bottom - top)) - height = static_cast(monitor_info_ex.rcWork.bottom - top); - } - else - { - uint32_t screenw = monitor_info_ex.rcWork.right - monitor_info_ex.rcWork.left; - uint32_t screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top; - - uint32_t win_width, win_height; - AdjustWindow(width, height, GetStyle(), &win_width, &win_height); - - left = monitor_info_ex.rcWork.left + (screenw - win_width) / 2; - top = monitor_info_ex.rcWork.top + (screenh - win_height) / 2; - width = win_width; - height = win_height; - } - - handle_ = ::CreateWindowExA(is_fullscreen_ ? WS_EX_TOPMOST : 0, "KiwanoAppWnd", title.c_str(), GetStyle(), - left, top, width, height, nullptr, nullptr, hinst, nullptr); + width_ = width; + height_ = height; + resizable_ = resizable; + handle_ = ::CreateWindowExA(0, "KiwanoAppWnd", title.c_str(), GetStyle(), left, top, width, height, nullptr, + nullptr, hinst, nullptr); if (handle_ == nullptr) { @@ -292,9 +255,6 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, KGE_THROW_SYSTEM_ERROR(HRESULT_FROM_WIN32(GetLastError()), "Create window failed"); } - width_ = width; - height_ = height; - // disable imm ::ImmAssociateContext(handle_, nullptr); @@ -304,10 +264,20 @@ void WindowWin32Impl::Init(const String& title, uint32_t width, uint32_t height, ::ShowWindow(handle_, SW_SHOWNORMAL); ::UpdateWindow(handle_); - if (is_fullscreen_) + // Initialize Direct3D resources + auto d3d_res = graphics::directx::GetD3DDeviceResources(); + + HRESULT hr = d3d_res->Initialize(handle_); + + // Initialize Direct2D resources + if (SUCCEEDED(hr)) { - ChangeFullScreenResolution(width, height, device_name_.c_str()); + 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() @@ -322,101 +292,32 @@ void WindowWin32Impl::PumpEvents() void WindowWin32Impl::SetTitle(const String& title) { - if (handle_) - { - ::SetWindowTextA(handle_, title.c_str()); - } + KGE_ASSERT(handle_); + ::SetWindowTextA(handle_, title.c_str()); } void WindowWin32Impl::SetIcon(uint32_t icon_resource) { - if (handle_) - { - HINSTANCE hinstance = ::GetModuleHandle(nullptr); - HICON icon = (HICON)::LoadImage(hinstance, MAKEINTRESOURCE(icon_resource), IMAGE_ICON, 0, 0, - LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE); + KGE_ASSERT(handle_); - ::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)icon); - ::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon); - } + HINSTANCE hinstance = ::GetModuleHandle(nullptr); + HICON icon = (HICON)::LoadImage(hinstance, MAKEINTRESOURCE(icon_resource), IMAGE_ICON, 0, 0, + LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE); + + ::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)icon); + ::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon); } -void WindowWin32Impl::Resize(uint32_t width, uint32_t height) +void WindowWin32Impl::SetMinimumSize(uint32_t width, uint32_t height) { - if (handle_) - { - if (!is_fullscreen_) - { - MONITORINFOEXA info = GetMoniterInfoEx(handle_); - - uint32_t screenw = uint32_t(info.rcWork.right - info.rcWork.left); - uint32_t screenh = uint32_t(info.rcWork.bottom - info.rcWork.top); - - RECT rc = { 0, 0, LONG(width), LONG(height) }; - ::AdjustWindowRect(&rc, GetStyle(), false); - - width = rc.right - rc.left; - height = rc.bottom - rc.top; - - int left = screenw > width ? ((screenw - width) / 2) : 0; - int top = screenh > height ? ((screenh - height) / 2) : 0; - - ::SetWindowPos(handle_, 0, left, top, width, height, SWP_NOZORDER | SWP_NOACTIVATE); - } - else - { - // move window to (0, 0) before display switch - ::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE); - - ChangeFullScreenResolution(width, height, device_name_.c_str()); - - MONITORINFOEXA info = GetMoniterInfoEx(handle_); - ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width, height, - SWP_NOACTIVATE); - } - } + min_width_ = width; + min_height_ = height; } -void WindowWin32Impl::SetFullscreen(bool fullscreen) +void WindowWin32Impl::SetMaximumSize(uint32_t width, uint32_t height) { - if (is_fullscreen_ != fullscreen) - { - is_fullscreen_ = fullscreen; - - uint32_t width = GetWidth(); - uint32_t height = GetHeight(); - - if (is_fullscreen_) - { - // move window to (0, 0) before display switch - ::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE); - - ChangeFullScreenResolution(width, height, device_name_.c_str()); - - MONITORINFOEXA info = GetMoniterInfoEx(handle_); - - ::SetWindowLongPtrA(handle_, GWL_STYLE, GetStyle()); - ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width, height, - SWP_NOACTIVATE); - } - else - { - RestoreResolution(device_name_.c_str()); - - MONITORINFOEXA info = GetMoniterInfoEx(handle_); - - uint32_t screenw = uint32_t(info.rcWork.right - info.rcWork.left); - uint32_t screenh = uint32_t(info.rcWork.bottom - info.rcWork.top); - - int left = screenw > width ? ((screenw - width) / 2) : 0; - int top = screenh > height ? ((screenh - height) / 2) : 0; - - ::SetWindowLongPtrA(handle_, GWL_STYLE, GetStyle()); - ::SetWindowPos(handle_, HWND_NOTOPMOST, left, top, width, height, SWP_DRAWFRAME | SWP_FRAMECHANGED); - } - - ::ShowWindow(handle_, SW_SHOWNORMAL); - } + max_width_ = width; + max_height_ = height; } void WindowWin32Impl::SetCursor(CursorType cursor) @@ -424,23 +325,81 @@ void WindowWin32Impl::SetCursor(CursorType cursor) mouse_cursor_ = cursor; } -void WindowWin32Impl::Destroy() +void WindowWin32Impl::SetResolution(uint32_t width, uint32_t height, bool fullscreen) { - if (is_fullscreen_) - RestoreResolution(device_name_.c_str()); + auto d3d = kiwano::graphics::directx::GetD3DDeviceResources(); - if (handle_) + if (fullscreen) { - ::DestroyWindow(handle_); - handle_ = nullptr; + HRESULT hr = d3d->ResizeTarget(width, height); + KGE_THROW_IF_FAILED(hr, "DXGI ResizeTarget failed!"); + + hr = d3d->SetFullscreenState(fullscreen); + KGE_THROW_IF_FAILED(hr, "DXGI SetFullscreenState failed!"); + } + else + { + HRESULT hr = d3d->SetFullscreenState(fullscreen); + KGE_THROW_IF_FAILED(hr, "DXGI SetFullscreenState failed!"); + + hr = d3d->ResizeTarget(width, height); + KGE_THROW_IF_FAILED(hr, "DXGI ResizeTarget failed!"); } - Window::Destroy(); + is_fullscreen_ = fullscreen; +} + +Vector WindowWin32Impl::GetResolutions() +{ + if (resolutions_.empty()) + { + auto d3d = kiwano::graphics::directx::GetD3DDeviceResources(); + + DXGI_MODE_DESC* mode_descs = nullptr; + int mode_num = 0; + + HRESULT hr = d3d->GetDisplaySettings(&mode_descs, &mode_num); + if (SUCCEEDED(hr)) + { + std::unique_ptr mode_list(mode_descs); + + if (mode_list) + { + for (int i = 0; i < mode_num; i++) + { + Resolution res; + res.width = mode_descs[i].Width; + res.height = mode_descs[i].Height; + res.refresh_rate = 0; + + if (mode_descs[i].RefreshRate.Denominator > 0) + { + res.refresh_rate = mode_descs[i].RefreshRate.Numerator / mode_descs[i].RefreshRate.Denominator; + } + + if (!resolutions_.empty()) + { + auto& back = resolutions_.back(); + if (back.width == res.width && back.height == res.height + && back.refresh_rate == res.refresh_rate) + continue; + } + + resolutions_.push_back(res); + } + } + } + else + { + KGE_THROW_IF_FAILED(hr, "DXGI GetDisplaySettings failed!"); + } + } + return resolutions_; } DWORD WindowWin32Impl::GetStyle() const { - return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE)); + return (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE)); } void WindowWin32Impl::UpdateCursor() @@ -476,31 +435,6 @@ void WindowWin32Impl::UpdateCursor() ::SetCursor(::LoadCursor(nullptr, win32_cursor)); } -void WindowWin32Impl::SetActive(bool actived) -{ - if (!handle_) - return; - - if (is_fullscreen_) - { - if (actived) - { - ChangeFullScreenResolution(GetWidth(), GetHeight(), device_name_.c_str()); - - MONITORINFOEXA info = GetMoniterInfoEx(handle_); - ::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, GetWidth(), GetHeight(), - SWP_NOACTIVATE); - } - else - { - RestoreResolution(device_name_.c_str()); - - ::SetWindowPos(handle_, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - ::ShowWindow(handle_, SW_MINIMIZE); - } - } -} - LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) { switch (msg) @@ -612,21 +546,96 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) { KGE_SYS_LOG("Window minimized"); - } - else - { - // KGE_SYS_LOG("Window resized"); - this->width_ = ((uint32_t)(short)LOWORD(lparam)); - this->height_ = ((uint32_t)(short)HIWORD(lparam)); + is_minimized_ = true; + // Pause game when window is minimized + Application::GetInstance().Pause(); + } + else if (SIZE_MAXIMIZED == wparam) + { + KGE_SYS_LOG("Window maximized"); + + if (is_minimized_) + { + is_minimized_ = false; + Application::GetInstance().Resume(); + } + } + else if (wparam == SIZE_RESTORED) + { + if (is_minimized_) + { + KGE_SYS_LOG("Window restored"); + + // the window was restored and was previously minimized + is_minimized_ = false; + Application::GetInstance().Resume(); + } + else if (is_resizing_) + { + // DO NOTHING until the dragging / resizing has stopped. + } + else + { + this->width_ = ((uint32_t)(short)LOWORD(lparam)); + this->height_ = ((uint32_t)(short)HIWORD(lparam)); + + WindowResizedEventPtr evt = new WindowResizedEvent; + evt->width = this->GetWidth(); + evt->height = this->GetHeight(); + this->PushEvent(evt); + + KGE_SYS_LOG("Window resized to (%d, %d)", this->width_, this->height_); + } + } + } + break; + + case WM_ENTERSIZEMOVE: + { + is_resizing_ = true; + Application::GetInstance().Pause(); + return 0; + } + + case WM_EXITSIZEMOVE: + { + is_resizing_ = false; + Application::GetInstance().Resume(); + + // Send window resized event when client size changed + RECT client_rect = { 0 }; + ::GetClientRect(hwnd, &client_rect); + + uint32_t client_width = uint32_t(client_rect.right - client_rect.left); + uint32_t client_height = uint32_t(client_rect.bottom - client_rect.top); + if (client_width != this->GetWidth() || client_height != this->GetHeight()) + { + KGE_SYS_LOG("Window resized to (%d, %d)", client_width, client_height); + + this->width_ = client_width; + this->height_ = client_height; WindowResizedEventPtr evt = new WindowResizedEvent; evt->width = this->GetWidth(); evt->height = this->GetHeight(); this->PushEvent(evt); } + return 0; + } + + case WM_GETMINMAXINFO: + { + if (min_width_ || min_height_) + { + ((MINMAXINFO*)lparam)->ptMinTrackSize = POINT{ LONG(min_width_), LONG(min_height_) }; + } + if (max_width_ || max_height_) + { + ((MINMAXINFO*)lparam)->ptMaxTrackSize = POINT{ LONG(max_width_), LONG(max_height_) }; + } + return 0; } - break; case WM_MOVE: { @@ -637,18 +646,43 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA } break; + case WM_MENUCHAR: + { + // Disables the crazy beeping sound when pressing a mnemonic key. + // Simply tell Windows that we want the menu closed. + return MAKELRESULT(0, MNC_CLOSE); + } + case WM_ACTIVATE: { bool active = (LOWORD(wparam) != WA_INACTIVE); - this->SetActive(active); - WindowFocusChangedEventPtr evt = new WindowFocusChangedEvent; evt->focus = active; this->PushEvent(evt); } break; + case WM_SETFOCUS: + { + if (is_fullscreen_) + { + // TODO restore to fullscreen mode + // SetResolution(); + } + } + break; + + case WM_KILLFOCUS: + { + if (is_fullscreen_) + { + // TODO exit fullscreen mode + // ::ShowWindow(handle_, SW_MINIMIZE); + } + } + break; + case WM_SETTEXT: { KGE_SYS_LOG("Window title changed"); @@ -671,7 +705,17 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA { KGE_SYS_LOG("The display resolution has changed"); - ::InvalidateRect(hwnd, nullptr, FALSE); + // Check fullscreen state + auto d3d_res = graphics::directx::GetD3DDeviceResources(); + auto swap_chain = d3d_res->GetDXGISwapChain(); + if (swap_chain) + { + BOOL is_fullscreen = FALSE; + if (SUCCEEDED(swap_chain->GetFullscreenState(&is_fullscreen, nullptr))) + { + is_fullscreen_ = !!is_fullscreen; + } + } } break; diff --git a/src/kiwano/platform/win32/libraries.cpp b/src/kiwano/platform/win32/libraries.cpp index ac0f6bbb..4505ee66 100644 --- a/src/kiwano/platform/win32/libraries.cpp +++ b/src/kiwano/platform/win32/libraries.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include #include namespace kiwano diff --git a/src/kiwano/render/Brush.cpp b/src/kiwano/render/Brush.cpp index bab76f91..f106f2de 100644 --- a/src/kiwano/render/Brush.cpp +++ b/src/kiwano/render/Brush.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include #include diff --git a/src/kiwano/render/Brush.h b/src/kiwano/render/Brush.h index 32992be7..f2e1648d 100644 --- a/src/kiwano/render/Brush.h +++ b/src/kiwano/render/Brush.h @@ -19,6 +19,7 @@ // THE SOFTWARE. #pragma once +#include #include #include diff --git a/src/kiwano/render/Color.cpp b/src/kiwano/render/Color.cpp index 023e4d3a..7bba4f60 100644 --- a/src/kiwano/render/Color.cpp +++ b/src/kiwano/render/Color.cpp @@ -74,4 +74,25 @@ Color::Color(uint32_t rgb, float alpha) , a(alpha) { } + +Color Color::Rgb(float r, float g, float b) +{ + return Color::Rgba(r, g, b, 1.0f); +} + +Color Color::Rgb(uint32_t rgb) +{ + return Color::Rgba(rgb, 1.0f); +} + +Color Color::Rgba(float r, float g, float b, float alpha) +{ + return Color(r, g, b, alpha); +} + +Color Color::Rgba(uint32_t rgb, float alpha) +{ + return Color(rgb, alpha); +} + } // namespace kiwano diff --git a/src/kiwano/render/Color.h b/src/kiwano/render/Color.h index dec63edf..f91e561d 100644 --- a/src/kiwano/render/Color.h +++ b/src/kiwano/render/Color.h @@ -59,7 +59,7 @@ public: /// @param r ɫֵΧ 0.0 - 1.0 /// @param g ɫֵΧ 0.0 - 1.0 /// @param b ɫֵΧ 0.0 - 1.0 - /// @param a AlphaֵΧ 0.0 - 1.0 + /// @param alpha AlphaֵΧ 0.0 - 1.0 Color(float r, float g, float b, float alpha); /// \~chinese @@ -70,9 +70,35 @@ public: /// \~chinese /// @brief RGBA ɫ /// @param rgb ʹ16ֵʾ RGB ɫ - /// @param a AlphaֵΧ 0.0 - 1.0 + /// @param alpha AlphaֵΧ 0.0 - 1.0 Color(uint32_t rgb, float alpha); + /// \~chinese + /// @brief RGB ɫ + /// @param r ɫֵΧ 0.0 - 1.0 + /// @param g ɫֵΧ 0.0 - 1.0 + /// @param b ɫֵΧ 0.0 - 1.0 + static Color Rgb(float r, float g, float b); + + /// \~chinese + /// @brief RGB ɫ + /// @param rgb ʹ16ֵʾ RGBɫ + static Color Rgb(uint32_t rgb); + + /// \~chinese + /// @brief RGBA ɫ + /// @param r ɫֵΧ 0.0 - 1.0 + /// @param g ɫֵΧ 0.0 - 1.0 + /// @param b ɫֵΧ 0.0 - 1.0 + /// @param alpha AlphaֵΧ 0.0 - 1.0 + static Color Rgba(float r, float g, float b, float alpha); + + /// \~chinese + /// @brief RGBA ɫ + /// @param rgb ʹ16ֵʾ RGBɫ + /// @param alpha AlphaֵΧ 0.0 - 1.0 + static Color Rgba(uint32_t rgb, float alpha); + bool operator==(const Color& rhs) const; bool operator!=(const Color& rhs) const; diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.cpp b/src/kiwano/render/DirectX/D2DDeviceResources.cpp index 3f522162..2062ac2d 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.cpp +++ b/src/kiwano/render/DirectX/D2DDeviceResources.cpp @@ -19,13 +19,21 @@ // THE SOFTWARE. #include -#include +#include #pragma comment(lib, "d2d1.lib") #pragma comment(lib, "dwrite.lib") namespace kiwano { +namespace graphics +{ +namespace directx +{ + +// Global pointer for Direct2D device resources +static ComPtr global_d2d_device_resource; + struct D2DDeviceResources : public ID2DDeviceResources { public: @@ -33,6 +41,8 @@ public: virtual ~D2DDeviceResources(); + HRESULT Initialize(_In_ ComPtr dxgi_device, _In_ ComPtr dxgi_swap_chain) override; + HRESULT CreateDeviceIndependentResources(); HRESULT CreateDeviceResources(_In_ ComPtr dxgi_device, _In_ ComPtr dxgi_swap_chain); @@ -57,8 +67,8 @@ public: _In_ ComPtr collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, FLOAT font_size) override; - HRESULT CreateTextLayout(_Out_ ComPtr& text_layout, _In_ LPCWSTR text, - UINT32 length, _In_ ComPtr text_format) override; + HRESULT CreateTextLayout(_Out_ ComPtr& text_layout, _In_ LPCWSTR text, UINT32 length, + _In_ ComPtr text_format) override; HRESULT SetDpi(float dpi) override; @@ -85,40 +95,14 @@ private: ComPtr dxgi_swap_chain_; }; -HRESULT ID2DDeviceResources::Create(_Out_ ID2DDeviceResources** device_resources, _In_ ComPtr dxgi_device, - _In_ ComPtr dxgi_swap_chain) + +ComPtr GetD2DDeviceResources() { - HRESULT hr = E_FAIL; - if (device_resources) + if (!global_d2d_device_resource) { - D2DDeviceResources* res = new (std::nothrow) D2DDeviceResources; - if (res) - { - hr = res->CreateDeviceIndependentResources(); - - if (SUCCEEDED(hr)) - { - hr = res->CreateDeviceResources(dxgi_device, dxgi_swap_chain); - } - - if (SUCCEEDED(hr)) - { - hr = res->CreateWindowSizeDependentResources(); - } - } - - if (SUCCEEDED(hr)) - { - DX::SafeRelease(*device_resources); - (*device_resources) = DX::SafeAcquire(res); - } - else - { - delete res; - res = nullptr; - } + global_d2d_device_resource.Reset(new (std::nothrow) D2DDeviceResources); } - return hr; + return global_d2d_device_resource; } D2DDeviceResources::D2DDeviceResources() @@ -132,6 +116,22 @@ D2DDeviceResources::~D2DDeviceResources() DiscardResources(); } +HRESULT D2DDeviceResources::Initialize(ComPtr dxgi_device, ComPtr dxgi_swap_chain) +{ + HRESULT hr = this->CreateDeviceIndependentResources(); + + if (SUCCEEDED(hr)) + { + hr = this->CreateDeviceResources(dxgi_device, dxgi_swap_chain); + } + + if (SUCCEEDED(hr)) + { + hr = this->CreateWindowSizeDependentResources(); + } + return hr; +} + STDMETHODIMP_(unsigned long) D2DDeviceResources::AddRef() { return InterlockedIncrement(&ref_count_); @@ -423,8 +423,8 @@ HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr& te return E_UNEXPECTED; ComPtr output; - HRESULT hr = dwrite_factory_->CreateTextFormat(family, collection.Get(), weight, style, stretch, font_size, - L"", &output); + HRESULT hr = + dwrite_factory_->CreateTextFormat(family, collection.Get(), weight, style, stretch, font_size, L"", &output); if (SUCCEEDED(hr)) { @@ -450,4 +450,6 @@ HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr& te return hr; } +} // namespace directx +} // namespace graphics } // namespace kiwano diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.h b/src/kiwano/render/DirectX/D2DDeviceResources.h index a61e3f24..4c57f263 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.h +++ b/src/kiwano/render/DirectX/D2DDeviceResources.h @@ -26,12 +26,16 @@ namespace kiwano { +namespace graphics +{ +namespace directx +{ + MIDL_INTERFACE("5706684a-bf6d-4b03-b627-094758a33032") KGE_API ID2DDeviceResources : public IUnknown { public: - static HRESULT Create(_Out_ ID2DDeviceResources * *device_resources, _In_ ComPtr dxgi_device, - _In_ ComPtr dxgi_swap_chain); + virtual HRESULT Initialize(_In_ ComPtr dxgi_device, _In_ ComPtr dxgi_swap_chain) = 0; virtual HRESULT CreateBitmapConverter(_Out_ ComPtr & converter, _In_opt_ ComPtr source, _In_ REFWICPixelFormatGUID format, @@ -51,8 +55,8 @@ public: _In_ ComPtr collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, FLOAT font_size) = 0; - virtual HRESULT CreateTextLayout(_Out_ ComPtr & text_layout, _In_ LPCWSTR text, - UINT32 length, _In_ ComPtr text_format) = 0; + virtual HRESULT CreateTextLayout(_Out_ ComPtr & text_layout, _In_ LPCWSTR text, UINT32 length, + _In_ ComPtr text_format) = 0; virtual HRESULT SetDpi(float dpi) = 0; @@ -111,4 +115,9 @@ protected: ComPtr dwrite_factory_; }; + +extern ComPtr GetD2DDeviceResources(); + +} +} } // namespace kiwano diff --git a/src/kiwano/render/DirectX/D3D10DeviceResources.cpp b/src/kiwano/render/DirectX/D3D10DeviceResources.cpp index 70c4b74b..e10427db 100644 --- a/src/kiwano/render/DirectX/D3D10DeviceResources.cpp +++ b/src/kiwano/render/DirectX/D3D10DeviceResources.cpp @@ -18,16 +18,21 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include #pragma comment(lib, "d3d10_1.lib") namespace kiwano { - -namespace DX +namespace graphics { +namespace directx +{ + +// Global pointer for Direct3D11 device resources +static ComPtr global_d3d10_device_resources; + HRESULT CreateD3DDevice(IDXGIAdapter* adapter, D3D10_DRIVER_TYPE driver_type, uint32_t flags, ID3D10Device1** device) { HRESULT hr = S_OK; @@ -60,22 +65,30 @@ inline bool SdkLayersAvailable() } #endif -} // namespace DX - struct D3D10DeviceResources : public ID3D10DeviceResources { public: - HRESULT Present(bool vsync); + HRESULT Initialize(HWND hwnd) override; - void ClearRenderTarget(Color& clear_color); + HRESULT Present(bool vsync) override; - HRESULT HandleDeviceLost(); + void ClearRenderTarget(Color& clear_color) override; - HRESULT SetLogicalSize(Size logical_size); + HRESULT HandleDeviceLost() override; - HRESULT SetDpi(float dpi); + HRESULT SetLogicalSize(Size logical_size) override; - void DiscardResources(); + HRESULT SetDpi(float dpi) override; + + HRESULT SetFullscreenState(bool fullscreen) override; + + HRESULT GetFullscreenState(bool* fullscreen) override; + + HRESULT ResizeTarget(UINT width, UINT height) override; + + HRESULT GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num) override; + + void DiscardResources() override; public: unsigned long STDMETHODCALLTYPE AddRef(); @@ -99,11 +112,23 @@ public: Size logical_size_; Size output_size_; unsigned long ref_count_; + DXGI_FORMAT desired_color_format_; }; + +ComPtr GetD3D10DeviceResources() +{ + if (!global_d3d10_device_resources) + { + global_d3d10_device_resources.Reset(new (std::nothrow) D3D10DeviceResources); + } + return global_d3d10_device_resources; +} + D3D10DeviceResources::D3D10DeviceResources() : ref_count_(0) , hwnd_(nullptr) + , desired_color_format_(DXGI_FORMAT_B8G8R8A8_UNORM) { dpi_ = 96.f; // dpi_ = (float)GetDpiForWindow(hwnd); } @@ -113,55 +138,34 @@ D3D10DeviceResources::~D3D10DeviceResources() DiscardResources(); } -HRESULT ID3D10DeviceResources::Create(ID3D10DeviceResources** device_resources, HWND hwnd) +HRESULT D3D10DeviceResources::Initialize(HWND hwnd) { - HRESULT hr = E_FAIL; + RECT rc; + ::GetClientRect(hwnd, &rc); - if (device_resources) + this->hwnd_ = hwnd; + this->logical_size_.x = float(rc.right - rc.left); + this->logical_size_.y = float(rc.bottom - rc.top); + + HRESULT hr = this->CreateDeviceResources(); + + if (SUCCEEDED(hr)) { - D3D10DeviceResources* res = new (std::nothrow) D3D10DeviceResources; - if (res) - { - RECT rc; - ::GetClientRect(hwnd, &rc); - - res->hwnd_ = hwnd; - res->logical_size_.x = float(rc.right - rc.left); - res->logical_size_.y = float(rc.bottom - rc.top); - - hr = res->CreateDeviceResources(); - - if (SUCCEEDED(hr)) - { - hr = res->CreateWindowSizeDependentResources(); - } - - if (SUCCEEDED(hr)) - { - res->AddRef(); - - if (*device_resources) - { - (*device_resources)->Release(); - } - (*device_resources) = res; - } - else - { - delete res; - res = nullptr; - } - } + hr = this->CreateWindowSizeDependentResources(); } return hr; } HRESULT D3D10DeviceResources::Present(bool vsync) { - KGE_ASSERT(dxgi_swap_chain_ != nullptr); + HRESULT hr = E_FAIL; - // The first argument instructs DXGI to block until VSync. - return dxgi_swap_chain_->Present(vsync ? 1 : 0, 0); + if (dxgi_swap_chain_) + { + // The first argument instructs DXGI to block until VSync. + hr = dxgi_swap_chain_->Present(vsync ? 1 : 0, DXGI_PRESENT_DO_NOT_WAIT); + } + return hr; } void D3D10DeviceResources::ClearRenderTarget(Color& clear_color) @@ -194,14 +198,14 @@ HRESULT D3D10DeviceResources::CreateDeviceResources() uint32_t creation_flags = D3D10_CREATE_DEVICE_BGRA_SUPPORT; #if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG) - if (DX::SdkLayersAvailable()) + if (SdkLayersAvailable()) { creation_flags |= D3D10_CREATE_DEVICE_DEBUG; } #endif ComPtr device; - hr = DX::CreateD3DDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, creation_flags, &device); + hr = CreateD3DDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, creation_flags, &device); if (SUCCEEDED(hr)) { @@ -215,24 +219,32 @@ HRESULT D3D10DeviceResources::CreateDeviceResources() if (SUCCEEDED(hr)) { dxgi_device_ = dxgi_device; - - ComPtr dxgi_adapter; - hr = dxgi_device_->GetAdapter(&dxgi_adapter); - - if (SUCCEEDED(hr)) - { - ComPtr dxgi_factory; - hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); - - if (SUCCEEDED(hr)) - { - dxgi_factory_ = dxgi_factory; - } - } } } } + if (SUCCEEDED(hr)) + { + ComPtr dxgi_adapter; + hr = dxgi_device_->GetAdapter(&dxgi_adapter); + + if (SUCCEEDED(hr)) + { + ComPtr dxgi_factory; + hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); + + if (SUCCEEDED(hr)) + { + dxgi_factory_ = dxgi_factory; + } + } + + if (SUCCEEDED(hr)) + { + hr = dxgi_factory_->MakeWindowAssociation(hwnd_, DXGI_MWA_NO_ALT_ENTER); + } + } + if (SUCCEEDED(hr)) { // Setup swap chain @@ -241,9 +253,10 @@ HRESULT D3D10DeviceResources::CreateDeviceResources() swap_chain_desc.BufferCount = 2; swap_chain_desc.BufferDesc.Width = ::lround(output_size_.x); swap_chain_desc.BufferDesc.Height = ::lround(output_size_.y); - swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + swap_chain_desc.BufferDesc.Format = desired_color_format_; swap_chain_desc.BufferDesc.RefreshRate.Numerator = 60; swap_chain_desc.BufferDesc.RefreshRate.Denominator = 1; + swap_chain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED; swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swap_chain_desc.OutputWindow = hwnd_; @@ -293,7 +306,7 @@ HRESULT D3D10DeviceResources::CreateWindowSizeDependentResources() if (SUCCEEDED(hr)) { D3D10_RENDER_TARGET_VIEW_DESC renderDesc; - renderDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + renderDesc.Format = desired_color_format_; renderDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D; renderDesc.Texture2D.MipSlice = 0; @@ -396,6 +409,85 @@ HRESULT D3D10DeviceResources::SetDpi(float dpi) return S_OK; } +HRESULT D3D10DeviceResources::SetFullscreenState(bool fullscreen) +{ + HRESULT hr = E_FAIL; + if (dxgi_swap_chain_) + { + hr = dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr); + } + return hr; +} + +HRESULT D3D10DeviceResources::GetFullscreenState(bool* fullscreen) +{ + HRESULT hr = E_FAIL; + if (dxgi_swap_chain_) + { + BOOL is_fullscreen; + hr = dxgi_swap_chain_->GetFullscreenState(&is_fullscreen, nullptr); + + if (SUCCEEDED(hr)) + { + (*fullscreen) = (is_fullscreen == TRUE); + } + } + return hr; +} + +HRESULT D3D10DeviceResources::ResizeTarget(UINT width, UINT height) +{ + HRESULT hr = E_FAIL; + if (dxgi_swap_chain_) + { + DXGI_MODE_DESC desc = { 0 }; + desc.Width = width; + desc.Height = height; + desc.Format = DXGI_FORMAT_UNKNOWN; + + hr = dxgi_swap_chain_->ResizeTarget(&desc); + } + return hr; +} + +HRESULT D3D10DeviceResources::GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num) +{ + HRESULT hr = E_FAIL; + if (dxgi_swap_chain_) + { + ComPtr output; + hr = dxgi_swap_chain_->GetContainingOutput(&output); + + if (SUCCEEDED(hr)) + { + UINT num_of_supported_modes = 0; + output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, 0); + + if (num_of_supported_modes > 0) + { + DXGI_MODE_DESC* supported_modes = new DXGI_MODE_DESC[num_of_supported_modes]; + ZeroMemory(supported_modes, sizeof(DXGI_MODE_DESC) * num_of_supported_modes); + + hr = output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, supported_modes); + if (SUCCEEDED(hr) && mode_descs && num) + { + (*mode_descs) = supported_modes; + (*num) = (int)num_of_supported_modes; + } + else + { + delete[] supported_modes; + } + } + else + { + hr = E_FAIL; + } + } + } + return hr; +} + STDMETHODIMP_(unsigned long) D3D10DeviceResources::AddRef() { return InterlockedIncrement(&ref_count_); @@ -439,4 +531,6 @@ STDMETHODIMP D3D10DeviceResources::QueryInterface(const IID& riid, void** object return S_OK; } +} // namespace directx +} // namespace graphics } // namespace kiwano diff --git a/src/kiwano/render/DirectX/D3D10DeviceResources.h b/src/kiwano/render/DirectX/D3D10DeviceResources.h index 7ea02e61..0c12878f 100644 --- a/src/kiwano/render/DirectX/D3D10DeviceResources.h +++ b/src/kiwano/render/DirectX/D3D10DeviceResources.h @@ -26,12 +26,15 @@ namespace kiwano { +namespace graphics +{ +namespace directx +{ + MIDL_INTERFACE("3a150b9d-cc23-4022-a463-7e95452a54c4") KGE_API ID3D10DeviceResources : public ID3DDeviceResourcesBase { public: - static HRESULT Create(ID3D10DeviceResources * *device_resources, HWND hwnd); - inline ID3D10Device* GetDevice() { KGE_ASSERT(device_); @@ -77,4 +80,8 @@ protected: ComPtr dxgi_swap_chain_; }; +extern ComPtr GetD3D11DeviceResources(); + +} // namespace directx +} // namespace graphics } // namespace kiwano diff --git a/src/kiwano/render/DirectX/D3D11DeviceResources.cpp b/src/kiwano/render/DirectX/D3D11DeviceResources.cpp index a78790d3..e767c848 100644 --- a/src/kiwano/render/DirectX/D3D11DeviceResources.cpp +++ b/src/kiwano/render/DirectX/D3D11DeviceResources.cpp @@ -18,8 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include +#include KGE_SUPPRESS_WARNING_PUSH KGE_SUPPRESS_WARNING(4800) // Implicit conversion from 'type' to bool @@ -30,9 +31,16 @@ KGE_SUPPRESS_WARNING_POP namespace kiwano { -#if defined(KGE_DEBUG) -namespace DX +namespace graphics { +namespace directx +{ + +// Global pointer for Direct3D11 device resources +static ComPtr global_d3d11_device_resources; + + +#if defined(KGE_DEBUG) inline bool SdkLayersAvailable() { HRESULT hr = D3D11CreateDevice(nullptr, @@ -45,15 +53,15 @@ inline bool SdkLayersAvailable() nullptr, // No need to know the feature level. nullptr // No need to keep the D3D device context reference. ); - return SUCCEEDED(hr); } -} // namespace DX #endif struct D3D11DeviceResources : public ID3D11DeviceResources { public: + HRESULT Initialize(HWND hwnd) override; + HRESULT Present(bool vsync) override; void ClearRenderTarget(Color& clear_color) override; @@ -64,6 +72,14 @@ public: HRESULT SetDpi(float dpi) override; + HRESULT SetFullscreenState(bool fullscreen) override; + + HRESULT GetFullscreenState(bool* fullscreen) override; + + HRESULT ResizeTarget(UINT width, UINT height) override; + + HRESULT GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num) override; + void DiscardResources() override; public: @@ -90,12 +106,24 @@ public: unsigned long ref_count_; D3D_FEATURE_LEVEL d3d_feature_level_; + DXGI_FORMAT desired_color_format_; }; + +ComPtr GetD3D11DeviceResources() +{ + if (!global_d3d11_device_resources) + { + global_d3d11_device_resources.Reset(new (std::nothrow) D3D11DeviceResources); + } + return global_d3d11_device_resources; +} + D3D11DeviceResources::D3D11DeviceResources() : ref_count_(0) , hwnd_(nullptr) , d3d_feature_level_(D3D_FEATURE_LEVEL_9_1) + , desired_color_format_(DXGI_FORMAT_B8G8R8A8_UNORM) { dpi_ = 96.f; // dpi_ = (float)GetDpiForWindow(hwnd); } @@ -105,55 +133,34 @@ D3D11DeviceResources::~D3D11DeviceResources() DiscardResources(); } -HRESULT ID3D11DeviceResources::Create(ID3D11DeviceResources** device_resources, HWND hwnd) +HRESULT D3D11DeviceResources::Initialize(HWND hwnd) { - HRESULT hr = E_FAIL; + RECT rc; + ::GetClientRect(hwnd, &rc); - if (device_resources) + this->hwnd_ = hwnd; + this->logical_size_.x = float(rc.right - rc.left); + this->logical_size_.y = float(rc.bottom - rc.top); + + HRESULT hr = this->CreateDeviceResources(); + + if (SUCCEEDED(hr)) { - D3D11DeviceResources* res = new (std::nothrow) D3D11DeviceResources; - if (res) - { - RECT rc; - ::GetClientRect(hwnd, &rc); - - res->hwnd_ = hwnd; - res->logical_size_.x = float(rc.right - rc.left); - res->logical_size_.y = float(rc.bottom - rc.top); - - hr = res->CreateDeviceResources(); - - if (SUCCEEDED(hr)) - { - hr = res->CreateWindowSizeDependentResources(); - } - - if (SUCCEEDED(hr)) - { - res->AddRef(); - - if (*device_resources) - { - (*device_resources)->Release(); - } - (*device_resources) = res; - } - else - { - delete res; - res = nullptr; - } - } + hr = this->CreateWindowSizeDependentResources(); } return hr; } HRESULT D3D11DeviceResources::Present(bool vsync) { - KGE_ASSERT(dxgi_swap_chain_ != nullptr); + HRESULT hr = E_FAIL; - // The first argument instructs DXGI to block until VSync. - return dxgi_swap_chain_->Present(vsync ? 1 : 0, 0); + if (dxgi_swap_chain_) + { + // The first argument instructs DXGI to block until VSync. + hr = dxgi_swap_chain_->Present(vsync ? 1 : 0, DXGI_PRESENT_DO_NOT_WAIT); + } + return hr; } void D3D11DeviceResources::ClearRenderTarget(Color& clear_color) @@ -195,7 +202,7 @@ HRESULT D3D11DeviceResources::CreateDeviceResources() uint32_t creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG) - if (DX::SdkLayersAvailable()) + if (SdkLayersAvailable()) { creation_flags |= D3D11_CREATE_DEVICE_DEBUG; } @@ -237,21 +244,29 @@ HRESULT D3D11DeviceResources::CreateDeviceResources() if (SUCCEEDED(hr)) { dxgi_device_ = dxgi_device; + } + } - ComPtr dxgi_adapter; - hr = dxgi_device_->GetAdapter(&dxgi_adapter); + if (SUCCEEDED(hr)) + { + ComPtr dxgi_adapter; + hr = dxgi_device_->GetAdapter(&dxgi_adapter); + + if (SUCCEEDED(hr)) + { + ComPtr dxgi_factory; + hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); if (SUCCEEDED(hr)) { - ComPtr dxgi_factory; - hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); - - if (SUCCEEDED(hr)) - { - dxgi_factory_ = dxgi_factory; - } + dxgi_factory_ = dxgi_factory; } } + + if (SUCCEEDED(hr)) + { + hr = dxgi_factory_->MakeWindowAssociation(hwnd_, DXGI_MWA_NO_ALT_ENTER); + } } } @@ -263,9 +278,10 @@ HRESULT D3D11DeviceResources::CreateDeviceResources() swap_chain_desc.BufferCount = 2; swap_chain_desc.BufferDesc.Width = ::lround(output_size_.x); swap_chain_desc.BufferDesc.Height = ::lround(output_size_.y); - swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + swap_chain_desc.BufferDesc.Format = desired_color_format_; swap_chain_desc.BufferDesc.RefreshRate.Numerator = 60; swap_chain_desc.BufferDesc.RefreshRate.Denominator = 1; + swap_chain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED; swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swap_chain_desc.OutputWindow = hwnd_; @@ -320,8 +336,9 @@ HRESULT D3D11DeviceResources::CreateWindowSizeDependentResources() output_size_.x = std::max(output_size_.x, 1.f); output_size_.y = std::max(output_size_.y, 1.f); - hr = dxgi_swap_chain_->ResizeBuffers(2, // Double-buffered swap chain. - ::lround(output_size_.x), ::lround(output_size_.y), DXGI_FORMAT_UNKNOWN, 0); + hr = dxgi_swap_chain_->ResizeBuffers(2, /* Double-buffered swap chain */ + ::lround(output_size_.x), ::lround(output_size_.y), DXGI_FORMAT_UNKNOWN, + DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); if (SUCCEEDED(hr)) { @@ -371,7 +388,6 @@ HRESULT D3D11DeviceResources::CreateWindowSizeDependentResources() device_context_->RSSetViewports(1, &screen_viewport); } - return hr; } @@ -416,6 +432,85 @@ HRESULT D3D11DeviceResources::SetDpi(float dpi) return S_OK; } +HRESULT D3D11DeviceResources::SetFullscreenState(bool fullscreen) +{ + HRESULT hr = E_FAIL; + if (dxgi_swap_chain_) + { + hr = dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr); + } + return hr; +} + +HRESULT D3D11DeviceResources::GetFullscreenState(bool* fullscreen) +{ + HRESULT hr = E_FAIL; + if (dxgi_swap_chain_) + { + BOOL is_fullscreen; + hr = dxgi_swap_chain_->GetFullscreenState(&is_fullscreen, nullptr); + + if (SUCCEEDED(hr)) + { + (*fullscreen) = (is_fullscreen == TRUE); + } + } + return hr; +} + +HRESULT D3D11DeviceResources::ResizeTarget(UINT width, UINT height) +{ + HRESULT hr = E_FAIL; + if (dxgi_swap_chain_) + { + DXGI_MODE_DESC desc = { 0 }; + desc.Width = width; + desc.Height = height; + desc.Format = DXGI_FORMAT_UNKNOWN; + + hr = dxgi_swap_chain_->ResizeTarget(&desc); + } + return hr; +} + +HRESULT D3D11DeviceResources::GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num) +{ + HRESULT hr = E_FAIL; + if (dxgi_swap_chain_) + { + ComPtr output; + HRESULT hr = dxgi_swap_chain_->GetContainingOutput(&output); + + if (SUCCEEDED(hr)) + { + UINT num_of_supported_modes = 0; + output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, 0); + + if (num_of_supported_modes > 0) + { + DXGI_MODE_DESC* supported_modes = new DXGI_MODE_DESC[num_of_supported_modes]; + ZeroMemory(supported_modes, sizeof(DXGI_MODE_DESC) * num_of_supported_modes); + + hr = output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, supported_modes); + if (SUCCEEDED(hr) && mode_descs && num) + { + (*mode_descs) = supported_modes; + (*num) = (int)num_of_supported_modes; + } + else + { + delete[] supported_modes; + } + } + else + { + hr = E_FAIL; + } + } + } + return hr; +} + STDMETHODIMP_(unsigned long) D3D11DeviceResources::AddRef() { return InterlockedIncrement(&ref_count_); @@ -459,4 +554,6 @@ STDMETHODIMP D3D11DeviceResources::QueryInterface(const IID& riid, void** object return S_OK; } +} // namespace directx +} // namespace graphics } // namespace kiwano diff --git a/src/kiwano/render/DirectX/D3D11DeviceResources.h b/src/kiwano/render/DirectX/D3D11DeviceResources.h index 1cb12daf..3950a7e6 100644 --- a/src/kiwano/render/DirectX/D3D11DeviceResources.h +++ b/src/kiwano/render/DirectX/D3D11DeviceResources.h @@ -26,12 +26,15 @@ namespace kiwano { +namespace graphics +{ +namespace directx +{ + MIDL_INTERFACE("3ede2b87-a202-4799-a39b-2308ad34cae8") KGE_API ID3D11DeviceResources : public ID3DDeviceResourcesBase { public: - static HRESULT Create(ID3D11DeviceResources * *device_resources, HWND hwnd); - inline ID3D11Device* GetDevice() { KGE_ASSERT(device_); @@ -84,4 +87,8 @@ protected: ComPtr dxgi_swap_chain_; }; +extern ComPtr GetD3D11DeviceResources(); + +} // namespace directx +} // namespace graphics } // namespace kiwano diff --git a/src/kiwano/render/DirectX/D3DDeviceResources.h b/src/kiwano/render/DirectX/D3DDeviceResources.h new file mode 100644 index 00000000..fd625ba5 --- /dev/null +++ b/src/kiwano/render/DirectX/D3DDeviceResources.h @@ -0,0 +1,54 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#pragma once + +#if defined(KGE_USE_DIRECTX10) +#include +#else +#include +#endif + +namespace kiwano +{ +namespace graphics +{ +namespace directx +{ + +#if defined(KGE_USE_DIRECTX10) + using ID3DDeviceResources = kiwano::graphics::directx::ID3D10DeviceResources; + + inline ComPtr GetD3DDeviceResources() + { + return kiwano::graphics::directx::GetD3D10DeviceResources(); + } +#else + using ID3DDeviceResources = kiwano::graphics::directx::ID3D11DeviceResources; + + inline ComPtr GetD3DDeviceResources() + { + return kiwano::graphics::directx::GetD3D11DeviceResources(); + } +#endif + +} // namespace directx +} // namespace graphics +} // namespace kiwano diff --git a/src/kiwano/render/DirectX/D3DDeviceResourcesBase.h b/src/kiwano/render/DirectX/D3DDeviceResourcesBase.h index 5cdde8b1..a14ab67b 100644 --- a/src/kiwano/render/DirectX/D3DDeviceResourcesBase.h +++ b/src/kiwano/render/DirectX/D3DDeviceResourcesBase.h @@ -23,10 +23,17 @@ namespace kiwano { +namespace graphics +{ +namespace directx +{ + MIDL_INTERFACE("fb99fa64-d9cf-4e0e-9c75-90514797b01d") ID3DDeviceResourcesBase : public IUnknown { public: + virtual HRESULT Initialize(HWND hwnd) = 0; + virtual HRESULT Present(bool vsync) = 0; virtual void ClearRenderTarget(Color & clear_color) = 0; @@ -37,7 +44,17 @@ public: virtual HRESULT SetDpi(float dpi) = 0; + virtual HRESULT SetFullscreenState(bool fullscreen) = 0; + + virtual HRESULT GetFullscreenState(bool* fullscreen) = 0; + + virtual HRESULT ResizeTarget(UINT width, UINT height) = 0; + + virtual HRESULT GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num) = 0; + virtual void DiscardResources() = 0; }; +} // namespace directx +} // namespace graphics } // namespace kiwano diff --git a/src/kiwano/render/DirectX/RenderContextImpl.cpp b/src/kiwano/render/DirectX/RenderContextImpl.cpp index cbf90978..25a4ada6 100644 --- a/src/kiwano/render/DirectX/RenderContextImpl.cpp +++ b/src/kiwano/render/DirectX/RenderContextImpl.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include namespace kiwano { diff --git a/src/kiwano/render/DirectX/RendererImpl.cpp b/src/kiwano/render/DirectX/RendererImpl.cpp index fe48773c..49f496d8 100644 --- a/src/kiwano/render/DirectX/RendererImpl.cpp +++ b/src/kiwano/render/DirectX/RendererImpl.cpp @@ -19,17 +19,21 @@ // THE SOFTWARE. #include -#include -#include +#include +#include #include #include #include #include #include +#include + namespace kiwano { +using namespace kiwano::graphics::directx; + Renderer& Renderer::GetInstance() { return RendererImpl::GetInstance(); @@ -54,65 +58,51 @@ void RendererImpl::MakeContextForWindow(WindowPtr window) HWND target_window = window->GetHandle(); output_size_ = window->GetSize(); - d2d_res_ = nullptr; - d3d_res_ = nullptr; + d2d_res_ = graphics::directx::GetD2DDeviceResources(); + d3d_res_ = graphics::directx::GetD3DDeviceResources(); HRESULT hr = target_window ? S_OK : E_FAIL; - // Direct3D device resources + // Initialize other device resources if (SUCCEEDED(hr)) { - hr = ID3DDeviceResources::Create(&d3d_res_, target_window); + RenderContextImplPtr ctx = memory::New(); - // Direct2D device resources + hr = ctx->CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); if (SUCCEEDED(hr)) { - hr = ID2DDeviceResources::Create(&d2d_res_, d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain()); + render_ctx_ = ctx; + } + } + + // FontFileLoader and FontCollectionLoader + if (SUCCEEDED(hr)) + { + hr = IFontCollectionLoader::Create(&font_collection_loader_); + + if (SUCCEEDED(hr)) + { + hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.Get()); + } + } + + // ResourceFontFileLoader and ResourceFontCollectionLoader + if (SUCCEEDED(hr)) + { + hr = IResourceFontFileLoader::Create(&res_font_file_loader_); + + if (SUCCEEDED(hr)) + { + hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.Get()); + } + + if (SUCCEEDED(hr)) + { + hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, res_font_file_loader_.Get()); - // Other device resources if (SUCCEEDED(hr)) { - RenderContextImplPtr ctx = memory::New(); - - hr = ctx->CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); - if (SUCCEEDED(hr)) - { - render_ctx_ = ctx; - } - } - - // FontFileLoader and FontCollectionLoader - if (SUCCEEDED(hr)) - { - hr = IFontCollectionLoader::Create(&font_collection_loader_); - - if (SUCCEEDED(hr)) - { - hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.Get()); - } - } - - // ResourceFontFileLoader and ResourceFontCollectionLoader - if (SUCCEEDED(hr)) - { - hr = IResourceFontFileLoader::Create(&res_font_file_loader_); - - if (SUCCEEDED(hr)) - { - hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.Get()); - } - - if (SUCCEEDED(hr)) - { - hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, - res_font_file_loader_.Get()); - - if (SUCCEEDED(hr)) - { - hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader( - res_font_collection_loader_.Get()); - } - } + hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(res_font_collection_loader_.Get()); } } } @@ -149,7 +139,10 @@ void RendererImpl::Present() KGE_ASSERT(d3d_res_); HRESULT hr = d3d_res_->Present(vsync_); - KGE_THROW_IF_FAILED(hr, "Unexpected DXGI exception"); + if (FAILED(hr) && hr != DXGI_ERROR_WAS_STILL_DRAWING) + { + KGE_THROW_IF_FAILED(hr, "Unexpected DXGI exception"); + } } void RendererImpl::CreateTexture(Texture& texture, const String& file_path) diff --git a/src/kiwano/render/DirectX/RendererImpl.h b/src/kiwano/render/DirectX/RendererImpl.h index f2a1e13a..edddaa45 100644 --- a/src/kiwano/render/DirectX/RendererImpl.h +++ b/src/kiwano/render/DirectX/RendererImpl.h @@ -20,24 +20,14 @@ #pragma once #include +#include #include #include -#if defined(KGE_USE_DIRECTX10) -#include -#else -#include -#endif namespace kiwano { -#if defined(KGE_USE_DIRECTX10) -typedef ID3D10DeviceResources ID3DDeviceResources; -#else -typedef ID3D11DeviceResources ID3DDeviceResources; -#endif - class KGE_API RendererImpl : public Renderer { @@ -87,16 +77,6 @@ public: void Present() override; - /// \~chinese - /// @brief ȡDirect2D豸Դ - ID2DDeviceResources* GetD2DDeviceResources(); - - /// \~chinese - /// @brief ȡDirect3D豸Դ - ID3DDeviceResources* GetD3DDeviceResources(); - - /// \~chinese - /// @brief ȾС void Resize(uint32_t width, uint32_t height) override; protected: @@ -107,6 +87,9 @@ protected: void Destroy() override; private: + using ID2DDeviceResources = kiwano::graphics::directx::ID2DDeviceResources; + using ID3DDeviceResources = kiwano::graphics::directx::ID3DDeviceResources; + ComPtr d2d_res_; ComPtr d3d_res_; ComPtr font_collection_loader_; @@ -114,18 +97,7 @@ private: ComPtr res_font_collection_loader_; }; + /** @} */ -inline ID2DDeviceResources* RendererImpl::GetD2DDeviceResources() -{ - KGE_ASSERT(d2d_res_); - return d2d_res_.Get(); -} - -inline ID3DDeviceResources* RendererImpl::GetD3DDeviceResources() -{ - KGE_ASSERT(d3d_res_); - return d3d_res_.Get(); -} - } // namespace kiwano diff --git a/src/kiwano/render/DirectX/helper.h b/src/kiwano/render/DirectX/helper.h index 53f4ceae..5461cac8 100644 --- a/src/kiwano/render/DirectX/helper.h +++ b/src/kiwano/render/DirectX/helper.h @@ -29,6 +29,7 @@ namespace kiwano { namespace DX { + template inline void SafeRelease(T*& ptr) { @@ -174,5 +175,6 @@ inline float ConvertDipsToPixels(float dips, float dpi) static const float dips_per_inch = 96.0f; return math::Floor(dips * dpi / dips_per_inch + 0.5f); // Round to nearest integer. } + } // namespace DX } // namespace kiwano diff --git a/src/kiwano/2d/Frame.cpp b/src/kiwano/render/Frame.cpp similarity index 98% rename from src/kiwano/2d/Frame.cpp rename to src/kiwano/render/Frame.cpp index 9e9f95be..2c42cd7c 100644 --- a/src/kiwano/2d/Frame.cpp +++ b/src/kiwano/render/Frame.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include namespace kiwano diff --git a/src/kiwano/2d/Frame.h b/src/kiwano/render/Frame.h similarity index 99% rename from src/kiwano/2d/Frame.h rename to src/kiwano/render/Frame.h index a425f22b..f0679724 100644 --- a/src/kiwano/2d/Frame.h +++ b/src/kiwano/render/Frame.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include #include namespace kiwano diff --git a/src/kiwano/2d/FrameSequence.cpp b/src/kiwano/render/FrameSequence.cpp similarity index 98% rename from src/kiwano/2d/FrameSequence.cpp rename to src/kiwano/render/FrameSequence.cpp index 008517fe..03fd4a85 100644 --- a/src/kiwano/2d/FrameSequence.cpp +++ b/src/kiwano/render/FrameSequence.cpp @@ -18,8 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include -#include +#include +#include namespace kiwano { diff --git a/src/kiwano/2d/FrameSequence.h b/src/kiwano/render/FrameSequence.h similarity index 99% rename from src/kiwano/2d/FrameSequence.h rename to src/kiwano/render/FrameSequence.h index 681ecfd2..904eba8d 100644 --- a/src/kiwano/2d/FrameSequence.h +++ b/src/kiwano/render/FrameSequence.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include #include #include diff --git a/src/kiwano/render/GifImage.cpp b/src/kiwano/render/GifImage.cpp index 79e942f5..da775009 100644 --- a/src/kiwano/render/GifImage.cpp +++ b/src/kiwano/render/GifImage.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include #include diff --git a/src/kiwano/render/NativeObject.h b/src/kiwano/render/NativeObject.h index 4b83b322..fc020b23 100644 --- a/src/kiwano/render/NativeObject.h +++ b/src/kiwano/render/NativeObject.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX #include diff --git a/src/kiwano/render/RenderContext.cpp b/src/kiwano/render/RenderContext.cpp index fcb281d2..0bd36a47 100644 --- a/src/kiwano/render/RenderContext.cpp +++ b/src/kiwano/render/RenderContext.cpp @@ -60,6 +60,22 @@ void RenderContext::EndDraw() } } +void RenderContext::DrawFrame(FramePtr frame, const Point& dest_pos) +{ + if (frame) + { + this->DrawTexture(*frame->GetTexture(), &frame->GetCropRect(), &Rect(dest_pos, frame->GetSize())); + } +} + +void RenderContext::DrawFrame(FramePtr frame, const Rect& dest_rect) +{ + if (frame) + { + this->DrawTexture(*frame->GetTexture(), &frame->GetCropRect(), &dest_rect); + } +} + void RenderContext::SetGlobalTransform(const Matrix3x2* matrix) { if (matrix) @@ -121,4 +137,14 @@ void RenderContext::SetCurrentStrokeStyle(StrokeStylePtr stroke) current_stroke_ = stroke; } +void RenderContext::DrawCircle(const Point& center, float radius) +{ + this->DrawEllipse(center, Vec2(radius, radius)); +} + +void RenderContext::FillCircle(const Point& center, float radius) +{ + this->FillEllipse(center, Vec2(radius, radius)); +} + } // namespace kiwano diff --git a/src/kiwano/render/RenderContext.h b/src/kiwano/render/RenderContext.h index 8bafec7c..6f2199a0 100644 --- a/src/kiwano/render/RenderContext.h +++ b/src/kiwano/render/RenderContext.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace kiwano { @@ -79,6 +80,18 @@ public: virtual void DrawTexture(const Texture& texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr) = 0; + /// \~chinese + /// @brief ͼ֡ + /// @param frame ͼ֡ + /// @param dest_pos ͼλ + virtual void DrawFrame(FramePtr frame, const Point& dest_pos); + + /// \~chinese + /// @brief ͼ֡ + /// @param frame ͼ֡ + /// @param dest_rect ƵĿ + virtual void DrawFrame(FramePtr frame, const Rect& dest_rect); + /// \~chinese /// @brief ı /// @param layout ı @@ -107,6 +120,12 @@ public: /// @param radius Բǰ뾶 virtual void DrawRoundedRectangle(const Rect& rect, const Vec2& radius) = 0; + /// \~chinese + /// @brief Բα߿ + /// @param center Բ + /// @param radius Բ뾶 + virtual void DrawCircle(const Point& center, float radius); + /// \~chinese /// @brief Բ߿ /// @param center Բ @@ -129,6 +148,12 @@ public: /// @param radius Բǰ뾶 virtual void FillRoundedRectangle(const Rect& rect, const Vec2& radius) = 0; + /// \~chinese + /// @brief Բ + /// @param center Բ + /// @param radius Բ뾶 + virtual void FillCircle(const Point& center, float radius); + /// \~chinese /// @brief Բ /// @param center Բ diff --git a/src/kiwano/render/Renderer.cpp b/src/kiwano/render/Renderer.cpp index f25086ef..a95d65d4 100644 --- a/src/kiwano/render/Renderer.cpp +++ b/src/kiwano/render/Renderer.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include #include namespace kiwano @@ -44,11 +44,7 @@ void Renderer::DestroyModule() void Renderer::HandleEvent(Event* evt) { - if (evt->IsType()) - { - auto window_evt = dynamic_cast(evt); - Resize(window_evt->width, window_evt->height); - } + // DO NOTHING } void Renderer::BeginDraw() diff --git a/src/kiwano/render/Renderer.h b/src/kiwano/render/Renderer.h index ac03ca20..a42b3c7c 100644 --- a/src/kiwano/render/Renderer.h +++ b/src/kiwano/render/Renderer.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include #include #include #include @@ -39,6 +39,7 @@ namespace kiwano * @{ */ + /** * \~chinese * @brief Ⱦ @@ -54,6 +55,18 @@ public: /// @brief ȡɫ virtual Color GetClearColor() const; + /// \~chinese + /// @brief ȡȾС + Size GetOutputSize() const; + + /// \~chinese + /// @brief ȡȾ + RenderContext& GetContext(); + + /// \~chinese + /// @brief ȾС + virtual void Resize(uint32_t width, uint32_t height) = 0; + /// \~chinese /// @brief ɫ virtual void SetClearColor(const Color& clear_color); @@ -205,14 +218,6 @@ public: virtual RenderContextPtr CreateTextureRenderContext(Texture& texture, const Size* desired_size = nullptr) = 0; public: - /// \~chinese - /// @brief ȡȾ - RenderContext& GetContext(); - - /// \~chinese - /// @brief ȡȾС - Size GetOutputSize() const; - /// \~chinese /// @brief ʼȾ virtual void BeginDraw(); @@ -230,10 +235,6 @@ public: /// @throw kiwano::SystemError ʧʱ׳ virtual void Present() = 0; - /// \~chinese - /// @brief ȾС - virtual void Resize(uint32_t width, uint32_t height) = 0; - public: void SetupModule() override; diff --git a/src/kiwano/render/TextureCache.cpp b/src/kiwano/render/TextureCache.cpp index 27b74545..847ece2b 100644 --- a/src/kiwano/render/TextureCache.cpp +++ b/src/kiwano/render/TextureCache.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include #include #include diff --git a/src/kiwano/utils/EventTicker.cpp b/src/kiwano/utils/EventTicker.cpp new file mode 100644 index 00000000..609a918c --- /dev/null +++ b/src/kiwano/utils/EventTicker.cpp @@ -0,0 +1,57 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#include + +namespace kiwano +{ + +TickEvent::TickEvent() + : Event(KGE_EVENT(TickEvent)) + , ticker_(nullptr) +{ +} + +EventTickerPtr EventTicker::Create(Duration interval, int times) +{ + EventTickerPtr ptr = memory::New(); + if (ptr) + { + ptr->SetInterval(interval); + ptr->SetTotalTickCount(times); + } + return ptr; +} + +bool EventTicker::Tick(Duration dt) +{ + if (Ticker::Tick(dt)) + { + TickEventPtr evt = new TickEvent; + evt->delta_time_ = GetDeltaTime(); + evt->ticker_ = this; + DispatchEvent(evt.Get()); + + return true; + } + return false; +} + +} // namespace kiwano diff --git a/src/kiwano/utils/EventTicker.h b/src/kiwano/utils/EventTicker.h new file mode 100644 index 00000000..c1fd82d3 --- /dev/null +++ b/src/kiwano/utils/EventTicker.h @@ -0,0 +1,71 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#pragma once +#include +#include +#include + +namespace kiwano +{ + +KGE_DECLARE_SMART_PTR(TickEvent); +KGE_DECLARE_SMART_PTR(EventTicker); + +/** + * \addtogroup Events + * @{ + */ + +/// \~chinese +/// @brief ʱʱ +class KGE_API TickEvent : public Event +{ +public: + TickEvent(); + + EventTicker* ticker_; + Duration delta_time_; +}; + +/** + * @} + */ + + +/// \~chinese +/// @brief ¼ʱ +class KGE_API EventTicker + : public Ticker + , public EventDispatcher +{ +public: + /// \~chinese + /// @brief ¼ʱ + /// @param interval ʱ + /// @param times ʱ -1 Ϊã + static EventTickerPtr Create(Duration interval, int times = -1); + + using Ticker::Tick; + + bool Tick(Duration dt) override; +}; + +} // namespace kiwano diff --git a/src/kiwano/core/Json.h b/src/kiwano/utils/Json.h similarity index 100% rename from src/kiwano/core/Json.h rename to src/kiwano/utils/Json.h diff --git a/src/kiwano/utils/LocalStorage.h b/src/kiwano/utils/LocalStorage.h index 6972a5c9..d3475cab 100644 --- a/src/kiwano/utils/LocalStorage.h +++ b/src/kiwano/utils/LocalStorage.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include namespace kiwano { diff --git a/src/kiwano/core/Logger.cpp b/src/kiwano/utils/Logger.cpp similarity index 99% rename from src/kiwano/core/Logger.cpp rename to src/kiwano/utils/Logger.cpp index 3b958817..cc1c42e9 100644 --- a/src/kiwano/core/Logger.cpp +++ b/src/kiwano/utils/Logger.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include namespace { @@ -298,7 +298,7 @@ void Logger::ResetStreamToStdStream() } // replace the C++ global locale with the user-preferred locale - (void)std::locale::global(std::locale("")); + (void)std::locale::global(std::locale()); (void)std::cout.imbue(std::locale()); (void)std::cerr.imbue(std::locale()); diff --git a/src/kiwano/core/Logger.h b/src/kiwano/utils/Logger.h similarity index 95% rename from src/kiwano/core/Logger.h rename to src/kiwano/utils/Logger.h index 8f24fe34..b4177507 100644 --- a/src/kiwano/core/Logger.h +++ b/src/kiwano/utils/Logger.h @@ -19,10 +19,9 @@ // THE SOFTWARE. #pragma once -#include #include -#include -#include +#include +#include #ifndef KGE_SYS_LOG #ifdef KGE_DEBUG @@ -49,6 +48,14 @@ #define KGE_LOGF(FORMAT, ...) ::kiwano::Logger::GetInstance().Printf(::kiwano::Logger::Level::Info, FORMAT, __VA_ARGS__) #endif +#ifndef KGE_LOG_STREAM +#define KGE_LOG_STREAM() ::kiwano::Logger::GetInstance().GetOutputStream() +#endif + +#ifndef KGE_ERROR_STREAM +#define KGE_ERROR_STREAM() ::kiwano::Logger::GetInstance().GetErrorStream() +#endif + namespace kiwano { /** diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index 11398a40..be4b75bb 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #include -#include +#include #include #include #include diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h index 7917f30f..e6aaa9e8 100644 --- a/src/kiwano/utils/ResourceCache.h +++ b/src/kiwano/utils/ResourceCache.h @@ -19,11 +19,11 @@ // THE SOFTWARE. #pragma once -#include -#include #include -#include -#include +#include +#include +#include +#include #include #include diff --git a/src/kiwano/core/Timer.cpp b/src/kiwano/utils/Task.cpp similarity index 60% rename from src/kiwano/core/Timer.cpp rename to src/kiwano/utils/Task.cpp index ab72cb03..89f25f24 100644 --- a/src/kiwano/core/Timer.cpp +++ b/src/kiwano/utils/Task.cpp @@ -18,79 +18,72 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include namespace kiwano { - -TimerPtr Timer::Create(const Callback& cb, Duration interval, int times) +TaskPtr Task::Create(const Callback& cb, TickerPtr ticker) { - TimerPtr ptr = memory::New(); + TaskPtr ptr = memory::New(); if (ptr) { ptr->SetCallback(cb); - ptr->SetInterval(interval); - ptr->SetTotalRunTimes(times); + ptr->SetTicker(ticker); } return ptr; } -TimerPtr Timer::Create(const String& name, const Callback& cb, Duration interval, int times) +TaskPtr Task::Create(const String& name, const Callback& cb, TickerPtr ticker) { - TimerPtr ptr = memory::New(); + TaskPtr ptr = Task::Create(cb, ticker); if (ptr) { ptr->SetName(name); - ptr->SetCallback(cb); - ptr->SetInterval(interval); - ptr->SetTotalRunTimes(times); } return ptr; } -Timer::Timer() +TaskPtr Task::Create(const Callback& cb, Duration interval, int times) +{ + TickerPtr ticker = Ticker::Create(interval, times); + return Task::Create(cb, ticker); +} + +TaskPtr Task::Create(const String& name, const Callback& cb, Duration interval, int times) +{ + TickerPtr ticker = Ticker::Create(interval, times); + return Task::Create(name, cb, ticker); +} + +Task::Task() : running_(true) , removeable_(false) - , run_times_(0) - , total_times_(0) - , interval_(0) - , elapsed_(0) , callback_() { } -void Timer::Update(Duration dt) +void Task::Update(Duration dt) { - if (total_times_ == 0) + if (!ticker_ || ticker_->GetTotalTickCount() == 0) { Remove(); return; } - if (IsRunning()) + if (ticker_->Tick(dt)) { - if (!interval_.IsZero()) - { - elapsed_ += dt; - if (elapsed_ < interval_) - return; - } - if (callback_) - callback_(this, elapsed_); + callback_(this, ticker_->GetDeltaTime()); - ++run_times_; - elapsed_ = 0; - - if (run_times_ == total_times_) + if (ticker_->GetTickedCount() == ticker_->GetTotalTickCount()) Remove(); } } -void Timer::Reset() +void Task::Reset() { - elapsed_ = 0; - run_times_ = 0; + if (ticker_) + ticker_->Reset(); } } // namespace kiwano diff --git a/src/kiwano/utils/Task.h b/src/kiwano/utils/Task.h new file mode 100644 index 00000000..09b27dba --- /dev/null +++ b/src/kiwano/utils/Task.h @@ -0,0 +1,176 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#pragma once +#include +#include + +namespace kiwano +{ +class TaskScheduler; + +KGE_DECLARE_SMART_PTR(Task); + +/// \~chinese +/// @brief +/// @details ÿһʱִһλصҿִָܴ +class KGE_API Task + : public ObjectBase + , protected IntrusiveListValue +{ + friend class TaskScheduler; + friend IntrusiveList; + +public: + /// \~chinese + /// @brief ص + /// @details + /// صһڶʱ + using Callback = Function; + + /// \~chinese + /// @brief + /// @param cb ص + /// @param ʱ + static TaskPtr Create(const Callback& cb, TickerPtr ticker); + + /// \~chinese + /// @brief + /// @param name + /// @param cb ص + /// @param ʱ + static TaskPtr Create(const String& name, const Callback& cb, TickerPtr ticker); + + /// \~chinese + /// @brief + /// @param cb ص + /// @param interval ʱ + /// @param times ִд -1 ΪִУ + static TaskPtr Create(const Callback& cb, Duration interval, int times = -1); + + /// \~chinese + /// @brief + /// @param name + /// @param cb ص + /// @param interval ʱ + /// @param times ִд -1 ΪִУ + static TaskPtr Create(const String& name, const Callback& cb, Duration interval, int times = -1); + + /// \~chinese + /// @brief + Task(); + + /// \~chinese + /// @brief + void Start(); + + /// \~chinese + /// @brief ֹͣ + void Stop(); + + /// \~chinese + /// @brief Ƴ + void Remove(); + + /// \~chinese + /// @brief Ƿ + bool IsRunning() const; + + /// \~chinese + /// @brief ǷƳ + bool IsRemoveable() const; + + /// \~chinese + /// @brief ȡص + Callback GetCallback() const; + + /// \~chinese + /// @brief ص + void SetCallback(const Callback& callback); + + /// \~chinese + /// @brief ȡıʱ + TickerPtr GetTicker() const; + + /// \~chinese + /// @brief ıʱ + void SetTicker(TickerPtr ticker); + +private: + /// \~chinese + /// @brief + void Update(Duration dt); + + /// \~chinese + /// @brief + void Reset(); + +private: + bool running_; + bool removeable_; + TickerPtr ticker_; + Callback callback_; +}; + +inline void Task::Start() +{ + running_ = true; +} + +inline void Task::Stop() +{ + running_ = false; +} + +inline void Task::Remove() +{ + removeable_ = true; +} + +inline bool Task::IsRunning() const +{ + return running_; +} + +inline bool Task::IsRemoveable() const +{ + return removeable_; +} + +inline TickerPtr Task::GetTicker() const +{ + return ticker_; +} + +inline void Task::SetTicker(TickerPtr ticker) +{ + ticker_ = ticker; +} + +inline Task::Callback Task::GetCallback() const +{ + return callback_; +} + +inline void Task::SetCallback(const Task::Callback& callback) +{ + callback_ = callback; +} +} // namespace kiwano diff --git a/src/kiwano/utils/TaskScheduler.cpp b/src/kiwano/utils/TaskScheduler.cpp new file mode 100644 index 00000000..bf8ab4e3 --- /dev/null +++ b/src/kiwano/utils/TaskScheduler.cpp @@ -0,0 +1,130 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#include +#include + +namespace kiwano +{ + +void TaskScheduler::Update(Duration dt) +{ + if (tasks_.IsEmpty()) + return; + + TaskPtr next; + for (auto task = tasks_.GetFirst(); task; task = next) + { + next = task->GetNext(); + + task->Update(dt); + + if (task->IsRemoveable()) + tasks_.Remove(task); + } +} + +Task* TaskScheduler::AddTask(TaskPtr task) +{ + KGE_ASSERT(task && "AddTask failed, NULL pointer exception"); + + if (task) + { + task->Reset(); + tasks_.PushBack(task); + } + + return task.Get(); +} + +void TaskScheduler::StopTasks(const String& name) +{ + if (tasks_.IsEmpty()) + return; + + for (auto& task : tasks_) + { + if (task->IsName(name)) + { + task->Stop(); + } + } +} + +void TaskScheduler::StartTasks(const String& name) +{ + if (tasks_.IsEmpty()) + return; + + for (auto& task : tasks_) + { + if (task->IsName(name)) + { + task->Start(); + } + } +} + +void TaskScheduler::RemoveTasks(const String& name) +{ + if (tasks_.IsEmpty()) + return; + + for (auto& task : tasks_) + { + if (task->IsName(name)) + { + task->Remove(); + } + } +} + +void TaskScheduler::StopAllTasks() +{ + if (tasks_.IsEmpty()) + return; + + for (auto& task : tasks_) + { + task->Stop(); + } +} + +void TaskScheduler::StartAllTasks() +{ + if (tasks_.IsEmpty()) + return; + + for (auto& task : tasks_) + { + task->Start(); + } +} + +void TaskScheduler::RemoveAllTasks() +{ + tasks_.Clear(); +} + +const TaskList& TaskScheduler::GetAllTasks() const +{ + return tasks_; +} +} // namespace kiwano diff --git a/src/kiwano/utils/TaskScheduler.h b/src/kiwano/utils/TaskScheduler.h new file mode 100644 index 00000000..65ee6b5a --- /dev/null +++ b/src/kiwano/utils/TaskScheduler.h @@ -0,0 +1,78 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#pragma once +#include + +namespace kiwano +{ + +/// \~chinese +/// @brief б +typedef IntrusiveList TaskList; + +/** + * \~chinese + * @brief + */ +class KGE_API TaskScheduler +{ +public: + /// \~chinese + /// @brief + Task* AddTask(TaskPtr task); + + /// \~chinese + /// @brief + void StartTasks(const String& task_name); + + /// \~chinese + /// @brief ֹͣ + void StopTasks(const String& task_name); + + /// \~chinese + /// @brief Ƴ + void RemoveTasks(const String& task_name); + + /// \~chinese + /// @brief + void StartAllTasks(); + + /// \~chinese + /// @brief ֹͣ + void StopAllTasks(); + + /// \~chinese + /// @brief Ƴ + void RemoveAllTasks(); + + /// \~chinese + /// @brief ȡ + const TaskList& GetAllTasks() const; + + /// \~chinese + /// @brief µ + void Update(Duration dt); + +private: + TaskList tasks_; +}; + +} // namespace kiwano diff --git a/src/kiwano/utils/Ticker.cpp b/src/kiwano/utils/Ticker.cpp new file mode 100644 index 00000000..d44dc5ac --- /dev/null +++ b/src/kiwano/utils/Ticker.cpp @@ -0,0 +1,121 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#include + +namespace kiwano +{ + +TickerPtr Ticker::Create(Duration interval, int times) +{ + TickerPtr ptr = memory::New(); + if (ptr) + { + ptr->SetInterval(interval); + ptr->SetTotalTickCount(times); + } + return ptr; +} + +Ticker::Ticker() + : ticked_count_(0) + , total_tick_count_(0) + , is_paused_(false) +{ +} + +bool Ticker::Tick() +{ + if (is_paused_) + return false; + + if (!timer_) + timer_ = Timer::Create(); + + if (timer_->IsPausing()) + return false; + + timer_->Tick(); + + return this->Tick(timer_->GetDeltaTime()); +} + +bool Ticker::Tick(Duration dt) +{ + if (is_paused_) + return false; + + if (ticked_count_ == total_tick_count_) + return false; + + elapsed_time_ += dt; + + if (elapsed_time_ + error_time_ > interval_) + { + delta_time_ = elapsed_time_; + error_time_ = (elapsed_time_ + error_time_) - interval_; + elapsed_time_ = 0; + ++ticked_count_; + return true; + } + return false; +} + +void Ticker::Pause() +{ + is_paused_ = true; + if (timer_) + timer_->Pause(); +} + +void Ticker::Resume() +{ + is_paused_ = false; + if (timer_) + timer_->Resume(); +} + +Duration Ticker::GetDeltaTime() +{ + return delta_time_; +} + +TimerPtr Ticker::GetTimer() +{ + return timer_; +} + +void Ticker::SetTimer(TimerPtr timer) +{ + timer_ = timer; +} + +void Ticker::Reset() +{ + if (timer_) + timer_->Reset(); + + elapsed_time_ = 0; + delta_time_ = 0; + error_time_ = 0; + ticked_count_ = 0; +} + +} // namespace kiwano diff --git a/src/kiwano/utils/Ticker.h b/src/kiwano/utils/Ticker.h new file mode 100644 index 00000000..815bfe8c --- /dev/null +++ b/src/kiwano/utils/Ticker.h @@ -0,0 +1,143 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#pragma once +#include + +namespace kiwano +{ + +KGE_DECLARE_SMART_PTR(Ticker); + +/// \~chinese +/// @brief ʱ +class KGE_API Ticker + : public ObjectBase +{ +public: + /// \~chinese + /// @brief ʱ + /// @param interval ʱ + /// @param tick_count ʱ -1 Ϊã + static TickerPtr Create(Duration interval, int tick_count = -1); + + Ticker(); + + /// \~chinese + /// @brief ʱ + /// @return Ƿﵽʱʱ + virtual bool Tick(); + + /// \~chinese + /// @brief ʱ + /// @param dt ʱ + /// @return Ƿﵽʱʱ + virtual bool Tick(Duration dt); + + /// \~chinese + /// @brief ȡʱ + Duration GetDeltaTime(); + + /// \~chinese + /// @brief ȡͣ״̬ + bool IsPausing() const; + + /// \~chinese + /// @brief ͣʱ + void Pause(); + + /// \~chinese + /// @brief ʱ + void Resume(); + + /// \~chinese + /// @brief ȡʱʱ + int GetTickedCount() const; + + /// \~chinese + /// @brief ȡʱܱʱ + int GetTotalTickCount() const; + + /// \~chinese + /// @brief ñʱܱʱ + void SetTotalTickCount(int count); + + /// \~chinese + /// @brief ȡʱ + Duration GetInterval() const; + + /// \~chinese + /// @brief ñʱ + void SetInterval(Duration interval); + + /// \~chinese + /// @brief ȡʱ + TimerPtr GetTimer(); + + /// \~chinese + /// @brief üʱ + void SetTimer(TimerPtr timer); + + /// \~chinese + /// @brief ñʱ + void Reset(); + +private: + bool is_paused_; + int ticked_count_; + int total_tick_count_; + Duration interval_; + Duration elapsed_time_; + Duration delta_time_; + Duration error_time_; + TimerPtr timer_; +}; + +inline bool Ticker::IsPausing() const +{ + return is_paused_; +} + +inline int Ticker::GetTickedCount() const +{ + return ticked_count_; +} + +inline int Ticker::GetTotalTickCount() const +{ + return total_tick_count_; +} + +inline void Ticker::SetTotalTickCount(int count) +{ + total_tick_count_ = count; +} + +inline Duration Ticker::GetInterval() const +{ + return interval_; +} + +inline void Ticker::SetInterval(Duration interval) +{ + interval_ = interval; +} + +} // namespace kiwano diff --git a/src/kiwano/utils/Timer.cpp b/src/kiwano/utils/Timer.cpp new file mode 100644 index 00000000..1c9ce5e2 --- /dev/null +++ b/src/kiwano/utils/Timer.cpp @@ -0,0 +1,119 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#include +#include + +namespace kiwano +{ + +TimerPtr Timer::Create() +{ + TimerPtr ptr = memory::New(); + return ptr; +} + +Timer::Timer() + : is_paused_(false) +{ + Reset(); +} + +Timer::~Timer() {} + +Duration Timer::GetDeltaTime() const +{ + return delta_time_; +} + +Duration Timer::GetTotalTime() const +{ + if (is_paused_) + return paused_time_ - start_time_ - total_idle_time_; + return current_time_ - start_time_ - total_idle_time_; +} + +bool Timer::IsPausing() const +{ + return is_paused_; +} + +void Timer::Tick() +{ + if (is_paused_) + { + delta_time_ = 0; + return; + } + + current_time_ = Time::Now(); + + // compute the time elapsed since the previous frame + delta_time_ = (current_time_ - previous_time_); + + // set previous time to current time, as in the next tick, this frame will be the previous frame + previous_time_ = current_time_; + + // delta time can be negative if the processor goes idle for example + if (delta_time_ < 0) + delta_time_ = 0; +} + +void Timer::Resume() +{ + if (is_paused_) + { + const auto now = Time::Now(); + + // add the duration of the pause to the total idle time + total_idle_time_ += (now - paused_time_); + + // set the previous time to the current time + previous_time_ = now; + + paused_time_ = Time(); + is_paused_ = false; + } +} + +void Timer::Pause() +{ + if (!is_paused_) + { + const auto now = Time::Now(); + + paused_time_ = now; + is_paused_ = true; + } +} + +void Timer::Reset() +{ + const auto now = Time::Now(); + + start_time_ = now; + current_time_ = now; + previous_time_ = now; + paused_time_ = Time(); + delta_time_ = 0; + is_paused_ = false; +} + +} // namespace kiwano diff --git a/src/kiwano/utils/Timer.h b/src/kiwano/utils/Timer.h new file mode 100644 index 00000000..ab20f4dc --- /dev/null +++ b/src/kiwano/utils/Timer.h @@ -0,0 +1,82 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// 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. + +#pragma once +#include +#include + +namespace kiwano +{ + +KGE_DECLARE_SMART_PTR(Timer); + +/// \~chinese +/// @brief ʱ +class KGE_API Timer + : public ObjectBase +{ +public: + /// \~chinese + /// @brief ʱ + static TimerPtr Create(); + + Timer(); + + virtual ~Timer(); + + /// \~chinese + /// @brief ȡʱ + Duration GetDeltaTime() const; + + /// \~chinese + /// @brief ȡʱ + Duration GetTotalTime() const; + + /// \~chinese + /// @brief ȡͣ״̬ + bool IsPausing() const; + + /// \~chinese + /// @brief ʱ + void Tick(); + + /// \~chinese + /// @brief ʱ + void Resume(); + + /// \~chinese + /// @brief ͣʱ + void Pause(); + + /// \~chinese + /// @brief üʱ + void Reset(); + +private: + bool is_paused_; + Time start_time_; + Time paused_time_; + Time current_time_; + Time previous_time_; + Duration delta_time_; + Duration total_idle_time_; +}; + +} // namespace kiwano diff --git a/src/kiwano/core/Xml.h b/src/kiwano/utils/Xml.h similarity index 100% rename from src/kiwano/core/Xml.h rename to src/kiwano/utils/Xml.h