diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e494012..420794a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,6 +118,21 @@ elseif(TARGET_TYPE STREQUAL game) locale_en ) + elseif(TARGET_GAME STREQUAL sandbox) + add_compile_definitions( + GAME_NAME="Sandbox" + GAME_FILE="sandbox/game.h" + GAME_TYPE=sandboxgame_t + GAME_INIT=sandboxGameInit + GAME_UPDATE=sandboxGameUpdate + GAME_DISPOSE=sandboxGameDispose + GAME_VERSION=1.0 + ) + tool_assets( + shader_textured + font_opensans + texture_test + ) endif() # Common Game Dependencies. diff --git a/src/file/assetmanager.c b/src/file/assetmanager.c new file mode 100644 index 00000000..64ad62da --- /dev/null +++ b/src/file/assetmanager.c @@ -0,0 +1,251 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assetmanager.h" + +assetmanagerloaderdefinition_t ASSET_MANAGER_LOADERS[] = { + { + &_assetManagerLoaderTextureAsync, + &_assetManagerLoaderTextureSync + }, + { + &_assetManagerLoaderFontAsync, + &_assetManagerLoaderFontSync + }, + { + &_assetManagerLoaderShaderAsync, + &_assetManagerLoaderShaderSync + } +}; + + +void assetManagerInit(assetmanager_t *manager) { + threadInit(&manager->thread, &_assetManagerThread); + manager->thread.user = manager; + manager->itemCount = 0; +} + +void assetManagerStart(assetmanager_t *manager) { + threadStart(&manager->thread); +} + +float assetManagerProgressGet(assetmanager_t *manager) { + float done; + uint8_t i; + + done = 0.0f; + + for(i = 0; i < manager->itemCount; i++) { + if(!assetManagerIsItemFinished(manager->items + i)) continue; + done++; + } + + return done / ((float) manager->itemCount); +} + +bool assetManagerIsItemFinished(assetmanageritem_t *item) { + // Sync done is always done + if(item->state == ASSET_MANAGER_STATE_SYNC_DONE) return true; + // Only check if ASYNC is done. + if(item->state != ASSET_MANAGER_STATE_ASYNC_DONE) return false; + // Does it need to still sync load? + if(ASSET_MANAGER_LOADERS[item->type].loadSync == NULL) return true; + return false; +} + + +// Thread Management +int32_t _assetManagerThread(thread_t *thread) { + // TODO: Can I allow multiple threads to run? + uint8_t i; + assetmanager_t *manager; + assetmanageritem_t *item; + assetmanagerloaderdefinition_t *definition; + bool result; + manager = thread->user; + + for(i = 0; i < manager->itemCount; i++) { + item = manager->items + i; + definition = ASSET_MANAGER_LOADERS + item->type; + + // Only bother with ASYNC items + if(definition->loadAsync == NULL) continue; + + // Are we already loading or already tried to load? + if(item->state != ASSET_MANAGER_STATE_PENDING) continue; + + // Begin loading + item->state = ASSET_MANAGER_STATE_ASYNC_LOADING; + result = definition->loadAsync(item); + + // Finish Loading + if(!result) { + item->state = ASSET_MANAGER_STATE_ASYNC_ERROR; + } else { + item->state = ASSET_MANAGER_STATE_ASYNC_DONE; + } + } + + return 0; +} + +void assetManagerUpdate(assetmanager_t *manager) { + uint8_t i; + assetmanageritem_t *item; + assetmanagerloaderdefinition_t *definition; + bool result; + + for(i = 0; i < manager->itemCount; i++) { + item = manager->items + i; + definition = ASSET_MANAGER_LOADERS + item->type; + + // If requires ASYNC loading, then confirm it has finished loading. + if(definition->loadAsync != NULL) { + if(item->state != ASSET_MANAGER_STATE_ASYNC_DONE) continue; + } else if(item->state != ASSET_MANAGER_STATE_PENDING) { + continue; + } else if(definition->loadSync == NULL) { + continue; + } + + // Begin sync loading + item->state = ASSET_MANAGER_STATE_SYNC_LOADING; + result = definition->loadSync(item); + + // Finish loading + if(!result) { + item->state = ASSET_MANAGER_STATE_SYNC_ERROR; + } else { + item->state = ASSET_MANAGER_STATE_SYNC_DONE; + } + } +} + +assetmanageritem_t * assetManagerItemAdd(assetmanager_t *manager) { + assetmanageritem_t *item = manager->items + manager->itemCount++; + item->state = ASSET_MANAGER_STATE_PENDING; + return item; +} + + +// Texture +assetmanageritem_t * assetManagerLoadTexture( + assetmanager_t *manager, texture_t *texture, char *fileName +) { + assetmanageritem_t *item = assetManagerItemAdd(manager); + + item->type = ASSET_MANAGER_TYPE_TEXTURE; + item->data.texture.fileName = fileName; + item->data.texture.texture = texture; + + return item; +} + +bool _assetManagerLoaderTextureAsync(assetmanageritem_t *item) { + assetbuffer_t *buffer; + int channels; + stbi_io_callbacks OPENGL_STBI_CALLBACKS; + + buffer = assetBufferOpen(item->data.texture.fileName); + if(buffer == NULL) return false; + + // Setup the interface for STBI + OPENGL_STBI_CALLBACKS.read = &assetBufferRead; + OPENGL_STBI_CALLBACKS.skip = &assetBufferSkip; + OPENGL_STBI_CALLBACKS.eof = &assetBufferEnd; + + // Buffer the image + channels = 0; + item->data.texture.data = (pixel_t *)stbi_load_from_callbacks( + &OPENGL_STBI_CALLBACKS, buffer, + &item->data.texture.width, &item->data.texture.height, + &channels, STBI_rgb_alpha + ); + + // Close the buffer + assetBufferClose(buffer); + if(item->data.texture.data == NULL) return false; + return true; +} + +bool _assetManagerLoaderTextureSync(assetmanageritem_t *item) { + // Turn into a texture. + textureInit( + item->data.texture.texture, + item->data.texture.width, + item->data.texture.height, + item->data.texture.data + ); + + // Cleanup + stbi_image_free(item->data.texture.data); + return true; +} + + +// Font +assetmanageritem_t * assetManagerLoadFont( + assetmanager_t *manager, font_t *font, char *fileName +) { + assetmanageritem_t *item = assetManagerItemAdd(manager); + + item->type = ASSET_MANAGER_TYPE_FONT; + item->data.font.fileName = fileName; + item->data.font.font = font; + + return item; +} + +bool _assetManagerLoaderFontAsync(assetmanageritem_t *item) { + item->data.font.data = assetStringLoad(item->data.font.fileName); + return item->data.font.data != NULL; +} + +bool _assetManagerLoaderFontSync(assetmanageritem_t *item) { + fontInit(item->data.font.font, item->data.font.data); + free(item->data.font.data); + return true; +} + + +// Shader +assetmanageritem_t * assetManagerShaderLoad( + assetmanager_t *manager, shader_t *shader, char *fileVert, char *fileFrag +) { + assetmanageritem_t *item = assetManagerItemAdd(manager); + + item->type = ASSET_MANAGER_TYPE_SHADER; + item->data.shader.shader = shader; + item->data.shader.fileVert = fileVert; + item->data.shader.fileFrag = fileFrag; + + return item; +} + +bool _assetManagerLoaderShaderAsync(assetmanageritem_t *item) { + item->data.shader.dataVert = assetStringLoad(item->data.shader.fileVert); + if(item->data.shader.dataVert == NULL) return false; + + item->data.shader.dataFrag = assetStringLoad(item->data.shader.fileFrag); + if(item->data.shader.dataFrag == NULL) { + free(item->data.shader.fileVert); + return false; + } + + return true; +} + +bool _assetManagerLoaderShaderSync(assetmanageritem_t *item) { + shaderInit( + item->data.shader.shader, + item->data.shader.dataVert, + item->data.shader.dataFrag + ); + free(item->data.shader.dataFrag); + free(item->data.shader.dataVert); + return true; +} \ No newline at end of file diff --git a/src/file/assetmanager.h b/src/file/assetmanager.h new file mode 100644 index 00000000..b409794c --- /dev/null +++ b/src/file/assetmanager.h @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "asset.h" +#include "../util/flags.h" +#include "../engine/thread.h" +#include "../display/shader.h" +#include "../display/texture.h" +#include "../display/font.h" +#include "../script/scripter.h" +#include "xml.h" + +#define ASSET_MANAGER_ITEMS_MAX 64 + +#define ASSET_MANAGER_STATE_PENDING 0x00 +#define ASSET_MANAGER_STATE_ASYNC_LOADING 0x01 +#define ASSET_MANAGER_STATE_ASYNC_ERROR 0x02 +#define ASSET_MANAGER_STATE_ASYNC_DONE 0x03 +#define ASSET_MANAGER_STATE_SYNC_LOADING 0x04 +#define ASSET_MANAGER_STATE_SYNC_ERROR 0x05 +#define ASSET_MANAGER_STATE_SYNC_DONE 0x06 + +#define ASSET_MANAGER_TYPE_TEXTURE 0x00 +#define ASSET_MANAGER_TYPE_FONT 0x01 +#define ASSET_MANAGER_TYPE_SHADER 0x02 + +// Types +typedef struct { + texture_t *texture; + char *fileName; + int32_t width, height; + pixel_t *data; +} assetmanagertexture_t; + +typedef struct { + shader_t *shader; + char *fileVert; + char *fileFrag; + char *dataVert; + char *dataFrag; +} assetmanagershader_t; + +typedef struct { + font_t *font; + char *fileName; + char *data; +} assetmanagerfont_t; + +// Item +typedef union { + assetmanagertexture_t texture; + assetmanagershader_t shader; + assetmanagerfont_t font; +} assetmanagerassetdata_t; + +typedef struct { + uint8_t type; + uint8_t state; + assetmanagerassetdata_t data; +} assetmanageritem_t; + +// Loader +typedef bool assetmanagerloader_t(assetmanageritem_t *item); + +typedef struct { + assetmanagerloader_t *loadAsync; + assetmanagerloader_t *loadSync; +} assetmanagerloaderdefinition_t; + +// Manager +typedef struct { + thread_t thread; + + assetmanageritem_t items[ASSET_MANAGER_ITEMS_MAX]; + uint8_t itemCount; +} assetmanager_t; + +extern assetmanagerloaderdefinition_t ASSET_MANAGER_LOADERS[]; + +/** + * Initialize the asset manager + * + * @param manager Manager to initialize. + */ +void assetManagerInit(assetmanager_t *manager); + +/** + * Begin asynchronously loading all of the assets + * + * @param manager Manager to begin async loading. + */ +void assetManagerStart(assetmanager_t *manager); + +/** + * Synchronously tick the asset manager. Some assets require some form of sync + * operations, such as buffering to the GPU, so make sure this is called at a + * good time for that task, such as right at the end of a frame. + * + * @param manager Manager to synchronously tick. + */ +void assetManagerUpdate(assetmanager_t *manager); + +/** + * Returns whether or not the given item is finished. + * + * @param item Item to check state of. + * @return True if finished, otherwise false. + */ +bool assetManagerIsItemFinished(assetmanageritem_t *item); + +/** + * Gets the progress of the asset manager as a representation of 0-1 as a % that + * has loaded. + * + * @param manager Manager to check the state of. + * @return The progress percent as a representation of 0-1 + */ +float assetManagerProgressGet(assetmanager_t *manager); + +/** Private Thread that is executed asynchronously */ +int32_t _assetManagerThread(thread_t *thread); + +/** + * Private method, simply adds an item to the manager and resets the state. + * + * @param manager Manager to add to. + * @return The added and reset item. + */ +assetmanageritem_t * assetManagerItemAdd(assetmanager_t *manager); + +/** + * Queue a texture load onto the asset manager buffer. + * + * @param manager Manager to queue on to. + * @param texture Texture to push the result in to. + * @param fileName Texture filename to load. + * @return A pointer to the asset manager item for tracking. + */ +assetmanageritem_t * assetManagerLoadTexture( + assetmanager_t *manager, texture_t *texture, char *fileName +); + +bool _assetManagerLoaderTextureAsync(assetmanageritem_t *item); +bool _assetManagerLoaderTextureSync(assetmanageritem_t *item); + +/** + * Queue a font load onto the asset manager buffer. + * + * @param manager Manager to queue on to. + * @param font Font to push the result in to. + * @param fileName Filename of the asset to load. + * @return A pointer to the asset manager item for tracking. + */ +assetmanageritem_t * assetManagerLoadFont( + assetmanager_t *manager, font_t *font, char *fileName +); + +bool _assetManagerLoaderFontAsync(assetmanageritem_t *item); +bool _assetManagerLoaderFontSync(assetmanageritem_t *item); + +/** + * Queues a shader load onto the asset manager buffer. + * + * @param manager Manager to queue on to. + * @param shader Shader to push the result in to. + * @param fileVert Vertex file in question to load. + * @param fileFrag Fragment file in question to load. + * @return A pointer to the asset manager item for tracking. + */ +assetmanageritem_t * assetManagerShaderLoad( + assetmanager_t *manager, shader_t *shader, char *fileVert, char *fileFrag +); + +bool _assetManagerLoaderShaderAsync(assetmanageritem_t *item); +bool _assetManagerLoaderShaderSync(assetmanageritem_t *item); \ No newline at end of file diff --git a/src/game/poker/game.c b/src/game/poker/game.c index 9a672d77..5a5fa963 100644 --- a/src/game/poker/game.c +++ b/src/game/poker/game.c @@ -7,22 +7,7 @@ #include "game.h" -thread_t thread; - -int32_t threadTest(thread_t *thread) { - printf("Thread?\n"); - threadSleep(2); - printf("THREAD2!?!?\n"); - return 0; -} - bool pokerGameInit(pokergame_t *game) { - threadInit(&thread, &threadTest); - threadStart(&thread); - threadJoin(&thread); - printf("Done?\n"); - - // Load the Assets. pokerGameAssetsInit(&game->assets); diff --git a/src/game/sandbox/game.c b/src/game/sandbox/game.c new file mode 100644 index 00000000..e9f77255 --- /dev/null +++ b/src/game/sandbox/game.c @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "game.h" + + +bool sandboxGameInit(sandboxgame_t *game) { + // assetTextureLoad(&game->texture, "textures/test_texture.png"); + quadInit(&game->quad, 0, 0,0,0,0, 500,500,1,1); + + game->texture.width = -1; + assetManagerInit(&game->manager); + + assetManagerLoadTexture(&game->manager, &game->texture, "textures/test_texture.png"); + assetManagerLoadFont(&game->manager, &game->font, "fonts/opensans/OpenSans-Regular.ttf"); + assetManagerShaderLoad(&game->manager, &game->shader, + "shaders/textured.vert", + "shaders/textured.frag" + ); + + assetManagerStart(&game->manager); + + return true; +} + +void sandboxGameUpdate(sandboxgame_t *game) { + camera_t camera; + float n = assetManagerProgressGet(&game->manager); + if(n < 1.0f) { + assetManagerUpdate(&game->manager); + printf("Loading %.2f\n", n); + return; + } + + cameraOrtho(&camera, + 0, game->engine.render.width, + game->engine.render.height, 0, + 0.01f, 1000.0f + ); + cameraLookAt(&camera, 0,0,10, 0,0,0); + + shaderUse(&game->shader); + shaderUseCamera(&game->shader, &camera); + + + if(game->texture.width != -1) { + shaderUseTexture(&game->shader, &game->texture); + shaderUsePosition(&game->shader, 0,0,0, 0,0,0); + primitiveDraw(&game->quad, 0, -1); + } +} + +void sandboxGameDispose(sandboxgame_t *game) { + // shaderDispose(&game->shader); +} \ No newline at end of file diff --git a/src/game/sandbox/sandboxscene.h b/src/game/sandbox/game.h similarity index 72% rename from src/game/sandbox/sandboxscene.h rename to src/game/sandbox/game.h index c985317c..cd5162cb 100644 --- a/src/game/sandbox/sandboxscene.h +++ b/src/game/sandbox/game.h @@ -10,16 +10,22 @@ #include "../../display/camera.h" #include "../../display/font.h" #include "../../display/shader.h" +#include "../../display/primitive.h" +#include "../../display/primitives/quad.h" #include "../../file/asset.h" #include "../../ui/label.h" #include "../../ui/breakpoint.h" +#include "../../file/assetmanager.h" typedef struct { engine_t engine; shader_t shader; - texture_t texture; font_t font; -} sandboxscene_t; + primitive_t quad; + assetmanager_t manager; + + texture_t texture; +} sandboxgame_t; /** * Initialize the sandbox scene test game. @@ -28,7 +34,7 @@ typedef struct { * @param engine Engine to use during init. * @return True if successful, otherwise false. */ -bool sandboxSceneInit(sandboxscene_t *game); +bool sandboxGameInit(sandboxgame_t *game); /** * Update a sandbox scene. @@ -36,11 +42,11 @@ bool sandboxSceneInit(sandboxscene_t *game); * @param game Game to update. * @param engine Engine to use when updating. */ -void sandboxSceneUpdate(sandboxscene_t *game); +void sandboxGameUpdate(sandboxgame_t *game); /** * Dispose a previously created scene game. * * @param game Game to dispose. */ -void sandboxSceneDispose(sandboxscene_t *game); \ No newline at end of file +void sandboxGameDispose(sandboxgame_t *game); \ No newline at end of file diff --git a/src/game/sandbox/sandboxscene.c b/src/game/sandbox/sandboxscene.c deleted file mode 100644 index f36529df..00000000 --- a/src/game/sandbox/sandboxscene.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2021 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "sandboxscene.h" - -bool sandboxSceneInit(sandboxscene_t *game) { - // Init Assets - assetShaderLoad(&game->shader, - "shared/shaders/textured.vert", - "shared/shaders/textured.frag" - ); - assetFontLoad(&game->font, "shared/fonts/opensans/OpenSans-Regular.ttf"); - assetTextureLoad(&game->texture, "shared/test_texture.png"); - - return true; -} - -void sandboxSceneUpdate(sandboxscene_t *game) { - camera_t camera; - - shaderUse(&game->shader); - cameraOrtho(&camera, - 0, game->engine.render.width, - game->engine.render.height, 0, - 0.01f, 1000.0f - ); - cameraLookAt(&camera, 0,0,10, 0,0,0); - shaderUseCamera(&game->shader, &camera); -} - -void sandboxSceneDispose(sandboxscene_t *game) { - // shaderDispose(&game->shader); -} \ No newline at end of file diff --git a/src/vn/vncharacter.c b/src/vn/vncharacter.c index 54c4c8c9..feca9670 100644 --- a/src/vn/vncharacter.c +++ b/src/vn/vncharacter.c @@ -114,9 +114,9 @@ void vnCharacterUpdate(vncharacter_t *character, engine_t *engine) { uint8_t vnCharacterLayerAdd(vncharacter_t *character, uint8_t frames, - int32_t lx, int32_t ly, - int32_t x, int32_t y, - int32_t width, int32_t height + int16_t lx, int16_t ly, + int16_t x, int16_t y, + int16_t width, int16_t height ) { uint8_t i; vncharacterlayer_t *layer;