Skip to content

Commit 1aaccfc

Browse files
committed
feat: Implement Save/Load - Serialization/Deserialization
1 parent 37b001a commit 1aaccfc

71 files changed

Lines changed: 2726 additions & 755 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Test/ContainerTest.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ TEST(ContainerTest, SHashMapVectorTest)
131131
TEST(ContainerTest, SHashSetVectorTest)
132132
{
133133
using namespace sh;
134-
core::SHashSetVector<int> set{};
134+
core::SHashSetVector<int, std::hash<int>, std::equal_to<int>, 8> set{};
135135
set.Insert(0);
136136
set.Insert(1);
137137
set.Insert(2);

Test/OctreeTest.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ TEST(OctreeTest, InsertTest)
2525
{
2626
return pos;
2727
}
28-
bool Intersect(const render::AABB& aabb) const override
28+
bool Intersect(const render::AABB& other) const override
2929
{
30-
return aabb.Intersects(aabb);
30+
return aabb.Intersects(other);
3131
}
3232
};
3333

Test/ReflectionTest.hpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class Derived : public Base
2929
Derived* sobjectPtr;
3030
PROPERTY(sobjectArr)
3131
std::array<Derived*, 2> sobjectArr;
32+
PROPERTY(map)
33+
sh::core::SMap<std::string, int> map;
3234
};
3335

3436
TEST(ReflectionTest, TypeInfoTest)
@@ -56,7 +58,7 @@ TEST(ReflectionTest, PropertyTest)
5658
ASSERT_NE(numbersProperty, nullptr);
5759

5860
EXPECT_EQ(*numberProperty->Get<int>(&derived), 42);
59-
EXPECT_EQ(numbersProperty->GetTypeName(), sh::core::reflection::GetTypeName<std::vector<int>>());
61+
EXPECT_EQ(numbersProperty->type.name, sh::core::reflection::GetTypeName<std::vector<int>>());
6062

6163
auto begin = numbersProperty->Begin(&derived);
6264
auto end = numbersProperty->End(&derived);
@@ -94,6 +96,24 @@ TEST(ReflectionTest, PropertyTest)
9496
auto arrIterator = prop->Begin(&derived);
9597
EXPECT_FALSE(arrIterator.IsConst());
9698
}
99+
// map 요소 변경 테스트
100+
{
101+
derived.map.insert({ "test0", 0 });
102+
derived.map.insert({ "test1", 1 });
103+
auto prop = derived.GetType().GetProperty("map");
104+
EXPECT_TRUE(prop->isContainer);
105+
for (auto it = prop->Begin(&derived); it != prop->End(&derived); ++it)
106+
{
107+
EXPECT_TRUE(it.IsPair());
108+
EXPECT_TRUE(it.GetPairType()->first.isConst);
109+
EXPECT_TRUE(it.GetPairType()->first == sh::core::reflection::GetType<std::string>());
110+
EXPECT_TRUE(it.GetPairType()->second == sh::core::reflection::GetType<int>());
111+
auto pair = it.Get<std::pair<const std::string, int>>();
112+
pair->second++;
113+
}
114+
EXPECT_EQ(derived.map["test0"], 1);
115+
EXPECT_EQ(derived.map["test1"], 2);
116+
}
97117
}
98118

99119
TEST(ReflectionTest, SafePropertyTest)

UserCode/Save.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "Save.h"
2+
#include "Game/Input.h"
3+
#include "Game/GameObject.h"
4+
5+
#include <fstream>
6+
7+
using namespace sh::game;
8+
9+
Save::Save(sh::game::GameObject& owner) :
10+
Component(owner)
11+
{
12+
}
13+
14+
void Save::Update()
15+
{
16+
if (Input::GetKeyDown(Input::KeyCode::LCtrl) && Input::GetKeyDown(Input::KeyCode::S))
17+
{
18+
std::ofstream file{ "test.json" };
19+
file << gameObject.Serialize();
20+
}
21+
if (Input::GetKeyDown(Input::KeyCode::LCtrl) && Input::GetKeyDown(Input::KeyCode::O))
22+
{
23+
std::ifstream file{ "test.json" };
24+
sh::core::Json json{};
25+
file >> json;
26+
gameObject.Deserialize(json);
27+
}
28+
}

UserCode/Save.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
#include "Export.h"
3+
#include "Game/Component/Component.h"
4+
5+
class Save : public sh::game::Component
6+
{
7+
COMPONENT(Save)
8+
public:
9+
SH_USER_API Save(sh::game::GameObject& owner);
10+
SH_USER_API void Update() override;
11+
};

