Reset
This commit is contained in:
@ -1,200 +0,0 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "assert/assert.hpp"
|
||||
#include "AssetDataLoader.hpp"
|
||||
#include "util/Math.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
ssize_t assetDataLoaderArchiveRead(
|
||||
struct archive *archive,
|
||||
void *d,
|
||||
const void **buffer
|
||||
) {
|
||||
assertNotNull(archive, "Archive is NULL!");
|
||||
assertNotNull(d, "Data is NULL!");
|
||||
assertNotNull(buffer, "Buffer is NULL!");
|
||||
AssetDataLoader *loader = (AssetDataLoader*)d;
|
||||
|
||||
*buffer = loader->buffer;
|
||||
size_t read = fread(
|
||||
loader->buffer, 1, ASSET_LOADER_BUFFER_SIZE, loader->assetArchiveFile
|
||||
);
|
||||
if(ferror(loader->assetArchiveFile)) return ARCHIVE_FATAL;
|
||||
return read;
|
||||
}
|
||||
|
||||
int64_t assetDataLoaderArchiveSeek(
|
||||
struct archive *archive,
|
||||
void *d,
|
||||
int64_t offset,
|
||||
int32_t whence
|
||||
) {
|
||||
assertNotNull(archive, "Archive is NULL!");
|
||||
assertNotNull(d, "Data is NULL!");
|
||||
assertTrue(offset > 0, "Offset must be greater than 0!");
|
||||
AssetDataLoader *loader = (AssetDataLoader*)d;
|
||||
int32_t ret = fseek(loader->assetArchiveFile, offset, whence);
|
||||
assertTrue(ret == 0, "Failed to seek!");
|
||||
return ftell(loader->assetArchiveFile);
|
||||
}
|
||||
|
||||
int32_t assetDataLoaderArchiveOpen(struct archive *a, void *d) {
|
||||
assertNotNull(a, "Archive is NULL!");
|
||||
assertNotNull(d, "Data is NULL!");
|
||||
AssetDataLoader *loader = (AssetDataLoader*)d;
|
||||
|
||||
int32_t ret = fseek(loader->assetArchiveFile, 0, SEEK_SET);
|
||||
assertTrue(ret == 0, "Failed to seek to start of file!");
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
int32_t assetDataLoaderArchiveClose(struct archive *a, void *d) {
|
||||
assertNotNull(a, "Archive is NULL!");
|
||||
assertNotNull(d, "Data is NULL!");
|
||||
return assetDataLoaderArchiveOpen(a, d);
|
||||
}
|
||||
|
||||
// // // // // // // // // // // // // // // // // // // // // // // // // // //
|
||||
|
||||
AssetDataLoader::AssetDataLoader(std::string fileName) : fileName(fileName) {
|
||||
assertTrue(
|
||||
fileName.size() > 0,
|
||||
"IAssetDataLoader::IAssetDataLoader: fileName must be greater than 0"
|
||||
);
|
||||
}
|
||||
|
||||
void AssetDataLoader::open() {
|
||||
assertNull(this->assetArchiveFile, "AssetDataLoader::open: File is already open");
|
||||
assertNull(this->assetArchive, "AssetDataLoader::open: Archive is already open");
|
||||
assertNull(this->assetArchiveEntry, "AssetDataLoader::open: Entry is already open");
|
||||
|
||||
this->assetArchiveFile = this->openAssetArchiveFile();
|
||||
assertNotNull(this->assetArchiveFile, "AssetDataLoader::open: Failed to open archive file!");
|
||||
|
||||
// Open archive reader
|
||||
assetArchive = archive_read_new();
|
||||
assertNotNull(assetArchive, "AssetDataLoader::open: Failed to create archive reader");
|
||||
|
||||
// Set up the reader
|
||||
archive_read_support_format_tar(assetArchive);
|
||||
|
||||
// Open reader
|
||||
archive_read_set_open_callback(assetArchive, &assetDataLoaderArchiveOpen);
|
||||
archive_read_set_read_callback(assetArchive, &assetDataLoaderArchiveRead);
|
||||
archive_read_set_seek_callback(assetArchive, &assetDataLoaderArchiveSeek);
|
||||
archive_read_set_close_callback(assetArchive, &assetDataLoaderArchiveClose);
|
||||
archive_read_set_callback_data(assetArchive, this);
|
||||
|
||||
int32_t ret = archive_read_open1(assetArchive);
|
||||
assertTrue(ret == ARCHIVE_OK, "AssetDataLoader::open: Failed to open archive!");
|
||||
position = 0;
|
||||
|
||||
// Iterate over each file to find the one for this asset loader.
|
||||
while(archive_read_next_header(assetArchive, &assetArchiveEntry) == ARCHIVE_OK) {
|
||||
const char_t *headerFile = (char_t*)archive_entry_pathname(assetArchiveEntry);
|
||||
if(std::string(headerFile) == this->fileName) return;
|
||||
int32_t ret = archive_read_data_skip(assetArchive);
|
||||
assertTrue(ret == ARCHIVE_OK, "AssetDataLoader::open: Failed to skip data!");
|
||||
}
|
||||
|
||||
assertUnreachable("AssetDataLoader::open: Failed to find file!");
|
||||
}
|
||||
|
||||
int32_t AssetDataLoader::close() {
|
||||
assertNotNull(this->assetArchiveFile, "AssetDataLoader::close: File is NULL");
|
||||
assertNotNull(this->assetArchive, "AssetDataLoader::close: Archive is NULL!");
|
||||
assertNotNull(this->assetArchiveEntry, "AssetDataLoader::close: Entry is NULL!");
|
||||
|
||||
// Close the archive
|
||||
int32_t ret = archive_read_free(this->assetArchive);
|
||||
assertTrue(ret == ARCHIVE_OK, "AssetDataLoader::close: Failed to close archive!");
|
||||
|
||||
this->assetArchive = nullptr;
|
||||
this->assetArchiveEntry = nullptr;
|
||||
|
||||
// Close the file
|
||||
int32_t res = fclose(this->assetArchiveFile);
|
||||
this->assetArchiveFile = nullptr;
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t AssetDataLoader::read(uint8_t *buffer, size_t size) {
|
||||
assertNotNull(buffer, "Buffer is NULL!");
|
||||
assertTrue(size > 0, "Size must be greater than 0!");
|
||||
assertNotNull(this->assetArchive, "assetRead: Archive is NULL!");
|
||||
assertNotNull(this->assetArchiveEntry, "assetRead: Entry is NULL!");
|
||||
|
||||
ssize_t read = archive_read_data(this->assetArchive, buffer, size);
|
||||
this->position += read;
|
||||
|
||||
if(read == ARCHIVE_FATAL) {
|
||||
assertUnreachable(archive_error_string(this->assetArchive));
|
||||
}
|
||||
|
||||
assertTrue(read != ARCHIVE_RETRY, "assetRead: Failed to read data (RETRY)!");
|
||||
assertTrue(read != ARCHIVE_WARN, "assetRead: Failed to read data (WARN)!");
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
size_t AssetDataLoader::readUntil(
|
||||
uint8_t *buffer,
|
||||
const size_t maxSize,
|
||||
const char_t delimiter
|
||||
) {
|
||||
size_t totalRead = this->read(buffer, maxSize);
|
||||
size_t i = 0;
|
||||
while(i < totalRead) {
|
||||
if(buffer[i] == delimiter) break;
|
||||
i++;
|
||||
}
|
||||
buffer[i++] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
size_t AssetDataLoader::getSize() {
|
||||
assertTrue(this->assetArchiveEntry != nullptr, "AssetDataLoader::getSize: Entry is NULL!");
|
||||
assertTrue(archive_entry_size_is_set(assetArchiveEntry), "assetGetSize: Entry size is not set!");
|
||||
return archive_entry_size(assetArchiveEntry);
|
||||
}
|
||||
|
||||
size_t AssetDataLoader::skip(size_t n) {
|
||||
assertTrue(n >= 0, "AssetDataLoader::skip: Byte count must be greater than 0.");
|
||||
|
||||
uint8_t dumpBuffer[ASSET_LOADER_BUFFER_SIZE];
|
||||
size_t skipped = 0;
|
||||
size_t n2, n3;
|
||||
while(n != 0) {
|
||||
n2 = Math::min<size_t>(n, ASSET_LOADER_BUFFER_SIZE);
|
||||
n3 = this->read(dumpBuffer, n2);
|
||||
assertTrue(n3 == n2, "AssetDataLoader::skip: Failed to skip bytes!");
|
||||
n -= n3;
|
||||
}
|
||||
|
||||
return skipped;
|
||||
}
|
||||
|
||||
size_t AssetDataLoader::setPosition(const size_t position) {
|
||||
assertTrue(position >= 0, "Position must be greater than or equal to 0");
|
||||
this->rewind();
|
||||
return this->skip(position);
|
||||
}
|
||||
|
||||
void AssetDataLoader::rewind() {
|
||||
// TODO: See if I can optimize this
|
||||
this->close();
|
||||
this->open();
|
||||
}
|
||||
|
||||
size_t AssetDataLoader::getPosition() {
|
||||
assertNotNull(this->assetArchiveFile, "AssetDataLoader::getPosition: File is not open!");
|
||||
return this->position;
|
||||
}
|
||||
|
||||
AssetDataLoader::~AssetDataLoader() {
|
||||
if(this->assetArchiveFile != nullptr) this->close();
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
}
|
||||
|
||||
#define ASSET_LOADER_BUFFER_SIZE 32768
|
||||
|
||||
/**
|
||||
* Method invoked by the libarchive internals to read bytes from the archive
|
||||
* file pointer.
|
||||
*
|
||||
* @param archive Archive requesting the read.
|
||||
* @param data Data pointer passed to the archive.
|
||||
* @param buffer Pointer to where the buffer pointer should be stored.
|
||||
* @return Count of bytes read.
|
||||
*/
|
||||
ssize_t assetDataLoaderArchiveRead(
|
||||
struct archive *archive,
|
||||
void *data,
|
||||
const void **buffer
|
||||
);
|
||||
|
||||
/**
|
||||
* Method invoked by the libarchive internals to seek the archive file pointer.
|
||||
*
|
||||
* @param archive Archive requesting the seek.
|
||||
* @param data Data pointer passed to the archive.
|
||||
* @param offset Offset to seek to.
|
||||
* @param whence Whence to seek from.
|
||||
* @return The new offset.
|
||||
*/
|
||||
int64_t assetDataLoaderArchiveSeek(
|
||||
struct archive *archive,
|
||||
void *data,
|
||||
int64_t offset,
|
||||
int32_t whence
|
||||
);
|
||||
|
||||
/**
|
||||
* Method invoked by the libarchive internals to open the archive file pointer.
|
||||
*
|
||||
* @param archive Archive requesting the open.
|
||||
* @param data Data pointer passed to the archive.
|
||||
* @return 0 if success, otherwise for failure.
|
||||
*/
|
||||
int32_t assetDataLoaderArchiveOpen(struct archive *a, void *data);
|
||||
|
||||
/**
|
||||
* Method invoked by the libarchive internals to close the archive file pointer.
|
||||
*
|
||||
* @param archive Archive requesting the close.
|
||||
* @param data Data pointer passed to the archive.
|
||||
* @return 0 if success, otherwise for failure.
|
||||
*/
|
||||
int32_t assetDataLoaderArchiveClose(struct archive *a, void *data);
|
||||
|
||||
namespace Dawn {
|
||||
class AssetDataLoader {
|
||||
protected:
|
||||
struct archive *assetArchive = nullptr;
|
||||
struct archive_entry *assetArchiveEntry = nullptr;
|
||||
size_t position;
|
||||
std::string fileName;
|
||||
|
||||
public:
|
||||
uint8_t buffer[ASSET_LOADER_BUFFER_SIZE];
|
||||
FILE *assetArchiveFile = nullptr;
|
||||
|
||||
/**
|
||||
* Unimplemented method intended to be implemented by the platform that
|
||||
* will be used to request a File pointer to the asset.
|
||||
*
|
||||
* @return Pointer to the opened asset archive.
|
||||
*/
|
||||
FILE * openAssetArchiveFile();
|
||||
|
||||
/**
|
||||
* Create a new asset loader. Asset Loaders can be used to load data from
|
||||
* a file in a myriad of ways.
|
||||
*
|
||||
* @param fileName File name of the asset that is to be loaded.
|
||||
*/
|
||||
AssetDataLoader(std::string filename);
|
||||
|
||||
/**
|
||||
* Platform-centric method to open a file buffer to an asset.
|
||||
*/
|
||||
void open();
|
||||
|
||||
/**
|
||||
* Closes the previously ppened asset.
|
||||
* @return 0 if successful, otherwise false.
|
||||
*/
|
||||
int32_t close();
|
||||
|
||||
/**
|
||||
* Read bytes from buffer.
|
||||
* @param buffer Pointer to a ubyte array to buffer data into.
|
||||
* @param size Length of the data buffer (How many bytes to read).
|
||||
* @return The count of bytes read.
|
||||
*/
|
||||
size_t read(uint8_t *buffer, size_t size);
|
||||
|
||||
/**
|
||||
* Reads bytes from the buffer until a given delimiter is found. Returned
|
||||
* position will be the index of the delimiter within the buffer.
|
||||
*
|
||||
* @param buffer Buffer to read into.
|
||||
* @param maxSize Maximum size of the buffer.
|
||||
* @param delimiter Delimiter to read until.
|
||||
* @return The count of bytes read (including null terminator)
|
||||
*/
|
||||
size_t readUntil(
|
||||
uint8_t *buffer,
|
||||
const size_t maxSize,
|
||||
const char_t delimiter
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the size of the asset.
|
||||
* @return The size of the asset in bytes.
|
||||
*/
|
||||
size_t getSize();
|
||||
|
||||
/**
|
||||
* Skips the read head forward to a given position.
|
||||
*
|
||||
* @param n Count of bytes to progress the read head by.
|
||||
* @return Count of bytes progressed.
|
||||
*/
|
||||
size_t skip(size_t n);
|
||||
|
||||
/**
|
||||
* Rewind the read head to the beginning of the file.
|
||||
*/
|
||||
void rewind();
|
||||
|
||||
/**
|
||||
* Sets the absolute position of the read head within the buffer of the
|
||||
* file.
|
||||
*
|
||||
* @param absolutePosition Absolute position to set the read head to.
|
||||
*/
|
||||
size_t setPosition(const size_t absolutePosition);
|
||||
|
||||
/**
|
||||
* Returns the current position of the read head.
|
||||
*
|
||||
* @return The current read head position.
|
||||
*/
|
||||
size_t getPosition();
|
||||
|
||||
/**
|
||||
* Cleanup the asset loader.
|
||||
*/
|
||||
virtual ~AssetDataLoader();
|
||||
};
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
// Copyright (c) 2022 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "AssetLoader.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
AssetLoader::AssetLoader(const std::string name) : name(name) {
|
||||
assertTrue(name.size() > 0, "Asset::Asset: Name cannot be empty");
|
||||
}
|
||||
|
||||
AssetLoader::~AssetLoader() {
|
||||
this->loaded = false;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// Copyright (c) 2022 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class AssetLoader {
|
||||
public:
|
||||
const std::string name;
|
||||
bool_t loaded = false;
|
||||
|
||||
/**
|
||||
* Create an abstract Asset object.
|
||||
*
|
||||
* @param name Name of the asset.
|
||||
*/
|
||||
AssetLoader(const std::string name);
|
||||
|
||||
/**
|
||||
* Virtual function that will be called by the asset manager on a
|
||||
* synchronous basis. This will only trigger if the blocks are false and
|
||||
* the loaded is also false.
|
||||
*/
|
||||
virtual void updateSync() = 0;
|
||||
|
||||
/**
|
||||
* Virtual function called by the asset manager asynchronously every tick.
|
||||
* This will only trigger if blocks are false and the loaded state is also
|
||||
* false.
|
||||
*/
|
||||
virtual void updateAsync() = 0;
|
||||
|
||||
/**
|
||||
* Dispose the asset item.
|
||||
*/
|
||||
virtual ~AssetLoader();
|
||||
};
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
// Copyright (c) 2022 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "AssetManager.hpp"
|
||||
#include "loaders/TextureLoader.hpp"
|
||||
#include "loaders/TrueTypeLoader.hpp"
|
||||
#include "loaders/JSONLoader.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void AssetManager::init() {
|
||||
|
||||
}
|
||||
|
||||
void AssetManager::update() {
|
||||
auto itPending = pendingAssetLoaders.begin();
|
||||
while(itPending != pendingAssetLoaders.end()) {
|
||||
auto loader = *itPending;
|
||||
loader->updateSync();
|
||||
loader->updateAsync();
|
||||
if(loader->loaded) {
|
||||
finishedAssetLoaders.push_back(loader);
|
||||
itPending = pendingAssetLoaders.erase(itPending);
|
||||
} else {
|
||||
itPending++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssetManager::removeExisting(const std::string filename) {
|
||||
auto existing = std::find_if(
|
||||
pendingAssetLoaders.begin(), pendingAssetLoaders.end(),
|
||||
[&](auto &loader) {
|
||||
return loader->name == filename;
|
||||
}
|
||||
);
|
||||
if(existing != pendingAssetLoaders.end()) {
|
||||
pendingAssetLoaders.erase(existing);
|
||||
}
|
||||
|
||||
existing = std::find_if(
|
||||
finishedAssetLoaders.begin(), finishedAssetLoaders.end(),
|
||||
[&](auto &loader) {
|
||||
return loader->name == filename;
|
||||
}
|
||||
);
|
||||
if(existing != finishedAssetLoaders.end()) {
|
||||
finishedAssetLoaders.erase(existing);
|
||||
}
|
||||
}
|
||||
|
||||
bool_t AssetManager::isEverythingLoaded() {
|
||||
return pendingAssetLoaders.size() == 0;
|
||||
}
|
||||
|
||||
bool_t AssetManager::isLoaded(const std::string filename) {
|
||||
auto existing = this->getExisting<AssetLoader>(filename);
|
||||
if(existing) return existing->loaded;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::shared_ptr<TrueTypeTexture> AssetManager::get<TrueTypeTexture>(
|
||||
const std::string filename,
|
||||
const uint32_t fontSize
|
||||
) {
|
||||
auto existing = this->getExisting<TrueTypeLoader>(filename);
|
||||
if(existing) {
|
||||
// Check pointer hasn't gone stale, if it has remove it and create new.
|
||||
auto texture = existing->getTexture(fontSize);
|
||||
if(texture) return texture;
|
||||
this->removeExisting(filename);
|
||||
}
|
||||
|
||||
std::shared_ptr<TrueTypeLoader> loader = std::make_shared<TrueTypeLoader>(
|
||||
filename
|
||||
);
|
||||
pendingAssetLoaders.push_back(std::static_pointer_cast<AssetLoader>(loader));
|
||||
return loader->getTexture(fontSize);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::shared_ptr<json> AssetManager::get<json>(
|
||||
const std::string filename
|
||||
) {
|
||||
auto existing = this->getExisting<JSONLoader>(filename);
|
||||
if(existing) return existing->data;
|
||||
|
||||
std::shared_ptr<JSONLoader> loader = std::make_shared<JSONLoader>(
|
||||
filename
|
||||
);
|
||||
pendingAssetLoaders.push_back(std::static_pointer_cast<AssetLoader>(loader));
|
||||
return loader->data;
|
||||
}
|
||||
|
||||
|
||||
AssetManager::~AssetManager() {
|
||||
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
// Copyright (c) 2022 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
#include "asset/AssetLoader.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class AssetManager final {
|
||||
private:
|
||||
std::vector<std::shared_ptr<AssetLoader>> pendingAssetLoaders;
|
||||
std::vector<std::shared_ptr<AssetLoader>> finishedAssetLoaders;
|
||||
|
||||
/**
|
||||
* Returns an existing asset loader if it exists.
|
||||
*
|
||||
* @param filename The filename of the asset to get.
|
||||
* @return The asset loader if it exists, otherwise nullptr.
|
||||
*/
|
||||
template<class T>
|
||||
std::shared_ptr<T> getExisting(const std::string filename) {
|
||||
auto existing = std::find_if(
|
||||
pendingAssetLoaders.begin(), pendingAssetLoaders.end(),
|
||||
[&](auto &loader) {
|
||||
return loader->name == filename;
|
||||
}
|
||||
);
|
||||
|
||||
if(existing == pendingAssetLoaders.end()) {
|
||||
existing = std::find_if(
|
||||
finishedAssetLoaders.begin(), finishedAssetLoaders.end(),
|
||||
[&](auto &loader) {
|
||||
return loader->name == filename;
|
||||
}
|
||||
);
|
||||
|
||||
if(existing == finishedAssetLoaders.end()) return nullptr;
|
||||
}
|
||||
|
||||
return std::static_pointer_cast<T>(*existing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing asset loader if it exists.
|
||||
*
|
||||
* @param filename The filename of the asset to remove.
|
||||
*/
|
||||
void removeExisting(const std::string filename);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initializes this asset manager so it can begin accepting assets.
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Updates the asset manager.
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* Returns whether the asset manager has loaded all of the currently
|
||||
* managed assets.
|
||||
*
|
||||
* @return True if all assets have been loaded.
|
||||
*/
|
||||
bool_t isEverythingLoaded();
|
||||
|
||||
/**
|
||||
* Returns whether the asset manager has loaded the given asset.
|
||||
*
|
||||
* @param filename The filename of the asset to check.
|
||||
* @return True if the asset has been loaded.
|
||||
*/
|
||||
bool_t isLoaded(const std::string filename);
|
||||
|
||||
/**
|
||||
* Returns the asset loader for the given asset.
|
||||
*
|
||||
* @param filename The filename of the asset to get.
|
||||
* @param fontSize The font size to get the truetype asset of.
|
||||
* @return The asset loader for the given asset.
|
||||
*/
|
||||
template<class T>
|
||||
std::shared_ptr<T> get(const std::string filename);
|
||||
|
||||
/**
|
||||
* Returns the asset loader for the given asset.
|
||||
*
|
||||
* @param filename The filename of the asset to get.
|
||||
* @param fontSize The font size to get the truetype asset of.
|
||||
* @return The asset loader for the given asset.
|
||||
*/
|
||||
template<class T>
|
||||
std::shared_ptr<T> get(
|
||||
const std::string filename,
|
||||
const uint32_t fontSize
|
||||
);
|
||||
|
||||
/**
|
||||
* Dispose the asset manager, and all attached assets.
|
||||
*/
|
||||
~AssetManager();
|
||||
};
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
# Copyright (c) 2022 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DAWN_TARGET_NAME}
|
||||
PRIVATE
|
||||
AssetLoader.cpp
|
||||
AssetDataLoader.cpp
|
||||
AssetManager.cpp
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(loaders)
|
@ -1,12 +0,0 @@
|
||||
# Copyright (c) 2022 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DAWN_TARGET_NAME}
|
||||
PRIVATE
|
||||
TextureLoader.cpp
|
||||
TrueTypeLoader.cpp
|
||||
JSONLoader.cpp
|
||||
)
|
@ -1,46 +0,0 @@
|
||||
// Copyright (c) 2024 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "JSONLoader.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
JSONLoader::JSONLoader(const std::string name) :
|
||||
AssetLoader(name),
|
||||
loader(name + ".json"),
|
||||
state(JSONLoaderLoadState::INITIAL)
|
||||
{
|
||||
data = std::make_shared<json>();
|
||||
}
|
||||
|
||||
void JSONLoader::updateAsync() {
|
||||
if(this->state != JSONLoaderLoadState::INITIAL) return;
|
||||
this->state = JSONLoaderLoadState::LOADING_FILE;
|
||||
|
||||
this->loader.open();
|
||||
auto size = this->loader.getSize();
|
||||
|
||||
auto buffer = new uint8_t[size + 1];
|
||||
assertNotNull(buffer, "Failed to allocate buffer!");
|
||||
|
||||
this->state = JSONLoaderLoadState::PARSING_DATA;
|
||||
auto read = this->loader.read(buffer, size);
|
||||
assertTrue(read == size, "Failed to read entire file!");
|
||||
buffer[size] = '\0';
|
||||
|
||||
*data = json::parse(buffer);
|
||||
delete[] buffer;
|
||||
|
||||
this->state = JSONLoaderLoadState::DONE;
|
||||
this->loaded = true;
|
||||
}
|
||||
|
||||
void JSONLoader::updateSync() {
|
||||
}
|
||||
|
||||
JSONLoader::~JSONLoader() {
|
||||
this->data = nullptr;
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
// Copyright (c) 2024 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "asset/AssetLoader.hpp"
|
||||
#include "asset/AssetDataLoader.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
enum class JSONLoaderLoadState {
|
||||
INITIAL,
|
||||
LOADING_FILE,
|
||||
PARSING_DATA,
|
||||
DONE
|
||||
};
|
||||
|
||||
class JSONLoader : public AssetLoader {
|
||||
protected:
|
||||
AssetDataLoader loader;
|
||||
enum JSONLoaderLoadState state;
|
||||
|
||||
public:
|
||||
std::shared_ptr<json> data;
|
||||
|
||||
/**
|
||||
* Constructs a JSON asset loader. You should instead use the parent
|
||||
* asset managers' abstracted load method
|
||||
*
|
||||
* @param name File name asset to load, omitting the extension.
|
||||
*/
|
||||
JSONLoader(const std::string name);
|
||||
|
||||
void updateSync() override;
|
||||
void updateAsync() override;
|
||||
|
||||
/**
|
||||
* Dispose / Cleanup the JSON asset.
|
||||
*/
|
||||
~JSONLoader();
|
||||
};
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
// Copyright (c) 2022 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "TextureLoader.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
TextureLoader::TextureLoader(const std::string name) :
|
||||
AssetLoader(name),
|
||||
loader(name + ".texture"),
|
||||
state(TextureLoaderLoadState::INITIAL)
|
||||
{
|
||||
sharedTexture = std::make_shared<Texture>();
|
||||
weakTexture = sharedTexture;
|
||||
}
|
||||
|
||||
void TextureLoader::updateAsync() {
|
||||
if(this->state != TextureLoaderLoadState::INITIAL) return;
|
||||
this->state = TextureLoaderLoadState::ASYNC_LOADING;
|
||||
this->loader.open();
|
||||
|
||||
// Read in the header.
|
||||
uint8_t buffer[TEXTURE_LOADER_HEADER_SIZE];
|
||||
size_t pos = 0;
|
||||
|
||||
// Read Version
|
||||
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
||||
std::string version = std::string((char*)buffer);
|
||||
assertTrue(version == "DT_2.00", "Invalid Texture Version!");
|
||||
|
||||
// Read Texture Width
|
||||
this->loader.setPosition(pos);
|
||||
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
||||
width = std::stoi(std::string((char*)buffer));
|
||||
assertTrue(width > 0, "Invalid Texture Width!");
|
||||
|
||||
// Read Texture Height
|
||||
this->loader.setPosition(pos);
|
||||
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
||||
height = std::stoi(std::string((char*)buffer));
|
||||
assertTrue(height > 0, "Invalid Texture Height!");
|
||||
|
||||
// Texture Format (RGBA, RGB, etc)
|
||||
this->loader.setPosition(pos);
|
||||
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
||||
int32_t iFormat = std::stoi(std::string((char*)buffer));
|
||||
switch(iFormat) {
|
||||
case 1: format = TextureFormat::R; break;
|
||||
case 2: format = TextureFormat::RG; break;
|
||||
case 3: format = TextureFormat::RGB; break;
|
||||
case 4: format = TextureFormat::RGBA; break;
|
||||
default: assertUnreachable("Invalid Texture Format %i!", iFormat);
|
||||
}
|
||||
|
||||
// Wrap X
|
||||
this->loader.setPosition(pos);
|
||||
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
||||
int32_t iWrapX = std::stoi(std::string((char*)buffer));
|
||||
switch(iWrapX) {
|
||||
case 0: wrapX = TextureWrapMode::REPEAT; break;
|
||||
case 1: wrapX = TextureWrapMode::MIRRORED_REPEAT; break;
|
||||
case 2: wrapX = TextureWrapMode::CLAMP_TO_EDGE; break;
|
||||
case 3: wrapX = TextureWrapMode::CLAMP_TO_BORDER; break;
|
||||
default: assertUnreachable("Invalid Texture Wrap X %i!", iWrapX);
|
||||
}
|
||||
|
||||
// Wrap Y
|
||||
this->loader.setPosition(pos);
|
||||
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
||||
int32_t iWrapY = std::stoi(std::string((char*)buffer));
|
||||
switch(iWrapY) {
|
||||
case 0: wrapY = TextureWrapMode::REPEAT; break;
|
||||
case 1: wrapY = TextureWrapMode::MIRRORED_REPEAT; break;
|
||||
case 2: wrapY = TextureWrapMode::CLAMP_TO_EDGE; break;
|
||||
case 3: wrapY = TextureWrapMode::CLAMP_TO_BORDER; break;
|
||||
default: assertUnreachable("Invalid Texture Wrap Y %i!", iWrapY);
|
||||
}
|
||||
|
||||
// Filter Min
|
||||
this->loader.setPosition(pos);
|
||||
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
||||
int32_t iFilterMin = std::stoi(std::string((char*)buffer));
|
||||
switch(iFilterMin) {
|
||||
case 0: filterMin = TextureFilterMode::NEAREST; break;
|
||||
case 1: filterMin = TextureFilterMode::LINEAR; break;
|
||||
default: assertUnreachable("Invalid Texture Filter Min %i!", iFilterMin);
|
||||
}
|
||||
|
||||
// Filter Mag
|
||||
this->loader.setPosition(pos);
|
||||
pos += this->loader.readUntil(buffer, TEXTURE_LOADER_HEADER_SIZE, '|');
|
||||
int32_t iFilterMag = std::stoi(std::string((char*)buffer));
|
||||
switch(iFilterMag) {
|
||||
case 0: filterMag = TextureFilterMode::NEAREST; break;
|
||||
case 1: filterMag = TextureFilterMode::LINEAR; break;
|
||||
default: assertUnreachable("Invalid Texture Filter Mag %i!", iFilterMag);
|
||||
}
|
||||
|
||||
// Data begins here. This part is done synchronously directly to the GPU.
|
||||
this->loader.setPosition(pos);
|
||||
size_t bufferSize = width * height * iFormat;
|
||||
data = new uint8_t[bufferSize];
|
||||
assertNotNull(data, "Failed to allocate texture data!");
|
||||
this->loader.read(data, bufferSize);
|
||||
|
||||
// Handoff to sync to buffer to GPU.
|
||||
this->state = TextureLoaderLoadState::ASYNC_DONE;
|
||||
}
|
||||
|
||||
void TextureLoader::updateSync() {
|
||||
if(this->state != TextureLoaderLoadState::ASYNC_DONE) return;
|
||||
this->state = TextureLoaderLoadState::SYNC_LOADING;
|
||||
|
||||
assertNotNull(this->sharedTexture, "Texture is null!");
|
||||
assertNotNull(this->data, "Texture data is null!");
|
||||
|
||||
// Setup Texture
|
||||
this->sharedTexture->setSize(
|
||||
this->width,
|
||||
this->height,
|
||||
this->format,
|
||||
TextureDataFormat::UNSIGNED_BYTE
|
||||
);
|
||||
this->sharedTexture->buffer(this->data);
|
||||
|
||||
// Free data buffer
|
||||
delete[] this->data;
|
||||
this->data = nullptr;
|
||||
|
||||
// Leat go of the held pointer
|
||||
this->sharedTexture = nullptr;
|
||||
|
||||
// Hand off and call done
|
||||
this->state = TextureLoaderLoadState::SYNC_DONE;
|
||||
this->loaded = true;
|
||||
}
|
||||
|
||||
TextureLoader::~TextureLoader() {
|
||||
if(this->data != nullptr) {
|
||||
delete[] this->data;
|
||||
this->data = nullptr;
|
||||
}
|
||||
this->sharedTexture = nullptr;
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2022 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "asset/AssetLoader.hpp"
|
||||
#include "asset/AssetDataLoader.hpp"
|
||||
#include "display/Texture.hpp"
|
||||
|
||||
#define TEXTURE_LOADER_HEADER_SIZE 256
|
||||
|
||||
namespace Dawn {
|
||||
enum class TextureLoaderLoadState {
|
||||
INITIAL,
|
||||
ASYNC_LOADING,
|
||||
ASYNC_DONE,
|
||||
SYNC_LOADING,
|
||||
SYNC_DONE
|
||||
};
|
||||
|
||||
class TextureLoader : public AssetLoader {
|
||||
protected:
|
||||
AssetDataLoader loader;
|
||||
enum TextureLoaderLoadState state;
|
||||
uint8_t *data = nullptr;
|
||||
int32_t width = -1, height = -1;
|
||||
enum TextureFormat format;
|
||||
enum TextureWrapMode wrapX;
|
||||
enum TextureWrapMode wrapY;
|
||||
enum TextureFilterMode filterMin;
|
||||
enum TextureFilterMode filterMag;
|
||||
|
||||
public:
|
||||
std::shared_ptr<Texture> sharedTexture;
|
||||
std::weak_ptr<Texture> weakTexture;
|
||||
|
||||
/**
|
||||
* Constructs a texture asset loader. You should instead use the parent
|
||||
* asset managers' abstracted load method
|
||||
*
|
||||
* @param name File name asset to load, omitting the extension.
|
||||
*/
|
||||
TextureLoader(const std::string name);
|
||||
|
||||
void updateSync() override;
|
||||
void updateAsync() override;
|
||||
|
||||
/**
|
||||
* Dispose / Cleanup the texture asset. Will also dispose the underlying
|
||||
* texture itself.
|
||||
*/
|
||||
~TextureLoader();
|
||||
};
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "TrueTypeLoader.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
TrueTypeLoader::TrueTypeLoader(const std::string name) :
|
||||
AssetLoader(name),
|
||||
loader(name + ".ttf")
|
||||
{
|
||||
// Init the font.
|
||||
auto ret = FT_Init_FreeType(&fontLibrary);
|
||||
assertTrue(ret == 0, "Failed to initialize FreeType library.");
|
||||
}
|
||||
|
||||
void TrueTypeLoader::updateSync() {
|
||||
if(state != TrueTypeLoaderState::ASYNC_DONE) return;
|
||||
state = TrueTypeLoaderState::SYNC_LOADING;
|
||||
|
||||
// Init all the textures.
|
||||
auto it = textures.begin();
|
||||
while(it != textures.end()) {
|
||||
auto texture = it->second.lock();
|
||||
|
||||
if(texture) {
|
||||
texture->setFace(face);
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
it = textures.erase(it);
|
||||
}
|
||||
|
||||
// Done
|
||||
state = TrueTypeLoaderState::SYNC_DONE;
|
||||
this->loaded = true;
|
||||
}
|
||||
|
||||
void TrueTypeLoader::updateAsync() {
|
||||
if(state != TrueTypeLoaderState::INITIAL) return;
|
||||
state = TrueTypeLoaderState::ASYNC_LOADING;
|
||||
|
||||
// Load the data.
|
||||
this->loader.open();
|
||||
size_t size = loader.getSize();
|
||||
buffer = new uint8_t[size];
|
||||
|
||||
// Read the data.
|
||||
size_t readSize = loader.read(buffer, size);
|
||||
assertTrue(readSize == size, "Failed to read all data from TrueTypeLoader.");
|
||||
|
||||
// Init the font.
|
||||
auto ret = FT_New_Memory_Face(fontLibrary, buffer, size, 0, &face);
|
||||
assertTrue(ret == 0, "Failed to load font face.");
|
||||
|
||||
// Now close the asset loader
|
||||
loader.close();
|
||||
state = TrueTypeLoaderState::ASYNC_DONE;
|
||||
}
|
||||
|
||||
std::shared_ptr<TrueTypeTexture> TrueTypeLoader::getTexture(
|
||||
const uint32_t fontSize
|
||||
) {
|
||||
// Check if we have the texture already and it hasn't gone stale.
|
||||
auto it = textures.find(fontSize);
|
||||
if(it != textures.end()) {
|
||||
if(!it->second.expired()) return it->second.lock();
|
||||
textures.erase(it);
|
||||
}
|
||||
|
||||
// Create the texture.
|
||||
auto texture = std::make_shared<TrueTypeTexture>(fontSize);
|
||||
textures[fontSize] = texture;
|
||||
if(this->loaded) texture->setFace(face);
|
||||
return texture;
|
||||
}
|
||||
|
||||
TrueTypeLoader::~TrueTypeLoader() {
|
||||
if(
|
||||
this->state == TrueTypeLoaderState::SYNC_DONE ||
|
||||
this->state == TrueTypeLoaderState::SYNC_LOADING ||
|
||||
this->state == TrueTypeLoaderState::ASYNC_DONE
|
||||
) {
|
||||
FT_Done_Face(face);
|
||||
}
|
||||
|
||||
FT_Done_FreeType(fontLibrary);
|
||||
|
||||
if(buffer != nullptr) {
|
||||
delete[] buffer;
|
||||
buffer = nullptr;
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "asset/AssetLoader.hpp"
|
||||
#include "asset/AssetDataLoader.hpp"
|
||||
#include "display/font/TrueTypeTexture.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
enum class TrueTypeLoaderState {
|
||||
INITIAL,
|
||||
ASYNC_LOADING,
|
||||
ASYNC_DONE,
|
||||
SYNC_LOADING,
|
||||
SYNC_DONE
|
||||
};
|
||||
|
||||
class TrueTypeLoader : public AssetLoader {
|
||||
protected:
|
||||
FT_Library fontLibrary;
|
||||
FT_Face face;
|
||||
AssetDataLoader loader;
|
||||
std::unordered_map<uint32_t, std::weak_ptr<TrueTypeTexture>> textures;
|
||||
enum TrueTypeLoaderState state = TrueTypeLoaderState::INITIAL;
|
||||
uint8_t *buffer = nullptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructs a TrueTypeLoader. You should instead use the parent
|
||||
* asset managers' abstracted load method
|
||||
*
|
||||
* @param name File name asset to load, omitting the extension.
|
||||
*/
|
||||
TrueTypeLoader(const std::string name);
|
||||
|
||||
void updateSync() override;
|
||||
void updateAsync() override;
|
||||
|
||||
/**
|
||||
* Returns the texture for the given font size.
|
||||
*
|
||||
* @param fontSize Font size to get the texture for.
|
||||
* @return Texture for the given character.
|
||||
*/
|
||||
std::shared_ptr<TrueTypeTexture> getTexture(
|
||||
const uint32_t fontSize
|
||||
);
|
||||
|
||||
/**
|
||||
* Dispose / Cleanup the truetype asset. Will also dispose the underlying
|
||||
* truetype itself.
|
||||
*/
|
||||
~TrueTypeLoader();
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user