添加CustomTextRenderer类,用于实现文字描边功能

This commit is contained in:
Nomango 2018-04-21 23:09:59 +08:00
parent 6d7550608c
commit f215632e60
8 changed files with 541 additions and 20 deletions

View File

@ -3,12 +3,15 @@
#include "..\e2dnode.h" #include "..\e2dnode.h"
static bool s_bShowFps = false; static bool s_bShowFps = false;
static float s_fDpiScaleX = 0;
static float s_fDpiScaleY = 0;
static IDWriteTextFormat * s_pTextFormat = nullptr; static IDWriteTextFormat * s_pTextFormat = nullptr;
static ID2D1Factory * s_pDirect2dFactory = nullptr; static ID2D1Factory * s_pDirect2dFactory = nullptr;
static ID2D1HwndRenderTarget * s_pRenderTarget = nullptr; static ID2D1HwndRenderTarget * s_pRenderTarget = nullptr;
static ID2D1SolidColorBrush * s_pSolidBrush = nullptr; static ID2D1SolidColorBrush * s_pSolidBrush = nullptr;
static IWICImagingFactory * s_pIWICFactory = nullptr; static IWICImagingFactory * s_pIWICFactory = nullptr;
static IDWriteFactory * s_pDWriteFactory = nullptr; static IDWriteFactory * s_pDWriteFactory = nullptr;
static e2d::CustomTextRenderer * s_pTextRenderer = nullptr;
static D2D1_COLOR_F s_nClearColor = D2D1::ColorF(D2D1::ColorF::Black); static D2D1_COLOR_F s_nClearColor = D2D1::ColorF(D2D1::ColorF::Black);
@ -46,21 +49,27 @@ bool e2d::Renderer::__createDeviceIndependentResources()
ASSERT(SUCCEEDED(hr), "Create IDWriteFactory Failed!"); ASSERT(SUCCEEDED(hr), "Create IDWriteFactory Failed!");
} }
if (SUCCEEDED(hr))
{
// 工厂将返回当前的系统 DPI这个值也将用来创建窗口
Renderer::getID2D1Factory()->GetDesktopDpi(&s_fDpiScaleX, &s_fDpiScaleY);
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// 创建文本格式化对象 // 创建文本格式化对象
hr = s_pDWriteFactory->CreateTextFormat( hr = s_pDWriteFactory->CreateTextFormat(
L"", L"",
NULL, NULL,
DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_WEIGHT_BOLD,
DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
18, 22,
L"", L"",
&s_pTextFormat &s_pTextFormat
); );
if (s_pTextFormat) if (SUCCEEDED(hr))
{ {
s_pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); s_pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
} }
@ -107,6 +116,16 @@ bool e2d::Renderer::__createDeviceResources()
); );
ASSERT(SUCCEEDED(hr), "Create ID2D1SolidColorBrush Failed!"); ASSERT(SUCCEEDED(hr), "Create ID2D1SolidColorBrush Failed!");
} }
if (SUCCEEDED(hr))
{
// 创建自定义的文字渲染器
s_pTextRenderer = new (std::nothrow) CustomTextRenderer(
s_pDirect2dFactory,
s_pRenderTarget,
s_pSolidBrush
);
}
} }
return SUCCEEDED(hr); return SUCCEEDED(hr);
@ -116,6 +135,7 @@ void e2d::Renderer::__discardDeviceResources()
{ {
SafeReleaseInterface(&s_pRenderTarget); SafeReleaseInterface(&s_pRenderTarget);
SafeReleaseInterface(&s_pSolidBrush); SafeReleaseInterface(&s_pSolidBrush);
SafeReleaseInterface(&s_pTextRenderer);
} }
void e2d::Renderer::__discardResources() void e2d::Renderer::__discardResources()
@ -124,6 +144,7 @@ void e2d::Renderer::__discardResources()
SafeReleaseInterface(&s_pDirect2dFactory); SafeReleaseInterface(&s_pDirect2dFactory);
SafeReleaseInterface(&s_pRenderTarget); SafeReleaseInterface(&s_pRenderTarget);
SafeReleaseInterface(&s_pSolidBrush); SafeReleaseInterface(&s_pSolidBrush);
SafeReleaseInterface(&s_pTextRenderer);
SafeReleaseInterface(&s_pIWICFactory); SafeReleaseInterface(&s_pIWICFactory);
SafeReleaseInterface(&s_pDWriteFactory); SafeReleaseInterface(&s_pDWriteFactory);
} }
@ -148,7 +169,7 @@ void e2d::Renderer::__render()
{ {
static int s_nRenderTimes = 0; static int s_nRenderTimes = 0;
static double s_fLastRenderTime = 0; static double s_fLastRenderTime = 0;
static e2d::String s_sFpsText = L""; static String s_sFpsText;
s_nRenderTimes++; s_nRenderTimes++;
@ -160,9 +181,31 @@ void e2d::Renderer::__render()
s_nRenderTimes = 0; s_nRenderTimes = 0;
} }
s_pSolidBrush->SetColor(D2D1::ColorF(D2D1::ColorF::White)); IDWriteTextLayout * pTextLayout = nullptr;
s_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
s_pRenderTarget->DrawTextW(s_sFpsText, (UINT32)s_sFpsText.getLength(), s_pTextFormat, D2D1::RectF(), s_pSolidBrush); hr = s_pDWriteFactory->CreateTextLayout(
s_sFpsText,
(UINT32)s_sFpsText.getLength(),
s_pTextFormat,
0,
0,
&pTextLayout
);
if (SUCCEEDED(hr))
{
s_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
s_pTextRenderer->SetTextStyle(
D2D1::ColorF(D2D1::ColorF::White),
D2D1::ColorF(D2D1::ColorF::Black),
2.0f,
1.0f
);
pTextLayout->Draw(NULL, s_pTextRenderer, 10, 0);
SafeReleaseInterface(&pTextLayout);
}
} }
// 终止渲染 // 终止渲染
@ -195,6 +238,16 @@ void e2d::Renderer::showFps(bool show)
s_bShowFps = show; s_bShowFps = show;
} }
float e2d::Renderer::getDpiScaleX()
{
return s_fDpiScaleX;
}
float e2d::Renderer::getDpiScaleY()
{
return s_fDpiScaleY;
}
ID2D1Factory * e2d::Renderer::getID2D1Factory() ID2D1Factory * e2d::Renderer::getID2D1Factory()
{ {
return s_pDirect2dFactory; return s_pDirect2dFactory;
@ -219,3 +272,8 @@ IDWriteFactory * e2d::Renderer::getIDWriteFactory()
{ {
return s_pDWriteFactory; return s_pDWriteFactory;
} }
e2d::CustomTextRenderer * e2d::Renderer::getCustomTextRenderer()
{
return s_pTextRenderer;
}

View File

@ -29,10 +29,8 @@ bool e2d::Window::__init()
// 因为 CreateWindow 函数使用的是像素大小,获取系统的 DPI 以使它 // 因为 CreateWindow 函数使用的是像素大小,获取系统的 DPI 以使它
// 适应窗口缩放 // 适应窗口缩放
float dpiX, dpiY; float dpiX = Renderer::getDpiScaleX();
float dpiY = Renderer::getDpiScaleY();
// 工厂将返回当前的系统 DPI这个值也将用来创建窗口
Renderer::getID2D1Factory()->GetDesktopDpi(&dpiX, &dpiY);
UINT nWidth = static_cast<UINT>(ceil(640 * dpiX / 96.f)); UINT nWidth = static_cast<UINT>(ceil(640 * dpiX / 96.f));
UINT nHeight = static_cast<UINT>(ceil(480 * dpiY / 96.f)); UINT nHeight = static_cast<UINT>(ceil(480 * dpiY / 96.f));

View File

@ -0,0 +1,346 @@
#include "..\e2dcustom.h"
using namespace e2d;
CustomTextRenderer::CustomTextRenderer(
ID2D1Factory* pD2DFactory,
ID2D1HwndRenderTarget* pRT,
ID2D1SolidColorBrush* pBrush
)
: cRefCount_(0)
, pD2DFactory_(pD2DFactory)
, pRT_(pRT)
, pBrush_(pBrush)
, sFillColor_()
, sOutlineColor_()
, fStrokeWidth_(1)
, fOpacity_(1)
{
pD2DFactory_->AddRef();
pRT_->AddRef();
pBrush_->AddRef();
}
CustomTextRenderer::~CustomTextRenderer()
{
SafeReleaseInterface(&pD2DFactory_);
SafeReleaseInterface(&pRT_);
SafeReleaseInterface(&pBrush_);
}
STDMETHODIMP_(void) CustomTextRenderer::SetTextStyle(
CONST D2D1_COLOR_F &fillColor,
CONST D2D1_COLOR_F &outlineColor,
FLOAT strokeWidth,
FLOAT opacity
)
{
sFillColor_ = fillColor;
sOutlineColor_ = outlineColor;
fStrokeWidth_ = strokeWidth;
fOpacity_ = opacity;
}
STDMETHODIMP CustomTextRenderer::DrawGlyphRun(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
__in DWRITE_GLYPH_RUN const* glyphRun,
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
IUnknown* clientDrawingEffect
)
{
HRESULT hr = S_OK;
ID2D1PathGeometry* pPathGeometry = NULL;
hr = pD2DFactory_->CreatePathGeometry(
&pPathGeometry
);
ID2D1GeometrySink* pSink = NULL;
if (SUCCEEDED(hr))
{
hr = pPathGeometry->Open(
&pSink
);
}
if (SUCCEEDED(hr))
{
hr = glyphRun->fontFace->GetGlyphRunOutline(
glyphRun->fontEmSize,
glyphRun->glyphIndices,
glyphRun->glyphAdvances,
glyphRun->glyphOffsets,
glyphRun->glyphCount,
glyphRun->isSideways,
glyphRun->bidiLevel % 2,
pSink
);
}
if (SUCCEEDED(hr))
{
hr = pSink->Close();
}
D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
1.0f, 0.0f,
0.0f, 1.0f,
baselineOriginX, baselineOriginY
);
ID2D1TransformedGeometry* pTransformedGeometry = NULL;
if (SUCCEEDED(hr))
{
hr = pD2DFactory_->CreateTransformedGeometry(
pPathGeometry,
&matrix,
&pTransformedGeometry
);
}
if (SUCCEEDED(hr))
{
pBrush_->SetOpacity(fOpacity_);
pBrush_->SetColor(sOutlineColor_);
pRT_->DrawGeometry(
pTransformedGeometry,
pBrush_,
fStrokeWidth_
);
pBrush_->SetColor(sFillColor_);
pRT_->FillGeometry(
pTransformedGeometry,
pBrush_
);
}
SafeReleaseInterface(&pPathGeometry);
SafeReleaseInterface(&pSink);
SafeReleaseInterface(&pTransformedGeometry);
return hr;
}
STDMETHODIMP CustomTextRenderer::DrawUnderline(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
__in DWRITE_UNDERLINE const* underline,
IUnknown* clientDrawingEffect
)
{
HRESULT hr;
D2D1_RECT_F rect = D2D1::RectF(
0,
underline->offset,
underline->width,
underline->offset + underline->thickness
);
ID2D1RectangleGeometry* pRectangleGeometry = NULL;
hr = pD2DFactory_->CreateRectangleGeometry(
&rect,
&pRectangleGeometry
);
D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
1.0f, 0.0f,
0.0f, 1.0f,
baselineOriginX, baselineOriginY
);
ID2D1TransformedGeometry* pTransformedGeometry = NULL;
if (SUCCEEDED(hr))
{
hr = pD2DFactory_->CreateTransformedGeometry(
pRectangleGeometry,
&matrix,
&pTransformedGeometry
);
}
if (SUCCEEDED(hr))
{
pBrush_->SetOpacity(fOpacity_);
pBrush_->SetColor(sOutlineColor_);
pRT_->DrawGeometry(
pTransformedGeometry,
pBrush_,
fStrokeWidth_
);
pBrush_->SetColor(sFillColor_);
pRT_->FillGeometry(
pTransformedGeometry,
pBrush_
);
}
SafeReleaseInterface(&pRectangleGeometry);
SafeReleaseInterface(&pTransformedGeometry);
return S_OK;
}
STDMETHODIMP CustomTextRenderer::DrawStrikethrough(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
__in DWRITE_STRIKETHROUGH const* strikethrough,
IUnknown* clientDrawingEffect
)
{
HRESULT hr;
D2D1_RECT_F rect = D2D1::RectF(
0,
strikethrough->offset,
strikethrough->width,
strikethrough->offset + strikethrough->thickness
);
ID2D1RectangleGeometry* pRectangleGeometry = NULL;
hr = pD2DFactory_->CreateRectangleGeometry(
&rect,
&pRectangleGeometry
);
D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(
1.0f, 0.0f,
0.0f, 1.0f,
baselineOriginX, baselineOriginY
);
ID2D1TransformedGeometry* pTransformedGeometry = NULL;
if (SUCCEEDED(hr))
{
hr = pD2DFactory_->CreateTransformedGeometry(
pRectangleGeometry,
&matrix,
&pTransformedGeometry
);
}
if (SUCCEEDED(hr))
{
pBrush_->SetOpacity(fOpacity_);
pBrush_->SetColor(sOutlineColor_);
pRT_->DrawGeometry(
pTransformedGeometry,
pBrush_,
fStrokeWidth_
);
pBrush_->SetColor(sFillColor_);
pRT_->FillGeometry(
pTransformedGeometry,
pBrush_
);
}
SafeReleaseInterface(&pRectangleGeometry);
SafeReleaseInterface(&pTransformedGeometry);
return S_OK;
}
STDMETHODIMP CustomTextRenderer::DrawInlineObject(
__maybenull void* clientDrawingContext,
FLOAT originX,
FLOAT originY,
IDWriteInlineObject* inlineObject,
BOOL isSideways,
BOOL isRightToLeft,
IUnknown* clientDrawingEffect
)
{
return E_NOTIMPL;
}
STDMETHODIMP_(unsigned long) CustomTextRenderer::AddRef()
{
return InterlockedIncrement(&cRefCount_);
}
STDMETHODIMP_(unsigned long) CustomTextRenderer::Release()
{
unsigned long newCount = InterlockedDecrement(&cRefCount_);
if (newCount == 0)
{
delete this;
return 0;
}
return newCount;
}
STDMETHODIMP CustomTextRenderer::IsPixelSnappingDisabled(
__maybenull void* clientDrawingContext,
__out BOOL* isDisabled
)
{
*isDisabled = FALSE;
return S_OK;
}
STDMETHODIMP CustomTextRenderer::GetCurrentTransform(
__maybenull void* clientDrawingContext,
__out DWRITE_MATRIX* transform
)
{
pRT_->GetTransform(reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));
return S_OK;
}
STDMETHODIMP CustomTextRenderer::GetPixelsPerDip(
__maybenull void* clientDrawingContext,
__out FLOAT* pixelsPerDip
)
{
float x, yUnused;
pRT_->GetDpi(&x, &yUnused);
*pixelsPerDip = x / 96;
return S_OK;
}
STDMETHODIMP CustomTextRenderer::QueryInterface(
IID const& riid,
void** ppvObject
)
{
if (__uuidof(IDWriteTextRenderer) == riid)
{
*ppvObject = this;
}
else if (__uuidof(IDWritePixelSnapping) == riid)
{
*ppvObject = this;
}
else if (__uuidof(IUnknown) == riid)
{
*ppvObject = this;
}
else
{
*ppvObject = NULL;
return E_FAIL;
}
AddRef();
return S_OK;
}

