Remove TextureRenderContext & add function to create a RenderContext from a texture

This commit is contained in:
Nomango 2020-02-20 18:22:52 +08:00
parent b9f1d47143
commit f71c5b9ff8
38 changed files with 263 additions and 589 deletions

View File

@ -83,7 +83,6 @@
<ClInclude Include="..\..\src\kiwano\render\DirectX\RenderContextImpl.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\RendererImpl.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextRenderer.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.h" />
<ClInclude Include="..\..\src\kiwano\render\Font.h" />
<ClInclude Include="..\..\src\kiwano\render\NativeObject.h" />
<ClInclude Include="..\..\src\kiwano\render\Shape.h" />
@ -97,7 +96,6 @@
<ClInclude Include="..\..\src\kiwano\render\TextStyle.hpp" />
<ClInclude Include="..\..\src\kiwano\render\Texture.h" />
<ClInclude Include="..\..\src\kiwano\render\TextureCache.h" />
<ClInclude Include="..\..\src\kiwano\render\TextureRenderContext.h" />
<ClInclude Include="..\..\src\kiwano\utils\LocalStorage.h" />
<ClInclude Include="..\..\src\kiwano\utils\ResourceCache.h" />
<ClInclude Include="..\..\src\kiwano\utils\UserData.h" />
@ -159,7 +157,6 @@
<ClCompile Include="..\..\src\kiwano\render\DirectX\RenderContextImpl.cpp" />
<ClCompile Include="..\..\src\kiwano\render\DirectX\RendererImpl.cpp" />
<ClCompile Include="..\..\src\kiwano\render\DirectX\TextRenderer.cpp" />
<ClCompile Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.cpp" />
<ClCompile Include="..\..\src\kiwano\render\Font.cpp" />
<ClCompile Include="..\..\src\kiwano\render\Shape.cpp" />
<ClCompile Include="..\..\src\kiwano\render\ShapeMaker.cpp" />
@ -171,7 +168,6 @@
<ClCompile Include="..\..\src\kiwano\render\TextLayout.cpp" />
<ClCompile Include="..\..\src\kiwano\render\Texture.cpp" />
<ClCompile Include="..\..\src\kiwano\render\TextureCache.cpp" />
<ClCompile Include="..\..\src\kiwano\render\TextureRenderContext.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\LocalStorage.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\ResourceCache.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\UserData.cpp" />

View File

@ -270,15 +270,9 @@
<ClInclude Include="..\..\src\kiwano\math\Scalar.h">
<Filter>math</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\TextureRenderContext.h">
<Filter>render</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\RenderContextImpl.h">
<Filter>render\DirectX</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.h">
<Filter>render\DirectX</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\RendererImpl.h">
<Filter>render\DirectX</Filter>
</ClInclude>
@ -509,15 +503,9 @@
<ClCompile Include="..\..\src\kiwano\render\Shape.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\TextureRenderContext.cpp">
<Filter>render</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\DirectX\RenderContextImpl.cpp">
<Filter>render\DirectX</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.cpp">
<Filter>render\DirectX</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\render\DirectX\RendererImpl.cpp">
<Filter>render\DirectX</Filter>
</ClCompile>

View File

