diff --git a/core/Base/Game.cpp b/core/Base/Game.cpp
index aa9c6f9b..0ef0bc7e 100644
--- a/core/Base/Game.cpp
+++ b/core/Base/Game.cpp
@@ -197,6 +197,9 @@ void e2d::Game::quit()
void e2d::Game::destroy()
{
+ if (!s_bInitialized)
+ return;
+
// 删除所有场景
SceneManager::__uninit();
// 删除输入监听器
diff --git a/core/Base/Renderer.cpp b/core/Base/Renderer.cpp
index 0a391da1..7c1cc5a1 100644
--- a/core/Base/Renderer.cpp
+++ b/core/Base/Renderer.cpp
@@ -11,7 +11,7 @@ static ID2D1HwndRenderTarget * s_pRenderTarget = nullptr;
static ID2D1SolidColorBrush * s_pSolidBrush = nullptr;
static IWICImagingFactory * s_pIWICFactory = nullptr;
static IDWriteFactory * s_pDWriteFactory = nullptr;
-static e2d::CustomTextRenderer * s_pTextRenderer = nullptr;
+static e2d::TextRenderer * s_pTextRenderer = nullptr;
static D2D1_COLOR_F s_nClearColor = D2D1::ColorF(D2D1::ColorF::Black);
@@ -120,7 +120,7 @@ bool e2d::Renderer::__createDeviceResources()
if (SUCCEEDED(hr))
{
// 创建自定义的文字渲染器
- s_pTextRenderer = new (std::nothrow) CustomTextRenderer(
+ s_pTextRenderer = new (std::nothrow) TextRenderer(
s_pDirect2dFactory,
s_pRenderTarget,
s_pSolidBrush
@@ -279,7 +279,7 @@ IDWriteFactory * e2d::Renderer::getIDWriteFactory()
return s_pDWriteFactory;
}
-e2d::CustomTextRenderer * e2d::Renderer::getCustomTextRenderer()
+e2d::TextRenderer * e2d::Renderer::getTextRenderer()
{
return s_pTextRenderer;
}
diff --git a/core/Custom/CustomTextRenderer.cpp b/core/Custom/TextRenderer.cpp
similarity index 91%
rename from core/Custom/CustomTextRenderer.cpp
rename to core/Custom/TextRenderer.cpp
index 3bed710d..6b4036ad 100644
--- a/core/Custom/CustomTextRenderer.cpp
+++ b/core/Custom/TextRenderer.cpp
@@ -3,7 +3,7 @@
using namespace e2d;
-CustomTextRenderer::CustomTextRenderer(
+TextRenderer::TextRenderer(
ID2D1Factory* pD2DFactory,
ID2D1HwndRenderTarget* pRT,
ID2D1SolidColorBrush* pBrush
@@ -23,14 +23,14 @@ CustomTextRenderer::CustomTextRenderer(
pBrush_->AddRef();
}
-CustomTextRenderer::~CustomTextRenderer()
+TextRenderer::~TextRenderer()
{
SafeReleaseInterface(pD2DFactory_);
SafeReleaseInterface(pRT_);
SafeReleaseInterface(pBrush_);
}
-STDMETHODIMP_(void) CustomTextRenderer::SetTextStyle(
+STDMETHODIMP_(void) TextRenderer::SetTextStyle(
CONST D2D1_COLOR_F &fillColor,
BOOL hasOutline,
CONST D2D1_COLOR_F &outlineColor,
@@ -45,7 +45,7 @@ STDMETHODIMP_(void) CustomTextRenderer::SetTextStyle(
nOutlineJoin_ = outlineJoin;
}
-STDMETHODIMP CustomTextRenderer::DrawGlyphRun(
+STDMETHODIMP TextRenderer::DrawGlyphRun(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
@@ -152,7 +152,7 @@ STDMETHODIMP CustomTextRenderer::DrawGlyphRun(
return hr;
}
-STDMETHODIMP CustomTextRenderer::DrawUnderline(
+STDMETHODIMP TextRenderer::DrawUnderline(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
@@ -237,7 +237,7 @@ STDMETHODIMP CustomTextRenderer::DrawUnderline(
return S_OK;
}
-STDMETHODIMP CustomTextRenderer::DrawStrikethrough(
+STDMETHODIMP TextRenderer::DrawStrikethrough(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
@@ -322,7 +322,7 @@ STDMETHODIMP CustomTextRenderer::DrawStrikethrough(
return S_OK;
}
-STDMETHODIMP CustomTextRenderer::DrawInlineObject(
+STDMETHODIMP TextRenderer::DrawInlineObject(
__maybenull void* clientDrawingContext,
FLOAT originX,
FLOAT originY,
@@ -335,12 +335,12 @@ STDMETHODIMP CustomTextRenderer::DrawInlineObject(
return E_NOTIMPL;
}
-STDMETHODIMP_(unsigned long) CustomTextRenderer::AddRef()
+STDMETHODIMP_(unsigned long) TextRenderer::AddRef()
{
return InterlockedIncrement(&cRefCount_);
}
-STDMETHODIMP_(unsigned long) CustomTextRenderer::Release()
+STDMETHODIMP_(unsigned long) TextRenderer::Release()
{
unsigned long newCount = InterlockedDecrement(&cRefCount_);
@@ -353,7 +353,7 @@ STDMETHODIMP_(unsigned long) CustomTextRenderer::Release()
return newCount;
}
-STDMETHODIMP CustomTextRenderer::IsPixelSnappingDisabled(
+STDMETHODIMP TextRenderer::IsPixelSnappingDisabled(
__maybenull void* clientDrawingContext,
__out BOOL* isDisabled
)
@@ -362,7 +362,7 @@ STDMETHODIMP CustomTextRenderer::IsPixelSnappingDisabled(
return S_OK;
}
-STDMETHODIMP CustomTextRenderer::GetCurrentTransform(
+STDMETHODIMP TextRenderer::GetCurrentTransform(
__maybenull void* clientDrawingContext,
__out DWRITE_MATRIX* transform
)
@@ -371,7 +371,7 @@ STDMETHODIMP CustomTextRenderer::GetCurrentTransform(
return S_OK;
}
-STDMETHODIMP CustomTextRenderer::GetPixelsPerDip(
+STDMETHODIMP TextRenderer::GetPixelsPerDip(
__maybenull void* clientDrawingContext,
__out FLOAT* pixelsPerDip
)
@@ -384,7 +384,7 @@ STDMETHODIMP CustomTextRenderer::GetPixelsPerDip(
return S_OK;
}
-STDMETHODIMP CustomTextRenderer::QueryInterface(
+STDMETHODIMP TextRenderer::QueryInterface(
IID const& riid,
void** ppvObject
)
diff --git a/core/Custom/VoiceCallback.cpp b/core/Custom/VoiceCallback.cpp
new file mode 100644
index 00000000..c4eb7da7
--- /dev/null
+++ b/core/Custom/VoiceCallback.cpp
@@ -0,0 +1,64 @@
+#include "..\e2dcustom.h"
+#include "..\e2dbase.h"
+#include "..\e2dtool.h"
+
+e2d::VoiceCallback::VoiceCallback(Music * music)
+ : _music(music)
+{
+}
+
+e2d::VoiceCallback::~VoiceCallback()
+{
+}
+
+void e2d::VoiceCallback::OnLoopEnd(void * pBufferContext)
+{
+ if (_loopEndFunc)
+ {
+ _loopEndFunc();
+ }
+}
+
+void e2d::VoiceCallback::OnStreamEnd()
+{
+ if (_streamEndFunc)
+ {
+ _streamEndFunc();
+ }
+}
+
+void e2d::VoiceCallback::OnBufferEnd(void * pBufferContext)
+{
+ if (_loopEndFunc)
+ {
+ _loopEndFunc();
+ }
+ e2d::GC::release(_music);
+}
+
+void e2d::VoiceCallback::OnBufferStart(void * pBufferContext)
+{
+ e2d::GC::retain(_music);
+}
+
+void e2d::VoiceCallback::OnVoiceProcessingPassEnd()
+{
+}
+
+void e2d::VoiceCallback::OnVoiceProcessingPassStart(UINT32 SamplesRequired)
+{
+}
+
+void e2d::VoiceCallback::OnVoiceError(void * pBufferContext, HRESULT Error)
+{
+}
+
+void e2d::VoiceCallback::SetFuncOnStreamEnd(const Function & func)
+{
+ _streamEndFunc = func;
+}
+
+void e2d::VoiceCallback::SetFuncOnLoopEnd(const Function & func)
+{
+ _loopEndFunc = func;
+}
\ No newline at end of file
diff --git a/core/Node/Text.cpp b/core/Node/Text.cpp
index e39ba8eb..b92aaefb 100644
--- a/core/Node/Text.cpp
+++ b/core/Node/Text.cpp
@@ -318,7 +318,7 @@ void e2d::Text::onRender()
// 设置画刷颜色和透明度
Renderer::getSolidColorBrush()->SetOpacity(_displayOpacity);
// 获取文本渲染器
- auto pTextRenderer = Renderer::getCustomTextRenderer();
+ auto pTextRenderer = Renderer::getTextRenderer();
pTextRenderer->SetTextStyle(
_style.color.toD2DColorF(),
_style.hasOutline,
diff --git a/core/Tool/Music.cpp b/core/Tool/Music.cpp
index 383b2b59..afa7bdc7 100644
--- a/core/Tool/Music.cpp
+++ b/core/Tool/Music.cpp
@@ -34,6 +34,7 @@ e2d::Music::Music()
, _waveData(nullptr)
, _dwSize(0)
, _voice(nullptr)
+ , _voiceCallback(this)
{
}
@@ -46,6 +47,7 @@ e2d::Music::Music(const e2d::String & filePath)
, _waveData(nullptr)
, _dwSize(0)
, _voice(nullptr)
+ , _voiceCallback(this)
{
this->open(filePath);
}
@@ -59,6 +61,7 @@ e2d::Music::Music(int resNameId, const String & resType)
, _waveData(nullptr)
, _dwSize(0)
, _voice(nullptr)
+ , _voiceCallback(this)
{
this->open(resNameId, resType);
}
@@ -128,7 +131,7 @@ bool e2d::Music::open(const e2d::String& filePath)
// 创建音源
HRESULT hr;
- if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx)))
+ if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &this->_voiceCallback)))
{
TraceError(L"Create source voice error", hr);
SAFE_DELETE_ARRAY(_waveData);
@@ -207,7 +210,7 @@ bool e2d::Music::open(int resNameId, const e2d::String& resType)
// 创建音源
HRESULT hr;
- if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx)))
+ if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &this->_voiceCallback)))
{
TraceError(L"Create source voice error", hr);
SAFE_DELETE_ARRAY(_waveData);
@@ -358,6 +361,16 @@ bool e2d::Music::setVolume(double volume)
return false;
}
+void e2d::Music::setFuncOnEnd(const Function & func)
+{
+ _voiceCallback.SetFuncOnStreamEnd(func);
+}
+
+void e2d::Music::setFuncOnLoopEnd(const Function & func)
+{
+ _voiceCallback.SetFuncOnLoopEnd(func);
+}
+
bool e2d::Music::_readMMIO()
{
MMCKINFO ckIn;
diff --git a/core/e2dbase.h b/core/e2dbase.h
index 8d73852e..7d41e214 100644
--- a/core/e2dbase.h
+++ b/core/e2dbase.h
@@ -1,6 +1,7 @@
#pragma once
#include "e2dmacros.h"
#include "e2dcommon.h"
+#include "e2dcustom.h"
// Base Classes
@@ -400,8 +401,8 @@ public:
// 获取 IDWriteFactory 对象
static IDWriteFactory * getIDWriteFactory();
- // 获取自定义的文字渲染器
- static CustomTextRenderer * getCustomTextRenderer();
+ // 获取文字渲染器
+ static TextRenderer * getTextRenderer();
private:
// 渲染游戏画面
diff --git a/core/e2dcommon.h b/core/e2dcommon.h
index 7cfb4982..93d2a4a5 100644
--- a/core/e2dcommon.h
+++ b/core/e2dcommon.h
@@ -1,12 +1,10 @@
#pragma once
#include "e2dmacros.h"
-#include "e2dcustom.h"
namespace e2d
{
-
// 方向
enum class Direction : int
{
diff --git a/core/e2dcustom.h b/core/e2dcustom.h
index d82ed664..fb2b1376 100644
--- a/core/e2dcustom.h
+++ b/core/e2dcustom.h
@@ -1,5 +1,6 @@
#pragma once
#include "e2dmacros.h"
+#include "e2dcommon.h"
namespace e2d
{
@@ -13,18 +14,68 @@ namespace e2d
}
}
- // 自定义的文字渲染器
- class CustomTextRenderer
+ class Music;
+
+ // 音源回调
+ class VoiceCallback
+ : public IXAudio2VoiceCallback
+ {
+ public:
+ VoiceCallback(Music * music);
+ ~VoiceCallback();
+
+ void __stdcall OnStreamEnd();
+
+ void __stdcall OnBufferEnd(
+ void * pBufferContext
+ );
+
+ void __stdcall OnBufferStart(
+ void * pBufferContext
+ );
+
+ void __stdcall OnLoopEnd(
+ void * pBufferContext
+ );
+
+ void __stdcall OnVoiceProcessingPassEnd();
+
+ void __stdcall OnVoiceProcessingPassStart(
+ UINT32 SamplesRequired
+ );
+
+ void __stdcall OnVoiceError(
+ void * pBufferContext,
+ HRESULT Error
+ );
+
+ void SetFuncOnStreamEnd(
+ const Function& func
+ );
+
+ void SetFuncOnLoopEnd(
+ const Function& func
+ );
+
+ protected:
+ Music * _music;
+ Function _loopEndFunc;
+ Function _streamEndFunc;
+ };
+
+
+ // 文字渲染器
+ class TextRenderer
: public IDWriteTextRenderer
{
public:
- CustomTextRenderer(
+ TextRenderer(
ID2D1Factory* pD2DFactory,
ID2D1HwndRenderTarget* pRT,
ID2D1SolidColorBrush* pBrush
);
- ~CustomTextRenderer();
+ ~TextRenderer();
STDMETHOD_(void, SetTextStyle)(
CONST D2D1_COLOR_F &fillColor,
diff --git a/core/e2dtool.h b/core/e2dtool.h
index 2bd03146..e6eb8e6d 100644
--- a/core/e2dtool.h
+++ b/core/e2dtool.h
@@ -96,13 +96,23 @@ public:
// 关闭并回收资源
void close();
+ // 是否正在播放
+ bool isPlaying() const;
+
// 设置音量
bool setVolume(
double volume
);
- // 是否正在播放
- bool isPlaying() const;
+ // 设置播放结束时的执行函数
+ void setFuncOnEnd(
+ const Function& func
+ );
+
+ // 设置循环播放中每一次播放结束时的执行函数
+ void setFuncOnLoopEnd(
+ const Function& func
+ );
// 获取 IXAudio2SourceVoice 对象
IXAudio2SourceVoice * getIXAudio2SourceVoice() const;
@@ -144,6 +154,7 @@ protected:
MMCKINFO _ck;
MMCKINFO _ckRiff;
WAVEFORMATEX* _wfx;
+ VoiceCallback _voiceCallback;
IXAudio2SourceVoice* _voice;
};
diff --git a/project/vs2017/Easy2D.vcxproj b/project/vs2017/Easy2D.vcxproj
index 2e1c2a1a..c7846384 100644
--- a/project/vs2017/Easy2D.vcxproj
+++ b/project/vs2017/Easy2D.vcxproj
@@ -235,7 +235,8 @@
-
+
+
diff --git a/project/vs2017/Easy2D.vcxproj.filters b/project/vs2017/Easy2D.vcxproj.filters
index ee9b4821..e8ce7e26 100644
--- a/project/vs2017/Easy2D.vcxproj.filters
+++ b/project/vs2017/Easy2D.vcxproj.filters
@@ -144,9 +144,6 @@
Node\Shape
-
- Custom
-
Common
@@ -225,6 +222,12 @@
Common
+
+ Custom
+
+
+ Custom
+