View File

@ -241,6 +241,12 @@ public:
bool show = true bool show = true
); );
// 获取系统 DPI 缩放
static float getDpiScaleX();
// 获取系统 DPI 缩放
static float getDpiScaleY();
// 获取 ID2D1Factory 对象 // 获取 ID2D1Factory 对象
static ID2D1Factory * getID2D1Factory(); static ID2D1Factory * getID2D1Factory();
@ -256,6 +262,9 @@ public:
// 获取 IDWriteFactory 对象 // 获取 IDWriteFactory 对象
static IDWriteFactory * getIDWriteFactory(); static IDWriteFactory * getIDWriteFactory();
// 获取自定义的文字渲染器
static CustomTextRenderer * getCustomTextRenderer();
private: private:
// 渲染游戏画面 // 渲染游戏画面
static void __render(); static void __render();

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "e2dmacros.h" #include "e2dmacros.h"
#include "e2dcustom.h"
#include <set> #include <set>
#include <stack> #include <stack>
#include <vector> #include <vector>
@ -677,13 +678,7 @@ protected:
}; };
template<typename T>
inline void SafeDelete(T** p) { if (*p) { delete *p; *p = nullptr; } }
template<typename Object> template<typename Object>
inline void SafeRelease(Object** p) { if (*p) { (*p)->release(); *p = nullptr; } } inline void SafeRelease(Object** p) { if (*p) { (*p)->release(); *p = nullptr; } }
template<class Interface>
inline void SafeReleaseInterface(Interface **pp) { if (*pp != nullptr) { (*pp)->Release(); (*pp) = nullptr; } }
} }

