add GifSprite

This commit is contained in:
Nomango 2019-07-31 16:22:33 +08:00
parent 2f2cbcd4f1
commit 961b864dee
11 changed files with 375 additions and 226 deletions

View File

@ -21,27 +21,19 @@
#include "GifImage.h"
#include "../base/logs.h"
#include "../platform/modules.h"
#include "../utils/FileUtil.h"
namespace kiwano
{
GifImage::GifImage()
: animating_(false)
, next_index_(0)
, total_loop_count_(1)
, loop_count_(0)
, frames_count_(0)
: frames_count_(0)
, disposal_type_(DisposalType::Unknown)
, width_in_pixels_(0)
, height_in_pixels_(0)
, frame_delay_(0)
, frame_position_{}
, bg_color_{}
{
factory_ = Renderer::Instance()->GetD2DDeviceResources()->GetWICImagingFactory();
auto ctx = Renderer::Instance()->GetD2DDeviceResources()->GetDeviceContext();
ThrowIfFailed(
ctx->CreateCompatibleRenderTarget(&frame_rt_)
);
}
GifImage::GifImage(Resource const& res)
@ -54,23 +46,25 @@ namespace kiwano
{
HRESULT hr = S_OK;
next_index_ = 0;
loop_count_ = 0;
frames_count_ = 0;
disposal_type_ = DisposalType::None;
saved_frame_.Reset();
decoder_.Reset();
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetWICImagingFactory();
if (res.IsFileType())
{
if (!modules::Shlwapi::Get().PathFileExistsW(res.GetFileName().c_str()))
#ifdef KGE_DEBUG
if (!FileUtil::ExistsFile(res.GetFileName().c_str()))
{
KGE_WARNING_LOG(L"Gif file '%s' not found!", res.GetFileName().c_str());
return false;
}
#endif
hr = factory_->CreateDecoderFromFilename(
hr = factory->CreateDecoderFromFilename(
res.GetFileName().c_str(),
nullptr,
GENERIC_READ,
@ -87,7 +81,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
hr = factory_->CreateStream(&stream);
hr = factory->CreateStream(&stream);
}
if (SUCCEEDED(hr))
@ -100,7 +94,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
hr = factory_->CreateDecoderFromStream(
hr = factory->CreateDecoderFromStream(
stream.Get(),
nullptr,
WICDecodeMetadataCacheOnLoad,
@ -114,54 +108,9 @@ namespace kiwano
hr = GetGlobalMetadata();
}
if (SUCCEEDED(hr))
{
if (frames_count_ > 0)
{
hr = ComposeNextFrame();
}
}
return SUCCEEDED(hr);
}
void GifImage::Update(Duration dt)
{
VisualNode::Update(dt);
if (animating_)
{
frame_elapsed_ += dt;
if (frame_delay_ <= frame_elapsed_)
{
frame_delay_ -= frame_elapsed_;
frame_elapsed_ = 0;
ComposeNextFrame();
}
}
}
void GifImage::Restart()
{
animating_ = true;
next_index_ = 0;
loop_count_ = 0;
disposal_type_ = DisposalType::None;
}
void GifImage::OnRender()
{
if (frame_rt_)
{
ComPtr<ID2D1Bitmap> frame_to_render;
if (SUCCEEDED(frame_rt_->GetBitmap(&frame_to_render)))
{
Rect bounds = GetBounds();
Renderer::Instance()->DrawBitmap(frame_to_render, bounds, bounds);
}
}
}
HRESULT GifImage::GetRawFrame(UINT frame_index)
{
ComPtr<IWICFormatConverter> converter;
@ -176,7 +125,8 @@ namespace kiwano
if (SUCCEEDED(hr))
{
// Format convert to 32bppPBGRA which D2D expects
hr = factory_->CreateFormatConverter(&converter);
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetWICImagingFactory();
hr = factory->CreateFormatConverter(&converter);
}
if (SUCCEEDED(hr))
@ -269,7 +219,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
unsigned int frame_delay = 0;
frame_delay_ = 0;
hr = metadata_reader->GetMetadataByName(
L"/grctlext/Delay",
@ -280,24 +230,22 @@ namespace kiwano
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
if (SUCCEEDED(hr))
{
hr = UIntMult(prop_val.uiVal, 10, &frame_delay);
hr = UIntMult(prop_val.uiVal, 10, &frame_delay_);
}
PropVariantClear(&prop_val);
}
else
{
frame_delay = 0;
frame_delay_ = 0;
}
if (SUCCEEDED(hr))
{
// 插入一个强制延迟
if (frame_delay < 90)
if (frame_delay_ < 90)
{
frame_delay = 90;
frame_delay_ = 90;
}
frame_delay_.SetMilliseconds(static_cast<long>(frame_delay));
}
}
@ -341,8 +289,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
hr = decoder_->GetMetadataQueryReader(
&metadata_reader);
hr = decoder_->GetMetadataQueryReader(&metadata_reader);
}
if (SUCCEEDED(hr))
@ -428,8 +375,6 @@ namespace kiwano
width_in_pixels_ = width;
height_in_pixels_ = height;
}
SetSize(static_cast<float>(width_in_pixels_), static_cast<float>(height_in_pixels_));
}
::PropVariantClear(&prop_val);
}
@ -439,28 +384,7 @@ namespace kiwano
return hr;
}
HRESULT GifImage::ComposeNextFrame()
{
HRESULT hr = E_FAIL;
if (frame_rt_)
{
// 找到延迟大于 0 的帧 (0 延迟帧是不可见的中间帧)
do
{
hr = DisposeCurrentFrame();
if (SUCCEEDED(hr))
{
hr = OverlayNextFrame();
}
} while (SUCCEEDED(hr) && frame_delay_.IsZero() && !IsLastFrame());
animating_ = (SUCCEEDED(hr) && !EndOfAnimation() && frames_count_ > 1);
}
return hr;
}
HRESULT GifImage::DisposeCurrentFrame()
HRESULT GifImage::DisposeCurrentFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt)
{
HRESULT hr = S_OK;
@ -471,11 +395,11 @@ namespace kiwano
break;
case DisposalType::Background:
// 用背景颜色清除当前原始帧覆盖的区域
hr = ClearCurrentFrameArea();
hr = ClearCurrentFrameArea(frame_rt);
break;
case DisposalType::Previous:
// 恢复先前构图的帧
hr = RestoreSavedFrame();
hr = RestoreSavedFrame(frame_rt);
break;
default:
hr = E_FAIL;
@ -483,59 +407,13 @@ namespace kiwano
return hr;
}
HRESULT GifImage::OverlayNextFrame()
{
HRESULT hr = GetRawFrame(next_index_);
if (SUCCEEDED(hr))
{
if (disposal_type_ == DisposalType::Previous)
{
hr = SaveComposedFrame();
}
}
if (SUCCEEDED(hr))
{
frame_rt_->BeginDraw();
if (next_index_ == 0)
{
// 重新绘制背景
frame_rt_->Clear(bg_color_);
loop_count_++;
}
frame_rt_->DrawBitmap(raw_frame_.Get(), frame_position_);
hr = frame_rt_->EndDraw();
}
if (SUCCEEDED(hr))
{
next_index_ = (++next_index_) % frames_count_;
}
if (IsLastFrame() && loop_cb_)
{
loop_cb_(loop_count_ - 1);
}
if (EndOfAnimation() && done_cb_)
{
done_cb_();
}
return hr;
}
HRESULT GifImage::SaveComposedFrame()
HRESULT GifImage::SaveComposedFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt)
{
HRESULT hr = S_OK;
ComPtr<ID2D1Bitmap> frame_to_be_saved;
hr = frame_rt_->GetBitmap(&frame_to_be_saved);
hr = frame_rt->GetBitmap(&frame_to_be_saved);
if (SUCCEEDED(hr))
{
if (saved_frame_ == nullptr)
@ -543,7 +421,7 @@ namespace kiwano
auto size = frame_to_be_saved->GetPixelSize();
auto prop = D2D1::BitmapProperties(frame_to_be_saved->GetPixelFormat());
hr = frame_rt_->CreateBitmap(size, prop, &saved_frame_);
hr = frame_rt->CreateBitmap(size, prop, &saved_frame_);
}
}
@ -554,7 +432,7 @@ namespace kiwano
return hr;
}
HRESULT GifImage::RestoreSavedFrame()
HRESULT GifImage::RestoreSavedFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt)
{
HRESULT hr = S_OK;
@ -564,7 +442,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
hr = frame_rt_->GetBitmap(&frame_to_copy_to);
hr = frame_rt->GetBitmap(&frame_to_copy_to);
}
if (SUCCEEDED(hr))
@ -575,15 +453,15 @@ namespace kiwano
return hr;
}
HRESULT GifImage::ClearCurrentFrameArea()
HRESULT GifImage::ClearCurrentFrameArea(ComPtr<ID2D1BitmapRenderTarget> frame_rt)
{
frame_rt_->BeginDraw();
frame_rt->BeginDraw();
frame_rt_->PushAxisAlignedClip(&frame_position_, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
frame_rt_->Clear(bg_color_);
frame_rt_->PopAxisAlignedClip();
frame_rt->PushAxisAlignedClip(&frame_position_, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
frame_rt->Clear(bg_color_);
frame_rt->PopAxisAlignedClip();
return frame_rt_->EndDraw();
return frame_rt->EndDraw();
}
HRESULT GifImage::GetBackgroundColor(IWICMetadataQueryReader* metadata_reader)
@ -627,7 +505,8 @@ namespace kiwano
if (SUCCEEDED(hr))
{
hr = factory_->CreatePalette(&wic_palette);
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetWICImagingFactory();
hr = factory->CreatePalette(&wic_palette);
}
if (SUCCEEDED(hr))

View File

@ -19,19 +19,16 @@
// THE SOFTWARE.
#pragma once
#include "Node.h"
#include "include-forwards.h"
#include "../base/Resource.h"
#include "../renderer/render.h"
namespace kiwano
{
class KGE_API GifImage
: public VisualNode
: public Object
{
public:
typedef Closure<void(int)> LoopDoneCallback;
typedef Closure<void()> DoneCallback;
GifImage();
GifImage(
@ -42,53 +39,15 @@ namespace kiwano
Resource const& res
);
// 设置 GIF 动画循环次数
inline void SetLoopCount(int loops) { total_loop_count_ = loops; }
inline unsigned int GetWidthInPixels() const { return width_in_pixels_; }
// 设置 GIF 动画每次循环结束回调函数
inline void SetLoopDoneCallback(LoopDoneCallback const& cb) { loop_cb_ = cb; }
inline unsigned int GetHeightInPixels() const { return height_in_pixels_; }
// 设置 GIF 动画结束回调函数
inline void SetDoneCallback(DoneCallback const& cb) { done_cb_ = cb; }
inline unsigned int GetFrameDelay() const { return frame_delay_; }
// 重新播放动画
void Restart();
inline int GetFramesCount() const { return static_cast<int>(frames_count_); }
inline int GetLoopCount() const { return total_loop_count_; }
inline LoopDoneCallback GetLoopDoneCallback() const { return loop_cb_; }
inline DoneCallback GetDoneCallback() const { return done_cb_; }
void OnRender() override;
protected:
void Update(Duration dt) override;
HRESULT GetRawFrame(UINT frame_index);
HRESULT GetGlobalMetadata();
HRESULT GetBackgroundColor(IWICMetadataQueryReader* metadata_reader);
HRESULT ComposeNextFrame();
HRESULT DisposeCurrentFrame();
HRESULT OverlayNextFrame();
HRESULT SaveComposedFrame();
HRESULT RestoreSavedFrame();
HRESULT ClearCurrentFrameArea();
inline bool IsLastFrame() const { return (next_index_ == 0); }
inline bool EndOfAnimation() const { return IsLastFrame() && loop_count_ == total_loop_count_ + 1; }
protected:
Duration frame_delay_;
Duration frame_elapsed_;
ComPtr<IWICImagingFactory> factory_;
ComPtr<ID2D1BitmapRenderTarget> frame_rt_;
ComPtr<ID2D1Bitmap> raw_frame_;
ComPtr<ID2D1Bitmap> saved_frame_;
ComPtr<IWICBitmapDecoder> decoder_;
inline unsigned int GetFramesCount() const { return frames_count_; }
public:
enum class DisposalType
{
Unknown,
@ -97,18 +56,37 @@ namespace kiwano
Previous
};
bool animating_;
int total_loop_count_;
int loop_count_;
unsigned int next_index_;
inline DisposalType GetDisposalType() const { return disposal_type_; }
inline D2D1_COLOR_F GetBackgroundColor() const { return bg_color_; }
inline D2D1_RECT_F const& GetFramePosition() const { return frame_position_; }
inline ComPtr<ID2D1Bitmap> GetRawFrame() const { return raw_frame_; }
inline void SetDisposalType(DisposalType type) { disposal_type_ = type; }
public:
HRESULT GetRawFrame(UINT frame_index);
HRESULT GetGlobalMetadata();
HRESULT GetBackgroundColor(IWICMetadataQueryReader* metadata_reader);
HRESULT DisposeCurrentFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt);
HRESULT SaveComposedFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt);
HRESULT RestoreSavedFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt);
HRESULT ClearCurrentFrameArea(ComPtr<ID2D1BitmapRenderTarget> frame_rt);
protected:
ComPtr<ID2D1Bitmap> raw_frame_;
ComPtr<ID2D1Bitmap> saved_frame_;
ComPtr<IWICBitmapDecoder> decoder_;
unsigned int frames_count_;
unsigned int frame_delay_;
unsigned int width_in_pixels_;
unsigned int height_in_pixels_;
DisposalType disposal_type_;
D2D1_RECT_F frame_position_;
D2D1_COLOR_F bg_color_;
LoopDoneCallback loop_cb_;
DoneCallback done_cb_;
};
}

