From 6069c713848305b18a2df7e2dad060dafc723a98 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sun, 21 May 2023 23:35:39 -0700 Subject: [PATCH] Prepping to allow textures to have different render modes/types. Prepping for freetype support --- .gitmodules | 3 + assets/ark-pixel.ttf | Bin 187780 -> 0 bytes lib/CMakeLists.txt | 3 + lib/freetype | 1 + src/dawn/CMakeLists.txt | 1 + src/dawn/asset/assets/TextureAsset.cpp | 87 +++++++++-- src/dawn/asset/assets/TextureAsset.hpp | 17 +++ src/dawn/asset/assets/TrueTypeAsset.cpp | 2 +- src/dawn/display/_Texture.hpp | 45 +++++- src/dawn/display/font/ExampleFont.cpp | 2 +- src/dawnliminal/CMakeLists.txt | 4 +- src/dawnopengl/display/Texture.cpp | 138 +++++++++++++++--- src/dawnopengl/display/Texture.hpp | 7 +- .../display/TextureRenderTarget.cpp | 2 +- src/dawntools/texturetool/CMakeLists.txt | 33 ++++- src/dawntools/texturetool/TextureTool.cpp | 45 +++++- src/dawntools/texturetool/TextureTool.hpp | 1 + src/dawntools/util/DawnTool.cpp | 1 + 18 files changed, 344 insertions(+), 48 deletions(-) delete mode 100644 assets/ark-pixel.ttf create mode 160000 lib/freetype diff --git a/.gitmodules b/.gitmodules index 442ca0ff..fb40d0ce 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "lib/AudioFile"] path = lib/AudioFile url = https://github.com/adamstark/AudioFile.git +[submodule "lib/freetype"] + path = lib/freetype + url = https://gitlab.freedesktop.org/freetype/freetype.git diff --git a/assets/ark-pixel.ttf b/assets/ark-pixel.ttf deleted file mode 100644 index 5e1d3e28b3f42f25ed45d6adb724347b26d42b06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 187780 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 IQ?=Uv0d+RJBLDyZ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 6ce1a1b4..4c1f567d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -22,6 +22,9 @@ add_subdirectory(glm) add_library(stb INTERFACE) target_include_directories(stb INTERFACE stb) +# FreeType +add_subdirectory(freetype) + # OpenAL if(DAWN_TARGET_OPENAL) set(LIBTYPE "STATIC") diff --git a/lib/freetype b/lib/freetype new file mode 160000 index 00000000..562f3481 --- /dev/null +++ b/lib/freetype @@ -0,0 +1 @@ +Subproject commit 562f34819229080abb05b4e7ae7e9e47fc84c6eb diff --git a/src/dawn/CMakeLists.txt b/src/dawn/CMakeLists.txt index ba848087..ca965749 100644 --- a/src/dawn/CMakeLists.txt +++ b/src/dawn/CMakeLists.txt @@ -8,6 +8,7 @@ target_link_libraries(${DAWN_TARGET_NAME} PUBLIC glm stb + freetype ) # Includes diff --git a/src/dawn/asset/assets/TextureAsset.cpp b/src/dawn/asset/assets/TextureAsset.cpp index cf882c2a..190acb93 100644 --- a/src/dawn/asset/assets/TextureAsset.cpp +++ b/src/dawn/asset/assets/TextureAsset.cpp @@ -20,8 +20,16 @@ void TextureAsset::updateSync() { ) return; this->state = 0x04; - this->texture.setSize(this->width, this->height); + + + this->texture.setSize(this->width, this->height, this->format); this->texture.buffer(this->colors); + + this->texture.wrapModeX = this->wrapModeX; + this->texture.wrapModeY = this->wrapModeY; + this->texture.filterModeMin = this->filterModeMin; + this->texture.filterModeMag = this->filterModeMag; + this->state = 0x05; this->loaded = true; } @@ -33,24 +41,83 @@ void TextureAsset::updateAsync() { this->state = 0x02; // Parse header data. - char integer[32]; + char integer[256]; size_t j = 0, i = 0; + enum TextureAssetHeaderParseState parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_VERSION; while(true) { + if(parseState == TEXTURE_ASSET_HEADER_PARSE_STATE_END) break; + auto c = this->buffer[i++]; - if(c == '|') { - integer[j] = '\0'; - if(this->width == -1) { + if(c != '|') { + integer[j++] = c; + continue; + } + + integer[j] = '\0'; + + switch(parseState) { + case TEXTURE_ASSET_HEADER_PARSE_STATE_VERSION: { + auto compared = strcmp(integer, "DT_1.00"); + assertTrue(compared == 0); + j = 0; + parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_WIDTH; + break; + } + + case TEXTURE_ASSET_HEADER_PARSE_STATE_WIDTH: { this->width = atoi(integer); assertTrue(this->width > 0); j = 0; - continue; - } else { - this->height = atoi(integer); - assertTrue(this->height > 0); + parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_HEIGHT; break; } + + case TEXTURE_ASSET_HEADER_PARSE_STATE_HEIGHT: { + this->height = atoi(integer); + assertTrue(this->height > 0); + j = 0; + parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_FORMAT; + break; + } + + case TEXTURE_ASSET_HEADER_PARSE_STATE_FORMAT: { + this->format = (enum TextureFormat)atoi(integer); + j = 0; + parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_WRAP_MODE_X; + break; + } + + case TEXTURE_ASSET_HEADER_PARSE_STATE_WRAP_MODE_X: { + this->wrapModeX = (enum TextureWrapMode)atoi(integer); + j = 0; + parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_WRAP_MODE_Y; + break; + } + + case TEXTURE_ASSET_HEADER_PARSE_STATE_WRAP_MODE_Y: { + this->wrapModeY = (enum TextureWrapMode)atoi(integer); + j = 0; + parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_FILTER_MODE_MIN; + break; + } + + case TEXTURE_ASSET_HEADER_PARSE_STATE_FILTER_MODE_MIN: { + this->filterModeMin = (enum TextureFilterMode)atoi(integer); + j = 0; + parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_FILTER_MODE_MAG; + break; + } + + case TEXTURE_ASSET_HEADER_PARSE_STATE_FILTER_MODE_MAG: { + this->filterModeMag = (enum TextureFilterMode)atoi(integer); + j = 0; + parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_END; + break; + } + + default: + assertUnreachable(); } - integer[j++] = c; } this->colors = (struct Color *)((void *)(this->buffer + i)); diff --git a/src/dawn/asset/assets/TextureAsset.hpp b/src/dawn/asset/assets/TextureAsset.hpp index d21c9e35..4c327879 100644 --- a/src/dawn/asset/assets/TextureAsset.hpp +++ b/src/dawn/asset/assets/TextureAsset.hpp @@ -9,12 +9,29 @@ #include "display/Texture.hpp" namespace Dawn { + enum TextureAssetHeaderParseState { + TEXTURE_ASSET_HEADER_PARSE_STATE_VERSION, + TEXTURE_ASSET_HEADER_PARSE_STATE_WIDTH, + TEXTURE_ASSET_HEADER_PARSE_STATE_HEIGHT, + TEXTURE_ASSET_HEADER_PARSE_STATE_FORMAT, + TEXTURE_ASSET_HEADER_PARSE_STATE_WRAP_MODE_X, + TEXTURE_ASSET_HEADER_PARSE_STATE_WRAP_MODE_Y, + TEXTURE_ASSET_HEADER_PARSE_STATE_FILTER_MODE_MIN, + TEXTURE_ASSET_HEADER_PARSE_STATE_FILTER_MODE_MAG, + TEXTURE_ASSET_HEADER_PARSE_STATE_END + }; + class TextureAsset : public Asset { protected: AssetLoader loader; uint8_t *buffer = nullptr; int32_t width = -1, height = -1; struct Color *colors; + enum TextureFormat format; + enum TextureWrapMode wrapModeX; + enum TextureWrapMode wrapModeY; + enum TextureFilterMode filterModeMin; + enum TextureFilterMode filterModeMag; public: Texture texture; diff --git a/src/dawn/asset/assets/TrueTypeAsset.cpp b/src/dawn/asset/assets/TrueTypeAsset.cpp index 73ccd8c9..a1ba7801 100644 --- a/src/dawn/asset/assets/TrueTypeAsset.cpp +++ b/src/dawn/asset/assets/TrueTypeAsset.cpp @@ -15,7 +15,7 @@ TrueTypeAsset::TrueTypeAsset(AssetManager *assMan, std::string name) : void TrueTypeAsset::updateSync() { if(this->state != 0x04) return; - this->font.texture.setSize(this->width, this->height); + this->font.texture.setSize(this->width, this->height, TEXTURE_FORMAT_RGBA); this->font.texture.buffer(this->pixels); auto i = this->pixels; memoryCopy( diff --git a/src/dawn/display/_Texture.hpp b/src/dawn/display/_Texture.hpp index b66d3959..f54626cf 100644 --- a/src/dawn/display/_Texture.hpp +++ b/src/dawn/display/_Texture.hpp @@ -5,10 +5,46 @@ #pragma once #include "display/Color.hpp" +#include "state/StateOwner.hpp" namespace Dawn { - class ITexture { + enum TextureFormat { + TEXTURE_FORMAT_R = 1, + TEXTURE_FORMAT_RG = 2, + TEXTURE_FORMAT_RGB = 3, + TEXTURE_FORMAT_RGBA = 4 + }; + + enum TextureWrapMode { + TEXTURE_WRAP_MODE_REPEAT = 0, + TEXTURE_WRAP_MODE_MIRRORED_REPEAT = 1, + TEXTURE_WRAP_MODE_CLAMP_TO_EDGE = 2, + TEXTURE_WRAP_MODE_CLAMP_TO_BORDER = 3 + }; + + enum TextureFilterMode { + TEXTURE_FILTER_MODE_NEAREST = 0, + TEXTURE_FILTER_MODE_LINEAR = 1 + }; + + class ITexture : public StateOwner { + protected: + bool_t texturePropertiesNeedUpdating = true; + public: + StateProperty wrapModeX; + StateProperty wrapModeY; + StateProperty filterModeMin; + StateProperty filterModeMag; + + ITexture() : + wrapModeX(TEXTURE_WRAP_MODE_CLAMP_TO_EDGE), + wrapModeY(TEXTURE_WRAP_MODE_CLAMP_TO_EDGE), + filterModeMin(TEXTURE_FILTER_MODE_LINEAR), + filterModeMag(TEXTURE_FILTER_MODE_LINEAR) + { + } + /** * Returns the width of the texture. * @@ -28,8 +64,13 @@ namespace Dawn { * * @param width Width of the texture (in pixels). * @param height Height of the texture (in pixels). + * @param format Data format of the texture to use. */ - virtual void setSize(int32_t width, int32_t height) = 0; + virtual void setSize( + int32_t width, + int32_t height, + enum TextureFormat format + ) = 0; /** * Fill a texture with a single color. This is stupidly costly. diff --git a/src/dawn/display/font/ExampleFont.cpp b/src/dawn/display/font/ExampleFont.cpp index 48a07a31..41bc271c 100644 --- a/src/dawn/display/font/ExampleFont.cpp +++ b/src/dawn/display/font/ExampleFont.cpp @@ -99,6 +99,6 @@ void ExampleFont::init() { pixels[j++] = this->getColor(n & 0x01); } - this->realTexture.setSize(128, 64); + this->realTexture.setSize(128, 64, TEXTURE_FORMAT_RGBA); this->realTexture.buffer(pixels); } diff --git a/src/dawnliminal/CMakeLists.txt b/src/dawnliminal/CMakeLists.txt index c0224a20..261a3063 100644 --- a/src/dawnliminal/CMakeLists.txt +++ b/src/dawnliminal/CMakeLists.txt @@ -20,8 +20,8 @@ add_subdirectory(save) set(LIMINAL_ASSETS_DIR ${DAWN_ASSETS_DIR}/games/liminal) tool_truetype(font_main ${LIMINAL_ASSETS_DIR}/fonts/Ysabeau-Medium.ttf) -tool_texture(texture_eth ${LIMINAL_ASSETS_DIR}/textures/eth.png) -tool_texture(texture_border ${LIMINAL_ASSETS_DIR}/textures/texture_test.png) +tool_texture(texture_eth FILE=${LIMINAL_ASSETS_DIR}/textures/eth.png) +tool_texture(texture_border FILE=${LIMINAL_ASSETS_DIR}/textures/texture_test.png) tool_scene(${LIMINAL_ASSETS_DIR}/scenes/SceneBase.xml) tool_vnscene(${LIMINAL_ASSETS_DIR}/scenes/Scene1Prologue0.xml) diff --git a/src/dawnopengl/display/Texture.cpp b/src/dawnopengl/display/Texture.cpp index 60809e86..3a865dbe 100644 --- a/src/dawnopengl/display/Texture.cpp +++ b/src/dawnopengl/display/Texture.cpp @@ -7,10 +7,18 @@ using namespace Dawn; +Texture::Texture() : ITexture() { +} + void Texture::bind(textureslot_t slot) { assertTrue(this->id != -1); glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(GL_TEXTURE_2D, this->id); + + if(this->texturePropertiesNeedUpdating) { + this->updateTextureProperties(); + this->texturePropertiesNeedUpdating = false; + } } int32_t Texture::getWidth() { @@ -21,56 +29,140 @@ int32_t Texture::getHeight() { return this->height; } -void Texture::setSize(int32_t width, int32_t height) { +void Texture::setSize(int32_t width, int32_t height, enum TextureFormat format) { if(this->id != -1) glDeleteTextures(1, &this->id); this->width = width; this->height = height; + this->format = format; glGenTextures(1, &this->id); if(this->id <= 0) throw "Texture generation failed!"; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, this->id); - - // Setup our preferred texture params, later this will be configurable. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // Initialize the texture to blank - glTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, - width, height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL - ); + glActiveTexture(GL_TEXTURE0); + this->bufferRaw(NULL); } void Texture::fill(struct Color color) { struct Color *pixels = (struct Color *)memoryAllocate( sizeof(struct Color) * this->width * this->height ); - this->buffer(pixels); - memoryFree(pixels); } bool_t Texture::isReady() { return this->id != -1; } - -void Texture::buffer(struct Color pixels[]) { + +void Texture::updateTextureProperties() { + switch(((enum TextureWrapMode)this->wrapModeX)) { + case TEXTURE_WRAP_MODE_REPEAT: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + break; + + case TEXTURE_WRAP_MODE_MIRRORED_REPEAT: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + break; + + case TEXTURE_WRAP_MODE_CLAMP_TO_EDGE: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + break; + + case TEXTURE_WRAP_MODE_CLAMP_TO_BORDER: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + break; + + default: + assertUnreachable(); + } + + switch(((enum TextureWrapMode)this->wrapModeY)) { + case TEXTURE_WRAP_MODE_REPEAT: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T ,GL_REPEAT); + break; + + case TEXTURE_WRAP_MODE_MIRRORED_REPEAT: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + break; + + case TEXTURE_WRAP_MODE_CLAMP_TO_EDGE: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + break; + + case TEXTURE_WRAP_MODE_CLAMP_TO_BORDER: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + break; + + default: + assertUnreachable(); + } + + switch(((enum TextureFilterMode)this->filterModeMin)) { + case TEXTURE_FILTER_MODE_NEAREST: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + break; + + case TEXTURE_FILTER_MODE_LINEAR: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + break; + + default: + assertUnreachable(); + } + + switch(((enum TextureFilterMode)this->filterModeMag)) { + case TEXTURE_FILTER_MODE_NEAREST: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); + break; + + case TEXTURE_FILTER_MODE_LINEAR: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); + break; + + default: + assertUnreachable(); + } +} + +void Texture::bufferRaw(void *data) { + assertTrue(this->isReady()); glBindTexture(GL_TEXTURE_2D, this->id); + GLenum format; + switch(this->format) { + case TEXTURE_FORMAT_R: + format = GL_RED; + break; + + case TEXTURE_FORMAT_RG: + format = GL_RG; + break; + + case TEXTURE_FORMAT_RGB: + format = GL_RGB; + break; + + case TEXTURE_FORMAT_RGBA: + format = GL_RGBA; + break; + + default: + assertUnreachable(); + } + glTexImage2D( - GL_TEXTURE_2D, 0, GL_RGBA, + GL_TEXTURE_2D, 0, format, this->width, this->height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixels + 0, format, GL_UNSIGNED_BYTE, data ); + glGenerateMipmap(GL_TEXTURE_2D); + this->texturePropertiesNeedUpdating = true; +} + +void Texture::buffer(struct Color pixels[]) { + this->bufferRaw((void*)pixels); } Texture::~Texture() { diff --git a/src/dawnopengl/display/Texture.hpp b/src/dawnopengl/display/Texture.hpp index b292c864..56d3785b 100644 --- a/src/dawnopengl/display/Texture.hpp +++ b/src/dawnopengl/display/Texture.hpp @@ -19,11 +19,16 @@ namespace Dawn { int32_t width = -1; int32_t height = -1; GLuint id = -1; + enum TextureFormat format; + + void updateTextureProperties(); + void bufferRaw(void *data); public: + Texture(); int32_t getWidth() override; int32_t getHeight() override; - void setSize(int32_t width, int32_t height) override; + void setSize(int32_t width, int32_t height, enum TextureFormat format) override; void fill(struct Color) override; bool_t isReady() override; void buffer(struct Color pixels[]) override; diff --git a/src/dawnopengl/display/TextureRenderTarget.cpp b/src/dawnopengl/display/TextureRenderTarget.cpp index 94f709ac..d04ee6e0 100644 --- a/src/dawnopengl/display/TextureRenderTarget.cpp +++ b/src/dawnopengl/display/TextureRenderTarget.cpp @@ -26,7 +26,7 @@ void TextureRenderTarget::setSize(float_t width, float_t height) { if(this->fboId != -1) glDeleteFramebuffers(1, &this->fboId); // Resize texture - this->texture.setSize((int32_t)width, (int32_t) height); + this->texture.setSize((int32_t)width, (int32_t)height, TEXTURE_FORMAT_RGBA); this->eventRenderTargetResized.invoke(this, width, height); // Create Frame Buffer diff --git a/src/dawntools/texturetool/CMakeLists.txt b/src/dawntools/texturetool/CMakeLists.txt index f343a691..31744395 100644 --- a/src/dawntools/texturetool/CMakeLists.txt +++ b/src/dawntools/texturetool/CMakeLists.txt @@ -38,15 +38,42 @@ target_link_libraries(texturetool ) # Tool Function -function(tool_texture target in) +function(tool_texture target) + # Defaults + set(FILE "" ) + set(FILTER_MIN "") + set(FILTER_MAG "") + set(WRAP_X "") + set(WRAP_Y "") + + # Parse Args + foreach(_PAIR IN LISTS ARGN) + if (_PAIR MATCHES "^([^:]+)=(.*)$") + set(${CMAKE_MATCH_1} ${CMAKE_MATCH_2}) + else() + message(FATAL_ERROR "Invalid pair: ${_PAIR}") + endif() + endforeach() + + # Check for missing args + if(NOT DEFINED FILE) + message(FATAL_ERROR "Missing FILE input") + endif() + set(DEPS "") if(DAWN_BUILD_TOOLS) set(DEPS texturetool) endif() add_custom_target(${target} - COMMAND texturetool --input="${DAWN_ASSETS_SOURCE_DIR}/${in}" --output="${DAWN_ASSETS_BUILD_DIR}/${target}" - COMMENT "Generating texture ${target} from ${in}" + COMMAND texturetool + --input="${DAWN_ASSETS_SOURCE_DIR}/${FILE}" + --output="${DAWN_ASSETS_BUILD_DIR}/${target}" + --wrapX="${WRAP_X}" + --wrapY="${WRAP_Y}" + --filterMin="${FILTER_MIN}" + --filterMag="${FILTER_MIN}" + COMMENT "Generating texture ${target} from ${FILE}" DEPENDS ${DEPS} ) add_dependencies(${DAWN_TARGET_NAME} ${target}) diff --git a/src/dawntools/texturetool/TextureTool.cpp b/src/dawntools/texturetool/TextureTool.cpp index 9b66163c..c930107c 100644 --- a/src/dawntools/texturetool/TextureTool.cpp +++ b/src/dawntools/texturetool/TextureTool.cpp @@ -11,6 +11,15 @@ std::vector TextureTool::getRequiredFlags() { return std::vector{ "input", "output" }; } +std::map TextureTool::getOptionalFlags() { + return { + { "wrapX", "clamp" }, + { "wrapY", "clamp" }, + { "filterMin", "linear" }, + { "filterMax", "linear" } + }; +} + int32_t TextureTool::start() { // Finished with XML data, now we can write data out. File fileOut(flags["output"] + ".texture"); @@ -40,6 +49,38 @@ int32_t TextureTool::start() { } stbi_image_free(imageRaw); + std::function wrapFromString = [&](std::string wr) { + if(wr == "repeat") return 0; + if(wr == "mirror") return 1; + if(wr == "clamp") return 2; + if(wr == "border") return 3; + return -1; + }; + + int32_t wrapX = wrapFromString(flags["wrapX"]); + if(wrapX == -1) { + std::cout << "Invalid wrapX value " << flags["wrapX"] << std::endl; + return 1; + } + + int32_t wrapY = wrapFromString(flags["wrapY"]); + if(wrapY == -1) { + std::cout << "Invalid wrapY value " << flags["wrapY"] << std::endl; + return 1; + } + + // Write info + char headerBuffer[256]; + size_t headerBufferLength = sprintf((char *)headerBuffer, "DT_1.00|%i|%i|%i|%i|%i|%i|%i|", + w, + h, + 4, // RGBA, + wrapX, // WRAPX + wrapY, // WRAPY + flags["filterMin"] == "nearest" ? 0 : 1, + flags["filterMag"] == "nearest" ? 0 : 1 + ); + // Open and create output File out(flags["output"] + ".texture"); if(!out.mkdirp()) { @@ -50,10 +91,6 @@ int32_t TextureTool::start() { std::cout << "Failed to open texture file for writing " << out.filename << std::endl; return 1; } - - // Write info - char headerBuffer[64]; - size_t headerBufferLength = sprintf((char *)headerBuffer, "%i|%i|", w, h); if(!out.writeRaw(headerBuffer, headerBufferLength)) { std::cout << "Failed to write texture header for " << out.filename << std::endl; return 1; diff --git a/src/dawntools/texturetool/TextureTool.hpp b/src/dawntools/texturetool/TextureTool.hpp index 911f8f39..1e7114e7 100644 --- a/src/dawntools/texturetool/TextureTool.hpp +++ b/src/dawntools/texturetool/TextureTool.hpp @@ -12,6 +12,7 @@ namespace Dawn { class TextureTool : public DawnTool { protected: std::vector getRequiredFlags() override; + std::map getOptionalFlags() override; public: int32_t start(); diff --git a/src/dawntools/util/DawnTool.cpp b/src/dawntools/util/DawnTool.cpp index 661273d9..02af162b 100644 --- a/src/dawntools/util/DawnTool.cpp +++ b/src/dawntools/util/DawnTool.cpp @@ -51,6 +51,7 @@ int32_t DawnTool::exec(const int32_t argc, const char *argv[]) { // Get prefix and val and store auto prefix = flag.substr(0, equalPos); auto val = flag.substr(equalPos + 1); + if(val.size() == 0) continue; flags[prefix] = val; }