106
core/e2dcustom.h Normal file
View File

@ -0,0 +1,106 @@
#pragma once
#include "e2dmacros.h"
namespace e2d
{
template<class Interface>
inline void SafeReleaseInterface(Interface **pp)
{
if (*pp != nullptr)
{
(*pp)->Release();
(*pp) = nullptr;
}
}
// ×Ô¶¨ÒåµÄÎÄ×ÖäÖȾÆ÷
class CustomTextRenderer
: public IDWriteTextRenderer
{
public:
CustomTextRenderer(
ID2D1Factory* pD2DFactory,
ID2D1HwndRenderTarget* pRT,
ID2D1SolidColorBrush* pBrush
);
~CustomTextRenderer();
STDMETHOD_(void, SetTextStyle)(
CONST D2D1_COLOR_F &fillColor,
CONST D2D1_COLOR_F &outlineColor,
FLOAT strokeWidth,
FLOAT opacity
);
STDMETHOD(DrawGlyphRun)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
__in DWRITE_GLYPH_RUN const* glyphRun,
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
IUnknown* clientDrawingEffect
);
STDMETHOD(DrawUnderline)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
__in DWRITE_UNDERLINE const* underline,
IUnknown* clientDrawingEffect
);
STDMETHOD(DrawStrikethrough)(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
__in DWRITE_STRIKETHROUGH const* strikethrough,
IUnknown* clientDrawingEffect
);
STDMETHOD(DrawInlineObject)(
__maybenull void* clientDrawingContext,
FLOAT originX,
FLOAT originY,
IDWriteInlineObject* inlineObject,
BOOL isSideways,
BOOL isRightToLeft,
IUnknown* clientDrawingEffect
);
STDMETHOD(IsPixelSnappingDisabled)(
__maybenull void* clientDrawingContext,
__out BOOL* isDisabled
);
STDMETHOD(GetCurrentTransform)(
__maybenull void* clientDrawingContext,
__out DWRITE_MATRIX* transform
);
STDMETHOD(GetPixelsPerDip)(
__maybenull void* clientDrawingContext,
__out FLOAT* pixelsPerDip
);
public:
unsigned long STDMETHODCALLTYPE AddRef();
unsigned long STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
IID const& riid,
void** ppvObject
);
private:
unsigned long cRefCount_;
D2D1_COLOR_F sFillColor_;
D2D1_COLOR_F sOutlineColor_;
FLOAT fStrokeWidth_;
FLOAT fOpacity_;
ID2D1Factory* pD2DFactory_;
ID2D1HwndRenderTarget* pRT_;
ID2D1SolidColorBrush* pBrush_;
};
}

