Refactor Singleton && Singleton mode ResourceCache

This commit is contained in:
Nomango 2019-08-13 15:00:43 +08:00
parent bd58cf1b49
commit 222b09f166
24 changed files with 254 additions and 237 deletions

View File

@ -81,7 +81,7 @@ namespace kiwano
return false;
}
hr = Audio::Instance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx());
hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx());
if (FAILED(hr))
{
if (wave_data_)

View File

@ -45,9 +45,9 @@ namespace kiwano
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer bindings
Init(Window::Instance()->GetHandle());
Init(Window::GetInstance()->GetHandle());
target_window_ = Renderer::Instance()->GetTargetWindow();
target_window_ = Renderer::GetInstance()->GetTargetWindow();
}
void ImGuiModule::DestroyComponent()
@ -64,9 +64,9 @@ namespace kiwano
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.KeyCtrl = Input::GetInstance()->IsDown(KeyCode::Ctrl);
io.KeyShift = Input::GetInstance()->IsDown(KeyCode::Shift);
io.KeyAlt = Input::GetInstance()->IsDown(KeyCode::Alt);
io.KeySuper = false;
// io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below.
@ -106,7 +106,7 @@ namespace kiwano
io.KeyMap[ImGuiKey_Y] = KeyCode::Y;
io.KeyMap[ImGuiKey_Z] = KeyCode::Z;
ImGui_Impl_Init(Renderer::Instance());
ImGui_Impl_Init(Renderer::GetInstance());
}
void ImGuiModule::BeforeRender()
@ -213,7 +213,7 @@ namespace kiwano
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();
Size display_size = Renderer::GetInstance()->GetOutputSize();
io.DisplaySize = ImVec2(display_size.x, display_size.y);
ImGui::NewFrame();
@ -238,7 +238,7 @@ namespace kiwano
::SetCursorPos(pos.x, pos.y);
}
Point pos = Input::Instance()->GetMousePos();
Point pos = Input::GetInstance()->GetMousePos();
io.MousePos = ImVec2(pos.x, pos.y);
}
@ -260,7 +260,7 @@ namespace kiwano
case ImGuiMouseCursor_Hand: cursor = MouseCursor::Hand; break;
}
Window::Instance()->SetMouseCursor(cursor);
Window::GetInstance()->SetMouseCursor(cursor);
}
void ImGuiModule::UpdateGamepads()
{

View File

@ -124,7 +124,7 @@ namespace kiwano
{
Rect bounds = GetBounds();
auto renderer = Renderer::Instance();
auto renderer = Renderer::GetInstance();
renderer->SetTransform(transform_matrix_);
renderer->FillRectangle(bounds, Color(Color::Red, .4f));
renderer->DrawRectangle(bounds, Color(Color::Red, .8f), 4.f);
@ -659,7 +659,7 @@ namespace kiwano
void VisualActor::PrepareRender()
{
auto renderer = Renderer::Instance();
auto renderer = Renderer::GetInstance();
renderer->SetTransform(transform_matrix_);
renderer->SetOpacity(displayed_opacity_);
}

View File

@ -28,7 +28,7 @@ namespace kiwano
: cache_expired_(false)
, stroke_width_(1.0f)
{
auto ctx = Renderer::Instance()->GetD2DDeviceResources()->GetDeviceContext();
auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
ThrowIfFailed(
ctx->CreateCompatibleRenderTarget(&render_target_)
@ -96,7 +96,7 @@ namespace kiwano
if (bitmap_cached_)
{
Rect bitmap_rect(0.f, 0.f, bitmap_cached_->GetSize().width, bitmap_cached_->GetSize().height);
Renderer::Instance()->DrawBitmap(
Renderer::GetInstance()->DrawBitmap(
bitmap_cached_,
bitmap_rect,
bitmap_rect
@ -121,7 +121,7 @@ namespace kiwano
void Canvas::SetOutlineJoinStyle(StrokeStyle outline_join)
{
outline_join_style_ = Renderer::Instance()->GetD2DDeviceResources()->GetStrokeStyle(outline_join);
outline_join_style_ = Renderer::GetInstance()->GetD2DDeviceResources()->GetStrokeStyle(outline_join);
}
void Canvas::SetTextStyle(Font const& font, TextStyle const & text_style)
@ -135,7 +135,7 @@ namespace kiwano
text_style_.outline,
DX::ConvertToColorF(text_style_.outline_color),
text_style_.outline_width,
Renderer::Instance()->GetD2DDeviceResources()->GetStrokeStyle(text_style_.outline_stroke)
Renderer::GetInstance()->GetD2DDeviceResources()->GetStrokeStyle(text_style_.outline_stroke)
);
// clear text format
@ -271,7 +271,7 @@ namespace kiwano
if (!text_format_)
{
ThrowIfFailed(
Renderer::Instance()->GetD2DDeviceResources()->CreateTextFormat(
Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextFormat(
text_format_,
text_font_,
text_style_
@ -282,7 +282,7 @@ namespace kiwano
ComPtr<IDWriteTextLayout> text_layout;
Size layout_size;
ThrowIfFailed(
Renderer::Instance()->GetD2DDeviceResources()->CreateTextLayout(
Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextLayout(
text_layout,
layout_size,
text,
@ -365,7 +365,7 @@ namespace kiwano
current_geometry_ = nullptr;
ThrowIfFailed(
Renderer::Instance()->GetD2DDeviceResources()->GetFactory()->CreatePathGeometry(&current_geometry_)
Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory()->CreatePathGeometry(&current_geometry_)
);
ThrowIfFailed(

View File

@ -60,7 +60,7 @@ namespace kiwano
void DebugNode::OnRender()
{
auto renderer = Renderer::Instance();
auto renderer = Renderer::GetInstance();
renderer->GetSolidColorBrush()->SetColor(DX::ConvertToColorF(background_color_));
renderer->GetD2DDeviceResources()->GetDeviceContext()->FillRoundedRectangle(
@ -89,9 +89,9 @@ namespace kiwano
}
#endif
ss << "Render: " << Renderer::Instance()->GetStatus().duration.Milliseconds() << "ms" << std::endl;
ss << "Render: " << Renderer::GetInstance()->GetStatus().duration.Milliseconds() << "ms" << std::endl;
ss << "Primitives / sec: " << Renderer::Instance()->GetStatus().primitives * frame_time_.size() << std::endl;
ss << "Primitives / sec: " << Renderer::GetInstance()->GetStatus().primitives * frame_time_.size() << std::endl;
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));

View File

@ -39,7 +39,7 @@ namespace kiwano
bool Frame::Load(Resource const& res)
{
ImagePtr image = ImageCache::Instance()->AddImage(res);
ImagePtr image = ImageCache::GetInstance()->AddImage(res);
if (image && image->IsValid())
{
SetImage(image);

View File

@ -69,7 +69,7 @@ namespace kiwano
if (!frame_rt_)
{
auto ctx = Renderer::Instance()->GetD2DDeviceResources()->GetDeviceContext();
auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
ThrowIfFailed(
ctx->CreateCompatibleRenderTarget(&frame_rt_)
);
@ -105,7 +105,7 @@ namespace kiwano
if (frame_to_render_)
{
Rect bounds = GetBounds();
Renderer::Instance()->DrawBitmap(frame_to_render_, bounds, bounds);
Renderer::GetInstance()->DrawBitmap(frame_to_render_, bounds, bounds);
}
}

View File

@ -27,7 +27,7 @@ namespace kiwano
Layer::Layer()
: swallow_(false)
{
SetSize(Renderer::Instance()->GetOutputSize());
SetSize(Renderer::GetInstance()->GetOutputSize());
auto handler = MakeClosure(this, &Layer::HandleMessages);

View File

@ -129,12 +129,12 @@ namespace kiwano
{
if (geo_)
{
Renderer::Instance()->FillGeometry(
Renderer::GetInstance()->FillGeometry(
geo_,
fill_color_
);
Renderer::Instance()->DrawGeometry(
Renderer::GetInstance()->DrawGeometry(
geo_,
stroke_color_,
stroke_width_,
@ -165,7 +165,7 @@ namespace kiwano
ComPtr<ID2D1PathGeometry> path_geo;
ComPtr<ID2D1GeometrySink> path_sink;
HRESULT hr = Renderer::Instance()->GetD2DDeviceResources()->GetFactory()->CreatePathGeometry(&path_geo);
HRESULT hr = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory()->CreatePathGeometry(&path_geo);
if (SUCCEEDED(hr))
{
@ -222,7 +222,7 @@ namespace kiwano
void RectNode::SetRect(Rect const& rect)
{
ComPtr<ID2D1RectangleGeometry> geo;
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetFactory();
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
if (SUCCEEDED(factory->CreateRectangleGeometry(DX::ConvertToRectF(rect), &geo)))
{
@ -264,7 +264,7 @@ namespace kiwano
void RoundedRectNode::SetRoundedRect(Rect const& rect, float radius_x, float radius_y)
{
ComPtr<ID2D1RoundedRectangleGeometry> geo;
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetFactory();
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
if (SUCCEEDED(factory->CreateRoundedRectangleGeometry(
D2D1::RoundedRect(
@ -313,7 +313,7 @@ namespace kiwano
void CircleNode::SetCircle(Point const& center, float radius)
{
ComPtr<ID2D1EllipseGeometry> geo;
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetFactory();
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
if (SUCCEEDED(factory->CreateEllipseGeometry(
D2D1::Ellipse(
@ -361,7 +361,7 @@ namespace kiwano
void EllipseNode::SetEllipse(Point const& center, float radius_x, float radius_y)
{
ComPtr<ID2D1EllipseGeometry> geo;
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetFactory();
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
if (SUCCEEDED(factory->CreateEllipseGeometry(
D2D1::Ellipse(
@ -393,7 +393,7 @@ namespace kiwano
{
current_geometry_ = nullptr;
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetFactory();
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
ThrowIfFailed(
factory->CreatePathGeometry(&current_geometry_)

View File

@ -87,7 +87,7 @@ namespace kiwano
{
if (frame_)
{
Renderer::Instance()->DrawBitmap(frame_->GetImage()->GetBitmap(), frame_->GetCropRect(), GetBounds());
Renderer::GetInstance()->DrawBitmap(frame_->GetImage()->GetBitmap(), frame_->GetCropRect(), GetBounds());
}
}
}

View File

@ -29,7 +29,7 @@ namespace kiwano
stage_ = this;
SetAnchor(0, 0);
SetSize(Renderer::Instance()->GetOutputSize());
SetSize(Renderer::GetInstance()->GetOutputSize());
}
Stage::~Stage()

View File

@ -303,7 +303,7 @@ namespace kiwano
if (text_layout_)
{
auto renderer = Renderer::Instance();
auto renderer = Renderer::GetInstance();
renderer->SetTextStyle(
GetDisplayedOpacity(),
style_.color,
@ -328,7 +328,7 @@ namespace kiwano
if (text_.empty())
return;
auto renderer = Renderer::Instance();
auto renderer = Renderer::GetInstance();
ThrowIfFailed(
renderer->GetD2DDeviceResources()->CreateTextFormat(

View File

@ -66,18 +66,18 @@ namespace kiwano
if (in_scene_)
{
ThrowIfFailed(
Renderer::Instance()->CreateLayer(in_layer_)
Renderer::GetInstance()->CreateLayer(in_layer_)
);
}
if (out_scene_)
{
ThrowIfFailed(
Renderer::Instance()->CreateLayer(out_layer_)
Renderer::GetInstance()->CreateLayer(out_layer_)
);
}
window_size_ = Renderer::Instance()->GetOutputSize();
window_size_ = Renderer::GetInstance()->GetOutputSize();
out_layer_prop_ = in_layer_prop_ = LayerProperties{ Rect(Point(), window_size_),1.f };
}
@ -101,7 +101,7 @@ namespace kiwano
void Transition::Render()
{
auto renderer = Renderer::Instance();
auto renderer = Renderer::GetInstance();
if (out_scene_)
{

View File

@ -521,7 +521,7 @@ namespace kiwano
geo_ = nullptr;
geo_sink_ = nullptr;
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetFactory();
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
ThrowIfFailed(
factory->CreatePathGeometry(&geo_)

View File

@ -27,18 +27,18 @@
#ifndef KGE_LOG
# ifdef KGE_DEBUG
# define KGE_LOG(FORMAT, ...) kiwano::Logger::Instance()->Messagef((FORMAT ## "\n"), __VA_ARGS__)
# define KGE_LOG(FORMAT, ...) kiwano::Logger::GetInstance()->Messagef((FORMAT ## "\n"), __VA_ARGS__)
# else
# define KGE_LOG __noop
# endif
#endif
#ifndef KGE_WARNING_LOG
# define KGE_WARNING_LOG(FORMAT, ...) kiwano::Logger::Instance()->Warningf((FORMAT ## "\n"), __VA_ARGS__)
# define KGE_WARNING_LOG(FORMAT, ...) kiwano::Logger::GetInstance()->Warningf((FORMAT ## "\n"), __VA_ARGS__)
#endif
#ifndef KGE_ERROR_LOG
# define KGE_ERROR_LOG(FORMAT, ...) kiwano::Logger::Instance()->Errorf((FORMAT ## "\n"), __VA_ARGS__)
# define KGE_ERROR_LOG(FORMAT, ...) kiwano::Logger::GetInstance()->Errorf((FORMAT ## "\n"), __VA_ARGS__)
#endif
namespace kiwano
@ -274,7 +274,7 @@ namespace kiwano
inline std::wostream& Logger::DefaultOutputColor(std::wostream& out)
{
::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), Logger::Instance()->default_stdout_color_);
::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), Logger::GetInstance()->default_stdout_color_);
return out;
}
}

View File

@ -28,7 +28,7 @@
#ifndef KGE_DECLARE_SINGLETON
#define KGE_DECLARE_SINGLETON( CLASS ) \
friend ::kiwano::Singleton< CLASS >; \
friend ::std::default_delete< CLASS >
friend typename std::unique_ptr< CLASS >::deleter_type
#endif
namespace kiwano
@ -37,21 +37,24 @@ namespace kiwano
struct Singleton
{
public:
static inline _Ty* Instance()
static inline _Ty* GetInstance()
{
if (!instance_)
{
std::call_once(once_, Init);
std::call_once(once_, InitInstance);
}
return instance_.get();
}
static inline void Init()
static inline void InitInstance()
{
if (!instance_) instance_.reset(new (std::nothrow) _Ty);
if (!instance_)
{
instance_.reset(new (std::nothrow) _Ty);
}
}
static inline void Destroy()
static inline void DestroyInstance()
{
instance_.reset();
}

View File

@ -25,6 +25,7 @@
#include "../base/input.h"
#include "../base/Director.h"
#include "../renderer/render.h"
#include "../utils/ResourceCache.h"
#include <windowsx.h> // GET_X_LPARAM, GET_Y_LPARAM
#include <imm.h> // ImmAssociateContext
#include <mutex> // std::mutex
@ -64,9 +65,9 @@ namespace kiwano
::CoInitialize(nullptr)
);
Use(Renderer::Instance());
Use(Input::Instance());
Use(Director::Instance());
Use(Renderer::GetInstance());
Use(Input::GetInstance());
Use(Director::GetInstance());
}
Application::~Application()
@ -79,7 +80,7 @@ namespace kiwano
void Application::Init(const Options& options)
{
ThrowIfFailed(
Window::Instance()->Create(
Window::GetInstance()->Create(
options.title,
options.width,
options.height,
@ -89,8 +90,8 @@ namespace kiwano
)
);
Renderer::Instance()->SetClearColor(options.clear_color);
Renderer::Instance()->SetVSyncEnabled(options.vsync);
Renderer::GetInstance()->SetClearColor(options.clear_color);
Renderer::GetInstance()->SetVSyncEnabled(options.vsync);
// Setup all components
for (Component* c : components_)
@ -100,14 +101,14 @@ namespace kiwano
if (options.debug)
{
Director::Instance()->ShowDebugInfo(true);
Renderer::Instance()->SetCollectingStatus(true);
Director::GetInstance()->ShowDebugInfo(true);
Renderer::GetInstance()->SetCollectingStatus(true);
}
// Everything is ready
OnReady();
HWND hwnd = Window::Instance()->GetHandle();
HWND hwnd = Window::GetInstance()->GetHandle();
// disable imm
::ImmAssociateContext(hwnd, nullptr);
@ -120,7 +121,7 @@ namespace kiwano
void Application::Run()
{
HWND hwnd = Window::Instance()->GetHandle();
HWND hwnd = Window::GetInstance()->GetHandle();
if (!hwnd)
throw std::exception("Calling Application::Run before Application::Init");
@ -128,7 +129,7 @@ namespace kiwano
if (hwnd)
{
end_ = false;
Window::Instance()->Prepare();
Window::GetInstance()->Prepare();
MSG msg = {};
while (::GetMessageW(&msg, nullptr, 0, 0) && !end_)
@ -158,13 +159,14 @@ namespace kiwano
}
// Destroy all instances
Director::Destroy();
Input::Destroy();
Renderer::Destroy();
Window::Destroy();
ResourceCache::DestroyInstance();
Director::DestroyInstance();
Input::DestroyInstance();
Renderer::DestroyInstance();
Window::DestroyInstance();
// DO NOT destroy Logger instance manually
// Logger::Destroy();
// Logger::DestroyInstance();
}
void Application::Use(Component* component)
@ -379,7 +381,7 @@ namespace kiwano
{
KGE_LOG(L"Window resized");
Window::Instance()->UpdateWindowRect();
Window::GetInstance()->UpdateWindowRect();
Event evt(Event::WindowResized);
evt.win.width = LOWORD(lparam);
@ -405,7 +407,7 @@ namespace kiwano
{
bool active = (LOWORD(wparam) != WA_INACTIVE);
Window::Instance()->SetActive(active);
Window::GetInstance()->SetActive(active);
Event evt(Event::WindowFocusChanged);
evt.win.focus = active;

View File

@ -174,7 +174,7 @@ namespace kiwano
void D2DDeviceResources::DiscardResources()
{
ImageCache::Instance()->Clear();
ImageCache::GetInstance()->Clear();
factory_.Reset();
device_.Reset();

View File

@ -51,7 +51,7 @@ namespace kiwano
saved_frame_.Reset();
decoder_.Reset();
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetWICImagingFactory();
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
if (res.IsFileType())
{
@ -124,7 +124,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
// Format convert to 32bppPBGRA which D2D expects
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetWICImagingFactory();
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
hr = factory->CreateFormatConverter(&converter);
}
@ -141,7 +141,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
auto ctx = Renderer::Instance()->GetD2DDeviceResources()->GetDeviceContext();
auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
// Create a D2DBitmap from IWICBitmapSource
raw_frame_.Reset();
@ -504,7 +504,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
auto factory = Renderer::Instance()->GetD2DDeviceResources()->GetWICImagingFactory();
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
hr = factory->CreatePalette(&wic_palette);
}

View File

@ -46,11 +46,11 @@ namespace kiwano
if (res.IsFileType())
{
hr = Renderer::Instance()->GetD2DDeviceResources()->CreateBitmapFromFile(bitmap, res.GetFileName());
hr = Renderer::GetInstance()->GetD2DDeviceResources()->CreateBitmapFromFile(bitmap, res.GetFileName());
}
else
{
hr = Renderer::Instance()->GetD2DDeviceResources()->CreateBitmapFromResource(bitmap, res);
hr = Renderer::GetInstance()->GetD2DDeviceResources()->CreateBitmapFromResource(bitmap, res);
}
if (SUCCEEDED(hr))

View File

@ -44,7 +44,7 @@ namespace kiwano
{
KGE_LOG(L"Creating device resources");
hwnd_ = Window::Instance()->GetHandle();
hwnd_ = Window::GetInstance()->GetHandle();
ThrowIfFailed(hwnd_ ? S_OK : E_FAIL);
@ -86,7 +86,7 @@ namespace kiwano
CreateDeviceResources()
);
output_size_ = Window::Instance()->GetSize();
output_size_ = Window::GetInstance()->GetSize();
}
void Renderer::DestroyComponent()

View File

@ -112,7 +112,7 @@ namespace kiwano
if (evt.type == Event::MouseHover)
{
SetStatus(Status::Hover);
Window::Instance()->SetMouseCursor(MouseCursor::Hand);
Window::GetInstance()->SetMouseCursor(MouseCursor::Hand);
if (mouse_over_callback_)
mouse_over_callback_();
@ -120,7 +120,7 @@ namespace kiwano
else if (evt.type == Event::MouseOut)
{
SetStatus(Status::Normal);
Window::Instance()->SetMouseCursor(MouseCursor::Arrow);
Window::GetInstance()->SetMouseCursor(MouseCursor::Arrow);
if (mouse_out_callback_)
mouse_out_callback_();

View File

@ -23,164 +23,38 @@
#include "../2d/Frame.h"
#include "../2d/FrameSequence.h"
#include "../renderer/GifImage.h"
#include "FileUtil.h"
#include <fstream>
namespace kiwano
{
namespace __res_loader_01
namespace __resource_cache_01
{
struct GlobalData
{
String path;
};
bool LoadImagesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* type,
const String* file, const Array<const wchar_t*>* files, int rows, int cols)
{
if (!gdata || !id) return false;
if (file)
{
// Gif image
if (type && (*type) == L"gif")
{
return loader->AddGifImage(*id, Resource(gdata->path + (*file)));
}
if (!(*file).empty())
{
if (rows || cols)
{
// Frame slices
return !!loader->AddFrameSequence(*id, Resource(gdata->path + (*file)), std::max(cols, 1), std::max(rows, 1));
}
else
{
// Simple image
return loader->AddFrame(*id, Resource(gdata->path + (*file)));
}
}
}
// Frames
if (files)
{
Array<FramePtr> frames;
frames.reserve(files->size());
for (const auto& file : (*files))
{
FramePtr frame = new Frame;
if (frame->Load(gdata->path + (file)))
{
frames.push_back(frame);
}
}
return !!loader->AddFrameSequence(*id, frames);
}
return false;
}
bool LoadJsonData(ResourceCache* loader, Json const& json_data)
{
GlobalData global_data;
if (json_data.count(L"path"))
{
global_data.path = json_data[L"path"];
}
if (json_data.count(L"images"))
{
for (const auto& image : json_data[L"images"])
{
const String* id = nullptr, *type = nullptr, *file = nullptr;
int rows = 0, cols = 0;
if (image.count(L"id")) id = &image[L"id"].as_string();
if (image.count(L"type")) type = &image[L"type"].as_string();
if (image.count(L"file")) file = &image[L"file"].as_string();
if (image.count(L"rows")) rows = image[L"rows"].as_int();
if (image.count(L"cols")) cols = image[L"cols"].as_int();
if (image.count(L"files"))
{
Array<const wchar_t*> files;
files.reserve(image[L"files"].size());
for (const auto& file : image[L"files"])
{
files.push_back(file.as_string().c_str());
}
if (!LoadImagesFromData(loader, &global_data, id, type, file, &files, rows, cols))
return false;
}
else
{
if (!LoadImagesFromData(loader, &global_data, id, type, file, nullptr, rows, cols))
return false;
}
}
}
return true;
}
bool LoadXmlData(ResourceCache* loader, tinyxml2::XMLElement* elem)
{
GlobalData global_data;
if (auto path = elem->FirstChildElement(L"path"))
{
global_data.path = path->GetText();
}
if (auto images = elem->FirstChildElement(L"images"))
{
for (auto image = images->FirstChildElement(); image; image = image->NextSiblingElement())
{
String id, type, file;
int rows = 0, cols = 0;
if (auto attr = image->Attribute(L"id")) id.assign(attr); // assign() copies attr content
if (auto attr = image->Attribute(L"type")) type = attr; // operator=() just holds attr pointer
if (auto attr = image->Attribute(L"file")) file = attr;
if (auto attr = image->IntAttribute(L"rows")) rows = attr;
if (auto attr = image->IntAttribute(L"cols")) cols = attr;
if (file.empty() && !image->NoChildren())
{
Array<const wchar_t*> files_arr;
for (auto file = image->FirstChildElement(); file; file = file->NextSiblingElement())
{
if (auto path = file->Attribute(L"path"))
{
files_arr.push_back(path);
}
}
if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, &files_arr, rows, cols))
return false;
}
else
{
if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, nullptr, rows, cols))
return false;
}
}
}
return true;
}
bool LoadJsonData(ResourceCache* loader, Json const& json_data);
bool LoadXmlData(ResourceCache* loader, tinyxml2::XMLElement* elem);
}
namespace
{
Map<String, Closure<bool(ResourceCache*, Json const&)>> load_json_funcs = {
{ L"latest", __res_loader_01::LoadJsonData },
{ L"0.1", __res_loader_01::LoadJsonData },
{ L"latest", __resource_cache_01::LoadJsonData },
{ L"0.1", __resource_cache_01::LoadJsonData },
};
Map<String, Closure<bool(ResourceCache*, tinyxml2::XMLElement*)>> load_xml_funcs = {
{ L"latest", __res_loader_01::LoadXmlData },
{ L"0.1", __res_loader_01::LoadXmlData },
{ L"latest", __resource_cache_01::LoadXmlData },
{ L"0.1", __resource_cache_01::LoadXmlData },
};
}
ResourceCache::ResourceCache()
{
}
ResourceCache::~ResourceCache()
{
Clear();
}
bool ResourceCache::LoadFromJsonFile(String const& file_path)
{
Json json_data;
@ -479,18 +353,152 @@ namespace kiwano
cache_.erase(id);
}
void ResourceCache::Destroy()
void ResourceCache::Clear()
{
cache_.clear();
}
ResourceCache::ResourceCache()
{
}
ResourceCache::~ResourceCache()
{
Destroy();
}
}
namespace kiwano
{
namespace __resource_cache_01
{
struct GlobalData
{
String path;
};
bool LoadImagesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* type,
const String* file, const Array<const wchar_t*>* files, int rows, int cols)
{
if (!gdata || !id) return false;
if (file)
{
// Gif image
if (type && (*type) == L"gif")
{
return loader->AddGifImage(*id, Resource(gdata->path + (*file)));
}
if (!(*file).empty())
{
if (rows || cols)
{
// Frame slices
return !!loader->AddFrameSequence(*id, Resource(gdata->path + (*file)), std::max(cols, 1), std::max(rows, 1));
}
else
{
// Simple image
return loader->AddFrame(*id, Resource(gdata->path + (*file)));
}
}
}
// Frames
if (files)
{
Array<FramePtr> frames;
frames.reserve(files->size());
for (const auto& file : (*files))
{
FramePtr frame = new Frame;
if (frame->Load(gdata->path + (file)))
{
frames.push_back(frame);
}
}
return !!loader->AddFrameSequence(*id, frames);
}
return false;
}
bool LoadJsonData(ResourceCache* loader, Json const& json_data)
{
GlobalData global_data;
if (json_data.count(L"path"))
{
global_data.path = json_data[L"path"];
}
if (json_data.count(L"images"))
{
for (const auto& image : json_data[L"images"])
{
const String* id = nullptr, * type = nullptr, * file = nullptr;
int rows = 0, cols = 0;
if (image.count(L"id")) id = &image[L"id"].as_string();
if (image.count(L"type")) type = &image[L"type"].as_string();
if (image.count(L"file")) file = &image[L"file"].as_string();
if (image.count(L"rows")) rows = image[L"rows"].as_int();
if (image.count(L"cols")) cols = image[L"cols"].as_int();
if (image.count(L"files"))
{
Array<const wchar_t*> files;
files.reserve(image[L"files"].size());
for (const auto& file : image[L"files"])
{
files.push_back(file.as_string().c_str());
}
if (!LoadImagesFromData(loader, &global_data, id, type, file, &files, rows, cols))
return false;
}
else
{
if (!LoadImagesFromData(loader, &global_data, id, type, file, nullptr, rows, cols))
return false;
}
}
}
return true;
}
bool LoadXmlData(ResourceCache* loader, tinyxml2::XMLElement* elem)
{
GlobalData global_data;
if (auto path = elem->FirstChildElement(L"path"))
{
global_data.path = path->GetText();
}
if (auto images = elem->FirstChildElement(L"images"))
{
for (auto image = images->FirstChildElement(); image; image = image->NextSiblingElement())
{
String id, type, file;
int rows = 0, cols = 0;
if (auto attr = image->Attribute(L"id")) id.assign(attr); // assign() copies attr content
if (auto attr = image->Attribute(L"type")) type = attr; // operator=() just holds attr pointer
if (auto attr = image->Attribute(L"file")) file = attr;
if (auto attr = image->IntAttribute(L"rows")) rows = attr;
if (auto attr = image->IntAttribute(L"cols")) cols = attr;
if (file.empty() && !image->NoChildren())
{
Array<const wchar_t*> files_arr;
for (auto file = image->FirstChildElement(); file; file = file->NextSiblingElement())
{
if (auto path = file->Attribute(L"path"))
{
files_arr.push_back(path);
}
}
if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, &files_arr, rows, cols))
return false;
}
else
{
if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, nullptr, rows, cols))
return false;
}
}
}
return true;
}
}
}

View File

@ -22,6 +22,7 @@
#include "../macros.h"
#include "../common/helper.h"
#include "../common/Json.hpp"
#include "../common/Singleton.hpp"
#include "../base/Resource.h"
#include "../2d/include-forwards.h"
#include "../renderer/GifImage.h"
@ -31,7 +32,10 @@ namespace kiwano
{
// 资源缓存
class KGE_API ResourceCache
: public Singleton<ResourceCache>
{
KGE_DECLARE_SINGLETON(ResourceCache);
public:
// 从 JSON 文件加载资源信息
bool LoadFromJsonFile(String const& file_path);
@ -89,8 +93,8 @@ namespace kiwano
// 删除指定资源
void Delete(String const& id);
// 销毁所有资源
void Destroy();
// 清空所有资源
void Clear();
template<typename _Ty>
_Ty* Get(String const& id) const
@ -101,7 +105,7 @@ namespace kiwano
return dynamic_cast<_Ty*>((*iter).second.Get());
}
public:
protected:
ResourceCache();
virtual ~ResourceCache();