194
kiwano/2d/GifSprite.cpp Normal file
View File

@ -0,0 +1,194 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "GifSprite.h"
#include "GifImage.h"
#include "../base/logs.h"
#include "../platform/modules.h"
namespace kiwano
{
GifSprite::GifSprite()
: animating_(false)
, next_index_(0)
, total_loop_count_(1)
, loop_count_(0)
{
}
GifSprite::GifSprite(Resource const& res)
: GifSprite()
{
Load(res);
}
GifSprite::GifSprite(GifImagePtr image)
{
Load(image);
}
bool GifSprite::Load(Resource const& res)
{
GifImagePtr image = new (std::nothrow) GifImage;
if (image->Load(res))
{
return Load(image);
}
return false;
}
bool GifSprite::Load(GifImagePtr image)
{
if (image && image_ != image)
{
image_ = image;
next_index_ = 0;
loop_count_ = 0;
SetSize(
static_cast<float>(image_->GetWidthInPixels()),
static_cast<float>(image_->GetHeightInPixels())
);
if (!frame_rt_)
{
auto ctx = Renderer::Instance()->GetD2DDeviceResources()->GetDeviceContext();
ThrowIfFailed(
ctx->CreateCompatibleRenderTarget(&frame_rt_)
);
}
if (image_->GetFramesCount() > 0)
{
ComposeNextFrame();
}
return true;
}
return false;
}
void GifSprite::Update(Duration dt)
{
VisualNode::Update(dt);
if (image_ && animating_)
{
frame_elapsed_ += dt;
if (frame_delay_ <= frame_elapsed_)
{
frame_delay_ -= frame_elapsed_;
frame_elapsed_ = 0;
ComposeNextFrame();
}
}
}
void GifSprite::OnRender()
{
if (frame_to_render_)
{
Rect bounds = GetBounds();
Renderer::Instance()->DrawBitmap(frame_to_render_, bounds, bounds);
}
}
void GifSprite::RestartAnimation()
{
animating_ = true;
next_index_ = 0;
loop_count_ = 0;
image_->SetDisposalType(GifImage::DisposalType::None);
}
void GifSprite::ComposeNextFrame()
{
if (frame_rt_)
{
// 找到延迟大于 0 的帧 (0 延迟帧是不可见的中间帧)
HRESULT hr = E_FAIL;
do
{
hr = image_->DisposeCurrentFrame(frame_rt_);
if (SUCCEEDED(hr))
{
hr = OverlayNextFrame();
}
if (SUCCEEDED(hr))
{
frame_delay_.SetMilliseconds(static_cast<long>(image_->GetFrameDelay()));
}
} while (SUCCEEDED(hr) && frame_delay_.IsZero() && !IsLastFrame());
animating_ = (SUCCEEDED(hr) && !EndOfAnimation() && image_->GetFramesCount() > 1);
}
}
HRESULT GifSprite::OverlayNextFrame()
{
HRESULT hr = image_->GetRawFrame(next_index_);
if (SUCCEEDED(hr))
{
if (image_->GetDisposalType() == GifImage::DisposalType::Previous)
{
hr = image_->SaveComposedFrame(frame_rt_);
}
}
if (SUCCEEDED(hr))
{
frame_rt_->BeginDraw();
if (next_index_ == 0)
{
// 重新绘制背景
frame_rt_->Clear(image_->GetBackgroundColor());
loop_count_++;
}
frame_rt_->DrawBitmap(image_->GetRawFrame().Get(), image_->GetFramePosition());
hr = frame_rt_->EndDraw();
}
if (SUCCEEDED(hr))
{
frame_to_render_ = nullptr;
hr = frame_rt_->GetBitmap(&frame_to_render_);
}
if (SUCCEEDED(hr))
{
next_index_ = (++next_index_) % image_->GetFramesCount();
}
if (IsLastFrame() && loop_cb_)
{
loop_cb_(loop_count_ - 1);
}
if (EndOfAnimation() && done_cb_)
{
done_cb_();
}
return hr;
}
}

