diff --git a/appveyor.yml b/appveyor.yml index e876db8b..2435c118 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,13 +23,6 @@ environment: flag_to_deploy: false appveyor_api_token: secure: UJFCbRNHMOqQg3e3Kv/ZnaIqqwXAt+5HDldetaZsZ5E= - matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - VS_PLATFORM_TOOLSET: v142 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - VS_PLATFORM_TOOLSET: v141 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - VS_PLATFORM_TOOLSET: v140 matrix: fast_finish: true # set this flag to immediately finish build once one of the jobs fails @@ -48,6 +41,18 @@ only_commits: - appveyor.yml for: +- + branches: + only: + - master + environment: + matrix: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + VS_PLATFORM_TOOLSET: v142 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + VS_PLATFORM_TOOLSET: v141 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + VS_PLATFORM_TOOLSET: v140 - branches: except: diff --git a/projects/kiwano-audio.vcxproj b/projects/kiwano-audio.vcxproj index 0deda3e8..fdaf9844 100644 --- a/projects/kiwano-audio.vcxproj +++ b/projects/kiwano-audio.vcxproj @@ -4,14 +4,14 @@ - + - + diff --git a/projects/kiwano-audio.vcxproj.filters b/projects/kiwano-audio.vcxproj.filters index 62e0774b..b6974b55 100644 --- a/projects/kiwano-audio.vcxproj.filters +++ b/projects/kiwano-audio.vcxproj.filters @@ -8,15 +8,15 @@ src - - src - src src + + src + @@ -25,15 +25,15 @@ src - - src - src src + + src + diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj index 6284642f..cd2a541d 100644 --- a/projects/kiwano.vcxproj +++ b/projects/kiwano.vcxproj @@ -29,7 +29,6 @@ - @@ -38,7 +37,7 @@ - + @@ -112,6 +111,7 @@ + diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters index 7dadb0ef..11b8653f 100644 --- a/projects/kiwano.vcxproj.filters +++ b/projects/kiwano.vcxproj.filters @@ -51,9 +51,6 @@ 2d - - 2d - 2d @@ -69,9 +66,6 @@ 2d - - 2d - 2d @@ -309,6 +303,9 @@ core + + 2d + @@ -482,5 +479,8 @@ renderer + + 2d + \ No newline at end of file diff --git a/scripts/appveyor/clear_project_configuration.ps1 b/scripts/appveyor/clear_project_configuration.ps1 index 1bc7f59f..2cb25d9e 100644 --- a/scripts/appveyor/clear_project_configuration.ps1 +++ b/scripts/appveyor/clear_project_configuration.ps1 @@ -3,7 +3,13 @@ $replaceTo = "None" Get-ChildItem -Path 'projects\' *.vcxproj | ForEach-Object { $filePath = 'projects\' + $_ + + # Create a copy of .vcxproj file Copy-Item -Path $filePath -Destination ($filePath + '.template') + + # Overlay some configurations Get-Content ($filePath + '.template') -Encoding UTF8 | ForEach-Object { $_ -replace $replace, $replaceTo } | Out-File $filePath -Encoding UTF8 + + # Delete the copy file Remove-Item -Path ($filePath + '.template') } diff --git a/scripts/appveyor/coapp_make.ps1 b/scripts/appveyor/coapp_make.ps1 index c557453a..b5a57aa1 100644 --- a/scripts/appveyor/coapp_make.ps1 +++ b/scripts/appveyor/coapp_make.ps1 @@ -25,11 +25,17 @@ Write-Host "Start to build nupkg files" # This is the CoApp .autopkg file to create. $autopkgFile = "scripts\coapp\kiwano.autopkg" +# Create a copy of ".autopkg" file +Copy-Item -Path $autopkgFile -Destination ($autopkgFile + '.template') + # Get the ".autopkg.template" file, replace "@appveyor_version" with the Appveyor version number, then save to the ".autopkg" file. -Get-Content ($autopkgFile + ".template") | ForEach-Object { $_ -replace "@appveyor_version", $env:appveyor_build_version } > $autopkgFile +Get-Content ($autopkgFile + ".template") -Encoding UTF8 | ForEach-Object { $_ -replace "@appveyor_version", $env:appveyor_build_version } | Out-File $autopkgFile -Encoding UTF8 + +# Delete the copy file +Remove-Item -Path ($autopkgFile + '.template') # Use the CoApp tools to create NuGet native packages from the .autopkg. Write-NuGetPackage $autopkgFile # Push all newly created .nupkg files as Appveyor artifacts for later deployment. -Get-ChildItem .\*.nupkg | ForEach-Object { Push-AppveyorArtifact $_.FullName -FileName $_.Name } \ No newline at end of file +Get-ChildItem .\*.nupkg | ForEach-Object { Push-AppveyorArtifact $_.FullName -FileName $_.Name } diff --git a/scripts/coapp/kiwano.autopkg.template b/scripts/coapp/kiwano.autopkg similarity index 99% rename from scripts/coapp/kiwano.autopkg.template rename to scripts/coapp/kiwano.autopkg index 3d9cc68e..8e763bcb 100644 --- a/scripts/coapp/kiwano.autopkg.template +++ b/scripts/coapp/kiwano.autopkg @@ -1,4 +1,4 @@ -#defines { +#defines { // Global variables may be added here. // Variables on the "value" side of each definition will be processed at access time. // GlobalVar1 = ""; diff --git a/src/kiwano-audio/kiwano-audio.h b/src/kiwano-audio/kiwano-audio.h index 8f6e027a..02ca2f43 100644 --- a/src/kiwano-audio/kiwano-audio.h +++ b/src/kiwano-audio/kiwano-audio.h @@ -22,4 +22,4 @@ #include "src/audio.h" #include "src/Sound.h" -#include "src/Player.h" +#include "src/SoundPlayer.h" diff --git a/src/kiwano-audio/src/Sound.cpp b/src/kiwano-audio/src/Sound.cpp index 04bc7920..30d64e84 100644 --- a/src/kiwano-audio/src/Sound.cpp +++ b/src/kiwano-audio/src/Sound.cpp @@ -22,7 +22,6 @@ #include #include "Sound.h" #include "audio.h" -#include "Transcoder.h" namespace kiwano { @@ -32,12 +31,16 @@ namespace kiwano Sound::Sound() : opened_(false) , playing_(false) - , size_(0) - , wave_data_(nullptr) , voice_(nullptr) { } + Sound::Sound(String const& file_path) + : Sound() + { + Load(file_path); + } + Sound::Sound(Resource const& res) : Sound() { @@ -51,21 +54,19 @@ namespace kiwano bool Sound::Load(String const& file_path) { - if (opened_) - { - Close(); - } - -#if defined(KGE_DEBUG) if (!FileUtil::ExistsFile(file_path)) { KGE_WARNING_LOG(L"Media file '%s' not found", file_path.c_str()); return false; } -#endif + + if (opened_) + { + Close(); + } Transcoder transcoder; - HRESULT hr = transcoder.LoadMediaFile(file_path, &wave_data_, &size_); + HRESULT hr = transcoder.LoadMediaFile(file_path); if (FAILED(hr)) { @@ -73,14 +74,11 @@ namespace kiwano return false; } - hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx()); + hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetBuffer().format); if (FAILED(hr)) { - if (wave_data_) - { - delete[] wave_data_; - wave_data_ = nullptr; - } + Close(); + KGE_ERROR_LOG(L"Create source voice failed with HRESULT of %08X", hr); return false; } @@ -97,7 +95,7 @@ namespace kiwano } Transcoder transcoder; - HRESULT hr = transcoder.LoadMediaResource(res, &wave_data_, &size_); + HRESULT hr = transcoder.LoadMediaResource(res); if (FAILED(hr)) { @@ -105,14 +103,11 @@ namespace kiwano return false; } - hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx()); + hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetBuffer().format); if (FAILED(hr)) { - if (wave_data_) - { - delete[] wave_data_; - wave_data_ = nullptr; - } + Close(); + KGE_ERROR_LOG(L"Create source voice failed with HRESULT of %08X", hr); return false; } @@ -140,10 +135,12 @@ namespace kiwano // clamp loop count loop_count = (loop_count < 0) ? XAUDIO2_LOOP_INFINITE : std::min(loop_count, XAUDIO2_LOOP_INFINITE - 1); + auto wave_buffer = transcoder_.GetBuffer(); + XAUDIO2_BUFFER buffer = { 0 }; - buffer.pAudioData = wave_data_; + buffer.pAudioData = wave_buffer.data; buffer.Flags = XAUDIO2_END_OF_STREAM; - buffer.AudioBytes = size_; + buffer.AudioBytes = wave_buffer.size; buffer.LoopCount = static_cast(loop_count); HRESULT hr = voice_->SubmitSourceBuffer(&buffer); @@ -202,11 +199,7 @@ namespace kiwano voice_ = nullptr; } - if (wave_data_) - { - delete[] wave_data_; - wave_data_ = nullptr; - } + transcoder_.ClearBuffer(); opened_ = false; playing_ = false; diff --git a/src/kiwano-audio/src/Sound.h b/src/kiwano-audio/src/Sound.h index bff2118c..e3e64fd9 100644 --- a/src/kiwano-audio/src/Sound.h +++ b/src/kiwano-audio/src/Sound.h @@ -23,6 +23,7 @@ #include #include #include +#include "Transcoder.h" namespace kiwano { @@ -86,11 +87,10 @@ namespace kiwano ); protected: - bool opened_; - bool playing_; - UInt32 size_; - BYTE* wave_data_; - IXAudio2SourceVoice* voice_; + bool opened_; + bool playing_; + Transcoder transcoder_; + IXAudio2SourceVoice* voice_; }; } } diff --git a/src/kiwano-audio/src/Player.cpp b/src/kiwano-audio/src/SoundPlayer.cpp similarity index 83% rename from src/kiwano-audio/src/Player.cpp rename to src/kiwano-audio/src/SoundPlayer.cpp index 5e696ec0..7503908c 100644 --- a/src/kiwano-audio/src/Player.cpp +++ b/src/kiwano-audio/src/SoundPlayer.cpp @@ -18,23 +18,23 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "Player.h" +#include "SoundPlayer.h" namespace kiwano { namespace audio { - Player::Player() + SoundPlayer::SoundPlayer() : volume_(1.f) { } - Player::~Player() + SoundPlayer::~SoundPlayer() { ClearCache(); } - UInt32 Player::Load(String const& file_path) + UInt32 SoundPlayer::Load(String const& file_path) { UInt32 hash_code = file_path.hash(); if (sound_cache_.end() != sound_cache_.find(hash_code)) @@ -54,7 +54,7 @@ namespace kiwano return false; } - UInt32 Player::Load(Resource const& res) + UInt32 SoundPlayer::Load(Resource const& res) { UInt32 hash_code = res.GetId(); if (sound_cache_.end() != sound_cache_.find(hash_code)) @@ -74,35 +74,35 @@ namespace kiwano return false; } - void Player::Play(UInt32 id, Int32 loop_count) + void SoundPlayer::Play(UInt32 id, Int32 loop_count) { auto iter = sound_cache_.find(id); if (sound_cache_.end() != iter) iter->second->Play(loop_count); } - void Player::Pause(UInt32 id) + void SoundPlayer::Pause(UInt32 id) { auto iter = sound_cache_.find(id); if (sound_cache_.end() != iter) iter->second->Pause(); } - void Player::Resume(UInt32 id) + void SoundPlayer::Resume(UInt32 id) { auto iter = sound_cache_.find(id); if (sound_cache_.end() != iter) iter->second->Resume(); } - void Player::Stop(UInt32 id) + void SoundPlayer::Stop(UInt32 id) { auto iter = sound_cache_.find(id); if (sound_cache_.end() != iter) iter->second->Stop(); } - bool Player::IsPlaying(UInt32 id) + bool SoundPlayer::IsPlaying(UInt32 id) { auto iter = sound_cache_.find(id); if (sound_cache_.end() != iter) @@ -110,12 +110,12 @@ namespace kiwano return false; } - Float32 Player::GetVolume() const + Float32 SoundPlayer::GetVolume() const { return volume_; } - void Player::SetVolume(Float32 volume) + void SoundPlayer::SetVolume(Float32 volume) { volume_ = std::min(std::max(volume, -224.f), 224.f); for (const auto& pair : sound_cache_) @@ -124,7 +124,7 @@ namespace kiwano } } - void Player::PauseAll() + void SoundPlayer::PauseAll() { for (const auto& pair : sound_cache_) { @@ -132,7 +132,7 @@ namespace kiwano } } - void Player::ResumeAll() + void SoundPlayer::ResumeAll() { for (const auto& pair : sound_cache_) { @@ -140,7 +140,7 @@ namespace kiwano } } - void Player::StopAll() + void SoundPlayer::StopAll() { for (const auto& pair : sound_cache_) { @@ -148,7 +148,7 @@ namespace kiwano } } - void Player::ClearCache() + void SoundPlayer::ClearCache() { sound_cache_.clear(); } diff --git a/src/kiwano-audio/src/Player.h b/src/kiwano-audio/src/SoundPlayer.h similarity index 89% rename from src/kiwano-audio/src/Player.h rename to src/kiwano-audio/src/SoundPlayer.h index 7e33e2d0..596ea530 100644 --- a/src/kiwano-audio/src/Player.h +++ b/src/kiwano-audio/src/SoundPlayer.h @@ -27,23 +27,23 @@ namespace kiwano { namespace audio { - KGE_DECLARE_SMART_PTR(Player); + KGE_DECLARE_SMART_PTR(SoundPlayer); // ÒôÀÖ²¥·ÅÆ÷ - class KGE_API Player + class KGE_API SoundPlayer : protected ObjectBase { public: - Player(); + SoundPlayer(); - ~Player(); + ~SoundPlayer(); - // ¼ÓÔØ±¾µØÒôƵÎļþ, ·µ»Ø¸Ã×ÊÔ´±êʶ·û + // ¼ÓÔØ±¾µØÒôƵÎļþ, ·µ»Ø¸Ã×ÊÔ´µÄ±êʶ·û UInt32 Load( String const& file_path ); - // ¼ÓÔØÒôÀÖ×ÊÔ´, ·µ»Ø¸Ã×ÊÔ´±êʶ·û + // ¼ÓÔØÒôÀÖ×ÊÔ´, ·µ»Ø¸Ã×ÊÔ´µÄ±êʶ·û UInt32 Load( Resource const& res /* ÒôÀÖ×ÊÔ´ */ ); @@ -51,7 +51,7 @@ namespace kiwano // ²¥·ÅÒôÀÖ void Play( UInt32 id, /* ±êʶ·û */ - Int32 loop_count = 0 /* ²¥·ÅÑ­»·´ÎÊý (-1 Ϊѭ»·²¥·Å) */ + Int32 loop_count = 0 /* ²¥·ÅÑ­»·´ÎÊý (-1 Ϊѭ»·²¥·Å) */ ); // ÔÝÍ£ÒôÀÖ diff --git a/src/kiwano-audio/src/Transcoder.cpp b/src/kiwano-audio/src/Transcoder.cpp index a07dca56..4204725a 100644 --- a/src/kiwano-audio/src/Transcoder.cpp +++ b/src/kiwano-audio/src/Transcoder.cpp @@ -38,24 +38,39 @@ namespace kiwano Transcoder::Transcoder() : wave_format_(nullptr) + , wave_data_(nullptr) + , wave_size_(0) { } Transcoder::~Transcoder() + { + ClearBuffer(); + } + + Transcoder::Buffer Transcoder::GetBuffer() const + { + return Buffer{ wave_data_, wave_size_, wave_format_ }; + } + + void Transcoder::ClearBuffer() { if (wave_format_) { ::CoTaskMemFree(wave_format_); wave_format_ = nullptr; } + + if (wave_data_) + { + delete[] wave_data_; + wave_data_ = nullptr; + } + + wave_size_ = 0; } - const WAVEFORMATEX* Transcoder::GetWaveFormatEx() const - { - return wave_format_; - } - - HRESULT Transcoder::LoadMediaFile(String const& file_path, BYTE** wave_data, UInt32* wave_data_size) + HRESULT Transcoder::LoadMediaFile(String const& file_path) { HRESULT hr = S_OK; @@ -69,13 +84,13 @@ namespace kiwano if (SUCCEEDED(hr)) { - hr = ReadSource(reader.get(), wave_data, wave_data_size); + hr = ReadSource(reader.get()); } return hr; } - HRESULT Transcoder::LoadMediaResource(Resource const& res, BYTE** wave_data, UInt32* wave_data_size) + HRESULT Transcoder::LoadMediaResource(Resource const& res) { HRESULT hr = S_OK; @@ -87,7 +102,7 @@ namespace kiwano if (!data) { return E_FAIL; } stream = kiwano::modules::Shlwapi::Get().SHCreateMemStream( - static_cast(data.buffer), + static_cast(data.buffer), static_cast(data.size) ); @@ -113,13 +128,13 @@ namespace kiwano if (SUCCEEDED(hr)) { - hr = ReadSource(reader.get(), wave_data, wave_data_size); + hr = ReadSource(reader.get()); } return hr; } - HRESULT Transcoder::ReadSource(IMFSourceReader* reader, BYTE** wave_data, UInt32* wave_data_size) + HRESULT Transcoder::ReadSource(IMFSourceReader* reader) { HRESULT hr = S_OK; DWORD max_stream_size = 0; @@ -194,7 +209,7 @@ namespace kiwano LONGLONG duration = prop.uhVal.QuadPart; max_stream_size = static_cast( (duration * wave_format_->nAvgBytesPerSec) / 10000000 + 1 - ); + ); PropVariantClear(&prop); } @@ -203,7 +218,7 @@ namespace kiwano { DWORD flags = 0; DWORD position = 0; - BYTE* data = new (std::nothrow) BYTE[max_stream_size]; + Byte* data = new (std::nothrow) Byte[max_stream_size]; ComPtr sample; ComPtr buffer; @@ -236,7 +251,7 @@ namespace kiwano if (SUCCEEDED(hr)) { - BYTE* audio_data = nullptr; + Byte* audio_data = nullptr; DWORD sample_buffer_length = 0; hr = buffer->Lock( @@ -245,7 +260,7 @@ namespace kiwano &sample_buffer_length ); - if (SUCCEEDED(hr)) + if (SUCCEEDED(hr) && sample_buffer_length <= max_stream_size) { for (DWORD i = 0; i < sample_buffer_length; i++) { @@ -263,8 +278,8 @@ namespace kiwano if (SUCCEEDED(hr)) { - *wave_data = data; - *wave_data_size = position; + wave_data_ = data; + wave_size_ = position; } } } diff --git a/src/kiwano-audio/src/Transcoder.h b/src/kiwano-audio/src/Transcoder.h index 9bc02cb4..9195e0dd 100644 --- a/src/kiwano-audio/src/Transcoder.h +++ b/src/kiwano-audio/src/Transcoder.h @@ -31,31 +31,36 @@ namespace kiwano class KGE_API Transcoder { public: + struct Buffer + { + Byte* data; + UInt32 size; + const WAVEFORMATEX* format; + }; + Transcoder(); ~Transcoder(); - const WAVEFORMATEX* GetWaveFormatEx() const; + Buffer GetBuffer() const; + + void ClearBuffer(); HRESULT LoadMediaFile( - String const& file_path, - BYTE** wave_data, - UInt32* wave_data_size + String const& file_path ); HRESULT LoadMediaResource( - Resource const& res, - BYTE** wave_data, - UInt32* wave_data_size + Resource const& res ); HRESULT ReadSource( - IMFSourceReader* reader, - BYTE** wave_data, - UInt32* wave_data_size + IMFSourceReader* reader ); private: + Byte* wave_data_; + UInt32 wave_size_; WAVEFORMATEX* wave_format_; }; } diff --git a/src/kiwano-audio/src/audio.cpp b/src/kiwano-audio/src/audio.cpp index b703054a..db0d0b75 100644 --- a/src/kiwano-audio/src/audio.cpp +++ b/src/kiwano-audio/src/audio.cpp @@ -76,9 +76,17 @@ namespace kiwano HRESULT Audio::CreateVoice(IXAudio2SourceVoice** voice, const WAVEFORMATEX* wfx) { + KGE_ASSERT(x_audio2_ && "Audio engine hasn't been initialized!"); + if (voice == nullptr) { - return E_UNEXPECTED; + return E_INVALIDARG; + } + + if (*voice) + { + (*voice)->DestroyVoice(); + (*voice) = nullptr; } HRESULT hr = x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO); @@ -87,11 +95,15 @@ namespace kiwano void Audio::Open() { + KGE_ASSERT(x_audio2_ && "Audio engine hasn't been initialized!"); + x_audio2_->StartEngine(); } void Audio::Close() { + KGE_ASSERT(x_audio2_ && "Audio engine hasn't been initialized!"); + x_audio2_->StopEngine(); } } diff --git a/src/kiwano-imgui/src/ImGuiLayer.cpp b/src/kiwano-imgui/src/ImGuiLayer.cpp index 63f2b55f..522d6e81 100644 --- a/src/kiwano-imgui/src/ImGuiLayer.cpp +++ b/src/kiwano-imgui/src/ImGuiLayer.cpp @@ -33,9 +33,9 @@ namespace kiwano { } - void ImGuiLayer::OnRender(Renderer* renderer) + void ImGuiLayer::OnRender(RenderTarget* rt) { - PrepareRender(renderer); + PrepareRender(rt); for (const auto& pipeline : pipelines_) { pipeline.second(); diff --git a/src/kiwano-imgui/src/ImGuiLayer.h b/src/kiwano-imgui/src/ImGuiLayer.h index 7f057185..59921cc7 100644 --- a/src/kiwano-imgui/src/ImGuiLayer.h +++ b/src/kiwano-imgui/src/ImGuiLayer.h @@ -52,7 +52,7 @@ namespace kiwano void RemoveAllItems(); public: - void OnRender(Renderer* renderer) override; + void OnRender(RenderTarget* rt) override; protected: Map pipelines_; diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index 15518e7a..681af26f 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -71,7 +71,7 @@ namespace kiwano OnUpdate(dt); } - if (!children_.item_empty()) + if (!children_.empty()) { ActorPtr next; for (auto child = children_.first_item(); child; child = next) @@ -82,16 +82,16 @@ namespace kiwano } } - void Actor::Render(Renderer* renderer) + void Actor::Render(RenderTarget* rt) { if (!visible_) return; UpdateTransform(); - if (children_.item_empty()) + if (children_.empty()) { - OnRender(renderer); + OnRender(rt); } else { @@ -102,41 +102,40 @@ namespace kiwano if (child->GetZOrder() >= 0) break; - child->Render(renderer); + child->Render(rt); child = child->next_item().get(); } - OnRender(renderer); + OnRender(rt); while (child) { - child->Render(renderer); + child->Render(rt); child = child->next_item().get(); } } } - void Actor::PrepareRender(Renderer* renderer) + void Actor::PrepareRender(RenderTarget* rt) { - renderer->SetTransform(transform_matrix_); - renderer->SetOpacity(displayed_opacity_); + rt->SetTransform(transform_matrix_); + rt->SetOpacity(displayed_opacity_); } - void Actor::RenderBorder() + void Actor::RenderBorder(RenderTarget* rt) { - if (show_border_) + if (show_border_ && !size_.IsOrigin()) { Rect bounds = GetBounds(); - auto renderer = Renderer::GetInstance(); - renderer->SetTransform(transform_matrix_); - renderer->FillRectangle(bounds, Color(Color::Red, .4f)); - renderer->DrawRectangle(bounds, Color(Color::Red, .8f), 2.f); + rt->SetTransform(transform_matrix_); + rt->FillRectangle(bounds, Color(Color::Red, .4f)); + rt->DrawRectangle(bounds, Color(Color::Red, .8f), 2.f); } for (auto child = children_.first_item(); child; child = child->next_item()) { - child->RenderBorder(); + child->RenderBorder(rt); } } @@ -233,12 +232,7 @@ namespace kiwano else { // matrix multiplication is optimized by expression template - transform_matrix_ = Matrix3x2::SRT(transform_.position, transform_.scale, transform_.rotation); - - if (!transform_.skew.IsOrigin()) - { - transform_matrix_ = Matrix3x2::Skewing(transform_.skew) * transform_matrix_; - } + transform_matrix_ = transform_.ToMatrix(); } transform_matrix_.Translate(Point{ -size_.x * anchor_.x, -size_.y * anchor_.y }); @@ -270,14 +264,14 @@ namespace kiwano } } - void Actor::SetStage(Stage* scene) + void Actor::SetStage(Stage* stage) { - if (scene && stage_ != scene) + if (stage && stage_ != stage) { - stage_ = scene; + stage_ = stage; for (Actor* child = children_.first_item().get(); child; child = child->next_item().get()) { - child->stage_ = scene; + child->stage_ = stage; } } } @@ -288,7 +282,7 @@ namespace kiwano { ActorPtr me = this; - parent_->children_.remove_item(me); + parent_->children_.remove(me); Actor* sibling = parent_->children_.last_item().get(); @@ -309,7 +303,7 @@ namespace kiwano } else { - parent_->children_.push_front_item(me); + parent_->children_.push_front(me); } } } @@ -341,53 +335,31 @@ namespace kiwano UpdateOpacity(); } - void Actor::SetAnchorX(Float32 anchor_x) + void Actor::SetAnchor(Vec2 const& anchor) { - this->SetAnchor(anchor_x, anchor_.y); - } - - void Actor::SetAnchorY(Float32 anchor_y) - { - this->SetAnchor(anchor_.x, anchor_y); - } - - void Actor::SetAnchor(Float32 anchor_x, Float32 anchor_y) - { - if (anchor_.x == anchor_x && anchor_.y == anchor_y) + if (anchor_ == anchor) return; - anchor_.x = anchor_x; - anchor_.y = anchor_y; + anchor_ = anchor; dirty_transform_ = true; } - void Actor::SetAnchor(Point const& anchor) - { - this->SetAnchor(anchor.x, anchor.y); - } - void Actor::SetWidth(Float32 width) { - this->SetSize(width, size_.y); + SetSize(Size{ width, size_.y }); } void Actor::SetHeight(Float32 height) { - this->SetSize(size_.x, height); + SetSize(Size{ size_.x, height }); } - void Actor::SetSize(const Size& size) + void Actor::SetSize(Size const& size) { - this->SetSize(size.x, size.y); - } - - void Actor::SetSize(Float32 width, Float32 height) - { - if (size_.x == width && size_.y == height) + if (size_ == size) return; - size_.x = width; - size_.y = height; + size_ = size; dirty_transform_ = true; } @@ -412,98 +384,50 @@ namespace kiwano } } + void Actor::SetPosition(const Point & pos) + { + if (transform_.position == pos) + return; + + transform_.position = pos; + dirty_transform_ = true; + } + void Actor::SetPositionX(Float32 x) { - this->SetPosition(x, transform_.position.y); + SetPosition(Point{ x, transform_.position.y }); } void Actor::SetPositionY(Float32 y) { - this->SetPosition(transform_.position.x, y); + SetPosition(Point{ transform_.position.x, y }); } - void Actor::SetPosition(const Point & p) + void Actor::Move(Vec2 const& v) { - this->SetPosition(p.x, p.y); + this->SetPosition(Point{ transform_.position.x + v.x, transform_.position.y + v.y }); } - void Actor::SetPosition(Float32 x, Float32 y) + void Actor::SetScale(Vec2 const& scale) { - if (transform_.position.x == x && transform_.position.y == y) + if (transform_.scale == scale) return; - transform_.position.x = x; - transform_.position.y = y; - dirty_transform_ = true; - } - - void Actor::Move(Float32 x, Float32 y) - { - this->SetPosition(transform_.position.x + x, transform_.position.y + y); - } - - void Actor::Move(const Point & v) - { - this->Move(v.x, v.y); - } - - void Actor::SetScaleX(Float32 scale_x) - { - this->SetScale(scale_x, transform_.scale.y); - } - - void Actor::SetScaleY(Float32 scale_y) - { - this->SetScale(transform_.scale.x, scale_y); - } - - void Actor::SetScale(Float32 scale) - { - this->SetScale(scale, scale); - } - - void Actor::SetScale(Float32 scale_x, Float32 scale_y) - { - if (transform_.scale.x == scale_x && transform_.scale.y == scale_y) - return; - - transform_.scale.x = scale_x; - transform_.scale.y = scale_y; + transform_.scale = scale; dirty_transform_ = true; is_fast_transform_ = false; } - void Actor::SetScale(Point const& scale) + void Actor::SetSkew(Vec2 const& skew) { - this->SetScale(scale.x, scale.y); - } - - void Actor::SetSkewX(Float32 skew_x) - { - this->SetSkew(skew_x, transform_.skew.y); - } - - void Actor::SetSkewY(Float32 skew_y) - { - this->SetSkew(transform_.skew.x, skew_y); - } - - void Actor::SetSkew(Float32 skew_x, Float32 skew_y) - { - if (transform_.skew.x == skew_x && transform_.skew.y == skew_y) + if (transform_.skew == skew) return; - transform_.skew.x = skew_x; - transform_.skew.y = skew_y; + transform_.skew = skew; dirty_transform_ = true; is_fast_transform_ = false; } - void Actor::SetSkew(Point const& skew) - { - this->SetSkew(skew.x, skew.y); - } - void Actor::SetRotation(Float32 angle) { if (transform_.rotation == angle) @@ -531,7 +455,7 @@ namespace kiwano #endif // KGE_DEBUG - children_.push_back_item(child); + children_.push_back(child); child->parent_ = this; child->SetStage(this->stage_); child->dirty_transform_ = true; @@ -550,7 +474,7 @@ namespace kiwano Rect Actor::GetBounds() const { - return Rect(Point{}, size_); + return Rect{ Point{}, size_ }; } Rect Actor::GetBoundingBox() const @@ -609,20 +533,20 @@ namespace kiwano { KGE_ASSERT(child && "Actor::RemoveChild failed, NULL pointer exception"); - if (children_.item_empty()) + if (children_.empty()) return; if (child) { child->parent_ = nullptr; if (child->stage_) child->SetStage(nullptr); - children_.remove_item(ActorPtr(child)); + children_.remove(ActorPtr(child)); } } void Actor::RemoveChildren(String const& child_name) { - if (children_.item_empty()) + if (children_.empty()) { return; } @@ -643,7 +567,7 @@ namespace kiwano void Actor::RemoveAllChildren() { - children_.clear_items(); + children_.clear(); } void Actor::SetResponsible(bool enable) diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h index ccad06d9..e08037bc 100644 --- a/src/kiwano/2d/Actor.h +++ b/src/kiwano/2d/Actor.h @@ -20,7 +20,7 @@ #pragma once #include "include-forwards.h" -#include "Transform.hpp" +#include "Transform.h" #include "action/ActionManager.h" #include "../base/TimerManager.h" #include "../base/EventDispatcher.h" @@ -28,7 +28,7 @@ namespace kiwano { class Director; - class Renderer; + class RenderTarget; // ½ÇÉ« class KGE_API Actor @@ -49,10 +49,10 @@ namespace kiwano Actor(); // ¸üнÇÉ« - virtual void OnUpdate(Duration dt) { KGE_UNUSED(dt); } + virtual void OnUpdate(Duration dt) { KGE_UNUSED(dt); } // äÖȾ½ÇÉ« - virtual void OnRender(Renderer* renderer) { KGE_UNUSED(renderer); } + virtual void OnRender(RenderTarget* rt) { KGE_UNUSED(rt); } // »ñÈ¡ÏÔʾ״̬ bool IsVisible() const { return visible_; } @@ -67,7 +67,7 @@ namespace kiwano UInt32 GetHashName() const { return hash_name_; } // »ñÈ¡ Z Öá˳Ðò - Int32 GetZOrder() const { return z_order_; } + Int32 GetZOrder() const { return z_order_; } // »ñÈ¡×ø±ê Point GetPosition() const { return transform_.position; } @@ -97,7 +97,7 @@ namespace kiwano Float32 GetSkewY() const { return transform_.skew.y; } // »ñÈ¡Ðýת½Ç¶È - Float32 GetRotation() const { return transform_.rotation; } + Float32 GetRotation() const { return transform_.rotation; } // »ñÈ¡¿í¶È Float32 GetWidth() const { return size_.x; } @@ -109,10 +109,10 @@ namespace kiwano Size GetSize() const { return size_; } // »ñÈ¡Ëõ·ÅºóµÄ¿í¶È - Float32 GetScaledWidth() const { return size_.x * transform_.scale.x; } + Float32 GetScaledWidth() const { return size_.x * transform_.scale.x; } // »ñÈ¡Ëõ·ÅºóµÄ¸ß¶È - Float32 GetScaledHeight() const { return size_.y * transform_.scale.y; } + Float32 GetScaledHeight() const { return size_.y * transform_.scale.y; } // »ñÈ¡Ëõ·ÅºóµÄ´óС Size GetScaledSize() const { return Size{ GetScaledWidth(), GetScaledHeight() }; } @@ -121,16 +121,16 @@ namespace kiwano Point GetAnchor() const { return anchor_; } // »ñÈ¡ x ·½Ïòêµã - Float32 GetAnchorX() const { return anchor_.x; } + Float32 GetAnchorX() const { return anchor_.x; } // »ñÈ¡ y ·½Ïòêµã - Float32 GetAnchorY() const { return anchor_.y; } + Float32 GetAnchorY() const { return anchor_.y; } // »ñȡ͸Ã÷¶È - Float32 GetOpacity() const { return opacity_; } + Float32 GetOpacity() const { return opacity_; } // »ñÈ¡ÏÔʾ͸Ã÷¶È - Float32 GetDisplayedOpacity() const { return displayed_opacity_; } + Float32 GetDisplayedOpacity() const { return displayed_opacity_; } // »ñÈ¡±ä»» Transform GetTransform() const { return transform_; } @@ -163,6 +163,20 @@ namespace kiwano String const& name ); + // ÉèÖÃ×ø±ê + virtual void SetPosition( + Point const& point + ); + + // ÉèÖÃ×ø±ê + inline void SetPosition( + Float32 x, + Float32 y + ) + { + SetPosition(Point{ x, y }); + } + // ÉèÖúá×ø±ê void SetPositionX( Float32 x @@ -173,144 +187,101 @@ namespace kiwano Float32 y ); - // ÉèÖÃ×ø±ê - void SetPosition( - const Point & point - ); - - // ÉèÖÃ×ø±ê - void SetPosition( - Float32 x, - Float32 y - ); - - // ÒÆ¶¯ + // ÒÆ¶¯×ø±ê void Move( - Float32 x, - Float32 y + Vec2 const& v ); - // ÒÆ¶¯ - void Move( - const Point & vector - ); + // ÒÆ¶¯×ø±ê + inline void Move( + Float32 vx, + Float32 vy + ) + { + Move(Vec2{ vx, vy }); + } - // ÉèÖúáÏòËõ·Å±ÈÀý - // ĬÈÏΪ 1.0 - void SetScaleX( - Float32 scale_x - ); - - // ÉèÖÃ×ÝÏòËõ·Å±ÈÀý - // ĬÈÏΪ 1.0 - void SetScaleY( - Float32 scale_y + // ÉèÖÃËõ·Å±ÈÀý + // ĬÈÏΪ (1.0, 1.0) + virtual void SetScale( + Vec2 const& scale ); // ÉèÖÃËõ·Å±ÈÀý // ĬÈÏΪ (1.0, 1.0) - void SetScale( - Float32 scale_x, - Float32 scale_y - ); + inline void SetScale( + Float32 scalex, + Float32 scaley + ) + { + SetScale(Vec2{ scalex, scaley }); + } - // ÉèÖÃËõ·Å±ÈÀý - // ĬÈÏΪ (1.0, 1.0) - void SetScale( - Point const& scale - ); - - // ÉèÖÃËõ·Å±ÈÀý - // ĬÈÏΪ 1.0 - void SetScale( - Float32 scale - ); - - // ÉèÖúáÏò´íÇÐ½Ç¶È - // ĬÈÏΪ 0 - void SetSkewX( - Float32 skew_x - ); - - // ÉèÖÃ×ÝÏò´íÇÐ½Ç¶È - // ĬÈÏΪ 0 - void SetSkewY( - Float32 skew_y + // ÉèÖôíÇÐ½Ç¶È + // ĬÈÏΪ (0, 0) + virtual void SetSkew( + Vec2 const& skew ); // ÉèÖôíÇÐ½Ç¶È // ĬÈÏΪ (0, 0) - void SetSkew( - Float32 skew_x, - Float32 skew_y - ); - - // ÉèÖôíÇÐ½Ç¶È - // ĬÈÏΪ (0, 0) - void SetSkew( - Point const& skew - ); + inline void SetSkew( + Float32 skewx, + Float32 skewy + ) + { + SetSkew(Vec2{ skewx, skewy }); + } // ÉèÖÃÐýת½Ç¶È // ĬÈÏΪ 0 - void SetRotation( + virtual void SetRotation( Float32 rotation ); - // ÉèÖÃêµãµÄºáÏòλÖà - // ĬÈÏΪ 0, ·¶Î§ [0, 1] - void SetAnchorX( - Float32 anchor_x - ); - - // ÉèÖÃêµãµÄ×ÝÏòλÖà - // ĬÈÏΪ 0, ·¶Î§ [0, 1] - void SetAnchorY( - Float32 anchor_y + // ÉèÖÃêµãλÖà + // ĬÈÏΪ (0, 0), ·¶Î§ [0, 1] + virtual void SetAnchor( + Vec2 const& anchor ); // ÉèÖÃêµãλÖà // ĬÈÏΪ (0, 0), ·¶Î§ [0, 1] - void SetAnchor( - Float32 anchor_x, - Float32 anchor_y - ); - - // ÉèÖÃêµãλÖà - // ĬÈÏΪ (0, 0), ·¶Î§ [0, 1] - void SetAnchor( - Point const& anchor - ); + inline void SetAnchor( + Float32 anchorx, + Float32 anchory + ) + { + SetAnchor(Vec2{ anchorx, anchory }); + } // Ð޸Ŀí¶È - void SetWidth( + virtual void SetWidth( Float32 width ); // ÐÞ¸Ä¸ß¶È - void SetHeight( + virtual void SetHeight( Float32 height ); // Ð޸ĴóС - void SetSize( + virtual void SetSize( + Size const& size + ); + + // Ð޸ĴóС + inline void SetSize( Float32 width, Float32 height - ); - - // Ð޸ĴóС - void SetSize( - const Size & size - ); - - // ÉèÖöþά·ÂÉä±ä»» - void SetTransform( - Transform const& transform - ); + ) + { + SetSize(Size{ width, height }); + } // ÉèÖÃ͸Ã÷¶È // ĬÈÏΪ 1.0, ·¶Î§ [0, 1] - void SetOpacity( + virtual void SetOpacity( Float32 opacity ); @@ -319,6 +290,11 @@ namespace kiwano bool enabled ); + // ÉèÖöþά·ÂÉä±ä»» + void SetTransform( + Transform const& transform + ); + // ÉèÖà Z Öá˳Ðò // ĬÈÏΪ 0 void SetZOrder( @@ -331,11 +307,6 @@ namespace kiwano bool enable ); - // ÅжϵãÊÇ·ñÔÚ½ÇÉ«ÄÚ - bool ContainsPoint( - const Point& point - ) const; - // Ìí¼Ó×Ó½ÇÉ« void AddChild( ActorPtr child @@ -380,8 +351,8 @@ namespace kiwano // ´Ó¸¸½ÇÉ«ÒÆ³ý void RemoveFromParent(); - // ʼþ·Ö·¢ - void Dispatch(Event& evt) override; + // ÅжϵãÊÇ·ñÔÚ½ÇÉ«ÄÚ + virtual bool ContainsPoint(const Point& point) const; // ÔÝÍ£½ÇÉ«¸üРinline void PauseUpdating() { update_pausing_ = true; } @@ -401,6 +372,9 @@ namespace kiwano // äÖȾ½ÇÉ«±ß½ç inline void ShowBorder(bool show) { show_border_ = show; } + // ʼþ·Ö·¢ + void Dispatch(Event& evt) override; + // ÉèÖÃĬÈÏêµã static void SetDefaultAnchor( Float32 anchor_x, @@ -410,11 +384,11 @@ namespace kiwano protected: virtual void Update(Duration dt); - virtual void Render(Renderer* renderer); + virtual void Render(RenderTarget* rt); - void PrepareRender(Renderer* renderer); + virtual void PrepareRender(RenderTarget* rt); - void RenderBorder(); + virtual void RenderBorder(RenderTarget* rt); void UpdateTransform() const; @@ -422,7 +396,7 @@ namespace kiwano void Reorder(); - void SetStage(Stage* scene); + void SetStage(Stage* stage); protected: bool visible_; @@ -432,7 +406,7 @@ namespace kiwano bool update_pausing_; bool cascade_opacity_; bool show_border_; - Int32 z_order_; + Int32 z_order_; Float32 opacity_; Float32 displayed_opacity_; Actor* parent_; @@ -444,9 +418,9 @@ namespace kiwano UpdateCallback cb_update_; Transform transform_; - bool is_fast_transform_; - mutable bool dirty_transform_; - mutable bool dirty_transform_inverse_; + bool is_fast_transform_; + mutable bool dirty_transform_; + mutable bool dirty_transform_inverse_; mutable Matrix3x2 transform_matrix_; mutable Matrix3x2 transform_matrix_inverse_; }; diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp index 0e2d506f..4cf259f2 100644 --- a/src/kiwano/2d/Canvas.cpp +++ b/src/kiwano/2d/Canvas.cpp @@ -34,17 +34,6 @@ namespace kiwano Renderer::GetInstance()->CreateImageRenderTarget(rt_); } - Canvas::Canvas(Float32 width, Float32 height) - : Canvas() - { - this->SetSize(width, height); - } - - Canvas::Canvas(Size const & size) - : Canvas(size.x, size.y) - { - } - Canvas::~Canvas() { } @@ -60,16 +49,16 @@ namespace kiwano cache_expired_ = true; } - void Canvas::OnRender(Renderer* renderer) + void Canvas::OnRender(RenderTarget* rt) { UpdateCache(); if (image_cached_.IsValid()) { - PrepareRender(renderer); + PrepareRender(rt); Rect bitmap_rect(0.f, 0.f, image_cached_.GetWidth(), image_cached_.GetHeight()); - renderer->DrawImage(image_cached_, bitmap_rect, bitmap_rect); + rt->DrawImage(image_cached_, bitmap_rect, bitmap_rect); } } @@ -130,13 +119,7 @@ namespace kiwano void Canvas::SetBrushTransform(Transform const& transform) { - Matrix3x2 matrix = Matrix3x2::SRT(transform.position, transform.scale, transform.rotation); - if (!transform.skew.IsOrigin()) - { - matrix = Matrix3x2::Skewing(transform.skew) * matrix; - } - - rt_.SetTransform(matrix); + rt_.SetTransform(transform.ToMatrix()); } void Canvas::SetBrushTransform(Matrix3x2 const & transform) @@ -144,6 +127,26 @@ namespace kiwano rt_.SetTransform(transform); } + void Canvas::PushLayerArea(LayerArea& area) + { + rt_.PushLayer(area); + } + + void Canvas::PopLayerArea() + { + rt_.PopLayer(); + } + + void Canvas::PushClipRect(Rect const& clip_rect) + { + rt_.PushClipRect(clip_rect); + } + + void Canvas::PopClipRect() + { + rt_.PopClipRect(); + } + void Canvas::DrawLine(Point const& begin, Point const& end) { rt_.DrawLine( @@ -333,7 +336,7 @@ namespace kiwano { if (cache_expired_) { - rt_.GetOutput(image_cached_); + image_cached_ = rt_.GetOutput(); cache_expired_ = false; } } diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h index 8b636ad0..cf2a6f0d 100644 --- a/src/kiwano/2d/Canvas.h +++ b/src/kiwano/2d/Canvas.h @@ -35,15 +35,6 @@ namespace kiwano public: Canvas(); - Canvas( - Size const& size - ); - - Canvas( - Float32 width, - Float32 height - ); - virtual ~Canvas(); // ¿ªÊ¼»æÍ¼ @@ -148,7 +139,7 @@ namespace kiwano void AddArc( Point const& point, /* ÖÕµã */ Point const& radius, /* ÍÖÔ²°ë¾¶ */ - Float32 rotation, /* ÍÖÔ²Ðýת½Ç¶È */ + Float32 rotation, /* ÍÖÔ²Ðýת½Ç¶È */ bool clockwise = true, /* ˳ʱÕë or ÄæÊ±Õë */ bool is_small = true /* ÊÇ·ñȡСÓÚ 180¡ã µÄ»¡ */ ); @@ -202,6 +193,32 @@ namespace kiwano Float32 opacity ); + // »­±Ê¶þά±ä»» + void SetBrushTransform( + Transform const& transform + ); + + // »­±Ê¶þά±ä»» + void SetBrushTransform( + Matrix3x2 const& transform + ); + + // ÉèÖÃͼ²ã + void PushLayerArea( + LayerArea& area + ); + + // µ¯³öͼ²ã + void PopLayerArea(); + + // ÉèÖòüôÇøÓò + void PushClipRect( + Rect const& clip_rect + ); + + // µ¯³ö²Ã¼ôÇøÓò + void PopClipRect(); + // »ñÈ¡Ìî³äÑÕÉ« Color GetFillColor() const; @@ -214,20 +231,10 @@ namespace kiwano // »ñÈ¡»­±Ê͸Ã÷¶È Float32 GetBrushOpacity() const; - // »­±Ê¶þά±ä»» - void SetBrushTransform( - Transform const& transform - ); - - // »­±Ê¶þά±ä»» - void SetBrushTransform( - Matrix3x2 const& transform - ); - // µ¼³öΪͼƬ Image ExportToImage() const; - void OnRender(Renderer* renderer) override; + void OnRender(RenderTarget* rt) override; protected: void UpdateCache() const; diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index a2242f93..3ba2ea52 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -21,26 +21,43 @@ #include "DebugActor.h" #include "Text.h" #include "../renderer/Renderer.h" -#include #include #pragma comment(lib, "psapi.lib") namespace kiwano { + namespace + { + class comma_numpunct : public std::numpunct + { + protected: + virtual wchar_t do_thousands_sep() const override + { + return L','; + } + + virtual std::string do_grouping() const override + { + return "\03"; + } + }; + } + DebugActor::DebugActor() : background_color_(0.0f, 0.0f, 0.0f, 0.7f) { SetName(L"kiwano-debug-actor"); - SetPosition(10, 10); + SetPosition(Point{ 10, 10 }); SetResponsible(true); SetCascadeOpacityEnabled(true); debug_text_ = new Text; - debug_text_->SetPosition(10, 10); + debug_text_->SetPosition(Point{ 10, 10 }); this->AddChild(debug_text_); Font font; + font.family = L"Arial"; font.size = 16.f; font.weight = FontWeight::Normal; debug_text_->SetFont(font); @@ -57,15 +74,11 @@ namespace kiwano { } - void DebugActor::OnRender(Renderer* renderer) + void DebugActor::OnRender(RenderTarget* rt) { - PrepareRender(renderer); + PrepareRender(rt); - renderer->GetSolidColorBrush()->SetColor(DX::ConvertToColorF(background_color_)); - renderer->GetD2DDeviceResources()->GetDeviceContext()->FillRoundedRectangle( - D2D1::RoundedRect(DX::ConvertToRectF(GetBounds()), 5.f, 5.f), - renderer->GetSolidColorBrush() - ); + rt->FillRoundedRectangle(GetBounds(), Vec2{ 5.f, 5.f }, background_color_); } void DebugActor::OnUpdate(Duration dt) @@ -77,8 +90,15 @@ namespace kiwano { frame_time_.erase(frame_time_.begin()); } - - std::wstringstream ss; + + StringStream ss; + + { + // For formatting integers with commas + static std::locale comma_locale(std::locale(), new comma_numpunct); + (void)ss.imbue(comma_locale); + } + ss << "Fps: " << frame_time_.size() << std::endl; #if defined(KGE_DEBUG) @@ -90,11 +110,21 @@ namespace kiwano ss << "Render: " << Renderer::GetInstance()->GetStatus().duration.Milliseconds() << "ms" << std::endl; - ss << "Primitives / sec: " << Renderer::GetInstance()->GetStatus().primitives * frame_time_.size() << std::endl; + ss << "Primitives / sec: " << std::fixed << Renderer::GetInstance()->GetStatus().primitives * frame_time_.size() << std::endl; - PROCESS_MEMORY_COUNTERS_EX pmc; - GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)); - ss << "Memory: " << pmc.PrivateUsage / 1024 << "kb"; + ss << "Memory: "; + { + PROCESS_MEMORY_COUNTERS_EX pmc; + GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)); + + if (pmc.PrivateUsage > 1024 * 1024) + { + ss << pmc.PrivateUsage / (1024 * 1024) << "Mb "; + pmc.PrivateUsage %= (1024 * 1024); + } + + ss << pmc.PrivateUsage / 1024 << "Kb"; + } debug_text_->SetText(ss.str()); SetSize(Size{ 20 + debug_text_->GetSize().x, 20 + debug_text_->GetSize().y }); diff --git a/src/kiwano/2d/DebugActor.h b/src/kiwano/2d/DebugActor.h index 771758d2..d3bafc66 100644 --- a/src/kiwano/2d/DebugActor.h +++ b/src/kiwano/2d/DebugActor.h @@ -31,7 +31,7 @@ namespace kiwano virtual ~DebugActor(); - void OnRender(Renderer* renderer) override; + void OnRender(RenderTarget* rt) override; void OnUpdate(Duration dt) override; diff --git a/src/kiwano/2d/Frame.cpp b/src/kiwano/2d/Frame.cpp index ff99edde..88169c47 100644 --- a/src/kiwano/2d/Frame.cpp +++ b/src/kiwano/2d/Frame.cpp @@ -69,10 +69,10 @@ namespace kiwano if (image_.IsValid()) { auto bitmap_size = image_.GetSize(); - crop_rect_.origin.x = std::min(std::max(crop_rect.origin.x, 0.f), bitmap_size.x); - crop_rect_.origin.y = std::min(std::max(crop_rect.origin.y, 0.f), bitmap_size.y); - crop_rect_.size.x = std::min(std::max(crop_rect.size.x, 0.f), bitmap_size.x - crop_rect.origin.x); - crop_rect_.size.y = std::min(std::max(crop_rect.size.y, 0.f), bitmap_size.y - crop_rect.origin.y); + crop_rect_.left_top.x = std::min(std::max(crop_rect.left_top.x, 0.f), bitmap_size.x); + crop_rect_.left_top.y = std::min(std::max(crop_rect.left_top.y, 0.f), bitmap_size.y); + crop_rect_.right_bottom.x = std::min(std::max(crop_rect.right_bottom.x, 0.f), bitmap_size.x); + crop_rect_.right_bottom.y = std::min(std::max(crop_rect.right_bottom.y, 0.f), bitmap_size.y); } } @@ -81,9 +81,9 @@ namespace kiwano image_ = image; if (image_.IsValid()) { - crop_rect_.origin.x = crop_rect_.origin.y = 0; - crop_rect_.size.x = image_.GetWidth(); - crop_rect_.size.y = image_.GetHeight(); + crop_rect_.left_top.x = crop_rect_.left_top.y = 0; + crop_rect_.right_bottom.x = image_.GetWidth(); + crop_rect_.right_bottom.y = image_.GetHeight(); } } } diff --git a/src/kiwano/2d/Frame.h b/src/kiwano/2d/Frame.h index bbe845d2..30295db4 100644 --- a/src/kiwano/2d/Frame.h +++ b/src/kiwano/2d/Frame.h @@ -61,16 +61,16 @@ namespace kiwano ); // »ñÈ¡¿í¶È - Float32 GetWidth() const { return crop_rect_.size.x; } + Float32 GetWidth() const { return crop_rect_.GetWidth(); } // »ñÈ¡¸ß¶È - Float32 GetHeight() const { return crop_rect_.size.y; } + Float32 GetHeight() const { return crop_rect_.GetHeight(); } // »ñÈ¡´óС - Size GetSize() const { return crop_rect_.size; } + Size GetSize() const { return crop_rect_.GetSize(); } // »ñÈ¡²Ã¼ôλÖà - Point GetCropPoint() const { return crop_rect_.origin; } + Point GetCropPoint() const { return crop_rect_.GetLeftTop(); } // »ñÈ¡²Ã¼ô¾ØÐÎ inline Rect const& GetCropRect() const { return crop_rect_; } diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp index 66eb6fc4..af8b9053 100644 --- a/src/kiwano/2d/GifSprite.cpp +++ b/src/kiwano/2d/GifSprite.cpp @@ -72,10 +72,7 @@ namespace kiwano loop_count_ = 0; disposal_type_ = DisposalType::None; - SetSize( - static_cast(image_.GetWidthInPixels()), - static_cast(image_.GetHeightInPixels()) - ); + SetSize(Size{ static_cast(image_.GetWidthInPixels()), static_cast(image_.GetHeightInPixels()) }); if (!frame_rt_.IsValid()) { @@ -91,13 +88,13 @@ namespace kiwano return false; } - void GifSprite::OnRender(Renderer* renderer) + void GifSprite::OnRender(RenderTarget* rt) { - if (frame_.IsValid() && renderer->CheckVisibility(size_, transform_matrix_)) + if (frame_.IsValid() && rt->CheckVisibility(GetBounds(), GetTransformMatrix())) { - PrepareRender(renderer); + PrepareRender(rt); - renderer->DrawImage(frame_); + rt->DrawImage(frame_); } } @@ -195,8 +192,7 @@ namespace kiwano if (SUCCEEDED(hr)) { - Image frame_to_render; - frame_rt_.GetOutput(frame_to_render); + Image frame_to_render = frame_rt_.GetOutput(); hr = frame_to_render.IsValid() ? S_OK : E_FAIL; @@ -222,8 +218,7 @@ namespace kiwano void GifSprite::SaveComposedFrame() { - Image frame_to_be_saved; - frame_rt_.GetOutput(frame_to_be_saved); + Image frame_to_be_saved = frame_rt_.GetOutput(); HRESULT hr = frame_to_be_saved.IsValid() ? S_OK : E_FAIL; @@ -258,8 +253,7 @@ namespace kiwano if (SUCCEEDED(hr)) { - Image frame_to_copy_to; - frame_rt_.GetOutput(frame_to_copy_to); + Image frame_to_copy_to = frame_rt_.GetOutput(); hr = frame_to_copy_to.IsValid() ? S_OK : E_FAIL; diff --git a/src/kiwano/2d/GifSprite.h b/src/kiwano/2d/GifSprite.h index 6a875591..ee94ed99 100644 --- a/src/kiwano/2d/GifSprite.h +++ b/src/kiwano/2d/GifSprite.h @@ -62,7 +62,7 @@ namespace kiwano ); // ÉèÖà GIF ¶¯»­Ñ­»·´ÎÊý - inline void SetLoopCount(Int32 loops) { total_loop_count_ = loops; } + inline void SetLoopCount(Int32 loops) { total_loop_count_ = loops; } // ÉèÖà GIF ¶¯»­Ã¿´ÎÑ­»·½áÊø»Øµ÷º¯Êý inline void SetLoopDoneCallback(LoopDoneCallback const& cb) { loop_cb_ = cb; } @@ -77,7 +77,7 @@ namespace kiwano inline DoneCallback GetDoneCallback() const { return done_cb_; } - void OnRender(Renderer* renderer) override; + void OnRender(RenderTarget* rt) override; protected: void Update(Duration dt) override; @@ -100,8 +100,8 @@ namespace kiwano protected: bool animating_; - Int32 total_loop_count_; - Int32 loop_count_; + Int32 total_loop_count_; + Int32 loop_count_; UInt32 next_index_; Duration frame_delay_; Duration frame_elapsed_; diff --git a/src/kiwano/2d/Layer.cpp b/src/kiwano/2d/Layer.cpp index a4218f99..0c6e6d8e 100644 --- a/src/kiwano/2d/Layer.cpp +++ b/src/kiwano/2d/Layer.cpp @@ -27,8 +27,6 @@ namespace kiwano Layer::Layer() : swallow_(false) { - SetSize(Renderer::GetInstance()->GetOutputSize()); - auto handler = Closure(this, &Layer::HandleMessages); AddListener(Event::MouseBtnDown, handler); @@ -45,6 +43,27 @@ namespace kiwano { } + void Layer::SetClipRect(Rect const& clip_rect) + { + area_.SetAreaRect(clip_rect); + } + + void Layer::SetOpacity(Float32 opacity) + { + // Actor::SetOpacity(opacity); + area_.SetOpacity(opacity); + } + + void Layer::SetMaskGeometry(Geometry const& mask) + { + area_.SetMaskGeometry(mask); + } + + void Layer::SetMaskTransform(Matrix3x2 const& transform) + { + area_.SetMaskTransform(transform); + } + void Layer::Dispatch(Event& evt) { if (!IsVisible()) @@ -63,7 +82,19 @@ namespace kiwano EventDispatcher::Dispatch(evt); } - void Layer::HandleMessages(Event const & evt) + void Layer::Render(RenderTarget* rt) + { + if (!children_.empty()) + { + PrepareRender(rt); + + rt->PushLayer(area_); + Actor::Render(rt); + rt->PopLayer(); + } + } + + void Layer::HandleMessages(Event const& evt) { switch (evt.type) { diff --git a/src/kiwano/2d/Layer.h b/src/kiwano/2d/Layer.h index 6bcdd43b..c6d4ed6f 100644 --- a/src/kiwano/2d/Layer.h +++ b/src/kiwano/2d/Layer.h @@ -20,6 +20,8 @@ #pragma once #include "Actor.h" +#include "..\renderer\LayerArea.h" +#include "..\renderer\RenderTarget.h" namespace kiwano { @@ -31,25 +33,49 @@ namespace kiwano virtual ~Layer(); + // ÖØÔØÏÂÁк¯ÊýÒÔ»ñȡͼ²ãʼþ virtual void OnMouseButtonDown(Int32 btn, Point const& p) {} virtual void OnMouseButtonUp(Int32 btn, Point const& p) {} virtual void OnMouseMoved(Point const& p) {} virtual void OnMouseWheel(Float32 wheel) {} - virtual void OnKeyDown(Int32 key) {} virtual void OnKeyUp(Int32 key) {} virtual void OnChar(char c) {} + // ÊÇ·ñ¿ªÆôÏûÏ¢ÍÌû + inline bool IsSwallowEventsEnabled() const { return swallow_; } + // ÍÌûÏûÏ¢ - inline void SetSwallowEvents(bool enabled) { swallow_ = enabled; } + inline void SetSwallowEvents(bool enabled) { swallow_ = enabled; } + + // ÉèÖòüôÇøÓò + void SetClipRect(Rect const& clip_rect); + + // ÉèÖÃͼ²ã͸Ã÷¶È + void SetOpacity(Float32 opacity) override; + + // ÉèÖü¸ºÎÃɲã + void SetMaskGeometry(Geometry const& mask); + + // ÉèÖü¸ºÎÃɲãµÄ¶þά±ä»» + void SetMaskTransform(Matrix3x2 const& transform); + + // ÉèÖÃͼ²ãÇøÓò + inline void SetArea(LayerArea const& area) { area_ = area; } + + // »ñȡͼ²ãÇøÓò + inline LayerArea const& GetArea() const { return area_; } public: void Dispatch(Event& evt) override; protected: + void Render(RenderTarget* rt) override; + void HandleMessages(Event const& evt); protected: - bool swallow_; + bool swallow_; + LayerArea area_; }; } diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp index dafeffd0..5bd96330 100644 --- a/src/kiwano/2d/ShapeActor.cpp +++ b/src/kiwano/2d/ShapeActor.cpp @@ -44,10 +44,7 @@ namespace kiwano Rect ShapeActor::GetBounds() const { - if (!geo_) - return Rect{}; - - return geo_.GetBoundingBox(Matrix3x2()); + return bounds_; } Rect ShapeActor::GetBoundingBox() const @@ -58,6 +55,11 @@ namespace kiwano return geo_.GetBoundingBox(GetTransformMatrix()); } + bool ShapeActor::ContainsPoint(const Point& point) const + { + return geo_.ContainsPoint(point, GetTransformMatrix()); + } + void ShapeActor::SetFillColor(const Color & color) { fill_color_ = color; @@ -78,18 +80,33 @@ namespace kiwano stroke_style_ = stroke_style; } - void ShapeActor::OnRender(Renderer* renderer) + void ShapeActor::SetGeometry(Geometry geometry) { + geo_ = geometry; if (geo_) { - PrepareRender(renderer); + bounds_ = geo_.GetBoundingBox(Matrix3x2()); + SetSize(bounds_.GetSize()); + } + else + { + bounds_ = Rect{}; + SetSize(0.f, 0.f); + } + } - renderer->FillGeometry( + void ShapeActor::OnRender(RenderTarget* rt) + { + if (geo_ && rt->CheckVisibility(GetBounds(), GetTransformMatrix())) + { + PrepareRender(rt); + + rt->FillGeometry( geo_, fill_color_ ); - renderer->DrawGeometry( + rt->DrawGeometry( geo_, stroke_color_, stroke_width_, @@ -106,22 +123,23 @@ namespace kiwano { } - LineActor::LineActor(Point const& end) + LineActor::LineActor(Point const& point) { - SetEndPoint(end); + SetPoint(point); } LineActor::~LineActor() { } - void LineActor::SetEndPoint(Point const& end) + void LineActor::SetPoint(Point const& point) { - geo_ = Geometry::CreateLine(Point{}, end); + Geometry geo = Geometry::CreateLine(Point{}, point); - if (geo_) + if (geo) { - SetSize(end); + point_ = point; + SetGeometry(geo); } } @@ -145,11 +163,12 @@ namespace kiwano void RectActor::SetRectSize(Size const& size) { - geo_ = Geometry::CreateRect(Rect{ Point{}, size }); + Geometry geo = Geometry::CreateRect(Rect{ Point{}, size }); - if (geo_) + if (geo) { - SetSize(size); + rect_size_ = size; + SetGeometry(geo); } } @@ -183,11 +202,12 @@ namespace kiwano void RoundRectActor::SetRoundedRect(Size const& size, Vec2 const& radius) { - geo_ = Geometry::CreateRoundedRect(Rect{ Point{}, size }, radius); + Geometry geo = Geometry::CreateRoundedRect(Rect{ Point{}, size }, radius); - if (geo_) + if (geo) { - SetSize(size); + rect_size_ = size; + SetGeometry(geo); } } @@ -212,11 +232,11 @@ namespace kiwano void CircleActor::SetRadius(Float32 radius) { - geo_ = Geometry::CreateCircle(Point{}, radius); + Geometry geo = Geometry::CreateCircle(Point{}, radius); - if (geo_) + if (geo) { - SetSize(radius * 2, radius * 2); + SetGeometry(geo); } } @@ -240,11 +260,11 @@ namespace kiwano void EllipseActor::SetRadius(Vec2 const& radius) { - geo_ = Geometry::CreateEllipse(Point{}, radius); + Geometry geo = Geometry::CreateEllipse(Point{}, radius); - if (geo_) + if (geo) { - SetSize(radius * 2); + SetGeometry(geo); } } @@ -269,7 +289,12 @@ namespace kiwano void PathActor::EndPath(bool closed) { sink_.EndPath(closed); - geo_ = sink_.GetGeometry(); + Geometry geo = sink_.GetGeometry(); + + if (geo) + { + SetGeometry(geo); + } } void PathActor::AddLine(Point const& point) diff --git a/src/kiwano/2d/ShapeActor.h b/src/kiwano/2d/ShapeActor.h index d643914d..a710e45e 100644 --- a/src/kiwano/2d/ShapeActor.h +++ b/src/kiwano/2d/ShapeActor.h @@ -38,16 +38,19 @@ namespace kiwano virtual ~ShapeActor(); // »ñÈ¡Ìî³äÑÕÉ« - Color GetFillColor() const { return fill_color_; } + inline Color GetFillColor() const { return fill_color_; } // »ñÈ¡ÏßÌõÑÕÉ« - Color GetStrokeColor() const { return stroke_color_; } + inline Color GetStrokeColor() const { return stroke_color_; } // »ñÈ¡ÏßÌõ¿í¶È - Float32 GetStrokeWidth() const { return stroke_width_; } + inline Float32 GetStrokeWidth() const { return stroke_width_; } // »ñÈ¡ÏßÌõÑùʽ - StrokeStyle SetStrokeStyle() const { return stroke_style_; } + inline StrokeStyle SetStrokeStyle() const { return stroke_style_; } + + // »ñÈ¡ÐÎ×´ + inline Geometry GetGeometry() const { return geo_; } // »ñÈ¡±ß½ç Rect GetBounds() const override; @@ -55,44 +58,37 @@ namespace kiwano // »ñÈ¡ÍâÇаüΧºÐ Rect GetBoundingBox() const override; + // ÅжϵãÊÇ·ñÔÚÐÎ×´ÄÚ + bool ContainsPoint(const Point& point) const override; + // ÉèÖÃÌî³äÑÕÉ« - void SetFillColor( - const Color& color - ); + void SetFillColor(const Color& color); // ÉèÖÃÏßÌõÑÕÉ« - void SetStrokeColor( - const Color& color - ); + void SetStrokeColor(const Color& color); // ÉèÖÃÏßÌõ¿í¶È - void SetStrokeWidth( - Float32 width - ); + void SetStrokeWidth(Float32 width); // ÉèÖÃÏßÌõÑùʽ - void SetStrokeStyle( - StrokeStyle stroke_style - ); + void SetStrokeStyle(StrokeStyle stroke_style); // ÉèÖÃÐÎ×´ - inline void SetGeometry(Geometry geometry) { geo_ = geometry; } + void SetGeometry(Geometry geometry); - // »ñÈ¡ÐÎ×´ - inline Geometry GetGeometry() const { return geo_; } - - void OnRender(Renderer* renderer) override; + void OnRender(RenderTarget* rt) override; protected: Color fill_color_; Color stroke_color_; Float32 stroke_width_; StrokeStyle stroke_style_; + Rect bounds_; Geometry geo_; }; - // Ö±Ïß + // Ö±Ïß½ÇÉ« class KGE_API LineActor : public ShapeActor { @@ -100,19 +96,19 @@ namespace kiwano LineActor(); LineActor( - Point const& end_pos + Point const& point ); virtual ~LineActor(); - Point const& GetEndPoint() const { return end_; } + Point const& GetPoint() const { return point_; } - void SetEndPoint( - Point const& end + void SetPoint( + Point const& point ); protected: - Point end_; + Point point_; }; @@ -131,10 +127,10 @@ namespace kiwano void SetRectSize(Size const& size); - inline Size const& GetRectSize() const { return size_; } + inline Size const& GetRectSize() const { return rect_size_; } protected: - Size size_; + Size rect_size_; }; @@ -170,7 +166,7 @@ namespace kiwano inline Size GetRectSize() const { return size_; } protected: - Size size_; + Size rect_size_; Vec2 radius_; }; @@ -261,7 +257,7 @@ namespace kiwano void AddArc( Point const& point, /* ÖÕµã */ Size const& radius, /* ÍÖÔ²°ë¾¶ */ - Float32 rotation, /* ÍÖÔ²Ðýת½Ç¶È */ + Float32 rotation, /* ÍÖÔ²Ðýת½Ç¶È */ bool clockwise = true, /* ˳ʱÕë or ÄæÊ±Õë */ bool is_small = true /* ÊÇ·ñȡСÓÚ 180¡ã µÄ»¡ */ ); diff --git a/src/kiwano/2d/Sprite.cpp b/src/kiwano/2d/Sprite.cpp index 688faf90..38f7e14c 100644 --- a/src/kiwano/2d/Sprite.cpp +++ b/src/kiwano/2d/Sprite.cpp @@ -86,7 +86,7 @@ namespace kiwano if (frame_) { frame_->SetCropRect(crop_rect); - SetSize(frame_->GetWidth(), frame_->GetHeight()); + SetSize(Size{ frame_->GetWidth(), frame_->GetHeight() }); } } @@ -97,18 +97,18 @@ namespace kiwano frame_ = frame; if (frame_) { - SetSize(frame_->GetWidth(), frame_->GetHeight()); + SetSize(Size{ frame_->GetWidth(), frame_->GetHeight() }); } } } - void Sprite::OnRender(Renderer* renderer) + void Sprite::OnRender(RenderTarget* rt) { - if (frame_ && renderer->CheckVisibility(size_, transform_matrix_)) + if (frame_ && rt->CheckVisibility(GetBounds(), GetTransformMatrix())) { - PrepareRender(renderer); + PrepareRender(rt); - renderer->DrawImage(frame_->GetImage(), &frame_->GetCropRect(), nullptr); + rt->DrawImage(frame_->GetImage(), &frame_->GetCropRect(), nullptr); } } } diff --git a/src/kiwano/2d/Sprite.h b/src/kiwano/2d/Sprite.h index 8138f5e2..94dcc79a 100644 --- a/src/kiwano/2d/Sprite.h +++ b/src/kiwano/2d/Sprite.h @@ -77,7 +77,7 @@ namespace kiwano void SetFrame(FramePtr frame); // äÖȾ¾«Áé - void OnRender(Renderer* renderer) override; + void OnRender(RenderTarget* rt) override; protected: FramePtr frame_; diff --git a/src/kiwano/2d/Stage.cpp b/src/kiwano/2d/Stage.cpp index b694a39f..5bdee64f 100644 --- a/src/kiwano/2d/Stage.cpp +++ b/src/kiwano/2d/Stage.cpp @@ -28,7 +28,7 @@ namespace kiwano { stage_ = this; - SetAnchor(0, 0); + SetAnchor(Vec2{ 0, 0 }); SetSize(Renderer::GetInstance()->GetOutputSize()); } diff --git a/src/kiwano/2d/Text.cpp b/src/kiwano/2d/Text.cpp index 2a9c814d..6354d071 100644 --- a/src/kiwano/2d/Text.cpp +++ b/src/kiwano/2d/Text.cpp @@ -200,14 +200,14 @@ namespace kiwano style_.outline_stroke = outline_stroke; } - void Text::OnRender(Renderer* renderer) + void Text::OnRender(RenderTarget* rt) { UpdateLayout(); - if (text_layout_ && renderer->CheckVisibility(size_, transform_matrix_)) + if (text_layout_ && rt->CheckVisibility(GetBounds(), GetTransformMatrix())) { - PrepareRender(renderer); - renderer->DrawTextLayout(text_layout_); + PrepareRender(rt); + rt->DrawTextLayout(text_layout_); } } diff --git a/src/kiwano/2d/Text.h b/src/kiwano/2d/Text.h index ddc48b17..7dd84ef8 100644 --- a/src/kiwano/2d/Text.h +++ b/src/kiwano/2d/Text.h @@ -160,7 +160,7 @@ namespace kiwano TextStyle const& style ); - void OnRender(Renderer* renderer) override; + void OnRender(RenderTarget* rt) override; protected: void UpdateLayout(); diff --git a/src/kiwano/2d/Transform.cpp b/src/kiwano/2d/Transform.cpp new file mode 100644 index 00000000..8e51b6d1 --- /dev/null +++ b/src/kiwano/2d/Transform.cpp @@ -0,0 +1,49 @@ +// 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 "Transform.h" + +namespace kiwano +{ + Transform::Transform() + : position() + , rotation(0.f) + , scale(1.f, 1.f) + , skew(0.f, 0.f) + { + } + + Matrix3x2 Transform::ToMatrix() const + { + if (!skew.IsOrigin()) + { + return Matrix3x2::Skewing(skew) * Matrix3x2::SRT(position, scale, rotation); + } + return Matrix3x2::SRT(position, scale, rotation); + } + + bool Transform::operator== (Transform const& rhs) const + { + return position == rhs.position && + rotation == rhs.rotation && + scale == rhs.scale && + skew == rhs.skew; + } +} diff --git a/src/kiwano/2d/Transform.hpp b/src/kiwano/2d/Transform.h similarity index 79% rename from src/kiwano/2d/Transform.hpp rename to src/kiwano/2d/Transform.h index 64c8824e..9d5fbf97 100644 --- a/src/kiwano/2d/Transform.hpp +++ b/src/kiwano/2d/Transform.h @@ -19,32 +19,23 @@ // THE SOFTWARE. #pragma once -#include "../math/Vec2.hpp" +#include "../math/math.h" namespace kiwano { class Transform { public: - Float32 rotation; // Ðýת + Float32 rotation; // Ðýת Point position; // ×ø±ê Point scale; // Ëõ·Å Point skew; // ´íÇÐ½Ç¶È public: - Transform() - : position() - , rotation(0.f) - , scale(1.f, 1.f) - , skew(0.f, 0.f) - {} + Transform(); - bool operator== (const Transform& other) const - { - return position == other.position && - scale == other.scale && - skew == other.skew && - rotation == other.rotation; - } + Matrix3x2 ToMatrix() const; + + bool operator== (const Transform& rhs) const; }; } diff --git a/src/kiwano/2d/Transition.cpp b/src/kiwano/2d/Transition.cpp index dfa6dd2f..7e294333 100644 --- a/src/kiwano/2d/Transition.cpp +++ b/src/kiwano/2d/Transition.cpp @@ -37,8 +37,8 @@ namespace kiwano , delta_() , process_(0) , window_size_() - , out_scene_(nullptr) - , in_scene_(nullptr) + , out_stage_(nullptr) + , in_stage_(nullptr) , out_layer_() , in_layer_() { @@ -58,22 +58,19 @@ namespace kiwano process_ = 0; delta_ = Duration{}; - out_scene_ = prev; - in_scene_ = next; - - if (in_scene_) - { - Renderer::GetInstance()->CreateLayer(in_layer_); - } - - if (out_scene_) - { - Renderer::GetInstance()->CreateLayer(out_layer_); - } - + out_stage_ = prev; + in_stage_ = next; window_size_ = Renderer::GetInstance()->GetOutputSize(); - out_layer_.SetAreaRect(Rect{ Point(), window_size_ }); - in_layer_.SetAreaRect(Rect{ Point(), window_size_ }); + + if (in_stage_) + { + in_layer_.SetAreaRect(Rect{ Point(), window_size_ }); + } + + if (out_stage_) + { + out_layer_.SetAreaRect(Rect{ Point(), window_size_ }); + } } void Transition::Update(Duration dt) @@ -94,30 +91,30 @@ namespace kiwano } } - void Transition::Render(Renderer* renderer) + void Transition::Render(RenderTarget* rt) { - if (out_scene_) + if (out_stage_) { - renderer->SetTransform(out_scene_->GetTransformMatrix()); - renderer->PushClipRect(Rect{ Point{}, window_size_ }); - renderer->PushLayer(out_layer_); + out_stage_->PrepareRender(rt); + rt->PushClipRect(Rect{ Point{}, window_size_ }); + rt->PushLayer(out_layer_); - out_scene_->Render(renderer); + out_stage_->Render(rt); - renderer->PopLayer(); - renderer->PopClipRect(); + rt->PopLayer(); + rt->PopClipRect(); } - if (in_scene_) + if (in_stage_) { - renderer->SetTransform(in_scene_->GetTransformMatrix()); - renderer->PushClipRect(Rect{ Point{}, window_size_ }); - renderer->PushLayer(in_layer_); + in_stage_->PrepareRender(rt); + rt->PushClipRect(Rect{ Point{}, window_size_ }); + rt->PushLayer(in_layer_); - in_scene_->Render(renderer); + in_stage_->Render(rt); - renderer->PopLayer(); - renderer->PopClipRect(); + rt->PopLayer(); + rt->PopClipRect(); } } @@ -153,8 +150,8 @@ namespace kiwano Rect( window_size_.x * process_, window_size_.y * process_, - window_size_.x * (1 - process_ * 2), - window_size_.y * (1 - process_ * 2) + window_size_.x * (1 - process_), + window_size_.y * (1 - process_) ) ); } @@ -166,8 +163,8 @@ namespace kiwano Rect( window_size_.x * (1 - process_), window_size_.y * (1 - process_), - window_size_.x * (2 * process_ - 1), - window_size_.y * (2 * process_ - 1) + window_size_.x * process_, + window_size_.y * process_ ) ); } @@ -265,16 +262,16 @@ namespace kiwano break; } - if (out_scene_) + if (out_stage_) { - out_scene_->SetTransform(Transform{}); + out_stage_->SetTransform(Transform{}); } - if (in_scene_) + if (in_stage_) { auto transform = Transform{}; transform.position = start_pos_; - in_scene_->SetTransform(transform); + in_stage_->SetTransform(transform); } } @@ -282,31 +279,31 @@ namespace kiwano { Transition::Update(dt); - if (out_scene_) + if (out_stage_) { auto transform = Transform{}; transform.position = pos_delta_ * process_; - out_scene_->SetTransform(transform); + out_stage_->SetTransform(transform); } - if (in_scene_) + if (in_stage_) { auto transform = Transform{}; transform.position = start_pos_ + pos_delta_ * process_; - in_scene_->SetTransform(transform); + in_stage_->SetTransform(transform); } } void MoveTransition::Reset() { - if (out_scene_) + if (out_stage_) { - out_scene_->SetTransform(Transform{}); + out_stage_->SetTransform(Transform{}); } - if (in_scene_) + if (in_stage_) { - in_scene_->SetTransform(Transform{}); + in_stage_->SetTransform(Transform{}); } } @@ -327,16 +324,16 @@ namespace kiwano auto transform = Transform{}; transform.position = Point{ window_size_.x / 2, window_size_.y / 2 }; - if (out_scene_) + if (out_stage_) { - out_scene_->SetTransform(transform); - out_scene_->SetAnchor(0.5f, 0.5f); + out_stage_->SetTransform(transform); + out_stage_->SetAnchor(Vec2{ 0.5f, 0.5f }); } - if (in_scene_) + if (in_stage_) { - in_scene_->SetTransform(transform); - in_scene_->SetAnchor(0.5f, 0.5f); + in_stage_->SetTransform(transform); + in_stage_->SetAnchor(Vec2{ 0.5f, 0.5f }); } in_layer_.SetOpacity(0.f); @@ -348,42 +345,42 @@ namespace kiwano if (process_ < .5f) { - if (out_scene_) + if (out_stage_) { - auto transform = out_scene_->GetTransform(); + auto transform = out_stage_->GetTransform(); transform.scale = Point{ (.5f - process_) * 2, (.5f - process_) * 2 }; transform.rotation = rotation_ * (.5f - process_) * 2; - out_scene_->SetTransform(transform); + out_stage_->SetTransform(transform); } } else { - if (in_scene_) + if (in_stage_) { out_layer_.SetOpacity(0.f); in_layer_.SetOpacity(1.f); - auto transform = in_scene_->GetTransform(); + auto transform = in_stage_->GetTransform(); transform.scale = Point{ (process_ - .5f) * 2, (process_ - .5f) * 2 }; transform.rotation = rotation_ * (process_ - .5f) * 2; - in_scene_->SetTransform(transform); + in_stage_->SetTransform(transform); } } } void RotationTransition::Reset() { - if (out_scene_) + if (out_stage_) { - out_scene_->SetTransform(Transform{}); - out_scene_->SetAnchor(0.f, 0.f); + out_stage_->SetTransform(Transform{}); + out_stage_->SetAnchor(Vec2{ 0.f, 0.f }); } - if (in_scene_) + if (in_stage_) { - in_scene_->SetTransform(Transform{}); - in_scene_->SetAnchor(0.f, 0.f); + in_stage_->SetTransform(Transform{}); + in_stage_->SetAnchor(Vec2{ 0.f, 0.f }); } } } diff --git a/src/kiwano/2d/Transition.h b/src/kiwano/2d/Transition.h index af0a0fe9..5970062c 100644 --- a/src/kiwano/2d/Transition.h +++ b/src/kiwano/2d/Transition.h @@ -25,7 +25,7 @@ namespace kiwano { class Director; - class Renderer; + class RenderTarget; // Îę̀¹ý¶É class KGE_API Transition @@ -50,7 +50,7 @@ namespace kiwano virtual void Update(Duration dt); - virtual void Render(Renderer* renderer); + virtual void Render(RenderTarget* rt); virtual void Stop(); @@ -62,8 +62,8 @@ namespace kiwano Duration duration_; Duration delta_; Size window_size_; - StagePtr out_scene_; - StagePtr in_scene_; + StagePtr out_stage_; + StagePtr in_stage_; LayerArea out_layer_; LayerArea in_layer_; }; diff --git a/src/kiwano/2d/action/Action.h b/src/kiwano/2d/action/Action.h index 6becb2e3..fed487c2 100644 --- a/src/kiwano/2d/action/Action.h +++ b/src/kiwano/2d/action/Action.h @@ -62,7 +62,7 @@ namespace kiwano inline void SetDelay(Duration delay) { delay_ = delay; } // ÉèÖÃÑ­»·´ÎÊý (-1 ΪÓÀ¾ÃÑ­»·) - inline void SetLoops(Int32 loops) { loops_ = loops; } + inline void SetLoops(Int32 loops) { loops_ = loops; } // ¶¯×÷½áÊøÊ±ÒÆ³ýÄ¿±ê½ÇÉ« inline void RemoveTargetWhenDone() { detach_target_ = true; } @@ -89,7 +89,7 @@ namespace kiwano inline bool IsRemoveable() const { return status_ == Status::Removeable; } - inline Int32 GetLoops() const { return loops_; } + inline Int32 GetLoops() const { return loops_; } inline Duration GetDelay() const { return delay_; } @@ -114,8 +114,8 @@ namespace kiwano Status status_; bool running_; bool detach_target_; - Int32 loops_; - Int32 loops_done_; + Int32 loops_; + Int32 loops_done_; Duration delay_; Duration elapsed_; ActionCallback cb_done_; diff --git a/src/kiwano/2d/action/ActionGroup.cpp b/src/kiwano/2d/action/ActionGroup.cpp index 0cd36d40..458d398f 100644 --- a/src/kiwano/2d/action/ActionGroup.cpp +++ b/src/kiwano/2d/action/ActionGroup.cpp @@ -45,7 +45,7 @@ namespace kiwano void ActionGroup::Init(ActorPtr target) { - if (actions_.item_empty()) + if (actions_.empty()) { Done(); return; @@ -106,7 +106,7 @@ namespace kiwano { if (action) { - actions_.push_back_item(action); + actions_.push_back(action); } } @@ -135,7 +135,7 @@ namespace kiwano ActionPtr ActionGroup::Reverse() const { auto group = new (std::nothrow) ActionGroup(); - if (group && !actions_.item_empty()) + if (group && !actions_.empty()) { for (auto action = actions_.last_item(); action; action = action->prev_item()) { diff --git a/src/kiwano/2d/action/ActionHelper.h b/src/kiwano/2d/action/ActionHelper.h index b44bfd41..f6c73ed9 100644 --- a/src/kiwano/2d/action/ActionHelper.h +++ b/src/kiwano/2d/action/ActionHelper.h @@ -64,7 +64,7 @@ namespace kiwano inline TweenHelper& SetDuration(Duration dur) { base->SetDuration(dur); return (*this); } // ÉèÖÃÑ­»·´ÎÊý - inline TweenHelper& SetLoops(Int32 loops) { base->SetLoops(loops); return (*this); } + inline TweenHelper& SetLoops(Int32 loops) { base->SetLoops(loops); return (*this); } // ÉèÖûº¶¯º¯Êý inline TweenHelper& SetEaseFunc(EaseFunc ease) { base->SetEaseFunc(ease); return (*this); } @@ -118,7 +118,7 @@ namespace kiwano Duration dur, Point const& pos, /* Ä¿µÄ×ø±ê */ Float32 height, /* ÌøÔ¾¸ß¶È */ - Int32 jumps = 1) /* ÌøÔ¾´ÎÊý */ + Int32 jumps = 1) /* ÌøÔ¾´ÎÊý */ { return TweenHelper(new kiwano::ActionJumpBy(dur, pos, height, jumps)); } @@ -128,7 +128,7 @@ namespace kiwano Duration dur, Point const& pos, /* Ä¿µÄ×ø±ê */ Float32 height, /* ÌøÔ¾¸ß¶È */ - Int32 jumps = 1) /* ÌøÔ¾´ÎÊý */ + Int32 jumps = 1) /* ÌøÔ¾´ÎÊý */ { return TweenHelper(new kiwano::ActionJumpTo(dur, pos, height, jumps)); } diff --git a/src/kiwano/2d/action/ActionManager.cpp b/src/kiwano/2d/action/ActionManager.cpp index 186c717f..8eed8898 100644 --- a/src/kiwano/2d/action/ActionManager.cpp +++ b/src/kiwano/2d/action/ActionManager.cpp @@ -26,7 +26,7 @@ namespace kiwano { void ActionManager::UpdateActions(ActorPtr target, Duration dt) { - if (actions_.item_empty() || !target) + if (actions_.empty() || !target) return; ActionPtr next; @@ -38,7 +38,7 @@ namespace kiwano action->UpdateStep(target, dt); if (action->IsRemoveable()) - actions_.remove_item(action); + actions_.remove(action); } } @@ -48,14 +48,14 @@ namespace kiwano if (action) { - actions_.push_back_item(action); + actions_.push_back(action); } return action.get(); } ActionPtr ActionManager::GetAction(String const & name) { - if (actions_.item_empty()) + if (actions_.empty()) return nullptr; for (auto action = actions_.first_item().get(); action; action = action->next_item().get()) @@ -66,7 +66,7 @@ namespace kiwano void ActionManager::ResumeAllActions() { - if (actions_.item_empty()) + if (actions_.empty()) return; for (auto action = actions_.first_item().get(); action; action = action->next_item().get()) @@ -77,7 +77,7 @@ namespace kiwano void ActionManager::PauseAllActions() { - if (actions_.item_empty()) + if (actions_.empty()) return; for (auto action = actions_.first_item().get(); action; action = action->next_item().get()) @@ -88,7 +88,7 @@ namespace kiwano void ActionManager::StopAllActions() { - if (actions_.item_empty()) + if (actions_.empty()) return; for (auto action = actions_.first_item().get(); action; action = action->next_item().get()) diff --git a/src/kiwano/2d/action/ActionTween.cpp b/src/kiwano/2d/action/ActionTween.cpp index 360f507a..7b2f28b9 100644 --- a/src/kiwano/2d/action/ActionTween.cpp +++ b/src/kiwano/2d/action/ActionTween.cpp @@ -281,7 +281,7 @@ namespace kiwano void ActionScaleBy::UpdateTween(ActorPtr target, Float32 percent) { - target->SetScale(start_scale_x_ + delta_x_ * percent, start_scale_y_ + delta_y_ * percent); + target->SetScale(Vec2{ start_scale_x_ + delta_x_ * percent, start_scale_y_ + delta_y_ * percent }); } ActionPtr ActionScaleBy::Clone() const diff --git a/src/kiwano/2d/action/ActionTween.h b/src/kiwano/2d/action/ActionTween.h index 4b52f091..70146a2e 100644 --- a/src/kiwano/2d/action/ActionTween.h +++ b/src/kiwano/2d/action/ActionTween.h @@ -166,7 +166,7 @@ namespace kiwano Duration duration, /* ³ÖÐøÊ±³¤ */ Point const& vec, /* ÌøÔ¾¾àÀë */ Float32 height, /* ÌøÔ¾¸ß¶È */ - Int32 jumps = 1, /* ÌøÔ¾´ÎÊý */ + Int32 jumps = 1, /* ÌøÔ¾´ÎÊý */ EaseFunc func = nullptr /* Ëٶȱ仯 */ ); @@ -199,7 +199,7 @@ namespace kiwano Duration duration, /* ³ÖÐøÊ±³¤ */ Point const& pos, /* Ä¿µÄ×ø±ê */ Float32 height, /* ÌøÔ¾¸ß¶È */ - Int32 jumps = 1, /* ÌøÔ¾´ÎÊý */ + Int32 jumps = 1, /* ÌøÔ¾´ÎÊý */ EaseFunc func = nullptr /* Ëٶȱ仯 */ ); @@ -234,8 +234,8 @@ namespace kiwano ActionScaleBy( Duration duration, /* ³ÖÐøÊ±³¤ */ - Float32 scale_x, /* ºáÏòËõ·ÅÏà¶Ô±ä»¯Öµ */ - Float32 scale_y, /* ×ÝÏòËõ·ÅÏà¶Ô±ä»¯Öµ */ + Float32 scale_x, /* ºáÏòËõ·ÅÏà¶Ô±ä»¯Öµ */ + Float32 scale_y, /* ×ÝÏòËõ·ÅÏà¶Ô±ä»¯Öµ */ EaseFunc func = nullptr /* Ëٶȱ仯 */ ); @@ -271,8 +271,8 @@ namespace kiwano ActionScaleTo( Duration duration, /* ³ÖÐøÊ±³¤ */ - Float32 scale_x, /* ºáÏòËõ·ÅÄ¿±êÖµ */ - Float32 scale_y, /* ×ÝÏòËõ·ÅÄ¿±êÖµ */ + Float32 scale_x, /* ºáÏòËõ·ÅÄ¿±êÖµ */ + Float32 scale_y, /* ×ÝÏòËõ·ÅÄ¿±êÖµ */ EaseFunc func = nullptr /* Ëٶȱ仯 */ ); @@ -302,7 +302,7 @@ namespace kiwano public: ActionFadeTo( Duration duration, /* ³ÖÐøÊ±³¤ */ - Float32 opacity, /* Ä¿±êÖµ */ + Float32 opacity, /* Ä¿±êÖµ */ EaseFunc func = nullptr /* Ëٶȱ仯 */ ); @@ -361,7 +361,7 @@ namespace kiwano public: ActionRotateBy( Duration duration, /* ³ÖÐøÊ±³¤ */ - Float32 rotation, /* Ïà¶Ô±ä»¯Öµ */ + Float32 rotation, /* Ïà¶Ô±ä»¯Öµ */ EaseFunc func = nullptr /* Ëٶȱ仯 */ ); @@ -389,7 +389,7 @@ namespace kiwano public: ActionRotateTo( Duration duration, /* ³ÖÐøÊ±³¤ */ - Float32 rotation, /* Ä¿±êÖµ */ + Float32 rotation, /* Ä¿±êÖµ */ EaseFunc func = nullptr /* Ëٶȱ仯 */ ); diff --git a/src/kiwano/base/Component.h b/src/kiwano/base/Component.h index f68116a2..1198284b 100644 --- a/src/kiwano/base/Component.h +++ b/src/kiwano/base/Component.h @@ -25,7 +25,7 @@ namespace kiwano { - class Renderer; + class RenderTarget; class KGE_API Component { @@ -38,7 +38,7 @@ namespace kiwano virtual void AfterUpdate() {} virtual void BeforeRender() {} - virtual void OnRender(Renderer*) {} + virtual void OnRender(RenderTarget*) {} virtual void AfterRender() {} virtual void HandleEvent(Event&) {} diff --git a/src/kiwano/base/Director.cpp b/src/kiwano/base/Director.cpp index 39d5d36e..1c588ba2 100644 --- a/src/kiwano/base/Director.cpp +++ b/src/kiwano/base/Director.cpp @@ -23,6 +23,7 @@ #include "../2d/Stage.h" #include "../2d/Transition.h" #include "../2d/DebugActor.h" +#include "../renderer/RenderTarget.h" namespace kiwano { @@ -35,34 +36,34 @@ namespace kiwano { } - void Director::EnterStage(StagePtr scene) + void Director::EnterStage(StagePtr stage) { - KGE_ASSERT(scene && "Director::EnterStage failed, NULL pointer exception"); + KGE_ASSERT(stage && "Director::EnterStage failed, NULL pointer exception"); - if (curr_scene_ == scene || next_scene_ == scene) + if (curr_stage_ == stage || next_stage_ == stage) return; - next_scene_ = scene; + next_stage_ = stage; } - void Director::EnterStage(StagePtr scene, TransitionPtr transition) + void Director::EnterStage(StagePtr stage, TransitionPtr transition) { - EnterStage(scene); + EnterStage(stage); - if (transition && next_scene_) + if (transition && next_stage_) { if (transition_) { transition_->Stop(); } transition_ = transition; - transition_->Init(curr_scene_, next_scene_); + transition_->Init(curr_stage_, next_stage_); } } StagePtr Director::GetCurrentStage() { - return curr_scene_; + return curr_stage_; } void Director::SetRenderBorderEnabled(bool enabled) @@ -85,8 +86,8 @@ namespace kiwano void Director::ClearStages() { - curr_scene_.reset(); - next_scene_.reset(); + curr_stage_.reset(); + next_stage_.reset(); debug_actor_.reset(); transition_.reset(); } @@ -101,54 +102,52 @@ namespace kiwano transition_ = nullptr; } - if (next_scene_ && !transition_) + if (next_stage_ && !transition_) { - if (curr_scene_) + if (curr_stage_) { - curr_scene_->OnExit(); + curr_stage_->OnExit(); } - next_scene_->OnEnter(); + next_stage_->OnEnter(); - curr_scene_ = next_scene_; - next_scene_ = nullptr; + curr_stage_ = next_stage_; + next_stage_ = nullptr; } - if (curr_scene_) - curr_scene_->Update(dt); + if (curr_stage_) + curr_stage_->Update(dt); - if (next_scene_) - next_scene_->Update(dt); + if (next_stage_) + next_stage_->Update(dt); if (debug_actor_) debug_actor_->Update(dt); } - void Director::OnRender(Renderer* renderer) + void Director::OnRender(RenderTarget* rt) { if (transition_) { - transition_->Render(renderer); + transition_->Render(rt); } - else if (curr_scene_) + else if (curr_stage_) { - curr_scene_->Render(renderer); + curr_stage_->Render(rt); + } + + if (render_border_enabled_) + { + rt->SetOpacity(1.f); + if (curr_stage_) + { + curr_stage_->RenderBorder(rt); + } } if (debug_actor_) { - debug_actor_->Render(renderer); - } - } - - void Director::AfterRender() - { - if (render_border_enabled_) - { - if (curr_scene_) - { - curr_scene_->RenderBorder(); - } + debug_actor_->Render(rt); } } @@ -157,8 +156,8 @@ namespace kiwano if (debug_actor_) debug_actor_->Dispatch(evt); - if (curr_scene_) - curr_scene_->Dispatch(evt); + if (curr_stage_) + curr_stage_->Dispatch(evt); } } diff --git a/src/kiwano/base/Director.h b/src/kiwano/base/Director.h index 2b96f617..4799fc3f 100644 --- a/src/kiwano/base/Director.h +++ b/src/kiwano/base/Director.h @@ -35,12 +35,12 @@ namespace kiwano public: // Çл»Îę̀ void EnterStage( - StagePtr scene /* Îę̀ */ + StagePtr stage /* Îę̀ */ ); // Çл»Îę̀ void EnterStage( - StagePtr scene, /* Îę̀ */ + StagePtr stage, /* Îę̀ */ TransitionPtr transition /* ¹ý¶É¶¯»­ */ ); @@ -63,9 +63,7 @@ namespace kiwano void OnUpdate(Duration dt) override; - void OnRender(Renderer* renderer) override; - - void AfterRender() override; + void OnRender(RenderTarget* rt) override; void HandleEvent(Event& evt) override; @@ -76,8 +74,8 @@ namespace kiwano protected: bool render_border_enabled_; - StagePtr curr_scene_; - StagePtr next_scene_; + StagePtr curr_stage_; + StagePtr next_stage_; ActorPtr debug_actor_; TransitionPtr transition_; }; diff --git a/src/kiwano/base/EventDispatcher.cpp b/src/kiwano/base/EventDispatcher.cpp index 4626598c..f74deea3 100644 --- a/src/kiwano/base/EventDispatcher.cpp +++ b/src/kiwano/base/EventDispatcher.cpp @@ -25,7 +25,7 @@ namespace kiwano { void EventDispatcher::Dispatch(Event& evt) { - if (listeners_.item_empty()) + if (listeners_.empty()) return; EventListenerPtr next; @@ -40,24 +40,21 @@ namespace kiwano } } - EventListenerPtr EventDispatcher::AddListener(EventListenerPtr listener) + EventListener* EventDispatcher::AddListener(EventListenerPtr listener) { KGE_ASSERT(listener && "AddListener failed, NULL pointer exception"); if (listener) { - listeners_.push_back_item(listener); + listeners_.push_back(listener); } - return listener; + return listener.get(); } - void EventDispatcher::AddListener(UInt32 type, EventCallback callback, String const& name) + EventListener* EventDispatcher::AddListener(UInt32 type, EventCallback callback, String const& name) { EventListenerPtr listener = new EventListener(type, callback, name); - if (listener) - { - listeners_.push_back_item(listener); - } + return AddListener(listener); } void EventDispatcher::StartListeners(String const & listener_name) @@ -91,7 +88,7 @@ namespace kiwano if (listener->IsName(listener_name)) { - listeners_.remove_item(listener); + listeners_.remove(listener); } } } @@ -127,7 +124,7 @@ namespace kiwano if (listener->type_ == type) { - listeners_.remove_item(listener); + listeners_.remove(listener); } } } diff --git a/src/kiwano/base/EventDispatcher.h b/src/kiwano/base/EventDispatcher.h index 02581f8c..786b6e7d 100644 --- a/src/kiwano/base/EventDispatcher.h +++ b/src/kiwano/base/EventDispatcher.h @@ -29,12 +29,12 @@ namespace kiwano public: // Ìí¼Ó¼àÌýÆ÷ - EventListenerPtr AddListener( + EventListener* AddListener( EventListenerPtr listener ); // Ìí¼Ó¼àÌýÆ÷ - void AddListener( + EventListener* AddListener( UInt32 type, EventCallback callback, String const& name = L"" diff --git a/src/kiwano/base/Logger.cpp b/src/kiwano/base/Logger.cpp index 02cb9fed..5ec38c4d 100644 --- a/src/kiwano/base/Logger.cpp +++ b/src/kiwano/base/Logger.cpp @@ -279,7 +279,7 @@ namespace kiwano { static WChar temp_buffer[1024 * 3 + 1]; - std::wstringstream ss; + StringStream ss; ss << Logger::OutPrefix; if (prompt) diff --git a/src/kiwano/base/Logger.h b/src/kiwano/base/Logger.h index b4934b97..60159af5 100644 --- a/src/kiwano/base/Logger.h +++ b/src/kiwano/base/Logger.h @@ -263,7 +263,7 @@ namespace kiwano template std::wstring Logger::MakeOutputString(const WChar* prompt, _Args&& ... args) const { - std::wstringstream ss; + StringStream ss; ss << Logger::OutPrefix; if (prompt) diff --git a/src/kiwano/base/ObjectBase.h b/src/kiwano/base/ObjectBase.h index 3737d9d5..570c68d8 100644 --- a/src/kiwano/base/ObjectBase.h +++ b/src/kiwano/base/ObjectBase.h @@ -46,7 +46,7 @@ namespace kiwano inline bool IsName(String const& name) const { return name_ ? (*name_ == name) : name.empty(); } - inline UInt32 GetObjectID() const { return id_; } + inline UInt32 GetObjectID() const { return id_; } String DumpObject(); diff --git a/src/kiwano/base/Resource.cpp b/src/kiwano/base/Resource.cpp index a6b2e336..fb0a8dc8 100644 --- a/src/kiwano/base/Resource.cpp +++ b/src/kiwano/base/Resource.cpp @@ -31,7 +31,7 @@ namespace kiwano } - Resource::Resource(UInt32 id, LPCWSTR type) + Resource::Resource(UInt32 id, const WChar* type) : id_(id) , type_(type) { diff --git a/src/kiwano/base/Resource.h b/src/kiwano/base/Resource.h index 0b5acb61..114c1202 100644 --- a/src/kiwano/base/Resource.h +++ b/src/kiwano/base/Resource.h @@ -49,8 +49,8 @@ namespace kiwano Resource(); Resource( - UInt32 id, /* ×ÊÔ´Ãû³Æ */ - LPCWSTR type /* ×ÊÔ´ÀàÐÍ */ + UInt32 id, /* ×ÊÔ´ ID */ + const WChar* type /* ×ÊÔ´ÀàÐÍ */ ); // »ñÈ¡¶þ½øÖÆÊý¾Ý @@ -58,11 +58,12 @@ namespace kiwano inline UInt32 GetId() const { return id_; } - inline LPCWSTR GetType() const { return type_; } + inline const WChar* GetType() const { return type_; } private: - UInt32 id_; - LPCWSTR type_; + UInt32 id_; + const WChar* type_; + mutable Resource::Data data_; }; } diff --git a/src/kiwano/base/Timer.cpp b/src/kiwano/base/Timer.cpp index cc34b2a9..4e4b5c3e 100644 --- a/src/kiwano/base/Timer.cpp +++ b/src/kiwano/base/Timer.cpp @@ -22,11 +22,6 @@ namespace kiwano { - Timer::Timer(Callback const& func, String const& name) - : Timer(func, Duration{}, -1, name) - { - } - Timer::Timer(Callback const& func, Duration delay, Int32 times, String const& name) : running_(true) , run_times_(0) @@ -91,4 +86,4 @@ namespace kiwano return running_; } -} \ No newline at end of file +} diff --git a/src/kiwano/base/Timer.h b/src/kiwano/base/Timer.h index 20d066af..02e4b67d 100644 --- a/src/kiwano/base/Timer.h +++ b/src/kiwano/base/Timer.h @@ -40,15 +40,10 @@ namespace kiwano using Callback = Function; public: - explicit Timer( - Callback const& func, /* Ö´Ðк¯Êý */ - String const& name = L"" /* ÈÎÎñÃû³Æ */ - ); - - explicit Timer( + Timer( Callback const& func, /* Ö´Ðк¯Êý */ Duration delay, /* ʱ¼ä¼ä¸ô£¨Ã룩 */ - Int32 times = -1, /* Ö´ÐдÎÊý£¨Éè -1 ΪÓÀ¾ÃÖ´ÐУ© */ + Int32 times = -1, /* Ö´ÐдÎÊý£¨Éè -1 ΪÓÀ¾ÃÖ´ÐУ© */ String const& name = L"" /* ÈÎÎñÃû³Æ */ ); @@ -68,8 +63,8 @@ namespace kiwano protected: bool running_; - Int32 run_times_; - Int32 total_times_; + Int32 run_times_; + Int32 total_times_; Duration delay_; Duration delta_; Callback callback_; diff --git a/src/kiwano/base/TimerManager.cpp b/src/kiwano/base/TimerManager.cpp index 0380baf8..41a11654 100644 --- a/src/kiwano/base/TimerManager.cpp +++ b/src/kiwano/base/TimerManager.cpp @@ -25,7 +25,7 @@ namespace kiwano { void TimerManager::UpdateTimers(Duration dt) { - if (timers_.item_empty()) + if (timers_.empty()) return; TimerPtr next; @@ -37,24 +37,32 @@ namespace kiwano timer->Update(dt, remove_after_update); if (remove_after_update) - timers_.remove_item(timer); + timers_.remove(timer); } } - void TimerManager::AddTimer(TimerPtr timer) + Timer* TimerManager::AddTimer(Timer::Callback const& func, Duration delay, Int32 times, String const& name) + { + TimerPtr timer = new Timer(func, delay, times, name); + return AddTimer(timer); + } + + Timer* TimerManager::AddTimer(TimerPtr timer) { KGE_ASSERT(timer && "AddTimer failed, NULL pointer exception"); if (timer) { timer->Reset(); - timers_.push_back_item(timer); + timers_.push_back(timer); } + + return timer.get(); } void TimerManager::StopTimers(String const& name) { - if (timers_.item_empty()) + if (timers_.empty()) return; for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get()) @@ -68,7 +76,7 @@ namespace kiwano void TimerManager::StartTimers(String const& name) { - if (timers_.item_empty()) + if (timers_.empty()) return; for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get()) @@ -82,7 +90,7 @@ namespace kiwano void TimerManager::RemoveTimers(String const& name) { - if (timers_.item_empty()) + if (timers_.empty()) return; TimerPtr next; @@ -91,14 +99,14 @@ namespace kiwano next = timer->next_item(); if (timer->IsName(name)) { - timers_.remove_item(timer); + timers_.remove(timer); } } } void TimerManager::StopAllTimers() { - if (timers_.item_empty()) + if (timers_.empty()) return; for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get()) @@ -109,7 +117,7 @@ namespace kiwano void TimerManager::StartAllTimers() { - if (timers_.item_empty()) + if (timers_.empty()) return; for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get()) @@ -120,7 +128,7 @@ namespace kiwano void TimerManager::RemoveAllTimers() { - timers_.clear_items(); + timers_.clear(); } const TimerManager::Timers & TimerManager::GetAllTimers() const diff --git a/src/kiwano/base/TimerManager.h b/src/kiwano/base/TimerManager.h index 3cfb474c..2b44bc60 100644 --- a/src/kiwano/base/TimerManager.h +++ b/src/kiwano/base/TimerManager.h @@ -28,8 +28,16 @@ namespace kiwano using Timers = intrusive_list; public: - // Ìí¼ÓÈÎÎñ - void AddTimer( + // Ìí¼Ó¶¨Ê±Æ÷ + Timer* AddTimer( + Timer::Callback const& func, /* Ö´Ðк¯Êý */ + Duration delay, /* ʱ¼ä¼ä¸ô£¨Ã룩 */ + Int32 times = -1, /* Ö´ÐдÎÊý£¨Éè -1 ΪÓÀ¾ÃÖ´ÐУ© */ + String const& name = L"" /* ÈÎÎñÃû³Æ */ + ); + + // Ìí¼Ó¶¨Ê±Æ÷ + Timer* AddTimer( TimerPtr timer ); diff --git a/src/kiwano/base/Window.cpp b/src/kiwano/base/Window.cpp index c2027c29..e62121bb 100644 --- a/src/kiwano/base/Window.cpp +++ b/src/kiwano/base/Window.cpp @@ -21,7 +21,8 @@ #include "Window.h" #include "Logger.h" -#define WINDOW_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX +#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 #define KGE_WND_CLASS_NAME L"KiwanoAppWnd" @@ -44,7 +45,8 @@ namespace kiwano , height_(0) , device_name_(nullptr) , is_fullscreen_(false) - , mouse_cursor_(MouseCursor(-1)) + , resizable_(false) + , mouse_cursor_(MouseCursor::Arrow) { } @@ -66,7 +68,7 @@ namespace kiwano } } - void Window::Init(String const& title, Int32 width, Int32 height, LPCWSTR icon, bool fullscreen, WNDPROC proc) + void Window::Init(String const& title, Int32 width, Int32 height, UInt32 icon, bool resizable, bool fullscreen, WNDPROC proc) { HINSTANCE hinst = GetModuleHandleW(nullptr); WNDCLASSEX wcex = { 0 }; @@ -80,11 +82,11 @@ namespace kiwano wcex.hInstance = hinst; wcex.hbrBackground = nullptr; wcex.lpszMenuName = nullptr; - wcex.hCursor = nullptr; + wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW); if (icon) { - wcex.hIcon = (HICON)::LoadImageW(hinst, icon, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE); + wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(icon), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE); } ::RegisterClassExW(&wcex); @@ -106,6 +108,7 @@ namespace kiwano Int32 left = -1; Int32 top = -1; + resizable_ = resizable; is_fullscreen_ = fullscreen; if (is_fullscreen_) @@ -165,8 +168,6 @@ namespace kiwano GetClientRect(handle_, &rc); width_ = rc.right - rc.left; height_ = rc.bottom - rc.top; - - SetMouseCursor(MouseCursor::Arrow); } } @@ -216,14 +217,14 @@ namespace kiwano return static_cast(height_); } - void Window::SetIcon(LPCWSTR icon_resource) + void Window::SetIcon(UInt32 icon_resource) { if (handle_) { HINSTANCE hinstance = GetModuleHandle(nullptr); HICON icon = (HICON)::LoadImage( hinstance, - icon_resource, + MAKEINTRESOURCE(icon_resource), IMAGE_ICON, 0, 0, @@ -296,24 +297,7 @@ namespace kiwano void Window::SetMouseCursor(MouseCursor cursor) { - if (mouse_cursor_ != cursor) - { - mouse_cursor_ = cursor; - - LPTSTR win32_cursor = IDC_ARROW; - switch (cursor) - { - case MouseCursor::Arrow: win32_cursor = IDC_ARROW; break; - case MouseCursor::TextInput: win32_cursor = IDC_IBEAM; break; - case MouseCursor::SizeAll: win32_cursor = IDC_SIZEALL; break; - case MouseCursor::SizeWE: win32_cursor = IDC_SIZEWE; break; - case MouseCursor::SizeNS: win32_cursor = IDC_SIZENS; break; - case MouseCursor::SizeNESW: win32_cursor = IDC_SIZENESW; break; - case MouseCursor::SizeNWSE: win32_cursor = IDC_SIZENWSE; break; - case MouseCursor::Hand: win32_cursor = IDC_HAND; break; - } - ::SetCursor(::LoadCursorW(nullptr, win32_cursor)); - } + mouse_cursor_ = cursor; } HWND Window::GetHandle() const @@ -323,7 +307,7 @@ namespace kiwano DWORD Window::GetWindowStyle() const { - return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (WINDOW_STYLE); + return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE)); } void Window::UpdateWindowRect() @@ -338,6 +322,23 @@ namespace kiwano height_ = rc.bottom - rc.top; } + void Window::UpdateCursor() + { + LPTSTR win32_cursor = IDC_ARROW; + switch (mouse_cursor_) + { + case MouseCursor::Arrow: win32_cursor = IDC_ARROW; break; + case MouseCursor::TextInput: win32_cursor = IDC_IBEAM; break; + case MouseCursor::SizeAll: win32_cursor = IDC_SIZEALL; break; + case MouseCursor::SizeWE: win32_cursor = IDC_SIZEWE; break; + case MouseCursor::SizeNS: win32_cursor = IDC_SIZENS; break; + case MouseCursor::SizeNESW: win32_cursor = IDC_SIZENESW; break; + case MouseCursor::SizeNWSE: win32_cursor = IDC_SIZENWSE; break; + case MouseCursor::Hand: win32_cursor = IDC_HAND; break; + } + ::SetCursor(::LoadCursorW(nullptr, win32_cursor)); + } + void Window::SetActive(bool actived) { if (!handle_) diff --git a/src/kiwano/base/Window.h b/src/kiwano/base/Window.h index 8c649f74..b613b941 100644 --- a/src/kiwano/base/Window.h +++ b/src/kiwano/base/Window.h @@ -48,7 +48,7 @@ namespace kiwano void SetTitle(String const& title); // ÉèÖô°¿Úͼ±ê - void SetIcon(LPCWSTR icon_resource); + void SetIcon(UInt32 icon_resource); // ÖØÉè´°¿Ú´óС void Resize(Int32 width, Int32 height); @@ -62,9 +62,10 @@ namespace kiwano public: void Init( String const& title, - Int32 width, - Int32 height, - LPCWSTR icon, + Int32 width, + Int32 height, + UInt32 icon, + bool resizable, bool fullscreen, WNDPROC proc ); @@ -77,6 +78,8 @@ namespace kiwano void UpdateWindowRect(); + void UpdateCursor(); + void SetActive(bool actived); protected: @@ -85,11 +88,12 @@ namespace kiwano ~Window(); private: - HWND handle_; - bool is_fullscreen_; + bool resizable_; + bool is_fullscreen_; + HWND handle_; Int32 width_; Int32 height_; - WCHAR* device_name_; - MouseCursor mouse_cursor_; + WCHAR* device_name_; + MouseCursor mouse_cursor_; }; } diff --git a/src/kiwano/base/types.h b/src/kiwano/base/types.h index 0066700c..8bc6aa8b 100644 --- a/src/kiwano/base/types.h +++ b/src/kiwano/base/types.h @@ -51,4 +51,13 @@ namespace kiwano GrayScale, // »Ò¶È¿¹¾â³Ý None // ²»ÆôÓÿ¹¾â³Ý }; + + // ·Ö±æÂÊģʽ + enum class ResolutionMode + { + Fixed, /* ¹Ì¶¨ */ + Center, /* ¾ÓÖÐ */ + Stretch, /* À­Éì */ + Adaptive, /* ¿í¸ß×ÔÊÊÓ¦ */ + }; } diff --git a/src/kiwano/core/core.h b/src/kiwano/core/core.h index ea5f63d8..23ade2dd 100644 --- a/src/kiwano/core/core.h +++ b/src/kiwano/core/core.h @@ -33,6 +33,7 @@ #include #include #include +#include namespace kiwano { diff --git a/src/kiwano/core/intrusive_list.hpp b/src/kiwano/core/intrusive_list.hpp index cfbaa93a..448178eb 100644 --- a/src/kiwano/core/intrusive_list.hpp +++ b/src/kiwano/core/intrusive_list.hpp @@ -71,9 +71,9 @@ class intrusive_list public: using ItemType = T; - intrusive_list() : first_(), last_() {} + intrusive_list() : first_(), last_() {} - ~intrusive_list() { clear_items(); } + ~intrusive_list() { clear(); } T const& first_item() const { return first_; } @@ -83,9 +83,9 @@ public: T& last_item() { return last_; } - bool item_empty() const { return !first_; } + bool empty() const { return !first_; } - void push_back_item(T const& child) + void push_back(T const& child) { if (child->prev_) child->prev_->next_ = child->next_; @@ -109,7 +109,7 @@ public: KGE_DEBUG_CHECK_LIST(this); } - void push_front_item(T const& child) + void push_front(T const& child) { if (child->prev_) child->prev_->next_ = child->next_; @@ -171,7 +171,7 @@ public: KGE_DEBUG_CHECK_LIST(this); } - void remove_item(T const& child) + void remove(T const& child) { #ifdef KGE_DEBUG_ENABLE_LIST_CHECK T tmp = first_; @@ -206,7 +206,7 @@ public: KGE_DEBUG_CHECK_LIST(this); } - void clear_items() + void clear() { T p = first_; while (p) diff --git a/src/kiwano/core/types.h b/src/kiwano/core/types.h index 85f23f2a..a7d74bd9 100644 --- a/src/kiwano/core/types.h +++ b/src/kiwano/core/types.h @@ -28,6 +28,7 @@ namespace kiwano KGE_DEFINE_NUMERIC_TYPE(Char, signed char); KGE_DEFINE_NUMERIC_TYPE(UChar, unsigned char); KGE_DEFINE_NUMERIC_TYPE(WChar, wchar_t); + KGE_DEFINE_NUMERIC_TYPE(Byte, UChar); KGE_DEFINE_NUMERIC_TYPE(Int8, std::int8_t); KGE_DEFINE_NUMERIC_TYPE(Int16, std::int16_t); diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h index 5ddf7f3d..8581c7f0 100644 --- a/src/kiwano/kiwano.h +++ b/src/kiwano/kiwano.h @@ -95,7 +95,7 @@ // -#include "2d/Transform.hpp" +#include "2d/Transform.h" #include "2d/TextStyle.hpp" #include "2d/Frame.h" diff --git a/src/kiwano/math/Matrix.hpp b/src/kiwano/math/Matrix.hpp index 6c6b94ec..084e7561 100644 --- a/src/kiwano/math/Matrix.hpp +++ b/src/kiwano/math/Matrix.hpp @@ -172,7 +172,7 @@ namespace kiwano value_type top = std::min(std::min(top_left.y, top_right.y), std::min(bottom_left.y, bottom_right.y)); value_type bottom = std::max(std::max(top_left.y, top_right.y), std::max(bottom_left.y, bottom_right.y)); - return rect_type{ left, top, (right - left), (bottom - top) }; + return rect_type{ left, top, right, bottom }; } inline void Translate(const vec2_type& v) @@ -324,8 +324,3 @@ namespace kiwano } } } - -namespace kiwano -{ - using Matrix3x2 = kiwano::math::Matrix3x2T; -} diff --git a/src/kiwano/math/Rect.hpp b/src/kiwano/math/Rect.hpp index f37b3fe3..d9f44344 100644 --- a/src/kiwano/math/Rect.hpp +++ b/src/kiwano/math/Rect.hpp @@ -25,100 +25,105 @@ namespace kiwano { namespace math { - // ¾ØÐÎ template struct RectT { public: using value_type = _Ty; - Vec2T origin; // ×óÉϽÇ×ø±ê - Vec2T size; // ¿í¶ÈºÍ¸ß¶È + Vec2T left_top; + Vec2T right_bottom; public: RectT() {} RectT( - value_type x, - value_type y, - value_type width, - value_type height + value_type left, + value_type top, + value_type right, + value_type bottom ) - : origin(x, y) - , size(width, height) + : left_top(left, top) + , right_bottom(right, bottom) {} RectT( - const Vec2T& pos, - const Vec2T& size + const Vec2T& left_top, + const Vec2T& right_bottom ) - : origin(pos.x, pos.y) - , size(size.x, size.y) + : left_top(left_top) + , right_bottom(right_bottom) {} RectT( const RectT& other ) - : origin(other.origin.x, other.origin.y) - , size(other.size.x, other.size.y) + : left_top(other.left_top) + , right_bottom(other.right_bottom) {} RectT& operator= (const RectT& other) { - origin = other.origin; - size = other.size; + left_top = other.left_top; + right_bottom = other.right_bottom; return *this; } inline bool operator== (const RectT& rect) const { - return (origin == rect.origin) && (size == rect.size); + return (left_top == rect.left_top) && (right_bottom == rect.right_bottom); } - inline void Set(value_type x, value_type y, value_type width, value_type height) + inline void Set(value_type left, value_type top, value_type right, value_type bottom) { - origin = Vec2T{ x, y }; - size = Vec2T{ width, height }; + left_top = Vec2T{ left, top }; + right_bottom = Vec2T{ right, bottom }; } - inline Vec2T GetCenter() const { return Vec2T{ origin.x + size.x / 2, origin.y + size.y / 2 }; } + inline Vec2T GetCenter() const { return Vec2T{ (left_top.x + right_bottom.x) / 2, (left_top.y + right_bottom.y) / 2 }; } - inline Vec2T GetLeftTop() const { return origin; } + inline Vec2T GetLeftTop() const { return left_top; } - inline Vec2T GetRightBottom() const { return Vec2T{ GetRight(), GetBottom() }; } + inline Vec2T GetRightBottom() const { return right_bottom; } - inline Vec2T GetRightTop() const { return Vec2T{ GetRight(), GetTop() }; } + inline Vec2T GetRightTop() const { return Vec2T{ right_bottom.x, left_top.y }; } - inline Vec2T GetLeftBottom() const { return Vec2T{ GetLeft(), GetBottom() }; } + inline Vec2T GetLeftBottom() const { return Vec2T{ left_top.x, right_bottom.y }; } - inline value_type GetLeft() const { return origin.x; } + inline value_type GetLeft() const { return left_top.x; } - inline value_type GetTop() const { return origin.y; } + inline value_type GetTop() const { return left_top.y; } - inline value_type GetRight() const { return origin.x + size.x; } + inline value_type GetRight() const { return right_bottom.x; } - inline value_type GetBottom() const { return origin.y + size.y; } + inline value_type GetBottom() const { return right_bottom.y; } - inline bool IsEmpty() const { return origin.IsOrigin() && size.IsOrigin(); } + inline value_type GetWidth() const { return right_bottom.x - left_top.x; } + + inline value_type GetHeight() const { return right_bottom.y - left_top.y; } + + inline Vec2T GetSize() const { return Vec2T{ GetWidth(), GetHeight() }; } + + inline bool IsEmpty() const { return left_top.IsOrigin() && right_bottom.IsOrigin(); } inline bool ContainsPoint(const Vec2T& point) const { - return point.x >= origin.x && point.x <= (origin.x + size.x) && - point.y >= origin.y && point.y <= (origin.y + size.y); + return point.x >= left_top.x && point.x <= right_bottom.x && + point.y >= left_top.y && point.y <= right_bottom.y; } inline bool Intersects(const RectT& rect) const { - return !((origin.x + size.x) < rect.origin.x || - (rect.origin.x + rect.size.x) < origin.x || - (origin.y + size.y) < rect.origin.y || - (rect.origin.y + rect.size.y) < origin.y); + return !(right_bottom.x < rect.left_top.x || + rect.right_bottom.x < left_top.x || + right_bottom.y < rect.left_top.y || + rect.right_bottom.y < left_top.y); + } + + static inline RectT Infinite() + { + return RectT{ -math::constants::FLOAT_MAX, -math::constants::FLOAT_MAX, math::constants::FLOAT_MAX, math::constants::FLOAT_MAX }; } }; } } - -namespace kiwano -{ - using Rect = kiwano::math::RectT; -} diff --git a/src/kiwano/math/Vec2.hpp b/src/kiwano/math/Vec2.hpp index 75fd778c..2cfc622d 100644 --- a/src/kiwano/math/Vec2.hpp +++ b/src/kiwano/math/Vec2.hpp @@ -120,8 +120,3 @@ namespace kiwano }; } } - -namespace kiwano -{ - using Vec2 = kiwano::math::Vec2T; -} diff --git a/src/kiwano/math/constants.hpp b/src/kiwano/math/constants.hpp index edc8f10e..65603b61 100644 --- a/src/kiwano/math/constants.hpp +++ b/src/kiwano/math/constants.hpp @@ -26,13 +26,16 @@ namespace kiwano { namespace constants { - const auto PI_F = 3.141592653589793f; - const auto PI_F_2 = 1.570796326794896f; - const auto PI_F_X_2 = 6.283185307179586f; + constexpr auto PI_F = 3.141592653589793f; + constexpr auto PI_F_2 = 1.570796326794896f; + constexpr auto PI_F_X_2 = 6.283185307179586f; - const auto PI_D = 3.14159265358979323846; - const auto PI_D_2 = 1.57079632679489661923; - const auto PI_D_X_2 = 6.28318530717958647692; + constexpr auto PI_D = 3.14159265358979323846; + constexpr auto PI_D_2 = 1.57079632679489661923; + constexpr auto PI_D_X_2 = 6.28318530717958647692; + + constexpr auto FLOAT_MAX = 3.402823466e+38F; + constexpr auto FLOAT_MIN = 1.175494351e-38F; } } } diff --git a/src/kiwano/math/math.h b/src/kiwano/math/math.h index 46af02dd..720531cf 100644 --- a/src/kiwano/math/math.h +++ b/src/kiwano/math/math.h @@ -19,6 +19,7 @@ // THE SOFTWARE. #pragma once +#include "..\core\core.h" #include "constants.hpp" #include "ease.hpp" #include "scalar.hpp" @@ -28,6 +29,10 @@ namespace kiwano { + using Vec2 = kiwano::math::Vec2T; + using Rect = kiwano::math::RectT; + using Matrix3x2 = kiwano::math::Matrix3x2T; + using Point = Vec2; using Size = Vec2; } diff --git a/src/kiwano/math/scalar.hpp b/src/kiwano/math/scalar.hpp index ef62cb95..2320018b 100644 --- a/src/kiwano/math/scalar.hpp +++ b/src/kiwano/math/scalar.hpp @@ -22,61 +22,60 @@ #include "constants.hpp" #include - namespace kiwano { namespace math { - inline Int32 Abs(Int32 val) { return ::abs(val); } + inline Int32 Abs(Int32 val) { return ::abs(val); } - inline Float32 Abs(Float32 val) { return ::fabsf(val); } + inline Float32 Abs(Float32 val) { return ::fabsf(val); } - inline Float64 Abs(Float64 val) { return ::fabs(val); } + inline Float64 Abs(Float64 val) { return ::fabs(val); } - inline Float32 Sqrt(Float32 val) { return ::sqrtf(val); } + inline Float32 Sqrt(Float32 val) { return ::sqrtf(val); } - inline Float64 Sqrt(Float64 val) { return ::sqrt(val); } + inline Float64 Sqrt(Float64 val) { return ::sqrt(val); } - inline Float32 Pow(Float32 base, Float32 exponent) { return ::powf(base, exponent); } + inline Float32 Pow(Float32 base, Float32 exponent) { return ::powf(base, exponent); } - inline Float64 Pow(Float64 base, Float64 exponent) { return ::pow(base, exponent); } + inline Float64 Pow(Float64 base, Float64 exponent) { return ::pow(base, exponent); } - inline Int32 Sign(Int32 val) { return val < 0 ? -1 : 1; } + inline Int32 Sign(Int32 val) { return val < 0 ? -1 : 1; } - inline Float32 Sign(Float32 val) { return val < 0 ? -1.f : 1.f; } + inline Float32 Sign(Float32 val) { return val < 0 ? -1.f : 1.f; } - inline Float64 Sign(Float64 val) { return val < 0 ? -1.0 : 1.0; } + inline Float64 Sign(Float64 val) { return val < 0 ? -1.0 : 1.0; } - inline Float32 Sin(Float32 val) { return ::sinf(val * constants::PI_F / 180.f); } + inline Float32 Sin(Float32 val) { return ::sinf(val * constants::PI_F / 180.f); } - inline Float64 Sin(Float64 val) { return ::sin(val * constants::PI_D / 180.0); } + inline Float64 Sin(Float64 val) { return ::sin(val * constants::PI_D / 180.0); } - inline Float32 Cos(Float32 val) { return ::cosf(val * constants::PI_F / 180.f); } + inline Float32 Cos(Float32 val) { return ::cosf(val * constants::PI_F / 180.f); } - inline Float64 Cos(Float64 val) { return ::cos(val * constants::PI_D / 180.0); } + inline Float64 Cos(Float64 val) { return ::cos(val * constants::PI_D / 180.0); } - inline Float32 Tan(Float32 val) { return ::tanf(val * constants::PI_F / 180.f); } + inline Float32 Tan(Float32 val) { return ::tanf(val * constants::PI_F / 180.f); } - inline Float64 Tan(Float64 val) { return ::tan(val * constants::PI_D / 180.0); } + inline Float64 Tan(Float64 val) { return ::tan(val * constants::PI_D / 180.0); } - inline Float32 Asin(Float32 val) { return ::asinf(val) * 180.f / constants::PI_F; } + inline Float32 Asin(Float32 val) { return ::asinf(val) * 180.f / constants::PI_F; } - inline Float64 Asin(Float64 val) { return ::asin(val) * 180.f / constants::PI_F; } + inline Float64 Asin(Float64 val) { return ::asin(val) * 180.f / constants::PI_F; } - inline Float32 Acos(Float32 val) { return ::acosf(val) * 180.f / constants::PI_F; } + inline Float32 Acos(Float32 val) { return ::acosf(val) * 180.f / constants::PI_F; } - inline Float64 Acos(Float64 val) { return ::acos(val) * 180.f / constants::PI_F; } + inline Float64 Acos(Float64 val) { return ::acos(val) * 180.f / constants::PI_F; } - inline Float32 Atan(Float32 val) { return ::atanf(val) * 180.f / constants::PI_F; } + inline Float32 Atan(Float32 val) { return ::atanf(val) * 180.f / constants::PI_F; } - inline Float64 Atan(Float64 val) { return ::atan(val) * 180.f / constants::PI_F; } + inline Float64 Atan(Float64 val) { return ::atan(val) * 180.f / constants::PI_F; } - inline Float32 Ceil(Float32 val) { return ::ceil(val); } + inline Float32 Ceil(Float32 val) { return ::ceil(val); } - inline Float64 Ceil(Float64 val) { return ::ceil(val); } + inline Float64 Ceil(Float64 val) { return ::ceil(val); } - inline Float32 Floor(Float32 val) { return ::floor(val); } + inline Float32 Floor(Float32 val) { return ::floor(val); } - inline Float64 Floor(Float64 val) { return ::floor(val); } + inline Float64 Floor(Float64 val) { return ::floor(val); } } } diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index 0fe4bd50..fbb81e70 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -43,13 +43,14 @@ namespace kiwano Queue functions_to_perform_; } - Options::Options(String const& title, Int32 width, Int32 height, LPCWSTR icon, Color clear_color, bool vsync, bool fullscreen, bool debug) + Options::Options(String const& title, Int32 width, Int32 height, UInt32 icon, Color clear_color, bool vsync, bool resizable, bool fullscreen, bool debug) : title(title) , width(width) , height(height) , icon(icon) , clear_color(clear_color) , vsync(vsync) + , resizable(resizable) , fullscreen(fullscreen) , debug(debug) {} @@ -85,6 +86,7 @@ namespace kiwano options.width, options.height, options.icon, + options.resizable, options.fullscreen, Application::WndProc ); @@ -380,11 +382,11 @@ namespace kiwano { if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) { - KGE_LOG(L"Window minimized"); + // KGE_LOG(L"Window minimized"); } else { - KGE_LOG(L"Window resized"); + // KGE_LOG(L"Window resized"); Window::GetInstance()->UpdateWindowRect(); @@ -422,7 +424,7 @@ namespace kiwano case WM_SETTEXT: { - KGE_LOG(L"Window title changed"); + // KGE_LOG(L"Window title changed"); Event evt(Event::WindowTitleChanged); evt.win.title = reinterpret_cast(lparam); @@ -432,21 +434,27 @@ namespace kiwano case WM_SETICON: { - KGE_LOG(L"Window icon changed"); + // KGE_LOG(L"Window icon changed"); } break; case WM_DISPLAYCHANGE: { - KGE_LOG(L"The display resolution has changed"); + // KGE_LOG(L"The display resolution has changed"); ::InvalidateRect(hwnd, nullptr, FALSE); } break; + case WM_SETCURSOR: + { + Window::GetInstance()->UpdateCursor(); + } + break; + case WM_CLOSE: { - KGE_LOG(L"Window is closing"); + // KGE_LOG(L"Window is closing"); if (!app->OnClosing()) { diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h index d42cb0b0..97de5da3 100644 --- a/src/kiwano/platform/Application.h +++ b/src/kiwano/platform/Application.h @@ -30,23 +30,25 @@ namespace kiwano struct Options { String title; // ±êÌâ - Int32 width; // ¿í¶È - Int32 height; // ¸ß¶È - LPCWSTR icon; // ͼ±ê + Int32 width; // ¿í¶È + Int32 height; // ¸ß¶È + UInt32 icon; // ͼ±ê×ÊÔ´ ID Color clear_color; // ÇåÆÁÑÕÉ« bool vsync; // ´¹Ö±Í¬²½ + bool resizable; // ´°¿Ú´óС¿ÉÀ­Éì bool fullscreen; // È«ÆÁģʽ bool debug; // µ÷ÊÔģʽ Options( - String const& title = L"Kiwano Game", - Int32 width = 640, - Int32 height = 480, - LPCWSTR icon = nullptr, - Color clear_color = Color::Black, - bool vsync = true, - bool fullscreen = false, - bool debug = false + String const& title = L"Kiwano Game", + Int32 width = 640, + Int32 height = 480, + UInt32 icon = 0, + Color clear_color = Color::Black, + bool vsync = true, + bool resizable = false, + bool fullscreen = false, + bool debug = false ); }; diff --git a/src/kiwano/renderer/Font.h b/src/kiwano/renderer/Font.h index d9e01df1..c703c6d0 100644 --- a/src/kiwano/renderer/Font.h +++ b/src/kiwano/renderer/Font.h @@ -43,15 +43,15 @@ namespace kiwano public: String family; // ×ÖÌå×å Float32 size; // ×ֺŠ- UInt32 weight; // ´Öϸֵ + UInt32 weight; // ´Öϸֵ bool italic; // ÊÇ·ñбÌå FontCollection collection; // ×ÖÌ弯 public: Font( const String& family = L"", - Float32 size = 18, - UInt32 weight = FontWeight::Normal, + Float32 size = 18, + UInt32 weight = FontWeight::Normal, bool italic = false, FontCollection collection = FontCollection() ); diff --git a/src/kiwano/renderer/Geometry.cpp b/src/kiwano/renderer/Geometry.cpp index 0d211b87..5858ba1d 100644 --- a/src/kiwano/renderer/Geometry.cpp +++ b/src/kiwano/renderer/Geometry.cpp @@ -38,18 +38,23 @@ namespace kiwano { } + bool Geometry::IsValid() const + { + return geo_ != nullptr; + } + Rect Geometry::GetBoundingBox(Matrix3x2 const& transform) const { if (!geo_) return Rect{}; - D2D1_RECT_F rect; + Rect rect; // no matter it failed or not - geo_->GetBounds(DX::ConvertToMatrix3x2F(transform), &rect); - return Rect{ rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top }; + geo_->GetBounds(DX::ConvertToMatrix3x2F(transform), DX::ConvertToRectF(&rect)); + return rect; } - Float32 Geometry::GetLength() + Float32 Geometry::GetLength() const { Float32 length = 0.f; if (geo_) @@ -60,7 +65,7 @@ namespace kiwano return length; } - bool Geometry::ComputePointAtLength(Float32 length, Point& point, Vec2& tangent) + bool Geometry::ComputePointAtLength(Float32 length, Point& point, Vec2& tangent) const { if (geo_) { @@ -76,7 +81,7 @@ namespace kiwano return false; } - Geometry Geometry::CombineWith(Geometry input, CombineMode mode, Matrix3x2 const& input_matrix) + Geometry Geometry::CombineWith(Geometry input, CombineMode mode, Matrix3x2 const& input_matrix) const { if (geo_ && input.geo_) { @@ -129,7 +134,7 @@ namespace kiwano return Geometry(); } - Float32 Geometry::ComputeArea() + Float32 Geometry::ComputeArea() const { if (!geo_) return 0.f; @@ -140,7 +145,7 @@ namespace kiwano return area; } - bool Geometry::ContainsPoint(Point const& point) + bool Geometry::ContainsPoint(Point const& point, Matrix3x2 const& transform) const { if (!geo_) return false; @@ -149,7 +154,7 @@ namespace kiwano // no matter it failed or not geo_->FillContainsPoint( DX::ConvertToPoint2F(point), - D2D1::Matrix3x2F::Identity(), + DX::ConvertToMatrix3x2F(transform), &ret ); return !!ret; diff --git a/src/kiwano/renderer/Geometry.h b/src/kiwano/renderer/Geometry.h index 961d340a..86b2f290 100644 --- a/src/kiwano/renderer/Geometry.h +++ b/src/kiwano/renderer/Geometry.h @@ -42,6 +42,8 @@ namespace kiwano Geometry(ComPtr geo); + bool IsValid() const; + // »ñÈ¡ÍâÇаüΧºÐ Rect GetBoundingBox( Matrix3x2 const& transform = Matrix3x2() @@ -49,28 +51,29 @@ namespace kiwano // ÅжÏͼÐÎÊÇ·ñ°üº¬µã bool ContainsPoint( - Point const& point - ); + Point const& point, + Matrix3x2 const& transform = Matrix3x2() + ) const; // »ñȡͼÐÎÕ¹¿ª³ÉÒ»ÌõÖ±Ïߵij¤¶È - Float32 GetLength(); + Float32 GetLength() const; // ¼ÆËãÃæ»ý - Float32 ComputeArea(); + Float32 ComputeArea() const; // ¼ÆËãͼÐη¾¶ÉϵãµÄλÖúÍÇÐÏßÏòÁ¿ bool ComputePointAtLength( Float32 length, Point& point, Vec2& tangent - ); + ) const; // ×éºÏ¼¸ºÎÌå Geometry CombineWith( Geometry input, CombineMode mode, Matrix3x2 const& input_matrix = Matrix3x2() - ); + ) const; // ×éºÏ¶à¸ö¼¸ºÎÌå // ²ÎÊý modes ºÍ matrixs µÄÊýÁ¿Ó¦Îª 1 »ò geos µÄÊýÁ¿¼õÒ» @@ -114,7 +117,7 @@ namespace kiwano inline void SetGeometry(ComPtr geometry) { geo_ = geometry; } - inline operator bool() const { return static_cast(geo_); } + inline operator bool() const { return IsValid(); } protected: ComPtr geo_; diff --git a/src/kiwano/renderer/GifImage.cpp b/src/kiwano/renderer/GifImage.cpp index e4b6655e..bea8a029 100644 --- a/src/kiwano/renderer/GifImage.cpp +++ b/src/kiwano/renderer/GifImage.cpp @@ -191,7 +191,7 @@ namespace kiwano HRESULT GifImage::GetBackgroundColor(ComPtr metadata_reader) { - BYTE bg_index = 0; + UChar bg_index = 0; WICColor bgcolors[256]; UInt32 colors_copied = 0; ComPtr wic_palette; @@ -317,7 +317,7 @@ namespace kiwano hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); if (SUCCEEDED(hr)) { - frame_rect.origin.x = static_cast(prop_val.uiVal); + frame_rect.left_top.x = static_cast(prop_val.uiVal); } PropVariantClear(&prop_val); } @@ -331,7 +331,7 @@ namespace kiwano hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); if (SUCCEEDED(hr)) { - frame_rect.origin.y = static_cast(prop_val.uiVal); + frame_rect.left_top.y = static_cast(prop_val.uiVal); } PropVariantClear(&prop_val); } @@ -345,7 +345,7 @@ namespace kiwano hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); if (SUCCEEDED(hr)) { - frame_rect.size.x = static_cast(prop_val.uiVal); + frame_rect.right_bottom.x = frame_rect.left_top.x + static_cast(prop_val.uiVal); } PropVariantClear(&prop_val); } @@ -359,7 +359,7 @@ namespace kiwano hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); if (SUCCEEDED(hr)) { - frame_rect.size.y = static_cast(prop_val.uiVal); + frame_rect.right_bottom.y = frame_rect.left_top.y + static_cast(prop_val.uiVal); } PropVariantClear(&prop_val); } diff --git a/src/kiwano/renderer/LayerArea.cpp b/src/kiwano/renderer/LayerArea.cpp index a81ddddd..8841f3eb 100644 --- a/src/kiwano/renderer/LayerArea.cpp +++ b/src/kiwano/renderer/LayerArea.cpp @@ -24,6 +24,7 @@ namespace kiwano { LayerArea::LayerArea() : opacity_(1.f) + , area_(Rect::Infinite()) { } diff --git a/src/kiwano/renderer/LayerArea.h b/src/kiwano/renderer/LayerArea.h index 802e9960..b39bbfc4 100644 --- a/src/kiwano/renderer/LayerArea.h +++ b/src/kiwano/renderer/LayerArea.h @@ -33,27 +33,36 @@ namespace kiwano Size GetSize() const; - inline Rect const& GetAreaRect() const { return area_; } - - inline void SetAreaRect(Rect const& area) { area_ = area; } + inline Rect const& GetAreaRect() const { return area_; } inline Float32 GetOpacity() const { return opacity_; } - inline void SetOpacity(Float32 opacity) { opacity_ = opacity; } + inline Geometry const& GetMaskGeometry() const { return mask_; } - inline Geometry const& GetMaskGeometry() const { return mask_; } + inline Matrix3x2 const& GetMaskTransform() const { return mask_transform_; } - inline void SetMaskGeometry(Geometry const& mask) { mask_ = mask; } + // ÉèÖÃͼ²ãÇøÓò + inline void SetAreaRect(Rect const& area) { area_ = area; } + + // ÉèÖÃͼ²ã͸Ã÷¶È + inline void SetOpacity(Float32 opacity) { opacity_ = opacity; } + + // ÉèÖü¸ºÎÃɲã + inline void SetMaskGeometry(Geometry const& mask) { mask_ = mask; } + + // ÉèÖü¸ºÎÃɲã±ä»» + inline void SetMaskTransform(Matrix3x2 const& matrix) { mask_transform_ = matrix; } public: - inline ComPtr GetLayer() const { return layer_; } + inline ComPtr GetLayer() const { return layer_; } - inline void SetLayer(ComPtr layer) { layer_ = layer; } + inline void SetLayer(ComPtr layer) { layer_ = layer; } protected: Rect area_; Float32 opacity_; Geometry mask_; + Matrix3x2 mask_transform_; ComPtr layer_; }; } diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp index af0557cf..b516ea77 100644 --- a/src/kiwano/renderer/RenderTarget.cpp +++ b/src/kiwano/renderer/RenderTarget.cpp @@ -36,14 +36,14 @@ namespace kiwano status_.primitives = 0; } - HRESULT RenderTarget::InitDeviceResources(ComPtr rt, ComPtr dev_res) + HRESULT RenderTarget::CreateDeviceResources(ComPtr rt, ComPtr dev_res) { HRESULT hr = E_FAIL; if (rt && dev_res) { render_target_ = rt; - d2d_res_ = dev_res; + device_resources_ = dev_res; hr = S_OK; } @@ -58,20 +58,29 @@ namespace kiwano if (SUCCEEDED(hr)) { - solid_color_brush_.reset(); + default_brush_.reset(); hr = render_target_->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::White), D2D1::BrushProperties(), - &solid_color_brush_ + &default_brush_ ); } return hr; } + void RenderTarget::DiscardDeviceResources() + { + text_renderer_.reset(); + render_target_.reset(); + default_brush_.reset(); + current_brush_.reset(); + device_resources_.reset(); + } + bool RenderTarget::IsValid() const { - return render_target_ && d2d_res_; + return render_target_ && device_resources_; } void RenderTarget::BeginDraw() @@ -111,20 +120,20 @@ namespace kiwano ) const { HRESULT hr = S_OK; - if (!solid_color_brush_ || !render_target_) + if (!default_brush_ || !render_target_) { hr = E_UNEXPECTED; } if (SUCCEEDED(hr) && geometry.GetGeometry()) { - solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color)); + default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); render_target_->DrawGeometry( geometry.GetGeometry().get(), - solid_color_brush_.get(), + default_brush_.get(), stroke_width, - d2d_res_->GetStrokeStyle(stroke) + device_resources_->GetStrokeStyle(stroke) ); IncreasePrimitivesCount(); @@ -136,17 +145,17 @@ namespace kiwano void RenderTarget::FillGeometry(Geometry const& geometry, Color const& fill_color) const { HRESULT hr = S_OK; - if (!solid_color_brush_ || !render_target_) + if (!default_brush_ || !render_target_) { hr = E_UNEXPECTED; } if (SUCCEEDED(hr) && geometry.GetGeometry()) { - solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color)); + default_brush_->SetColor(DX::ConvertToColorF(fill_color)); render_target_->FillGeometry( geometry.GetGeometry().get(), - solid_color_brush_.get() + default_brush_.get() ); } @@ -156,21 +165,21 @@ namespace kiwano void RenderTarget::DrawLine(Point const& point1, Point const& point2, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const { HRESULT hr = S_OK; - if (!solid_color_brush_ || !render_target_) + if (!default_brush_ || !render_target_) { hr = E_UNEXPECTED; } if (SUCCEEDED(hr)) { - solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color)); + default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); render_target_->DrawLine( DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2), - solid_color_brush_.get(), + default_brush_.get(), stroke_width, - d2d_res_->GetStrokeStyle(stroke) + device_resources_->GetStrokeStyle(stroke) ); IncreasePrimitivesCount(); @@ -182,20 +191,20 @@ namespace kiwano void RenderTarget::DrawRectangle(Rect const& rect, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const { HRESULT hr = S_OK; - if (!solid_color_brush_ || !render_target_) + if (!default_brush_ || !render_target_) { hr = E_UNEXPECTED; } if (SUCCEEDED(hr)) { - solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color)); + default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); render_target_->DrawRectangle( DX::ConvertToRectF(rect), - solid_color_brush_.get(), + default_brush_.get(), stroke_width, - d2d_res_->GetStrokeStyle(stroke) + device_resources_->GetStrokeStyle(stroke) ); IncreasePrimitivesCount(); @@ -207,17 +216,17 @@ namespace kiwano void RenderTarget::FillRectangle(Rect const& rect, Color const& fill_color) const { HRESULT hr = S_OK; - if (!solid_color_brush_ || !render_target_) + if (!default_brush_ || !render_target_) { hr = E_UNEXPECTED; } if (SUCCEEDED(hr)) { - solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color)); + default_brush_->SetColor(DX::ConvertToColorF(fill_color)); render_target_->FillRectangle( DX::ConvertToRectF(rect), - solid_color_brush_.get() + default_brush_.get() ); } @@ -227,14 +236,14 @@ namespace kiwano void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const { HRESULT hr = S_OK; - if (!solid_color_brush_ || !render_target_) + if (!default_brush_ || !render_target_) { hr = E_UNEXPECTED; } if (SUCCEEDED(hr)) { - solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color)); + default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); render_target_->DrawRoundedRectangle( D2D1::RoundedRect( @@ -242,9 +251,9 @@ namespace kiwano radius.x, radius.y ), - solid_color_brush_.get(), + default_brush_.get(), stroke_width, - d2d_res_->GetStrokeStyle(stroke) + device_resources_->GetStrokeStyle(stroke) ); IncreasePrimitivesCount(); @@ -256,21 +265,21 @@ namespace kiwano void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& fill_color) const { HRESULT hr = S_OK; - if (!solid_color_brush_ || !render_target_) + if (!default_brush_ || !render_target_) { hr = E_UNEXPECTED; } if (SUCCEEDED(hr)) { - solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color)); + default_brush_->SetColor(DX::ConvertToColorF(fill_color)); render_target_->FillRoundedRectangle( D2D1::RoundedRect( DX::ConvertToRectF(rect), radius.x, radius.y ), - solid_color_brush_.get() + default_brush_.get() ); } @@ -280,14 +289,14 @@ namespace kiwano void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const { HRESULT hr = S_OK; - if (!solid_color_brush_ || !render_target_) + if (!default_brush_ || !render_target_) { hr = E_UNEXPECTED; } if (SUCCEEDED(hr)) { - solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color)); + default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); render_target_->DrawEllipse( D2D1::Ellipse( @@ -295,9 +304,9 @@ namespace kiwano radius.x, radius.y ), - solid_color_brush_.get(), + default_brush_.get(), stroke_width, - d2d_res_->GetStrokeStyle(stroke) + device_resources_->GetStrokeStyle(stroke) ); IncreasePrimitivesCount(); @@ -309,21 +318,21 @@ namespace kiwano void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius, Color const& fill_color) const { HRESULT hr = S_OK; - if (!solid_color_brush_ || !render_target_) + if (!default_brush_ || !render_target_) { hr = E_UNEXPECTED; } if (SUCCEEDED(hr)) { - solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color)); + default_brush_->SetColor(DX::ConvertToColorF(fill_color)); render_target_->FillEllipse( D2D1::Ellipse( DX::ConvertToPoint2F(center), radius.x, radius.y ), - solid_color_brush_.get() + default_brush_.get() ); } @@ -375,7 +384,7 @@ namespace kiwano layout.GetTextStyle().outline, DX::ConvertToColorF(layout.GetTextStyle().outline_color), layout.GetTextStyle().outline_width, - d2d_res_->GetStrokeStyle(layout.GetTextStyle().outline_stroke) + device_resources_->GetStrokeStyle(layout.GetTextStyle().outline_stroke) ); } @@ -447,14 +456,19 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::PushLayer(LayerArea const& layer) + void RenderTarget::PushLayer(LayerArea& layer) { HRESULT hr = S_OK; - if (!render_target_ || !solid_color_brush_) + if (!render_target_ || !default_brush_) { hr = E_UNEXPECTED; } + if (!layer.IsValid()) + { + CreateLayer(layer); + } + if (SUCCEEDED(hr) && layer.IsValid()) { render_target_->PushLayer( @@ -462,7 +476,7 @@ namespace kiwano DX::ConvertToRectF(layer.GetAreaRect()), layer.GetMaskGeometry().GetGeometry().get(), antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED, - D2D1::Matrix3x2F::Identity(), + DX::ConvertToMatrix3x2F(layer.GetMaskTransform()), layer.GetOpacity(), nullptr, D2D1_LAYER_OPTIONS_NONE @@ -521,6 +535,11 @@ namespace kiwano return opacity_; } + Matrix3x2 RenderTarget::GetGlobalTransform() const + { + return global_matrix_; + } + void RenderTarget::SetTransform(const Matrix3x2& matrix) { HRESULT hr = S_OK; @@ -531,16 +550,22 @@ namespace kiwano if (SUCCEEDED(hr)) { - render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); + Matrix3x2 result = matrix * global_matrix_; + render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result)); } ThrowIfFailed(hr); } + void RenderTarget::SetGlobalTransform(const Matrix3x2& matrix) + { + global_matrix_ = matrix; + } + void RenderTarget::SetOpacity(Float32 opacity) { HRESULT hr = S_OK; - if (!solid_color_brush_) + if (!default_brush_) { hr = E_UNEXPECTED; } @@ -550,7 +575,7 @@ namespace kiwano if (opacity_ != opacity) { opacity_ = opacity; - solid_color_brush_->SetOpacity(opacity); + default_brush_->SetOpacity(opacity); } } @@ -611,6 +636,13 @@ namespace kiwano ThrowIfFailed(hr); } + bool RenderTarget::CheckVisibility(Rect const& bounds, Matrix3x2 const& transform) + { + return Rect{ Point{}, reinterpret_cast(render_target_->GetSize()) }.Intersects( + Matrix3x2(transform * global_matrix_).Transform(bounds) + ); + } + void RenderTarget::SetCollectingStatus(bool collecting) { collecting_status_ = collecting; @@ -633,28 +665,29 @@ namespace kiwano { } - void ImageRenderTarget::GetOutput(Image& output) const + Image ImageRenderTarget::GetOutput() const { HRESULT hr = E_FAIL; - ComPtr bitmap_rt; if (render_target_) { + ComPtr bitmap_rt; hr = render_target_->QueryInterface(&bitmap_rt); - } - ComPtr bitmap; - if (SUCCEEDED(hr)) - { - hr = bitmap_rt->GetBitmap(&bitmap); - } + if (SUCCEEDED(hr)) + { + ComPtr bitmap; + hr = bitmap_rt->GetBitmap(&bitmap); - if (SUCCEEDED(hr)) - { - output.SetBitmap(bitmap); + if (SUCCEEDED(hr)) + { + return Image(bitmap); + } + } } ThrowIfFailed(hr); + return Image(); } } diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h index 1582504c..f8c63c5e 100644 --- a/src/kiwano/renderer/RenderTarget.h +++ b/src/kiwano/renderer/RenderTarget.h @@ -33,6 +33,8 @@ namespace kiwano : public noncopyable { public: + bool IsValid() const; + void BeginDraw(); void EndDraw(); @@ -125,7 +127,7 @@ namespace kiwano void PopClipRect(); void PushLayer( - LayerArea const& layer + LayerArea& layer ); void PopLayer(); @@ -138,6 +140,8 @@ namespace kiwano Float32 GetOpacity() const; + Matrix3x2 GetGlobalTransform() const; + void SetOpacity( Float32 opacity ); @@ -146,6 +150,10 @@ namespace kiwano const Matrix3x2& matrix ); + void SetGlobalTransform( + const Matrix3x2& matrix + ); + // ÉèÖÿ¹¾â³Ýģʽ void SetAntialiasMode( bool enabled @@ -156,6 +164,11 @@ namespace kiwano TextAntialias mode ); + bool CheckVisibility( + Rect const& bounds, + Matrix3x2 const& transform + ); + public: struct Status { @@ -170,17 +183,19 @@ namespace kiwano inline Status const& GetStatus() const { return status_; } - inline ComPtr GetRenderTarget() const { return render_target_; } + inline ComPtr GetRenderTarget() const { KGE_ASSERT(render_target_); return render_target_; } + + inline ComPtr GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_; } public: RenderTarget(); - HRESULT InitDeviceResources( + HRESULT CreateDeviceResources( ComPtr rt, ComPtr dev_res ); - bool IsValid() const; + void DiscardDeviceResources(); protected: Float32 opacity_; @@ -188,10 +203,12 @@ namespace kiwano mutable bool collecting_status_; mutable Status status_; TextAntialias text_antialias_; - ComPtr render_target_; ComPtr text_renderer_; - ComPtr solid_color_brush_; - ComPtr d2d_res_; + ComPtr render_target_; + ComPtr default_brush_; + ComPtr current_brush_; + ComPtr device_resources_; + Matrix3x2 global_matrix_; }; @@ -202,6 +219,6 @@ namespace kiwano public: ImageRenderTarget(); - void GetOutput(Image& output) const; + Image GetOutput() const; }; } diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index d63623f7..ccae9a87 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -29,6 +29,7 @@ namespace kiwano : hwnd_(nullptr) , vsync_(true) , clear_color_(Color::Black) + , resolution_mode_(ResolutionMode::Fixed) { } @@ -41,7 +42,7 @@ namespace kiwano KGE_LOG(L"Creating device resources"); hwnd_ = Window::GetInstance()->GetHandle(); - output_size_ = Window::GetInstance()->GetSize(); + resolution_ = output_size_ = Window::GetInstance()->GetSize(); d2d_res_ = nullptr; d3d_res_ = nullptr; @@ -126,6 +127,8 @@ namespace kiwano { KGE_LOG(L"Destroying device resources"); + RenderTarget::DiscardDeviceResources(); + d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get()); res_font_file_loader_.reset(); @@ -133,7 +136,6 @@ namespace kiwano res_font_collection_loader_.reset(); drawing_state_block_.reset(); - solid_color_brush_.reset(); d2d_res_.reset(); d3d_res_.reset(); } @@ -158,6 +160,12 @@ namespace kiwano hr = d3d_res_->ClearRenderTarget(clear_color_); } + if (SUCCEEDED(hr)) + { + SetTransform(Matrix3x2{}); + PushClipRect(Rect{ Point{}, resolution_ }); + } + ThrowIfFailed(hr); } @@ -170,8 +178,11 @@ namespace kiwano hr = E_UNEXPECTED; } + if (SUCCEEDED(hr)) { + PopClipRect(); + EndDraw(); render_target_->RestoreDrawingState(drawing_state_block_.get()); @@ -200,7 +211,7 @@ namespace kiwano UInt32 width = LOWORD(lparam); UInt32 height = HIWORD(lparam); - Resize(width, height); + ResizeTarget(width, height); break; } } @@ -208,7 +219,9 @@ namespace kiwano HRESULT Renderer::CreateDeviceResources() { - HRESULT hr = InitDeviceResources( + KGE_ASSERT(d2d_res_); + + HRESULT hr = RenderTarget::CreateDeviceResources( d2d_res_->GetDeviceContext(), d2d_res_ ); @@ -656,7 +669,7 @@ namespace kiwano if (SUCCEEDED(hr)) { - hr = render_target.InitDeviceResources(output, d2d_res_); + hr = render_target.CreateDeviceResources(output, d2d_res_); } ThrowIfFailed(hr); @@ -667,7 +680,30 @@ namespace kiwano vsync_ = enabled; } - void Renderer::Resize(UInt32 width, UInt32 height) + void Renderer::SetResolution(Size const& resolution) + { + if (resolution_ != resolution) + { + resolution_ = resolution; + UpdateResolution(); + } + } + + void Renderer::SetResolutionMode(ResolutionMode mode) + { + if (resolution_mode_ != mode) + { + resolution_mode_ = mode; + UpdateResolution(); + } + } + + void Renderer::SetClearColor(const Color& color) + { + clear_color_ = color; + } + + void Renderer::ResizeTarget(UInt32 width, UInt32 height) { HRESULT hr = S_OK; if (!d3d_res_) @@ -682,19 +718,58 @@ namespace kiwano hr = d3d_res_->SetLogicalSize(output_size_); } + if (SUCCEEDED(hr)) + { + UpdateResolution(); + } + ThrowIfFailed(hr); } - void Renderer::SetClearColor(const Color& color) + void Renderer::UpdateResolution() { - clear_color_ = color; - } + switch (resolution_mode_) + { + case ResolutionMode::Fixed: + { + SetGlobalTransform(Matrix3x2{}); + break; + } - bool Renderer::CheckVisibility(Size const& content_size, Matrix3x2 const& transform) - { - return Rect{ Point{}, output_size_ }.Intersects( - transform.Transform(Rect{ Point{}, content_size }) - ); + case ResolutionMode::Center: + { + Float32 left = math::Ceil((output_size_.x - resolution_.x) / 2); + Float32 top = math::Ceil((output_size_.y - resolution_.y) / 2); + SetGlobalTransform(Matrix3x2::Translation(Vec2{ left, top })); + break; + } + + case ResolutionMode::Stretch: + { + Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100; + Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100; + SetGlobalTransform(Matrix3x2::Scaling(Vec2{ scalex, scaley })); + break; + } + + case ResolutionMode::Adaptive: + { + Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100; + Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100; + if (scalex > scaley) + { + Float32 left = math::Ceil((output_size_.x - resolution_.x * scaley) / 2); + SetGlobalTransform(Matrix3x2::SRT(Vec2{ left, 0 }, Vec2{ scaley, scaley }, 0)); + } + else + { + Float32 top = math::Ceil((output_size_.y - resolution_.y * scalex) / 2); + SetGlobalTransform(Matrix3x2::SRT(Vec2{ 0, top }, Vec2{ scalex, scalex }, 0)); + + } + break; + } + } } } diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index b28fcab5..7e59ff9a 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -131,14 +131,12 @@ namespace kiwano ImageRenderTarget& render_target ); - void Resize( - UInt32 width, - UInt32 height + void SetResolution( + Size const& resolution ); - bool CheckVisibility( - Size const& content_size, - Matrix3x2 const& transform + void SetResolutionMode( + ResolutionMode mode ); public: @@ -157,14 +155,14 @@ namespace kiwano inline Size const& GetOutputSize() const { return output_size_; } + inline Size const& GetResolution() const { return resolution_; } + + inline Color const& GetClearColor() const { return clear_color_; } + inline ID2DDeviceResources* GetD2DDeviceResources() const { KGE_ASSERT(d2d_res_); return d2d_res_.get(); } inline ID3DDeviceResources* GetD3DDeviceResources() const { KGE_ASSERT(d3d_res_); return d3d_res_.get(); } - inline ITextRenderer* GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_.get(); } - - inline ID2D1SolidColorBrush* GetSolidColorBrush() const { KGE_ASSERT(solid_color_brush_); return solid_color_brush_.get(); } - private: Renderer(); @@ -174,11 +172,17 @@ namespace kiwano HRESULT HandleDeviceLost(); + void ResizeTarget(UInt32 width, UInt32 height); + + void UpdateResolution(); + private: - bool vsync_; - HWND hwnd_; - Size output_size_; - Color clear_color_; + bool vsync_; + HWND hwnd_; + Color clear_color_; + Size output_size_; + Size resolution_; + ResolutionMode resolution_mode_; ComPtr d2d_res_; ComPtr d3d_res_; diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.h b/src/kiwano/renderer/win32/D2DDeviceResources.h index 52598120..c3c73a24 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.h +++ b/src/kiwano/renderer/win32/D2DDeviceResources.h @@ -101,16 +101,31 @@ namespace kiwano } // - // SizeF + // RectF // - inline D2D1_RECT_F ConvertToRectF(Rect const& rect) + inline D2D1_RECT_F const& ConvertToRectF(Rect const& rect) { - return D2D1_RECT_F{ rect.origin.x, rect.origin.y, rect.origin.x + rect.size.x, rect.origin.y + rect.size.y }; + return reinterpret_cast(rect); + } + + inline D2D1_RECT_F& ConvertToRectF(Rect& rect) + { + return reinterpret_cast(rect); + } + + inline const D2D1_RECT_F* ConvertToRectF(const Rect* rect) + { + return reinterpret_cast(rect); + } + + inline D2D1_RECT_F* ConvertToRectF(Rect* rect) + { + return reinterpret_cast(rect); } // - // SizeF + // ColorF // inline D2D1_COLOR_F const& ConvertToColorF(Color const& color) { @@ -133,7 +148,7 @@ namespace kiwano } // - // SizeF + // MatrixF // inline D2D1_MATRIX_3X2_F const& ConvertToMatrix3x2F(Matrix3x2 const& matrix) diff --git a/src/kiwano/renderer/win32/FontCollectionLoader.cpp b/src/kiwano/renderer/win32/FontCollectionLoader.cpp index d896e7ac..94c41e4d 100644 --- a/src/kiwano/renderer/win32/FontCollectionLoader.cpp +++ b/src/kiwano/renderer/win32/FontCollectionLoader.cpp @@ -948,7 +948,7 @@ namespace kiwano if (fileOffset <= resourceSize_ && fragmentSize <= resourceSize_ - fileOffset) { - *fragmentStart = static_cast(resourcePtr_) + static_cast(fileOffset); + *fragmentStart = static_cast(resourcePtr_) + static_cast(fileOffset); *fragmentContext = NULL; return S_OK; } diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index b82d4ab2..43dd40ff 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -119,7 +119,7 @@ namespace kiwano { ifs.open(file_path.c_str()); - std::wstringstream ss; + StringStream ss; ss << ifs.rdbuf(); if (tinyxml2::XML_SUCCESS != doc.Parse(ss.str().c_str())) @@ -248,7 +248,7 @@ namespace kiwano FramePtr ptr = new (std::nothrow) Frame(raw->GetImage()); if (ptr) { - ptr->SetCropRect(Rect{ j * width, i * height, width, height }); + ptr->SetCropRect(Rect{ j * width, i * height, (j + 1) * width, (i + 1) * height }); image_arr.push_back(ptr); } }