Adds serialization base classes

Adds file writing to BinaryFileBuffer
master
Joey Pollack 3 years ago
parent 5ada9d5e1c
commit 0160e7c623

@ -8,10 +8,10 @@ Build System:
Core: Core:
☐ Figure out how to represent Unique Entities and entity instances - and how this will work with UUIDs @critical ☐ Figure out how to represent Unique Entities and entity instances - and how this will work with UUIDs @critical
☐ Implement generic serializeation system ✔ Implement generic serialization system @done(22-06-29 18:44)
☐ JSON serializeable base class ✔ JSON serializable base class @done(22-06-29 17:41)
JSON implementions should be stubbed out in non-editor builds JSON implementions should be stubbed out in non-editor builds @done(22-06-29 17:41)
☐ Binary serializeable base class ✔ Binary serializable base class @done(22-06-29 18:44)
✔ Wrap NFD in an API in the platform module @low @done(22-05-31 15:44) ✔ Wrap NFD in an API in the platform module @low @done(22-05-31 15:44)
Wrapper added to utils - not platform Wrapper added to utils - not platform
✔ Add custom (64 bit?) UUID generator (based on Chreno's UUIDs) @done(22-06-27 13:34) ✔ Add custom (64 bit?) UUID generator (based on Chreno's UUIDs) @done(22-06-27 13:34)
@ -76,6 +76,9 @@ Core:
Enitity: Enitity:
✔ Single UUID @done(22-06-01 14:01) ✔ Single UUID @done(22-06-01 14:01)
✔ Functionality for adding/working with components (through EnTT) @done(22-06-01 14:01) ✔ Functionality for adding/working with components (through EnTT) @done(22-06-01 14:01)
☐ Serialize
☐ JSON
☐ Binary
Components: Components:
✔ Tag @done(22-06-23 15:49) ✔ Tag @done(22-06-23 15:49)
@ -90,6 +93,9 @@ Core:
World (Lunariums version of a "Scene"): World (Lunariums version of a "Scene"):
☐ Implement the world without Regions first ☐ Implement the world without Regions first
☐ Serialize world
☐ JSON
☐ Binary
Implement Regions: Implement Regions:
☐ Track/manage active regions ☐ Track/manage active regions
@ -145,7 +151,7 @@ Utils:
Assets: Assets:
✔ Internal Asset Manager @high @done (1/25/2022, 3:58:20 PM) ✔ Internal Asset Manager @high @done (1/25/2022, 3:58:20 PM)
☐ Document Index.Dat and the AssetIndex class ☐ Document Index.Dat and the AssetIndex class
Move the GenerateFont method from internal_font.h into data_manager.h Move the GenerateFont method from internal_font.h into data_manager.h @done(22-06-29 17:42)
Types: Types:
- Classes that represent each resource Types - Classes that represent each resource Types
@ -158,7 +164,7 @@ Assets:
Loaders: Loaders:
- Need class (or classes?) to load resources from the packed format that the pipeline generates - Need class (or classes?) to load resources from the packed format that the pipeline generates
Come up with binary file formats for each type: Come up with binary file formats for each type:
☐ .xml (This will probably be multiple different formats depending on what the .xml file is describing) ☐ .json (This will probably be multiple different formats depending on what the .json file is describing)
☐ Image ☐ Image
☐ Script ☐ Script
☐ Audio ☐ Audio

@ -42,6 +42,7 @@ Editor:
World View: World View:
World Hierarchy (Tree View): World Hierarchy (Tree View):
☐ Handle showing Enities with children @high
Asset Viewer: Asset Viewer:
✔ Get references to the EditorAsset objects instead of the raw file locations @done(22-06-01 18:48) ✔ Get references to the EditorAsset objects instead of the raw file locations @done(22-06-01 18:48)