View File

@ -222,6 +222,7 @@
<ClCompile Include="..\..\core\Common\Size.cpp" /> <ClCompile Include="..\..\core\Common\Size.cpp" />
<ClCompile Include="..\..\core\Common\String.cpp" /> <ClCompile Include="..\..\core\Common\String.cpp" />
<ClCompile Include="..\..\core\Common\Image.cpp" /> <ClCompile Include="..\..\core\Common\Image.cpp" />
<ClCompile Include="..\..\core\Custom\CustomTextRenderer.cpp" />
<ClCompile Include="..\..\core\Manager\ActionManager.cpp" /> <ClCompile Include="..\..\core\Manager\ActionManager.cpp" />
<ClCompile Include="..\..\core\Manager\InputManager.cpp" /> <ClCompile Include="..\..\core\Manager\InputManager.cpp" />
<ClCompile Include="..\..\core\Manager\MusicManager.cpp" /> <ClCompile Include="..\..\core\Manager\MusicManager.cpp" />
@ -255,6 +256,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\core\e2daction.h" /> <ClInclude Include="..\..\core\e2daction.h" />
<ClInclude Include="..\..\core\e2dcustom.h" />
<ClInclude Include="..\..\core\easy2d.h" /> <ClInclude Include="..\..\core\easy2d.h" />
<ClInclude Include="..\..\core\e2dbase.h" /> <ClInclude Include="..\..\core\e2dbase.h" />
<ClInclude Include="..\..\core\e2dcommon.h" /> <ClInclude Include="..\..\core\e2dcommon.h" />