@ -42,7 +42,7 @@ KGE_DECLARE_SMART_PTR(Sound);
* \~chinese
* @brief
*/
class KGE_API Sound : public virtual ObjectBase
class KGE_API Sound : public ObjectBase
{
friend class AudioModule;

View File

@ -37,7 +37,7 @@ KGE_DECLARE_SMART_PTR(SoundPlayer);
* \~chinese
* @brief
*/
class KGE_API SoundPlayer : public virtual ObjectBase
class KGE_API SoundPlayer : public ObjectBase
{
public:
/// \~chinese

View File

@ -51,7 +51,7 @@ enum class HttpType
* \~chinese
* @brief HTTP请求
*/
class KGE_API HttpRequest : public virtual ObjectBase
class KGE_API HttpRequest : public ObjectBase
{
public:
/// \~chinese

View File

@ -36,7 +36,7 @@ KGE_DECLARE_SMART_PTR(HttpResponse);
* \~chinese
* @brief HTTP响应
*/
class KGE_API HttpResponse : public virtual ObjectBase
class KGE_API HttpResponse : public ObjectBase
{
public:
HttpResponse(HttpRequestPtr request);

View File

@ -36,7 +36,7 @@ KGE_DECLARE_SMART_PTR(Fixture);
/// \~chinese
/// @brief 物理夹具
class Fixture : public virtual ObjectBase
class KGE_API Fixture : public ObjectBase
{
public:
/// \~chinese

View File

@ -45,7 +45,7 @@ KGE_DECLARE_SMART_PTR(WheelJoint);
/// \~chinese
/// @brief 关节
class KGE_API Joint : public virtual ObjectBase
class KGE_API Joint : public ObjectBase
{
public:
/// \~chinese

View File

@ -57,7 +57,7 @@ typedef IntrusiveList<ActorPtr> ActorList;
*
*/
class KGE_API Actor
: public virtual ObjectBase
: public ObjectBase
, public TimerManager
, public ActionManager
, public EventDispatcher

View File

@ -20,7 +20,6 @@
#include <kiwano/2d/Canvas.h>
#include <kiwano/core/Logger.h>
#include <kiwano/render/Renderer.h>
namespace kiwano
{
@ -32,11 +31,9 @@ CanvasPtr Canvas::Create(const Size& size)
{
try
{
ptr->ctx_ = TextureRenderContext::Create();
ptr->stroke_brush_ = Brush::Create(Color::White);
ptr->fill_brush_ = Brush::Create(Color::White);
ptr->SetSize(ptr->ctx_->GetSize());
ptr->ResizeAndClear(size);
}
catch (std::exception)
{
@ -47,28 +44,24 @@ CanvasPtr Canvas::Create(const Size& size)
}
Canvas::Canvas()
: cache_expired_(false)
{
}
void Canvas::BeginDraw()
{
KGE_ASSERT(ctx_);
ctx_->BeginDraw();
KGE_ASSERT(render_ctx_);
render_ctx_->BeginDraw();
}
void Canvas::EndDraw()
{
KGE_ASSERT(ctx_);
ctx_->EndDraw();
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->EndDraw();
}
void Canvas::OnRender(RenderContext& ctx)
{
UpdateCache();
if (texture_cached_ && texture_cached_->IsValid())
if (texture_cached_)
{
PrepareToRender(ctx);
ctx.DrawTexture(*texture_cached_, nullptr, &GetBounds());
@ -77,156 +70,153 @@ void Canvas::OnRender(RenderContext& ctx)
void Canvas::SetBrush(BrushPtr brush)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(brush);
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(brush);
}
void Canvas::SetBrushTransform(const Transform& transform)
{
KGE_ASSERT(ctx_);
ctx_->SetTransform(transform.ToMatrix());
KGE_ASSERT(render_ctx_);
render_ctx_->SetTransform(transform.ToMatrix());
}
void Canvas::SetBrushTransform(const Matrix3x2& transform)
{
KGE_ASSERT(ctx_);
ctx_->SetTransform(transform);
KGE_ASSERT(render_ctx_);
render_ctx_->SetTransform(transform);
}
void Canvas::PushLayer(LayerPtr layer)
{
KGE_ASSERT(ctx_);
KGE_ASSERT(render_ctx_);
if (layer)
{
ctx_->PushLayer(*layer);
render_ctx_->PushLayer(*layer);
}
}
void Canvas::PopLayer()
{
KGE_ASSERT(ctx_);
ctx_->PopLayer();
KGE_ASSERT(render_ctx_);
render_ctx_->PopLayer();
}
void Canvas::PushClipRect(const Rect& clip_rect)
{
KGE_ASSERT(ctx_);
ctx_->PushClipRect(clip_rect);
KGE_ASSERT(render_ctx_);
render_ctx_->PushClipRect(clip_rect);
}
void Canvas::PopClipRect()
{
KGE_ASSERT(ctx_);
ctx_->PopClipRect();
KGE_ASSERT(render_ctx_);
render_ctx_->PopClipRect();
}
void Canvas::DrawShape(ShapePtr shape)
{
KGE_ASSERT(ctx_);
KGE_ASSERT(render_ctx_);
if (shape)
{
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->SetCurrentStrokeStyle(stroke_style_);
ctx_->DrawShape(*shape);
cache_expired_ = true;
render_ctx_->SetCurrentBrush(stroke_brush_);
render_ctx_->SetCurrentStrokeStyle(stroke_style_);
render_ctx_->DrawShape(*shape);
}
}
void Canvas::DrawLine(const Point& begin, const Point& end)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->SetCurrentStrokeStyle(stroke_style_);
ctx_->DrawLine(begin, end);
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(stroke_brush_);
render_ctx_->SetCurrentStrokeStyle(stroke_style_);
render_ctx_->DrawLine(begin, end);
}
void Canvas::DrawCircle(const Point& center, float radius)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->SetCurrentStrokeStyle(stroke_style_);
ctx_->DrawEllipse(center, Vec2(radius, radius));
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(stroke_brush_);
render_ctx_->SetCurrentStrokeStyle(stroke_style_);
render_ctx_->DrawEllipse(center, Vec2(radius, radius));
}
void Canvas::DrawEllipse(const Point& center, const Vec2& radius)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->SetCurrentStrokeStyle(stroke_style_);
ctx_->DrawEllipse(center, radius);
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(stroke_brush_);
render_ctx_->SetCurrentStrokeStyle(stroke_style_);
render_ctx_->DrawEllipse(center, radius);
}
void Canvas::DrawRect(const Rect& rect)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->SetCurrentStrokeStyle(stroke_style_);
ctx_->DrawRectangle(rect);
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(stroke_brush_);
render_ctx_->SetCurrentStrokeStyle(stroke_style_);
render_ctx_->DrawRectangle(rect);
}
void Canvas::DrawRoundedRect(const Rect& rect, const Vec2& radius)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->SetCurrentStrokeStyle(stroke_style_);
ctx_->DrawRoundedRectangle(rect, radius);
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(stroke_brush_);
render_ctx_->SetCurrentStrokeStyle(stroke_style_);
render_ctx_->DrawRoundedRectangle(rect, radius);
}
void Canvas::FillShape(ShapePtr shape)
{
KGE_ASSERT(ctx_);
KGE_ASSERT(render_ctx_);
if (shape)
{
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillShape(*shape);
cache_expired_ = true;
render_ctx_->SetCurrentBrush(fill_brush_);
render_ctx_->FillShape(*shape);
}
}
void Canvas::FillCircle(const Point& center, float radius)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillEllipse(center, Vec2(radius, radius));
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(fill_brush_);
render_ctx_->FillEllipse(center, Vec2(radius, radius));
}
void Canvas::FillEllipse(const Point& center, const Vec2& radius)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillEllipse(center, radius);
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(fill_brush_);
render_ctx_->FillEllipse(center, radius);
}
void Canvas::FillRect(const Rect& rect)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillRectangle(rect);
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(fill_brush_);
render_ctx_->FillRectangle(rect);
}
void Canvas::FillRoundedRect(const Rect& rect, const Vec2& radius)
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillRoundedRectangle(rect, radius);
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(fill_brush_);
render_ctx_->FillRoundedRectangle(rect, radius);
}
void Canvas::DrawTexture(TexturePtr texture, const Rect* src_rect, const Rect* dest_rect)
void Canvas::DrawFrame(FramePtr frame, const Point& pos)
{
KGE_ASSERT(ctx_);
if (texture)
KGE_ASSERT(render_ctx_);
if (frame && frame->IsValid())
{
ctx_->DrawTexture(*texture, src_rect, dest_rect);
cache_expired_ = true;
render_ctx_->DrawTexture(*frame->GetTexture(), &frame->GetCropRect(), &Rect(pos, frame->GetSize()));
}
}
void Canvas::DrawFrame(FramePtr frame, const Point& pos, const Size& size)
{
KGE_ASSERT(render_ctx_);
if (frame && frame->IsValid())
{
render_ctx_->DrawTexture(*frame->GetTexture(), &frame->GetCropRect(), &Rect(pos, size));
}
}
@ -240,11 +230,10 @@ void Canvas::DrawTextLayout(const String& text, const TextStyle& style, const Po
void Canvas::DrawTextLayout(TextLayoutPtr layout, const Point& point)
{
KGE_ASSERT(ctx_);
KGE_ASSERT(render_ctx_);
if (layout)
{
ctx_->DrawTextLayout(*layout, point);
cache_expired_ = true;
render_ctx_->DrawTextLayout(*layout, point);
}
}
@ -280,60 +269,42 @@ void Canvas::AddArc(const Point& point, const Size& radius, float rotation, bool
void Canvas::StrokePath()
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->SetCurrentStrokeStyle(stroke_style_);
ctx_->DrawShape(*shape_maker_.GetShape());
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(stroke_brush_);
render_ctx_->SetCurrentStrokeStyle(stroke_style_);
render_ctx_->DrawShape(*shape_maker_.GetShape());
}
void Canvas::FillPath()
{
KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillShape(*shape_maker_.GetShape());
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->SetCurrentBrush(fill_brush_);
render_ctx_->FillShape(*shape_maker_.GetShape());
}
void Canvas::Clear()
{
KGE_ASSERT(ctx_);
ctx_->Clear();
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->Clear();
}
void Canvas::Clear(const Color& clear_color)
{
KGE_ASSERT(ctx_);
ctx_->Clear(clear_color);
cache_expired_ = true;
KGE_ASSERT(render_ctx_);
render_ctx_->Clear(clear_color);
}
void Canvas::ResizeAndClear(Size size)
{
ctx_ = TextureRenderContext::Create(size);
texture_cached_ = new Texture;
render_ctx_ = RenderContext::Create(*texture_cached_, size);
SetSize(render_ctx_->GetSize());
}
TexturePtr Canvas::ExportToTexture() const
{
UpdateCache();
return texture_cached_;
}
void Canvas::UpdateCache() const
{
if (cache_expired_ && ctx_)
{
if (!texture_cached_)
{
texture_cached_ = new Texture;
}
if (ctx_->GetOutput(*texture_cached_))
{
cache_expired_ = false;
}
}
}
} // namespace kiwano