97
kiwano/2d/GifSprite.h Normal file
View File

@ -0,0 +1,97 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "Node.h"
#include "../base/Resource.h"
#include "../renderer/render.h"
namespace kiwano
{
class KGE_API GifSprite
: public VisualNode
{
public:
using LoopDoneCallback = Closure<void(int)>;
using DoneCallback = Closure<void()>;
GifSprite();
GifSprite(
Resource const& res
);
GifSprite(
GifImagePtr image
);
bool Load(
Resource const& res
);
bool Load(
GifImagePtr image
);
// 设置 GIF 动画循环次数
inline void SetLoopCount(int loops) { total_loop_count_ = loops; }
// 设置 GIF 动画每次循环结束回调函数
inline void SetLoopDoneCallback(LoopDoneCallback const& cb) { loop_cb_ = cb; }
// 设置 GIF 动画结束回调函数
inline void SetDoneCallback(DoneCallback const& cb) { done_cb_ = cb; }
// 重新播放动画
void RestartAnimation();
inline LoopDoneCallback GetLoopDoneCallback() const { return loop_cb_; }
inline DoneCallback GetDoneCallback() const { return done_cb_; }
void OnRender() override;
protected:
void Update(Duration dt) override;
void ComposeNextFrame();
HRESULT OverlayNextFrame();
inline bool IsLastFrame() const { return (next_index_ == 0); }
inline bool EndOfAnimation() const { return IsLastFrame() && loop_count_ == total_loop_count_ + 1; }
protected:
bool animating_;
int total_loop_count_;
int loop_count_;
unsigned int next_index_;
Duration frame_delay_;
Duration frame_elapsed_;
LoopDoneCallback loop_cb_;
DoneCallback done_cb_;
GifImagePtr image_;
ComPtr<ID2D1Bitmap> frame_to_render_;
ComPtr<ID2D1BitmapRenderTarget> frame_rt_;
};
}