@ -0,0 +1,26 @@
/******************************************************************************
* File - binary_serializable.h
* Author - Joey Pollack
* Date - 2022/06/29 (y/m/d)
* Mod Date - 2022/06/29 (y/m/d)
* Description - base class for any object that can be serialized to binary
******************************************************************************/
#ifndef LUNARIUM_BINARY_SERIALIZABLE_H_
#define LUNARIUM_BINARY_SERIALIZABLE_H_
#include <utils/op_res.h>
namespace lunarium
{
class BinaryFileBuffer;
class BinarySerializable
{
public:
[[nodiscard]] OpRes Serialize(BinaryFileBuffer* pBuffer);
[[nodiscard]] OpRes Deserialize(BinaryFileBuffer* pBuffer);
};
}
#endif // LUNARIUM_BINARY_SERIALIZABLE_H_

@ -0,0 +1,28 @@
/******************************************************************************
* File - json_serializable.h
* Author - Joey Pollack
* Date - 2022/06/29 (y/m/d)
* Mod Date - 2022/06/29 (y/m/d)
* Description - Base class for any json serializable object
******************************************************************************/
#ifndef LUNARIUM_JSON_SERIALIZABLE_H_
#define LUNARIUM_JSON_SERIALIZABLE_H_
#include <utils/op_res.h>
#include <nlohmann/json.hpp>
namespace lunarium
{
class JSONSerializable
{
public:
[[nodiscard]] virtual OpRes Serialize(nlohmann::json& node) = 0;
[[nodiscard]] virtual OpRes Deserialize(nlohmann::json& node) = 0;
[[nodiscard]] virtual nlohmann::json AsJSON() = 0;
[[nodiscord]] virtual bool IsValidNode(nlohmann::json& node) = 0;
};
}
#endif // LUNARIUM_JSON_SERIALIZABLE_H_

@ -7,6 +7,7 @@
******************************************************************************/ ******************************************************************************/
#include "world.h" #include "world.h"
#include <LunariumConfig.h>
#include <world/world.h> #include <world/world.h>
@ -33,18 +34,24 @@ namespace lunarium { namespace editor
return OpRes::OK(); return OpRes::OK();
} }
OpRes World::LoadFromJSON(nlohmann::json& node) OpRes World::Deserialize(nlohmann::json& node)
{ {
// TODO: Implement World::LoadFromJSON // TODO: Implement World::LoadFromJSON
// Create the lunarium::World Object here // Create the lunarium::World Object here
// Replace the one created in the constructor // Replace the one created in the constructor
#if !BUILD_NO_EDITOR // Only does this when this is an editor build
#endif
return OpRes::OK(); return OpRes::OK();
} }
OpRes World::SaveToJSON(nlohmann::json& node) OpRes World::Serialize(nlohmann::json& node)
{ {
// TODO: Implement World::SaveToJSON // TODO: Implement World::SaveToJSON
// Store the entities UUID - the Entity class will serialize itself // Store the entities UUID - the Entity class will serialize itself
#if !BUILD_NO_EDITOR // Only does this when this is an editor build
#endif
return OpRes::OK(); return OpRes::OK();
} }
@ -54,4 +61,15 @@ namespace lunarium { namespace editor
return true; return true;
} }
nlohmann::json World::AsJSON()
{
#if !BUILD_NO_EDITOR // Only does this when this is an editor build
nlohmann::json node;
return node;
#endif
return nlohmann::json();
}
}} }}