View File

@ -20,8 +20,9 @@
#pragma once
#include <kiwano/2d/Actor.h>
#include <kiwano/2d/Frame.h>
#include <kiwano/render/ShapeMaker.h>
#include <kiwano/render/TextureRenderContext.h>
#include <kiwano/render/RenderContext.h>
namespace kiwano
{
@ -117,11 +118,17 @@ public:
void FillRoundedRect(const Rect& rect, const Vec2& radius);
/// \~chinese
/// @brief 绘制纹理
/// @param texture 纹理
/// @param src_rect 纹理裁剪区域
/// @param dest_rect 绘制目标区域
void DrawTexture(TexturePtr texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr);
/// @brief 绘制图像帧
/// @param frame 图像帧
/// @param pos 绘制图像的位置
void DrawFrame(FramePtr frame, const Point& pos);
/// \~chinese
/// @brief 绘制图像帧
/// @param frame 图像帧
/// @param pos 绘制图像的位置
/// @param size 渲染的图像大小
void DrawFrame(FramePtr frame, const Point& pos, const Size& size);
/// \~chinese
/// @brief 绘制文字布局
@ -268,17 +275,13 @@ public:
private:
Canvas();
void UpdateCache() const;
private:
StrokeStylePtr stroke_style_;
ShapeMaker shape_maker_;
BrushPtr fill_brush_;
BrushPtr stroke_brush_;
mutable bool cache_expired_;
mutable TexturePtr texture_cached_;
mutable TextureRenderContextPtr ctx_;
StrokeStylePtr stroke_style_;
ShapeMaker shape_maker_;
BrushPtr fill_brush_;
BrushPtr stroke_brush_;
TexturePtr texture_cached_;
RenderContextPtr render_ctx_;
};
/** @} */

