From 89afd1e53f75df5364ddb9dd853cc1163226f541 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Thu, 27 Apr 2023 21:52:19 -0700 Subject: [PATCH] TTF Loading Fixed --- assets/games/liminal/VNTextbox.xml | 4 + src/dawn/scene/components/ui/UIComponent.cpp | 2 +- src/dawnliminal/CMakeLists.txt | 5 +- src/dawnliminal/game/LiminalGame.cpp | 4 +- src/dawnliminal/scenes/HelloWorldScene.hpp | 54 ++----------- src/dawntools/CMakeLists.txt | 1 + .../prefabtool/PrefabAssetParser.cpp | 2 + .../prefabtool/PrefabAssetParser.hpp | 3 +- src/dawntools/prefabtool/PrefabGen.cpp | 5 ++ src/dawntools/truetypetool/CMakeLists.txt | 51 +++++++++++++ src/dawntools/truetypetool/TrueTypeTool.cpp | 75 +++++++++++++++++++ src/dawntools/truetypetool/TrueTypeTool.hpp | 22 ++++++ src/dawntools/util/File.cpp | 18 +++-- src/dawntools/util/File.hpp | 9 +++ 14 files changed, 196 insertions(+), 59 deletions(-) create mode 100644 assets/games/liminal/VNTextbox.xml create mode 100644 src/dawntools/truetypetool/CMakeLists.txt create mode 100644 src/dawntools/truetypetool/TrueTypeTool.cpp create mode 100644 src/dawntools/truetypetool/TrueTypeTool.hpp diff --git a/assets/games/liminal/VNTextbox.xml b/assets/games/liminal/VNTextbox.xml new file mode 100644 index 00000000..64e88d98 --- /dev/null +++ b/assets/games/liminal/VNTextbox.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/dawn/scene/components/ui/UIComponent.cpp b/src/dawn/scene/components/ui/UIComponent.cpp index 739bf0bf..8ac8a331 100644 --- a/src/dawn/scene/components/ui/UIComponent.cpp +++ b/src/dawn/scene/components/ui/UIComponent.cpp @@ -19,7 +19,7 @@ UIComponent::UIComponent(SceneItem *item) : UIComponentDimensional * UIComponent::getParentDimensional() { auto parent = this->transform->getParent(); - if(!parent) return nullptr; + if(parent == nullptr) return nullptr; auto dimensional = parent->item->getComponent(); assertNotNull(dimensional); return dimensional; diff --git a/src/dawnliminal/CMakeLists.txt b/src/dawnliminal/CMakeLists.txt index b78b1e1c..773059b1 100644 --- a/src/dawnliminal/CMakeLists.txt +++ b/src/dawnliminal/CMakeLists.txt @@ -18,4 +18,7 @@ add_subdirectory(save) # Assets set(LIMINAL_ASSETS_DIR ${DAWN_ASSETS_DIR}/games/liminal) -tool_vnscene(${LIMINAL_ASSETS_DIR}/test.xml) \ No newline at end of file +tool_vnscene(${LIMINAL_ASSETS_DIR}/test.xml) + +tool_prefab(${LIMINAL_ASSETS_DIR}/VNTextbox.xml) +tool_truetype(font_main ${DAWN_ASSETS_DIR}/ark-pixel.ttf) \ No newline at end of file diff --git a/src/dawnliminal/game/LiminalGame.cpp b/src/dawnliminal/game/LiminalGame.cpp index 7bec3cab..4c28a4cb 100644 --- a/src/dawnliminal/game/LiminalGame.cpp +++ b/src/dawnliminal/game/LiminalGame.cpp @@ -10,6 +10,6 @@ using namespace Dawn; Scene * Dawn::dawnGameGetInitialScene(DawnGame *game) { - // return new HelloWorldScene(game); - return new TestScene(game); + return new HelloWorldScene(game); + // return new TestScene(game); } \ No newline at end of file diff --git a/src/dawnliminal/scenes/HelloWorldScene.hpp b/src/dawnliminal/scenes/HelloWorldScene.hpp index 6daa3b5e..fe34516c 100644 --- a/src/dawnliminal/scenes/HelloWorldScene.hpp +++ b/src/dawnliminal/scenes/HelloWorldScene.hpp @@ -7,14 +7,7 @@ #include "scene/Scene.hpp" #include "scene/components/display/Camera.hpp" #include "prefabs/SimpleSpinningCubePrefab.hpp" -#include "games/vn/components/VNManager.hpp" -#include "games/vn/events/VNDummyEvent.hpp" -#include "games/vn/events/VNTextEvent.hpp" -#include "games/vn/events/VNPositionEvent.hpp" -#include "games/vn/events/VNSetEvent.hpp" -#include "games/vn/events/VNChoiceEvent.hpp" -#include "games/vn/events/VNParallelEvent.hpp" -#include "games/vn/events/VNWaitEvent.hpp" +#include "prefabs/VNTextbox.hpp" namespace Dawn { class HelloWorldScene : public Scene { @@ -33,52 +26,15 @@ namespace Dawn { auto cube = SimpleSpinningCubePrefab::create(this); - auto vnItem = this->createSceneItem(); - auto vnManager = vnItem->addComponent(); - - auto eventTest = vnManager->createEvent(); - - auto positionEvent = vnManager->createEvent(); - positionEvent->to.x = 2.0f; - positionEvent->item = cube; - positionEvent->duration = 3.0f; - - auto vnTextEvent = vnManager->createEvent(); - vnTextEvent->text = "Hello World!"; - - auto setPropertyEvent = vnManager->createEvent>(); - setPropertyEvent->modifies = &test; - setPropertyEvent->to = 10; - - auto choiceEvent = vnManager->createEvent(); - choiceEvent->text = "Choice?"; - choiceEvent->choices["state0"] = "State 0"; - choiceEvent->choices["state1"] = "State 1"; - choiceEvent->choices["state2"] = "State 2"; - choiceEvent->choices["state3"] = "State 3"; - - auto parallelEvent = vnManager->createEvent(); - auto wait0 = vnManager->createEvent(); - wait0->duration = 1.0f; - parallelEvent->events.push_back(wait0); - - auto wait1 = vnManager->createEvent(); - wait1->duration = 3.0f; - parallelEvent->events.push_back(wait1); - - eventTest - ->then(parallelEvent) - ->then(positionEvent) - // ->then(vnTextEvent) - // ->then(setPropertyEvent) - // ->then(choiceEvent) - ; - vnManager->setEvent(eventTest); + auto textbox = VNTextbox::create(this); + textbox->transform.setParent(canvas->transform); } std::vector getRequiredAssets() override { auto assMan = &this->game->assetManager; std::vector assets; + vectorAppend(&assets, SimpleSpinningCubePrefab::prefabAssets(assMan)); + vectorAppend(&assets, VNTextbox::prefabAssets(assMan)); return assets; } diff --git a/src/dawntools/CMakeLists.txt b/src/dawntools/CMakeLists.txt index 7f4bff00..99b0091e 100644 --- a/src/dawntools/CMakeLists.txt +++ b/src/dawntools/CMakeLists.txt @@ -21,4 +21,5 @@ include(util/CMakeLists.txt) # Tools add_subdirectory(prefabtool) add_subdirectory(texturetool) +add_subdirectory(truetypetool) add_subdirectory(vnscenetool) \ No newline at end of file diff --git a/src/dawntools/prefabtool/PrefabAssetParser.cpp b/src/dawntools/prefabtool/PrefabAssetParser.cpp index c94b9c41..586cc0cf 100644 --- a/src/dawntools/prefabtool/PrefabAssetParser.cpp +++ b/src/dawntools/prefabtool/PrefabAssetParser.cpp @@ -25,6 +25,8 @@ int32_t PrefabAssetParser::onParse( if(values["type"] == "texture") { out->type = PREFAB_ASSET_TYPE_TEXTURE; + } else if(values["type"] == "truetype") { + out->type = PREFAB_ASSET_TYPE_TRUETYPE_FONT; } else { *error = "Unknown asset type '" + values["type"] + "'"; return 1; diff --git a/src/dawntools/prefabtool/PrefabAssetParser.hpp b/src/dawntools/prefabtool/PrefabAssetParser.hpp index c2c57e77..b263bb1e 100644 --- a/src/dawntools/prefabtool/PrefabAssetParser.hpp +++ b/src/dawntools/prefabtool/PrefabAssetParser.hpp @@ -8,7 +8,8 @@ namespace Dawn { enum PrefabAssetType { - PREFAB_ASSET_TYPE_TEXTURE + PREFAB_ASSET_TYPE_TEXTURE, + PREFAB_ASSET_TYPE_TRUETYPE_FONT }; struct PrefabAsset { diff --git a/src/dawntools/prefabtool/PrefabGen.cpp b/src/dawntools/prefabtool/PrefabGen.cpp index 78af3edb..6b42a244 100644 --- a/src/dawntools/prefabtool/PrefabGen.cpp +++ b/src/dawntools/prefabtool/PrefabGen.cpp @@ -44,6 +44,11 @@ void PrefabGen::generate( assetMap[a.fileName] = "&" + a.usageName + "->texture"; break; + case PREFAB_ASSET_TYPE_TRUETYPE_FONT: + assetType = "TrueTypeAsset"; + assetMap[a.fileName] = "&" + a.usageName + "->font"; + break; + default: assertUnreachable(); } diff --git a/src/dawntools/truetypetool/CMakeLists.txt b/src/dawntools/truetypetool/CMakeLists.txt new file mode 100644 index 00000000..0efff173 --- /dev/null +++ b/src/dawntools/truetypetool/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (c) 2021 Dominic Msters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +project(truetypetool VERSION 2.0) +add_executable(truetypetool) + +target_sources(truetypetool + PRIVATE + ${DAWN_SHARED_SOURCES} + ${DAWN_TOOL_SOURCES} + TrueTypeTool.cpp +) + +target_include_directories(truetypetool + PUBLIC + ${DAWN_SHARED_INCLUDES} + ${DAWN_TOOL_INCLUDES} + ${CMAKE_CURRENT_LIST_DIR} +) + +# Definitions +target_compile_definitions(truetypetool + PUBLIC + ${DAWN_SHARED_DEFINITIONS} + DAWN_TOOL_INSTANCE=TrueTypeTool + DAWN_TOOL_HEADER="TrueTypeTool.hpp" +) + +# Libraries +target_link_libraries(truetypetool + PUBLIC + ${DAWN_BUILD_HOST_LIBS} + stb +) + +# Tool Function +function(tool_truetype target in) + set(DEPS "") + if(DAWN_BUILD_TOOLS) + set(DEPS truetypetool) + endif() + + add_custom_target(${target} + COMMAND truetypetool --input="${DAWN_ASSETS_SOURCE_DIR}/${in}" --output="${DAWN_ASSETS_BUILD_DIR}/${target}" + COMMENT "Generating truetype font ${target} from ${in}" + DEPENDS ${DEPS} + ) + add_dependencies(${DAWN_TARGET_NAME} ${target}) +endfunction() \ No newline at end of file diff --git a/src/dawntools/truetypetool/TrueTypeTool.cpp b/src/dawntools/truetypetool/TrueTypeTool.cpp new file mode 100644 index 00000000..39dcfa5d --- /dev/null +++ b/src/dawntools/truetypetool/TrueTypeTool.cpp @@ -0,0 +1,75 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "TrueTypeTool.hpp" +#ifndef STB_TRUETYPE_IMPLEMENTATION + #define STB_TRUETYPE_IMPLEMENTATION + #include +#endif + +using namespace Dawn; + +std::vector TrueTypeTool::getRequiredFlags() { + return { "input", "output" }; +} + +int32_t TrueTypeTool::start() { + File fileIn(flags["input"]); + char *ttfData = nullptr; + if(!fileIn.readToBuffer(&ttfData)) { + std::cout << "Failed to read file to buffer!" << std::endl; + return 1; + } + + // Create bitmap data. This is a single channel color (alpha). + size_t width = 1024; + size_t height = 1024; + float_t fontSize = 128.0f; + size_t textureSize = width * height; + stbi_uc *bitmapData = new stbi_uc[textureSize]; + stbtt_bakedchar characterData[TRUETYPE_NUM_CHARS]; + + // Now parse the TTF itself. + stbtt_BakeFontBitmap( + (uint8_t*)ttfData, 0, (float)fontSize, bitmapData, + width, height, + TRUETYPE_FIRST_CHAR, TRUETYPE_NUM_CHARS, + characterData + ); + + // Prepare output file for writing. + File fileOut(flags["output"] + ".truetype"); + if(!fileOut.mkdirp()) { + free(ttfData); + delete bitmapData; + std::cout << "Failed to create output directory!" << std::endl; + return 1; + } + if(!fileOut.open(FILE_MODE_WRITE)) { + free(ttfData); + delete bitmapData; + std::cout << "Failed to open output file for writing!" << std::endl; + return 1; + } + + // Write data + fileOut.writeString(std::to_string(width) + "|" + std::to_string(height) + "|" + std::to_string(fontSize) + "|"); + uint8_t pixels[4]; + for(size_t i = 0; i < textureSize; i++) { + pixels[0] = 255; + pixels[1] = 255; + pixels[2] = 255; + pixels[3] = bitmapData[i]; + fileOut.writeRaw((char*)pixels, 4); + } + + // Write quads + fileOut.writeRaw((char*)characterData, sizeof(stbtt_bakedchar) * TRUETYPE_NUM_CHARS); + free(ttfData); + delete bitmapData; + fileOut.close(); + + return 0; +} \ No newline at end of file diff --git a/src/dawntools/truetypetool/TrueTypeTool.hpp b/src/dawntools/truetypetool/TrueTypeTool.hpp new file mode 100644 index 00000000..2c35530e --- /dev/null +++ b/src/dawntools/truetypetool/TrueTypeTool.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 "util/DawnTool.hpp" +#include "util/File.hpp" +#include "util/Image.hpp" + +#define TRUETYPE_FIRST_CHAR 32 +#define TRUETYPE_NUM_CHARS 96 + +namespace Dawn { + class TrueTypeTool : public DawnTool { + protected: + std::vector getRequiredFlags() override; + + public: + int32_t start(); + }; +} \ No newline at end of file diff --git a/src/dawntools/util/File.cpp b/src/dawntools/util/File.cpp index 56df6443..496097fa 100644 --- a/src/dawntools/util/File.cpp +++ b/src/dawntools/util/File.cpp @@ -166,18 +166,26 @@ size_t File::readAhead(char *buffer, size_t max, char needle) { return -1; } -bool_t File::writeString(std::string in) { +size_t File::readToBuffer(char **buffer) { if(!this->isOpen()) { - if(!this->open(FILE_MODE_WRITE)) return false; + if(!this->open(FILE_MODE_READ)) return 0; } + assertTrue(this->mode == FILE_MODE_READ); + + if((*buffer) == nullptr) *buffer = (char*)malloc(this->length); + fseek(this->file, 0, SEEK_SET); + auto l = fread((*buffer), sizeof(char), this->length, this->file); + return l; +} + +bool_t File::writeString(std::string in) { + if(!this->isOpen() && !this->open(FILE_MODE_WRITE)) return false; assertTrue(this->mode == FILE_MODE_WRITE); return this->writeRaw((char *)in.c_str(), in.size()) && this->length == in.size(); } bool_t File::writeRaw(char *data, size_t len) { - if(!this->isOpen()) { - if(!this->open(FILE_MODE_WRITE)) return false; - } + if(!this->isOpen() && !this->open(FILE_MODE_WRITE)) return false; assertTrue(this->mode == FILE_MODE_WRITE); this->length = fwrite(data, sizeof(char_t), len, this->file); return true; diff --git a/src/dawntools/util/File.hpp b/src/dawntools/util/File.hpp index d92add27..0ff97515 100644 --- a/src/dawntools/util/File.hpp +++ b/src/dawntools/util/File.hpp @@ -109,6 +109,15 @@ namespace Dawn { char needle ); + /** + * Reads the contents of this file into a given buffer. If buffer is null + * then the buffer will be allocated and returned. + * + * @param buffer Pointer to buffer to read to. + * @return The size of the read data. + */ + size_t readToBuffer(char **buffer); + /** * Writes the entire contents of a string to a file. *