Skip to content

Commit

Permalink
docs(engine): cleanup and document assets.json
Browse files Browse the repository at this point in the history
  • Loading branch information
RiscadoA committed Sep 10, 2023
1 parent 37ddc12 commit 0c1c436
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 36 deletions.
1 change: 1 addition & 0 deletions docs/pages/3_examples/2_engine/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ multiple plugins of the engine:

- @subpage examples-engine-renderer - @copybrief examples-engine-renderer
- @subpage examples-engine-assets-bridge - @copybrief examples-engine-assets-bridge
- @subpage examples-engine-assets-json - @copybrief examples-engine-assets-json
74 changes: 38 additions & 36 deletions engine/samples/assets/json/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,79 +25,80 @@ using cubos::core::ecs::Write;
using cubos::core::memory::Stream;
using namespace cubos::engine;

/// [Asset type]
/// A simple serializable type which we will be saving and loading.
struct MyAsset
{
int an_integer;
std::vector<std::string> some_strings;
int anInteger;
std::vector<std::string> someStrings;
};
/// [Asset type]

// We must implement the cubos::core::data::serialize function for our type, so that it can be
// serialized by the JSONBridge.
/// [Serialization definition]
template <>
void cubos::core::data::serialize<MyAsset>(Serializer& ser, const MyAsset& obj, const char* name)
{
ser.beginObject(name);
ser.write(obj.an_integer, "an_integer");
ser.write(obj.some_strings, "some_strings");
ser.write(obj.anInteger, "anInteger");
ser.write(obj.someStrings, "someStrings");
ser.endObject();
}

// We must also implement the cubos::core::data::deserialize function for our type, so that it can
// be deserialized by the JSONBridge.
template <>
void cubos::core::data::deserialize<MyAsset>(Deserializer& des, MyAsset& obj)
{
des.beginObject();
des.read(obj.an_integer);
des.read(obj.some_strings);
des.read(obj.anInteger);
des.read(obj.someStrings);
des.endObject();
}
/// [Serialization definition]

static void config(Write<Settings> settings)
/// [Setting]
static void configSystem(Write<Settings> settings)
{
settings->setString("assets.io.path", SAMPLE_ASSETS_FOLDER);

// If we want to save assets, we must set this to false.
settings->setBool("assets.io.readOnly", false);
/// [Setting]

settings->setString("assets.io.path", SAMPLE_ASSETS_FOLDER);
}

static void bridge(Write<Assets> assets)
/// [Register bridge]
static void bridgeSystem(Write<Assets> assets)
{
// Add the a JSONBridge for the .my extension.
assets->registerBridge(".my", std::make_unique<JSONBridge<MyAsset>>());
}
/// [Register bridge]

static void save_and_load(Write<Assets> assets)
/// [Create a new asset]
static void saveAndLoadSystem(Write<Assets> assets)
{
// Create a new asset (with a random UUID).
auto handle = assets->create(MyAsset{
.an_integer = 42,
.some_strings = {"Hello", "World"},
.anInteger = 42,
.someStrings = {"Hello", "World"},
});
/// [Create a new asset]

// Set a path for the asset - necessary for the JSONBridge to know where to save the asset.
// It is important to set the correct extension, so that the asset manager knows which bridge
// to use.
/// [Save the asset]
assets->writeMeta(handle)->set("path", "/assets/sample/asset.my");

// Save the asset.
assets->save(handle);
/// [Save the asset]

// After making the handle weak, the asset won't have any more strong references.
handle.makeWeak();

// By calling cleanup, we can remove the asset from memory, forcing it to be reloaded from disk
// the next time it is accessed.
assets->cleanup();
/// [Force reload]
assets->invalidate(handle);
/// [Force reload]

/// [Read the asset]
// Access the asset - will be loaded automatically.
auto read = assets->read(handle);
Stream::stdOut.printf("Integer: {}\n", read->an_integer);
for (const auto& str : read->some_strings)
Stream::stdOut.printf("Integer: {}\n", read->anInteger);
for (const auto& str : read->someStrings)
{
Stream::stdOut.printf("String: {}\n", str);
}
/// [Read the asset]

// Wait for input before exiting.
Stream::stdOut.print("You can now check the contents of the file!\nPress enter to exit...");
Expand All @@ -107,13 +108,14 @@ static void save_and_load(Write<Assets> assets)
FileSystem::destroy("/assets/sample");
}

/// [Run]
int main()
{
auto cubos = Cubos();
Cubos cubos{};
cubos.addPlugin(assetsPlugin);
cubos.startupSystem(config).tagged("cubos.settings");
cubos.startupSystem(bridge).tagged("cubos.assets.bridge");
cubos.startupSystem(save_and_load).tagged("cubos.assets");
cubos.startupSystem(configSystem).tagged("cubos.settings");
cubos.startupSystem(bridgeSystem).tagged("cubos.assets.bridge");
cubos.startupSystem(saveAndLoadSystem).tagged("cubos.assets");
cubos.run();
return 0;
}
/// [Run]
56 changes: 56 additions & 0 deletions engine/samples/assets/json/page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Loading and Saving JSON Assets {#examples-engine-assets-json}

@brief Loading and saving serializable assets from and to JSON.

This example demonstrates how you can load and save assets of a serializable
type from and to JSON files.

Before we go any further, if we want to save assets to the filesystem, we must
allow assets to be modified. This is done through the following setting:

@snippet assets/json/main.cpp Setting

We'll use the following type as an example:

@snippet assets/json/main.cpp Asset type

We can make it serializable by implementing the following specializations:

@snippet assets/json/main.cpp Serialization definition

Then, we must register a bridge for this type. Since we want to load and save
the data as JSON, we'll use @ref cubos::engine::JSONBridge "JSONBridge".

@snippet assets/json/main.cpp Register bridge

First, we'll create an asset of this type:

@snippet assets/json/main.cpp Create a new asset

Then, we'll assign it a path and save it. Its important that the path ends with
the correct extension, so that @ref cubos::engine::Assets "Assets" knows which
bridge to use when loading it.

@snippet assets/json/main.cpp Save the asset

With this, the files `sample/asset.my` and `sample/asset.my.meta` should have
appeared on the `assets/` directory. The `.meta` file contains the UUID of the
asset, which is used by the engine to identify it.

To test whether the asset can be loaded correctly from the saved data, we'll
force it to be reloaded, using @ref cubos::engine::Assets::invalidate
"Assets::invalidate".

@snippet assets/json/main.cpp Force reload

Now, when we try reading the asset data again, it will be loaded from the
previously saved file.

@snippet assets/json/main.cpp Read the asset

Finally, the engine is configured the following way:

@snippet assets/json/main.cpp Run

Try running the sample yourself to see the loaded data!

0 comments on commit 0c1c436

Please sign in to comment.