ResLoader supports loading from JSON files

This commit is contained in:
Nomango 2019-07-31 00:09:24 +08:00 committed by Nomango
parent 4768c340a6
commit c523a138d4
13 changed files with 212 additions and 58 deletions

View File

@ -49,6 +49,7 @@ namespace kiwano
KGE_DECLARE_SMART_PTR(Scene); KGE_DECLARE_SMART_PTR(Scene);
KGE_DECLARE_SMART_PTR(Layer); KGE_DECLARE_SMART_PTR(Layer);
KGE_DECLARE_SMART_PTR(Sprite); KGE_DECLARE_SMART_PTR(Sprite);
KGE_DECLARE_SMART_PTR(GifImage);
KGE_DECLARE_SMART_PTR(Text); KGE_DECLARE_SMART_PTR(Text);
KGE_DECLARE_SMART_PTR(Canvas); KGE_DECLARE_SMART_PTR(Canvas);
KGE_DECLARE_SMART_PTR(GeometryNode); KGE_DECLARE_SMART_PTR(GeometryNode);

View File

@ -2467,10 +2467,34 @@ namespace kiwano
public: public:
// implicitly convert functions // implicitly convert functions
template <typename _Ty> inline operator boolean_type () const
inline operator _Ty() 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: public:

View File