View File

@ -31,6 +31,9 @@
<Filter Include="Tool\Listener"> <Filter Include="Tool\Listener">
<UniqueIdentifier>{d3968182-2399-40d4-8e39-accb4711018c}</UniqueIdentifier> <UniqueIdentifier>{d3968182-2399-40d4-8e39-accb4711018c}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Custom">
<UniqueIdentifier>{3475b59d-d50c-43b1-8334-bcb9e1703ed2}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\core\Base\Input.cpp"> <ClCompile Include="..\..\core\Base\Input.cpp">
@ -219,6 +222,9 @@
<ClCompile Include="..\..\core\Tool\Listener\Listener.cpp"> <ClCompile Include="..\..\core\Tool\Listener\Listener.cpp">
<Filter>Tool\Listener</Filter> <Filter>Tool\Listener</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\core\Custom\CustomTextRenderer.cpp">
<Filter>Custom</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\core\easy2d.h" /> <ClInclude Include="..\..\core\easy2d.h" />
@ -232,5 +238,6 @@
<ClInclude Include="..\..\core\e2dshape.h" /> <ClInclude Include="..\..\core\e2dshape.h" />
<ClInclude Include="..\..\core\e2dtool.h" /> <ClInclude Include="..\..\core\e2dtool.h" />
<ClInclude Include="..\..\core\e2dtransition.h" /> <ClInclude Include="..\..\core\e2dtransition.h" />
<ClInclude Include="..\..\core\e2dcustom.h" />
</ItemGroup> </ItemGroup>
</Project> </Project>