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(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);

View File

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

View File

@ -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 <fstream>
namespace kiwano
{
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();
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<Resource> 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<Rect> 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<ImagePtr> image_arr;
@ -206,6 +296,11 @@ namespace kiwano
return Get<Image>(id);
}
GifImagePtr ResLoader::GetGifImage(String const& id) const
{
return Get<GifImage>(id);
}
FramesPtr ResLoader::GetFrames(String const & id) const
{
return Get<Frames>(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);
}
}
}

View File

@ -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<Resource> 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<typename _Ty>
_Ty* Get(String const& id) const
{
@ -83,6 +93,5 @@ namespace kiwano
protected:
UnorderedMap<String, ObjectPtr> res_;
List<String> search_paths_;
};
}

View File

@ -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 = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
// Ìí¼Ó°´¼ü¼àÌý

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