@ -19,40 +19,107 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "ResLoader.h" #include "ResLoader.h"
#include "../platform/modules.h" #include "../base/logs.h"
#include "../2d/Image.h" #include "../2d/Image.h"
#include "../2d/Frames.h" #include "../2d/Frames.h"
#include "../2d/GifImage.h"
#include "FileUtil.h"
#include <fstream>
namespace kiwano namespace kiwano
{ {
namespace namespace
{ {
Resource LocateRes(Resource const& res, List<String> 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(); path = json_data[L"path"];
for (const auto& path : paths) }
if (json_data.count(L"images"))
{
for (const auto& image : json_data[L"images"])
{ {
if (modules::Shlwapi::Get().PathFileExistsW((path + file_name).c_str())) String file = image[L"file"];
{ String id = image.count(L"id") ? image[L"id"] : file;
return Resource{ path + file_name };
} 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) bool ResLoader::AddImage(String const& id, Resource const& image)
{ {
ImagePtr ptr = new (std::nothrow) Image; ImagePtr ptr = new (std::nothrow) Image;
if (ptr) if (ptr)
{ {
if (ptr->Load(LocateRes(image, search_paths_))) if (ptr->Load(image))
{ {
res_.insert(std::make_pair(id, ptr)); return AddImage(id, ptr);
return true;
} }
} }
return false; return false;
@ -68,6 +135,29 @@ namespace kiwano
return false; 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<Resource> const& images) size_t ResLoader::AddFrames(String const& id, Array<Resource> const& images)
{ {
if (images.empty()) if (images.empty())
@ -81,7 +171,7 @@ namespace kiwano
ImagePtr ptr = new (std::nothrow) Image; ImagePtr ptr = new (std::nothrow) Image;
if (ptr) if (ptr)
{ {
if (ptr->Load(LocateRes(image, search_paths_))) if (ptr->Load(image))
{ {
image_arr.push_back(ptr); image_arr.push_back(ptr);
} }
@ -120,7 +210,7 @@ namespace kiwano
return 0; return 0;
ImagePtr raw = new (std::nothrow) Image; ImagePtr raw = new (std::nothrow) Image;
if (!raw || !raw->Load(LocateRes(image, search_paths_))) if (!raw || !raw->Load(image))
return 0; return 0;
float raw_width = raw->GetSourceWidth(); float raw_width = raw->GetSourceWidth();
@ -156,7 +246,7 @@ namespace kiwano
size_t ResLoader::AddFrames(String const & id, Resource const & image, Array<Rect> const & crop_rects) size_t ResLoader::AddFrames(String const & id, Resource const & image, Array<Rect> const & crop_rects)
{ {
ImagePtr raw = new (std::nothrow) Image; ImagePtr raw = new (std::nothrow) Image;
if (!raw || !raw->Load(LocateRes(image, search_paths_))) if (!raw || !raw->Load(image))
return 0; return 0;
Array<ImagePtr> image_arr; Array<ImagePtr> image_arr;
@ -206,6 +296,11 @@ namespace kiwano
return Get<Image>(id); return Get<Image>(id);
} }
GifImagePtr ResLoader::GetGifImage(String const& id) const
{
return Get<GifImage>(id);
}
FramesPtr ResLoader::GetFrames(String const & id) const FramesPtr ResLoader::GetFrames(String const & id) const
{ {
return Get<Frames>(id); return Get<Frames>(id);
@ -226,26 +321,4 @@ namespace kiwano
res_.clear(); 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);
}
}
} }

View File

@ -21,6 +21,7 @@
#pragma once #pragma once
#include "../macros.h" #include "../macros.h"
#include "../common/helper.h" #include "../common/helper.h"
#include "../common/Json.h"
#include "../base/Resource.h" #include "../base/Resource.h"
#include "../2d/include-forwards.h" #include "../2d/include-forwards.h"
@ -29,12 +30,24 @@ namespace kiwano
class KGE_API ResLoader class KGE_API ResLoader
{ {
public: 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, Resource const& image);
// 添加图片 // 添加图片
bool AddImage(String const& id, ImagePtr 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<Resource> const& images); size_t AddFrames(String const& id, Array<Resource> const& images);
@ -57,6 +70,8 @@ namespace kiwano
ImagePtr GetImage(String const& id) const; ImagePtr GetImage(String const& id) const;
GifImagePtr GetGifImage(String const& id) const;
FramesPtr GetFrames(String const& id) const; FramesPtr GetFrames(String const& id) const;
ObjectPtr GetObj(String const& id) const; ObjectPtr GetObj(String const& id) const;
@ -67,11 +82,6 @@ namespace kiwano
// 销毁所有资源 // 销毁所有资源
void Destroy(); void Destroy();
// Ìí¼Ó×ÊÔ´ËÑË÷·¾¶
void AddSearchPath(
String const& path
);
template<typename _Ty> template<typename _Ty>
_Ty* Get(String const& id) const _Ty* Get(String const& id) const
{ {
@ -83,6 +93,5 @@ namespace kiwano
protected: protected:
UnorderedMap<String, ObjectPtr> res_; UnorderedMap<String, ObjectPtr> res_;
List<String> search_paths_;
}; };
} }

View File

@ -7,15 +7,15 @@ class Demo1
: public Scene : public Scene
{ {
public: 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 = { auto ease_functions = {

View File

@ -67,7 +67,7 @@ class Demo2
: public Scene : public Scene
{ {
public: public:
static ScenePtr Create() static ScenePtr Create(ResLoader* loader)
{ {
return new Demo2; return new Demo2;
} }

View File

@ -11,7 +11,7 @@ class Demo3
TextPtr state_text; // 播放状态文字 TextPtr state_text; // 播放状态文字
public: public:
static ScenePtr Create() static ScenePtr Create(ResLoader* loader)
{ {
return new Demo3; return new Demo3;
} }

View File

@ -163,7 +163,7 @@ class Demo4
: public Scene : public Scene
{ {
public: public:
static ScenePtr Create() static ScenePtr Create(ResLoader* loader)
{ {
return new Demo4; return new Demo4;
} }

View File

@ -8,7 +8,7 @@ class Demo5
: public Scene : public Scene
{ {
public: public:
static ScenePtr Create() static ScenePtr Create(ResLoader* loader)
{ {
return new Demo5; return new Demo5;
} }

View File

@ -213,6 +213,9 @@
<Project>{ff7f943d-a89c-4e6c-97cf-84f7d8ff8edf}</Project> <Project>{ff7f943d-a89c-4e6c-97cf-84f7d8ff8edf}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="res\res.json" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>

View File

@ -11,4 +11,7 @@
<ClInclude Include="Demo4.h" /> <ClInclude Include="Demo4.h" />
<ClInclude Include="Demo5.h" /> <ClInclude Include="Demo5.h" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="res\res.json" />
</ItemGroup>
</Project> </Project>

View File

@ -11,7 +11,7 @@ namespace
struct Demo struct Demo
{ {
String title; String title;
ScenePtr(*Create)(); ScenePtr(*Create)(ResLoader*);
}; };
Demo s_Demos[] = { Demo s_Demos[] = {
@ -28,6 +28,8 @@ namespace
class DemoApp class DemoApp
: public Application : public Application
{ {
ResLoader loader_;
public: public:
DemoApp() DemoApp()
{ {
@ -43,6 +45,10 @@ public:
void OnStart() override void OnStart() override
{ {
// 从 JSON 文件中加载资源
loader_.LoadFromJsonFile(L"res/res.json");
// 切换到第一个场景
ChangeDemoScene(0); ChangeDemoScene(0);
} }
@ -55,7 +61,7 @@ public:
String title = s_Demos[index].title; String title = s_Demos[index].title;
Window::Instance()->SetTitle(L"KiwanoʾÀý³ÌÐò - " + title); Window::Instance()->SetTitle(L"KiwanoʾÀý³ÌÐò - " + title);
ScenePtr scene = s_Demos[index].Create(); ScenePtr scene = s_Demos[index].Create(&loader_);
EnterScene(scene); EnterScene(scene);
// Ìí¼Ó°´¼ü¼àÌý // Ìí¼Ó°´¼ü¼àÌý

View File

@ -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"
}
]
}