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.
*