diff --git a/assets/games/tictactoe/font/BIZUDPGothic-Bold.ttf b/assets/games/tictactoe/font/BIZUDPGothic-Bold.ttf
new file mode 100644
index 00000000..ae6dc1f7
Binary files /dev/null and b/assets/games/tictactoe/font/BIZUDPGothic-Bold.ttf differ
diff --git a/assets/games/tictactoe/font/BIZUDPGothic-Regular.ttf b/assets/games/tictactoe/font/BIZUDPGothic-Regular.ttf
new file mode 100644
index 00000000..9a3f215a
Binary files /dev/null and b/assets/games/tictactoe/font/BIZUDPGothic-Regular.ttf differ
diff --git a/assets/games/tictactoe/font/OFL.txt b/assets/games/tictactoe/font/OFL.txt
new file mode 100644
index 00000000..07e212f9
--- /dev/null
+++ b/assets/games/tictactoe/font/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2022 The BIZ UDGothic Project Authors (https://github.com/googlefonts/morisawa-biz-ud-mincho)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/assets/games/tictactoe/locale/en.xml b/assets/games/tictactoe/locale/en.xml
new file mode 100644
index 00000000..48aa1945
--- /dev/null
+++ b/assets/games/tictactoe/locale/en.xml
@@ -0,0 +1,9 @@
+
+ Hello Undefined
+
+
+ Some text
+
+ Other string
+
+
\ No newline at end of file
diff --git a/cmake/targets/CMakeLists.txt b/cmake/targets/CMakeLists.txt
index d8224db6..93698f07 100644
--- a/cmake/targets/CMakeLists.txt
+++ b/cmake/targets/CMakeLists.txt
@@ -8,7 +8,7 @@ if(NOT DEFINED DAWN_BUILD_TARGET)
if(WIN32)
set(DAWN_BUILD_TARGET "target-pokergame-win32-glfw")
elseif(UNIX AND NOT APPLE)
- set(DAWN_BUILD_TARGET "target-pokergame-linux64-glfw")
+ set(DAWN_BUILD_TARGET "target-tictactoe-linux64-glfw")
endif()
endif()
diff --git a/cmake/targets/target-tictactoe-linux64-glfw/CMakeLists.txt b/cmake/targets/target-tictactoe-linux64-glfw/CMakeLists.txt
new file mode 100644
index 00000000..07a95c6e
--- /dev/null
+++ b/cmake/targets/target-tictactoe-linux64-glfw/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright (c) 2022 Dominic Masters
+#
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+set(DAWN_BUILDING dawntictactoe CACHE INTERNAL ${DAWN_CACHE_TARGET})
+set(DAWN_TARGET_LINUX64 true CACHE INTERNAL ${DAWN_CACHE_TARGET})
+set(DAWN_TARGET_GLFW true CACHE INTERNAL ${DAWN_CACHE_TARGET})
\ No newline at end of file
diff --git a/src/dawn/prefabs/SimpleSpinningCubePrefab.hpp b/src/dawn/prefabs/SimpleSpinningCubePrefab.hpp
index 06cf45e6..09ad7243 100644
--- a/src/dawn/prefabs/SimpleSpinningCubePrefab.hpp
+++ b/src/dawn/prefabs/SimpleSpinningCubePrefab.hpp
@@ -1,38 +1,38 @@
-// Copyright (c) 2023 Dominic Masters
-//
-// This software is released under the MIT License.
-// https://opensource.org/licenses/MIT
-
-#pragma once
-#include "prefab/SceneItemPrefab.hpp"
-#include "display/mesh/CubeMesh.hpp"
-#include "scene/components/display/MeshRenderer.hpp"
-#include "scene/components/display/MeshHost.hpp"
-#include "scene/components/display/material/SimpleTexturedMaterial.hpp"
-#include "scene/components/example/ExampleSpin.hpp"
-
-namespace Dawn {
- class SimpleSpinningCubePrefab :
- public SceneItemPrefab
- {
- public:
- std::vector prefabAssets(AssetManager *man) {
- return std::vector();
- }
-
- SimpleSpinningCubePrefab(Scene *s, sceneitemid_t i) :
- SceneItemPrefab(s, i)
- {
- }
-
- void prefabInit(AssetManager *man) override {
- auto meshRenderer = this->addComponent();
- auto meshHost = this->addComponent();
- auto spinning = this->addComponent();
- auto material = this->addComponent();
-
- meshHost->mesh.createBuffers(CUBE_VERTICE_COUNT, CUBE_INDICE_COUNT);
- CubeMesh::buffer(&meshHost->mesh, glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(1, 1, 1), 0, 0);
- }
- };
+// Copyright (c) 2023 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "prefab/SceneItemPrefab.hpp"
+#include "display/mesh/CubeMesh.hpp"
+#include "scene/components/display/MeshRenderer.hpp"
+#include "scene/components/display/MeshHost.hpp"
+#include "scene/components/display/material/SimpleTexturedMaterial.hpp"
+#include "scene/components/example/ExampleSpin.hpp"
+
+namespace Dawn {
+ class SimpleSpinningCubePrefab :
+ public SceneItemPrefab
+ {
+ public:
+ static std::vector prefabAssets(AssetManager *man) {
+ return std::vector();
+ }
+
+ SimpleSpinningCubePrefab(Scene *s, sceneitemid_t i) :
+ SceneItemPrefab(s, i)
+ {
+ }
+
+ void prefabInit(AssetManager *man) override {
+ auto meshRenderer = this->addComponent();
+ auto meshHost = this->addComponent();
+ auto spinning = this->addComponent();
+ auto material = this->addComponent();
+
+ meshHost->mesh.createBuffers(CUBE_VERTICE_COUNT, CUBE_INDICE_COUNT);
+ CubeMesh::buffer(&meshHost->mesh, glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(1, 1, 1), 0, 0);
+ }
+ };
}
\ No newline at end of file
diff --git a/src/dawn/scenes/TestScene.hpp b/src/dawn/scenes/TestScene.hpp
new file mode 100644
index 00000000..adc552d0
--- /dev/null
+++ b/src/dawn/scenes/TestScene.hpp
@@ -0,0 +1,33 @@
+// Copyright (c) 2023 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "scene/Scene.hpp"
+#include "prefabs/SimpleSpinningCubePrefab.hpp"
+
+namespace Dawn {
+ class TestScene : public Scene {
+ protected:
+ Camera *camera;
+ SimpleSpinningCubePrefab *cube;
+
+ void stage() override {
+ camera = Camera::create(this);
+ camera->transform->lookAt(glm::vec3(5, 5, 5), glm::vec3(0, 0, 0));
+
+ cube = SimpleSpinningCubePrefab::prefabCreate(this);
+ }
+
+ std::vector getRequiredAssets() override {
+ auto assMan = &this->game->assetManager;
+ std::vector assets;
+ vectorAppend(&assets, SimpleSpinningCubePrefab::getRequiredAssets(assMan));
+ return assets;
+ }
+
+ public:
+ TestScene(DawnGame *game) : Scene(game) {}
+ };
+}
\ No newline at end of file
diff --git a/src/dawntictactoe/CMakeLists.txt b/src/dawntictactoe/CMakeLists.txt
new file mode 100644
index 00000000..c31f3496
--- /dev/null
+++ b/src/dawntictactoe/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright (c) 2023 Dominic Masters
+#
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+# Set up the executable
+set(DAWN_TARGET_NAME "TicTacToe" CACHE INTERNAL ${DAWN_CACHE_TARGET})
+
+# Build Project
+add_executable(${DAWN_TARGET_NAME})
+
+# Includes
+target_include_directories(${DAWN_TARGET_NAME}
+ PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}
+)
+
+# Subdirs
+add_subdirectory(game)
+add_subdirectory(save)
+
+# Assets
+set(DIR_GAME_ASSETS games/tictactoe)
+
+tool_language(locale_en ${DIR_GAME_ASSETS}/locale/en.xml)
\ No newline at end of file
diff --git a/src/dawntictactoe/game/CMakeLists.txt b/src/dawntictactoe/game/CMakeLists.txt
new file mode 100644
index 00000000..8ca94ca8
--- /dev/null
+++ b/src/dawntictactoe/game/CMakeLists.txt
@@ -0,0 +1,10 @@
+# Copyright (c) 2023 Dominic Masters
+#
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+# Sources
+target_sources(${DAWN_TARGET_NAME}
+ PRIVATE
+ DawnGame.cpp
+)
\ No newline at end of file
diff --git a/src/dawntictactoe/game/DawnGame.cpp b/src/dawntictactoe/game/DawnGame.cpp
new file mode 100644
index 00000000..d99f1e70
--- /dev/null
+++ b/src/dawntictactoe/game/DawnGame.cpp
@@ -0,0 +1,46 @@
+// Copyright (c) 2023 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "DawnGame.hpp"
+#include "scenes/TestScene.hpp"
+
+using namespace Dawn;
+
+DawnGame::DawnGame(DawnHost *host) :
+ host(host),
+ renderManager(this),
+ inputManager(this),
+ localeManager(this),
+ physicsManager(this),
+ saveManager(this)
+{
+}
+
+int32_t DawnGame::init() {
+ this->assetManager.init();
+ this->localeManager.init();
+ this->renderManager.init();
+
+ this->scene = new TestScene(this);
+
+ return DAWN_GAME_INIT_RESULT_SUCCESS;
+}
+
+int32_t DawnGame::update(float_t delta) {
+ this->assetManager.update();
+ this->inputManager.update();
+ this->timeManager.update(delta);
+
+ if(this->scene != nullptr) this->scene->update();
+
+ this->renderManager.update();
+
+ return DAWN_GAME_UPDATE_RESULT_SUCCESS;
+}
+
+void DawnGame::sceneCutover(Scene *scene) {
+ if(scene == nullptr) scene = this->scene;
+ this->sceneToCutTo = scene;
+}
\ No newline at end of file
diff --git a/src/dawntictactoe/game/DawnGame.hpp b/src/dawntictactoe/game/DawnGame.hpp
new file mode 100644
index 00000000..8839502f
--- /dev/null
+++ b/src/dawntictactoe/game/DawnGame.hpp
@@ -0,0 +1,31 @@
+// Copyright (c) 2023 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "game/_DawnGame.hpp"
+#include "scene/components/Components.hpp"
+#include "save/DawnGameSaveManager.hpp"
+
+namespace Dawn {
+ class DawnGame : public IDawnGame {
+ private:
+ Scene *sceneToCutTo = nullptr;
+
+ public:
+ DawnHost *host;
+ RenderManager renderManager;
+ AssetManager assetManager;
+ InputManager inputManager;
+ TimeManager timeManager;
+ LocaleManager localeManager;
+ DawnGameSaveManager saveManager;
+ PhysicsManager physicsManager;
+
+ DawnGame(DawnHost *host);
+ int32_t init() override;
+ int32_t update(float_t delta) override;
+ void sceneCutover(Scene *scene) override;
+ };
+}
\ No newline at end of file
diff --git a/src/dawntictactoe/input/InputBinds.hpp b/src/dawntictactoe/input/InputBinds.hpp
new file mode 100644
index 00000000..89145de6
--- /dev/null
+++ b/src/dawntictactoe/input/InputBinds.hpp
@@ -0,0 +1,14 @@
+// Copyright (c) 2023 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "input/InputManager.hpp"
+
+#define INPUT_BIND(n) ((inputbind_t)n)
+#define INPUT_BIND_ACCEPT INPUT_BIND(1)
+#define INPUT_BIND_NEGATIVE_X INPUT_BIND(2)
+#define INPUT_BIND_POSITIVE_X INPUT_BIND(3)
+#define INPUT_BIND_NEGATIVE_Y INPUT_BIND(4)
+#define INPUT_BIND_POSITIVE_Y INPUT_BIND(5)
\ No newline at end of file
diff --git a/src/dawntictactoe/save/CMakeLists.txt b/src/dawntictactoe/save/CMakeLists.txt
new file mode 100644
index 00000000..2d057169
--- /dev/null
+++ b/src/dawntictactoe/save/CMakeLists.txt
@@ -0,0 +1,10 @@
+# Copyright (c) 2023 Dominic Masters
+#
+# This software is released under the MIT License.
+# https://opensource.org/licenses/MIT
+
+# Sources
+target_sources(${DAWN_TARGET_NAME}
+ PRIVATE
+ DawnGameSaveManager.cpp
+)
\ No newline at end of file
diff --git a/src/dawntictactoe/save/DawnGameSaveManager.cpp b/src/dawntictactoe/save/DawnGameSaveManager.cpp
new file mode 100644
index 00000000..75a006b4
--- /dev/null
+++ b/src/dawntictactoe/save/DawnGameSaveManager.cpp
@@ -0,0 +1,28 @@
+// Copyright (c) 2023 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "DawnGameSaveManager.hpp"
+
+using namespace Dawn;
+
+DawnGameSaveManager::DawnGameSaveManager(DawnGame *game) : SaveManager(game) {
+}
+
+bool_t DawnGameSaveManager::validateSave(struct SaveFile raw) {
+ if(!raw.has(POKER_SAVE_KEY_EXAMPLE)) return true;
+ this->currentSave.copy(raw, POKER_SAVE_KEY_EXAMPLE);
+
+ return false;
+}
+
+void DawnGameSaveManager::setExample(int32_t val) {
+ savedata_t value;
+ value.i32 = val;
+ this->currentSave.set(POKER_SAVE_KEY_EXAMPLE, value);
+}
+
+int32_t DawnGameSaveManager::getExample() {
+ return this->currentSave.get(POKER_SAVE_KEY_EXAMPLE).i32;
+}
\ No newline at end of file
diff --git a/src/dawntictactoe/save/DawnGameSaveManager.hpp b/src/dawntictactoe/save/DawnGameSaveManager.hpp
new file mode 100644
index 00000000..bc946262
--- /dev/null
+++ b/src/dawntictactoe/save/DawnGameSaveManager.hpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2023 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "save/SaveManager.hpp"
+
+#define POKER_SAVE_KEY_EXAMPLE "poker.example"
+
+namespace Dawn {
+ class DawnGameSaveManager : public SaveManager {
+ protected:
+ virtual bool_t validateSave(struct SaveFile raw) override;
+
+ public:
+ DawnGameSaveManager(DawnGame *game);
+
+ void setExample(int32_t value);
+ int32_t getExample();
+ };
+}
\ No newline at end of file
diff --git a/src/dawntools/tools/CMakeLists.txt b/src/dawntools/tools/CMakeLists.txt
index 9eccd122..90998bce 100644
--- a/src/dawntools/tools/CMakeLists.txt
+++ b/src/dawntools/tools/CMakeLists.txt
@@ -79,10 +79,12 @@ endfunction()
# Language Tool
function(tool_language target in)
add_custom_target(${target}
- COMMAND languagegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}"
+ COMMAND languagegen --input="${DAWN_ASSETS_SOURCE_DIR}/${in}" --output="${DAWN_TOOL_GENERATED_LANG_DIR}/${target}.language"
COMMENT "Generating language set ${target} from ${in}"
DEPENDS languagegen
)
+ tool_generatedlanguages("${DAWN_TOOL_GENERATED_LANG_DIR}/${target}.language")
+ add_dependencies(${DAWN_TARGET_NAME} ${target})
endfunction()
# Audio Tool
diff --git a/src/dawntools/tools/generatedlanguages/GeneratedLanguages.cpp b/src/dawntools/tools/generatedlanguages/GeneratedLanguages.cpp
index 97a43679..ded35f47 100644
--- a/src/dawntools/tools/generatedlanguages/GeneratedLanguages.cpp
+++ b/src/dawntools/tools/generatedlanguages/GeneratedLanguages.cpp
@@ -26,6 +26,7 @@ int32_t GeneratedLanguages::start() {
// Now process each language file
std::map> strings;
+
std::vector knownKeys;
auto itFiles = files.begin();
while(itFiles != files.end()) {
@@ -84,6 +85,7 @@ int32_t GeneratedLanguages::start() {
File langOut(flags["output"] + FILE_PATH_SEP + "language_" + itLang->first + ".language");
bufferOut.clear();
+
auto itKeys = knownKeys.begin();
while(itKeys != knownKeys.end()) {
auto key = *itKeys;
@@ -97,6 +99,7 @@ int32_t GeneratedLanguages::start() {
}
// Write out.
+ langOut.mkdirp();
if(!langOut.writeString(bufferOut)) {
std::cout << "Failed to create output file \"" + langOut.filename + "\"" << std::endl;
return 1;
diff --git a/src/dawntools/tools/languagegen/CMakeLists.txt b/src/dawntools/tools/languagegen/CMakeLists.txt
index 4d20d747..4b32b157 100644
--- a/src/dawntools/tools/languagegen/CMakeLists.txt
+++ b/src/dawntools/tools/languagegen/CMakeLists.txt
@@ -6,31 +6,32 @@
# Texture Build Tool
project(languagegen VERSION 2.0)
add_executable(languagegen)
+
+
+# Sources
target_sources(languagegen
PRIVATE
${DAWN_SHARED_SOURCES}
+ ${DAWN_TOOL_SOURCES}
LanguageGen.cpp
- ../../util/DawnTool.cpp
- ../../util/File.cpp
-
- ../../util/file.cpp
- ../../util/csv.cpp
- ../../util/xml.cpp
)
+# Includes
target_include_directories(languagegen
PUBLIC
${DAWN_SHARED_INCLUDES}
- ${CMAKE_CURRENT_LIST_DIR}/../../
+ ${DAWN_TOOL_INCLUDES}
${CMAKE_CURRENT_LIST_DIR}
)
+# Definitions
target_compile_definitions(languagegen
PUBLIC
DAWN_TOOL_INSTANCE=LanguageGen
DAWN_TOOL_HEADER="LanguageGen.hpp"
)
+# Libraries
target_link_libraries(languagegen
PUBLIC
${DAWN_BUILD_HOST_LIBS}
diff --git a/src/dawntools/tools/languagegen/LanguageGen.cpp b/src/dawntools/tools/languagegen/LanguageGen.cpp
index e2e8994a..7cdc8076 100644
--- a/src/dawntools/tools/languagegen/LanguageGen.cpp
+++ b/src/dawntools/tools/languagegen/LanguageGen.cpp
@@ -9,162 +9,144 @@
using namespace Dawn;
-int32_t LanguageGen::start() {
- if(this->args.size() != 3) {
- std::cout << "Invalid number of arguments provided to language gen!" << std::endl;
- return 1;
+std::vector LanguageParser::getRequiredAttributes() {
+ return std::vector{ "key" };
+}
+
+std::map LanguageParser::getOptionalAttributes() {
+ return std::map();
+}
+
+int32_t LanguageParser::onParse(
+ Xml *node,
+ std::map values,
+ struct LanguageString *out,
+ std::string *error
+) {
+ out->key = values["key"];
+ out->text = node->value;
+ return 0;
+}
+
+
+
+std::vector LanguageGroupParser::getRequiredAttributes() {
+ return std::vector{ "key" };
+}
+
+std::map LanguageGroupParser::getOptionalAttributes() {
+ return std::map();
+}
+
+int32_t LanguageGroupParser::onParse(
+ Xml *node,
+ std::map values,
+ struct LanguageGroup *out,
+ std::string *error
+) {
+ std::string key = values["key"];
+ out->key += key;
+
+ auto it = node->children.begin();
+ int32_t ret;
+ while(it != node->children.end()) {
+ auto c = *it;
+ if(c->node == "string") {
+ struct LanguageString string;
+ ret = (LanguageParser()).parse(c, &string, error);
+ if(ret != 0) return ret;
+
+ string.lang = out->lang;
+ string.key = out->key + "." + string.key;
+ out->strings.push_back(string);
+
+ } else if(c->node == "group") {
+ struct LanguageGroup group;
+ group.key += key + ".";
+ group.lang = out->lang;
+
+ ret = (LanguageGroupParser()).parse(c, &group, error);
+ if(ret != 0) return ret;
+ vectorAppend(&out->strings, group.strings);
+
+ }
+ ++it;
+ }
+ return 0;
+}
+
+
+
+std::vector LanguageRootParser::getRequiredAttributes() {
+ return std::vector{ "lang" };
+}
+
+std::map LanguageRootParser::getOptionalAttributes() {
+ return std::map();
+}
+
+int32_t LanguageRootParser::onParse(
+ Xml *node,
+ std::map values,
+ struct LanguageRoot *out,
+ std::string *error
+) {
+ int32_t ret;
+ out->lang = values["lang"];
+
+ auto it = node->children.begin();
+ while(it != node->children.end()) {
+ auto c = *it;
+ if(c->node == "string") {
+ struct LanguageString string;
+ ret = (LanguageParser()).parse(c, &string, error);
+ if(ret != 0) return ret;
+ string.lang = out->lang;
+ out->strings.push_back(string);
+
+ } else if(c->node == "group") {
+ struct LanguageGroup group;
+ group.lang = out->lang;
+ ret = (LanguageGroupParser()).parse(c, &group, error);
+ if(ret != 0) return ret;
+ vectorAppend(&out->strings, group.strings);
+
+ }
+
+ ++it;
}
- auto fileIn = File(this->args[1]);
+ return 0;
+}
+
+
+
+std::vector LanguageGen::getRequiredFlags() {
+ return std::vector{ "input", "output" };
+}
+
+int32_t LanguageGen::start() {
+ auto fileIn = File(flags["input"]);
std::string buffer;
if(!fileIn.readString(&buffer)) {
std::cout << "Failed to open/read input file " << fileIn.filename << std::endl;
return 1;
}
+
+
auto xml = Xml::load(buffer);
+ std::string error;
+ struct LanguageRoot root;
- // Begin parsing. Start by looking for the tags
- std::vector languages;
- auto itChildren = xml.children.begin();
- while(itChildren != xml.children.end()) {
- auto child = *itChildren;
- if(child->node == "language") {
- auto attrName = child->attributes.find("name");
- if(attrName == child->attributes.end()) {
- std::cout << "Missing name param on language node" << std::endl;
- return 1;
- }
- languages.push_back(attrName->second);
- }
- ++itChildren;
+ auto ret = (LanguageRootParser()).parse(&xml, &root, &error);
+ if(ret != 0) {
+ std::cout << error << std::endl;
+ return ret;
}
- // Now begin actually parsing
- std::map> strings;
- itChildren = xml.children.begin();
- while(itChildren != xml.children.end()) {
- auto child = *itChildren;
- if(child->node == "group") {
- auto ret = this->parseGroup(child, "", &strings);
- if(ret != 0) return ret;
- } else if(child->node == "string") {
- std::cout << "String cannot be a root node" << std::endl;
- return 1;
- }
- ++itChildren;
- }
-
- // Now we validate each lang has each key.
- std::vector keys;
- auto it = strings.begin();
- while(it != strings.end()) {
- auto it2 = it->second.begin();
- while(it2 != it->second.end()) {
- auto key = it2->key;
- auto exist = std::find(keys.begin(), keys.end(), key);
- if(exist == keys.end()) {
- keys.push_back(key);
- }
- it2++;
- }
- ++it;
- }
-
- // Now we actually parse each string, validating as we go.
- it = strings.begin();
- while(it != strings.end()) {
- std::vector itKeys;
-
- std::string bufferOut;
-
- auto it2 = it->second.begin();
- while(it2 != it->second.end()) {
- auto l = *it2;
- itKeys.push_back(l.key);
- bufferOut += l.key + "|" + l.value + "|";
- it2++;
- }
-
- File fileOut(this->args[2] + "/language_" + it->first + ".language");
- if(!fileOut.mkdirp()) {
- std::cout << "Failed to create output folder" << std::endl;
- }
- if(!fileOut.writeString(bufferOut)) {
- std::cout << "Failed to write to output file " << fileOut.filename << std::endl;
- return 1;
- }
-
- auto it3 = keys.begin();
- while(it3 != keys.end()) {
- auto key = *it3;
- auto inIt = std::find(itKeys.begin(), itKeys.end(), key);
- if(inIt == itKeys.end()) {
- std::cout << "Locale " << it->first << " missing key " << key << std::endl;
- }
- it3++;
- }
-
- if(itKeys.size() != keys.size()) {
- std::cout << "Locale is missing some keys, see above" << std::endl;
- return 1;
- }
- ++it;
- }
-
- return 0;
-}
-
-int32_t LanguageGen::parseString(
- Xml *stringNode,
- std::string key,
- std::map> *strings
-) {
- auto attrLang = stringNode->attributes.find("lang");
- if(attrLang == stringNode->attributes.end()) {
- std::cout << "String is missing lang parameter." << std::endl;
- return -1;
- }
-
- struct LanguageString str;
- str.key = key;
- str.value = stringNode->value;
-
- auto existing = (*strings).find(attrLang->second);
- if(existing == (*strings).end()) {
- (*strings).insert(std::make_pair(attrLang->second, std::vector()));
- }
- (*strings)[attrLang->second].push_back(str);
- return 0;
-}
-
-int32_t LanguageGen::parseGroup(
- Xml *groupNode,
- std::string key,
- std::map> *strings
-) {
- int32_t ret;
-
- auto attrKey = groupNode->attributes.find("key");
- if(attrKey == groupNode->attributes.end()) {
- std::cout << "Group node is missing key" << std::endl;
- return 1;
- }
-
- if(key.size() > 0) key += ".";
- key += attrKey->second;
-
- auto itChildren = groupNode->children.begin();
- while(itChildren != groupNode->children.end()) {
- auto child = *itChildren;
- if(child->node == "string") {
- ret = this->parseString(child, key, strings);
- if(ret != 0) return ret;
- } else if(child->node == "group") {
- ret = this->parseGroup(child, key, strings);
- if(ret != 0) return ret;
- }
- ++itChildren;
- }
+ // Now dump out the language strings to be picked up later.
+ ret = languageSaveStrings(flags["output"], root.strings);
+ if(ret != 0) return ret;
return 0;
}
\ No newline at end of file
diff --git a/src/dawntools/tools/languagegen/LanguageGen.hpp b/src/dawntools/tools/languagegen/LanguageGen.hpp
index e15e4d59..c643baff 100644
--- a/src/dawntools/tools/languagegen/LanguageGen.hpp
+++ b/src/dawntools/tools/languagegen/LanguageGen.hpp
@@ -5,17 +5,62 @@
#pragma once
#include "util/DawnTool.hpp"
-#include "util/Xml.hpp"
#include "util/File.hpp"
+#include "util/XmlParser.hpp"
+#include "util/Language.cpp"
namespace Dawn {
- struct LanguageString {
+ struct LanguageGroup {
+ std::vector strings;
std::string key;
- std::string value;
+ std::string lang;
+ };
+
+ struct LanguageRoot {
+ std::string lang;
+ std::vector strings;
+ };
+
+ class LanguageParser : public XmlParser {
+ protected:
+ std::vector getRequiredAttributes();
+ std::map getOptionalAttributes();
+ int32_t onParse(
+ Xml *node,
+ std::map values,
+ struct LanguageString *out,
+ std::string *error
+ );
+ };
+
+ class LanguageGroupParser : public XmlParser {
+ protected:
+ std::vector getRequiredAttributes();
+ std::map getOptionalAttributes();
+ int32_t onParse(
+ Xml *node,
+ std::map values,
+ struct LanguageGroup *out,
+ std::string *error
+ );
+ };
+
+ class LanguageRootParser : public XmlParser {
+ protected:
+ std::vector getRequiredAttributes();
+ std::map getOptionalAttributes();
+ int32_t onParse(
+ Xml *node,
+ std::map values,
+ struct LanguageRoot *out,
+ std::string *error
+ ) override;
};
class LanguageGen : public DawnTool {
protected:
+ std::vector getRequiredFlags() override;
+
int32_t parseGroup(
Xml *node,
std::string key,