diff --git a/assets/en.csv b/assets/en.csv new file mode 100644 index 00000000..2725968c --- /dev/null +++ b/assets/en.csv @@ -0,0 +1,3 @@ +test,Some test string, +test2,Some other test string +test3,こんいちは \ No newline at end of file diff --git a/src/dawn/CMakeLists.txt b/src/dawn/CMakeLists.txt index ce971d7e..e4cada52 100644 --- a/src/dawn/CMakeLists.txt +++ b/src/dawn/CMakeLists.txt @@ -21,6 +21,7 @@ add_subdirectory(assert) add_subdirectory(asset) add_subdirectory(display) add_subdirectory(input) +add_subdirectory(locale) add_subdirectory(poker) add_subdirectory(scene) add_subdirectory(time) diff --git a/src/dawn/asset/AssetLoader.cpp b/src/dawn/asset/AssetLoader.cpp index e304247b..c22ad2f1 100644 --- a/src/dawn/asset/AssetLoader.cpp +++ b/src/dawn/asset/AssetLoader.cpp @@ -91,6 +91,12 @@ size_t AssetLoader::loadRaw(uint8_t **buffer) { return read; } +size_t AssetLoader::setPosition(size_t position) { + assertTrue(position >= 0); + this->rewind(); + return this->skip(position); +} + AssetLoader::~AssetLoader() { if(this->handle != nullptr) { this->close(); diff --git a/src/dawn/asset/AssetLoader.hpp b/src/dawn/asset/AssetLoader.hpp index 8b4abec2..2a87cb22 100644 --- a/src/dawn/asset/AssetLoader.hpp +++ b/src/dawn/asset/AssetLoader.hpp @@ -71,6 +71,14 @@ namespace Dawn { */ size_t getPosition(); + /** + * Sets the position of the file read head. + * + * @param position Position to set to. + * @return How many bytes were skipped / rewound. + */ + size_t setPosition(size_t position); + /** * Loads the entire file into a raw buffer. * @param buffer Pointer to where a pointer to the buffer will be stored. diff --git a/src/dawn/asset/AssetManager.hpp b/src/dawn/asset/AssetManager.hpp index 97af6170..241e70b2 100644 --- a/src/dawn/asset/AssetManager.hpp +++ b/src/dawn/asset/AssetManager.hpp @@ -7,6 +7,7 @@ #include "Asset.hpp" #include "util/array.hpp" +#include "assets/LanguageAsset.hpp" #include "assets/TextureAsset.hpp" #include "assets/TilesetAsset.hpp" #include "assets/TrueTypeAsset.hpp" diff --git a/src/dawn/asset/assets/CMakeLists.txt b/src/dawn/asset/assets/CMakeLists.txt index 0f57218e..ffa28cda 100644 --- a/src/dawn/asset/assets/CMakeLists.txt +++ b/src/dawn/asset/assets/CMakeLists.txt @@ -6,6 +6,7 @@ # Sources target_sources(${DAWN_TARGET_NAME} PRIVATE + LanguageAsset.cpp TextureAsset.cpp TilesetAsset.cpp TrueTypeAsset.cpp diff --git a/src/dawn/asset/assets/LanguageAsset.cpp b/src/dawn/asset/assets/LanguageAsset.cpp new file mode 100644 index 00000000..8292d1d0 --- /dev/null +++ b/src/dawn/asset/assets/LanguageAsset.cpp @@ -0,0 +1,84 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "LanguageAsset.hpp" + +using namespace Dawn; + +LanguageAsset::LanguageAsset(AssetManager *man, std::string name) : + Asset(man, name), + loader(name + ".language") +{ + +} + +void LanguageAsset::updateSync() { + +} + +void LanguageAsset::updateAsync() { + assertTrue(this->state == 0x00); + + // Open Asset + this->state = 0x01; + this->loader.open(); + + // Get Length + this->state = 0x02; + this->loader.end(); + this->state = 0x03; + size_t len = this->loader.getPosition(); + this->state = 0x04; + this->loader.rewind(); + + // Create buffer + this->state = 0x05; + size_t position = 0; + + // Loop over CSV + while(position < len) { + this->loader.read(buffer, 1024); + + // Get strings + uint8_t *keyStart = buffer; + uint8_t *keyEnd = (uint8_t*)strchr((char*)keyStart, '|'); + *keyEnd = '\0'; + uint8_t *valueStart = keyEnd + 1; + uint8_t *valueEnd = (uint8_t*)strchr((char*)valueStart, '|'); + + // Load value positions + struct AssetLanguageValue value; + value.begin = position + (size_t)(valueStart - buffer); + value.length = (size_t)(valueEnd - valueStart); + + // Prepare for next string. + position = position + (size_t)(valueEnd - buffer + 1); + this->loader.rewind(); + this->loader.skip(position); + + // Store strings. + std::string key((char *)keyStart); + this->values[key] = value; + } + + this->state = 0x06; + this->loader.rewind(); + + this->state = 0x07; + this->loaded = true; +} + +std::string LanguageAsset::getValue(std::string key) { + assertTrue(this->state == 0x07); + + // Get the positions + struct AssetLanguageValue value = this->values[key]; + + this->loader.setPosition(value.begin); + this->loader.read(buffer, value.length); + buffer[value.length] = '\0'; + + return std::string((char *)buffer, value.length + 1); +} \ No newline at end of file diff --git a/src/dawn/asset/assets/LanguageAsset.hpp b/src/dawn/asset/assets/LanguageAsset.hpp new file mode 100644 index 00000000..7fda9a3a --- /dev/null +++ b/src/dawn/asset/assets/LanguageAsset.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "../Asset.hpp" +#include "../AssetLoader.hpp" + +namespace Dawn { + struct AssetLanguageValue { + size_t begin; + size_t length; + }; + + class LanguageAsset : public Asset { + protected: + AssetLoader loader; + uint8_t state = 0x00; + std::map values; + uint8_t buffer[1024]; + + public: + LanguageAsset(AssetManager *man, std::string name); + + void updateSync() override; + void updateAsync() override; + + std::string getValue(std::string key); + }; +} \ No newline at end of file diff --git a/src/dawn/game/_DawnGame.hpp b/src/dawn/game/_DawnGame.hpp index d9f65fe1..af0b6469 100644 --- a/src/dawn/game/_DawnGame.hpp +++ b/src/dawn/game/_DawnGame.hpp @@ -11,6 +11,7 @@ #include "input/InputManager.hpp" #include "time/TimeManager.hpp" #include "input/InputBinds.hpp" +#include "locale/LanguageManager.hpp" #define DAWN_GAME_INIT_RESULT_SUCCESS 0 #define DAWN_GAME_UPDATE_RESULT_SUCCESS 0 diff --git a/src/dawn/locale/CMakeLists.txt b/src/dawn/locale/CMakeLists.txt new file mode 100644 index 00000000..472a8dd6 --- /dev/null +++ b/src/dawn/locale/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2022 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + + +# Sources +target_sources(${DAWN_TARGET_NAME} + PRIVATE + LanguageManager.cpp +) \ No newline at end of file diff --git a/src/dawn/locale/LanguageManager.cpp b/src/dawn/locale/LanguageManager.cpp new file mode 100644 index 00000000..8647fa14 --- /dev/null +++ b/src/dawn/locale/LanguageManager.cpp @@ -0,0 +1,19 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "LanguageManager.hpp" +#include "game/DawnGame.hpp" + +using namespace Dawn; + +LanguageManager::LanguageManager(DawnGame *game) { + this->game = game; + + auto lang = this->game->assetManager.get("language_en"); + while(!lang->loaded) { + lang->updateAsync(); + } + std::cout << lang->getValue("test2"); +} \ No newline at end of file diff --git a/src/dawn/locale/LanguageManager.hpp b/src/dawn/locale/LanguageManager.hpp new file mode 100644 index 00000000..e44b2882 --- /dev/null +++ b/src/dawn/locale/LanguageManager.hpp @@ -0,0 +1,29 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "event/Event.hpp" +#include "asset/AssetManager.hpp" + +namespace Dawn { + class DawnGame; + + struct LocalizedString { + std::string data; + }; + + class LanguageManager { + private: + DawnGame *game; + LanguageAsset *asset; + + public: + Event<> eventLanguageChanged; + + LanguageManager(DawnGame *game); + + struct LocalizedString getString(std::string key); + }; +} \ No newline at end of file diff --git a/src/dawnpokergame/CMakeLists.txt b/src/dawnpokergame/CMakeLists.txt index 402ade03..ef51b726 100644 --- a/src/dawnpokergame/CMakeLists.txt +++ b/src/dawnpokergame/CMakeLists.txt @@ -23,6 +23,7 @@ add_subdirectory(visualnovel) add_subdirectory(scenes) # Assets +tool_language(language_en en.csv) tool_texture(texture_test texture_test.png) tool_texture(texture_city_day borrowed/city_day.png) tool_texture(texture_city_night borrowed/city_night.png) @@ -40,6 +41,7 @@ tool_truetype(truetype_ark ) add_dependencies(${DAWN_TARGET_NAME} + language_en texture_test tileset_penny truetype_ark diff --git a/src/dawnpokergame/game/DawnGame.cpp b/src/dawnpokergame/game/DawnGame.cpp index bf062a82..4a7873e3 100644 --- a/src/dawnpokergame/game/DawnGame.cpp +++ b/src/dawnpokergame/game/DawnGame.cpp @@ -14,7 +14,8 @@ TextureAsset *assetTexture; DawnGame::DawnGame(DawnHost *host) : host(host), renderManager(this), - inputManager(this) + inputManager(this), + languageManager(this) { } diff --git a/src/dawnpokergame/game/DawnGame.hpp b/src/dawnpokergame/game/DawnGame.hpp index d2857d6a..3c26e1cd 100644 --- a/src/dawnpokergame/game/DawnGame.hpp +++ b/src/dawnpokergame/game/DawnGame.hpp @@ -15,6 +15,7 @@ namespace Dawn { AssetManager assetManager; InputManager inputManager; TimeManager timeManager; + LanguageManager languageManager; DawnGame(DawnHost *host); int32_t init() override; diff --git a/src/dawnpokergame/scenes/PokerVNScene.hpp b/src/dawnpokergame/scenes/PokerVNScene.hpp index 3f17e179..c414b577 100644 --- a/src/dawnpokergame/scenes/PokerVNScene.hpp +++ b/src/dawnpokergame/scenes/PokerVNScene.hpp @@ -13,10 +13,16 @@ namespace Dawn { class PokerVNScene : public SimpleVNScene { protected: - virtual std::vector getPokerPlayers() = 0; void vnStage() override; std::vector getRequiredAssets() override; + /** + * Returns the Poker Players that are in this poker scene. + * + * @return List of Poker Players. + */ + virtual std::vector getPokerPlayers() = 0; + public: PokerGame *pokerGame; std::vector pokerPlayers; diff --git a/src/dawntools/CMakeLists.txt b/src/dawntools/CMakeLists.txt index 97afa1e4..a6dfa96e 100644 --- a/src/dawntools/CMakeLists.txt +++ b/src/dawntools/CMakeLists.txt @@ -4,4 +4,5 @@ # https://opensource.org/licenses/MIT add_subdirectory(display) -add_subdirectory(file) \ No newline at end of file +add_subdirectory(file) +add_subdirectory(locale) \ No newline at end of file diff --git a/src/dawntools/display/truetypegen/main.c b/src/dawntools/display/truetypegen/main.c index bf06c886..ddc0fc62 100644 --- a/src/dawntools/display/truetypegen/main.c +++ b/src/dawntools/display/truetypegen/main.c @@ -88,6 +88,7 @@ int main(int argc, char *args[]) { size_t readSize = fread(ttfData, 1, fileSize, file); fclose(file); if(readSize < fileSize) { + free(ttfData); printf("Failed to read all data form TTF\n"); return 1; } diff --git a/src/dawntools/locale/CMakeLists.txt b/src/dawntools/locale/CMakeLists.txt new file mode 100644 index 00000000..65ad32d6 --- /dev/null +++ b/src/dawntools/locale/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2021 Dominic Msters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +add_subdirectory(languagegen) + +# Language Tool +function(tool_language target in) + add_custom_target(${target} + COMMAND languagegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${target}" + COMMENT "Generating texture ${target} from ${in}" + DEPENDS languagegen + ) +endfunction() \ No newline at end of file diff --git a/src/dawntools/locale/languagegen/CMakeLists.txt b/src/dawntools/locale/languagegen/CMakeLists.txt new file mode 100644 index 00000000..e628bc38 --- /dev/null +++ b/src/dawntools/locale/languagegen/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (c) 2021 Dominic Msters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Texture Build Tool +project(languagegen VERSION 1.0) +add_executable(languagegen) +target_sources(languagegen + PRIVATE + main.c + ../../utils/file.c + ../../utils/image.c + ../../utils/csv.c +) +target_include_directories(languagegen + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/../../ + ${CMAKE_CURRENT_LIST_DIR} +) +target_link_libraries(languagegen + PUBLIC + ${DAWN_BUILD_HOST_LIBS} + stb +) \ No newline at end of file diff --git a/src/dawntools/locale/languagegen/main.c b/src/dawntools/locale/languagegen/main.c new file mode 100644 index 00000000..a7d87547 --- /dev/null +++ b/src/dawntools/locale/languagegen/main.c @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "../../utils/common.h" +#include "../../utils/file.h" +#include "../../utils/csv.h" + +int main(int argc, char *argv[]) { + FILE *file; + char path[FILENAME_MAX + 1]; + csv_t csv; + char *in; + char *out; + char *buffer; + char sep = '|'; + + if(argc != 3) { + printf("Invalid number of arguments\n"); + return 1; + } + + // Set up strings + in = argv[1]; + out = argv[2]; + + // Normalize slashes + fileNormalizeSlashes(in); + fileNormalizeSlashes(out); + + // Check the output doesn't already exist + sprintf(path, "%s.language", out); + // file = fopen(path, "rb"); + // if(file != NULL) { + // fclose(file); + // return 0; + // } + + // Read in original CSV string + file = fopen(in, "rb"); + if(file == NULL) { + printf("Failed to open file!\n"); + return 1; + } + + // Seek to end, get length, seek back to start. + fseek(file, 0, SEEK_END); + size_t fileSize = ftell(file); + fseek(file, 0, SEEK_SET); + + // Read in all data + buffer = malloc(sizeof(char) * (fileSize + 1)); + size_t readSize = fread(buffer, 1, fileSize, file); + fclose(file); + if(readSize < fileSize) { + free(buffer); + printf("Failed to read all data from CSV\n"); + return 1; + } + buffer[fileSize] = '\0'; + + csvParse(buffer, &csv); + free(buffer); + printf("Parsed\n"); + + // Prepare output file for writing. + sprintf(path, "%s.language", out); + fileMkdirp(path); + file = fopen(path, "wb"); + if(file == NULL) { + csvDispose(&csv); + printf("Failed to create output language file\n"); + return 1; + } + + // Iterate over the CSV + for(int32_t y = 0; y < csv.rowCount; y++) { + // Ensure valid line + if(csv.cellCounts[y] != 2) { + printf("Failed to parse language. Line %i has %i cells instead of 2\n", y, csv.cellCounts); + fclose(file); + csvDispose(&csv); + return 1; + } + + char *key = csvGetCell(&csv, y, 0); + char *value = csvGetCell(&csv, y, 1); + + if(strlen(key) <= 0 || strlen(value) <= 0) { + printf("Failed to parse language. Line %i has an invalid string\n", y); + fclose(file); + csvDispose(&csv); + return 1; + } + + fwrite(key, sizeof(char), strlen(key), file); + fwrite(&sep, sizeof(char), 1, file); + fwrite(value, sizeof(char), strlen(value), file); + fwrite(&sep, sizeof(char), 1, file); + } + + // Finished writing + fclose(file); + csvDispose(&csv); + + return 0; +} \ No newline at end of file diff --git a/src/dawntools/utils/csv.c b/src/dawntools/utils/csv.c index 394baf3b..9e58482b 100644 --- a/src/dawntools/utils/csv.c +++ b/src/dawntools/utils/csv.c @@ -7,12 +7,16 @@ #include "csv.h" +char * csvGetCell(csv_t *csv, int32_t row, int32_t cell) { + return csv->rows[(row * CSV_ROW_COUNT_MAX) + cell]; +} + void csvParse(char *string, csv_t *csv) { char c; size_t i, j, length; csvparsestate_t state; int32_t rowCellCount; - + length = strlen(string); csv->buffer = malloc(sizeof(char) * length * 2); csv->cellCounts = malloc(sizeof(int32_t) * CSV_ROW_COUNT_MAX); diff --git a/src/dawntools/utils/csv.h b/src/dawntools/utils/csv.h index 6c06d754..3ab2582c 100644 --- a/src/dawntools/utils/csv.h +++ b/src/dawntools/utils/csv.h @@ -24,6 +24,8 @@ typedef struct { int32_t *cellCounts; } csv_t; +char * csvGetCell(csv_t *csv, int32_t row, int32_t cell); + void csvParse(char *string, csv_t *csv); void csvDispose(csv_t *csv); \ No newline at end of file