View File

@ -20,7 +20,6 @@
#include "Image.h"
#include "../base/logs.h"
#include "../renderer/render.h"
#include "../platform/modules.h"
#include "../utils/FileUtil.h"

View File

@ -21,7 +21,7 @@
#pragma once
#include "include-forwards.h"
#include "../base/Resource.h"
#include <d2d1.h>
#include "../renderer/render.h"
namespace kiwano
{

View File

@ -53,7 +53,7 @@ namespace kiwano
bool Sprite::Load(ImagePtr image)
{
if (image)
if (image && image_ != image)
{
image_ = image;
@ -65,18 +65,10 @@ namespace kiwano
bool Sprite::Load(Resource const& res)
{
if (!image_)
ImagePtr image = new (std::nothrow) Image;
if (image->Load(res))
{
image_ = new (std::nothrow) Image;
}
if (image_)
{
if (image_->Load(res))
{
Node::SetSize(image_->GetWidth(), image_->GetHeight());
return true;
}
return Load(image);
}
return false;
}

View File

@ -35,6 +35,7 @@
namespace kiwano
{
KGE_DECLARE_SMART_PTR(Image);
KGE_DECLARE_SMART_PTR(GifImage);
KGE_DECLARE_SMART_PTR(Frames);
KGE_DECLARE_SMART_PTR(Geometry);
@ -49,7 +50,7 @@ namespace kiwano
KGE_DECLARE_SMART_PTR(Scene);
KGE_DECLARE_SMART_PTR(Layer);
KGE_DECLARE_SMART_PTR(Sprite);
KGE_DECLARE_SMART_PTR(GifImage);
KGE_DECLARE_SMART_PTR(GifSprite);
KGE_DECLARE_SMART_PTR(Text);
KGE_DECLARE_SMART_PTR(Canvas);
KGE_DECLARE_SMART_PTR(GeometryNode);

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClInclude Include="2d\GifSprite.h" />
<ClInclude Include="base\types.h" />
<ClInclude Include="kiwano.h" />
<ClInclude Include="config.h" />
@ -93,6 +94,7 @@
<ClCompile Include="2d\Geometry.cpp" />
<ClCompile Include="2d\GeometryNode.cpp" />
<ClCompile Include="2d\GifImage.cpp" />
<ClCompile Include="2d\GifSprite.cpp" />
<ClCompile Include="2d\Image.cpp" />
<ClCompile Include="2d\Layer.cpp" />
<ClCompile Include="2d\Node.cpp" />

View File

@ -261,6 +261,9 @@
<ClInclude Include="base\types.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="2d\GifSprite.h">
<Filter>2d</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ui\Button.cpp">
@ -395,5 +398,8 @@
<ClCompile Include="utils\FileUtil.cpp">
<Filter>utils</Filter>
</ClCompile>
<ClCompile Include="2d\GifSprite.cpp">
<Filter>2d</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -98,6 +98,7 @@
#include "2d/Scene.h"
#include "2d/Layer.h"
#include "2d/Sprite.h"
#include "2d/GifSprite.h"
#include "2d/Text.h"
#include "2d/Canvas.h"
#include "2d/GeometryNode.h"