diff --git a/.clang-format b/.clang-format
new file mode 100644
index 00000000..f3202c42
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,108 @@
+# Clang-format version v9.0.0
+---
+Language: Cpp
+BasedOnStyle: Google
+
+ColumnLimit: 120
+
+##
+## Indent Style
+##
+
+IndentWidth: 4
+AccessModifierOffset: -4
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+TabWidth: 4
+UseTab: Never
+IndentCaseLabels: false
+NamespaceIndentation: None
+
+##
+## Align Style
+##
+
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: true
+AlignConsecutiveDeclarations: true
+AlignEscapedNewlinesLeft: true
+AlignOperands: true
+AlignTrailingComments: true
+PointerAlignment: Left
+
+##
+## SingleLine Style
+##
+
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Empty
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BreakBeforeBraces: Allman
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: true
+BreakBeforeBinaryOperators: NonAssignment
+BreakBeforeTernaryOperators: true
+CommentPragmas: "^ IWYU pragma:"
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+
+##
+## Others
+##
+
+BreakConstructorInitializers: BeforeComma
+BreakInheritanceList: BeforeComma
+ReflowComments: true
+SortIncludes: true
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros: [foreach, Q_FOREACH, BOOST_FOREACH]
+IncludeCategories:
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ Priority: 2
+ - Regex: '^(<|"(gtest|isl|json)/)'
+ Priority: 3
+ - Regex: ".*"
+ Priority: 1
+IndentWrappedFunctionNames: false
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ""
+MacroBlockEnd: ""
+MaxEmptyLinesToKeep: 1
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 2
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
diff --git a/.editorconfig b/.editorconfig
index 433e5b04..552be4bf 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -14,10 +14,10 @@ insert_final_newline = true
charset = gb2312
# 4 space indentation
-indent_style = tab
+indent_style = space
indent_size = 4
# Matches the exact files
[*.{json,xml}]
indent_style = space
-indent_size = 2
\ No newline at end of file
+indent_size = 2
diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj
index e829f7cc..a9cdfe46 100644
--- a/projects/kiwano/kiwano.vcxproj
+++ b/projects/kiwano/kiwano.vcxproj
@@ -65,13 +65,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -136,11 +136,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters
index dc22d2b5..4281032d 100644
--- a/projects/kiwano/kiwano.vcxproj.filters
+++ b/projects/kiwano/kiwano.vcxproj.filters
@@ -28,7 +28,7 @@
{adb44ca9-674a-4b77-993f-d65193d8ab06}
-
+
{fd281702-0006-46d2-8fd1-28c502464164}
@@ -222,27 +222,6 @@
core
-
- render\dx
-
-
- render\dx
-
-
- render\dx
-
-
- render\dx
-
-
- render\dx
-
-
- render\dx
-
-
- render\dx
-
render
@@ -285,6 +264,27 @@
render
+
+ render\DirectX
+
+
+ render\DirectX
+
+
+ render\DirectX
+
+
+ render\DirectX
+
+
+ render\DirectX
+
+
+ render\DirectX
+
+
+ render\DirectX
+
@@ -431,21 +431,6 @@
core
-
- render\dx
-
-
- render\dx
-
-
- render\dx
-
-
- render\dx
-
-
- render\dx
-
render
@@ -485,5 +470,20 @@
render
+
+ render\DirectX
+
+
+ render\DirectX
+
+
+ render\DirectX
+
+
+ render\DirectX
+
+
+ render\DirectX
+
\ No newline at end of file
diff --git a/scripts/clang-format-all b/scripts/clang-format-all
new file mode 100644
index 00000000..645c3ceb
--- /dev/null
+++ b/scripts/clang-format-all
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# clang-format-all: a tool to run clang-format on an entire project
+# Copyright (C) 2016 Evan Klitzke
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+function usage {
+ echo "Usage: $0 DIR..."
+ exit 1
+}
+
+if [ $# -eq 0 ]; then
+ usage
+fi
+
+# Variable that will hold the name of the clang-format command
+FMT=""
+
+# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent
+# that the version number be part of the command. We prefer clang-format if
+# that's present, otherwise we work backwards from highest version to lowest
+# version.
+for clangfmt in clang-format{,-{4,3}.{9,8,7,6,5,4,3,2,1,0}}; do
+ if which "$clangfmt" &>/dev/null; then
+ FMT="$clangfmt"
+ break
+ fi
+done
+
+# Check if we found a working clang-format
+if [ -z "$FMT" ]; then
+ echo "failed to find clang-format"
+ exit 1
+fi
+
+# Check all of the arguments first to make sure they're all directories
+for dir in "$@"; do
+ if [ ! -d "${dir}" ]; then
+ echo "${dir} is not a directory"
+ usage
+ fi
+done
+
+# Find a dominating file, starting from a given directory and going up.
+find-dominating-file() {
+ if [ -r "$1"/"$2" ]; then
+ return 0
+ fi
+ if [ "$1" = "/" ]; then
+ return 1
+ fi
+ find-dominating-file "$(realpath "$1"/..)" "$2"
+ return $?
+}
+
+# Run clang-format -i on all of the things
+for dir in "$@"; do
+ pushd "${dir}" &>/dev/null
+ if ! find-dominating-file . .clang-format; then
+ echo "Failed to find dominating .clang-format starting at $PWD"
+ continue
+ fi
+ find . \
+ \( -name '*.c' \
+ -o -name '*.cc' \
+ -o -name '*.cpp' \
+ -o -name '*.h' \
+ -o -name '*.hh' \
+ -o -name '*.hpp' \) \
+ -exec "${FMT}" -i '{}' \;
+ popd &>/dev/null
+done
diff --git a/src/kiwano-audio/AudioEngine.cpp b/src/kiwano-audio/AudioEngine.cpp
index d060e31f..8e238f66 100644
--- a/src/kiwano-audio/AudioEngine.cpp
+++ b/src/kiwano-audio/AudioEngine.cpp
@@ -1,15 +1,15 @@
// 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
@@ -18,108 +18,106 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include // win32::ThrowIfFailed
-#include
-#include
#include
+#include
+#include
+#include // win32::ThrowIfFailed
namespace kiwano
{
- namespace audio
- {
- AudioEngine::AudioEngine()
- : x_audio2_(nullptr)
- , mastering_voice_(nullptr)
- {
- }
-
- AudioEngine::~AudioEngine()
- {
- }
-
- void AudioEngine::SetupComponent()
- {
- KGE_SYS_LOG(L"Creating audio resources");
-
- HRESULT hr = dlls::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL);
-
- if (SUCCEEDED(hr))
- {
- hr = dlls::XAudio2::Get().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = x_audio2_->CreateMasteringVoice(&mastering_voice_);
- }
-
- win32::ThrowIfFailed(hr);
- }
-
- void AudioEngine::DestroyComponent()
- {
- KGE_SYS_LOG(L"Destroying audio resources");
-
- if (mastering_voice_)
- {
- mastering_voice_->DestroyVoice();
- mastering_voice_ = nullptr;
- }
-
- if (x_audio2_)
- {
- x_audio2_->Release();
- x_audio2_ = nullptr;
- }
-
- dlls::MediaFoundation::Get().MFShutdown();
- }
-
- bool AudioEngine::CreateSound(Sound& sound, const Transcoder::Buffer& buffer)
- {
- KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
-
- HRESULT hr = S_OK;
-
- if (buffer.format == nullptr)
- hr = E_INVALIDARG;
-
- if (SUCCEEDED(hr))
- {
- IXAudio2SourceVoice* voice = nullptr;
- hr = x_audio2_->CreateSourceVoice(&voice, buffer.format, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
-
- if (SUCCEEDED(hr))
- {
- IXAudio2SourceVoice* old = sound.GetXAudio2Voice();
- if (old)
- {
- old->DestroyVoice();
- old = nullptr;
- }
-
- sound.SetXAudio2Voice(voice);
- }
- }
-
- win32::WarnIfFailed(hr);
- return SUCCEEDED(hr);
- }
-
- void AudioEngine::Open()
- {
- KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
-
- if (x_audio2_)
- x_audio2_->StartEngine();
- }
-
- void AudioEngine::Close()
- {
- KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
-
- if (x_audio2_)
- x_audio2_->StopEngine();
- }
- }
+namespace audio
+{
+AudioEngine::AudioEngine()
+ : x_audio2_(nullptr)
+ , mastering_voice_(nullptr)
+{
}
+
+AudioEngine::~AudioEngine() {}
+
+void AudioEngine::SetupComponent()
+{
+ KGE_SYS_LOG(L"Creating audio resources");
+
+ HRESULT hr = dlls::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = dlls::XAudio2::Get().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = x_audio2_->CreateMasteringVoice(&mastering_voice_);
+ }
+
+ win32::ThrowIfFailed(hr);
+}
+
+void AudioEngine::DestroyComponent()
+{
+ KGE_SYS_LOG(L"Destroying audio resources");
+
+ if (mastering_voice_)
+ {
+ mastering_voice_->DestroyVoice();
+ mastering_voice_ = nullptr;
+ }
+
+ if (x_audio2_)
+ {
+ x_audio2_->Release();
+ x_audio2_ = nullptr;
+ }
+
+ dlls::MediaFoundation::Get().MFShutdown();
+}
+
+bool AudioEngine::CreateSound(Sound& sound, const Transcoder::Buffer& buffer)
+{
+ KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
+
+ HRESULT hr = S_OK;
+
+ if (buffer.format == nullptr)
+ hr = E_INVALIDARG;
+
+ if (SUCCEEDED(hr))
+ {
+ IXAudio2SourceVoice* voice = nullptr;
+ hr = x_audio2_->CreateSourceVoice(&voice, buffer.format, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
+
+ if (SUCCEEDED(hr))
+ {
+ IXAudio2SourceVoice* old = sound.GetXAudio2Voice();
+ if (old)
+ {
+ old->DestroyVoice();
+ old = nullptr;
+ }
+
+ sound.SetXAudio2Voice(voice);
+ }
+ }
+
+ win32::WarnIfFailed(hr);
+ return SUCCEEDED(hr);
+}
+
+void AudioEngine::Open()
+{
+ KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
+
+ if (x_audio2_)
+ x_audio2_->StartEngine();
+}
+
+void AudioEngine::Close()
+{
+ KGE_ASSERT(x_audio2_ && "AudioEngine hasn't been initialized!");
+
+ if (x_audio2_)
+ x_audio2_->StopEngine();
+}
+} // namespace audio
+} // namespace kiwano
diff --git a/src/kiwano-audio/AudioEngine.h b/src/kiwano-audio/AudioEngine.h
index 7a39c09a..fd877360 100644
--- a/src/kiwano-audio/AudioEngine.h
+++ b/src/kiwano-audio/AudioEngine.h
@@ -1,15 +1,15 @@
// 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
@@ -19,64 +19,66 @@
// THE SOFTWARE.
#pragma once
+#include
+#include
#include
#include
-#include
-#include
#include
namespace kiwano
{
- namespace audio
- {
- /**
- * \~chinese
- * \defgroup Audio 音频引擎
- */
+namespace audio
+{
- /**
- * \addtogroup Audio
- * @{
- */
+/**
+ * \~chinese
+ * \defgroup Audio 音频引擎
+ */
- /**
- * \~chinese
- * @brief 音频引擎
- */
- class KGE_API AudioEngine
- : public Singleton
- , public ComponentBase
- {
- friend Singleton;
+/**
+ * \addtogroup Audio
+ * @{
+ */
- public:
- /// \~chinese
- /// @brief 开启音频设备
- void Open();
+/**
+ * \~chinese
+ * @brief 音频引擎
+ */
+class KGE_API AudioEngine
+ : public Singleton
+ , public ComponentBase
+{
+ friend Singleton;
- /// \~chinese
- /// @brief 关闭音频设备
- void Close();
+public:
+ /// \~chinese
+ /// @brief 开启音频设备
+ void Open();
- /// \~chinese
- /// @brief 从解码器数据缓冲中创建音频对象
- bool CreateSound(Sound& sound, const Transcoder::Buffer& buffer);
+ /// \~chinese
+ /// @brief 关闭音频设备
+ void Close();
- public:
- void SetupComponent() override;
+ /// \~chinese
+ /// @brief 从解码器数据缓冲中创建音频对象
+ bool CreateSound(Sound& sound, const Transcoder::Buffer& buffer);
- void DestroyComponent() override;
+public:
+ void SetupComponent() override;
- private:
- AudioEngine();
+ void DestroyComponent() override;
- ~AudioEngine();
+private:
+ AudioEngine();
- private:
- IXAudio2* x_audio2_;
- IXAudio2MasteringVoice* mastering_voice_;
- };
+ ~AudioEngine();
- /** @} */
- }
-}
+private:
+ IXAudio2* x_audio2_;
+ IXAudio2MasteringVoice* mastering_voice_;
+};
+
+/** @} */
+
+} // namespace audio
+} // namespace kiwano
diff --git a/src/kiwano-audio/Sound.cpp b/src/kiwano-audio/Sound.cpp
index 88e6d056..39158d6b 100644
--- a/src/kiwano-audio/Sound.cpp
+++ b/src/kiwano-audio/Sound.cpp
@@ -1,15 +1,15 @@
// 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
@@ -18,210 +18,210 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#include
+#include
#include
#include
-#include
-#include
namespace kiwano
{
- namespace audio
- {
+namespace audio
+{
- Sound::Sound()
- : opened_(false)
- , playing_(false)
- , voice_(nullptr)
- {
- }
-
- Sound::~Sound()
- {
- Close();
- }
-
- bool Sound::Load(String const& file_path)
- {
- if (!FileSystem::Instance().IsFileExists(file_path))
- {
- KGE_WARN(L"Media file '%s' not found", file_path.c_str());
- return false;
- }
-
- if (opened_)
- {
- Close();
- }
-
- String full_path = FileSystem::Instance().GetFullPathForFile(file_path);
-
- HRESULT hr = transcoder_.LoadMediaFile(full_path);
- if (FAILED(hr))
- {
- KGE_ERROR(L"Load media file failed with HRESULT of %08X", hr);
- return false;
- }
-
- if (!AudioEngine::Instance().CreateSound(*this, transcoder_.GetBuffer()))
- {
- Close();
- return false;
- }
-
- opened_ = true;
- return true;
- }
-
- bool Sound::Load(Resource const& res)
- {
- if (opened_)
- {
- Close();
- }
-
- HRESULT hr = transcoder_.LoadMediaResource(res);
- if (FAILED(hr))
- {
- KGE_ERROR(L"Load media resource failed with HRESULT of %08X", hr);
- return false;
- }
-
- if (!AudioEngine::Instance().CreateSound(*this, transcoder_.GetBuffer()))
- {
- Close();
- return false;
- }
-
- opened_ = true;
- return true;
- }
-
- bool Sound::IsValid() const
- {
- return voice_ != nullptr;
- }
-
- void Sound::Play(int loop_count)
- {
- if (!opened_)
- {
- KGE_ERROR(L"Sound must be opened first!");
- return;
- }
-
- KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
-
- // if sound stream is not empty, stop() will clear it
- XAUDIO2_VOICE_STATE state;
- voice_->GetState(&state);
- if (state.BuffersQueued)
- Stop();
-
- // 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_buffer.data;
- buffer.Flags = XAUDIO2_END_OF_STREAM;
- buffer.AudioBytes = wave_buffer.size;
- buffer.LoopCount = static_cast(loop_count);
-
- HRESULT hr = voice_->SubmitSourceBuffer(&buffer);
- if (SUCCEEDED(hr))
- {
- hr = voice_->Start();
- }
-
- if (FAILED(hr))
- {
- KGE_ERROR(L"Submitting source buffer failed with HRESULT of %08X", hr);
- }
-
- playing_ = SUCCEEDED(hr);
- }
-
- void Sound::Pause()
- {
- KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
-
- if (SUCCEEDED(voice_->Stop()))
- playing_ = false;
- }
-
- void Sound::Resume()
- {
- KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
-
- if (SUCCEEDED(voice_->Start()))
- playing_ = true;
- }
-
- void Sound::Stop()
- {
- KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
-
- HRESULT hr = voice_->Stop();
-
- if (SUCCEEDED(hr))
- hr = voice_->ExitLoop();
-
- if (SUCCEEDED(hr))
- hr = voice_->FlushSourceBuffers();
-
- if (SUCCEEDED(hr))
- playing_ = false;
- }
-
- void Sound::Close()
- {
- if (voice_)
- {
- voice_->Stop();
- voice_->FlushSourceBuffers();
- voice_->DestroyVoice();
- voice_ = nullptr;
- }
-
- transcoder_.ClearBuffer();
-
- opened_ = false;
- playing_ = false;
- }
-
- bool Sound::IsPlaying() const
- {
- if (opened_)
- {
- if (!voice_)
- return false;
-
- XAUDIO2_VOICE_STATE state;
- voice_->GetState(&state);
- uint32_t buffers_queued = state.BuffersQueued;
-
- if (buffers_queued && playing_)
- return true;
- }
- return false;
- }
-
- float Sound::GetVolume() const
- {
- KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
-
- float volume = 0.0f;
- voice_->GetVolume(&volume);
- return volume;
- }
-
- void Sound::SetVolume(float volume)
- {
- KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
-
- volume = std::min(std::max(volume, -224.f), 224.f);
- voice_->SetVolume(volume);
- }
- }
+Sound::Sound()
+ : opened_(false)
+ , playing_(false)
+ , voice_(nullptr)
+{
}
+
+Sound::~Sound()
+{
+ Close();
+}
+
+bool Sound::Load(String const& file_path)
+{
+ if (!FileSystem::Instance().IsFileExists(file_path))
+ {
+ KGE_WARN(L"Media file '%s' not found", file_path.c_str());
+ return false;
+ }
+
+ if (opened_)
+ {
+ Close();
+ }
+
+ String full_path = FileSystem::Instance().GetFullPathForFile(file_path);
+
+ HRESULT hr = transcoder_.LoadMediaFile(full_path);
+ if (FAILED(hr))
+ {
+ KGE_ERROR(L"Load media file failed with HRESULT of %08X", hr);
+ return false;
+ }
+
+ if (!AudioEngine::Instance().CreateSound(*this, transcoder_.GetBuffer()))
+ {
+ Close();
+ return false;
+ }
+
+ opened_ = true;
+ return true;
+}
+
+bool Sound::Load(Resource const& res)
+{
+ if (opened_)
+ {
+ Close();
+ }
+
+ HRESULT hr = transcoder_.LoadMediaResource(res);
+ if (FAILED(hr))
+ {
+ KGE_ERROR(L"Load media resource failed with HRESULT of %08X", hr);
+ return false;
+ }
+
+ if (!AudioEngine::Instance().CreateSound(*this, transcoder_.GetBuffer()))
+ {
+ Close();
+ return false;
+ }
+
+ opened_ = true;
+ return true;
+}
+
+bool Sound::IsValid() const
+{
+ return voice_ != nullptr;
+}
+
+void Sound::Play(int loop_count)
+{
+ if (!opened_)
+ {
+ KGE_ERROR(L"Sound must be opened first!");
+ return;
+ }
+
+ KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
+
+ // if sound stream is not empty, stop() will clear it
+ XAUDIO2_VOICE_STATE state;
+ voice_->GetState(&state);
+ if (state.BuffersQueued)
+ Stop();
+
+ // 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_buffer.data;
+ buffer.Flags = XAUDIO2_END_OF_STREAM;
+ buffer.AudioBytes = wave_buffer.size;
+ buffer.LoopCount = static_cast(loop_count);
+
+ HRESULT hr = voice_->SubmitSourceBuffer(&buffer);
+ if (SUCCEEDED(hr))
+ {
+ hr = voice_->Start();
+ }
+
+ if (FAILED(hr))
+ {
+ KGE_ERROR(L"Submitting source buffer failed with HRESULT of %08X", hr);
+ }
+
+ playing_ = SUCCEEDED(hr);
+}
+
+void Sound::Pause()
+{
+ KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
+
+ if (SUCCEEDED(voice_->Stop()))
+ playing_ = false;
+}
+
+void Sound::Resume()
+{
+ KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
+
+ if (SUCCEEDED(voice_->Start()))
+ playing_ = true;
+}
+
+void Sound::Stop()
+{
+ KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
+
+ HRESULT hr = voice_->Stop();
+
+ if (SUCCEEDED(hr))
+ hr = voice_->ExitLoop();
+
+ if (SUCCEEDED(hr))
+ hr = voice_->FlushSourceBuffers();
+
+ if (SUCCEEDED(hr))
+ playing_ = false;
+}
+
+void Sound::Close()
+{
+ if (voice_)
+ {
+ voice_->Stop();
+ voice_->FlushSourceBuffers();
+ voice_->DestroyVoice();
+ voice_ = nullptr;
+ }
+
+ transcoder_.ClearBuffer();
+
+ opened_ = false;
+ playing_ = false;
+}
+
+bool Sound::IsPlaying() const
+{
+ if (opened_)
+ {
+ if (!voice_)
+ return false;
+
+ XAUDIO2_VOICE_STATE state;
+ voice_->GetState(&state);
+ uint32_t buffers_queued = state.BuffersQueued;
+
+ if (buffers_queued && playing_)
+ return true;
+ }
+ return false;
+}
+
+float Sound::GetVolume() const
+{
+ KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
+
+ float volume = 0.0f;
+ voice_->GetVolume(&volume);
+ return volume;
+}
+
+void Sound::SetVolume(float volume)
+{
+ KGE_ASSERT(voice_ != nullptr && "IXAudio2SourceVoice* is NULL");
+
+ volume = std::min(std::max(volume, -224.f), 224.f);
+ voice_->SetVolume(volume);
+}
+} // namespace audio
+} // namespace kiwano
diff --git a/src/kiwano-audio/Sound.h b/src/kiwano-audio/Sound.h
index 61d40983..14987b15 100644
--- a/src/kiwano-audio/Sound.h
+++ b/src/kiwano-audio/Sound.h
@@ -1,15 +1,15 @@
// 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
@@ -19,110 +19,108 @@
// THE SOFTWARE.
#pragma once
+#include
#include
#include
#include
-#include
#include
namespace kiwano
{
- namespace audio
- {
- class AudioEngine;
+namespace audio
+{
+class AudioEngine;
- KGE_DECLARE_SMART_PTR(Sound);
+KGE_DECLARE_SMART_PTR(Sound);
- /**
- * \addtogroup Audio
- * @{
- */
+/**
+ * \addtogroup Audio
+ * @{
+ */
- /**
- * \~chinese
- * @brief 音频
- */
- class KGE_API Sound
- : public virtual ObjectBase
- {
- friend class AudioEngine;
+/**
+ * \~chinese
+ * @brief 音频
+ */
+class KGE_API Sound : public virtual ObjectBase
+{
+ friend class AudioEngine;
- public:
- Sound();
+public:
+ Sound();
- virtual ~Sound();
+ virtual ~Sound();
- /// \~chinese
- /// @brief 打开本地音频文件
- /// @param res 本地音频文件路径
- bool Load(String const& file_path);
+ /// \~chinese
+ /// @brief 打开本地音频文件
+ /// @param res 本地音频文件路径
+ bool Load(String const& file_path);
- /// \~chinese
- /// @brief 打开音频资源
- /// @param res 音频资源
- bool Load(Resource const& res);
+ /// \~chinese
+ /// @brief 打开音频资源
+ /// @param res 音频资源
+ bool Load(Resource const& res);
- /// \~chinese
- /// @brief 是否有效
- bool IsValid() const;
+ /// \~chinese
+ /// @brief 是否有效
+ bool IsValid() const;
- /// \~chinese
- /// @brief 播放
- /// @param loop_count 播放循环次数,设置 -1 为循环播放
- void Play(int loop_count = 0);
+ /// \~chinese
+ /// @brief 播放
+ /// @param loop_count 播放循环次数,设置 -1 为循环播放
+ void Play(int loop_count = 0);
- /// \~chinese
- /// @brief 暂停
- void Pause();
+ /// \~chinese
+ /// @brief 暂停
+ void Pause();
- /// \~chinese
- /// @brief 继续
- void Resume();
+ /// \~chinese
+ /// @brief 继续
+ void Resume();
- /// \~chinese
- /// @brief 停止
- void Stop();
+ /// \~chinese
+ /// @brief 停止
+ void Stop();
- /// \~chinese
- /// @brief 关闭并销毁资源
- void Close();
+ /// \~chinese
+ /// @brief 关闭并销毁资源
+ void Close();
- /// \~chinese
- /// @brief 是否正在播放
- bool IsPlaying() const;
+ /// \~chinese
+ /// @brief 是否正在播放
+ bool IsPlaying() const;
- /// \~chinese
- /// @brief 获取音量
- float GetVolume() const;
+ /// \~chinese
+ /// @brief 获取音量
+ float GetVolume() const;
- /// \~chinese
- /// @brief 设置音量
- /// @param volume 音量大小,1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量
- void SetVolume(float volume);
+ /// \~chinese
+ /// @brief 设置音量
+ /// @param volume 音量大小,1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量
+ void SetVolume(float volume);
- private:
- IXAudio2SourceVoice* GetXAudio2Voice() const;
+private:
+ IXAudio2SourceVoice* GetXAudio2Voice() const;
- void SetXAudio2Voice(IXAudio2SourceVoice* voice);
+ void SetXAudio2Voice(IXAudio2SourceVoice* voice);
- private:
- bool opened_;
- bool playing_;
- Transcoder transcoder_;
- IXAudio2SourceVoice* voice_;
- };
+private:
+ bool opened_;
+ bool playing_;
+ Transcoder transcoder_;
+ IXAudio2SourceVoice* voice_;
+};
- /** @} */
+/** @} */
-
- inline IXAudio2SourceVoice* Sound::GetXAudio2Voice() const
- {
- return voice_;
- }
-
- inline void Sound::SetXAudio2Voice(IXAudio2SourceVoice* voice)
- {
- voice_ = voice;
- }
- }
+inline IXAudio2SourceVoice* Sound::GetXAudio2Voice() const
+{
+ return voice_;
}
+
+inline void Sound::SetXAudio2Voice(IXAudio2SourceVoice* voice)
+{
+ voice_ = voice;
+}
+} // namespace audio
+} // namespace kiwano
diff --git a/src/kiwano-audio/SoundPlayer.cpp b/src/kiwano-audio/SoundPlayer.cpp
index 5146b885..442a3e2a 100644
--- a/src/kiwano-audio/SoundPlayer.cpp
+++ b/src/kiwano-audio/SoundPlayer.cpp
@@ -1,15 +1,15 @@
// 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
@@ -22,135 +22,135 @@
namespace kiwano
{
- namespace audio
- {
- SoundPlayer::SoundPlayer()
- : volume_(1.f)
- {
- }
-
- SoundPlayer::~SoundPlayer()
- {
- ClearCache();
- }
-
- size_t SoundPlayer::Load(String const& file_path)
- {
- int hash_code = static_cast(file_path.hash());
- if (sound_cache_.end() != sound_cache_.find(hash_code))
- return hash_code;
-
- SoundPtr sound = new (std::nothrow) Sound;
-
- if (sound)
- {
- if (sound->Load(file_path))
- {
- sound->SetVolume(volume_);
- sound_cache_.insert(std::make_pair(hash_code, sound));
- return hash_code;
- }
- }
- return 0;
- }
-
- size_t SoundPlayer::Load(Resource const& res)
- {
- size_t hash_code = static_cast(res.GetId());
- if (sound_cache_.end() != sound_cache_.find(hash_code))
- return hash_code;
-
- SoundPtr sound = new (std::nothrow) Sound;
-
- if (sound)
- {
- if (sound->Load(res))
- {
- sound->SetVolume(volume_);
- sound_cache_.insert(std::make_pair(hash_code, sound));
- return hash_code;
- }
- }
- return 0;
- }
-
- void SoundPlayer::Play(size_t id, int loop_count)
- {
- auto iter = sound_cache_.find(id);
- if (sound_cache_.end() != iter)
- iter->second->Play(loop_count);
- }
-
- void SoundPlayer::Pause(size_t id)
- {
- auto iter = sound_cache_.find(id);
- if (sound_cache_.end() != iter)
- iter->second->Pause();
- }
-
- void SoundPlayer::Resume(size_t id)
- {
- auto iter = sound_cache_.find(id);
- if (sound_cache_.end() != iter)
- iter->second->Resume();
- }
-
- void SoundPlayer::Stop(size_t id)
- {
- auto iter = sound_cache_.find(id);
- if (sound_cache_.end() != iter)
- iter->second->Stop();
- }
-
- bool SoundPlayer::IsPlaying(size_t id)
- {
- auto iter = sound_cache_.find(id);
- if (sound_cache_.end() != iter)
- return iter->second->IsPlaying();
- return false;
- }
-
- float SoundPlayer::GetVolume() const
- {
- return volume_;
- }
-
- void SoundPlayer::SetVolume(float volume)
- {
- volume_ = std::min(std::max(volume, -224.f), 224.f);
- for (auto& pair : sound_cache_)
- {
- pair.second->SetVolume(volume_);
- }
- }
-
- void SoundPlayer::PauseAll()
- {
- for (auto& pair : sound_cache_)
- {
- pair.second->Pause();
- }
- }
-
- void SoundPlayer::ResumeAll()
- {
- for (auto& pair : sound_cache_)
- {
- pair.second->Resume();
- }
- }
-
- void SoundPlayer::StopAll()
- {
- for (auto& pair : sound_cache_)
- {
- pair.second->Stop();
- }
- }
-
- void SoundPlayer::ClearCache()
- {
- sound_cache_.clear();
- }
- }
+namespace audio
+{
+SoundPlayer::SoundPlayer()
+ : volume_(1.f)
+{
}
+
+SoundPlayer::~SoundPlayer()
+{
+ ClearCache();
+}
+
+size_t SoundPlayer::Load(String const& file_path)
+{
+ int hash_code = static_cast(file_path.hash());
+ if (sound_cache_.end() != sound_cache_.find(hash_code))
+ return hash_code;
+
+ SoundPtr sound = new (std::nothrow) Sound;
+
+ if (sound)
+ {
+ if (sound->Load(file_path))
+ {
+ sound->SetVolume(volume_);
+ sound_cache_.insert(std::make_pair(hash_code, sound));
+ return hash_code;
+ }
+ }
+ return 0;
+}
+
+size_t SoundPlayer::Load(Resource const& res)
+{
+ size_t hash_code = static_cast(res.GetId());
+ if (sound_cache_.end() != sound_cache_.find(hash_code))
+ return hash_code;
+
+ SoundPtr sound = new (std::nothrow) Sound;
+
+ if (sound)
+ {
+ if (sound->Load(res))
+ {
+ sound->SetVolume(volume_);
+ sound_cache_.insert(std::make_pair(hash_code, sound));
+ return hash_code;
+ }
+ }
+ return 0;
+}
+
+void SoundPlayer::Play(size_t id, int loop_count)
+{
+ auto iter = sound_cache_.find(id);
+ if (sound_cache_.end() != iter)
+ iter->second->Play(loop_count);
+}
+
+void SoundPlayer::Pause(size_t id)
+{
+ auto iter = sound_cache_.find(id);
+ if (sound_cache_.end() != iter)
+ iter->second->Pause();
+}
+
+void SoundPlayer::Resume(size_t id)
+{
+ auto iter = sound_cache_.find(id);
+ if (sound_cache_.end() != iter)
+ iter->second->Resume();
+}
+
+void SoundPlayer::Stop(size_t id)
+{
+ auto iter = sound_cache_.find(id);
+ if (sound_cache_.end() != iter)
+ iter->second->Stop();
+}
+
+bool SoundPlayer::IsPlaying(size_t id)
+{
+ auto iter = sound_cache_.find(id);
+ if (sound_cache_.end() != iter)
+ return iter->second->IsPlaying();
+ return false;
+}
+
+float SoundPlayer::GetVolume() const
+{
+ return volume_;
+}
+
+void SoundPlayer::SetVolume(float volume)
+{
+ volume_ = std::min(std::max(volume, -224.f), 224.f);
+ for (auto& pair : sound_cache_)
+ {
+ pair.second->SetVolume(volume_);
+ }
+}
+
+void SoundPlayer::PauseAll()
+{
+ for (auto& pair : sound_cache_)
+ {
+ pair.second->Pause();
+ }
+}
+
+void SoundPlayer::ResumeAll()
+{
+ for (auto& pair : sound_cache_)
+ {
+ pair.second->Resume();
+ }
+}
+
+void SoundPlayer::StopAll()
+{
+ for (auto& pair : sound_cache_)
+ {
+ pair.second->Stop();
+ }
+}
+
+void SoundPlayer::ClearCache()
+{
+ sound_cache_.clear();
+}
+} // namespace audio
+} // namespace kiwano
diff --git a/src/kiwano-audio/SoundPlayer.h b/src/kiwano-audio/SoundPlayer.h
index 523a37bc..df200860 100644
--- a/src/kiwano-audio/SoundPlayer.h
+++ b/src/kiwano-audio/SoundPlayer.h
@@ -1,15 +1,15 @@
// 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
@@ -19,102 +19,101 @@
// THE SOFTWARE.
#pragma once
-#include
#include
+#include
namespace kiwano
{
- namespace audio
- {
- KGE_DECLARE_SMART_PTR(SoundPlayer);
+namespace audio
+{
+KGE_DECLARE_SMART_PTR(SoundPlayer);
- /**
- * \addtogroup Audio
- * @{
- */
+/**
+ * \addtogroup Audio
+ * @{
+ */
- /**
- * \~chinese
- * @brief 音频播放器
- */
- class KGE_API SoundPlayer
- : public virtual ObjectBase
- {
- public:
- SoundPlayer();
+/**
+ * \~chinese
+ * @brief 音频播放器
+ */
+class KGE_API SoundPlayer : public virtual ObjectBase
+{
+public:
+ SoundPlayer();
- ~SoundPlayer();
+ ~SoundPlayer();
- /// \~chinese
- /// @brief 加载本地音频文件
- /// @param file_path 本地音频文件路径
- /// @return 音频标识符
- size_t Load(String const& file_path);
+ /// \~chinese
+ /// @brief 加载本地音频文件
+ /// @param file_path 本地音频文件路径
+ /// @return 音频标识符
+ size_t Load(String const& file_path);
- /// \~chinese
- /// @brief 加载音频资源
- /// @param res 音频资源
- /// @return 音频标识符
- size_t Load(Resource const& res);
+ /// \~chinese
+ /// @brief 加载音频资源
+ /// @param res 音频资源
+ /// @return 音频标识符
+ size_t Load(Resource const& res);
- /// \~chinese
- /// @brief 播放音频
- /// @param id 音频标识符
- /// @param loop_count 播放循环次数,设置 -1 为循环播放
- void Play(size_t id, int loop_count = 0);
+ /// \~chinese
+ /// @brief 播放音频
+ /// @param id 音频标识符
+ /// @param loop_count 播放循环次数,设置 -1 为循环播放
+ void Play(size_t id, int loop_count = 0);
- /// \~chinese
- /// @brief 暂停音频
- /// @param id 音频标识符
- void Pause(size_t id);
+ /// \~chinese
+ /// @brief 暂停音频
+ /// @param id 音频标识符
+ void Pause(size_t id);
- /// \~chinese
- /// @brief 继续播放音频
- /// @param id 音频标识符
- void Resume(size_t id);
+ /// \~chinese
+ /// @brief 继续播放音频
+ /// @param id 音频标识符
+ void Resume(size_t id);
- /// \~chinese
- /// @brief 停止音频
- /// @param id 音频标识符
- void Stop(size_t id);
+ /// \~chinese
+ /// @brief 停止音频
+ /// @param id 音频标识符
+ void Stop(size_t id);
- /// \~chinese
- /// @brief 获取音频播放状态
- /// @param id 音频标识符
- bool IsPlaying(size_t id);
+ /// \~chinese
+ /// @brief 获取音频播放状态
+ /// @param id 音频标识符
+ bool IsPlaying(size_t id);
- /// \~chinese
- /// @brief 获取音量
- float GetVolume() const;
+ /// \~chinese
+ /// @brief 获取音量
+ float GetVolume() const;
- /// \~chinese
- /// @brief 设置音量
- /// @param volume 音量大小,1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量
- void SetVolume(float volume);
+ /// \~chinese
+ /// @brief 设置音量
+ /// @param volume 音量大小,1.0 为原始音量, 大于 1 为放大音量, 0 为最小音量
+ void SetVolume(float volume);
- /// \~chinese
- /// @brief 暂停所有音频
- void PauseAll();
+ /// \~chinese
+ /// @brief 暂停所有音频
+ void PauseAll();
- /// \~chinese
- /// @brief 继续播放所有音频
- void ResumeAll();
+ /// \~chinese
+ /// @brief 继续播放所有音频
+ void ResumeAll();
- /// \~chinese
- /// @brief 停止所有音频
- void StopAll();
+ /// \~chinese
+ /// @brief 停止所有音频
+ void StopAll();
- /// \~chinese
- /// @brief 清除缓存
- void ClearCache();
+ /// \~chinese
+ /// @brief 清除缓存
+ void ClearCache();
- private:
- float volume_;
+private:
+ float volume_;
- using SoundMap = Map;
- SoundMap sound_cache_;
- };
+ using SoundMap = Map;
+ SoundMap sound_cache_;
+};
- /** @} */
- }
-}
+/** @} */
+} // namespace audio
+} // namespace kiwano
diff --git a/src/kiwano-audio/Transcoder.cpp b/src/kiwano-audio/Transcoder.cpp
index d55b1a67..bef635c4 100644
--- a/src/kiwano-audio/Transcoder.cpp
+++ b/src/kiwano-audio/Transcoder.cpp
@@ -1,15 +1,15 @@
// 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
@@ -19,280 +19,252 @@
// THE SOFTWARE.
#ifndef INITGUID
-# define INITGUID // MFAudioFormat_PCM, MF_MT_MAJOR_TYPE, MF_MT_SUBTYPE, MFMediaType_Audio
+#define INITGUID // MFAudioFormat_PCM, MF_MT_MAJOR_TYPE, MF_MT_SUBTYPE, MFMediaType_Audio
#endif
-#include
+#include
+#include
#include
-#include
#include
+#include
+#include
#include
#include
-#include
-#include
namespace kiwano
{
- namespace audio
- {
+namespace audio
+{
- 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;
- }
-
- HRESULT Transcoder::LoadMediaFile(String const& file_path)
- {
- HRESULT hr = S_OK;
-
- ComPtr reader;
-
- hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromURL(
- file_path.c_str(),
- nullptr,
- &reader
- );
-
- if (SUCCEEDED(hr))
- {
- hr = ReadSource(reader.get());
- }
-
- return hr;
- }
-
- HRESULT Transcoder::LoadMediaResource(Resource const& res)
- {
- HRESULT hr = S_OK;
-
- ComPtr stream;
- ComPtr byte_stream;
- ComPtr reader;
-
- Resource::Data data = res.GetData();
- if (!data) { return E_FAIL; }
-
- stream = win32::dlls::Shlwapi::Get().SHCreateMemStream(
- static_cast(data.buffer),
- static_cast(data.size)
- );
-
- if (stream == nullptr)
- {
- KGE_ERROR(L"SHCreateMemStream failed");
- return E_OUTOFMEMORY;
- }
-
- if (SUCCEEDED(hr))
- {
- hr = dlls::MediaFoundation::Get().MFCreateMFByteStreamOnStream(stream.get(), &byte_stream);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromByteStream(
- byte_stream.get(),
- nullptr,
- &reader
- );
- }
-
- if (SUCCEEDED(hr))
- {
- hr = ReadSource(reader.get());
- }
-
- return hr;
- }
-
- HRESULT Transcoder::ReadSource(IMFSourceReader* reader)
- {
- HRESULT hr = S_OK;
- DWORD max_stream_size = 0;
-
- ComPtr partial_type;
- ComPtr uncompressed_type;
-
- hr = dlls::MediaFoundation::Get().MFCreateMediaType(&partial_type);
-
- if (SUCCEEDED(hr))
- {
- hr = partial_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = partial_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
- }
-
- // 设置 source reader 的媒体类型,它将使用合适的解码器去解码这个音频
- if (SUCCEEDED(hr))
- {
- hr = reader->SetCurrentMediaType(
- (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
- 0,
- partial_type.get()
- );
- }
-
- // 从 IMFMediaType 中获取 WAVEFORMAT 结构
- if (SUCCEEDED(hr))
- {
- hr = reader->GetCurrentMediaType(
- (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
- &uncompressed_type
- );
- }
-
- // 指定音频流
- if (SUCCEEDED(hr))
- {
- hr = reader->SetStreamSelection(
- (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
- true
- );
- }
-
- // 获取 WAVEFORMAT 数据
- if (SUCCEEDED(hr))
- {
- uint32_t size = 0;
- hr = dlls::MediaFoundation::Get().MFCreateWaveFormatExFromMFMediaType(
- uncompressed_type.get(),
- &wave_format_,
- &size,
- (DWORD)MFWaveFormatExConvertFlag_Normal
- );
- }
-
- // 估算音频流大小
- if (SUCCEEDED(hr))
- {
- PROPVARIANT prop;
- PropVariantInit(&prop);
-
- hr = reader->GetPresentationAttribute(
- (DWORD)MF_SOURCE_READER_MEDIASOURCE,
- MF_PD_DURATION,
- &prop
- );
-
- LONGLONG duration = prop.uhVal.QuadPart;
- max_stream_size = static_cast(
- (duration * wave_format_->nAvgBytesPerSec) / 10000000 + 1
- );
- PropVariantClear(&prop);
- }
-
- // 读取音频数据
- if (SUCCEEDED(hr))
- {
- DWORD flags = 0;
- DWORD position = 0;
- BYTE* data = new (std::nothrow) BYTE[max_stream_size];
-
- ComPtr sample;
- ComPtr buffer;
-
- if (data == nullptr)
- {
- KGE_ERROR(L"Low memory");
- hr = E_OUTOFMEMORY;
- }
- else
- {
- while (true)
- {
- hr = reader->ReadSample(
- (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
- 0,
- nullptr,
- &flags,
- nullptr,
- &sample
- );
-
- if (flags & MF_SOURCE_READERF_ENDOFSTREAM) { break; }
-
- if (sample == nullptr) { continue; }
-
- if (SUCCEEDED(hr))
- {
- hr = sample->ConvertToContiguousBuffer(&buffer);
-
- if (SUCCEEDED(hr))
- {
- BYTE* audio_data = nullptr;
- DWORD sample_buffer_length = 0;
-
- hr = buffer->Lock(
- &audio_data,
- nullptr,
- &sample_buffer_length
- );
-
- if (position + sample_buffer_length >= max_stream_size)
- {
- hr = E_FAIL;
- }
-
- if (SUCCEEDED(hr))
- {
- ::memcpy(data + position, audio_data, sample_buffer_length);
- position += sample_buffer_length;
- hr = buffer->Unlock();
- }
- }
- buffer = nullptr;
- }
- sample = nullptr;
-
- if (FAILED(hr)) { break; }
- }
-
- if (SUCCEEDED(hr))
- {
- wave_data_ = data;
- wave_size_ = position;
- }
- else
- {
- delete[] data;
- data = nullptr;
- }
- }
- }
-
- return hr;
- }
- }
+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;
+}
+
+HRESULT Transcoder::LoadMediaFile(String const& file_path)
+{
+ HRESULT hr = S_OK;
+
+ ComPtr reader;
+
+ hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromURL(file_path.c_str(), nullptr, &reader);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ReadSource(reader.get());
+ }
+
+ return hr;
+}
+
+HRESULT Transcoder::LoadMediaResource(Resource const& res)
+{
+ HRESULT hr = S_OK;
+
+ ComPtr stream;
+ ComPtr byte_stream;
+ ComPtr reader;
+
+ Resource::Data data = res.GetData();
+ if (!data)
+ {
+ return E_FAIL;
+ }
+
+ stream = win32::dlls::Shlwapi::Get().SHCreateMemStream(static_cast(data.buffer),
+ static_cast(data.size));
+
+ if (stream == nullptr)
+ {
+ KGE_ERROR(L"SHCreateMemStream failed");
+ return E_OUTOFMEMORY;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = dlls::MediaFoundation::Get().MFCreateMFByteStreamOnStream(stream.get(), &byte_stream);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromByteStream(byte_stream.get(), nullptr, &reader);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ReadSource(reader.get());
+ }
+
+ return hr;
+}
+
+HRESULT Transcoder::ReadSource(IMFSourceReader* reader)
+{
+ HRESULT hr = S_OK;
+ DWORD max_stream_size = 0;
+
+ ComPtr partial_type;
+ ComPtr uncompressed_type;
+
+ hr = dlls::MediaFoundation::Get().MFCreateMediaType(&partial_type);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = partial_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = partial_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
+ }
+
+ // 设置 source reader 的媒体类型,它将使用合适的解码器去解码这个音频
+ if (SUCCEEDED(hr))
+ {
+ hr = reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, partial_type.get());
+ }
+
+ // 从 IMFMediaType 中获取 WAVEFORMAT 结构
+ if (SUCCEEDED(hr))
+ {
+ hr = reader->GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, &uncompressed_type);
+ }
+
+ // 指定音频流
+ if (SUCCEEDED(hr))
+ {
+ hr = reader->SetStreamSelection((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
+ }
+
+ // 获取 WAVEFORMAT 数据
+ if (SUCCEEDED(hr))
+ {
+ uint32_t size = 0;
+ hr = dlls::MediaFoundation::Get().MFCreateWaveFormatExFromMFMediaType(
+ uncompressed_type.get(), &wave_format_, &size, (DWORD)MFWaveFormatExConvertFlag_Normal);
+ }
+
+ // 估算音频流大小
+ if (SUCCEEDED(hr))
+ {
+ PROPVARIANT prop;
+ PropVariantInit(&prop);
+
+ hr = reader->GetPresentationAttribute((DWORD)MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &prop);
+
+ LONGLONG duration = prop.uhVal.QuadPart;
+ max_stream_size = static_cast((duration * wave_format_->nAvgBytesPerSec) / 10000000 + 1);
+ PropVariantClear(&prop);
+ }
+
+ // 读取音频数据
+ if (SUCCEEDED(hr))
+ {
+ DWORD flags = 0;
+ DWORD position = 0;
+ BYTE* data = new (std::nothrow) BYTE[max_stream_size];
+
+ ComPtr sample;
+ ComPtr buffer;
+
+ if (data == nullptr)
+ {
+ KGE_ERROR(L"Low memory");
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ {
+ while (true)
+ {
+ hr = reader->ReadSample((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, nullptr, &flags, nullptr,
+ &sample);
+
+ if (flags & MF_SOURCE_READERF_ENDOFSTREAM)
+ {
+ break;
+ }
+
+ if (sample == nullptr)
+ {
+ continue;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = sample->ConvertToContiguousBuffer(&buffer);
+
+ if (SUCCEEDED(hr))
+ {
+ BYTE* audio_data = nullptr;
+ DWORD sample_buffer_length = 0;
+
+ hr = buffer->Lock(&audio_data, nullptr, &sample_buffer_length);
+
+ if (position + sample_buffer_length >= max_stream_size)
+ {
+ hr = E_FAIL;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ::memcpy(data + position, audio_data, sample_buffer_length);
+ position += sample_buffer_length;
+ hr = buffer->Unlock();
+ }
+ }
+ buffer = nullptr;
+ }
+ sample = nullptr;
+
+ if (FAILED(hr))
+ {
+ break;
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ wave_data_ = data;
+ wave_size_ = position;
+ }
+ else
+ {
+ delete[] data;
+ data = nullptr;
+ }
+ }
+ }
+
+ return hr;
+}
+} // namespace audio
+} // namespace kiwano
diff --git a/src/kiwano-audio/Transcoder.h b/src/kiwano-audio/Transcoder.h
index 50afd1c0..7b69cdb8 100644
--- a/src/kiwano-audio/Transcoder.h
+++ b/src/kiwano-audio/Transcoder.h
@@ -1,15 +1,15 @@
// 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
@@ -26,66 +26,66 @@
namespace kiwano
{
- namespace audio
- {
- class Sound;
+namespace audio
+{
+class Sound;
- /**
- * \addtogroup Audio
- * @{
- */
+/**
+ * \addtogroup Audio
+ * @{
+ */
- /**
- * \~chinese
- * @brief 音频解码器
- */
- class KGE_API Transcoder
- {
- friend class Sound;
+/**
+ * \~chinese
+ * @brief 音频解码器
+ */
+class KGE_API Transcoder
+{
+ friend class Sound;
- public:
- /**
- * \~chinese
- * @brief 音频数据缓冲
- */
- struct Buffer
- {
- BYTE* data; ///< 音频数据
- uint32_t size; ///< 音频数据大小
- const WAVEFORMATEX* format; ///< 音频数据格式
- };
+public:
+ /**
+ * \~chinese
+ * @brief 音频数据缓冲
+ */
+ struct Buffer
+ {
+ BYTE* data; ///< 音频数据
+ uint32_t size; ///< 音频数据大小
+ const WAVEFORMATEX* format; ///< 音频数据格式
+ };
- Transcoder();
+ Transcoder();
- ~Transcoder();
+ ~Transcoder();
- /// \~chinese
- /// @brief 获取数据缓冲
- Buffer GetBuffer() const;
+ /// \~chinese
+ /// @brief 获取数据缓冲
+ Buffer GetBuffer() const;
- /// \~chinese
- /// @brief 清空数据缓冲
- void ClearBuffer();
+ /// \~chinese
+ /// @brief 清空数据缓冲
+ void ClearBuffer();
- private:
- /// \~chinese
- /// @brief 解码本地音频文件
- HRESULT LoadMediaFile(String const& file_path);
+private:
+ /// \~chinese
+ /// @brief 解码本地音频文件
+ HRESULT LoadMediaFile(String const& file_path);
- /// \~chinese
- /// @brief 解码音频资源
- HRESULT LoadMediaResource(Resource const& res);
+ /// \~chinese
+ /// @brief 解码音频资源
+ HRESULT LoadMediaResource(Resource const& res);
- /// \~chinese
- /// @brief 读取音频源数据
- HRESULT ReadSource(IMFSourceReader* reader);
+ /// \~chinese
+ /// @brief 读取音频源数据
+ HRESULT ReadSource(IMFSourceReader* reader);
- private:
- BYTE* wave_data_;
- uint32_t wave_size_;
- WAVEFORMATEX* wave_format_;
- };
+private:
+ BYTE* wave_data_;
+ uint32_t wave_size_;
+ WAVEFORMATEX* wave_format_;
+};
- /** @} */
- }
-}
+/** @} */
+} // namespace audio
+} // namespace kiwano
diff --git a/src/kiwano-audio/kiwano-audio.h b/src/kiwano-audio/kiwano-audio.h
index 041b7aa7..975d92e1 100644
--- a/src/kiwano-audio/kiwano-audio.h
+++ b/src/kiwano-audio/kiwano-audio.h
@@ -1,15 +1,15 @@
// 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
diff --git a/src/kiwano-audio/libraries.cpp b/src/kiwano-audio/libraries.cpp
index 5239d216..2b060608 100644
--- a/src/kiwano-audio/libraries.cpp
+++ b/src/kiwano-audio/libraries.cpp
@@ -1,15 +1,15 @@
// 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
@@ -18,81 +18,84 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include
#include
+#include
namespace kiwano
{
- namespace audio
- {
- namespace dlls
- {
- XAudio2::XAudio2()
- : xaudio2()
- , XAudio2Create(nullptr)
- {
- const auto xaudio2_dll_names =
- {
- "xaudio2_9.dll", // for Windows 10
- "xaudio2_8.dll", // for Windows 8
- "xaudio2_7.dll" // for DirectX SDK
- };
+namespace audio
+{
+namespace dlls
+{
+XAudio2::XAudio2()
+ : xaudio2()
+ , XAudio2Create(nullptr)
+{
+ const auto xaudio2_dll_names = {
+ "xaudio2_9.dll", // for Windows 10
+ "xaudio2_8.dll", // for Windows 8
+ "xaudio2_7.dll" // for DirectX SDK
+ };
- for (const auto& name : xaudio2_dll_names)
- {
- if (xaudio2.Load(name))
- {
- break;
- }
- }
+ for (const auto& name : xaudio2_dll_names)
+ {
+ if (xaudio2.Load(name))
+ {
+ break;
+ }
+ }
- if (xaudio2.IsValid())
- {
- XAudio2Create = xaudio2.GetProcess("XAudio2Create");
- }
- else
- {
- KGE_ERROR(L"Load xaudio2.dll failed");
- throw std::runtime_error("Load xaudio2.dll failed");
- }
- }
-
- MediaFoundation::MediaFoundation()
- : mfplat()
- , mfreadwrite()
- , MFStartup(nullptr)
- , MFShutdown(nullptr)
- , MFCreateMediaType(nullptr)
- , MFCreateWaveFormatExFromMFMediaType(nullptr)
- , MFCreateSourceReaderFromURL(nullptr)
- , MFCreateSourceReaderFromByteStream(nullptr)
- , MFCreateMFByteStreamOnStream(nullptr)
- {
- if (mfplat.Load("Mfplat.dll"))
- {
- MFStartup = mfplat.GetProcess("MFStartup");
- MFShutdown = mfplat.GetProcess("MFShutdown");
- MFCreateMediaType = mfplat.GetProcess("MFCreateMediaType");
- MFCreateWaveFormatExFromMFMediaType = mfplat.GetProcess("MFCreateWaveFormatExFromMFMediaType");
- MFCreateMFByteStreamOnStream = mfplat.GetProcess("MFCreateMFByteStreamOnStream");
- }
- else
- {
- KGE_ERROR(L"Load Mfplat.dll failed");
- throw std::runtime_error("Load Mfplat.dll failed");
- }
-
- if (mfreadwrite.Load("Mfreadwrite.dll"))
- {
- MFCreateSourceReaderFromURL = mfreadwrite.GetProcess("MFCreateSourceReaderFromURL");
- MFCreateSourceReaderFromByteStream = mfreadwrite.GetProcess("MFCreateSourceReaderFromByteStream");
- }
- else
- {
- KGE_ERROR(L"Load Mfreadwrite.dll failed");
- throw std::runtime_error("Load Mfreadwrite.dll failed");
- }
- }
- }
- }
+ if (xaudio2.IsValid())
+ {
+ XAudio2Create = xaudio2.GetProcess("XAudio2Create");
+ }
+ else
+ {
+ KGE_ERROR(L"Load xaudio2.dll failed");
+ throw std::runtime_error("Load xaudio2.dll failed");
+ }
}
+
+MediaFoundation::MediaFoundation()
+ : mfplat()
+ , mfreadwrite()
+ , MFStartup(nullptr)
+ , MFShutdown(nullptr)
+ , MFCreateMediaType(nullptr)
+ , MFCreateWaveFormatExFromMFMediaType(nullptr)
+ , MFCreateSourceReaderFromURL(nullptr)
+ , MFCreateSourceReaderFromByteStream(nullptr)
+ , MFCreateMFByteStreamOnStream(nullptr)
+{
+ if (mfplat.Load("Mfplat.dll"))
+ {
+ MFStartup = mfplat.GetProcess("MFStartup");
+ MFShutdown = mfplat.GetProcess("MFShutdown");
+ MFCreateMediaType = mfplat.GetProcess("MFCreateMediaType");
+ MFCreateWaveFormatExFromMFMediaType =
+ mfplat.GetProcess("MFCreateWaveFormatExFromMFMediaType");
+ MFCreateMFByteStreamOnStream =
+ mfplat.GetProcess("MFCreateMFByteStreamOnStream");
+ }
+ else
+ {
+ KGE_ERROR(L"Load Mfplat.dll failed");
+ throw std::runtime_error("Load Mfplat.dll failed");
+ }
+
+ if (mfreadwrite.Load("Mfreadwrite.dll"))
+ {
+ MFCreateSourceReaderFromURL =
+ mfreadwrite.GetProcess("MFCreateSourceReaderFromURL");
+ MFCreateSourceReaderFromByteStream =
+ mfreadwrite.GetProcess("MFCreateSourceReaderFromByteStream");
+ }
+ else
+ {
+ KGE_ERROR(L"Load Mfreadwrite.dll failed");
+ throw std::runtime_error("Load Mfreadwrite.dll failed");
+ }
+}
+} // namespace dlls
+} // namespace audio
+} // namespace kiwano
diff --git a/src/kiwano-audio/libraries.h b/src/kiwano-audio/libraries.h
index 44d26bf7..35324db0 100644
--- a/src/kiwano-audio/libraries.h
+++ b/src/kiwano-audio/libraries.h
@@ -1,15 +1,15 @@
// 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
@@ -20,80 +20,79 @@
#pragma once
#include
-#include
#include
#include
#include
+#include
#ifndef KGE_DOXYGEN_DO_NOT_INCLUDE
namespace kiwano
{
- namespace audio
- {
- namespace dlls
- {
- class KGE_API XAudio2
- {
- public:
- static inline XAudio2& Get()
- {
- static XAudio2 instance;
- return instance;
- }
+namespace audio
+{
+namespace dlls
+{
+class KGE_API XAudio2
+{
+public:
+ static inline XAudio2& Get()
+ {
+ static XAudio2 instance;
+ return instance;
+ }
- // XAudio2 functions
- typedef HRESULT(WINAPI* PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR);
+ // XAudio2 functions
+ typedef HRESULT(WINAPI* PFN_XAudio2Create)(IXAudio2**, UINT32, XAUDIO2_PROCESSOR);
- PFN_XAudio2Create XAudio2Create;
+ PFN_XAudio2Create XAudio2Create;
- private:
- XAudio2();
+private:
+ XAudio2();
- XAudio2(const XAudio2&) = delete;
- XAudio2& operator=(const XAudio2&) = delete;
+ XAudio2(const XAudio2&) = delete;
+ XAudio2& operator=(const XAudio2&) = delete;
- Library xaudio2;
- };
+ Library xaudio2;
+};
+class KGE_API MediaFoundation
+{
+public:
+ static inline MediaFoundation& Get()
+ {
+ static MediaFoundation instance;
+ return instance;
+ }
- class KGE_API MediaFoundation
- {
- public:
- static inline MediaFoundation& Get()
- {
- static MediaFoundation instance;
- return instance;
- }
+ // MediaFoundation functions
+ typedef HRESULT(WINAPI* PFN_MFStartup)(ULONG, DWORD);
+ typedef HRESULT(WINAPI* PFN_MFShutdown)();
+ typedef HRESULT(WINAPI* PFN_MFCreateMediaType)(IMFMediaType**);
+ typedef HRESULT(WINAPI* PFN_MFCreateWaveFormatExFromMFMediaType)(IMFMediaType*, WAVEFORMATEX**, UINT32*, UINT32);
+ typedef HRESULT(WINAPI* PFN_MFCreateSourceReaderFromURL)(LPCWSTR, IMFAttributes*, IMFSourceReader**);
+ typedef HRESULT(WINAPI* PFN_MFCreateSourceReaderFromByteStream)(IMFByteStream*, IMFAttributes*, IMFSourceReader**);
+ typedef HRESULT(WINAPI* PFN_MFCreateMFByteStreamOnStream)(IStream*, IMFByteStream**);
- // MediaFoundation functions
- typedef HRESULT(WINAPI* PFN_MFStartup)(ULONG, DWORD);
- typedef HRESULT(WINAPI* PFN_MFShutdown)();
- typedef HRESULT(WINAPI* PFN_MFCreateMediaType)(IMFMediaType**);
- typedef HRESULT(WINAPI* PFN_MFCreateWaveFormatExFromMFMediaType)(IMFMediaType*, WAVEFORMATEX**, UINT32*, UINT32);
- typedef HRESULT(WINAPI* PFN_MFCreateSourceReaderFromURL)(LPCWSTR, IMFAttributes*, IMFSourceReader**);
- typedef HRESULT(WINAPI* PFN_MFCreateSourceReaderFromByteStream)(IMFByteStream*, IMFAttributes*, IMFSourceReader**);
- typedef HRESULT(WINAPI* PFN_MFCreateMFByteStreamOnStream)(IStream*, IMFByteStream**);
+ PFN_MFStartup MFStartup;
+ PFN_MFShutdown MFShutdown;
+ PFN_MFCreateMediaType MFCreateMediaType;
+ PFN_MFCreateWaveFormatExFromMFMediaType MFCreateWaveFormatExFromMFMediaType;
+ PFN_MFCreateSourceReaderFromURL MFCreateSourceReaderFromURL;
+ PFN_MFCreateSourceReaderFromByteStream MFCreateSourceReaderFromByteStream;
+ PFN_MFCreateMFByteStreamOnStream MFCreateMFByteStreamOnStream;
- PFN_MFStartup MFStartup;
- PFN_MFShutdown MFShutdown;
- PFN_MFCreateMediaType MFCreateMediaType;
- PFN_MFCreateWaveFormatExFromMFMediaType MFCreateWaveFormatExFromMFMediaType;
- PFN_MFCreateSourceReaderFromURL MFCreateSourceReaderFromURL;
- PFN_MFCreateSourceReaderFromByteStream MFCreateSourceReaderFromByteStream;
- PFN_MFCreateMFByteStreamOnStream MFCreateMFByteStreamOnStream;
+private:
+ MediaFoundation();
- private:
- MediaFoundation();
+ MediaFoundation(const MediaFoundation&) = delete;
+ MediaFoundation& operator=(const MediaFoundation&) = delete;
- MediaFoundation(const MediaFoundation&) = delete;
- MediaFoundation& operator=(const MediaFoundation&) = delete;
-
- Library mfplat;
- Library mfreadwrite;
- };
- }
- }
-}
+ Library mfplat;
+ Library mfreadwrite;
+};
+} // namespace dlls
+} // namespace audio
+} // namespace kiwano
#endif
diff --git a/src/kiwano-imgui/ImGuiLayer.cpp b/src/kiwano-imgui/ImGuiLayer.cpp
index ae5ea8e7..94054b4d 100644
--- a/src/kiwano-imgui/ImGuiLayer.cpp
+++ b/src/kiwano-imgui/ImGuiLayer.cpp
@@ -1,15 +1,15 @@
// 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
@@ -22,47 +22,45 @@
namespace kiwano
{
- namespace imgui
- {
- ImGuiLayer::ImGuiLayer()
- {
- SetSwallowEvents(true);
- }
-
- ImGuiLayer::~ImGuiLayer()
- {
- }
-
- void ImGuiLayer::OnRender(RenderContext& ctx)
- {
- for (const auto& pipeline : pipelines_)
- {
- pipeline.second();
- }
- }
-
- bool ImGuiLayer::CheckVisibility(RenderContext& ctx) const
- {
- return true;
- }
-
- void ImGuiLayer::AddItem(String const& name, ImGuiPipeline const& item)
- {
- pipelines_.insert(std::make_pair(name, item));
- }
-
- void ImGuiLayer::RemoveItem(String const& name)
- {
- auto iter = pipelines_.find(name);
- if (iter != pipelines_.end())
- {
- pipelines_.erase(iter);
- }
- }
-
- void ImGuiLayer::RemoveAllItems()
- {
- pipelines_.clear();
- }
- }
+namespace imgui
+{
+ImGuiLayer::ImGuiLayer()
+{
+ SetSwallowEvents(true);
}
+
+ImGuiLayer::~ImGuiLayer() {}
+
+void ImGuiLayer::OnRender(RenderContext& ctx)
+{
+ for (const auto& pipeline : pipelines_)
+ {
+ pipeline.second();
+ }
+}
+
+bool ImGuiLayer::CheckVisibility(RenderContext& ctx) const
+{
+ return true;
+}
+
+void ImGuiLayer::AddItem(String const& name, ImGuiPipeline const& item)
+{
+ pipelines_.insert(std::make_pair(name, item));
+}
+
+void ImGuiLayer::RemoveItem(String const& name)
+{
+ auto iter = pipelines_.find(name);
+ if (iter != pipelines_.end())
+ {
+ pipelines_.erase(iter);
+ }
+}
+
+void ImGuiLayer::RemoveAllItems()
+{
+ pipelines_.clear();
+}
+} // namespace imgui
+} // namespace kiwano
diff --git a/src/kiwano-imgui/ImGuiLayer.h b/src/kiwano-imgui/ImGuiLayer.h
index d62e5b0c..a377805e 100644
--- a/src/kiwano-imgui/ImGuiLayer.h
+++ b/src/kiwano-imgui/ImGuiLayer.h
@@ -1,15 +1,15 @@
// 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
@@ -23,49 +23,48 @@
namespace kiwano
{
- namespace imgui
- {
- KGE_DECLARE_SMART_PTR(ImGuiLayer);
+namespace imgui
+{
+KGE_DECLARE_SMART_PTR(ImGuiLayer);
- /// \~chinese
- /// @brief ImGui管道
- using ImGuiPipeline = Function;
+/// \~chinese
+/// @brief ImGui管道
+using ImGuiPipeline = Function;
- /**
- * \~chinese
- * @brief ImGui图层
- */
- class ImGuiLayer
- : public Layer
- {
- public:
- ImGuiLayer();
+/**
+ * \~chinese
+ * @brief ImGui图层
+ */
+class ImGuiLayer : public Layer
+{
+public:
+ ImGuiLayer();
- virtual ~ImGuiLayer();
+ virtual ~ImGuiLayer();
- /// \~chinese
- /// @brief 添加 ImGui 元素
- /// @param name 元素名称
- /// @param item 管道
- void AddItem(String const& name, ImGuiPipeline const& item);
+ /// \~chinese
+ /// @brief 添加 ImGui 元素
+ /// @param name 元素名称
+ /// @param item 管道
+ void AddItem(String const& name, ImGuiPipeline const& item);
- /// \~chinese
- /// @brief 移除 ImGui 元素
- /// @param name 元素名称
- void RemoveItem(String const& name);
+ /// \~chinese
+ /// @brief 移除 ImGui 元素
+ /// @param name 元素名称
+ void RemoveItem(String const& name);
- // 移除所有元素
- /// \~chinese
- /// @brief 移除所有元素
- void RemoveAllItems();
+ // 移除所有元素
+ /// \~chinese
+ /// @brief 移除所有元素
+ void RemoveAllItems();
- public:
- void OnRender(RenderContext& ctx) override;
+public:
+ void OnRender(RenderContext& ctx) override;
- bool CheckVisibility(RenderContext& ctx) const override;
+ bool CheckVisibility(RenderContext& ctx) const override;
- private:
- Map pipelines_;
- };
- }
-}
+private:
+ Map pipelines_;
+};
+} // namespace imgui
+} // namespace kiwano
diff --git a/src/kiwano-imgui/ImGuiModule.cpp b/src/kiwano-imgui/ImGuiModule.cpp
index 0d5ff03f..fea5b179 100644
--- a/src/kiwano-imgui/ImGuiModule.cpp
+++ b/src/kiwano-imgui/ImGuiModule.cpp
@@ -1,209 +1,235 @@
// Copyright (C) 2019 Nomango
+#include
+#include
#include
#include
#include
-#include
#include
+#include
#include
-#include
-#include
namespace kiwano
{
- namespace imgui
- {
- ImGuiModule::ImGuiModule()
- : target_window_(nullptr)
- {
- }
-
- void ImGuiModule::SetupComponent()
- {
- // Setup Dear ImGui context
- IMGUI_CHECKVERSION();
- ImGui::CreateContext();
- ImGuiIO& io = ImGui::GetIO(); (void)io;
-
- // Setup Dear ImGui style
- ImGui::StyleColorsDark();
-
- // Setup Platform/Renderer bindings
- target_window_ = Renderer::Instance().GetTargetWindow();
-
- io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
- io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
- io.BackendPlatformName = "imgui_impl_win32";
- io.ImeWindowHandle = target_window_;
-
- // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
- io.KeyMap[ImGuiKey_Tab] = (int)KeyCode::Tab;
- io.KeyMap[ImGuiKey_LeftArrow] = (int)KeyCode::Left;
- io.KeyMap[ImGuiKey_RightArrow] = (int)KeyCode::Right;
- io.KeyMap[ImGuiKey_UpArrow] = (int)KeyCode::Up;
- io.KeyMap[ImGuiKey_DownArrow] = (int)KeyCode::Down;
- io.KeyMap[ImGuiKey_Delete] = (int)KeyCode::Delete;
- io.KeyMap[ImGuiKey_Backspace] = (int)KeyCode::Back;
- io.KeyMap[ImGuiKey_Space] = (int)KeyCode::Space;
- io.KeyMap[ImGuiKey_Enter] = (int)KeyCode::Enter;
- io.KeyMap[ImGuiKey_Escape] = (int)KeyCode::Esc;
- io.KeyMap[ImGuiKey_A] = (int)KeyCode::A;
- io.KeyMap[ImGuiKey_C] = (int)KeyCode::C;
- io.KeyMap[ImGuiKey_V] = (int)KeyCode::V;
- io.KeyMap[ImGuiKey_X] = (int)KeyCode::X;
- io.KeyMap[ImGuiKey_Y] = (int)KeyCode::Y;
- io.KeyMap[ImGuiKey_Z] = (int)KeyCode::Z;
-
- ImGui_Impl_Init(Renderer::Instance());
- }
-
- void ImGuiModule::DestroyComponent()
- {
- ImGui_Impl_Shutdown();
- ImGui::DestroyContext();
- }
-
- void ImGuiModule::OnUpdate(Duration dt)
- {
- ImGuiIO& io = ImGui::GetIO();
-
- // Setup time step
- io.DeltaTime = dt.Seconds();
-
- // Read keyboard modifiers inputs
- io.KeyCtrl = Input::Instance().IsDown(KeyCode::Ctrl);
- io.KeyShift = Input::Instance().IsDown(KeyCode::Shift);
- io.KeyAlt = Input::Instance().IsDown(KeyCode::Alt);
- io.KeySuper = Input::Instance().IsDown(KeyCode::Super);
- // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the HandleEvent function below.
-
- // Update OS mouse position
- UpdateMousePos();
-
- // Update OS mouse cursor with the cursor requested by imgui
- UpdateMouseCursor();
- }
-
- void ImGuiModule::BeforeRender()
- {
- NewFrame();
- }
-
- void ImGuiModule::AfterRender()
- {
- Render();
- }
-
- void ImGuiModule::HandleEvent(Event* evt)
- {
- if (ImGui::GetCurrentContext() == NULL)
- return;
-
- ImGuiIO& io = ImGui::GetIO();
- if (evt->IsType())
- {
- if (evt->IsType())
- {
- MouseButton button = dynamic_cast(evt)->button;
- int index = 0;
- if (button == MouseButton::Left) index = 0;
- else if (button == MouseButton::Right) index = 1;
- else if (button == MouseButton::Middle) index = 2;
- io.MouseDown[index] = true;
- }
- else if (evt->IsType())
- {
- MouseButton button = dynamic_cast(evt)->button;
- int index = 0;
- if (button == MouseButton::Left) index = 0;
- else if (button == MouseButton::Right) index = 1;
- else if (button == MouseButton::Middle) index = 2;
- io.MouseDown[index] = false;
- }
- else if (evt->IsType())
- {
- float wheel = dynamic_cast(evt)->wheel;
- io.MouseWheel += wheel;
- }
- }
- else if (evt->IsType())
- {
- if (evt->IsType())
- {
- KeyCode key = dynamic_cast(evt)->code;
- io.KeysDown[(int)key] = true;
- }
- else if (evt->IsType())
- {
- KeyCode key = dynamic_cast(evt)->code;
- io.KeysDown[(int)key] = false;
- }
- else if (evt->IsType())
- {
- // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
- char ch = dynamic_cast(evt)->value;
- io.AddInputCharacter(static_cast(ch));
- }
- }
- }
-
- void ImGuiModule::NewFrame()
- {
- ImGui_Impl_NewFrame();
-
- ImGuiIO& io = ImGui::GetIO();
- KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!");
-
- // Setup display size (every frame to accommodate for window resizing)
- Size display_size = Renderer::Instance().GetOutputSize();
- io.DisplaySize = ImVec2(display_size.x, display_size.y);
-
- ImGui::NewFrame();
- }
-
- void ImGuiModule::Render()
- {
- ImGui::Render();
-
- ImGui_Impl_RenderDrawData(ImGui::GetDrawData());
- }
-
- void ImGuiModule::UpdateMousePos()
- {
- ImGuiIO& io = ImGui::GetIO();
-
- // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
- if (io.WantSetMousePos)
- {
- POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
- ::ClientToScreen(target_window_, &pos);
- ::SetCursorPos(pos.x, pos.y);
- }
-
- Point pos = Input::Instance().GetMousePos();
- io.MousePos = ImVec2(pos.x, pos.y);
- }
-
- void ImGuiModule::UpdateMouseCursor()
- {
- if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
- return;
-
- CursorType cursor = CursorType::Arrow;
- switch (ImGui::GetMouseCursor())
- {
- case ImGuiMouseCursor_Arrow: cursor = CursorType::Arrow; break;
- case ImGuiMouseCursor_TextInput: cursor = CursorType::TextInput; break;
- case ImGuiMouseCursor_ResizeAll: cursor = CursorType::SizeAll; break;
- case ImGuiMouseCursor_ResizeEW: cursor = CursorType::SizeWE; break;
- case ImGuiMouseCursor_ResizeNS: cursor = CursorType::SizeNS; break;
- case ImGuiMouseCursor_ResizeNESW: cursor = CursorType::SizeNESW; break;
- case ImGuiMouseCursor_ResizeNWSE: cursor = CursorType::SizeNWSE; break;
- case ImGuiMouseCursor_Hand: cursor = CursorType::Hand; break;
- }
-
- Window::Instance().SetCursor(cursor);
- }
-
- }
+namespace imgui
+{
+ImGuiModule::ImGuiModule()
+ : target_window_(nullptr)
+{
}
+
+void ImGuiModule::SetupComponent()
+{
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO();
+ (void)io;
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+
+ // Setup Platform/Renderer bindings
+ target_window_ = Renderer::Instance().GetTargetWindow();
+
+ io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
+ io.BackendFlags |=
+ ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
+ io.BackendPlatformName = "imgui_impl_win32";
+ io.ImeWindowHandle = target_window_;
+
+ // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during
+ // the application lifetime.
+ io.KeyMap[ImGuiKey_Tab] = (int)KeyCode::Tab;
+ io.KeyMap[ImGuiKey_LeftArrow] = (int)KeyCode::Left;
+ io.KeyMap[ImGuiKey_RightArrow] = (int)KeyCode::Right;
+ io.KeyMap[ImGuiKey_UpArrow] = (int)KeyCode::Up;
+ io.KeyMap[ImGuiKey_DownArrow] = (int)KeyCode::Down;
+ io.KeyMap[ImGuiKey_Delete] = (int)KeyCode::Delete;
+ io.KeyMap[ImGuiKey_Backspace] = (int)KeyCode::Back;
+ io.KeyMap[ImGuiKey_Space] = (int)KeyCode::Space;
+ io.KeyMap[ImGuiKey_Enter] = (int)KeyCode::Enter;
+ io.KeyMap[ImGuiKey_Escape] = (int)KeyCode::Esc;
+ io.KeyMap[ImGuiKey_A] = (int)KeyCode::A;
+ io.KeyMap[ImGuiKey_C] = (int)KeyCode::C;
+ io.KeyMap[ImGuiKey_V] = (int)KeyCode::V;
+ io.KeyMap[ImGuiKey_X] = (int)KeyCode::X;
+ io.KeyMap[ImGuiKey_Y] = (int)KeyCode::Y;
+ io.KeyMap[ImGuiKey_Z] = (int)KeyCode::Z;
+
+ ImGui_Impl_Init(Renderer::Instance());
+}
+
+void ImGuiModule::DestroyComponent()
+{
+ ImGui_Impl_Shutdown();
+ ImGui::DestroyContext();
+}
+
+void ImGuiModule::OnUpdate(Duration dt)
+{
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Setup time step
+ io.DeltaTime = dt.Seconds();
+
+ // Read keyboard modifiers inputs
+ io.KeyCtrl = Input::Instance().IsDown(KeyCode::Ctrl);
+ io.KeyShift = Input::Instance().IsDown(KeyCode::Shift);
+ io.KeyAlt = Input::Instance().IsDown(KeyCode::Alt);
+ io.KeySuper = Input::Instance().IsDown(KeyCode::Super);
+ // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the HandleEvent function below.
+
+ // Update OS mouse position
+ UpdateMousePos();
+
+ // Update OS mouse cursor with the cursor requested by imgui
+ UpdateMouseCursor();
+}
+
+void ImGuiModule::BeforeRender()
+{
+ NewFrame();
+}
+
+void ImGuiModule::AfterRender()
+{
+ Render();
+}
+
+void ImGuiModule::HandleEvent(Event* evt)
+{
+ if (ImGui::GetCurrentContext() == NULL)
+ return;
+
+ ImGuiIO& io = ImGui::GetIO();
+ if (evt->IsType())
+ {
+ if (evt->IsType())
+ {
+ MouseButton button = dynamic_cast(evt)->button;
+ int index = 0;
+ if (button == MouseButton::Left)
+ index = 0;
+ else if (button == MouseButton::Right)
+ index = 1;
+ else if (button == MouseButton::Middle)
+ index = 2;
+ io.MouseDown[index] = true;
+ }
+ else if (evt->IsType())
+ {
+ MouseButton button = dynamic_cast(evt)->button;
+ int index = 0;
+ if (button == MouseButton::Left)
+ index = 0;
+ else if (button == MouseButton::Right)
+ index = 1;
+ else if (button == MouseButton::Middle)
+ index = 2;
+ io.MouseDown[index] = false;
+ }
+ else if (evt->IsType())
+ {
+ float wheel = dynamic_cast(evt)->wheel;
+ io.MouseWheel += wheel;
+ }
+ }
+ else if (evt->IsType())
+ {
+ if (evt->IsType())
+ {
+ KeyCode key = dynamic_cast(evt)->code;
+ io.KeysDown[(int)key] = true;
+ }
+ else if (evt->IsType())
+ {
+ KeyCode key = dynamic_cast(evt)->code;
+ io.KeysDown[(int)key] = false;
+ }
+ else if (evt->IsType())
+ {
+ // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
+ char ch = dynamic_cast(evt)->value;
+ io.AddInputCharacter(static_cast(ch));
+ }
+ }
+}
+
+void ImGuiModule::NewFrame()
+{
+ ImGui_Impl_NewFrame();
+
+ ImGuiIO& io = ImGui::GetIO();
+ KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!");
+
+ // Setup display size (every frame to accommodate for window resizing)
+ Size display_size = Renderer::Instance().GetOutputSize();
+ io.DisplaySize = ImVec2(display_size.x, display_size.y);
+
+ ImGui::NewFrame();
+}
+
+void ImGuiModule::Render()
+{
+ ImGui::Render();
+
+ ImGui_Impl_RenderDrawData(ImGui::GetDrawData());
+}
+
+void ImGuiModule::UpdateMousePos()
+{
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by
+ // user)
+ if (io.WantSetMousePos)
+ {
+ POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
+ ::ClientToScreen(target_window_, &pos);
+ ::SetCursorPos(pos.x, pos.y);
+ }
+
+ Point pos = Input::Instance().GetMousePos();
+ io.MousePos = ImVec2(pos.x, pos.y);
+}
+
+void ImGuiModule::UpdateMouseCursor()
+{
+ if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
+ return;
+
+ CursorType cursor = CursorType::Arrow;
+ switch (ImGui::GetMouseCursor())
+ {
+ case ImGuiMouseCursor_Arrow:
+ cursor = CursorType::Arrow;
+ break;
+ case ImGuiMouseCursor_TextInput:
+ cursor = CursorType::TextInput;
+ break;
+ case ImGuiMouseCursor_ResizeAll:
+ cursor = CursorType::SizeAll;
+ break;
+ case ImGuiMouseCursor_ResizeEW:
+ cursor = CursorType::SizeWE;
+ break;
+ case ImGuiMouseCursor_ResizeNS:
+ cursor = CursorType::SizeNS;
+ break;
+ case ImGuiMouseCursor_ResizeNESW:
+ cursor = CursorType::SizeNESW;
+ break;
+ case ImGuiMouseCursor_ResizeNWSE:
+ cursor = CursorType::SizeNWSE;
+ break;
+ case ImGuiMouseCursor_Hand:
+ cursor = CursorType::Hand;
+ break;
+ }
+
+ Window::Instance().SetCursor(cursor);
+}
+
+} // namespace imgui
+} // namespace kiwano
diff --git a/src/kiwano-imgui/ImGuiModule.h b/src/kiwano-imgui/ImGuiModule.h
index d609edc8..33a2a2f5 100644
--- a/src/kiwano-imgui/ImGuiModule.h
+++ b/src/kiwano-imgui/ImGuiModule.h
@@ -1,15 +1,15 @@
// 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
@@ -24,46 +24,46 @@
namespace kiwano
{
- namespace imgui
- {
- /**
- * \~chinese
- * @brief ImGui模块
- */
- class ImGuiModule
- : public Singleton
- , public RenderComponent
- , public UpdateComponent
- , public EventComponent
- {
- friend Singleton;
+namespace imgui
+{
+/**
+ * \~chinese
+ * @brief ImGui模块
+ */
+class ImGuiModule
+ : public Singleton
+ , public RenderComponent
+ , public UpdateComponent
+ , public EventComponent
+{
+ friend Singleton;
- public:
- ImGuiModule();
+public:
+ ImGuiModule();
- void SetupComponent() override;
+ void SetupComponent() override;
- void DestroyComponent() override;
+ void DestroyComponent() override;
- void BeforeRender() override;
+ void BeforeRender() override;
- void AfterRender() override;
+ void AfterRender() override;
- void HandleEvent(Event* evt) override;
+ void HandleEvent(Event* evt) override;
- void OnUpdate(Duration dt) override;
+ void OnUpdate(Duration dt) override;
- private:
- void NewFrame();
+private:
+ void NewFrame();
- void Render();
+ void Render();
- void UpdateMousePos();
+ void UpdateMousePos();
- void UpdateMouseCursor();
+ void UpdateMouseCursor();
- private:
- WindowHandle target_window_;
- };
- }
-}
+private:
+ WindowHandle target_window_;
+};
+} // namespace imgui
+} // namespace kiwano
diff --git a/src/kiwano-imgui/imgui_impl.h b/src/kiwano-imgui/imgui_impl.h
index 72fb88cf..0402bcd5 100644
--- a/src/kiwano-imgui/imgui_impl.h
+++ b/src/kiwano-imgui/imgui_impl.h
@@ -8,25 +8,62 @@
#include
-inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer) { return ImGui_ImplDX11_Init(renderer.GetD3DDeviceResources()->GetDevice(), renderer.GetD3DDeviceResources()->GetDeviceContext()); }
-inline void ImGui_Impl_Shutdown() { ImGui_ImplDX11_Shutdown(); }
-inline void ImGui_Impl_NewFrame() { ImGui_ImplDX11_NewFrame(); }
-inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX11_RenderDrawData(draw_data); }
+inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer)
+{
+ return ImGui_ImplDX11_Init(renderer.GetD3DDeviceResources()->GetDevice(),
+ renderer.GetD3DDeviceResources()->GetDeviceContext());
+}
+inline void ImGui_Impl_Shutdown()
+{
+ ImGui_ImplDX11_Shutdown();
+}
+inline void ImGui_Impl_NewFrame()
+{
+ ImGui_ImplDX11_NewFrame();
+}
+inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data)
+{
+ ImGui_ImplDX11_RenderDrawData(draw_data);
+}
-inline void ImGui_Impl_InvalidateDeviceObjects() { ImGui_ImplDX11_InvalidateDeviceObjects(); }
-inline bool ImGui_Impl_CreateDeviceObjects() { return ImGui_ImplDX11_CreateDeviceObjects(); }
+inline void ImGui_Impl_InvalidateDeviceObjects()
+{
+ ImGui_ImplDX11_InvalidateDeviceObjects();
+}
+inline bool ImGui_Impl_CreateDeviceObjects()
+{
+ return ImGui_ImplDX11_CreateDeviceObjects();
+}
#else
#include
-inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer) { return ImGui_ImplDX10_Init(renderer.GetD3DDeviceResources()->GetDevice()); }
-inline void ImGui_Impl_Shutdown() { ImGui_ImplDX10_Shutdown(); }
-inline void ImGui_Impl_NewFrame() { ImGui_ImplDX10_NewFrame(); }
-inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX10_RenderDrawData(draw_data); }
+inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer)
+{
+ return ImGui_ImplDX10_Init(renderer.GetD3DDeviceResources()->GetDevice());
+}
+inline void ImGui_Impl_Shutdown()
+{
+ ImGui_ImplDX10_Shutdown();
+}
+inline void ImGui_Impl_NewFrame()
+{
+ ImGui_ImplDX10_NewFrame();
+}
+inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data)
+{
+ ImGui_ImplDX10_RenderDrawData(draw_data);
+}
-inline void ImGui_Impl_InvalidateDeviceObjects() { ImGui_ImplDX10_InvalidateDeviceObjects(); }
-inline bool ImGui_Impl_CreateDeviceObjects() { return ImGui_ImplDX10_CreateDeviceObjects(); }
+inline void ImGui_Impl_InvalidateDeviceObjects()
+{
+ ImGui_ImplDX10_InvalidateDeviceObjects();
+}
+inline bool ImGui_Impl_CreateDeviceObjects()
+{
+ return ImGui_ImplDX10_CreateDeviceObjects();
+}
#endif
diff --git a/src/kiwano-imgui/imgui_impl_dx10.cpp b/src/kiwano-imgui/imgui_impl_dx10.cpp
index 8c0221be..78eedecf 100644
--- a/src/kiwano-imgui/imgui_impl_dx10.cpp
+++ b/src/kiwano-imgui/imgui_impl_dx10.cpp
@@ -3,40 +3,41 @@
#include
// DirectX
-#include
-#include
#include
+#include
#include
+#include
#ifdef _MSC_VER
-#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
+#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
#endif
// DirectX data
-static ID3D10Device* g_pd3dDevice = NULL;
-static IDXGIFactory* g_pFactory = NULL;
-static ID3D10Buffer* g_pVB = NULL;
-static ID3D10Buffer* g_pIB = NULL;
-static ID3D10Blob* g_pVertexShaderBlob = NULL;
-static ID3D10VertexShader* g_pVertexShader = NULL;
-static ID3D10InputLayout* g_pInputLayout = NULL;
-static ID3D10Buffer* g_pVertexConstantBuffer = NULL;
-static ID3D10Blob* g_pPixelShaderBlob = NULL;
-static ID3D10PixelShader* g_pPixelShader = NULL;
-static ID3D10SamplerState* g_pFontSampler = NULL;
-static ID3D10ShaderResourceView*g_pFontTextureView = NULL;
-static ID3D10RasterizerState* g_pRasterizerState = NULL;
-static ID3D10BlendState* g_pBlendState = NULL;
-static ID3D10DepthStencilState* g_pDepthStencilState = NULL;
-static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
+static ID3D10Device* g_pd3dDevice = NULL;
+static IDXGIFactory* g_pFactory = NULL;
+static ID3D10Buffer* g_pVB = NULL;
+static ID3D10Buffer* g_pIB = NULL;
+static ID3D10Blob* g_pVertexShaderBlob = NULL;
+static ID3D10VertexShader* g_pVertexShader = NULL;
+static ID3D10InputLayout* g_pInputLayout = NULL;
+static ID3D10Buffer* g_pVertexConstantBuffer = NULL;
+static ID3D10Blob* g_pPixelShaderBlob = NULL;
+static ID3D10PixelShader* g_pPixelShader = NULL;
+static ID3D10SamplerState* g_pFontSampler = NULL;
+static ID3D10ShaderResourceView* g_pFontTextureView = NULL;
+static ID3D10RasterizerState* g_pRasterizerState = NULL;
+static ID3D10BlendState* g_pBlendState = NULL;
+static ID3D10DepthStencilState* g_pDepthStencilState = NULL;
+static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
struct VERTEX_CONSTANT_BUFFER
{
- float mvp[4][4];
+ float mvp[4][4];
};
// Render Function
-// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
+// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from
+// your main loop)
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
{
ID3D10Device* ctx = g_pd3dDevice;
@@ -44,28 +45,36 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
// Create and grow vertex/index buffers if needed
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
{
- if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
+ if (g_pVB)
+ {
+ g_pVB->Release();
+ g_pVB = NULL;
+ }
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D10_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
- desc.Usage = D3D10_USAGE_DYNAMIC;
- desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
- desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
+ desc.Usage = D3D10_USAGE_DYNAMIC;
+ desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
+ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
- desc.MiscFlags = 0;
+ desc.MiscFlags = 0;
if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0)
return;
}
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
{
- if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
+ if (g_pIB)
+ {
+ g_pIB->Release();
+ g_pIB = NULL;
+ }
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D10_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
- desc.Usage = D3D10_USAGE_DYNAMIC;
- desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
- desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
+ desc.Usage = D3D10_USAGE_DYNAMIC;
+ desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
+ desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0)
return;
@@ -73,7 +82,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
// Copy and convert all vertices into a single contiguous buffer
ImDrawVert* vtx_dst = NULL;
- ImDrawIdx* idx_dst = NULL;
+ ImDrawIdx* idx_dst = NULL;
g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
for (int n = 0; n < draw_data->CmdListsCount; n++)
@@ -88,48 +97,49 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
g_pIB->Unmap();
// Setup orthographic projection matrix into our constant buffer
- // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to
+ // draw_data->DisplayPos+data_data->DisplaySize (bottom right).
{
void* mapped_resource;
if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
return;
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource;
- float L = draw_data->DisplayPos.x;
- float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
- float T = draw_data->DisplayPos.y;
- float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
- float mvp[4][4] =
- {
- { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
- { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.5f, 0.0f },
- { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
+ float L = draw_data->DisplayPos.x;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
+ float T = draw_data->DisplayPos.y;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
+ float mvp[4][4] = {
+ { 2.0f / (R - L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f / (T - B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.5f, 0.0f },
+ { (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f },
};
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
g_pVertexConstantBuffer->Unmap();
}
- // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
+ // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and
+ // verbose. Close your eyes!)
struct BACKUP_DX10_STATE
{
- UINT ScissorRectsCount, ViewportsCount;
- D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
- D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
- ID3D10RasterizerState* RS;
- ID3D10BlendState* BlendState;
- FLOAT BlendFactor[4];
- UINT SampleMask;
- UINT StencilRef;
- ID3D10DepthStencilState* DepthStencilState;
- ID3D10ShaderResourceView* PSShaderResource;
- ID3D10SamplerState* PSSampler;
- ID3D10PixelShader* PS;
- ID3D10VertexShader* VS;
- D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology;
- ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
- UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
- DXGI_FORMAT IndexBufferFormat;
- ID3D10InputLayout* InputLayout;
+ UINT ScissorRectsCount, ViewportsCount;
+ D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ ID3D10RasterizerState* RS;
+ ID3D10BlendState* BlendState;
+ FLOAT BlendFactor[4];
+ UINT SampleMask;
+ UINT StencilRef;
+ ID3D10DepthStencilState* DepthStencilState;
+ ID3D10ShaderResourceView* PSShaderResource;
+ ID3D10SamplerState* PSSampler;
+ ID3D10PixelShader* PS;
+ ID3D10VertexShader* VS;
+ D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology;
+ ID3D10Buffer * IndexBuffer, *VertexBuffer, *VSConstantBuffer;
+ UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
+ DXGI_FORMAT IndexBufferFormat;
+ ID3D10InputLayout* InputLayout;
};
BACKUP_DX10_STATE old;
old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
@@ -151,8 +161,8 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
// Setup viewport
D3D10_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D10_VIEWPORT));
- vp.Width = (UINT)draw_data->DisplaySize.x;
- vp.Height = (UINT)draw_data->DisplaySize.y;
+ vp.Width = (UINT)draw_data->DisplaySize.x;
+ vp.Height = (UINT)draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
@@ -177,9 +187,9 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ctx->RSSetState(g_pRasterizerState);
// Render command lists
- int vtx_offset = 0;
- int idx_offset = 0;
- ImVec2 pos = draw_data->DisplayPos;
+ int vtx_offset = 0;
+ int idx_offset = 0;
+ ImVec2 pos = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -194,7 +204,8 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
else
{
// Apply scissor/clipping rectangle
- const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y), (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y)};
+ const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y),
+ (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw
@@ -210,55 +221,77 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
// Restore modified DX state
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
- ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
- ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
- ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
- ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
- ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
- ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release();
- ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release();
- ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
+ ctx->RSSetState(old.RS);
+ if (old.RS)
+ old.RS->Release();
+ ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask);
+ if (old.BlendState)
+ old.BlendState->Release();
+ ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef);
+ if (old.DepthStencilState)
+ old.DepthStencilState->Release();
+ ctx->PSSetShaderResources(0, 1, &old.PSShaderResource);
+ if (old.PSShaderResource)
+ old.PSShaderResource->Release();
+ ctx->PSSetSamplers(0, 1, &old.PSSampler);
+ if (old.PSSampler)
+ old.PSSampler->Release();
+ ctx->PSSetShader(old.PS);
+ if (old.PS)
+ old.PS->Release();
+ ctx->VSSetShader(old.VS);
+ if (old.VS)
+ old.VS->Release();
+ ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer);
+ if (old.VSConstantBuffer)
+ old.VSConstantBuffer->Release();
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
- ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
- ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
- ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
+ ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset);
+ if (old.IndexBuffer)
+ old.IndexBuffer->Release();
+ ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
+ if (old.VertexBuffer)
+ old.VertexBuffer->Release();
+ ctx->IASetInputLayout(old.InputLayout);
+ if (old.InputLayout)
+ old.InputLayout->Release();
}
static void ImGui_ImplDX10_CreateFontsTexture()
{
// Build texture atlas
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
- int width, height;
+ int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Upload texture to graphics system
{
D3D10_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.Width = width;
- desc.Height = height;
- desc.MipLevels = 1;
- desc.ArraySize = 1;
- desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
- desc.Usage = D3D10_USAGE_DEFAULT;
- desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
+ desc.Usage = D3D10_USAGE_DEFAULT;
+ desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
- ID3D10Texture2D *pTexture = NULL;
+ ID3D10Texture2D* pTexture = NULL;
D3D10_SUBRESOURCE_DATA subResource;
- subResource.pSysMem = pixels;
- subResource.SysMemPitch = desc.Width * 4;
+ subResource.pSysMem = pixels;
+ subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
// Create texture view
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
ZeroMemory(&srv_desc, sizeof(srv_desc));
- srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
- srv_desc.Texture2D.MipLevels = desc.MipLevels;
+ srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
+ srv_desc.Texture2D.MipLevels = desc.MipLevels;
srv_desc.Texture2D.MostDetailedMip = 0;
g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView);
pTexture->Release();
@@ -271,35 +304,36 @@ static void ImGui_ImplDX10_CreateFontsTexture()
{
D3D10_SAMPLER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
- desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP;
- desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP;
- desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP;
- desc.MipLODBias = 0.f;
+ desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
+ desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP;
+ desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP;
+ desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP;
+ desc.MipLODBias = 0.f;
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
- desc.MinLOD = 0.f;
- desc.MaxLOD = 0.f;
+ desc.MinLOD = 0.f;
+ desc.MaxLOD = 0.f;
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
}
}
-bool ImGui_ImplDX10_CreateDeviceObjects()
+bool ImGui_ImplDX10_CreateDeviceObjects()
{
if (!g_pd3dDevice)
return false;
if (g_pFontSampler)
ImGui_ImplDX10_InvalidateDeviceObjects();
- // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
- // If you would like to use this DX10 sample code but remove this dependency you can:
- // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
- // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
+ // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of
+ // d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) If you would like to use this DX10 sample code but remove this
+ // dependency you can:
+ // 1) compile once, save the compiled shader blobs into a file or source code and pass them to
+ // CreateVertexShader()/CreatePixelShader() [preferred solution] 2) use code to detect any version of the DLL and
+ // grab a pointer to D3DCompile from the DLL.
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
// Create the vertex shader
{
- static const char* vertexShader =
- "cbuffer vertexBuffer : register(b0) \
+ static const char* vertexShader = "cbuffer vertexBuffer : register(b0) \
{\
float4x4 ProjectionMatrix; \
};\
@@ -326,38 +360,46 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
return output;\
}";
- D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL);
- if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob,
+ NULL);
+ if (g_pVertexShaderBlob
+ == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
+ // char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
return false;
- if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pVertexShader) != S_OK)
+ if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(),
+ g_pVertexShaderBlob->GetBufferSize(), &g_pVertexShader)
+ != S_OK)
return false;
// Create the input layout
- D3D10_INPUT_ELEMENT_DESC local_layout[] =
- {
- { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 },
- { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 },
- { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 },
+ D3D10_INPUT_ELEMENT_DESC local_layout[] = {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA,
+ 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA,
+ 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA,
+ 0 },
};
- if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
+ if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(),
+ g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout)
+ != S_OK)
return false;
// Create the constant buffer
{
D3D10_BUFFER_DESC desc;
- desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
- desc.Usage = D3D10_USAGE_DYNAMIC;
- desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
+ desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
+ desc.Usage = D3D10_USAGE_DYNAMIC;
+ desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
- desc.MiscFlags = 0;
+ desc.MiscFlags = 0;
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
}
}
// Create the pixel shader
{
- static const char* pixelShader =
- "struct PS_INPUT\
+ static const char* pixelShader = "struct PS_INPUT\
{\
float4 pos : SV_POSITION;\
float4 col : COLOR0;\
@@ -372,10 +414,15 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
return out_col; \
}";
- D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL);
- if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob,
+ NULL);
+ if (g_pPixelShaderBlob
+ == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
+ // char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
return false;
- if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), &g_pPixelShader) != S_OK)
+ if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(),
+ g_pPixelShaderBlob->GetBufferSize(), &g_pPixelShader)
+ != S_OK)
return false;
}
@@ -383,14 +430,14 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
{
D3D10_BLEND_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.AlphaToCoverageEnable = false;
- desc.BlendEnable[0] = true;
- desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
- desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
- desc.BlendOp = D3D10_BLEND_OP_ADD;
- desc.SrcBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
- desc.DestBlendAlpha = D3D10_BLEND_ZERO;
- desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+ desc.AlphaToCoverageEnable = false;
+ desc.BlendEnable[0] = true;
+ desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
+ desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
+ desc.BlendOp = D3D10_BLEND_OP_ADD;
+ desc.SrcBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
+ desc.DestBlendAlpha = D3D10_BLEND_ZERO;
+ desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
}
@@ -399,9 +446,9 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
{
D3D10_RASTERIZER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.FillMode = D3D10_FILL_SOLID;
- desc.CullMode = D3D10_CULL_NONE;
- desc.ScissorEnable = true;
+ desc.FillMode = D3D10_FILL_SOLID;
+ desc.CullMode = D3D10_CULL_NONE;
+ desc.ScissorEnable = true;
desc.DepthClipEnable = true;
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
}
@@ -410,13 +457,14 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
{
D3D10_DEPTH_STENCIL_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.DepthEnable = false;
- desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
- desc.DepthFunc = D3D10_COMPARISON_ALWAYS;
- desc.StencilEnable = false;
- desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
+ desc.DepthEnable = false;
+ desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
+ desc.DepthFunc = D3D10_COMPARISON_ALWAYS;
+ desc.StencilEnable = false;
+ desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp =
+ D3D10_STENCIL_OP_KEEP;
desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
- desc.BackFace = desc.FrontFace;
+ desc.BackFace = desc.FrontFace;
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
}
@@ -425,46 +473,101 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
return true;
}
-void ImGui_ImplDX10_InvalidateDeviceObjects()
+void ImGui_ImplDX10_InvalidateDeviceObjects()
{
if (!g_pd3dDevice)
return;
- if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
- if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
- if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
- if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
+ if (g_pFontSampler)
+ {
+ g_pFontSampler->Release();
+ g_pFontSampler = NULL;
+ }
+ if (g_pFontTextureView)
+ {
+ g_pFontTextureView->Release();
+ g_pFontTextureView = NULL;
+ ImGui::GetIO().Fonts->TexID = NULL;
+ } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
+ if (g_pIB)
+ {
+ g_pIB->Release();
+ g_pIB = NULL;
+ }
+ if (g_pVB)
+ {
+ g_pVB->Release();
+ g_pVB = NULL;
+ }
- if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
- if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
- if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
- if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
- if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
- if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
- if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
- if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
- if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }
+ if (g_pBlendState)
+ {
+ g_pBlendState->Release();
+ g_pBlendState = NULL;
+ }
+ if (g_pDepthStencilState)
+ {
+ g_pDepthStencilState->Release();
+ g_pDepthStencilState = NULL;
+ }
+ if (g_pRasterizerState)
+ {
+ g_pRasterizerState->Release();
+ g_pRasterizerState = NULL;
+ }
+ if (g_pPixelShader)
+ {
+ g_pPixelShader->Release();
+ g_pPixelShader = NULL;
+ }
+ if (g_pPixelShaderBlob)
+ {
+ g_pPixelShaderBlob->Release();
+ g_pPixelShaderBlob = NULL;
+ }
+ if (g_pVertexConstantBuffer)
+ {
+ g_pVertexConstantBuffer->Release();
+ g_pVertexConstantBuffer = NULL;
+ }
+ if (g_pInputLayout)
+ {
+ g_pInputLayout->Release();
+ g_pInputLayout = NULL;
+ }
+ if (g_pVertexShader)
+ {
+ g_pVertexShader->Release();
+ g_pVertexShader = NULL;
+ }
+ if (g_pVertexShaderBlob)
+ {
+ g_pVertexShaderBlob->Release();
+ g_pVertexShaderBlob = NULL;
+ }
}
-bool ImGui_ImplDX10_Init(ID3D10Device* device)
+bool ImGui_ImplDX10_Init(ID3D10Device* device)
{
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx10";
// Get factory from device
- IDXGIDevice* pDXGIDevice = NULL;
+ IDXGIDevice* pDXGIDevice = NULL;
IDXGIAdapter* pDXGIAdapter = NULL;
- IDXGIFactory* pFactory = NULL;
+ IDXGIFactory* pFactory = NULL;
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
{
g_pd3dDevice = device;
- g_pFactory = pFactory;
+ g_pFactory = pFactory;
}
- if (pDXGIDevice) pDXGIDevice->Release();
- if (pDXGIAdapter) pDXGIAdapter->Release();
+ if (pDXGIDevice)
+ pDXGIDevice->Release();
+ if (pDXGIAdapter)
+ pDXGIAdapter->Release();
return true;
}
@@ -472,7 +575,11 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device)
void ImGui_ImplDX10_Shutdown()
{
ImGui_ImplDX10_InvalidateDeviceObjects();
- if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
+ if (g_pFactory)
+ {
+ g_pFactory->Release();
+ g_pFactory = NULL;
+ }
g_pd3dDevice = NULL;
}
diff --git a/src/kiwano-imgui/imgui_impl_dx10.h b/src/kiwano-imgui/imgui_impl_dx10.h
index 26fdb0c1..7fd26e53 100644
--- a/src/kiwano-imgui/imgui_impl_dx10.h
+++ b/src/kiwano-imgui/imgui_impl_dx10.h
@@ -7,13 +7,13 @@
struct ID3D10Device;
-IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device);
-IMGUI_IMPL_API void ImGui_ImplDX10_Shutdown();
-IMGUI_IMPL_API void ImGui_ImplDX10_NewFrame();
-IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
+IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device);
+IMGUI_IMPL_API void ImGui_ImplDX10_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplDX10_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state.
-IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
-IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
+IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
+IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
#endif
diff --git a/src/kiwano-imgui/imgui_impl_dx11.cpp b/src/kiwano-imgui/imgui_impl_dx11.cpp
index 470f914b..5fccb34d 100644
--- a/src/kiwano-imgui/imgui_impl_dx11.cpp
+++ b/src/kiwano-imgui/imgui_impl_dx11.cpp
@@ -3,40 +3,41 @@
#include
// DirectX
-#include
#include
#include
+#include
#ifdef _MSC_VER
-#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
+#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
#endif
// DirectX data
-static ID3D11Device* g_pd3dDevice = NULL;
-static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
-static IDXGIFactory* g_pFactory = NULL;
-static ID3D11Buffer* g_pVB = NULL;
-static ID3D11Buffer* g_pIB = NULL;
-static ID3D10Blob* g_pVertexShaderBlob = NULL;
-static ID3D11VertexShader* g_pVertexShader = NULL;
-static ID3D11InputLayout* g_pInputLayout = NULL;
-static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
-static ID3D10Blob* g_pPixelShaderBlob = NULL;
-static ID3D11PixelShader* g_pPixelShader = NULL;
-static ID3D11SamplerState* g_pFontSampler = NULL;
-static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
-static ID3D11RasterizerState* g_pRasterizerState = NULL;
-static ID3D11BlendState* g_pBlendState = NULL;
-static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
-static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
+static ID3D11Device* g_pd3dDevice = NULL;
+static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
+static IDXGIFactory* g_pFactory = NULL;
+static ID3D11Buffer* g_pVB = NULL;
+static ID3D11Buffer* g_pIB = NULL;
+static ID3D10Blob* g_pVertexShaderBlob = NULL;
+static ID3D11VertexShader* g_pVertexShader = NULL;
+static ID3D11InputLayout* g_pInputLayout = NULL;
+static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
+static ID3D10Blob* g_pPixelShaderBlob = NULL;
+static ID3D11PixelShader* g_pPixelShader = NULL;
+static ID3D11SamplerState* g_pFontSampler = NULL;
+static ID3D11ShaderResourceView* g_pFontTextureView = NULL;
+static ID3D11RasterizerState* g_pRasterizerState = NULL;
+static ID3D11BlendState* g_pBlendState = NULL;
+static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
+static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
struct VERTEX_CONSTANT_BUFFER
{
- float mvp[4][4];
+ float mvp[4][4];
};
// Render Function
-// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
+// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from
+// your main loop)
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
{
ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
@@ -44,27 +45,35 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
// Create and grow vertex/index buffers if needed
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
{
- if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
+ if (g_pVB)
+ {
+ g_pVB->Release();
+ g_pVB = NULL;
+ }
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
- desc.Usage = D3D11_USAGE_DYNAMIC;
- desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
- desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
+ desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- desc.MiscFlags = 0;
+ desc.MiscFlags = 0;
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
return;
}
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
{
- if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
+ if (g_pIB)
+ {
+ g_pIB->Release();
+ g_pIB = NULL;
+ }
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
- desc.Usage = D3D11_USAGE_DYNAMIC;
- desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
- desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
+ desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
return;
@@ -77,7 +86,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
return;
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
- ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
+ ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -90,50 +99,51 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ctx->Unmap(g_pIB, 0);
// Setup orthographic projection matrix into our constant buffer
- // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to
+ // draw_data->DisplayPos+data_data->DisplaySize (bottom right).
{
D3D11_MAPPED_SUBRESOURCE mapped_resource;
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
return;
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
- float L = draw_data->DisplayPos.x;
- float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
- float T = draw_data->DisplayPos.y;
- float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
- float mvp[4][4] =
- {
- { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
- { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.5f, 0.0f },
- { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
+ float L = draw_data->DisplayPos.x;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
+ float T = draw_data->DisplayPos.y;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
+ float mvp[4][4] = {
+ { 2.0f / (R - L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f / (T - B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.5f, 0.0f },
+ { (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f },
};
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
ctx->Unmap(g_pVertexConstantBuffer, 0);
}
- // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
+ // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and
+ // verbose. Close your eyes!)
struct BACKUP_DX11_STATE
{
- UINT ScissorRectsCount, ViewportsCount;
- D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
- D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
- ID3D11RasterizerState* RS;
- ID3D11BlendState* BlendState;
- FLOAT BlendFactor[4];
- UINT SampleMask;
- UINT StencilRef;
- ID3D11DepthStencilState* DepthStencilState;
- ID3D11ShaderResourceView* PSShaderResource;
- ID3D11SamplerState* PSSampler;
- ID3D11PixelShader* PS;
- ID3D11VertexShader* VS;
- UINT PSInstancesCount, VSInstancesCount;
- ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
- D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
- ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
- UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
- DXGI_FORMAT IndexBufferFormat;
- ID3D11InputLayout* InputLayout;
+ UINT ScissorRectsCount, ViewportsCount;
+ D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ ID3D11RasterizerState* RS;
+ ID3D11BlendState* BlendState;
+ FLOAT BlendFactor[4];
+ UINT SampleMask;
+ UINT StencilRef;
+ ID3D11DepthStencilState* DepthStencilState;
+ ID3D11ShaderResourceView* PSShaderResource;
+ ID3D11SamplerState* PSSampler;
+ ID3D11PixelShader* PS;
+ ID3D11VertexShader* VS;
+ UINT PSInstancesCount, VSInstancesCount;
+ ID3D11ClassInstance *PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
+ D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
+ ID3D11Buffer * IndexBuffer, *VertexBuffer, *VSConstantBuffer;
+ UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
+ DXGI_FORMAT IndexBufferFormat;
+ ID3D11InputLayout* InputLayout;
};
BACKUP_DX11_STATE old;
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
@@ -156,8 +166,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
// Setup viewport
D3D11_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
- vp.Width = draw_data->DisplaySize.x;
- vp.Height = draw_data->DisplaySize.y;
+ vp.Width = draw_data->DisplaySize.x;
+ vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
@@ -182,9 +192,9 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ctx->RSSetState(g_pRasterizerState);
// Render command lists
- int vtx_offset = 0;
- int idx_offset = 0;
- ImVec2 pos = draw_data->DisplayPos;
+ int vtx_offset = 0;
+ int idx_offset = 0;
+ ImVec2 pos = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -199,7 +209,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
else
{
// Apply scissor/clipping rectangle
- const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y), (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
+ const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - pos.x), (LONG)(pcmd->ClipRect.y - pos.y),
+ (LONG)(pcmd->ClipRect.z - pos.x), (LONG)(pcmd->ClipRect.w - pos.y) };
ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw
@@ -215,61 +226,87 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
// Restore modified DX state
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
- ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
- ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
- ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
- ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
- ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
- ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
- for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
- ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
- ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
- for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
+ ctx->RSSetState(old.RS);
+ if (old.RS)
+ old.RS->Release();
+ ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask);
+ if (old.BlendState)
+ old.BlendState->Release();
+ ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef);
+ if (old.DepthStencilState)
+ old.DepthStencilState->Release();
+ ctx->PSSetShaderResources(0, 1, &old.PSShaderResource);
+ if (old.PSShaderResource)
+ old.PSShaderResource->Release();
+ ctx->PSSetSamplers(0, 1, &old.PSSampler);
+ if (old.PSSampler)
+ old.PSSampler->Release();
+ ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount);
+ if (old.PS)
+ old.PS->Release();
+ for (UINT i = 0; i < old.PSInstancesCount; i++)
+ if (old.PSInstances[i])
+ old.PSInstances[i]->Release();
+ ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount);
+ if (old.VS)
+ old.VS->Release();
+ ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer);
+ if (old.VSConstantBuffer)
+ old.VSConstantBuffer->Release();
+ for (UINT i = 0; i < old.VSInstancesCount; i++)
+ if (old.VSInstances[i])
+ old.VSInstances[i]->Release();
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
- ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
- ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
- ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
+ ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset);
+ if (old.IndexBuffer)
+ old.IndexBuffer->Release();
+ ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
+ if (old.VertexBuffer)
+ old.VertexBuffer->Release();
+ ctx->IASetInputLayout(old.InputLayout);
+ if (old.InputLayout)
+ old.InputLayout->Release();
}
static void ImGui_ImplDX11_CreateFontsTexture()
{
// Build texture atlas
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
- int width, height;
+ int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Upload texture to graphics system
{
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.Width = width;
- desc.Height = height;
- desc.MipLevels = 1;
- desc.ArraySize = 1;
- desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
- ID3D11Texture2D *pTexture = NULL;
+ ID3D11Texture2D* pTexture = NULL;
D3D11_SUBRESOURCE_DATA subResource;
- subResource.pSysMem = pixels;
- subResource.SysMemPitch = desc.Width * 4;
+ subResource.pSysMem = pixels;
+ subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
- g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
+ g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
if (pTexture)
{
// Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
- srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- srvDesc.Texture2D.MipLevels = desc.MipLevels;
+ srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
- g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
+ g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
pTexture->Release();
}
@@ -282,35 +319,36 @@ static void ImGui_ImplDX11_CreateFontsTexture()
{
D3D11_SAMPLER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
- desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
- desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
- desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
- desc.MipLODBias = 0.f;
+ desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.MipLODBias = 0.f;
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
- desc.MinLOD = 0.f;
- desc.MaxLOD = 0.f;
+ desc.MinLOD = 0.f;
+ desc.MaxLOD = 0.f;
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
}
}
-bool ImGui_ImplDX11_CreateDeviceObjects()
+bool ImGui_ImplDX11_CreateDeviceObjects()
{
if (!g_pd3dDevice)
return false;
if (g_pFontSampler)
ImGui_ImplDX11_InvalidateDeviceObjects();
- // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
- // If you would like to use this DX11 sample code but remove this dependency you can:
- // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
- // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
+ // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of
+ // d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) If you would like to use this DX11 sample code but remove this
+ // dependency you can:
+ // 1) compile once, save the compiled shader blobs into a file or source code and pass them to
+ // CreateVertexShader()/CreatePixelShader() [preferred solution] 2) use code to detect any version of the DLL and
+ // grab a pointer to D3DCompile from the DLL.
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
// Create the vertex shader
{
- static const char* vertexShader =
- "cbuffer vertexBuffer : register(b0) \
+ static const char* vertexShader = "cbuffer vertexBuffer : register(b0) \
{\
float4x4 ProjectionMatrix; \
};\
@@ -337,38 +375,46 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
return output;\
}";
- D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL);
- if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob,
+ NULL);
+ if (g_pVertexShaderBlob
+ == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
+ // char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
return false;
- if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK)
+ if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(),
+ g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader)
+ != S_OK)
return false;
// Create the input layout
- D3D11_INPUT_ELEMENT_DESC local_layout[] =
- {
- { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ D3D11_INPUT_ELEMENT_DESC local_layout[] = {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA,
+ 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA,
+ 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA,
+ 0 },
};
- if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
+ if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(),
+ g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout)
+ != S_OK)
return false;
// Create the constant buffer
{
D3D11_BUFFER_DESC desc;
- desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
- desc.Usage = D3D11_USAGE_DYNAMIC;
- desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- desc.MiscFlags = 0;
+ desc.MiscFlags = 0;
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
}
}
// Create the pixel shader
{
- static const char* pixelShader =
- "struct PS_INPUT\
+ static const char* pixelShader = "struct PS_INPUT\
{\
float4 pos : SV_POSITION;\
float4 col : COLOR0;\
@@ -383,10 +429,15 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
return out_col; \
}";
- D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL);
- if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob,
+ NULL);
+ if (g_pPixelShaderBlob
+ == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const
+ // char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
return false;
- if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK)
+ if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(),
+ g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader)
+ != S_OK)
return false;
}
@@ -394,14 +445,14 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
{
D3D11_BLEND_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.AlphaToCoverageEnable = false;
- desc.RenderTarget[0].BlendEnable = true;
- desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
- desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
- desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
- desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
- desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
- desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ desc.AlphaToCoverageEnable = false;
+ desc.RenderTarget[0].BlendEnable = true;
+ desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
+ desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
+ desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
}
@@ -410,9 +461,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
{
D3D11_RASTERIZER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.FillMode = D3D11_FILL_SOLID;
- desc.CullMode = D3D11_CULL_NONE;
- desc.ScissorEnable = true;
+ desc.FillMode = D3D11_FILL_SOLID;
+ desc.CullMode = D3D11_CULL_NONE;
+ desc.ScissorEnable = true;
desc.DepthClipEnable = true;
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
}
@@ -421,13 +472,14 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
{
D3D11_DEPTH_STENCIL_DESC desc;
ZeroMemory(&desc, sizeof(desc));
- desc.DepthEnable = false;
- desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
- desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
- desc.StencilEnable = false;
- desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ desc.DepthEnable = false;
+ desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
+ desc.StencilEnable = false;
+ desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp =
+ D3D11_STENCIL_OP_KEEP;
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
- desc.BackFace = desc.FrontFace;
+ desc.BackFace = desc.FrontFace;
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
}
@@ -436,47 +488,102 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
return true;
}
-void ImGui_ImplDX11_InvalidateDeviceObjects()
+void ImGui_ImplDX11_InvalidateDeviceObjects()
{
if (!g_pd3dDevice)
return;
- if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
- if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
- if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
- if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
+ if (g_pFontSampler)
+ {
+ g_pFontSampler->Release();
+ g_pFontSampler = NULL;
+ }
+ if (g_pFontTextureView)
+ {
+ g_pFontTextureView->Release();
+ g_pFontTextureView = NULL;
+ ImGui::GetIO().Fonts->TexID = NULL;
+ } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
+ if (g_pIB)
+ {
+ g_pIB->Release();
+ g_pIB = NULL;
+ }
+ if (g_pVB)
+ {
+ g_pVB->Release();
+ g_pVB = NULL;
+ }
- if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
- if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
- if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
- if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
- if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
- if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
- if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
- if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
- if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }
+ if (g_pBlendState)
+ {
+ g_pBlendState->Release();
+ g_pBlendState = NULL;
+ }
+ if (g_pDepthStencilState)
+ {
+ g_pDepthStencilState->Release();
+ g_pDepthStencilState = NULL;
+ }
+ if (g_pRasterizerState)
+ {
+ g_pRasterizerState->Release();
+ g_pRasterizerState = NULL;
+ }
+ if (g_pPixelShader)
+ {
+ g_pPixelShader->Release();
+ g_pPixelShader = NULL;
+ }
+ if (g_pPixelShaderBlob)
+ {
+ g_pPixelShaderBlob->Release();
+ g_pPixelShaderBlob = NULL;
+ }
+ if (g_pVertexConstantBuffer)
+ {
+ g_pVertexConstantBuffer->Release();
+ g_pVertexConstantBuffer = NULL;
+ }
+ if (g_pInputLayout)
+ {
+ g_pInputLayout->Release();
+ g_pInputLayout = NULL;
+ }
+ if (g_pVertexShader)
+ {
+ g_pVertexShader->Release();
+ g_pVertexShader = NULL;
+ }
+ if (g_pVertexShaderBlob)
+ {
+ g_pVertexShaderBlob->Release();
+ g_pVertexShaderBlob = NULL;
+ }
}
-bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
+bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
{
- ImGuiIO& io = ImGui::GetIO();
+ ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx11";
// Get factory from device
- IDXGIDevice* pDXGIDevice = NULL;
+ IDXGIDevice* pDXGIDevice = NULL;
IDXGIAdapter* pDXGIAdapter = NULL;
- IDXGIFactory* pFactory = NULL;
+ IDXGIFactory* pFactory = NULL;
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
{
- g_pd3dDevice = device;
+ g_pd3dDevice = device;
g_pd3dDeviceContext = device_context;
- g_pFactory = pFactory;
+ g_pFactory = pFactory;
}
- if (pDXGIDevice) pDXGIDevice->Release();
- if (pDXGIAdapter) pDXGIAdapter->Release();
+ if (pDXGIDevice)
+ pDXGIDevice->Release();
+ if (pDXGIAdapter)
+ pDXGIAdapter->Release();
return true;
}
@@ -484,8 +591,12 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
void ImGui_ImplDX11_Shutdown()
{
ImGui_ImplDX11_InvalidateDeviceObjects();
- if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
- g_pd3dDevice = NULL;
+ if (g_pFactory)
+ {
+ g_pFactory->Release();
+ g_pFactory = NULL;
+ }
+ g_pd3dDevice = NULL;
g_pd3dDeviceContext = NULL;
}
diff --git a/src/kiwano-imgui/imgui_impl_dx11.h b/src/kiwano-imgui/imgui_impl_dx11.h
index 4964c00c..e15f79d1 100644
--- a/src/kiwano-imgui/imgui_impl_dx11.h
+++ b/src/kiwano-imgui/imgui_impl_dx11.h
@@ -8,13 +8,13 @@
struct ID3D11Device;
struct ID3D11DeviceContext;
-IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
-IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
-IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
-IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
+IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
+IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state.
-IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
-IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
+IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
+IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
#endif
diff --git a/src/kiwano-imgui/kiwano-imgui.h b/src/kiwano-imgui/kiwano-imgui.h
index 453a1a0c..6f8a1ab2 100644
--- a/src/kiwano-imgui/kiwano-imgui.h
+++ b/src/kiwano-imgui/kiwano-imgui.h
@@ -1,15 +1,15 @@
// 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
diff --git a/src/kiwano-network/HttpClient.cpp b/src/kiwano-network/HttpClient.cpp
index 65b0305d..b98a6f50 100644
--- a/src/kiwano-network/HttpClient.cpp
+++ b/src/kiwano-network/HttpClient.cpp
@@ -1,15 +1,15 @@
// 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
@@ -18,364 +18,338 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include
+#include <3rd-party/curl/curl.h> // CURL
#include
-
+#include
#include
#include
-#include
-
#include
#include
-#include <3rd-party/curl/curl.h> // CURL
+#include
namespace
{
- using namespace kiwano;
- using namespace kiwano::network;
+using namespace kiwano;
+using namespace kiwano::network;
- uint32_t write_data(void* buffer, uint32_t size, uint32_t nmemb, void* userp)
- {
- ByteString* recv_buffer = (ByteString*)userp;
- uint32_t total = size * nmemb;
+uint32_t write_data(void* buffer, uint32_t size, uint32_t nmemb, void* userp)
+{
+ ByteString* recv_buffer = (ByteString*)userp;
+ uint32_t total = size * nmemb;
- // add data to the end of recv_buffer
- // write data maybe called more than once in a single request
- recv_buffer->append((char*)buffer, total);
+ // add data to the end of recv_buffer
+ // write data maybe called more than once in a single request
+ recv_buffer->append((char*)buffer, total);
- return total;
- }
-
- ByteString convert_to_utf8(String const& str)
- {
- std::wstring_convert> utf8_conv;
- ByteString result;
-
- try
- {
- result = utf8_conv.to_bytes(str.c_str());
- }
- catch (std::range_error&)
- {
- // bad conversion
- result = WideToMultiByte(str);
- }
- return result;
- }
-
- String convert_from_utf8(ByteString const& str)
- {
- oc::string_convert> utf8_conv;
- String result;
-
- try
- {
- result = utf8_conv.from_bytes(str);
- }
- catch (std::range_error&)
- {
- // bad conversion
- result = MultiByteToWide(str);
- }
- return result;
- }
-
- class Curl
- {
- public:
- Curl()
- : curl_(curl_easy_init())
- , curl_headers_(nullptr)
- {
- }
-
- ~Curl()
- {
- if (curl_)
- {
- curl_easy_cleanup(curl_);
- curl_ = nullptr;
- }
-
- if (curl_headers_)
- {
- curl_slist_free_all(curl_headers_);
- curl_headers_ = nullptr;
- }
- }
-
- bool Init(HttpClient* client, Vector const& headers, ByteString const& url, ByteString* response_data, ByteString* response_header, char* error_buffer)
- {
- if (!SetOption(CURLOPT_ERRORBUFFER, error_buffer))
- return false;
- if (!SetOption(CURLOPT_TIMEOUT, client->GetTimeoutForRead()))
- return false;
- if (!SetOption(CURLOPT_CONNECTTIMEOUT, client->GetTimeoutForConnect()))
- return false;
-
- const auto ssl_ca_file = wide_to_string(client->GetSSLVerification());
- if (ssl_ca_file.empty()) {
- if (!SetOption(CURLOPT_SSL_VERIFYPEER, 0L))
- return false;
- if (!SetOption(CURLOPT_SSL_VERIFYHOST, 0L))
- return false;
- }
- else {
- if (!SetOption(CURLOPT_SSL_VERIFYPEER, 1L))
- return false;
- if (!SetOption(CURLOPT_SSL_VERIFYHOST, 2L))
- return false;
- if (!SetOption(CURLOPT_CAINFO, ssl_ca_file.c_str()))
- return false;
- }
-
- if (!SetOption(CURLOPT_NOSIGNAL, 1L))
- return false;
- if (!SetOption(CURLOPT_ACCEPT_ENCODING, ""))
- return false;
-
- // set request headers
- if (!headers.empty())
- {
- for (const auto& header : headers)
- {
- curl_headers_ = curl_slist_append(curl_headers_, header.c_str());
- }
- if (!SetOption(CURLOPT_HTTPHEADER, curl_headers_))
- return false;
- }
-
- return SetOption(CURLOPT_URL, url.c_str())
- && SetOption(CURLOPT_WRITEFUNCTION, write_data)
- && SetOption(CURLOPT_WRITEDATA, response_data)
- && SetOption(CURLOPT_HEADERFUNCTION, write_data)
- && SetOption(CURLOPT_HEADERDATA, response_header);
- }
-
- bool Perform(long* response_code)
- {
- if (CURLE_OK != curl_easy_perform(curl_))
- return false;
-
- CURLcode code = curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, response_code);
- return code == CURLE_OK && (*response_code >= 200 && *response_code < 300);
- }
-
- template
- bool SetOption(CURLoption option, _Args&&... args)
- {
- return CURLE_OK == curl_easy_setopt(curl_, option, std::forward<_Args>(args)...);
- }
-
- public:
- static inline bool GetRequest(
- HttpClient* client,
- Vector const& headers,
- ByteString const& url,
- long* response_code,
- ByteString* response_data,
- ByteString* response_header,
- char* error_buffer)
- {
- Curl curl;
- return curl.Init(client, headers, url, response_data, response_header, error_buffer)
- && curl.SetOption(CURLOPT_FOLLOWLOCATION, true)
- && curl.Perform(response_code);
- }
-
- static inline bool PostRequest(
- HttpClient* client,
- Vector const& headers,
- ByteString const& url,
- ByteString const& request_data,
- long* response_code,
- ByteString* response_data,
- ByteString* response_header,
- char* error_buffer)
- {
- Curl curl;
- return curl.Init(client, headers, url, response_data, response_header, error_buffer)
- && curl.SetOption(CURLOPT_POST, 1)
- && curl.SetOption(CURLOPT_POSTFIELDS, request_data.c_str())
- && curl.SetOption(CURLOPT_POSTFIELDSIZE, request_data.size())
- && curl.Perform(response_code);
- }
-
- static inline bool PutRequest(
- HttpClient* client,
- Vector const& headers,
- ByteString const& url,
- ByteString const& request_data,
- long* response_code,
- ByteString* response_data,
- ByteString* response_header,
- char* error_buffer)
- {
- Curl curl;
- return curl.Init(client, headers, url, response_data, response_header, error_buffer)
- && curl.SetOption(CURLOPT_CUSTOMREQUEST, "PUT")
- && curl.SetOption(CURLOPT_POSTFIELDS, request_data.c_str())
- && curl.SetOption(CURLOPT_POSTFIELDSIZE, request_data.size())
- && curl.Perform(response_code);
- }
-
- static inline bool DeleteRequest(
- HttpClient* client,
- Vector const& headers,
- ByteString const& url,
- long* response_code,
- ByteString* response_data,
- ByteString* response_header,
- char* error_buffer)
- {
- Curl curl;
- return curl.Init(client, headers, url, response_data, response_header, error_buffer)
- && curl.SetOption(CURLOPT_CUSTOMREQUEST, "DELETE")
- && curl.SetOption(CURLOPT_FOLLOWLOCATION, true)
- && curl.Perform(response_code);
- }
-
- private:
- CURL* curl_;
- curl_slist* curl_headers_;
- };
+ return total;
}
+ByteString convert_to_utf8(String const& str)
+{
+ std::wstring_convert> utf8_conv;
+ ByteString result;
+
+ try
+ {
+ result = utf8_conv.to_bytes(str.c_str());
+ }
+ catch (std::range_error&)
+ {
+ // bad conversion
+ result = WideToMultiByte(str);
+ }
+ return result;
+}
+
+String convert_from_utf8(ByteString const& str)
+{
+ oc::string_convert> utf8_conv;
+ String result;
+
+ try
+ {
+ result = utf8_conv.from_bytes(str);
+ }
+ catch (std::range_error&)
+ {
+ // bad conversion
+ result = MultiByteToWide(str);
+ }
+ return result;
+}
+
+class Curl
+{
+public:
+ Curl()
+ : curl_(curl_easy_init())
+ , curl_headers_(nullptr)
+ {
+ }
+
+ ~Curl()
+ {
+ if (curl_)
+ {
+ curl_easy_cleanup(curl_);
+ curl_ = nullptr;
+ }
+
+ if (curl_headers_)
+ {
+ curl_slist_free_all(curl_headers_);
+ curl_headers_ = nullptr;
+ }
+ }
+
+ bool Init(HttpClient* client, Vector const& headers, ByteString const& url, ByteString* response_data,
+ ByteString* response_header, char* error_buffer)
+ {
+ if (!SetOption(CURLOPT_ERRORBUFFER, error_buffer))
+ return false;
+ if (!SetOption(CURLOPT_TIMEOUT, client->GetTimeoutForRead()))
+ return false;
+ if (!SetOption(CURLOPT_CONNECTTIMEOUT, client->GetTimeoutForConnect()))
+ return false;
+
+ const auto ssl_ca_file = wide_to_string(client->GetSSLVerification());
+ if (ssl_ca_file.empty())
+ {
+ if (!SetOption(CURLOPT_SSL_VERIFYPEER, 0L))
+ return false;
+ if (!SetOption(CURLOPT_SSL_VERIFYHOST, 0L))
+ return false;
+ }
+ else
+ {
+ if (!SetOption(CURLOPT_SSL_VERIFYPEER, 1L))
+ return false;
+ if (!SetOption(CURLOPT_SSL_VERIFYHOST, 2L))
+ return false;
+ if (!SetOption(CURLOPT_CAINFO, ssl_ca_file.c_str()))
+ return false;
+ }
+
+ if (!SetOption(CURLOPT_NOSIGNAL, 1L))
+ return false;
+ if (!SetOption(CURLOPT_ACCEPT_ENCODING, ""))
+ return false;
+
+ // set request headers
+ if (!headers.empty())
+ {
+ for (const auto& header : headers)
+ {
+ curl_headers_ = curl_slist_append(curl_headers_, header.c_str());
+ }
+ if (!SetOption(CURLOPT_HTTPHEADER, curl_headers_))
+ return false;
+ }
+
+ return SetOption(CURLOPT_URL, url.c_str()) && SetOption(CURLOPT_WRITEFUNCTION, write_data)
+ && SetOption(CURLOPT_WRITEDATA, response_data) && SetOption(CURLOPT_HEADERFUNCTION, write_data)
+ && SetOption(CURLOPT_HEADERDATA, response_header);
+ }
+
+ bool Perform(long* response_code)
+ {
+ if (CURLE_OK != curl_easy_perform(curl_))
+ return false;
+
+ CURLcode code = curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, response_code);
+ return code == CURLE_OK && (*response_code >= 200 && *response_code < 300);
+ }
+
+ template
+ bool SetOption(CURLoption option, _Args&&... args)
+ {
+ return CURLE_OK == curl_easy_setopt(curl_, option, std::forward<_Args>(args)...);
+ }
+
+public:
+ static inline bool GetRequest(HttpClient* client, Vector const& headers, ByteString const& url,
+ long* response_code, ByteString* response_data, ByteString* response_header,
+ char* error_buffer)
+ {
+ Curl curl;
+ return curl.Init(client, headers, url, response_data, response_header, error_buffer)
+ && curl.SetOption(CURLOPT_FOLLOWLOCATION, true) && curl.Perform(response_code);
+ }
+
+ static inline bool PostRequest(HttpClient* client, Vector const& headers, ByteString const& url,
+ ByteString const& request_data, long* response_code, ByteString* response_data,
+ ByteString* response_header, char* error_buffer)
+ {
+ Curl curl;
+ return curl.Init(client, headers, url, response_data, response_header, error_buffer)
+ && curl.SetOption(CURLOPT_POST, 1) && curl.SetOption(CURLOPT_POSTFIELDS, request_data.c_str())
+ && curl.SetOption(CURLOPT_POSTFIELDSIZE, request_data.size()) && curl.Perform(response_code);
+ }
+
+ static inline bool PutRequest(HttpClient* client, Vector const& headers, ByteString const& url,
+ ByteString const& request_data, long* response_code, ByteString* response_data,
+ ByteString* response_header, char* error_buffer)
+ {
+ Curl curl;
+ return curl.Init(client, headers, url, response_data, response_header, error_buffer)
+ && curl.SetOption(CURLOPT_CUSTOMREQUEST, "PUT")
+ && curl.SetOption(CURLOPT_POSTFIELDS, request_data.c_str())
+ && curl.SetOption(CURLOPT_POSTFIELDSIZE, request_data.size()) && curl.Perform(response_code);
+ }
+
+ static inline bool DeleteRequest(HttpClient* client, Vector const& headers, ByteString const& url,
+ long* response_code, ByteString* response_data, ByteString* response_header,
+ char* error_buffer)
+ {
+ Curl curl;
+ return curl.Init(client, headers, url, response_data, response_header, error_buffer)
+ && curl.SetOption(CURLOPT_CUSTOMREQUEST, "DELETE") && curl.SetOption(CURLOPT_FOLLOWLOCATION, true)
+ && curl.Perform(response_code);
+ }
+
+private:
+ CURL* curl_;
+ curl_slist* curl_headers_;
+};
+} // namespace
+
namespace kiwano
{
- namespace network
- {
- HttpClient::HttpClient()
- : timeout_for_connect_(30000 /* 30 seconds */)
- , timeout_for_read_(60000 /* 60 seconds */)
- {
- }
-
- void HttpClient::SetupComponent()
- {
- ::curl_global_init(CURL_GLOBAL_ALL);
-
- std::thread thread(Closure(this, &HttpClient::NetworkThread));
- thread.detach();
- }
-
- void HttpClient::DestroyComponent()
- {
- ::curl_global_cleanup();
- }
-
- void HttpClient::Send(HttpRequestPtr request)
- {
- if (!request)
- return;
-
- request_mutex_.lock();
- request_queue_.push(request);
- request_mutex_.unlock();
-
- sleep_condition_.notify_one();
- }
-
- void HttpClient::NetworkThread()
- {
- while (true)
- {
- HttpRequestPtr request;
- {
- std::lock_guard lock(request_mutex_);
- while (request_queue_.empty())
- {
- sleep_condition_.wait(request_mutex_);
- }
- request = request_queue_.front();
- request_queue_.pop();
- }
-
- HttpResponsePtr response = new (std::nothrow) HttpResponse(request);
- Perform(request, response);
-
- response_mutex_.lock();
- response_queue_.push(response);
- response_mutex_.unlock();
-
- Application::PreformInMainThread(Closure(this, &HttpClient::DispatchResponseCallback));
- }
- }
-
- void HttpClient::Perform(HttpRequestPtr request, HttpResponsePtr response)
- {
- bool ok = false;
- long response_code = 0;
- char error_message[256] = { 0 };
- ByteString response_header;
- ByteString response_data;
-
- ByteString url = convert_to_utf8(request->GetUrl());
- ByteString data = convert_to_utf8(request->GetData());
-
- Vector headers;
- headers.reserve(request->GetHeaders().size());
- for (const auto& pair : request->GetHeaders())
- {
- headers.push_back(wide_to_string(pair.first) + ":" + wide_to_string(pair.second));
- }
-
- switch (request->GetType())
- {
- case HttpRequest::Type::Get:
- ok = Curl::GetRequest(this, headers, url, &response_code, &response_data, &response_header, error_message);
- break;
- case HttpRequest::Type::Post:
- ok = Curl::PostRequest(this, headers, url, data, &response_code, &response_data, &response_header, error_message);
- break;
- case HttpRequest::Type::Put:
- ok = Curl::PutRequest(this, headers, url, data, &response_code, &response_data, &response_header, error_message);
- break;
- case HttpRequest::Type::Delete:
- ok = Curl::DeleteRequest(this, headers, url, &response_code, &response_data, &response_header, error_message);
- break;
- default:
- KGE_ERROR(L"HttpClient: unknown request type, only GET, POST, PUT or DELETE is supported");
- return;
- }
-
- response->SetResponseCode(response_code);
- response->SetHeader(MultiByteToWide(response_header));
- response->SetData(convert_from_utf8(response_data));
- if (!ok)
- {
- response->SetSucceed(false);
- response->SetError(MultiByteToWide(error_message));
- }
- else
- {
- response->SetSucceed(true);
- }
- }
-
- void HttpClient::DispatchResponseCallback()
- {
- HttpResponsePtr response;
-
- response_mutex_.lock();
- if (!response_queue_.empty())
- {
- response = response_queue_.front();
- response_queue_.pop();
- }
- response_mutex_.unlock();
-
- if (response)
- {
- HttpRequestPtr request = response->GetRequest();
- const auto& callback = request->GetResponseCallback();
-
- if (callback)
- {
- callback(request.get(), response.get());
- }
- }
- }
-
- }
+namespace network
+{
+HttpClient::HttpClient()
+ : timeout_for_connect_(30000 /* 30 seconds */)
+ , timeout_for_read_(60000 /* 60 seconds */)
+{
}
+
+void HttpClient::SetupComponent()
+{
+ ::curl_global_init(CURL_GLOBAL_ALL);
+
+ std::thread thread(Closure(this, &HttpClient::NetworkThread));
+ thread.detach();
+}
+
+void HttpClient::DestroyComponent()
+{
+ ::curl_global_cleanup();
+}
+
+void HttpClient::Send(HttpRequestPtr request)
+{
+ if (!request)
+ return;
+
+ request_mutex_.lock();
+ request_queue_.push(request);
+ request_mutex_.unlock();
+
+ sleep_condition_.notify_one();
+}
+
+void HttpClient::NetworkThread()
+{
+ while (true)
+ {
+ HttpRequestPtr request;
+ {
+ std::lock_guard lock(request_mutex_);
+ while (request_queue_.empty())
+ {
+ sleep_condition_.wait(request_mutex_);
+ }
+ request = request_queue_.front();
+ request_queue_.pop();
+ }
+
+ HttpResponsePtr response = new (std::nothrow) HttpResponse(request);
+ Perform(request, response);
+
+ response_mutex_.lock();
+ response_queue_.push(response);
+ response_mutex_.unlock();
+
+ Application::PreformInMainThread(Closure(this, &HttpClient::DispatchResponseCallback));
+ }
+}
+
+void HttpClient::Perform(HttpRequestPtr request, HttpResponsePtr response)
+{
+ bool ok = false;
+ long response_code = 0;
+ char error_message[256] = { 0 };
+ ByteString response_header;
+ ByteString response_data;
+
+ ByteString url = convert_to_utf8(request->GetUrl());
+ ByteString data = convert_to_utf8(request->GetData());
+
+ Vector headers;
+ headers.reserve(request->GetHeaders().size());
+ for (const auto& pair : request->GetHeaders())
+ {
+ headers.push_back(wide_to_string(pair.first) + ":" + wide_to_string(pair.second));
+ }
+
+ switch (request->GetType())
+ {
+ case HttpRequest::Type::Get:
+ ok = Curl::GetRequest(this, headers, url, &response_code, &response_data, &response_header, error_message);
+ break;
+ case HttpRequest::Type::Post:
+ ok = Curl::PostRequest(this, headers, url, data, &response_code, &response_data, &response_header,
+ error_message);
+ break;
+ case HttpRequest::Type::Put:
+ ok =
+ Curl::PutRequest(this, headers, url, data, &response_code, &response_data, &response_header, error_message);
+ break;
+ case HttpRequest::Type::Delete:
+ ok = Curl::DeleteRequest(this, headers, url, &response_code, &response_data, &response_header, error_message);
+ break;
+ default:
+ KGE_ERROR(L"HttpClient: unknown request type, only GET, POST, PUT or DELETE is supported");
+ return;
+ }
+
+ response->SetResponseCode(response_code);
+ response->SetHeader(MultiByteToWide(response_header));
+ response->SetData(convert_from_utf8(response_data));
+ if (!ok)
+ {
+ response->SetSucceed(false);
+ response->SetError(MultiByteToWide(error_message));
+ }
+ else
+ {
+ response->SetSucceed(true);
+ }
+}
+
+void HttpClient::DispatchResponseCallback()
+{
+ HttpResponsePtr response;
+
+ response_mutex_.lock();
+ if (!response_queue_.empty())
+ {
+ response = response_queue_.front();
+ response_queue_.pop();
+ }
+ response_mutex_.unlock();
+
+ if (response)
+ {
+ HttpRequestPtr request = response->GetRequest();
+ const auto& callback = request->GetResponseCallback();
+
+ if (callback)
+ {
+ callback(request.get(), response.get());
+ }
+ }
+}
+
+} // namespace network
+} // namespace kiwano
diff --git a/src/kiwano-network/HttpClient.h b/src/kiwano-network/HttpClient.h
index 660380a3..c1a29b9b 100644
--- a/src/kiwano-network/HttpClient.h
+++ b/src/kiwano-network/HttpClient.h
@@ -1,15 +1,15 @@
// 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
@@ -19,127 +19,126 @@
// THE SOFTWARE.
#pragma once
+#include
#include
#include
#include
-#include
namespace kiwano
{
- namespace network
- {
- /**
- * \~chinese
- * \defgroup Network 网络通信
- */
+namespace network
+{
+/**
+ * \~chinese
+ * \defgroup Network 网络通信
+ */
- /**
- * \addtogroup Network
- * @{
- */
+/**
+ * \addtogroup Network
+ * @{
+ */
- /**
- * \~chinese
- * @brief HTTP客户端
- */
- class KGE_API HttpClient
- : public Singleton
- , public ComponentBase
- {
- friend Singleton;
+/**
+ * \~chinese
+ * @brief HTTP客户端
+ */
+class KGE_API HttpClient
+ : public Singleton
+ , public ComponentBase
+{
+ friend Singleton;
- public:
- /// \~chinese
- /// @brief 发送HTTP请求
- /// @param[in] request HTTP请求
- /// @details 发送请求后,无论结束或失败都将调用请求的响应回调函数
- void Send(HttpRequestPtr request);
+public:
+ /// \~chinese
+ /// @brief 发送HTTP请求
+ /// @param[in] request HTTP请求
+ /// @details 发送请求后,无论结束或失败都将调用请求的响应回调函数
+ void Send(HttpRequestPtr request);
- /// \~chinese
- /// @brief 设置连接超时时长
- void SetTimeoutForConnect(Duration timeout);
+ /// \~chinese
+ /// @brief 设置连接超时时长
+ void SetTimeoutForConnect(Duration timeout);
- /// \~chinese
- /// @brief 获取连接超时时长
- Duration GetTimeoutForConnect() const;
+ /// \~chinese
+ /// @brief 获取连接超时时长
+ Duration GetTimeoutForConnect() const;
- /// \~chinese
- /// @brief 设置读取超时时长
- void SetTimeoutForRead(Duration timeout);
+ /// \~chinese
+ /// @brief 设置读取超时时长
+ void SetTimeoutForRead(Duration timeout);
- /// \~chinese
- /// @brief 获取读取超时时长
- Duration GetTimeoutForRead() const;
+ /// \~chinese
+ /// @brief 获取读取超时时长
+ Duration GetTimeoutForRead() const;
- /// \~chinese
- /// @brief 设置SSL证书地址
- void SetSSLVerification(String const& root_certificate_path);
+ /// \~chinese
+ /// @brief 设置SSL证书地址
+ void SetSSLVerification(String const& root_certificate_path);
- /// \~chinese
- /// @brief 获取SSL证书地址
- String const& GetSSLVerification() const;
+ /// \~chinese
+ /// @brief 获取SSL证书地址
+ String const& GetSSLVerification() const;
- public:
- virtual void SetupComponent() override;
+public:
+ virtual void SetupComponent() override;
- virtual void DestroyComponent() override;
+ virtual void DestroyComponent() override;
- private:
- HttpClient();
+private:
+ HttpClient();
- void NetworkThread();
+ void NetworkThread();
- void Perform(HttpRequestPtr request, HttpResponsePtr response);
+ void Perform(HttpRequestPtr request, HttpResponsePtr response);
- void DispatchResponseCallback();
+ void DispatchResponseCallback();
- private:
- Duration timeout_for_connect_;
- Duration timeout_for_read_;
+private:
+ Duration timeout_for_connect_;
+ Duration timeout_for_read_;
- String ssl_verification_;
+ String ssl_verification_;
- std::mutex request_mutex_;
- Queue request_queue_;
+ std::mutex request_mutex_;
+ Queue request_queue_;
- std::mutex response_mutex_;
- Queue response_queue_;
+ std::mutex response_mutex_;
+ Queue response_queue_;
- std::condition_variable_any sleep_condition_;
- };
+ std::condition_variable_any sleep_condition_;
+};
- /** @} */
+/** @} */
-
- inline void HttpClient::SetTimeoutForConnect(Duration timeout)
- {
- timeout_for_connect_ = timeout;
- }
-
- inline Duration HttpClient::GetTimeoutForConnect() const
- {
- return timeout_for_connect_;
- }
-
- inline void HttpClient::SetTimeoutForRead(Duration timeout)
- {
- timeout_for_read_ = timeout;
- }
-
- inline Duration HttpClient::GetTimeoutForRead() const
- {
- return timeout_for_read_;
- }
-
- inline void HttpClient::SetSSLVerification(String const& root_certificate_path)
- {
- ssl_verification_ = root_certificate_path;
- }
-
- inline String const& HttpClient::GetSSLVerification() const
- {
- return ssl_verification_;
- }
-
- }
+inline void HttpClient::SetTimeoutForConnect(Duration timeout)
+{
+ timeout_for_connect_ = timeout;
}
+
+inline Duration HttpClient::GetTimeoutForConnect() const
+{
+ return timeout_for_connect_;
+}
+
+inline void HttpClient::SetTimeoutForRead(Duration timeout)
+{
+ timeout_for_read_ = timeout;
+}
+
+inline Duration HttpClient::GetTimeoutForRead() const
+{
+ return timeout_for_read_;
+}
+
+inline void HttpClient::SetSSLVerification(String const& root_certificate_path)
+{
+ ssl_verification_ = root_certificate_path;
+}
+
+inline String const& HttpClient::GetSSLVerification() const
+{
+ return ssl_verification_;
+}
+
+} // namespace network
+} // namespace kiwano
diff --git a/src/kiwano-network/HttpRequest.cpp b/src/kiwano-network/HttpRequest.cpp
index 610df352..6aacca61 100644
--- a/src/kiwano-network/HttpRequest.cpp
+++ b/src/kiwano-network/HttpRequest.cpp
@@ -1,15 +1,15 @@
// 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
@@ -23,12 +23,12 @@
namespace kiwano
{
- namespace network
- {
- void HttpRequest::SetJsonData(Json const& json)
- {
- SetHeader(L"Content-Type", L"application/json;charset=UTF-8");
- data_ = json.dump();
- }
- }
+namespace network
+{
+void HttpRequest::SetJsonData(Json const& json)
+{
+ SetHeader(L"Content-Type", L"application/json;charset=UTF-8");
+ data_ = json.dump();
}
+} // namespace network
+} // namespace kiwano
diff --git a/src/kiwano-network/HttpRequest.h b/src/kiwano-network/HttpRequest.h
index 69609be4..cc01a9cb 100644
--- a/src/kiwano-network/HttpRequest.h
+++ b/src/kiwano-network/HttpRequest.h
@@ -1,15 +1,15 @@
// 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
@@ -25,132 +25,173 @@
namespace kiwano
{
- namespace network
- {
- class HttpResponse;
+namespace network
+{
+class HttpResponse;
- KGE_DECLARE_SMART_PTR(HttpRequest);
+KGE_DECLARE_SMART_PTR(HttpRequest);
- /**
- * \addtogroup Network
- * @{
- */
+/**
+ * \addtogroup Network
+ * @{
+ */
- /**
- * \~chinese
- * @brief HTTP请求
- */
- class KGE_API HttpRequest
- : public virtual ObjectBase
- {
- public:
- /// \~chinese
- /// @brief 响应回调函数
- using ResponseCallback = Function;
+/**
+ * \~chinese
+ * @brief HTTP请求
+ */
+class KGE_API HttpRequest : public virtual ObjectBase
+{
+public:
+ /// \~chinese
+ /// @brief 响应回调函数
+ using ResponseCallback = Function;
- /// \~chinese
- /// @brief 请求类型
- enum class Type
- {
- Unknown, ///< 未知
- Get, ///< HTTP GET请求
- Post, ///< HTTP POST请求
- Put, ///< HTTP PUT请求
- Delete ///< HTTP DELETE请求
- };
+ /// \~chinese
+ /// @brief 请求类型
+ enum class Type
+ {
+ Unknown, ///< 未知
+ Get, ///< HTTP GET请求
+ Post, ///< HTTP POST请求
+ Put, ///< HTTP PUT请求
+ Delete ///< HTTP DELETE请求
+ };
- HttpRequest();
+ HttpRequest();
- HttpRequest(Type type);
+ HttpRequest(Type type);
- /// \~chinese
- /// @brief 设置请求地址
- void SetUrl(String const& url);
+ /// \~chinese
+ /// @brief 设置请求地址
+ void SetUrl(String const& url);
- /// \~chinese
- /// @brief 设置请求类型
- void SetType(Type type);
+ /// \~chinese
+ /// @brief 设置请求类型
+ void SetType(Type type);
- /// \~chinese
- /// @brief 设置请求携带的数据
- void SetData(String const& data);
+ /// \~chinese
+ /// @brief 设置请求携带的数据
+ void SetData(String const& data);
- /// \~chinese
- /// @brief 设置请求携带的JSON数据
- void SetJsonData(Json const& json);
+ /// \~chinese
+ /// @brief 设置请求携带的JSON数据
+ void SetJsonData(Json const& json);
- /// \~chinese
- /// @brief 设置HTTP头
- void SetHeaders(Map const& headers);
+ /// \~chinese
+ /// @brief 设置HTTP头
+ void SetHeaders(Map const& headers);
- /// \~chinese
- /// @brief 设置HTTP头
- void SetHeader(String const& field, String const& content);
+ /// \~chinese
+ /// @brief 设置HTTP头
+ void SetHeader(String const& field, String const& content);
- /// \~chinese
- /// @brief 设置响应回调函数
- void SetResponseCallback(ResponseCallback const& callback);
+ /// \~chinese
+ /// @brief 设置响应回调函数
+ void SetResponseCallback(ResponseCallback const& callback);
- /// \~chinese
- /// @brief 获取请求地址
- String const& GetUrl() const;
+ /// \~chinese
+ /// @brief 获取请求地址
+ String const& GetUrl() const;
- /// \~chinese
- /// @brief 获取请求类型
- Type GetType() const;
+ /// \~chinese
+ /// @brief 获取请求类型
+ Type GetType() const;
- /// \~chinese
- /// @brief 获取请求数据
- String const& GetData() const;
+ /// \~chinese
+ /// @brief 获取请求数据
+ String const& GetData() const;
- /// \~chinese
- /// @brief 获取HTTP头
- Map& GetHeaders();
+ /// \~chinese
+ /// @brief 获取HTTP头
+ Map& GetHeaders();
- /// \~chinese
- /// @brief 获取HTTP头
- String const& GetHeader(String const& header) const;
+ /// \~chinese
+ /// @brief 获取HTTP头
+ String const& GetHeader(String const& header) const;
- /// \~chinese
- /// @brief 获取响应回调函数
- ResponseCallback const& GetResponseCallback() const;
+ /// \~chinese
+ /// @brief 获取响应回调函数
+ ResponseCallback const& GetResponseCallback() const;
- private:
- Type type_;
- String url_;
- String data_;
- Map headers_;
- ResponseCallback response_cb_;
- };
+private:
+ Type type_;
+ String url_;
+ String data_;
+ Map headers_;
+ ResponseCallback response_cb_;
+};
- /** @} */
+/** @} */
- inline HttpRequest::HttpRequest() : type_(Type::Unknown) {}
-
- inline HttpRequest::HttpRequest(Type type) : type_(type) {}
-
- inline void HttpRequest::SetUrl(String const& url) { url_ = url; }
-
- inline String const& HttpRequest::GetUrl() const { return url_; }
-
- inline void HttpRequest::SetType(Type type) { type_ = type; }
-
- inline HttpRequest::Type HttpRequest::GetType() const { return type_; }
-
- inline void HttpRequest::SetData(String const& data) { data_ = data; }
-
- inline String const& HttpRequest::GetData() const { return data_; }
-
- inline void HttpRequest::SetHeaders(Map const& headers) { headers_ = headers; }
-
- inline void HttpRequest::SetHeader(String const& field, String const& content) { headers_[field] = content; }
-
- inline Map& HttpRequest::GetHeaders() { return headers_; }
-
- inline String const& HttpRequest::GetHeader(String const& header) const { return headers_.at(header); }
-
- inline void HttpRequest::SetResponseCallback(ResponseCallback const& callback) { response_cb_ = callback; }
-
- inline HttpRequest::ResponseCallback const& HttpRequest::GetResponseCallback() const { return response_cb_; }
- }
+inline HttpRequest::HttpRequest()
+ : type_(Type::Unknown)
+{
}
+
+inline HttpRequest::HttpRequest(Type type)
+ : type_(type)
+{
+}
+
+inline void HttpRequest::SetUrl(String const& url)
+{
+ url_ = url;
+}
+
+inline String const& HttpRequest::GetUrl() const
+{
+ return url_;
+}
+
+inline void HttpRequest::SetType(Type type)
+{
+ type_ = type;
+}
+
+inline HttpRequest::Type HttpRequest::GetType() const
+{
+ return type_;
+}
+
+inline void HttpRequest::SetData(String const& data)
+{
+ data_ = data;
+}
+
+inline String const& HttpRequest::GetData() const
+{
+ return data_;
+}
+
+inline void HttpRequest::SetHeaders(Map const& headers)
+{
+ headers_ = headers;
+}
+
+inline void HttpRequest::SetHeader(String const& field, String const& content)
+{
+ headers_[field] = content;
+}
+
+inline Map& HttpRequest::GetHeaders()
+{
+ return headers_;
+}
+
+inline String const& HttpRequest::GetHeader(String const& header) const
+{
+ return headers_.at(header);
+}
+
+inline void HttpRequest::SetResponseCallback(ResponseCallback const& callback)
+{
+ response_cb_ = callback;
+}
+
+inline HttpRequest::ResponseCallback const& HttpRequest::GetResponseCallback() const
+{
+ return response_cb_;
+}
+} // namespace network
+} // namespace kiwano
diff --git a/src/kiwano-network/HttpResponse.hpp b/src/kiwano-network/HttpResponse.hpp
index 42106e2e..0c91baa2 100644
--- a/src/kiwano-network/HttpResponse.hpp
+++ b/src/kiwano-network/HttpResponse.hpp
@@ -1,15 +1,15 @@
// 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
@@ -23,103 +23,140 @@
namespace kiwano
{
- namespace network
- {
- KGE_DECLARE_SMART_PTR(HttpResponse);
+namespace network
+{
+KGE_DECLARE_SMART_PTR(HttpResponse);
- /**
- * \addtogroup Network
- * @{
- */
+/**
+ * \addtogroup Network
+ * @{
+ */
- /**
- * \~chinese
- * @brief HTTP响应
- */
- class KGE_API HttpResponse
- : public virtual ObjectBase
- {
- public:
- HttpResponse(HttpRequestPtr request);
+/**
+ * \~chinese
+ * @brief HTTP响应
+ */
+class KGE_API HttpResponse : public virtual ObjectBase
+{
+public:
+ HttpResponse(HttpRequestPtr request);
- /// \~chinese
- /// @brief 获取对应的HTTP请求
- HttpRequestPtr GetRequest() const;
+ /// \~chinese
+ /// @brief 获取对应的HTTP请求
+ HttpRequestPtr GetRequest() const;
- /// \~chinese
- /// @brief 获取响应状态
- bool IsSucceed() const;
+ /// \~chinese
+ /// @brief 获取响应状态
+ bool IsSucceed() const;
- /// \~chinese
- /// @brief 获取HTTP状态码
- long GetResponseCode() const;
+ /// \~chinese
+ /// @brief 获取HTTP状态码
+ long GetResponseCode() const;
- /// \~chinese
- /// @brief 获取响应头
- String GetHeader() const;
+ /// \~chinese
+ /// @brief 获取响应头
+ String GetHeader() const;
- /// \~chinese
- /// @brief 获取响应数据
- String const& GetData() const;
+ /// \~chinese
+ /// @brief 获取响应数据
+ String const& GetData() const;
- /// \~chinese
- /// @brief 获取错误信息
- String const& GetError() const;
+ /// \~chinese
+ /// @brief 获取错误信息
+ String const& GetError() const;
- /// \~chinese
- /// @brief 设置响应状态
- void SetSucceed(bool succeed);
+ /// \~chinese
+ /// @brief 设置响应状态
+ void SetSucceed(bool succeed);
- /// \~chinese
- /// @brief 设置HTTP状态码
- void SetResponseCode(long response_code);
+ /// \~chinese
+ /// @brief 设置HTTP状态码
+ void SetResponseCode(long response_code);
- /// \~chinese
- /// @brief 设置响应头
- void SetHeader(String const& response_header);
+ /// \~chinese
+ /// @brief 设置响应头
+ void SetHeader(String const& response_header);
- /// \~chinese
- /// @brief 设置响应数据
- void SetData(String const& response_data);
+ /// \~chinese
+ /// @brief 设置响应数据
+ void SetData(String const& response_data);
- /// \~chinese
- /// @brief 设置错误信息
- void SetError(String const& error_buffer);
+ /// \~chinese
+ /// @brief 设置错误信息
+ void SetError(String const& error_buffer);
- private:
- bool succeed_;
- long response_code_;
- HttpRequestPtr request_;
+private:
+ bool succeed_;
+ long response_code_;
+ HttpRequestPtr request_;
- String response_header_;
- String response_data_;
- String error_buffer_;
- };
+ String response_header_;
+ String response_data_;
+ String error_buffer_;
+};
- /** @} */
+/** @} */
- inline HttpResponse::HttpResponse(HttpRequestPtr request) : request_(request), succeed_(false), response_code_(0) {}
-
- inline HttpRequestPtr HttpResponse::GetRequest() const { return request_; }
-
- inline void HttpResponse::SetSucceed(bool succeed) { succeed_ = succeed; }
-
- inline bool HttpResponse::IsSucceed() const { return succeed_; }
-
- inline void HttpResponse::SetResponseCode(long response_code) { response_code_ = response_code; }
-
- inline long HttpResponse::GetResponseCode() const { return response_code_; }
-
- inline void HttpResponse::SetHeader(String const& response_header) { response_header_ = response_header; }
-
- inline String HttpResponse::GetHeader() const { return response_header_; }
-
- inline void HttpResponse::SetData(String const& response_data) { response_data_ = response_data; }
-
- inline String const& HttpResponse::GetData() const { return response_data_; }
-
- inline void HttpResponse::SetError(String const& error_buffer) { error_buffer_ = error_buffer; }
-
- inline String const& HttpResponse::GetError() const { return error_buffer_; }
- }
+inline HttpResponse::HttpResponse(HttpRequestPtr request)
+ : request_(request)
+ , succeed_(false)
+ , response_code_(0)
+{
}
+
+inline HttpRequestPtr HttpResponse::GetRequest() const
+{
+ return request_;
+}
+
+inline void HttpResponse::SetSucceed(bool succeed)
+{
+ succeed_ = succeed;
+}
+
+inline bool HttpResponse::IsSucceed() const
+{
+ return succeed_;
+}
+
+inline void HttpResponse::SetResponseCode(long response_code)
+{
+ response_code_ = response_code;
+}
+
+inline long HttpResponse::GetResponseCode() const
+{
+ return response_code_;
+}
+
+inline void HttpResponse::SetHeader(String const& response_header)
+{
+ response_header_ = response_header;
+}
+
+inline String HttpResponse::GetHeader() const
+{
+ return response_header_;
+}
+
+inline void HttpResponse::SetData(String const& response_data)
+{
+ response_data_ = response_data;
+}
+
+inline String const& HttpResponse::GetData() const
+{
+ return response_data_;
+}
+
+inline void HttpResponse::SetError(String const& error_buffer)
+{
+ error_buffer_ = error_buffer;
+}
+
+inline String const& HttpResponse::GetError() const
+{
+ return error_buffer_;
+}
+} // namespace network
+} // namespace kiwano
diff --git a/src/kiwano-network/kiwano-network.h b/src/kiwano-network/kiwano-network.h
index e1078261..eb134a7a 100644
--- a/src/kiwano-network/kiwano-network.h
+++ b/src/kiwano-network/kiwano-network.h
@@ -1,15 +1,15 @@
// 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
@@ -20,6 +20,6 @@
#pragma once
+#include
#include
#include
-#include
diff --git a/src/kiwano-physics/Body.cpp b/src/kiwano-physics/Body.cpp
index cd4055c7..7698824b 100644
--- a/src/kiwano-physics/Body.cpp
+++ b/src/kiwano-physics/Body.cpp
@@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 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
@@ -23,283 +23,280 @@
namespace kiwano
{
- namespace physics
- {
-
- Body::Body()
- : body_(nullptr)
- , actor_(nullptr)
- , world_(nullptr)
- , category_bits_(0x0001)
- , mask_bits_(0xFFFF)
- , group_index_(0)
- {
- }
-
- Body::~Body()
- {
- Destroy();
- }
-
- bool Body::InitBody(World* world, Actor* actor)
- {
- KGE_ASSERT(world);
-
- Destroy();
-
- world_ = world;
- b2BodyDef def;
- b2Body* b2body = world->GetB2World()->CreateBody(&def);
-
- if (b2body)
- {
- SetB2Body(b2body);
- SetActor(actor);
- UpdateFromActor();
- return true;
- }
- return false;
- }
-
- Fixture Body::AddFixture(Shape* shape, const Fixture::Param& param)
- {
- KGE_ASSERT(body_ && world_);
- return Fixture(this, shape, param);
- }
-
- Fixture Body::AddCircleShape(float radius, float density)
- {
- return AddFixture(&CircleShape(radius), Fixture::Param(density));
- }
-
- Fixture Body::AddBoxShape(Vec2 const& size, float density)
- {
- return AddFixture(&BoxShape(size), Fixture::Param(density));
- }
-
- Fixture Body::AddPolygonShape(Vector const& vertexs, float density)
- {
- return AddFixture(&PolygonShape(vertexs), Fixture::Param(density));
- }
-
- Fixture Body::AddEdgeShape(Point const& p1, Point const& p2, float density)
- {
- return AddFixture(&EdgeShape(p1, p2), Fixture::Param(density));
- }
-
- Fixture Body::AddChainShape(Vector const& vertexs, bool loop, float density)
- {
- return AddFixture(&ChainShape(vertexs, loop), Fixture::Param(density));
- }
-
- void Body::RemoveFixture(Fixture const& fixture)
- {
- if (fixture.GetB2Fixture())
- {
- body_->DestroyFixture(fixture.GetB2Fixture());
- }
- }
-
- void Body::SetCategoryBits(uint16_t category_bits)
- {
- KGE_ASSERT(body_);
-
- if (category_bits != category_bits_)
- {
- category_bits_ = category_bits;
-
- b2Fixture* fixture = body_->GetFixtureList();
- while (fixture)
- {
- UpdateFixtureFilter(fixture);
- fixture = fixture->GetNext();
- }
- }
- }
-
- void Body::SetMaskBits(uint16_t mask_bits)
- {
- KGE_ASSERT(body_);
-
- if (mask_bits != mask_bits_)
- {
- mask_bits_ = mask_bits;
-
- b2Fixture* fixture = body_->GetFixtureList();
- while (fixture)
- {
- UpdateFixtureFilter(fixture);
- fixture = fixture->GetNext();
- }
- }
- }
-
- void Body::SetGroupIndex(int16_t index)
- {
- KGE_ASSERT(body_);
-
- if (index != group_index_)
- {
- group_index_ = index;
-
- b2Fixture* fixture = body_->GetFixtureList();
- while (fixture)
- {
- UpdateFixtureFilter(fixture);
- fixture = fixture->GetNext();
- }
- }
- }
-
- void Body::GetMassData(float* mass, Point* center, float* inertia) const
- {
- KGE_ASSERT(body_ && world_);
-
- b2MassData data;
- body_->GetMassData(&data);
-
- if (mass) *mass = data.mass;
- if (center) *center = world_->World2Stage(data.center);
- if (inertia) *inertia = data.I;
- }
-
- void Body::SetMassData(float mass, Point const& center, float inertia)
- {
- KGE_ASSERT(body_ && world_);
-
- b2MassData data;
- data.mass = mass;
- data.center = world_->Stage2World(center);
- data.I = inertia;
- body_->SetMassData(&data);
- }
-
- void Body::ResetMassData()
- {
- KGE_ASSERT(body_);
- body_->ResetMassData();
- }
-
- Point Body::GetBodyPosition() const
- {
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetPosition());
- }
-
- void Body::SetBodyTransform(Point const& pos, float angle)
- {
- KGE_ASSERT(body_ && world_);
- body_->SetTransform(world_->Stage2World(pos), math::Degree2Radian(angle));
- }
-
- Point Body::GetLocalPoint(Point const& world) const
- {
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetLocalPoint(world_->Stage2World(world)));
- }
-
- Point Body::GetWorldPoint(Point const& local) const
- {
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetWorldPoint(world_->Stage2World(local)));
- }
-
- Point Body::GetLocalCenter() const
- {
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetLocalCenter());
- }
-
- Point Body::GetWorldCenter() const
- {
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetWorldCenter());
- }
-
- void Body::ApplyForce(Vec2 const& force, Point const& point, bool wake)
- {
- KGE_ASSERT(body_ && world_);
- body_->ApplyForce(b2Vec2(force.x, force.y), world_->Stage2World(point), wake);
- }
-
- void Body::ApplyForceToCenter(Vec2 const& force, bool wake)
- {
- KGE_ASSERT(body_ && world_);
- body_->ApplyForceToCenter(b2Vec2(force.x, force.y), wake);
- }
-
- void Body::ApplyTorque(float torque, bool wake)
- {
- KGE_ASSERT(body_ && world_);
- body_->ApplyTorque(torque, wake);
- }
-
- void Body::SetB2Body(b2Body* body)
- {
- body_ = body;
- if (body_)
- {
- body_->SetUserData(this);
- }
- }
-
- void Body::Destroy()
- {
- if (world_)
- {
- world_->RemoveBody(this);
- }
-
- body_ = nullptr;
- world_ = nullptr;
- actor_ = nullptr;
- }
-
- void Body::UpdateActor()
- {
- if (actor_ && body_)
- {
- if (world_)
- {
- actor_->SetPosition(world_->World2Stage(body_->GetPosition()));
- }
- else
- {
- actor_->SetPosition(World2Stage(body_->GetPosition()));
- }
- actor_->SetRotation(math::Radian2Degree(body_->GetAngle()));
- }
- }
-
- void Body::UpdateFromActor()
- {
- if (actor_ && body_)
- {
- if (world_)
- {
- body_->SetTransform(
- world_->Stage2World(actor_->GetPosition()),
- math::Degree2Radian(actor_->GetRotation())
- );
- }
- else
- {
- body_->SetTransform(
- Stage2World(actor_->GetPosition()),
- math::Degree2Radian(actor_->GetRotation())
- );
- }
- }
- }
-
- void Body::UpdateFixtureFilter(b2Fixture* fixture)
- {
- b2Filter filter;
- filter.categoryBits = category_bits_;
- filter.maskBits = mask_bits_;
- filter.groupIndex = group_index_;
- fixture->SetFilterData(filter);
- }
+namespace physics
+{
+Body::Body()
+ : body_(nullptr)
+ , actor_(nullptr)
+ , world_(nullptr)
+ , category_bits_(0x0001)
+ , mask_bits_(0xFFFF)
+ , group_index_(0)
+{
}
+
+Body::~Body()
+{
+ Destroy();
}
+
+bool Body::InitBody(World* world, Actor* actor)
+{
+ KGE_ASSERT(world);
+
+ Destroy();
+
+ world_ = world;
+ b2BodyDef def;
+ b2Body* b2body = world->GetB2World()->CreateBody(&def);
+
+ if (b2body)
+ {
+ SetB2Body(b2body);
+ SetActor(actor);
+ UpdateFromActor();
+ return true;
+ }
+ return false;
+}
+
+Fixture Body::AddFixture(Shape* shape, const Fixture::Param& param)
+{
+ KGE_ASSERT(body_ && world_);
+ return Fixture(this, shape, param);
+}
+
+Fixture Body::AddCircleShape(float radius, float density)
+{
+ return AddFixture(&CircleShape(radius), Fixture::Param(density));
+}
+
+Fixture Body::AddBoxShape(Vec2 const& size, float density)
+{
+ return AddFixture(&BoxShape(size), Fixture::Param(density));
+}
+
+Fixture Body::AddPolygonShape(Vector const& vertexs, float density)
+{
+ return AddFixture(&PolygonShape(vertexs), Fixture::Param(density));
+}
+
+Fixture Body::AddEdgeShape(Point const& p1, Point const& p2, float density)
+{
+ return AddFixture(&EdgeShape(p1, p2), Fixture::Param(density));
+}
+
+Fixture Body::AddChainShape(Vector const& vertexs, bool loop, float density)
+{
+ return AddFixture(&ChainShape(vertexs, loop), Fixture::Param(density));
+}
+
+void Body::RemoveFixture(Fixture const& fixture)
+{
+ if (fixture.GetB2Fixture())
+ {
+ body_->DestroyFixture(fixture.GetB2Fixture());
+ }
+}
+
+void Body::SetCategoryBits(uint16_t category_bits)
+{
+ KGE_ASSERT(body_);
+
+ if (category_bits != category_bits_)
+ {
+ category_bits_ = category_bits;
+
+ b2Fixture* fixture = body_->GetFixtureList();
+ while (fixture)
+ {
+ UpdateFixtureFilter(fixture);
+ fixture = fixture->GetNext();
+ }
+ }
+}
+
+void Body::SetMaskBits(uint16_t mask_bits)
+{
+ KGE_ASSERT(body_);
+
+ if (mask_bits != mask_bits_)
+ {
+ mask_bits_ = mask_bits;
+
+ b2Fixture* fixture = body_->GetFixtureList();
+ while (fixture)
+ {
+ UpdateFixtureFilter(fixture);
+ fixture = fixture->GetNext();
+ }
+ }
+}
+
+void Body::SetGroupIndex(int16_t index)
+{
+ KGE_ASSERT(body_);
+
+ if (index != group_index_)
+ {
+ group_index_ = index;
+
+ b2Fixture* fixture = body_->GetFixtureList();
+ while (fixture)
+ {
+ UpdateFixtureFilter(fixture);
+ fixture = fixture->GetNext();
+ }
+ }
+}
+
+void Body::GetMassData(float* mass, Point* center, float* inertia) const
+{
+ KGE_ASSERT(body_ && world_);
+
+ b2MassData data;
+ body_->GetMassData(&data);
+
+ if (mass)
+ *mass = data.mass;
+ if (center)
+ *center = world_->World2Stage(data.center);
+ if (inertia)
+ *inertia = data.I;
+}
+
+void Body::SetMassData(float mass, Point const& center, float inertia)
+{
+ KGE_ASSERT(body_ && world_);
+
+ b2MassData data;
+ data.mass = mass;
+ data.center = world_->Stage2World(center);
+ data.I = inertia;
+ body_->SetMassData(&data);
+}
+
+void Body::ResetMassData()
+{
+ KGE_ASSERT(body_);
+ body_->ResetMassData();
+}
+
+Point Body::GetBodyPosition() const
+{
+ KGE_ASSERT(body_ && world_);
+ return world_->World2Stage(body_->GetPosition());
+}
+
+void Body::SetBodyTransform(Point const& pos, float angle)
+{
+ KGE_ASSERT(body_ && world_);
+ body_->SetTransform(world_->Stage2World(pos), math::Degree2Radian(angle));
+}
+
+Point Body::GetLocalPoint(Point const& world) const
+{
+ KGE_ASSERT(body_ && world_);
+ return world_->World2Stage(body_->GetLocalPoint(world_->Stage2World(world)));
+}
+
+Point Body::GetWorldPoint(Point const& local) const
+{
+ KGE_ASSERT(body_ && world_);
+ return world_->World2Stage(body_->GetWorldPoint(world_->Stage2World(local)));
+}
+
+Point Body::GetLocalCenter() const
+{
+ KGE_ASSERT(body_ && world_);
+ return world_->World2Stage(body_->GetLocalCenter());
+}
+
+Point Body::GetWorldCenter() const
+{
+ KGE_ASSERT(body_ && world_);
+ return world_->World2Stage(body_->GetWorldCenter());
+}
+
+void Body::ApplyForce(Vec2 const& force, Point const& point, bool wake)
+{
+ KGE_ASSERT(body_ && world_);
+ body_->ApplyForce(b2Vec2(force.x, force.y), world_->Stage2World(point), wake);
+}
+
+void Body::ApplyForceToCenter(Vec2 const& force, bool wake)
+{
+ KGE_ASSERT(body_ && world_);
+ body_->ApplyForceToCenter(b2Vec2(force.x, force.y), wake);
+}
+
+void Body::ApplyTorque(float torque, bool wake)
+{
+ KGE_ASSERT(body_ && world_);
+ body_->ApplyTorque(torque, wake);
+}
+
+void Body::SetB2Body(b2Body* body)
+{
+ body_ = body;
+ if (body_)
+ {
+ body_->SetUserData(this);
+ }
+}
+
+void Body::Destroy()
+{
+ if (world_)
+ {
+ world_->RemoveBody(this);
+ }
+
+ body_ = nullptr;
+ world_ = nullptr;
+ actor_ = nullptr;
+}
+
+void Body::UpdateActor()
+{
+ if (actor_ && body_)
+ {
+ if (world_)
+ {
+ actor_->SetPosition(world_->World2Stage(body_->GetPosition()));
+ }
+ else
+ {
+ actor_->SetPosition(World2Stage(body_->GetPosition()));
+ }
+ actor_->SetRotation(math::Radian2Degree(body_->GetAngle()));
+ }
+}
+
+void Body::UpdateFromActor()
+{
+ if (actor_ && body_)
+ {
+ if (world_)
+ {
+ body_->SetTransform(world_->Stage2World(actor_->GetPosition()), math::Degree2Radian(actor_->GetRotation()));
+ }
+ else
+ {
+ body_->SetTransform(Stage2World(actor_->GetPosition()), math::Degree2Radian(actor_->GetRotation()));
+ }
+ }
+}
+
+void Body::UpdateFixtureFilter(b2Fixture* fixture)
+{
+ b2Filter filter;
+ filter.categoryBits = category_bits_;
+ filter.maskBits = mask_bits_;
+ filter.groupIndex = group_index_;
+ fixture->SetFilterData(filter);
+}
+
+} // namespace physics
+} // namespace kiwano
diff --git a/src/kiwano-physics/Body.h b/src/kiwano-physics/Body.h
index 6409bca4..25fd0c8e 100644
--- a/src/kiwano-physics/Body.h
+++ b/src/kiwano-physics/Body.h
@@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 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
@@ -19,366 +19,471 @@
// THE SOFTWARE.
#pragma once
-#include
-#include
-#include
#include
+#include
+#include
+#include
namespace kiwano
{
- namespace physics
- {
- class World;
-
- KGE_DECLARE_SMART_PTR(Body);
-
- /**
- * \addtogroup Physics
- * @{
- */
-
- /// \~chinese
- /// @brief 物体
- class KGE_API Body
- : public virtual ObjectBase
- {
- public:
- /// \~chinese
- /// @brief 物体类型
- enum class Type
- {
- Static = 0, ///< 静态物体
- Kinematic, ///< 动力学物体
- Dynamic, ///< 动态物体
- };
-
- Body();
-
- virtual ~Body();
-
- /// \~chinese
- /// @brief 初始化
- /// @param[in] world 物理世界
- /// @param[in] actor 绑定的角色
- bool InitBody(World* world, ActorPtr actor);
-
- /// \~chinese
- /// @brief 初始化
- /// @param[in] world 物理世界
- /// @param[in] actor 绑定的角色
- bool InitBody(World* world, Actor* actor);
-
- /// \~chinese
- /// @brief 添加夹具
- /// @param shape 物体形状
- /// @param density 物体密度
- Fixture AddFixture(Shape* shape, const Fixture::Param& param);
-
- /// \~chinese
- /// @brief 添加圆形夹具
- /// @param radius 圆形半径
- /// @param density 物体密度
- Fixture AddCircleShape(float radius, float density = 0.f);
-
- /// \~chinese
- /// @brief 添加盒形夹具
- /// @param size 盒大小
- /// @param density 物体密度
- Fixture AddBoxShape(Vec2 const& size, float density = 0.f);
-
- /// \~chinese
- /// @brief 添加多边形夹具
- /// @param vertexs 多边形端点
- /// @param density 物体密度
- Fixture AddPolygonShape(Vector const& vertexs, float density = 0.f);
-
- /// \~chinese
- /// @brief 添加线段形夹具
- /// @param p1 线段起点
- /// @param p2 线段终点
- /// @param density 物体密度
- Fixture AddEdgeShape(Point const& p1, Point const& p2, float density = 0.f);
-
- /// \~chinese
- /// @brief 添加链条形夹具
- /// @param vertexs 链条端点
- /// @param loop 是否闭合
- /// @param density 物体密度
- Fixture AddChainShape(Vector const& vertexs, bool loop, float density = 0.f);
-
- /// \~chinese
- /// @brief 获取夹具列表
- FixtureList GetFixtureList() const;
-
- /// \~chinese
- /// @brief 移除夹具
- void RemoveFixture(Fixture const& fixture);
-
- /// \~chinese
- /// @brief 获取接触边列表
- ContactEdgeList GetContactList() const;
-
- /// \~chinese
- /// @brief 获取类别码
- uint16_t GetCategoryBits() const;
-
- /// \~chinese
- /// @brief 设置类别码
- void SetCategoryBits(uint16_t category_bits);
-
- /// \~chinese
- /// @brief 获取碰撞掩码
- uint16_t GetMaskBits() const;
-
- /// \~chinese
- /// @brief 设置碰撞掩码
- void SetMaskBits(uint16_t mask_bits);
-
- /// \~chinese
- /// @brief 获取组索引
- int16_t GetGroupIndex() const;
-
- /// \~chinese
- /// @brief 设置组索引
- void SetGroupIndex(int16_t index);
-
- /// \~chinese
- /// @brief 获取旋转角度
- float GetBodyRotation() const;
-
- /// \~chinese
- /// @brief 设置旋转角度
- void SetBodyRotation(float angle);
-
- /// \~chinese
- /// @brief 获取物体位置
- Point GetBodyPosition() const;
-
- /// \~chinese
- /// @brief 设置物体位置
- void SetBodyPosition(Point const& pos);
-
- /// \~chinese
- /// @brief 位置和旋转变换
- void SetBodyTransform(Point const& pos, float angle);
-
- /// \~chinese
- /// @brief 获取质量 [kg]
- float GetMass() const;
-
- /// \~chinese
- /// @brief 获取惯性
- float GetInertia() const;
-
- /// \~chinese
- /// @brief 获取质量数据
- /// @param[out] mass 物体质量 [kg]
- /// @param[out] center 质心位置
- /// @param[out] inertia 惯性
- void GetMassData(float* mass, Point* center, float* inertia) const;
-
- /// \~chinese
- /// @brief 设置质量数据
- /// @param mass 物体质量 [kg]
- /// @param center 质心位置
- /// @param inertia 惯性
- void SetMassData(float mass, Point const& center, float inertia);
-
- /// \~chinese
- /// @brief 重置质量数据
- void ResetMassData();
-
- /// \~chinese
- /// @brief 获取世界坐标系上的点在物体上的位置
- Point GetLocalPoint(Point const& world) const;
-
- /// \~chinese
- /// @brief 获取物体上的点在世界坐标系的位置
- Point GetWorldPoint(Point const& local) const;
-
- /// \~chinese
- /// @brief 获取物体质心相对于物体的位置
- Point GetLocalCenter() const;
-
- /// \~chinese
- /// @brief 获取物体质心位置
- Point GetWorldCenter() const;
-
- /// \~chinese
- /// @brief 获取物体类型
- Type GetType() const;
-
- /// \~chinese
- /// @brief 设置物体类型
- void SetType(Type type);
-
- /// \~chinese
- /// @brief 获取物体受重力的比例
- float GetGravityScale() const;
-
- /// \~chinese
- /// @brief 设置物体受重力的比例
- void SetGravityScale(float scale);
-
- /// \~chinese
- /// @brief 施力
- /// @param force 力的大小和方向
- /// @param point 施力点
- /// @param wake 是否唤醒物体
- void ApplyForce(Vec2 const& force, Point const& point, bool wake = true);
-
- /// \~chinese
- /// @brief 给物体中心施力
- /// @param force 力的大小和方向
- /// @param wake 是否唤醒物体
- void ApplyForceToCenter(Vec2 const& force, bool wake = true);
-
- /// \~chinese
- /// @brief 施加扭矩
- /// @param torque 扭矩
- /// @param wake 是否唤醒物体
- void ApplyTorque(float torque, bool wake = false);
-
- /// \~chinese
- /// @brief 旋转角度是否固定
- bool IsIgnoreRotation() const;
-
- /// \~chinese
- /// @brief 设置是否固定旋转角度
- void SetIgnoreRotation(bool flag);
-
- /// \~chinese
- /// @brief 是否是子弹物体
- bool IsBullet() const;
-
- /// \~chinese
- /// @brief 设置物体是否是子弹物体
- void SetBullet(bool flag);
-
- /// \~chinese
- /// @brief 是否处于唤醒状态
- bool IsAwake() const;
-
- /// \~chinese
- /// @brief 设置唤醒状态
- void SetAwake(bool flag);
-
- /// \~chinese
- /// @brief 是否启用休眠
- bool IsSleepingAllowed() const;
-
- /// \~chinese
- /// @brief 设置是否允许休眠
- void SetSleepingAllowed(bool flag);
-
- /// \~chinese
- /// @brief 是否启用
- bool IsActive() const;
-
- /// \~chinese
- /// @brief 设置启用状态
- void SetActive(bool flag);
-
- /// \~chinese
- /// @brief 获取物体所在物理世界
- World* GetWorld() const;
-
- /// \~chinese
- /// @brief 获取物体绑定的角色
- Actor* GetActor() const;
-
- /// \~chinese
- /// @brief 设置物体绑定的角色
- void SetActor(Actor* actor);
-
- /// \~chinese
- /// @brief 将物体信息更新到角色
- void UpdateActor();
-
- /// \~chinese
- /// @brief 将角色信息更新到物体
- void UpdateFromActor();
-
- b2Body* GetB2Body() const;
- void SetB2Body(b2Body* body);
-
- private:
- /// \~chinese
- /// @brief 销毁物体
- void UpdateFixtureFilter(b2Fixture* fixture);
-
- /// \~chinese
- /// @brief 销毁物体
- void Destroy();
-
- private:
- Actor* actor_;
- World* world_;
- b2Body* body_;
-
- uint16_t category_bits_;
- uint16_t mask_bits_;
- int16_t group_index_;
- };
-
- /** @} */
-
- inline bool Body::InitBody(World* world, ActorPtr actor) { return InitBody(world, actor.get()); }
-
- inline FixtureList Body::GetFixtureList() const { KGE_ASSERT(body_); return FixtureList(Fixture(body_->GetFixtureList())); }
-
- inline ContactEdgeList Body::GetContactList() const { KGE_ASSERT(body_); return ContactEdgeList(ContactEdge(body_->GetContactList())); }
-
- inline uint16_t Body::GetCategoryBits() const { return category_bits_; }
-
- inline uint16_t Body::GetMaskBits() const { return mask_bits_; }
-
- inline int16_t Body::GetGroupIndex() const { return group_index_; }
-
- inline float Body::GetBodyRotation() const { KGE_ASSERT(body_); return math::Radian2Degree(body_->GetAngle()); }
-
- inline void Body::SetBodyRotation(float angle) { SetBodyTransform(GetBodyPosition(), angle); }
-
- inline void Body::SetBodyPosition(Point const& pos) { SetBodyTransform(pos, GetBodyRotation()); }
-
- inline float Body::GetMass() const { KGE_ASSERT(body_); return body_->GetMass(); }
-
- inline float Body::GetInertia() const { KGE_ASSERT(body_); return body_->GetInertia(); }
-
- inline Body::Type Body::GetType() const { KGE_ASSERT(body_); return Type(body_->GetType()); }
-
- inline void Body::SetType(Type type) { KGE_ASSERT(body_); body_->SetType(static_cast(type)); }
-
- inline float Body::GetGravityScale() const { KGE_ASSERT(body_); return body_->GetGravityScale(); }
-
- inline void Body::SetGravityScale(float scale) { KGE_ASSERT(body_); body_->SetGravityScale(scale); }
-
- inline bool Body::IsIgnoreRotation() const { KGE_ASSERT(body_); return body_->IsFixedRotation(); }
-
- inline void Body::SetIgnoreRotation(bool flag) { KGE_ASSERT(body_); body_->SetFixedRotation(flag); }
-
- inline bool Body::IsBullet() const { KGE_ASSERT(body_); return body_->IsBullet(); }
-
- inline void Body::SetBullet(bool flag) { KGE_ASSERT(body_); body_->SetBullet(flag); }
-
- inline bool Body::IsAwake() const { KGE_ASSERT(body_); return body_->IsAwake(); }
-
- inline void Body::SetAwake(bool flag) { KGE_ASSERT(body_); body_->SetAwake(flag); }
-
- inline bool Body::IsSleepingAllowed() const { KGE_ASSERT(body_); return body_->IsSleepingAllowed(); }
-
- inline void Body::SetSleepingAllowed(bool flag) { KGE_ASSERT(body_); body_->SetSleepingAllowed(flag); }
-
- inline bool Body::IsActive() const { KGE_ASSERT(body_); return body_->IsActive(); }
-
- inline void Body::SetActive(bool flag) { KGE_ASSERT(body_); body_->SetActive(flag); }
-
- inline Actor* Body::GetActor() const { return actor_; }
-
- inline void Body::SetActor(Actor* actor) { actor_ = actor; }
-
- inline b2Body* Body::GetB2Body() const { return body_; }
-
- inline World* Body::GetWorld() const { return world_; }
- }
+namespace physics
+{
+class World;
+
+KGE_DECLARE_SMART_PTR(Body);
+
+/**
+ * \addtogroup Physics
+ * @{
+ */
+
+/// \~chinese
+/// @brief 物体
+class KGE_API Body : public virtual ObjectBase
+{
+public:
+ /// \~chinese
+ /// @brief 物体类型
+ enum class Type
+ {
+ Static = 0, ///< 静态物体
+ Kinematic, ///< 动力学物体
+ Dynamic, ///< 动态物体
+ };
+
+ Body();
+
+ virtual ~Body();
+
+ /// \~chinese
+ /// @brief 初始化
+ /// @param[in] world 物理世界
+ /// @param[in] actor 绑定的角色
+ bool InitBody(World* world, ActorPtr actor);
+
+ /// \~chinese
+ /// @brief 初始化
+ /// @param[in] world 物理世界
+ /// @param[in] actor 绑定的角色
+ bool InitBody(World* world, Actor* actor);
+
+ /// \~chinese
+ /// @brief 添加夹具
+ /// @param shape 物体形状
+ /// @param density 物体密度
+ Fixture AddFixture(Shape* shape, const Fixture::Param& param);
+
+ /// \~chinese
+ /// @brief 添加圆形夹具
+ /// @param radius 圆形半径
+ /// @param density 物体密度
+ Fixture AddCircleShape(float radius, float density = 0.f);
+
+ /// \~chinese
+ /// @brief 添加盒形夹具
+ /// @param size 盒大小
+ /// @param density 物体密度
+ Fixture AddBoxShape(Vec2 const& size, float density = 0.f);
+
+ /// \~chinese
+ /// @brief 添加多边形夹具
+ /// @param vertexs 多边形端点
+ /// @param density 物体密度
+ Fixture AddPolygonShape(Vector const& vertexs, float density = 0.f);
+
+ /// \~chinese
+ /// @brief 添加线段形夹具
+ /// @param p1 线段起点
+ /// @param p2 线段终点
+ /// @param density 物体密度
+ Fixture AddEdgeShape(Point const& p1, Point const& p2, float density = 0.f);
+
+ /// \~chinese
+ /// @brief 添加链条形夹具
+ /// @param vertexs 链条端点
+ /// @param loop 是否闭合
+ /// @param density 物体密度
+ Fixture AddChainShape(Vector const& vertexs, bool loop, float density = 0.f);
+
+ /// \~chinese
+ /// @brief 获取夹具列表
+ FixtureList GetFixtureList() const;
+
+ /// \~chinese
+ /// @brief 移除夹具
+ void RemoveFixture(Fixture const& fixture);
+
+ /// \~chinese
+ /// @brief 获取接触边列表
+ ContactEdgeList GetContactList() const;
+
+ /// \~chinese
+ /// @brief 获取类别码
+ uint16_t GetCategoryBits() const;
+
+ /// \~chinese
+ /// @brief 设置类别码
+ void SetCategoryBits(uint16_t category_bits);
+
+ /// \~chinese
+ /// @brief 获取碰撞掩码
+ uint16_t GetMaskBits() const;
+
+ /// \~chinese
+ /// @brief 设置碰撞掩码
+ void SetMaskBits(uint16_t mask_bits);
+
+ /// \~chinese
+ /// @brief 获取组索引
+ int16_t GetGroupIndex() const;
+
+ /// \~chinese
+ /// @brief 设置组索引
+ void SetGroupIndex(int16_t index);
+
+ /// \~chinese
+ /// @brief 获取旋转角度
+ float GetBodyRotation() const;
+
+ /// \~chinese
+ /// @brief 设置旋转角度
+ void SetBodyRotation(float angle);
+
+ /// \~chinese
+ /// @brief 获取物体位置
+ Point GetBodyPosition() const;
+
+ /// \~chinese
+ /// @brief 设置物体位置
+ void SetBodyPosition(Point const& pos);
+
+ /// \~chinese
+ /// @brief 位置和旋转变换
+ void SetBodyTransform(Point const& pos, float angle);
+
+ /// \~chinese
+ /// @brief 获取质量 [kg]
+ float GetMass() const;
+
+ /// \~chinese
+ /// @brief 获取惯性
+ float GetInertia() const;
+
+ /// \~chinese
+ /// @brief 获取质量数据
+ /// @param[out] mass 物体质量 [kg]
+ /// @param[out] center 质心位置
+ /// @param[out] inertia 惯性
+ void GetMassData(float* mass, Point* center, float* inertia) const;
+
+ /// \~chinese
+ /// @brief 设置质量数据
+ /// @param mass 物体质量 [kg]
+ /// @param center 质心位置
+ /// @param inertia 惯性
+ void SetMassData(float mass, Point const& center, float inertia);
+
+ /// \~chinese
+ /// @brief 重置质量数据
+ void ResetMassData();
+
+ /// \~chinese
+ /// @brief 获取世界坐标系上的点在物体上的位置
+ Point GetLocalPoint(Point const& world) const;
+
+ /// \~chinese
+ /// @brief 获取物体上的点在世界坐标系的位置
+ Point GetWorldPoint(Point const& local) const;
+
+ /// \~chinese
+ /// @brief 获取物体质心相对于物体的位置
+ Point GetLocalCenter() const;
+
+ /// \~chinese
+ /// @brief 获取物体质心位置
+ Point GetWorldCenter() const;
+
+ /// \~chinese
+ /// @brief 获取物体类型
+ Type GetType() const;
+
+ /// \~chinese
+ /// @brief 设置物体类型
+ void SetType(Type type);
+
+ /// \~chinese
+ /// @brief 获取物体受重力的比例
+ float GetGravityScale() const;
+
+ /// \~chinese
+ /// @brief 设置物体受重力的比例
+ void SetGravityScale(float scale);
+
+ /// \~chinese
+ /// @brief 施力
+ /// @param force 力的大小和方向
+ /// @param point 施力点
+ /// @param wake 是否唤醒物体
+ void ApplyForce(Vec2 const& force, Point const& point, bool wake = true);
+
+ /// \~chinese
+ /// @brief 给物体中心施力
+ /// @param force 力的大小和方向
+ /// @param wake 是否唤醒物体
+ void ApplyForceToCenter(Vec2 const& force, bool wake = true);
+
+ /// \~chinese
+ /// @brief 施加扭矩
+ /// @param torque 扭矩
+ /// @param wake 是否唤醒物体
+ void ApplyTorque(float torque, bool wake = false);
+
+ /// \~chinese
+ /// @brief 旋转角度是否固定
+ bool IsIgnoreRotation() const;
+
+ /// \~chinese
+ /// @brief 设置是否固定旋转角度
+ void SetIgnoreRotation(bool flag);
+
+ /// \~chinese
+ /// @brief 是否是子弹物体
+ bool IsBullet() const;
+
+ /// \~chinese
+ /// @brief 设置物体是否是子弹物体
+ void SetBullet(bool flag);
+
+ /// \~chinese
+ /// @brief 是否处于唤醒状态
+ bool IsAwake() const;
+
+ /// \~chinese
+ /// @brief 设置唤醒状态
+ void SetAwake(bool flag);
+
+ /// \~chinese
+ /// @brief 是否启用休眠
+ bool IsSleepingAllowed() const;
+
+ /// \~chinese
+ /// @brief 设置是否允许休眠
+ void SetSleepingAllowed(bool flag);
+
+ /// \~chinese
+ /// @brief 是否启用
+ bool IsActive() const;
+
+ /// \~chinese
+ /// @brief 设置启用状态
+ void SetActive(bool flag);
+
+ /// \~chinese
+ /// @brief 获取物体所在物理世界
+ World* GetWorld() const;
+
+ /// \~chinese
+ /// @brief 获取物体绑定的角色
+ Actor* GetActor() const;
+
+ /// \~chinese
+ /// @brief 设置物体绑定的角色
+ void SetActor(Actor* actor);
+
+ /// \~chinese
+ /// @brief 将物体信息更新到角色
+ void UpdateActor();
+
+ /// \~chinese
+ /// @brief 将角色信息更新到物体
+ void UpdateFromActor();
+
+ b2Body* GetB2Body() const;
+ void SetB2Body(b2Body* body);
+
+private:
+ /// \~chinese
+ /// @brief 销毁物体
+ void UpdateFixtureFilter(b2Fixture* fixture);
+
+ /// \~chinese
+ /// @brief 销毁物体
+ void Destroy();
+
+private:
+ Actor* actor_;
+ World* world_;
+ b2Body* body_;
+
+ uint16_t category_bits_;
+ uint16_t mask_bits_;
+ int16_t group_index_;
+};
+
+/** @} */
+
+inline bool Body::InitBody(World* world, ActorPtr actor)
+{
+ return InitBody(world, actor.get());
}
+
+inline FixtureList Body::GetFixtureList() const
+{
+ KGE_ASSERT(body_);
+ return FixtureList(Fixture(body_->GetFixtureList()));
+}
+
+inline ContactEdgeList Body::GetContactList() const
+{
+ KGE_ASSERT(body_);
+ return ContactEdgeList(ContactEdge(body_->GetContactList()));
+}
+
+inline uint16_t Body::GetCategoryBits() const
+{
+ return category_bits_;
+}
+
+inline uint16_t Body::GetMaskBits() const
+{
+ return mask_bits_;
+}
+
+inline int16_t Body::GetGroupIndex() const
+{
+ return group_index_;
+}
+
+inline float Body::GetBodyRotation() const
+{
+ KGE_ASSERT(body_);
+ return math::Radian2Degree(body_->GetAngle());
+}
+
+inline void Body::SetBodyRotation(float angle)
+{
+ SetBodyTransform(GetBodyPosition(), angle);
+}
+
+inline void Body::SetBodyPosition(Point const& pos)
+{
+ SetBodyTransform(pos, GetBodyRotation());
+}
+
+inline float Body::GetMass() const
+{
+ KGE_ASSERT(body_);
+ return body_->GetMass();
+}
+
+inline float Body::GetInertia() const
+{
+ KGE_ASSERT(body_);
+ return body_->GetInertia();
+}
+
+inline Body::Type Body::GetType() const
+{
+ KGE_ASSERT(body_);
+ return Type(body_->GetType());
+}
+
+inline void Body::SetType(Type type)
+{
+ KGE_ASSERT(body_);
+ body_->SetType(static_cast(type));
+}
+
+inline float Body::GetGravityScale() const
+{
+ KGE_ASSERT(body_);
+ return body_->GetGravityScale();
+}
+
+inline void Body::SetGravityScale(float scale)
+{
+ KGE_ASSERT(body_);
+ body_->SetGravityScale(scale);
+}
+
+inline bool Body::IsIgnoreRotation() const
+{
+ KGE_ASSERT(body_);
+ return body_->IsFixedRotation();
+}
+
+inline void Body::SetIgnoreRotation(bool flag)
+{
+ KGE_ASSERT(body_);
+ body_->SetFixedRotation(flag);
+}
+
+inline bool Body::IsBullet() const
+{
+ KGE_ASSERT(body_);
+ return body_->IsBullet();
+}
+
+inline void Body::SetBullet(bool flag)
+{
+ KGE_ASSERT(body_);
+ body_->SetBullet(flag);
+}
+
+inline bool Body::IsAwake() const
+{
+ KGE_ASSERT(body_);
+ return body_->IsAwake();
+}
+
+inline void Body::SetAwake(bool flag)
+{
+ KGE_ASSERT(body_);
+ body_->SetAwake(flag);
+}
+
+inline bool Body::IsSleepingAllowed() const
+{
+ KGE_ASSERT(body_);
+ return body_->IsSleepingAllowed();
+}
+
+inline void Body::SetSleepingAllowed(bool flag)
+{
+ KGE_ASSERT(body_);
+ body_->SetSleepingAllowed(flag);
+}
+
+inline bool Body::IsActive() const
+{
+ KGE_ASSERT(body_);
+ return body_->IsActive();
+}
+
+inline void Body::SetActive(bool flag)
+{
+ KGE_ASSERT(body_);
+ body_->SetActive(flag);
+}
+
+inline Actor* Body::GetActor() const
+{
+ return actor_;
+}
+
+inline void Body::SetActor(Actor* actor)
+{
+ actor_ = actor;
+}
+
+inline b2Body* Body::GetB2Body() const
+{
+ return body_;
+}
+
+inline World* Body::GetWorld() const
+{
+ return world_;
+}
+} // namespace physics
+} // namespace kiwano
diff --git a/src/kiwano-physics/Contact.cpp b/src/kiwano-physics/Contact.cpp
index db133c94..4df8b5b5 100644
--- a/src/kiwano-physics/Contact.cpp
+++ b/src/kiwano-physics/Contact.cpp
@@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 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
@@ -18,73 +18,73 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include
#include
+#include
#include
namespace kiwano
{
- namespace physics
- {
+namespace physics
+{
- Contact::Contact()
- : contact_(nullptr)
- {
- }
-
- Contact::Contact(b2Contact* contact)
- : Contact()
- {
- SetB2Contact(contact);
- }
-
- Fixture Contact::GetFixtureA() const
- {
- KGE_ASSERT(contact_);
- return Fixture(contact_->GetFixtureA());
- }
-
- Fixture Contact::GetFixtureB() const
- {
- KGE_ASSERT(contact_);
- return Fixture(contact_->GetFixtureB());
- }
-
- Body* Contact::GetBodyA() const
- {
- return GetFixtureA().GetBody();
- }
-
- Body* Contact::GetBodyB() const
- {
- return GetFixtureB().GetBody();
- }
-
- void Contact::SetTangentSpeed(float speed)
- {
- KGE_ASSERT(contact_);
-
- Body* body = GetFixtureA().GetBody();
- KGE_ASSERT(body);
-
- World* world = body->GetWorld();
- KGE_ASSERT(world);
-
- contact_->SetTangentSpeed(world->Stage2World(speed));
- }
-
- float Contact::GetTangentSpeed() const
- {
- KGE_ASSERT(contact_);
-
- const Body* body = GetFixtureA().GetBody();
- KGE_ASSERT(body);
-
- const World* world = body->GetWorld();
- KGE_ASSERT(world);
-
- return world->World2Stage(contact_->GetTangentSpeed());
- }
-
- }
+Contact::Contact()
+ : contact_(nullptr)
+{
}
+
+Contact::Contact(b2Contact* contact)
+ : Contact()
+{
+ SetB2Contact(contact);
+}
+
+Fixture Contact::GetFixtureA() const
+{
+ KGE_ASSERT(contact_);
+ return Fixture(contact_->GetFixtureA());
+}
+
+Fixture Contact::GetFixtureB() const
+{
+ KGE_ASSERT(contact_);
+ return Fixture(contact_->GetFixtureB());
+}
+
+Body* Contact::GetBodyA() const
+{
+ return GetFixtureA().GetBody();
+}
+
+Body* Contact::GetBodyB() const
+{
+ return GetFixtureB().GetBody();
+}
+
+void Contact::SetTangentSpeed(float speed)
+{
+ KGE_ASSERT(contact_);
+
+ Body* body = GetFixtureA().GetBody();
+ KGE_ASSERT(body);
+
+ World* world = body->GetWorld();
+ KGE_ASSERT(world);
+
+ contact_->SetTangentSpeed(world->Stage2World(speed));
+}
+
+float Contact::GetTangentSpeed() const
+{
+ KGE_ASSERT(contact_);
+
+ const Body* body = GetFixtureA().GetBody();
+ KGE_ASSERT(body);
+
+ const World* world = body->GetWorld();
+ KGE_ASSERT(world);
+
+ return world->World2Stage(contact_->GetTangentSpeed());
+}
+
+} // namespace physics
+} // namespace kiwano
diff --git a/src/kiwano-physics/Contact.h b/src/kiwano-physics/Contact.h
index 68b43fd0..5e5a9a79 100644
--- a/src/kiwano-physics/Contact.h
+++ b/src/kiwano-physics/Contact.h
@@ -1,15 +1,15 @@
// Copyright (c) 2018-2019 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
@@ -19,232 +19,277 @@
// THE SOFTWARE.
#pragma once
-#include
#include
+#include
namespace kiwano
{
- namespace physics
- {
- class Body;
+namespace physics
+{
+class Body;
- /**
- * \addtogroup Physics
- * @{
- */
+/**
+ * \addtogroup Physics
+ * @{
+ */
- /// \~chinese
- /// @brief 物理接触
- class KGE_API Contact
- {
- public:
- Contact();
- Contact(b2Contact* contact);
+/// \~chinese
+/// @brief 物理接触
+class KGE_API Contact
+{
+public:
+ Contact();
+ Contact(b2Contact* contact);
- /// \~chinese
- /// @brief 是否有效
- bool IsValid() const;
+ /// \~chinese
+ /// @brief 是否有效
+ bool IsValid() const;
- /// \~chinese
- /// @brief 是否是接触
- bool IsTouching() const;
+ /// \~chinese
+ /// @brief 是否是接触
+ bool IsTouching() const;
- /// \~chinese
- /// @brief 启用或禁用 (仅作用于一个时间步)
- void SetEnabled(bool flag);
+ /// \~chinese
+ /// @brief 启用或禁用 (仅作用于一个时间步)
+ void SetEnabled(bool flag);
- /// \~chinese
- /// @brief 是否启用
- bool IsEnabled() const;
+ /// \~chinese
+ /// @brief 是否启用
+ bool IsEnabled() const;
- /// \~chinese
- /// @brief 获取物体A的夹具
- Fixture GetFixtureA() const;
+ /// \~chinese
+ /// @brief 获取物体A的夹具
+ Fixture GetFixtureA() const;
- /// \~chinese
- /// @brief 获取物体B的夹具
- Fixture GetFixtureB() const;
+ /// \~chinese
+ /// @brief 获取物体B的夹具
+ Fixture GetFixtureB() const;
- /// \~chinese
- /// @brief 获取物体A
- Body* GetBodyA() const;
+ /// \~chinese
+ /// @brief 获取物体A
+ Body* GetBodyA() const;
- /// \~chinese
- /// @brief 获取物体B
- Body* GetBodyB() const;
+ /// \~chinese
+ /// @brief 获取物体B
+ Body* GetBodyB() const;
- /// \~chinese
- /// @brief 设置摩擦力
- void SetFriction(float friction);
+ /// \~chinese
+ /// @brief 设置摩擦力
+ void SetFriction(float friction);
- /// \~chinese
- /// @brief 获取摩擦力
- float GetFriction() const;
+ /// \~chinese
+ /// @brief 获取摩擦力
+ float GetFriction() const;
- /// \~chinese
- /// @brief 重置摩擦力
- void ResetFriction();
+ /// \~chinese
+ /// @brief 重置摩擦力
+ void ResetFriction();
- /// \~chinese
- /// @brief 设置弹性恢复
- void SetRestitution(float restitution);
+ /// \~chinese
+ /// @brief 设置弹性恢复
+ void SetRestitution(float restitution);
- /// \~chinese
- /// @brief 获取弹性恢复
- float GetRestitution() const;
+ /// \~chinese
+ /// @brief 获取弹性恢复
+ float GetRestitution() const;
- /// \~chinese
- /// @brief 重置弹性恢复
- void ResetRestitution();
+ /// \~chinese
+ /// @brief 重置弹性恢复
+ void ResetRestitution();
- /// \~chinese
- /// @brief 设置切线速度
- void SetTangentSpeed(float speed);
+ /// \~chinese
+ /// @brief 设置切线速度
+ void SetTangentSpeed(float speed);
- /// \~chinese
- /// @brief 获取切线速度
- float GetTangentSpeed() const;
+ /// \~chinese
+ /// @brief 获取切线速度
+ float GetTangentSpeed() const;
- b2Contact* GetB2Contact() const;
- void SetB2Contact(b2Contact* contact);
+ b2Contact* GetB2Contact() const;
+ void SetB2Contact(b2Contact* contact);
- bool operator== (const Contact& rhs) const;
- bool operator!= (const Contact& rhs) const;
+ bool operator==(const Contact& rhs) const;
+ bool operator!=(const Contact& rhs) const;
- private:
- b2Contact* contact_;
- };
+private:
+ b2Contact* contact_;
+};
+/// \~chinese
+/// @brief 物理接触列表
+class ContactList : public List
+{
+ template
+ class IteratorImpl : public std::iterator
+ {
+ using herit = std::iterator