View File

@ -40,7 +40,7 @@ typedef IntrusiveList<ComponentPtr> ComponentList;
* @brief
*/
class KGE_API Component
: public virtual ObjectBase
: public ObjectBase
, protected IntrusiveListValue<ComponentPtr>
{
friend class Actor;

View File

@ -30,7 +30,7 @@ KGE_DECLARE_SMART_PTR(Frame);
* \~chinese
* @brief
*/
class KGE_API Frame : public virtual ObjectBase
class KGE_API Frame : public ObjectBase
{
public:
/// \~chinese

View File

@ -31,7 +31,7 @@ KGE_DECLARE_SMART_PTR(FrameSequence);
* \~chinese
* @brief
*/
class KGE_API FrameSequence : public virtual ObjectBase
class KGE_API FrameSequence : public ObjectBase
{
public:
/// \~chinese

View File

@ -87,11 +87,13 @@ bool GifSprite::Load(GifImagePtr gif)
loop_count_ = 0;
frame_ = GifImage::Frame();
if (!frame_rt_)
{
Size frame_size = Size(float(gif_->GetWidthInPixels()), float(gif_->GetHeightInPixels()));
frame_rt_ = TextureRenderContext::Create(frame_size);
}
saved_frame_.Reset();
frame_to_render_.Reset();
frame_rt_.Reset();
Size frame_size = Size(float(gif_->GetWidthInPixels()), float(gif_->GetHeightInPixels()));
frame_to_render_ = new Texture;
frame_rt_ = RenderContext::Create(*frame_to_render_, frame_size);
SetSize(frame_rt_->GetSize());
@ -149,7 +151,7 @@ void GifSprite::ComposeNextFrame()
KGE_ASSERT(frame_rt_);
KGE_ASSERT(gif_);
if (frame_rt_->IsValid())
if (frame_rt_)
{
do
{
@ -191,7 +193,7 @@ void GifSprite::OverlayNextFrame()
SaveComposedFrame();
}
if (frame_rt_->IsValid())
if (frame_rt_)
{
frame_rt_->BeginDraw();
@ -208,15 +210,7 @@ void GifSprite::OverlayNextFrame()
frame_rt_->EndDraw();
if (!frame_to_render_)
{
frame_to_render_ = new Texture;
}
if (frame_rt_->GetOutput(*frame_to_render_))
{
next_index_ = (++next_index_) % gif_->GetFramesCount();
}
next_index_ = (++next_index_) % gif_->GetFramesCount();
}
// Execute callback
@ -235,18 +229,12 @@ void GifSprite::SaveComposedFrame()
{
KGE_ASSERT(frame_rt_);
TexturePtr frame_to_be_saved = new Texture;
if (frame_rt_->GetOutput(*frame_to_be_saved))
if (!saved_frame_)
{
if (!saved_frame_)
{
saved_frame_ = new Texture;
frame_rt_->CreateTexture(*saved_frame_, frame_to_be_saved->GetSizeInPixels());
}
saved_frame_->CopyFrom(frame_to_be_saved);
saved_frame_ = new Texture;
frame_rt_->CreateTexture(*saved_frame_, frame_to_render_->GetSizeInPixels());
}
saved_frame_->CopyFrom(frame_to_render_);
}
void GifSprite::RestoreSavedFrame()
@ -255,12 +243,7 @@ void GifSprite::RestoreSavedFrame()
if (saved_frame_)
{
TexturePtr frame_to_copy_to = new Texture;
if (frame_rt_->GetOutput(*frame_to_copy_to))
{
frame_to_copy_to->CopyFrom(saved_frame_);
}
frame_to_render_->CopyFrom(saved_frame_);
}
}

View File

@ -22,7 +22,7 @@
#include <kiwano/2d/Actor.h>
#include <kiwano/core/Resource.h>
#include <kiwano/render/GifImage.h>
#include <kiwano/render/TextureRenderContext.h>
#include <kiwano/render/RenderContext.h>
namespace kiwano
{
@ -150,18 +150,18 @@ private:
void ClearCurrentFrameArea();
private:
bool animating_;
int total_loop_count_;
int loop_count_;
size_t next_index_;
Duration frame_elapsed_;
LoopDoneCallback loop_cb_;
DoneCallback done_cb_;
GifImagePtr gif_;
GifImage::Frame frame_;
TexturePtr saved_frame_;
TexturePtr frame_to_render_;
TextureRenderContextPtr frame_rt_;
bool animating_;
int total_loop_count_;
int loop_count_;
size_t next_index_;
Duration frame_elapsed_;
LoopDoneCallback loop_cb_;
DoneCallback done_cb_;
GifImagePtr gif_;
GifImage::Frame frame_;
TexturePtr saved_frame_;
TexturePtr frame_to_render_;
RenderContextPtr frame_rt_;
};
/** @} */

View File

@ -160,7 +160,10 @@ void Sprite::SetFrame(FramePtr frame, bool autoresize)
void Sprite::OnRender(RenderContext& ctx)
{
ctx.DrawTexture(*frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds());
if (frame_ && frame_->IsValid())
{
ctx.DrawTexture(*frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds());
}
}
bool Sprite::CheckVisibility(RenderContext& ctx) const

View File

@ -38,7 +38,7 @@ KGE_DECLARE_SMART_PTR(RotationTransition);
* \~chinese
* @brief
*/
class KGE_API Transition : public virtual ObjectBase
class KGE_API Transition : public ObjectBase
{
friend class Director;

View File

@ -50,7 +50,7 @@ typedef IntrusiveList<ActionPtr> ActionList;
/// \~chinese
/// @brief 动画
class KGE_API Action
: public virtual ObjectBase
: public ObjectBase
, protected IntrusiveListValue<ActionPtr>
{
friend class ActionManager;

View File

@ -38,7 +38,7 @@ typedef Function<void()> AsyncTaskCallback;
/// task->Then(DoSomething);
/// task->Start();
/// @endcode
class AsyncTask : public virtual ObjectBase
class KGE_API AsyncTask : public ObjectBase
{
public:
/// \~chinese

View File

@ -43,7 +43,7 @@ typedef IntrusiveList<EventListenerPtr> ListenerList;
* @brief
*/
class KGE_API EventListener
: public virtual ObjectBase
: public ObjectBase
, protected IntrusiveListValue<EventListenerPtr>
{
friend class EventDispatcher;

View File

@ -28,6 +28,24 @@
namespace kiwano
{
// wide-to-ANSI string conversion helper
namespace detail
{
inline std::unique_ptr<char[]> to_narrow(BSTR msg)
{
return std::unique_ptr<char[]>(_com_util::ConvertBSTRToString(msg));
}
inline std::unique_ptr<char[]> to_narrow(const wchar_t* msg)
{
static_assert(std::is_same<wchar_t*, BSTR>::value, "BSTR must be wchar_t*");
// const_cast is fine:
// BSTR is a wchar_t*;
// ConvertBSTRToString internally uses _wcslen and WideCharToMultiByte;
return to_narrow(const_cast<wchar_t*>(msg));
}
}
class com_error_category : public std::error_category
{
public:
@ -38,16 +56,12 @@ public:
return "com";
}
// @note If _UNICODE is defined the error description gets
// converted to an ANSI string using the CP_ACP codepage.
std::string message(int hr) const override
{
return string::ToNarrow(_com_error{ hr }.ErrorMessage());
auto narrow = detail::to_narrow(_com_error{ hr }.ErrorMessage());
return narrow.get();
}
// Make error_condition for error code (generic if possible)
// @return system's default error condition if error value can be mapped to a Windows error, error condition with
// com category otherwise
std::error_condition default_error_condition(int hr) const noexcept override
{
if (HRESULT_CODE(hr) || hr == 0)

View File

@ -37,7 +37,7 @@ typedef IntrusiveList<TimerPtr> TimerList;
/// @brief 定时器
/// @details 定时器用于每隔一段时间执行一次回调函数,且可以指定执行总次数
class KGE_API Timer
: public virtual ObjectBase
: public ObjectBase
, protected IntrusiveListValue<TimerPtr>
{
friend class TimerManager;

View File

@ -34,7 +34,7 @@ KGE_DECLARE_SMART_PTR(Runner);
* \~chinese
* @brief
*/
class KGE_API Runner : public virtual ObjectBase
class KGE_API Runner : public ObjectBase
{
friend class Application;

View File

@ -33,12 +33,12 @@ RenderContextImpl::~RenderContextImpl()
DiscardDeviceResources();
}
HRESULT RenderContextImpl::CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPtr<ID2D1RenderTarget> ctx)
HRESULT RenderContextImpl::CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPtr<ID2D1RenderTarget> render_target)
{
if (!factory || !ctx)
if (!factory || !render_target)
return E_INVALIDARG;
render_target_ = ctx;
render_target_ = render_target;
text_renderer_.Reset();
current_brush_.Reset();
@ -49,7 +49,7 @@ HRESULT RenderContextImpl::CreateDeviceResources(ComPtr<ID2D1Factory> factory, C
SetAntialiasMode(antialias_);
SetTextAntialiasMode(text_antialias_);
Resize(reinterpret_cast<const Size&>(ctx->GetSize()));
Resize(reinterpret_cast<const Size&>(render_target->GetSize()));
}
// DrawingStateBlock
@ -58,6 +58,10 @@ HRESULT RenderContextImpl::CreateDeviceResources(ComPtr<ID2D1Factory> factory, C
hr = factory->CreateDrawingStateBlock(&drawing_state_);
}
if (SUCCEEDED(hr))
{
NativePtr::Set(this, render_target);
}
return hr;
}
@ -66,11 +70,8 @@ void RenderContextImpl::DiscardDeviceResources()
text_renderer_.Reset();
render_target_.Reset();
current_brush_.Reset();
}
bool RenderContextImpl::IsValid() const
{
return render_target_ != nullptr;
ResetNativePointer();
}
void RenderContextImpl::BeginDraw()

View File

@ -25,16 +25,16 @@
namespace kiwano
{
class RendererImpl;
KGE_DECLARE_SMART_PTR(RenderContextImpl);
class KGE_API RenderContextImpl : public virtual RenderContext
class KGE_API RenderContextImpl : public RenderContext
{
friend class RendererImpl;
public:
bool IsValid() const override;
RenderContextImpl();
virtual ~RenderContextImpl();
HRESULT CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPtr<ID2D1RenderTarget> render_target);
void BeginDraw() override;
@ -92,20 +92,14 @@ public:
void Resize(const Size& size) override;
protected:
RenderContextImpl();
virtual ~RenderContextImpl();
HRESULT CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPtr<ID2D1RenderTarget> ctx);
private:
void DiscardDeviceResources();
void SaveDrawingState();
void RestoreDrawingState();
protected:
private:
ComPtr<ITextRenderer> text_renderer_;
ComPtr<ID2D1RenderTarget> render_target_;
ComPtr<ID2D1DrawingStateBlock> drawing_state_;

View File

@ -24,7 +24,6 @@
#include <kiwano/platform/FileSystem.h>
#include <kiwano/platform/Application.h>
#include <kiwano/render/ShapeMaker.h>
#include <kiwano/render/DirectX/TextureRenderContextImpl.h>
#include <kiwano/render/DirectX/RendererImpl.h>
#include <kiwano/render/DirectX/NativePtr.h>
@ -44,7 +43,6 @@ RendererImpl& RendererImpl::GetInstance()
RendererImpl::RendererImpl()
{
render_ctx_ = new RenderContextImpl;
}
void RendererImpl::MakeContextForWindow(WindowPtr window)
@ -74,7 +72,13 @@ void RendererImpl::MakeContextForWindow(WindowPtr window)
// Other device resources
if (SUCCEEDED(hr))
{
hr = render_ctx_->CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
RenderContextImplPtr ctx = new RenderContextImpl;
hr = ctx->CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
if (SUCCEEDED(hr))
{
render_ctx_ = ctx;
}
}
// FontFileLoader and FontCollectionLoader
@ -133,20 +137,6 @@ void RendererImpl::Destroy()
::CoUninitialize();
}
void RendererImpl::BeginDraw()
{
KGE_ASSERT(render_ctx_);
render_ctx_->BeginDraw();
}
void RendererImpl::EndDraw()
{
KGE_ASSERT(render_ctx_);
render_ctx_->EndDraw();
}
void RendererImpl::Clear()
{
KGE_ASSERT(d3d_res_);
@ -159,34 +149,9 @@ void RendererImpl::Present()
KGE_ASSERT(d3d_res_);
HRESULT hr = d3d_res_->Present(vsync_);
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
{
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
hr = HandleDeviceLost();
}
KGE_THROW_IF_FAILED(hr, "Unexpected DXGI exception");
}
HRESULT RendererImpl::HandleDeviceLost()
{
KGE_ASSERT(d3d_res_ && d2d_res_ && render_ctx_);
HRESULT hr = d3d_res_->HandleDeviceLost();
if (SUCCEEDED(hr))
{
hr = d2d_res_->HandleDeviceLost(d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain());
}
if (SUCCEEDED(hr))
{
hr = render_ctx_->CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
}
return hr;
}
void RendererImpl::CreateTexture(Texture& texture, const String& file_path)
{
HRESULT hr = S_OK;
@ -937,9 +902,9 @@ void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style)
KGE_THROW_IF_FAILED(hr, "Create ID2D1StrokeStyle failed");
}
TextureRenderContextPtr RendererImpl::CreateTextureRenderContext(const Size* desired_size)
RenderContextPtr RendererImpl::CreateTextureRenderContext(Texture& texture, const Size* desired_size)
{
TextureRenderContextImplPtr ptr = new TextureRenderContextImpl;
RenderContextImplPtr ptr = new RenderContextImpl;
HRESULT hr = S_OK;
if (!d2d_res_)
@ -968,13 +933,17 @@ TextureRenderContextPtr RendererImpl::CreateTextureRenderContext(const Size* des
if (SUCCEEDED(hr))
{
ptr->bitmap_rt_ = bitmap_rt;
ComPtr<ID2D1Bitmap> output;
hr = bitmap_rt->GetBitmap(&output);
if (SUCCEEDED(hr))
{
NativePtr::Set(texture, output);
}
}
}
if (SUCCEEDED(hr))
return ptr;
return nullptr;
}

View File

@ -80,19 +80,13 @@ public:
void CreateStrokeStyle(StrokeStyle& stroke_style) override;
TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr) override;
RenderContextPtr CreateTextureRenderContext(Texture& texture, const Size* desired_size = nullptr) override;
public:
void BeginDraw() override;
void EndDraw() override;
void Clear() override;
void Present() override;
RenderContext& GetContext() override;
/// \~chinese
/// @brief 获取Direct2D设备资源
ID2DDeviceResources* GetD2DDeviceResources();
@ -112,10 +106,7 @@ protected:
void Destroy() override;
HRESULT HandleDeviceLost();
private:
RenderContextImplPtr render_ctx_;
ComPtr<ID2DDeviceResources> d2d_res_;
ComPtr<ID3DDeviceResources> d3d_res_;
ComPtr<IFontCollectionLoader> font_collection_loader_;
@ -125,11 +116,6 @@ private:
/** @} */
inline RenderContext& RendererImpl::GetContext()
{
return *render_ctx_;
}
inline ID2DDeviceResources* RendererImpl::GetD2DDeviceResources()
{
KGE_ASSERT(d2d_res_);

View File

@ -1,50 +0,0 @@
// Copyright (c) 2016-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
// 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 <kiwano/core/Logger.h>
#include <kiwano/render/Renderer.h>
#include <kiwano/render/DirectX/TextureRenderContextImpl.h>
#include <kiwano/render/DirectX/NativePtr.h>
namespace kiwano
{
bool TextureRenderContextImpl::GetOutput(Texture& texture)
{
HRESULT hr = E_FAIL;
if (bitmap_rt_)
{
ComPtr<ID2D1Bitmap> bitmap;
hr = bitmap_rt_->GetBitmap(&bitmap);
if (SUCCEEDED(hr))
{
NativePtr::Set(texture, bitmap);
texture.SetSize({ bitmap->GetSize().width, bitmap->GetSize().height });
texture.SetSizeInPixels({ bitmap->GetPixelSize().width, bitmap->GetPixelSize().height });
}
}
return SUCCEEDED(hr);
}
} // namespace kiwano

View File

@ -1,104 +0,0 @@
// Copyright (c) 2016-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
// 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 <kiwano/render/TextureRenderContext.h>
#include <kiwano/render/DirectX/RenderContextImpl.h>
namespace kiwano
{
class RendererImpl;
KGE_DECLARE_SMART_PTR(TextureRenderContextImpl);
KGE_SUPPRESS_WARNING_PUSH
KGE_SUPPRESS_WARNING(4250) // inherits via domainance
class KGE_API TextureRenderContextImpl
: public RenderContextImpl
, public TextureRenderContext
{
friend class RendererImpl;
public:
bool GetOutput(Texture& texture) override;
using RenderContextImpl::IsValid;
using RenderContextImpl::BeginDraw;
using RenderContextImpl::EndDraw;
using RenderContextImpl::DrawTexture;
using RenderContextImpl::DrawTextLayout;
using RenderContextImpl::DrawShape;
using RenderContextImpl::DrawLine;
using RenderContextImpl::DrawRectangle;
using RenderContextImpl::DrawRoundedRectangle;
using RenderContextImpl::DrawEllipse;
using RenderContextImpl::FillShape;
using RenderContextImpl::FillRectangle;
using RenderContextImpl::FillRoundedRectangle;
using RenderContextImpl::FillEllipse;
using RenderContextImpl::CreateTexture;
using RenderContextImpl::PushClipRect;
using RenderContextImpl::PopClipRect;
using RenderContextImpl::PushLayer;
using RenderContextImpl::PopLayer;
using RenderContextImpl::Clear;
using RenderContextImpl::GetSize;
using RenderContextImpl::SetCurrentBrush;
using RenderContextImpl::SetTransform;
using RenderContextImpl::SetAntialiasMode;
using RenderContextImpl::SetTextAntialiasMode;
using RenderContextImpl::CheckVisibility;
using RenderContextImpl::Resize;
private:
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt_;
};
KGE_SUPPRESS_WARNING_POP
} // namespace kiwano

View File

@ -39,7 +39,7 @@ KGE_DECLARE_SMART_PTR(NativeObject);
* \~chinese
* @brief
*/
class KGE_API NativeObject : public virtual ObjectBase
class KGE_API NativeObject : public ObjectBase
{
public:
virtual bool IsValid() const;

View File

@ -19,10 +19,21 @@
// THE SOFTWARE.
#include <kiwano/render/RenderContext.h>
#include <kiwano/render/Renderer.h>
namespace kiwano
{
RenderContextPtr RenderContext::Create(Texture& texture)
{
return Renderer::GetInstance().CreateTextureRenderContext(texture, nullptr);
}
RenderContextPtr RenderContext::Create(Texture& texture, const Size& size)
{
return Renderer::GetInstance().CreateTextureRenderContext(texture, &size);
}
RenderContext::RenderContext()
: collecting_status_(false)
, fast_global_transform_(true)

View File

@ -19,7 +19,6 @@
// THE SOFTWARE.
#pragma once
#include <kiwano/core/ObjectBase.h>
#include <kiwano/core/Time.h>
#include <kiwano/render/Brush.h>
#include <kiwano/render/Shape.h>
@ -29,7 +28,6 @@
namespace kiwano
{
class Renderer;
KGE_DECLARE_SMART_PTR(RenderContext);
@ -50,16 +48,20 @@ enum class TextAntialiasMode
/// \~chinese
/// @brief 渲染上下文
/// @details
/// 渲染上下文将完成基础图元的绘制,并将绘制结果输出到特定的目标中(如窗口或纹理)
class KGE_API RenderContext : public virtual ObjectBase
/// @details 渲染上下文将完成基础图元的绘制,并将绘制结果输出到特定的平面中
class KGE_API RenderContext : public NativeObject
{
friend class Renderer;
public:
/// \~chinese
/// @brief 是否有效
virtual bool IsValid() const = 0;
/// @brief 创建纹理渲染上下文,将绘制结果输出到纹理中
/// @param texture 保存绘制结果的纹理
static RenderContextPtr Create(Texture& texture);
/// \~chinese
/// @brief 创建纹理渲染上下文,将绘制结果输出到纹理中
/// @param texture 保存绘制结果的纹理
/// @param size 渲染输出大小
static RenderContextPtr Create(Texture& texture, const Size& size);
/// \~chinese
/// @brief 开始渲染

View File

@ -51,4 +51,18 @@ void Renderer::HandleEvent(Event* evt)
}
}
void Renderer::BeginDraw()
{
KGE_ASSERT(render_ctx_);
render_ctx_->BeginDraw();
}
void Renderer::EndDraw()
{
KGE_ASSERT(render_ctx_);
render_ctx_->EndDraw();
}
} // namespace kiwano

View File

@ -24,7 +24,6 @@
#include <kiwano/render/GifImage.h>
#include <kiwano/render/TextStyle.hpp>
#include <kiwano/render/RenderContext.h>
#include <kiwano/render/TextureRenderContext.h>
#include <kiwano/platform/Window.h>
namespace kiwano
@ -198,28 +197,29 @@ public:
virtual void CreateStrokeStyle(StrokeStyle& stroke_style) = 0;
/// \~chinese
/// @brief 创建纹理渲染上下文
/// @brief 创建纹理渲染上下文,将上下文的渲染输出到纹理中
/// @param[in,out] texture 渲染输出的纹理
/// @param[in] desired_size 期望的输出大小
/// @return 纹理渲染上下文
/// @throw kiwano::SystemError 创建失败时抛出
virtual TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr) = 0;
virtual RenderContextPtr CreateTextureRenderContext(Texture& texture, const Size* desired_size = nullptr) = 0;
public:
/// \~chinese
/// @brief 获取渲染上下文
virtual RenderContext& GetContext() = 0;
RenderContext& GetContext();
/// \~chinese
/// @brief 获取渲染输出大小
virtual Size GetOutputSize() const;
Size GetOutputSize() const;
/// \~chinese
/// @brief 开始渲染
virtual void BeginDraw() = 0;
virtual void BeginDraw();
/// \~chinese
/// @brief 结束渲染
virtual void EndDraw() = 0;
virtual void EndDraw();
/// \~chinese
/// @brief 清除绘制内容
@ -249,13 +249,19 @@ protected:
virtual void Destroy() = 0;
protected:
bool vsync_;
Color clear_color_;
Size output_size_;
bool vsync_;
Color clear_color_;
Size output_size_;
RenderContextPtr render_ctx_;
};
/** @} */
inline RenderContext& Renderer::GetContext()
{
return *render_ctx_;
}
inline Size Renderer::GetOutputSize() const
{
return output_size_;

View File

@ -1,56 +0,0 @@
// Copyright (c) 2016-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
// 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 <kiwano/core/Logger.h>
#include <kiwano/render/TextureRenderContext.h>
#include <kiwano/render/Renderer.h>
namespace kiwano
{
TextureRenderContextPtr TextureRenderContext::Create()
{
TextureRenderContextPtr ptr;
try
{
ptr = Renderer::GetInstance().CreateTextureRenderContext(nullptr);
}
catch (std::exception&)
{
return nullptr;
}
return ptr;
}
TextureRenderContextPtr TextureRenderContext::Create(const Size& desired_size)
{
TextureRenderContextPtr ptr;
try
{
ptr = Renderer::GetInstance().CreateTextureRenderContext(&desired_size);
}
catch (std::exception&)
{
return nullptr;
}
return ptr;
}
} // namespace kiwano

View File

@ -1,57 +0,0 @@
// Copyright (c) 2016-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
// 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 <kiwano/render/RenderContext.h>
namespace kiwano
{
KGE_DECLARE_SMART_PTR(TextureRenderContext);
/**
* \addtogroup Render
* @{
*/
/// \~chinese
/// @brief 纹理渲染上下文
/// @details 纹理渲染上下文将渲染输出到一个纹理对象中
class KGE_API TextureRenderContext : public virtual RenderContext
{
public:
/// \~chinese
/// @brief 创建纹理渲染上下文
static TextureRenderContextPtr Create();
/// \~chinese
/// @brief 创建纹理渲染上下文
/// @param size 期望的输出大小
static TextureRenderContextPtr Create(const Size& desired_size);
/// \~chinese
/// @brief 获取渲染输出
/// @param[out] texture 纹理输出
/// @return 操作是否成功
virtual bool GetOutput(Texture& texture) = 0;
};
/** @} */
} // namespace kiwano

View File

@ -37,7 +37,7 @@ KGE_DECLARE_SMART_PTR(LocalStorage);
/// data.SaveInt("best-score", 20); // 保存最高分 20
/// int best = data.GetInt("best-score"); // 读取之前储存的最高分
/// @endcode
class KGE_API LocalStorage : public virtual ObjectBase
class KGE_API LocalStorage : public ObjectBase
{
public:
/// \~chinese