UserCode/main.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
#include "Export.h"
2-
3-
#include "ComponentTest.h"
4-
#include "RotateObject.h"
5-
62
#include "Core/Logger.h"
7-
83
#include "Game/ComponentModule.h"
94

105
extern "C"
@@ -15,6 +10,6 @@ extern "C"
1510
}
1611
SH_USER_API auto GetModule() -> sh::game::ComponentModule*
1712
{
18-
return ComponentModule::GetInstance();
13+
return sh::game::ComponentModule::GetInstance();
1914
}
2015
}

include/Core/FileLoader.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ namespace sh::core
1111
class FileLoader
1212
{
1313
public:
14-
SH_CORE_API virtual ~FileLoader();
15-
16-
SH_CORE_API auto LoadBinary(std::string_view dir)->std::optional<std::vector<unsigned char>>;
17-
SH_CORE_API auto LoadText(std::string_view dir) -> std::optional<std::string>;
14+
SH_CORE_API static auto LoadBinary(std::string_view dir) -> std::optional<std::vector<unsigned char>>;
15+
SH_CORE_API static auto LoadText(std::string_view dir) -> std::optional<std::string>;
1816
};
1917
}

include/Core/FileSystem.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
#include "Export.h"
3+
4+
#include <string>
5+
#include <filesystem>
6+
namespace sh::core
7+
{
8+
class FileSystem
9+
{
10+
public:
11+
SH_CORE_API static auto GetDesktopDirectory() -> std::string;
12+
SH_CORE_API static auto GetHomeDirectory() -> std::string;
13+
/// @brief 해당 경로에 폴더를 만드는 함수. 이미 존재한다면 뒤에 숫자를 붙인다.
14+
/// @param path 경로
15+
/// @param name 폴더 이름
16+
SH_CORE_API static void CreateFolder(const std::filesystem::path& path, std::string_view folderName);
17+
/// @brief 해당 경로에 같은 이름의 파일이 존재 할 시 이름에 숫자를 붙여 반환하는 함수
18+
/// @param path 경로
19+
/// @param fileName 파일 이름
20+
/// @return 새 파일 이름
21+
SH_CORE_API static auto CreateUniqueFileName(const std::filesystem::path& path, const std::filesystem::path& fileName) -> std::string;
22+
};
23+
}//namespace

include/Core/GarbageCollection.h

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace sh::core
2020
{
2121
friend Singleton<GarbageCollection>;
2222
private:
23-
SHashSet<SObject*, 128> objs;
23+
SHashMap<std::string, SObject*>& objs;
2424
SHashSet<SObject*, 128> rootSets;
2525

2626
uint32_t elapseTime = 0;
@@ -43,10 +43,6 @@ namespace sh::core
4343
public:
4444
SH_CORE_API ~GarbageCollection();
4545

46-
/// @brief GC 목록에 추가하는 함수.
47-
/// @param obj SObject 포인터
48-
/// @return
49-
SH_CORE_API void AddObject(SObject* obj);
5046
/// @brief 루트셋으로 지정하는 함수. 루트셋 객체는 참조하고 있는 객체가 없어도 메모리에서 유지된다.
5147
/// @param obj 루트셋으로 지정할 SObject 포인터
5248
SH_CORE_API void SetRootSet(SObject* obj);
@@ -56,11 +52,6 @@ namespace sh::core
5652
/// @return
5753
SH_CORE_API void RemoveRootSet(SObject* obj);
5854

59-
/// @brief GC 목록에서 제거하는 함수.
60-
/// @param obj SObject 포인터
61-
/// @return 성공하면 true, 아니면 false
62-
SH_CORE_API auto RemoveObject(SObject* obj) -> bool;
63-
6455
/// @brief GC를 갱신하여 쓰레기 수집 시작
6556
SH_CORE_API void Update();
6657

include/Core/ISerializable.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#pragma once
2+
3+
#include "nlohmann/json.hpp"
4+
5+
namespace sh::core
6+
{
7+
using Json = nlohmann::json;
8+
9+
class ISerializable
10+
{
11+
public:
12+
virtual ~ISerializable() = default;
13+
virtual auto Serialize() const -> Json = 0;
14+
virtual void Deserialize(const Json& json) = 0;
15+
};
16+
17+
template<typename T>
18+
inline void SerializeProperty(core::Json& json, const std::string& key, const T& value)
19+
{
20+
json[key] = value;
21+
}
22+
template<typename T>
23+
inline void DeserializeProperty(const core::Json& json, const std::string& key, T& value)
24+
{
25+
if (json.contains(key))
26+
value = json.at(key).get<T>();
27+
}
28+
}

0 commit comments

Comments
 (0)