@ -133,7 +133,7 @@ namespace lunarium { namespace editor
pAsset->mLocation = std::filesystem::path(asset["Location"].get<std::string>()); pAsset->mLocation = std::filesystem::path(asset["Location"].get<std::string>());
// Load type specific data // Load type specific data
if (Failed(pAsset->LoadFromJSON(asset).LogIfFailed(Editor::LogCat).LogIfFailed(Editor::LogCat))) if (Failed(pAsset->Deserialize(asset).LogIfFailed(Editor::LogCat).LogIfFailed(Editor::LogCat)))
{ {
return OpRes::Fail("Could not load asset type specific data for asset with ID: %llu, File: %s", return OpRes::Fail("Could not load asset type specific data for asset with ID: %llu, File: %s",
pAsset->GetID(), pAsset->GetFileLocation().filename().string().c_str()); pAsset->GetID(), pAsset->GetFileLocation().filename().string().c_str());
@ -184,7 +184,7 @@ namespace lunarium { namespace editor
// TODO: This needs to be a relative path! (Relative to the project root) // TODO: This needs to be a relative path! (Relative to the project root)
asset["Location"] = pAsset->GetFileLocation().string().c_str(); asset["Location"] = pAsset->GetFileLocation().string().c_str();
if (Failed(pAsset->SaveToJSON(asset).LogIfFailed(Editor::LogCat).LogIfFailed(Editor::LogCat))) if (Failed(pAsset->Serialize(asset).LogIfFailed(Editor::LogCat).LogIfFailed(Editor::LogCat)))
{ {
return OpRes::Fail("Could not save asset meta data for file: %s", pAsset->GetFileLocation().string().c_str()); return OpRes::Fail("Could not save asset meta data for file: %s", pAsset->GetFileLocation().string().c_str());
} }

@ -11,14 +11,15 @@
#include "definitions.h" #include "definitions.h"
#include "content_manager.h" #include "content_manager.h"
#include <utils/op_res.h>
#include <assets/serializing/json_serializable.h>
#include <filesystem> #include <filesystem>
#include <string> #include <string>
#include <utils/op_res.h>
namespace lunarium { namespace editor namespace lunarium { namespace editor
{ {
class EditorAsset class EditorAsset : public JSONSerializable
{ {
public: public:
EditorAsset(AssetType type); EditorAsset(AssetType type);
@ -29,8 +30,10 @@ namespace lunarium { namespace editor
bool GetIsTrashed() const; bool GetIsTrashed() const;
[[nodiscard]] virtual OpRes LoadRawFile() = 0; [[nodiscard]] virtual OpRes LoadRawFile() = 0;
[[nodiscard]] virtual OpRes LoadFromJSON(nlohmann::json& node) = 0;
[[nodiscard]] virtual OpRes SaveToJSON(nlohmann::json& node) = 0;
// [[nodiscard]] virtual OpRes LoadFromJSON(nlohmann::json& node) = 0;
//[[nodiscard]] virtual OpRes SaveToJSON(nlohmann::json& node) = 0;
private: private:
friend class ContentManager; friend class ContentManager;
@ -43,7 +46,7 @@ namespace lunarium { namespace editor
protected: protected:
std::filesystem::path mAssetDir; std::filesystem::path mAssetDir;
[[nodiscord]] virtual bool IsValidNode(nlohmann::json& node) = 0; // [[nodiscord]] virtual bool IsValidNode(nlohmann::json& node) = 0;
private: // DISABLE COPY private: // DISABLE COPY
EditorAsset(const EditorAsset&) = delete; EditorAsset(const EditorAsset&) = delete;

@ -37,8 +37,10 @@ namespace lunarium { namespace editor
return OpRes::OK(); return OpRes::OK();
} }
OpRes TileSet::LoadFromJSON(nlohmann::json& node) OpRes TileSet::Deserialize(nlohmann::json& node)
{ {
#if !BUILD_NO_EDITOR // Only does this when this is an editor build
// Load Image // Load Image
mSetImage = FileLoaders::LoadImage(mAssetDir / GetFileLocation()); mSetImage = FileLoaders::LoadImage(mAssetDir / GetFileLocation());
if (!mSetImage) if (!mSetImage)
@ -57,20 +59,40 @@ namespace lunarium { namespace editor
mNumTiles.Width = node["NumTilesCol"].get<int>(); mNumTiles.Width = node["NumTilesCol"].get<int>();
mNumTiles.Height = node["NumTilesRow"].get<int>(); mNumTiles.Height = node["NumTilesRow"].get<int>();
#endif
return OpRes::OK(); return OpRes::OK();
} }
OpRes TileSet::SaveToJSON(nlohmann::json& node) OpRes TileSet::Serialize(nlohmann::json& node)
{ {
#if !BUILD_NO_EDITOR // Only does this when this is an editor build
node["TileSetID"] = mTileSetID; node["TileSetID"] = mTileSetID;
node["TileSizeWidth"] = mTileSize.Width; node["TileSizeWidth"] = mTileSize.Width;
node["TileSizeHeight"] = mTileSize.Height; node["TileSizeHeight"] = mTileSize.Height;
node["NumTilesCol"] = mNumTiles.Width; node["NumTilesCol"] = mNumTiles.Width;
node["NumTilesRow"] = mNumTiles.Height; node["NumTilesRow"] = mNumTiles.Height;
#endif
return OpRes::OK(); return OpRes::OK();
} }
nlohmann::json TileSet::AsJSON()
{
nlohmann::json node;
#if !BUILD_NO_EDITOR // Only does this when this is an editor build
node["TileSetID"] = mTileSetID;
node["TileSizeWidth"] = mTileSize.Width;
node["TileSizeHeight"] = mTileSize.Height;
node["NumTilesCol"] = mNumTiles.Width;
node["NumTilesRow"] = mNumTiles.Height;
#endif
return node;
}
bool TileSet::IsValidNode(nlohmann::json& node) bool TileSet::IsValidNode(nlohmann::json& node)
{ {
if (node["TileSetID"].is_null()) { return false; } if (node["TileSetID"].is_null()) { return false; }

@ -24,8 +24,10 @@ namespace lunarium { namespace editor
// Load the raw asset file from the internal location // Load the raw asset file from the internal location
OpRes LoadRawFile(); OpRes LoadRawFile();
OpRes LoadFromJSON(nlohmann::json& node); OpRes Serialize(nlohmann::json& node);
OpRes SaveToJSON(nlohmann::json& node); OpRes Deserialize(nlohmann::json& node);
bool IsValidNode(nlohmann::json& node);
nlohmann::json AsJSON();
void SetTileSetID(int id); void SetTileSetID(int id);
int GetTileSetID() const; int GetTileSetID() const;
@ -47,7 +49,6 @@ namespace lunarium { namespace editor
private: private:
[[nodiscord]] virtual bool IsValidNode(nlohmann::json& node);
}; };
}} }}

@ -28,8 +28,10 @@ namespace lunarium { namespace editor
~World(); ~World();
[[nodiscard]] virtual OpRes LoadRawFile(); [[nodiscard]] virtual OpRes LoadRawFile();
[[nodiscard]] virtual OpRes LoadFromJSON(nlohmann::json& node); [[nodiscard]] virtual OpRes Serialize(nlohmann::json& node);
[[nodiscard]] virtual OpRes SaveToJSON(nlohmann::json& node); [[nodiscard]] virtual OpRes Deserialize(nlohmann::json& node);
[[nodiscord]] virtual bool IsValidNode(nlohmann::json& node);
[[nodiscard]] virtual nlohmann::json AsJSON();
lunarium::World* GetWorld(); lunarium::World* GetWorld();
@ -38,7 +40,6 @@ namespace lunarium { namespace editor
private: private:
[[nodiscord]] virtual bool IsValidNode(nlohmann::json& node);
private: // DISABLED private: // DISABLED

@ -15,7 +15,7 @@
namespace lunarium namespace lunarium
{ {
BinaryFileBuffer::BinaryFileBuffer() BinaryFileBuffer::BinaryFileBuffer()
: mbIsLoaded(false), mpData(nullptr), mFileSize(0), mReadPos(0), mFileName("") : mbIsLoaded(false), mpBuffer(nullptr), mFileSize(0), mBufferPos(0), mFileName("")
{ {
} }
@ -24,6 +24,43 @@ namespace lunarium
Unload(); Unload();
} }
bool BinaryFileBuffer::NewFile(int reserve_size)
{
if (mbIsLoaded)
{
Unload();
}
mpBuffer = new unsigned char[reserve_size];
mFileSize = reserve_size;
mbIsLoaded = true;
return true;
}
bool BinaryFileBuffer::WriteFile(const char* filename, bool include_extra_bytes)
{
std::ofstream ofs(filename, std::ios_base::binary | std::ios_base::trunc);
if (!ofs.is_open())
{
return false;
}
// Only writing up to the buffer pos because the rest will be garbage data
int write_size = mBufferPos;
if (include_extra_bytes)
{
// Unless the user says otherwise
write_size = mFileSize;
}
ofs.write((const char*)mpBuffer, write_size);
ofs.close();
ofs.clear();
mFileName = filename;
return true;
}
bool BinaryFileBuffer::LoadFile(const char * filename) bool BinaryFileBuffer::LoadFile(const char * filename)
{ {
if (mbIsLoaded) if (mbIsLoaded)
@ -43,9 +80,9 @@ namespace lunarium
ifs.seekg(0, std::ios_base::beg); ifs.seekg(0, std::ios_base::beg);
mFileSize = end - start; mFileSize = end - start;
mpData = new unsigned char[mFileSize]; mpBuffer = new unsigned char[mFileSize];
ifs.read((char*)mpData, mFileSize); ifs.read((char*)mpBuffer, mFileSize);
ifs.close(); ifs.close();
ifs.clear(); ifs.clear();
@ -60,12 +97,12 @@ namespace lunarium
if (!mbIsLoaded) if (!mbIsLoaded)
return; return;
delete[] mpData; delete[] mpBuffer;
mpData = nullptr; mpBuffer = nullptr;
mFileSize = 0; mFileSize = 0;
mFileName = ""; mFileName = "";
mReadPos = 0; mBufferPos = 0;
mbIsLoaded = false; mbIsLoaded = false;
} }
@ -86,29 +123,130 @@ namespace lunarium
const unsigned char* BinaryFileBuffer::GetBuffer() const const unsigned char* BinaryFileBuffer::GetBuffer() const
{ {
return mpData; return mpBuffer;
} }
/////////////////////////////////////////////////////////////////////
// READ METHODS
/////////////////////////////////////////////////////////////////////
bool BinaryFileBuffer::Read(char * buffer, int numBytes) bool BinaryFileBuffer::Read(char * buffer, int numBytes)
{ {
if (!mbIsLoaded || mReadPos >= mFileSize) if (!mbIsLoaded || mBufferPos >= mFileSize)
return false; return false;
memcpy(buffer, &mpData[mReadPos], numBytes); memcpy(buffer, &mpBuffer[mBufferPos], numBytes);
mReadPos += numBytes; mBufferPos += numBytes;
return true; return true;
} }
int BinaryFileBuffer::ReadInt()
{
int value = 0;
Read((char*)&value, sizeof(int));
return value;
}
short BinaryFileBuffer::ReadShort()
{
short value = 0;
Read((char*)&value, sizeof(short));
return value;
}
char BinaryFileBuffer::ReadByte()
{
char value = 0;
Read((char*)&value, sizeof(char));
return value;
}
unsigned int BinaryFileBuffer::ReadUInt()
{
unsigned int value = 0;
Read((char*)&value, sizeof(unsigned int));
return value;
}
unsigned short BinaryFileBuffer::ReadUShort()
{
unsigned short value = 0;
Read((char*)&value, sizeof(unsigned short));
return value;
}
unsigned char BinaryFileBuffer::ReadUByte()
{
unsigned char value = 0;
Read((char*)&value, sizeof(unsigned char));
return value;
}
/////////////////////////////////////////////////////////////////////
// WRITE METHODS
/////////////////////////////////////////////////////////////////////
bool BinaryFileBuffer::Write(char* buffer, int num_bytes)
{
if (!mbIsLoaded)
{
return false;
}
if (mBufferPos + num_bytes >= mFileSize)
{
// Reserve more space
int new_size = mFileSize * 2 + num_bytes; // adding num_bytes to make sure the write will fit
unsigned char* new_buffer = new unsigned char[new_size];
memcpy(new_buffer, mpBuffer, mFileSize);
delete[] mpBuffer;
mpBuffer = new_buffer;
mFileSize = new_size;
}
memcpy(&mpBuffer[mBufferPos], buffer, num_bytes);
mBufferPos += num_bytes;
return true;
}
void BinaryFileBuffer::WriteInt(int value)
{
Write((char*)&value, sizeof(int));
}
void BinaryFileBuffer::WriteShort(short value)
{
Write((char*)&value, sizeof(short));
}
void BinaryFileBuffer::WriteByte(char value)
{
Write((char*)&value, sizeof(char));
}
void BinaryFileBuffer::WriteUInt(unsigned int value)
{
Write((char*)&value, sizeof(unsigned int));
}
void BinaryFileBuffer::WriteUShort(unsigned short value)
{
Write((char*)&value, sizeof(unsigned short));
}
void BinaryFileBuffer::WriteUByte(unsigned char value)
{
Write((char*)&value, sizeof(unsigned char));
}
void BinaryFileBuffer::SeekTo(int pos) void BinaryFileBuffer::SeekTo(int pos)
{ {
mReadPos = pos; mBufferPos = pos;
if (mReadPos < 0) if (mBufferPos < 0)
mReadPos = 0; mBufferPos = 0;
if (mReadPos >= mFileSize) if (mBufferPos >= mFileSize)
mReadPos = mFileSize - 1; mBufferPos = mFileSize - 1;
} }
} }

@ -21,6 +21,10 @@ namespace lunarium
BinaryFileBuffer(); BinaryFileBuffer();
~BinaryFileBuffer(); ~BinaryFileBuffer();
/// Create a new file buffer of the given starting size
/// This will clear out any existing buffer
bool NewFile(int reserve_size);
bool WriteFile(const char* filename, bool include_extra_bytes = false);
bool LoadFile(const char* filename); bool LoadFile(const char* filename);
void Unload(); void Unload();
bool IsLoaded() const; bool IsLoaded() const;
@ -29,6 +33,21 @@ namespace lunarium
const unsigned char* GetBuffer() const; const unsigned char* GetBuffer() const;
bool Read(char* buffer, int numBytes); bool Read(char* buffer, int numBytes);
int ReadInt();
short ReadShort();
char ReadByte();
unsigned int ReadUInt();
unsigned short ReadUShort();
unsigned char ReadUByte();
bool Write(char* buffer, int num_bytes);
void WriteInt(int value);
void WriteShort(short value);
void WriteByte(char value);
void WriteUInt(unsigned int value);
void WriteUShort(unsigned short value);
void WriteUByte(unsigned char value);
void SeekTo(int pos); void SeekTo(int pos);
private: private:
@ -36,8 +55,8 @@ namespace lunarium
bool mbIsLoaded; bool mbIsLoaded;
std::string mFileName; std::string mFileName;
int mFileSize; int mFileSize;
unsigned char* mpData; unsigned char* mpBuffer;
int mReadPos; int mBufferPos;
}; };
} }

@ -13,13 +13,10 @@
#include <utils/logger.h> #include <utils/logger.h>
#include <entt/entt.hpp> #include <entt/entt.hpp>
#include <world/world.h> #include <world/world.h>
#include <assets/serializing/json_serializable.h>
namespace nlohmann
{
class json;
}
namespace lunarium namespace lunarium // TODO: : public JSONSerializable
{ {
class Entity class Entity
{ {

Loading…
Cancel
Save