From c523a138d4a413304bf136b52d98a9509d2eb257 Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Wed, 31 Jul 2019 00:09:24 +0800 Subject: [PATCH] ResLoader supports loading from JSON files --- kiwano/2d/include-forwards.h | 1 + kiwano/common/Json.h | 30 ++++- kiwano/utils/ResLoader.cpp | 149 ++++++++++++++++++------ kiwano/utils/ResLoader.h | 21 +++- samples/Samples/Demo1.h | 10 +- samples/Samples/Demo2.h | 2 +- samples/Samples/Demo3.h | 2 +- samples/Samples/Demo4.h | 2 +- samples/Samples/Demo5.h | 2 +- samples/Samples/Samples.vcxproj | 3 + samples/Samples/Samples.vcxproj.filters | 3 + samples/Samples/main.cpp | 10 +- samples/Samples/res/res.json | 35 ++++++ 13 files changed, 212 insertions(+), 58 deletions(-) create mode 100644 samples/Samples/res/res.json diff --git a/kiwano/2d/include-forwards.h b/kiwano/2d/include-forwards.h index fe502288..eb07832f 100644 --- a/kiwano/2d/include-forwards.h +++ b/kiwano/2d/include-forwards.h @@ -49,6 +49,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(Text); KGE_DECLARE_SMART_PTR(Canvas); KGE_DECLARE_SMART_PTR(GeometryNode); diff --git a/kiwano/common/Json.h b/kiwano/common/Json.h index 46e98490..7ff64e3b 100644 --- a/kiwano/common/Json.h +++ b/kiwano/common/Json.h @@ -2467,10 +2467,34 @@ namespace kiwano public: // implicitly convert functions - template - inline operator _Ty() const + inline operator boolean_type () const { - return get<_Ty>(); + return as_bool(); + } + + inline operator integer_type () const + { + return as_int(); + } + + inline operator float_type () const + { + return as_float(); + } + + inline operator const array_type& () const + { + return as_array(); + } + + inline operator const string_type& () const + { + return as_string(); + } + + inline operator const object_type& () const + { + return as_object(); } public: diff --git a/kiwano/utils/ResLoader.cpp b/kiwano/utils/ResLoader.cpp index e0b62ae3..7496aba9 100644 --- a/kiwano/utils/ResLoader.cpp +++ b/kiwano/utils/ResLoader.cpp @@ -19,40 +19,107 @@ // THE SOFTWARE. #include "ResLoader.h" -#include "../platform/modules.h" +#include "../base/logs.h" #include "../2d/Image.h" #include "../2d/Frames.h" +#include "../2d/GifImage.h" +#include "FileUtil.h" +#include namespace kiwano { namespace { - Resource LocateRes(Resource const& res, List const& paths) + void LoadJsonData09(Json const& json_data, ResLoader* loader) { - if (res.IsFileType()) + String path; + if (json_data.count(L"path")) { - String file_name = res.GetFileName(); - for (const auto& path : paths) + path = json_data[L"path"]; + } + + if (json_data.count(L"images")) + { + for (const auto& image : json_data[L"images"]) { - if (modules::Shlwapi::Get().PathFileExistsW((path + file_name).c_str())) - { - return Resource{ path + file_name }; - } + String file = image[L"file"]; + String id = image.count(L"id") ? image[L"id"] : file; + + if (image.count(L"type") && image[L"type"].as_string() == L"gif") + loader->AddGifImage(id, Resource(path + file)); + else + loader->AddImage(id, Resource(path + file)); } } - return res; + + /*if (json_data.count(L"sounds")) + { + for (const auto& sound : json_data[L"sounds"]) + { + loader->AddObj(); + } + }*/ } } + bool ResLoader::LoadFromJsonFile(String const& file_path) + { + Json json_data; + std::wifstream ifs; + ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); + + try + { + ifs.open(file_path.c_str()); + ifs >> json_data; + ifs.close(); + } + catch (std::wifstream::failure& e) + { + String msg(e.what()); + KGE_WARNING_LOG(L"ResLoader::LoadFromJsonFile failed: Cannot open file. (%s)", msg.c_str()); + return false; + } + catch (json_exception& e) + { + String msg(e.what()); + KGE_WARNING_LOG(L"ResLoader::LoadFromJsonFile failed: Cannot parse to JSON. (%s)", msg.c_str()); + return false; + } + return LoadFromJson(json_data); + } + + bool ResLoader::LoadFromJson(Json const& json_data) + { + try + { + String version = json_data[L"version"]; + if (version.empty() || version == L"0.9") + { + LoadJsonData09(json_data, this); + } + else + { + throw std::runtime_error("unknown JSON data version"); + } + } + catch (std::exception& e) + { + String msg(e.what()); + KGE_WARNING_LOG(L"ResLoader::LoadFromJson failed: JSON data is invalid. (%s)", msg.c_str()); + return false; + } + return true; + } + bool ResLoader::AddImage(String const& id, Resource const& image) { ImagePtr ptr = new (std::nothrow) Image; if (ptr) { - if (ptr->Load(LocateRes(image, search_paths_))) + if (ptr->Load(image)) { - res_.insert(std::make_pair(id, ptr)); - return true; + return AddImage(id, ptr); } } return false; @@ -68,6 +135,29 @@ namespace kiwano return false; } + bool ResLoader::AddGifImage(String const& id, Resource const& image) + { + GifImagePtr ptr = new (std::nothrow) GifImage; + if (ptr) + { + if (ptr->Load(image)) + { + return AddGifImage(id, ptr); + } + } + return false; + } + + bool ResLoader::AddGifImage(String const& id, GifImagePtr image) + { + if (image) + { + res_.insert(std::make_pair(id, image)); + return true; + } + return false; + } + size_t ResLoader::AddFrames(String const& id, Array const& images) { if (images.empty()) @@ -81,7 +171,7 @@ namespace kiwano ImagePtr ptr = new (std::nothrow) Image; if (ptr) { - if (ptr->Load(LocateRes(image, search_paths_))) + if (ptr->Load(image)) { image_arr.push_back(ptr); } @@ -120,7 +210,7 @@ namespace kiwano return 0; ImagePtr raw = new (std::nothrow) Image; - if (!raw || !raw->Load(LocateRes(image, search_paths_))) + if (!raw || !raw->Load(image)) return 0; float raw_width = raw->GetSourceWidth(); @@ -156,7 +246,7 @@ namespace kiwano size_t ResLoader::AddFrames(String const & id, Resource const & image, Array const & crop_rects) { ImagePtr raw = new (std::nothrow) Image; - if (!raw || !raw->Load(LocateRes(image, search_paths_))) + if (!raw || !raw->Load(image)) return 0; Array image_arr; @@ -206,6 +296,11 @@ namespace kiwano return Get(id); } + GifImagePtr ResLoader::GetGifImage(String const& id) const + { + return Get(id); + } + FramesPtr ResLoader::GetFrames(String const & id) const { return Get(id); @@ -226,26 +321,4 @@ namespace kiwano res_.clear(); } - void ResLoader::AddSearchPath(String const & path) - { - String tmp = path; - size_t pos = 0; - while ((pos = tmp.find(L"/", pos)) != String::npos) - { - tmp.replace(pos, 1, L"\\"); - pos++; - } - - if (tmp.at(tmp.length() - 1) != L'\\') - { - tmp.append(L"\\"); - } - - auto iter = std::find(search_paths_.cbegin(), search_paths_.cend(), tmp); - if (iter == search_paths_.cend()) - { - search_paths_.push_front(tmp); - } - } - } \ No newline at end of file diff --git a/kiwano/utils/ResLoader.h b/kiwano/utils/ResLoader.h index 7b1e69ec..145e6aab 100644 --- a/kiwano/utils/ResLoader.h +++ b/kiwano/utils/ResLoader.h @@ -21,6 +21,7 @@ #pragma once #include "../macros.h" #include "../common/helper.h" +#include "../common/Json.h" #include "../base/Resource.h" #include "../2d/include-forwards.h" @@ -29,12 +30,24 @@ namespace kiwano class KGE_API ResLoader { public: + // 从 JSON 文件加载资源信息 + bool LoadFromJsonFile(String const& file_path); + + // 从 JSON 加载资源信息 + bool LoadFromJson(Json const& json_data); + // 添加图片 bool AddImage(String const& id, Resource const& image); // 添加图片 bool AddImage(String const& id, ImagePtr image); + // 添加 GIF 图片 + bool AddGifImage(String const& id, Resource const& image); + + // 添加 GIF 图片 + bool AddGifImage(String const& id, GifImagePtr image); + // 添加帧集合 size_t AddFrames(String const& id, Array const& images); @@ -57,6 +70,8 @@ namespace kiwano ImagePtr GetImage(String const& id) const; + GifImagePtr GetGifImage(String const& id) const; + FramesPtr GetFrames(String const& id) const; ObjectPtr GetObj(String const& id) const; @@ -67,11 +82,6 @@ namespace kiwano // 销毁所有资源 void Destroy(); - // 添加资源搜索路径 - void AddSearchPath( - String const& path - ); - template _Ty* Get(String const& id) const { @@ -83,6 +93,5 @@ namespace kiwano protected: UnorderedMap res_; - List search_paths_; }; } diff --git a/samples/Samples/Demo1.h b/samples/Samples/Demo1.h index 422ecbb5..38ef868b 100644 --- a/samples/Samples/Demo1.h +++ b/samples/Samples/Demo1.h @@ -7,15 +7,15 @@ class Demo1 : public Scene { public: - static ScenePtr Create() + static ScenePtr Create(ResLoader* loader) { - return new Demo1; + return new Demo1(loader); } - Demo1() + Demo1(ResLoader* loader) { - // 创建人物图片 - ImagePtr man_image = new Image(L"res/man.png"); + // 获取人物图片 + ImagePtr man_image = loader->GetImage(L"man"); // 缓动方程 auto ease_functions = { diff --git a/samples/Samples/Demo2.h b/samples/Samples/Demo2.h index d318632a..b1f8e572 100644 --- a/samples/Samples/Demo2.h +++ b/samples/Samples/Demo2.h @@ -67,7 +67,7 @@ class Demo2 : public Scene { public: - static ScenePtr Create() + static ScenePtr Create(ResLoader* loader) { return new Demo2; } diff --git a/samples/Samples/Demo3.h b/samples/Samples/Demo3.h index 2ea0073f..b791897d 100644 --- a/samples/Samples/Demo3.h +++ b/samples/Samples/Demo3.h @@ -11,7 +11,7 @@ class Demo3 TextPtr state_text; // 播放状态文字 public: - static ScenePtr Create() + static ScenePtr Create(ResLoader* loader) { return new Demo3; } diff --git a/samples/Samples/Demo4.h b/samples/Samples/Demo4.h index 0d6dbb89..6ef74780 100644 --- a/samples/Samples/Demo4.h +++ b/samples/Samples/Demo4.h @@ -163,7 +163,7 @@ class Demo4 : public Scene { public: - static ScenePtr Create() + static ScenePtr Create(ResLoader* loader) { return new Demo4; } diff --git a/samples/Samples/Demo5.h b/samples/Samples/Demo5.h index 63b5cddd..8f5a9b84 100644 --- a/samples/Samples/Demo5.h +++ b/samples/Samples/Demo5.h @@ -8,7 +8,7 @@ class Demo5 : public Scene { public: - static ScenePtr Create() + static ScenePtr Create(ResLoader* loader) { return new Demo5; } diff --git a/samples/Samples/Samples.vcxproj b/samples/Samples/Samples.vcxproj index 38fe17d6..c05de61c 100644 --- a/samples/Samples/Samples.vcxproj +++ b/samples/Samples/Samples.vcxproj @@ -213,6 +213,9 @@ {ff7f943d-a89c-4e6c-97cf-84f7d8ff8edf} + + + diff --git a/samples/Samples/Samples.vcxproj.filters b/samples/Samples/Samples.vcxproj.filters index f243c2ca..fdf10a3d 100644 --- a/samples/Samples/Samples.vcxproj.filters +++ b/samples/Samples/Samples.vcxproj.filters @@ -11,4 +11,7 @@ + + + \ No newline at end of file diff --git a/samples/Samples/main.cpp b/samples/Samples/main.cpp index d6c8f4a4..8dbb0997 100644 --- a/samples/Samples/main.cpp +++ b/samples/Samples/main.cpp @@ -11,7 +11,7 @@ namespace struct Demo { String title; - ScenePtr(*Create)(); + ScenePtr(*Create)(ResLoader*); }; Demo s_Demos[] = { @@ -28,6 +28,8 @@ namespace class DemoApp : public Application { + ResLoader loader_; + public: DemoApp() { @@ -43,6 +45,10 @@ public: void OnStart() override { + // 从 JSON 文件中加载资源 + loader_.LoadFromJsonFile(L"res/res.json"); + + // 切换到第一个场景 ChangeDemoScene(0); } @@ -55,7 +61,7 @@ public: String title = s_Demos[index].title; Window::Instance()->SetTitle(L"Kiwano示例程序 - " + title); - ScenePtr scene = s_Demos[index].Create(); + ScenePtr scene = s_Demos[index].Create(&loader_); EnterScene(scene); // 添加按键监听 diff --git a/samples/Samples/res/res.json b/samples/Samples/res/res.json new file mode 100644 index 00000000..c5774f4f --- /dev/null +++ b/samples/Samples/res/res.json @@ -0,0 +1,35 @@ +{ + "version": "0.9", + "path": "./res/", + "images": [ + { + "id": "man", + "file": "man.png" + }, + { + "id": "monster", + "file": "akushu.png" + }, + { + "id": "forest_bg", + "file": "spring_forest.jpg" + }, + { + "id": "tiger", + "file": "tiger.png", + "rows": 3, + "cols": 5 + }, + { + "id": "Kusanagi", + "file": "Kusanagi.gif", + "type": "gif" + } + ], + "sounds": [ + { + "id": "bg_music", + "file": "splash.mp3" + } + ] +} \ No newline at end of file