Almost done with new language tools
This commit is contained in:
116
src/dawntools/tools/CMakeLists.txt
Normal file
116
src/dawntools/tools/CMakeLists.txt
Normal file
@ -0,0 +1,116 @@
|
||||
# Copyright (c) 2023 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
add_subdirectory(texturegen)
|
||||
add_subdirectory(tilesetgen)
|
||||
add_subdirectory(truetypegen)
|
||||
add_subdirectory(uigen)
|
||||
add_subdirectory(languagegen)
|
||||
add_subdirectory(audiogen)
|
||||
add_subdirectory(generatedlanguages)
|
||||
|
||||
# Settings
|
||||
set(DAWN_TOOL_GENERATED_LANG_DIR "${DAWN_TEMP_DIR}/languages" CACHE INTERNAL ${DAWN_CACHE_TARGET})
|
||||
|
||||
# Texture Tool
|
||||
function(tool_texture target in)
|
||||
add_custom_target(${target}
|
||||
COMMAND texturegen --input="${DAWN_ASSETS_SOURCE_DIR}/${in}" --output="${DAWN_ASSETS_BUILD_DIR}/${target}"
|
||||
COMMENT "Generating texture ${target} from ${in}"
|
||||
DEPENDS texturegen
|
||||
)
|
||||
add_dependencies(${DAWN_TARGET_NAME} ${target})
|
||||
endfunction()
|
||||
|
||||
# Tileset Tool
|
||||
function(tool_tileset targetTileset targetTexture in cols rows)
|
||||
tool_texture(${targetTexture} ${in})
|
||||
add_custom_target(${targetTileset}
|
||||
COMMAND tilesetgen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${targetTileset}" "${cols}" "${rows}"
|
||||
COMMENT "Generating tileset ${target} from ${in}"
|
||||
DEPENDS tilesetgen ${targetTexture}
|
||||
)
|
||||
add_dependencies(${DAWN_TARGET_NAME} ${targetTileset})
|
||||
endfunction()
|
||||
|
||||
# TrueType Tool
|
||||
function(tool_truetype target in out width height fontSize)
|
||||
add_custom_target(${target}
|
||||
COMMAND truetypegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}/${out}" "${width}" "${height}" "${fontSize}"
|
||||
COMMENT "Generating truetype ${target} from ${in}"
|
||||
DEPENDS truetypegen
|
||||
)
|
||||
add_dependencies(${DAWN_TARGET_NAME} ${target})
|
||||
endfunction()
|
||||
|
||||
# UI Tool
|
||||
function(tool_ui target in)
|
||||
add_custom_target(${target}
|
||||
COMMAND uigen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_GENERATED_DIR}/ui/${target}"
|
||||
COMMENT "Generating ui ${target} from ${in}"
|
||||
DEPENDS uigen
|
||||
)
|
||||
target_include_directories(${DAWN_TARGET_NAME}
|
||||
PUBLIC
|
||||
${DAWN_GENERATED_DIR}/ui
|
||||
)
|
||||
add_dependencies(${DAWN_TARGET_NAME} ${target})
|
||||
endfunction()
|
||||
|
||||
# Generated Language Rollup Tool
|
||||
function(tool_generatedlanguages in)
|
||||
add_custom_target(generatedlanguages
|
||||
COMMAND generatedlanguagestool --input="${DAWN_TOOL_GENERATED_LANG_DIR}" --output="${DAWN_ASSETS_BUILD_DIR}"
|
||||
COMMENT "Generating all languages"
|
||||
DEPENDS generatedlanguagestool
|
||||
)
|
||||
|
||||
if(NOT generatedlanguages IN_LIST DAWN_TARGET_DEPENDENCIES_LAST)
|
||||
set(
|
||||
DAWN_TARGET_DEPENDENCIES_LAST
|
||||
generatedlanguages
|
||||
CACHE INTERNAL ${DAWN_CACHE_TARGET}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Language Tool
|
||||
function(tool_language target in)
|
||||
add_custom_target(${target}
|
||||
COMMAND languagegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}"
|
||||
COMMENT "Generating language set ${target} from ${in}"
|
||||
DEPENDS languagegen
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Audio Tool
|
||||
function(tool_audio target in)
|
||||
add_custom_target(${target}
|
||||
COMMAND audiogen --input="${DAWN_ASSETS_SOURCE_DIR}/${in}" --output="${DAWN_ASSETS_BUILD_DIR}/${target}"
|
||||
COMMENT "Generating audio ${target} from ${in}"
|
||||
DEPENDS audiogen
|
||||
)
|
||||
add_dependencies(${DAWN_TARGET_NAME} ${target})
|
||||
endfunction()
|
||||
|
||||
|
||||
if(DAWN_VISUAL_NOVEL)
|
||||
add_subdirectory(vnscenegen)
|
||||
|
||||
# VN Scene Tool
|
||||
function(tool_vnscene target in)
|
||||
tool_generatedlanguages("${DAWN_TOOL_GENERATED_LANG_DIR}/${target}.language")
|
||||
add_custom_target(${target}
|
||||
COMMAND vnscenegen --input="${DAWN_ASSETS_SOURCE_DIR}/${in}" --output="${DAWN_GENERATED_DIR}/scenes/${target}" --language-out="${DAWN_TOOL_GENERATED_LANG_DIR}/${target}.language"
|
||||
COMMENT "Generating VN Scene ${target} from ${in}"
|
||||
DEPENDS vnscenegen
|
||||
)
|
||||
target_include_directories(${DAWN_TARGET_NAME}
|
||||
PUBLIC
|
||||
${DAWN_GENERATED_DIR}
|
||||
)
|
||||
add_dependencies(${DAWN_TARGET_NAME} ${target})
|
||||
endfunction()
|
||||
endif()
|
60
src/dawntools/tools/audiogen/AudioGen.cpp
Normal file
60
src/dawntools/tools/audiogen/AudioGen.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "AudioGen.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::string> AudioGen::getRequiredFlags() {
|
||||
return std::vector<std::string>{ "input", "output" };
|
||||
}
|
||||
|
||||
int32_t AudioGen::start() {
|
||||
// Finished with XML data, now we can write data out.
|
||||
File fileOut(flags["output"] + ".audio");
|
||||
if(fileOut.exists()) return 0;
|
||||
|
||||
// Load input file
|
||||
AudioFile<double> audioFile;
|
||||
if(!audioFile.load(flags["input"])) {
|
||||
printf("Failed to load audio file.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Open Output File
|
||||
fileOut.mkdirp();
|
||||
if(!fileOut.open(FILE_MODE_WRITE)) {
|
||||
std::cout << "Failed to open " << fileOut.filename << " output for writing" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Write Header
|
||||
char buffer[FILE_BUFFER_SIZE];
|
||||
sprintf(buffer, "%i|%i|%i|%i|",
|
||||
audioFile.getNumChannels(),
|
||||
audioFile.getSampleRate(),
|
||||
audioFile.getNumSamplesPerChannel(),
|
||||
audioFile.getNumSamplesPerChannel() * audioFile.getNumChannels()*(
|
||||
sizeof(int16_t) / sizeof(uint8_t)
|
||||
)
|
||||
);
|
||||
auto bufferLength = strlen(buffer);
|
||||
fileOut.writeRaw(buffer, bufferLength);
|
||||
|
||||
// Convert Data to 16 bit audio
|
||||
for (int32_t i = 0; i < audioFile.getNumSamplesPerChannel(); i++) {
|
||||
for(int32_t y = 0; y < audioFile.getNumChannels(); y++) {
|
||||
double sample = audioFile.samples[y][i];
|
||||
sample = sample < -1 ? -1 : sample > 1 ? 1 : sample;
|
||||
auto q = static_cast<int16_t> (sample * 32767.);
|
||||
|
||||
buffer[0] = (q >> 8) & 0xFF;
|
||||
buffer[1] = q & 0xFF;
|
||||
fileOut.writeRaw(buffer, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
src/dawntools/tools/audiogen/AudioGen.hpp
Normal file
19
src/dawntools/tools/audiogen/AudioGen.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
// 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 "AudioFile.h"
|
||||
|
||||
namespace Dawn {
|
||||
class AudioGen : public DawnTool {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredFlags() override;
|
||||
|
||||
public:
|
||||
int32_t start();
|
||||
};
|
||||
}
|
38
src/dawntools/tools/audiogen/CMakeLists.txt
Normal file
38
src/dawntools/tools/audiogen/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2023 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
project(audiogen VERSION 1.0)
|
||||
add_executable(audiogen)
|
||||
|
||||
# Sources
|
||||
target_sources(audiogen
|
||||
PRIVATE
|
||||
${DAWN_SHARED_SOURCES}
|
||||
${DAWN_TOOL_SOURCES}
|
||||
AudioGen.cpp
|
||||
)
|
||||
|
||||
# Includes
|
||||
target_include_directories(audiogen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_INCLUDES}
|
||||
${DAWN_TOOL_INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
# Definitions
|
||||
target_compile_definitions(audiogen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_DEFINITIONS}
|
||||
DAWN_TOOL_INSTANCE=AudioGen
|
||||
DAWN_TOOL_HEADER="AudioGen.hpp"
|
||||
)
|
||||
|
||||
# Libraries
|
||||
target_link_libraries(audiogen
|
||||
PUBLIC
|
||||
${DAWN_BUILD_HOST_LIBS}
|
||||
AudioFile
|
||||
)
|
34
src/dawntools/tools/generatedlanguages/CMakeLists.txt
Normal file
34
src/dawntools/tools/generatedlanguages/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright (c) 2023 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Generated Languages Tool
|
||||
project(generatedlanguagestool VERSION 1.0)
|
||||
add_executable(generatedlanguagestool)
|
||||
|
||||
target_sources(generatedlanguagestool
|
||||
PRIVATE
|
||||
${DAWN_SHARED_SOURCES}
|
||||
${DAWN_TOOL_SOURCES}
|
||||
GeneratedLanguages.cpp
|
||||
)
|
||||
|
||||
target_include_directories(generatedlanguagestool
|
||||
PUBLIC
|
||||
${DAWN_SHARED_INCLUDES}
|
||||
${DAWN_TOOL_INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
target_compile_definitions(generatedlanguagestool
|
||||
PUBLIC
|
||||
${DAWN_SHARED_DEFINITIONS}
|
||||
DAWN_TOOL_INSTANCE=GeneratedLanguages
|
||||
DAWN_TOOL_HEADER="GeneratedLanguages.hpp"
|
||||
)
|
||||
|
||||
target_link_libraries(generatedlanguagestool
|
||||
PUBLIC
|
||||
${DAWN_BUILD_HOST_LIBS}
|
||||
)
|
@ -0,0 +1,25 @@
|
||||
// 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/Xml.hpp"
|
||||
#include "util/File.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class GeneratedLanguages : public DawnTool {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredFlags() override;
|
||||
|
||||
int32_t scanDir(
|
||||
std::string dir,
|
||||
std::string *error,
|
||||
std::vector<std::string> *files
|
||||
);
|
||||
|
||||
public:
|
||||
int32_t start() override;
|
||||
};
|
||||
}
|
37
src/dawntools/tools/languagegen/CMakeLists.txt
Normal file
37
src/dawntools/tools/languagegen/CMakeLists.txt
Normal file
@ -0,0 +1,37 @@
|
||||
# Copyright (c) 2021 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Texture Build Tool
|
||||
project(languagegen VERSION 2.0)
|
||||
add_executable(languagegen)
|
||||
target_sources(languagegen
|
||||
PRIVATE
|
||||
${DAWN_SHARED_SOURCES}
|
||||
LanguageGen.cpp
|
||||
../../util/DawnTool.cpp
|
||||
../../util/File.cpp
|
||||
|
||||
../../util/file.cpp
|
||||
../../util/csv.cpp
|
||||
../../util/xml.cpp
|
||||
)
|
||||
|
||||
target_include_directories(languagegen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
target_compile_definitions(languagegen
|
||||
PUBLIC
|
||||
DAWN_TOOL_INSTANCE=LanguageGen
|
||||
DAWN_TOOL_HEADER="LanguageGen.hpp"
|
||||
)
|
||||
|
||||
target_link_libraries(languagegen
|
||||
PUBLIC
|
||||
${DAWN_BUILD_HOST_LIBS}
|
||||
)
|
170
src/dawntools/tools/languagegen/LanguageGen.cpp
Normal file
170
src/dawntools/tools/languagegen/LanguageGen.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "LanguageGen.hpp"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
auto fileIn = File(this->args[1]);
|
||||
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);
|
||||
|
||||
// Begin parsing. Start by looking for the <language> tags
|
||||
std::vector<std::string> 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;
|
||||
}
|
||||
|
||||
// Now begin actually parsing
|
||||
std::map<std::string, std::vector<struct LanguageString>> 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<std::string> 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<std::string> 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<std::string,std::vector<struct LanguageString>> *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<struct LanguageString>()));
|
||||
}
|
||||
(*strings)[attrLang->second].push_back(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t LanguageGen::parseGroup(
|
||||
Xml *groupNode,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<struct LanguageString>> *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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
34
src/dawntools/tools/languagegen/LanguageGen.hpp
Normal file
34
src/dawntools/tools/languagegen/LanguageGen.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// 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/Xml.hpp"
|
||||
#include "util/File.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct LanguageString {
|
||||
std::string key;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
class LanguageGen : public DawnTool {
|
||||
protected:
|
||||
int32_t parseGroup(
|
||||
Xml *node,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<struct LanguageString>> *strings
|
||||
);
|
||||
|
||||
int32_t parseString(
|
||||
Xml *node,
|
||||
std::string key,
|
||||
std::map<std::string, std::vector<struct LanguageString>> *strings
|
||||
);
|
||||
|
||||
public:
|
||||
int32_t start() override;
|
||||
};
|
||||
}
|
38
src/dawntools/tools/texturegen/CMakeLists.txt
Normal file
38
src/dawntools/tools/texturegen/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2021 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Texture Build Tool
|
||||
project(texturegen VERSION 1.0)
|
||||
add_executable(texturegen)
|
||||
|
||||
target_sources(texturegen
|
||||
PRIVATE
|
||||
${DAWN_SHARED_SOURCES}
|
||||
${DAWN_TOOL_SOURCES}
|
||||
TextureGen.cpp
|
||||
../../util/image.cpp
|
||||
)
|
||||
|
||||
target_include_directories(texturegen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_INCLUDES}
|
||||
${DAWN_TOOL_INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
# Definitions
|
||||
target_compile_definitions(texturegen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_DEFINITIONS}
|
||||
DAWN_TOOL_INSTANCE=TextureGen
|
||||
DAWN_TOOL_HEADER="TextureGen.hpp"
|
||||
)
|
||||
|
||||
|
||||
target_link_libraries(texturegen
|
||||
PUBLIC
|
||||
${DAWN_BUILD_HOST_LIBS}
|
||||
stb
|
||||
)
|
67
src/dawntools/tools/texturegen/TextureGen.cpp
Normal file
67
src/dawntools/tools/texturegen/TextureGen.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "TextureGen.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::string> TextureGen::getRequiredFlags() {
|
||||
return std::vector<std::string>{ "input", "output" };
|
||||
}
|
||||
|
||||
int32_t TextureGen::start() {
|
||||
// Finished with XML data, now we can write data out.
|
||||
File fileOut(flags["output"] + ".texture");
|
||||
if(fileOut.exists()) return 0;
|
||||
|
||||
// Load input file
|
||||
File in(flags["input"]);
|
||||
if(!in.open(FILE_MODE_READ)) return 1;
|
||||
|
||||
int w, h, channels;
|
||||
auto imageRaw = stbi_load_from_file(in.file, &w, &h, &channels, STBI_rgb_alpha);
|
||||
if(imageRaw == NULL) {
|
||||
std::cout << "Failed to load input texture!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
in.close();
|
||||
|
||||
// Convert to floating points
|
||||
size_t len = STBI_rgb_alpha * w * h;
|
||||
float_t *dataImage = (float_t*)malloc(sizeof(float) * len);
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
auto dataIn = imageRaw[i];
|
||||
dataImage[i] = ((float_t)dataIn) / 255.0f;
|
||||
}
|
||||
stbi_image_free(imageRaw);
|
||||
|
||||
// Open and create output
|
||||
File out(flags["output"] + ".texture");
|
||||
if(!out.mkdirp()) {
|
||||
std::cout << "Failed to make output dir " << out.filename << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if(!out.open(FILE_MODE_WRITE)) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Write texture
|
||||
if(!out.writeRaw((char *)dataImage, sizeof(float_t) * len)) {
|
||||
std::cout << "Failed to write texture data for " << out.filename << std::endl;
|
||||
return 1;
|
||||
}
|
||||
free(dataImage);
|
||||
|
||||
return 0;
|
||||
}
|
19
src/dawntools/tools/texturegen/TextureGen.hpp
Normal file
19
src/dawntools/tools/texturegen/TextureGen.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
// 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"
|
||||
|
||||
namespace Dawn {
|
||||
class TextureGen : public DawnTool {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredFlags() override;
|
||||
|
||||
public:
|
||||
int32_t start();
|
||||
};
|
||||
}
|
25
src/dawntools/tools/tilesetgen/CMakeLists.txt
Normal file
25
src/dawntools/tools/tilesetgen/CMakeLists.txt
Normal file
@ -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(tilesetgen VERSION 1.0)
|
||||
add_executable(tilesetgen)
|
||||
target_sources(tilesetgen
|
||||
PRIVATE
|
||||
main.cpp
|
||||
../../util/file.cpp
|
||||
../../util/image.cpp
|
||||
)
|
||||
target_include_directories(tilesetgen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
target_link_libraries(tilesetgen
|
||||
PUBLIC
|
||||
${DAWN_BUILD_HOST_LIBS}
|
||||
stb
|
||||
)
|
147
src/dawntools/tools/tilesetgen/main.cpp
Normal file
147
src/dawntools/tools/tilesetgen/main.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "dawnsharedlibs.hpp"
|
||||
#include "../../util/file.hpp"
|
||||
#include "../../util/image.hpp"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *in;
|
||||
char *out;
|
||||
FILE *file;
|
||||
char path[FILENAME_MAX + 1];
|
||||
int w, h, channels, cols, rows;
|
||||
stbi_uc *dataImageRaw;
|
||||
int gapX, gapY, borderX, borderY;
|
||||
|
||||
if(argc < 5) {
|
||||
printf("Invalid number of arguments");
|
||||
return 1;
|
||||
}
|
||||
|
||||
in = argv[1];
|
||||
out = argv[2];
|
||||
gapX = 0, gapY = 0, borderX = 0, borderY = 0;
|
||||
|
||||
cols = atoi(argv[3]);
|
||||
if(cols <= 0) {
|
||||
printf("Columns is invalid\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
rows = atoi(argv[4]);
|
||||
if(rows <= 0) {
|
||||
printf("Rows is invalid");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(argc >= 6) {
|
||||
gapX = atoi(argv[5]);
|
||||
if(gapX <= 0) {
|
||||
printf("Gap X is invalid\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(argc >= 7) {
|
||||
gapY = atoi(argv[6]);
|
||||
if(gapY <= 0) {
|
||||
printf("Gap Y is invalid\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(argc >= 8) {
|
||||
borderX = atoi(argv[7]);
|
||||
if(borderX <= 0) {
|
||||
printf("Border X is invalid\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(argc >= 9) {
|
||||
borderY = atoi(argv[8]);
|
||||
if(borderY <= 0) {
|
||||
printf("Border Y is invalid\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize slashes
|
||||
fileNormalizeSlashes(in);
|
||||
fileNormalizeSlashes(out);
|
||||
|
||||
// Check the output doesn't already exist
|
||||
sprintf(path, "%s.tileset", out);
|
||||
file = fopen(path, "rb");
|
||||
if(file != NULL) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read in the original texture
|
||||
file = fopen(in, "rb");
|
||||
if(file == NULL) {
|
||||
printf("Failed to open file!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read image data
|
||||
dataImageRaw = stbi_load_from_file(file, &w, &h, &channels, STBI_rgb_alpha);
|
||||
if(dataImageRaw == NULL) {
|
||||
printf("Failed to load input texture!\n");
|
||||
return 1;
|
||||
}
|
||||
fclose(file);
|
||||
free(dataImageRaw);
|
||||
|
||||
if(w <= 0 || h <= 0) {
|
||||
printf("Reading image failed (corrupted?)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Calculate division sizes (pixels)
|
||||
int divX = (w - (borderX * 2) - (gapX * (cols - 1))) / cols;
|
||||
int divY = (h - (borderY * 2) - (gapY * (rows - 1))) / rows;
|
||||
|
||||
// Calculate the division sizes (units)
|
||||
float tdivX = (float)divX / (float)w;
|
||||
float tdivY = (float)divY / (float)h;
|
||||
|
||||
// Output buffer prep
|
||||
char *buffer = (char *)malloc(sizeof(char) * (cols * rows * 48 + 48 + 48));
|
||||
buffer[0] = '\0';
|
||||
|
||||
sprintf(buffer, "%i|%i|%i|%i|", cols, rows, divX, divY);
|
||||
|
||||
// Now prep tileset.
|
||||
for(float y = 0; y < rows; y++) {
|
||||
for(float x = 0; x < cols; x++) {
|
||||
float ux0 = ((float)borderX + ((float)divX * x) + ((float)gapX * x)) / (float)w;
|
||||
float ux1 = ux0 + tdivX;
|
||||
float uy0 = ((float)borderY + ((float)divY * y) + ((float)gapY * y)) / (float)h;
|
||||
float uy1 = uy0 + tdivY;
|
||||
sprintf(buffer, "%s%f,%f,%f,%f|", buffer, ux0, ux1, uy0, uy1);
|
||||
}
|
||||
}
|
||||
|
||||
// Open output file
|
||||
fileMkdirp(path);
|
||||
file = fopen(path, "wb");
|
||||
if(file == NULL) {
|
||||
free(buffer);
|
||||
printf("Invalid tileset file out!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Write and close
|
||||
fwrite(buffer, sizeof(char), strlen(buffer), file);
|
||||
fclose(file);
|
||||
free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
25
src/dawntools/tools/truetypegen/CMakeLists.txt
Normal file
25
src/dawntools/tools/truetypegen/CMakeLists.txt
Normal file
@ -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(truetypegen VERSION 1.0)
|
||||
add_executable(truetypegen)
|
||||
target_sources(truetypegen
|
||||
PRIVATE
|
||||
main.cpp
|
||||
../../util/file.cpp
|
||||
../../util/image.cpp
|
||||
)
|
||||
target_include_directories(truetypegen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
target_link_libraries(truetypegen
|
||||
PUBLIC
|
||||
${DAWN_BUILD_HOST_LIBS}
|
||||
stb
|
||||
)
|
141
src/dawntools/tools/truetypegen/main.cpp
Normal file
141
src/dawntools/tools/truetypegen/main.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "dawnsharedlibs.hpp"
|
||||
#include "../../util/file.hpp"
|
||||
#include "../../util/image.hpp"
|
||||
#ifndef STB_TRUETYPE_IMPLEMENTATION
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include <stb_truetype.h>
|
||||
#endif
|
||||
|
||||
#define TRUETYPE_FIRST_CHAR 32
|
||||
#define TRUETYPE_NUM_CHARS 96
|
||||
|
||||
int main(int argc, char *args[]) {
|
||||
FILE *file;
|
||||
char path[FILENAME_MAX + 1];
|
||||
int32_t width, height, fontSize, textureSize;
|
||||
|
||||
/*
|
||||
args0 - PATH
|
||||
args1 - Input Filename (TTF file)
|
||||
args2 - Output Filename
|
||||
args3 - Width of the output texture (Resolution X)
|
||||
args4 - Height of the output texture (Resolution Y)
|
||||
args5 - Font size to draw
|
||||
*/
|
||||
|
||||
if(argc != 6) {
|
||||
printf("Invalid number of arguments\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *fileIn = args[1];
|
||||
char *fileOut = args[2];
|
||||
char *strWidth = args[3];
|
||||
char *strHeight = args[4];
|
||||
char *strFontSize = args[5];
|
||||
|
||||
// Normalize slashes
|
||||
fileNormalizeSlashes(fileIn);
|
||||
fileNormalizeSlashes(fileOut);
|
||||
|
||||
// Check the output doesn't already exist
|
||||
sprintf(path, "%s.truetype", fileOut);
|
||||
file = fopen(path, "rb");
|
||||
if(file != NULL) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
width = atoi(strWidth);
|
||||
if(width <= 0) {
|
||||
printf("Width is invalid.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
height = atoi(strHeight);
|
||||
if(height <= 0) {
|
||||
printf("Height is invalid.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fontSize = atoi(strFontSize);
|
||||
if(fontSize <= 0) {
|
||||
printf("Font size is invalid.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read in the TTF data
|
||||
file = fopen(fileIn, "rb");
|
||||
if(file == NULL) {
|
||||
printf("Failed to open input TTF 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
|
||||
char *ttfData = (char*)malloc(sizeof(char) * fileSize);
|
||||
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;
|
||||
}
|
||||
|
||||
// Create bitmap data. This is a single channel color (alpha).
|
||||
textureSize = width * height;
|
||||
stbi_uc *bitmapData = (stbi_uc*)malloc(sizeof(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.
|
||||
sprintf(path, "%s.truetype", fileOut);
|
||||
fileMkdirp(path);
|
||||
file = fopen(path, "wb");
|
||||
if(file == NULL) {
|
||||
printf("Failed to create output TTF file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Now prepare output data.
|
||||
char headerBuffer[64];
|
||||
int32_t headerBufferLength = sprintf(
|
||||
headerBuffer, "%i|%i|%i|", width, height, fontSize
|
||||
);
|
||||
fwrite(headerBuffer, sizeof(char), headerBufferLength, file);
|
||||
|
||||
// Write output pixels.
|
||||
float outputPixels[4];
|
||||
for(int32_t i = 0; i < textureSize; i++) {
|
||||
outputPixels[0] = 1.0f;
|
||||
outputPixels[1] = 1.0f;
|
||||
outputPixels[2] = 1.0f;
|
||||
outputPixels[3] = ((float)bitmapData[i]) / 255.0f;
|
||||
fwrite(outputPixels, sizeof(float), 4, file);
|
||||
}
|
||||
|
||||
// Now write output quads data.
|
||||
fwrite(characterData, sizeof(stbtt_bakedchar), TRUETYPE_NUM_CHARS, file);
|
||||
fclose(file);
|
||||
free(bitmapData);
|
||||
|
||||
return 0;
|
||||
}
|
24
src/dawntools/tools/uigen/CMakeLists.txt
Normal file
24
src/dawntools/tools/uigen/CMakeLists.txt
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2023 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Texture Build Tool
|
||||
project(uigen VERSION 1.0)
|
||||
add_executable(uigen)
|
||||
target_sources(uigen
|
||||
PRIVATE
|
||||
main.cpp
|
||||
../../util/file.cpp
|
||||
../../util/xml.cpp
|
||||
)
|
||||
target_include_directories(uigen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
target_link_libraries(uigen
|
||||
PUBLIC
|
||||
${DAWN_BUILD_HOST_LIBS}
|
||||
)
|
343
src/dawntools/tools/uigen/main.cpp
Normal file
343
src/dawntools/tools/uigen/main.cpp
Normal file
@ -0,0 +1,343 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "../../util/xml.hpp"
|
||||
#include "../../util/file.hpp"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
struct UIGenerated {
|
||||
bool align = false;
|
||||
bool alignGrid = false;
|
||||
std::string alignX;
|
||||
std::string alignY;
|
||||
std::string align0;
|
||||
std::string align1;
|
||||
std::string align2;
|
||||
std::string align3;
|
||||
|
||||
bool isGrid = false;
|
||||
std::string rows;
|
||||
std::string columns;
|
||||
std::string gutterX;
|
||||
std::string gutterY;
|
||||
|
||||
|
||||
std::string type;
|
||||
std::string name;
|
||||
|
||||
std::string parent;
|
||||
|
||||
// Optionals
|
||||
bool hasColor = false;
|
||||
std::string color;
|
||||
};
|
||||
|
||||
std::vector<std::string> split(std::string s, std::string delimiter) {
|
||||
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
|
||||
std::string token;
|
||||
std::vector<std::string> res;
|
||||
|
||||
while ((pos_end = s.find (delimiter, pos_start)) != std::string::npos) {
|
||||
token = s.substr (pos_start, pos_end - pos_start);
|
||||
pos_start = pos_end + delim_len;
|
||||
res.push_back(token);
|
||||
}
|
||||
|
||||
res.push_back (s.substr (pos_start));
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string alignmentFromRaw(std::string strRaw) {
|
||||
if(strRaw == "start") return "UI_COMPONENT_ALIGN_START";
|
||||
if(strRaw == "middle") return "UI_COMPONENT_ALIGN_MIDDLE";
|
||||
if(strRaw == "end") return "UI_COMPONENT_ALIGN_END";
|
||||
if(strRaw == "stretch") return "UI_COMPONENT_ALIGN_STRETCH";
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool parseChildren(
|
||||
xml_t *currentNode,
|
||||
std::string parent,
|
||||
std::vector<struct UIGenerated> *items
|
||||
) {
|
||||
// Confirm attributes
|
||||
auto attrName = xmlGetAttributeByName(currentNode, "name");
|
||||
if(attrName == -1) {
|
||||
std::cout << "Missing name attribute." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct UIGenerated item;
|
||||
item.name = std::string(currentNode->attributeDatas[attrName] );
|
||||
item.type = std::string(currentNode->node);
|
||||
item.parent = parent;
|
||||
|
||||
// Standard Align
|
||||
auto attrAlign = xmlGetAttributeByName(currentNode, "align");
|
||||
if(attrAlign != -1) {
|
||||
// Parse alignment
|
||||
std::string alignRaw(currentNode->attributeDatas[attrAlign]);
|
||||
std::vector<std::string> alignmentParts = split(alignRaw, " ");
|
||||
if(alignmentParts.size() != 6) {
|
||||
std::cout << "Alignment is invalid" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
item.align = true;
|
||||
item.alignX = alignmentFromRaw(alignmentParts[0]);
|
||||
item.alignY = alignmentFromRaw(alignmentParts[1]);
|
||||
item.align0 = alignmentParts[2];
|
||||
item.align1 = alignmentParts[3];
|
||||
item.align2 = alignmentParts[4];
|
||||
item.align3 = alignmentParts[5];
|
||||
|
||||
if(item.alignX.size() == 0) {
|
||||
std::cout << "X Align is invalid" << std::endl;
|
||||
return "";
|
||||
}
|
||||
if(item.alignY.size() == 0) {
|
||||
std::cout << "Y Align is invalid" << std::endl;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Grid Align
|
||||
auto attrGridAlign = xmlGetAttributeByName(currentNode, "grid");
|
||||
if(attrGridAlign != -1) {
|
||||
// Parse alignment
|
||||
std::string alignRaw(currentNode->attributeDatas[attrGridAlign]);
|
||||
std::vector<std::string> alignmentParts = split(alignRaw, " ");
|
||||
if(alignmentParts.size() != 4) {
|
||||
std::cout << "Grid alignment is invalid" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
item.alignGrid = true;
|
||||
item.alignX = alignmentFromRaw(alignmentParts[0]);
|
||||
item.alignY = alignmentFromRaw(alignmentParts[1]);
|
||||
item.align0 = alignmentParts[2];
|
||||
item.align1 = alignmentParts[3];
|
||||
|
||||
if(item.alignX.size() == 0) {
|
||||
std::cout << "X Align is invalid" << std::endl;
|
||||
return "";
|
||||
}
|
||||
if(item.alignY.size() == 0) {
|
||||
std::cout << "Y Align is invalid" << std::endl;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Parse color
|
||||
auto attrColor = xmlGetAttributeByName(currentNode, "color");
|
||||
if(attrColor != -1) {
|
||||
item.hasColor = true;
|
||||
item.color = currentNode->attributeDatas[attrColor];
|
||||
}
|
||||
|
||||
|
||||
// Grid
|
||||
if(item.type == "UIGrid") {
|
||||
auto attrRows = xmlGetAttributeByName(currentNode, "rows");
|
||||
auto attrCols = xmlGetAttributeByName(currentNode, "columns");
|
||||
auto attrGutter = xmlGetAttributeByName(currentNode, "gutter");
|
||||
if(attrRows == -1 || attrCols == -1) {
|
||||
std::cout << "Grid is invalid" << std::endl;
|
||||
return false;
|
||||
}
|
||||
item.isGrid = true;
|
||||
item.rows = currentNode->attributeDatas[attrRows];
|
||||
item.columns = currentNode->attributeDatas[attrCols];
|
||||
if(attrGutter != -1) {
|
||||
auto gutterParts = split(currentNode->attributeDatas[attrGutter], " ");
|
||||
if(gutterParts.size() != 2) {
|
||||
std::cout << "Gutter is invalid" << std::endl;
|
||||
return false;
|
||||
}
|
||||
item.gutterX = gutterParts[0];
|
||||
item.gutterY = gutterParts[1];
|
||||
} else {
|
||||
item.gutterX = "0";
|
||||
item.gutterY = "0";
|
||||
}
|
||||
}
|
||||
|
||||
// Self
|
||||
items->push_back(item);
|
||||
|
||||
// Children
|
||||
for(int32_t i = 0; i < currentNode->childrenCount; i++) {
|
||||
if(!parseChildren(currentNode->children + i, item.name, items)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *args[]) {
|
||||
if(argc != 3) {
|
||||
std::cout << "Invalid number of args for ui gen" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Open input file.
|
||||
char fileIn[FILENAME_MAX];
|
||||
fileNormalizeSlashes(args[1]);
|
||||
sprintf(fileIn, "%s", args[1]);
|
||||
FILE *fin = fopen(fileIn, "rb");
|
||||
if(fin == NULL) {
|
||||
std::cout << "Failed to open input file " << fileIn << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Tell file len
|
||||
fseek(fin, 0, SEEK_END);
|
||||
auto len = ftell(fin);
|
||||
fseek(fin, 0, SEEK_SET);
|
||||
|
||||
// Read data.
|
||||
char *buffer = (char *)malloc(sizeof(char) * (len + 1));
|
||||
if(buffer == NULL) {
|
||||
std::cout << "Failed to create temporary memory." << std::endl;
|
||||
fclose(fin);
|
||||
return 1;
|
||||
}
|
||||
assetReadString(fin, buffer);
|
||||
fclose(fin);
|
||||
|
||||
// Parse XML
|
||||
xml_t xml;
|
||||
xmlLoad(&xml, buffer);
|
||||
free(buffer);
|
||||
|
||||
// Begin output
|
||||
std::string bufferOut = "";
|
||||
|
||||
// Imports
|
||||
bufferOut += "#pragma once\n";
|
||||
for(int32_t i = 0; i < xml.attributeCount; i++) {
|
||||
std::string attrName = xml.attributeNames[i];
|
||||
|
||||
if(
|
||||
attrName == "name"
|
||||
) continue;
|
||||
|
||||
bufferOut += "#include \"";
|
||||
bufferOut += xml.attributeDatas[i];
|
||||
bufferOut += "\"\n";
|
||||
}
|
||||
bufferOut += "\n";
|
||||
|
||||
// Now prep class itself.
|
||||
auto attrName = xmlGetAttributeByName(&xml, "name");
|
||||
if(attrName == -1) {
|
||||
std::cout << "Missing " << std::endl;
|
||||
xmlDispose(&xml);
|
||||
return 1;
|
||||
}
|
||||
std::string name = xml.attributeDatas[attrName];
|
||||
|
||||
// Children
|
||||
std::vector<struct UIGenerated> items;
|
||||
for(int32_t j = 0; j < xml.childrenCount; j++) {
|
||||
if(parseChildren(xml.children + j, "", &items)) continue;
|
||||
xmlDispose(&xml);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Generate strings.
|
||||
bufferOut += "namespace Dawn {\n";
|
||||
bufferOut += " class " + name + " : public UIEmpty {\n";
|
||||
bufferOut += " public:\n";
|
||||
auto it = items.begin();
|
||||
while(it != items.end()) {
|
||||
auto c = *it;
|
||||
bufferOut += " " + c.type + " " + c.name + ";\n";
|
||||
++it;
|
||||
}
|
||||
bufferOut += "\n";
|
||||
bufferOut += " " + name + "(UICanvas *canvas) : UIEmpty(canvas),\n";
|
||||
it = items.begin();
|
||||
while(it != items.end()) {
|
||||
auto c = *it;
|
||||
bufferOut += " " + c.name + "(canvas)";
|
||||
if(it != items.end() - 1) bufferOut += ",";
|
||||
bufferOut += "\n";
|
||||
++it;
|
||||
}
|
||||
bufferOut += " {\n";
|
||||
|
||||
it = items.begin();
|
||||
while(it != items.end()) {
|
||||
auto c = *it;
|
||||
bufferOut += "\n";
|
||||
|
||||
// Transform
|
||||
if(c.align) {
|
||||
bufferOut += " " + c.name + ".setTransform(\n";
|
||||
bufferOut += " " + c.alignX + ", " + c.alignY + ",\n";
|
||||
bufferOut += " glm::vec4(" + c.align0 + ", " + c.align1 + ", " + c.align2 + ", " + c.align3 + "),\n";
|
||||
bufferOut += " 0.0f\n";
|
||||
bufferOut += " );\n";
|
||||
}
|
||||
|
||||
// Color
|
||||
if(c.hasColor) {
|
||||
bufferOut += " " + c.name + ".color = " + c.color + ";\n";
|
||||
}
|
||||
|
||||
// Grid
|
||||
if(c.isGrid) {
|
||||
bufferOut += " " + c.name + ".setGridSize(\n";
|
||||
bufferOut += " " + c.rows + ", " + c.columns + ",\n";
|
||||
bufferOut += " " + c.gutterX + ", " + c.gutterY + "\n";
|
||||
bufferOut += " );\n";
|
||||
}
|
||||
|
||||
// Parent setting
|
||||
if(c.alignGrid) {
|
||||
bufferOut += " " + c.parent + ".addToGrid(\n";
|
||||
bufferOut += " &" + c.name + ",\n";
|
||||
bufferOut += " " + c.align0 + ", " + c.align1 + ",\n";
|
||||
bufferOut += " " + c.alignX + ", " + c.alignY + "\n";
|
||||
bufferOut += " );\n";
|
||||
} else {
|
||||
if(c.parent == "") {
|
||||
bufferOut += " this->addChild(&" + c.name + ");\n";
|
||||
} else {
|
||||
bufferOut += " " + c.parent + ".addChild(&" + c.name + ");\n";
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
bufferOut += " }\n";
|
||||
bufferOut += " };\n";
|
||||
bufferOut += "}";
|
||||
|
||||
xmlDispose(&xml);
|
||||
|
||||
// Finished with XML data, now we can write data out.
|
||||
char fileOut[FILENAME_MAX];
|
||||
fileNormalizeSlashes(args[2]);
|
||||
sprintf(fileOut, "%s.hpp", args[2]);
|
||||
fileMkdirp(fileOut);
|
||||
FILE *fout = fopen(fileOut, "wb");
|
||||
if(fout == NULL) {
|
||||
std::cout << "Failed to open output file." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Buffer out data.
|
||||
const char *bufferOutStr = bufferOut.c_str();
|
||||
fwrite(bufferOutStr, sizeof(char), strlen(bufferOutStr), fout);
|
||||
fclose(fout);
|
||||
std::cout << "Generated UI " << fileOut << std::endl;
|
||||
|
||||
// Cleanup
|
||||
return 0;
|
||||
}
|
39
src/dawntools/tools/vnscenegen/CMakeLists.txt
Normal file
39
src/dawntools/tools/vnscenegen/CMakeLists.txt
Normal file
@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2023 Dominic Msters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# VN Scene Generator Tool
|
||||
project(vnscenegen VERSION 1.1)
|
||||
add_executable(vnscenegen)
|
||||
|
||||
|
||||
# Sources
|
||||
target_sources(vnscenegen
|
||||
PRIVATE
|
||||
${DAWN_SHARED_SOURCES}
|
||||
${DAWN_TOOL_SOURCES}
|
||||
VnSceneGen.cpp
|
||||
)
|
||||
|
||||
# Includes
|
||||
target_include_directories(vnscenegen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_INCLUDES}
|
||||
${DAWN_TOOL_INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
# Definitions
|
||||
target_compile_definitions(vnscenegen
|
||||
PUBLIC
|
||||
${DAWN_SHARED_DEFINITIONS}
|
||||
DAWN_TOOL_INSTANCE=VnSceneGen
|
||||
DAWN_TOOL_HEADER="VnSceneGen.hpp"
|
||||
)
|
||||
|
||||
# Libraries
|
||||
target_link_libraries(vnscenegen
|
||||
PUBLIC
|
||||
${DAWN_BUILD_HOST_LIBS}
|
||||
)
|
60
src/dawntools/tools/vnscenegen/VnSceneGen.cpp
Normal file
60
src/dawntools/tools/vnscenegen/VnSceneGen.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "VnSceneGen.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
std::vector<std::string> VnSceneGen::getRequiredFlags() {
|
||||
return std::vector<std::string>{ "input", "output", "language-out" };
|
||||
}
|
||||
|
||||
int32_t VnSceneGen::start() {
|
||||
// Open input file.
|
||||
File file(flags["input"]);
|
||||
std::string buffer;
|
||||
if(!file.readString(&buffer)) {
|
||||
std::cout << "Failed to read scene " << file.filename << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Parse XML
|
||||
Xml xml = Xml::load(buffer);
|
||||
std::string error;
|
||||
struct RootInformation info;
|
||||
auto ret = (RootParser()).parse(&xml, &info, &error);
|
||||
if(ret != 0) {
|
||||
std::cout << error << std::endl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> lines;
|
||||
RootGen::generate(&lines, &info, "");
|
||||
|
||||
// Generate buffer
|
||||
std::string bufferOut;
|
||||
auto itLine = lines.begin();
|
||||
while(itLine != lines.end()) {
|
||||
bufferOut += *itLine + "\n";
|
||||
++itLine;
|
||||
}
|
||||
|
||||
// Finished with XML data, now we can write data out.
|
||||
File fileOut(flags["output"] + ".hpp");
|
||||
if(!fileOut.mkdirp()) {
|
||||
std::cout << "Failed to make scene output dir" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if(!fileOut.writeString(bufferOut)) {
|
||||
std::cout << "Failed to generate scene " << fileOut.filename << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Now dump out the language strings to be picked up later.
|
||||
ret = languageSaveStrings(flags["language-out"], info.strings);
|
||||
if(ret != 0) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
20
src/dawntools/tools/vnscenegen/VnSceneGen.hpp
Normal file
20
src/dawntools/tools/vnscenegen/VnSceneGen.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
// 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 "parse/root.hpp"
|
||||
#include "util/Language.cpp"
|
||||
|
||||
namespace Dawn {
|
||||
class VnSceneGen : public DawnTool {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredFlags() override;
|
||||
|
||||
public:
|
||||
int32_t start();
|
||||
};
|
||||
}
|
56
src/dawntools/tools/vnscenegen/parse/asset.hpp
Normal file
56
src/dawntools/tools/vnscenegen/parse/asset.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct AssetInformation {
|
||||
std::string type;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class AssetParser : public XmlParser<struct AssetInformation> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>{
|
||||
"name",
|
||||
"type"
|
||||
};
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct AssetInformation *out,
|
||||
std::string *error
|
||||
) {
|
||||
out->name = values["name"];
|
||||
out->type = values["type"];
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string convert(struct AssetInformation info) {
|
||||
std::string out;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
class AssetGen : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::vector<std::string> *out,
|
||||
struct AssetInformation *info,
|
||||
std::string tabs
|
||||
) {
|
||||
return line(out, "// Asset will be generated here", tabs);
|
||||
}
|
||||
};
|
||||
}
|
77
src/dawntools/tools/vnscenegen/parse/character.hpp
Normal file
77
src/dawntools/tools/vnscenegen/parse/character.hpp
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct CharacterInformation {
|
||||
std::string clazz;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class CharacterParser : public XmlParser<struct CharacterInformation> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>{
|
||||
"class",
|
||||
"name"
|
||||
};
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct CharacterInformation *out,
|
||||
std::string *error
|
||||
) {
|
||||
out->clazz = values["class"];
|
||||
out->name = values["name"];
|
||||
|
||||
if(out->clazz.size() == 0) {
|
||||
*error = "Character class cannot be empty.";
|
||||
return 1;
|
||||
}
|
||||
if(out->name.size() == 0) {
|
||||
*error = "Character name cannot be empty.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CharacterGen : public CodeGen {
|
||||
public:
|
||||
static void generateProperty(
|
||||
std::vector<std::string> *out,
|
||||
struct CharacterInformation info,
|
||||
std::string tabs
|
||||
) {
|
||||
line(out, info.clazz + " *" + info.name + ";", tabs);
|
||||
}
|
||||
|
||||
static void generateInitializer(
|
||||
std::vector<std::string> *out,
|
||||
struct CharacterInformation info,
|
||||
std::string tabs
|
||||
) {
|
||||
line(out, "this->" + info.name + " = " + info.clazz + "::create(this);", tabs);
|
||||
}
|
||||
|
||||
static void generateAssets(
|
||||
std::vector<std::string> *out,
|
||||
struct CharacterInformation info,
|
||||
std::string tabs
|
||||
) {
|
||||
line(out, "vectorAppend(&assets, " + info.clazz + "::getRequiredAssets(man));", "");
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct CharacterFadeEventInfo {
|
||||
std::string character;
|
||||
std::string duration;
|
||||
std::string ease;
|
||||
std::string fade;
|
||||
std::string include;
|
||||
};
|
||||
|
||||
class CharacterFadeParser : public XmlParser<struct CharacterFadeEventInfo> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>{
|
||||
"character"
|
||||
};
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>{
|
||||
{ "fade", "in" },
|
||||
{ "ease", "linear" },
|
||||
{ "duration", "1" }
|
||||
};
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct CharacterFadeEventInfo *out,
|
||||
std::string *error
|
||||
) {
|
||||
out->character = values["character"];
|
||||
out->duration = parseDuration(values["duration"]);
|
||||
out->ease = parseEase(values["ease"]);
|
||||
out->fade = values["fade"] == "in" ? "true" : "false";
|
||||
out->include = "visualnovel/events/characters/VisualNovelFadeCharacterEvent.hpp";
|
||||
|
||||
if(out->ease.size() == 0) {
|
||||
*error = "Invalid ease";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CharacterFadeGen : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::vector<std::string> *out,
|
||||
struct CharacterFadeEventInfo *info,
|
||||
std::string tabs = ""
|
||||
) {
|
||||
line(out, "new VisualNovelFadeCharacterEvent(vnManager,", tabs + " ");
|
||||
line(out, "this->" + info->character + "->vnCharacter,", tabs + " ");
|
||||
line(out, info->fade + ",", tabs + " ");
|
||||
line(out, info->ease + ",", tabs + " ");
|
||||
line(out, info->duration, tabs + " ");
|
||||
line(out, ")", tabs);
|
||||
}
|
||||
};
|
||||
}
|
48
src/dawntools/tools/vnscenegen/parse/event/pauseevent.hpp
Normal file
48
src/dawntools/tools/vnscenegen/parse/event/pauseevent.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct PauseEventInfo {
|
||||
std::string duration;
|
||||
std::string include;
|
||||
};
|
||||
|
||||
class PauseEventParser : public XmlParser<struct PauseEventInfo> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>{ "duration" };
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct PauseEventInfo *out,
|
||||
std::string *error
|
||||
) {
|
||||
out->duration = parseDuration(values["duration"]);
|
||||
out->include = "visualnovel/events/timing/VisualNovelPauseEvent.hpp";
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class PauseEventGen : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::vector<std::string> *out,
|
||||
struct PauseEventInfo *info,
|
||||
std::string tabs = ""
|
||||
) {
|
||||
line(out, "new VisualNovelPauseEvent(vnManager, " + info->duration + ")", tabs);
|
||||
}
|
||||
};
|
||||
}
|
101
src/dawntools/tools/vnscenegen/parse/event/textevent.hpp
Normal file
101
src/dawntools/tools/vnscenegen/parse/event/textevent.hpp
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
#include "util/Language.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct TextEventInfo {
|
||||
std::string character;
|
||||
std::string emotion;
|
||||
std::vector<struct LanguageString> strings;
|
||||
std::string key;
|
||||
};
|
||||
|
||||
class TextStringParser : public XmlParser<struct LanguageString> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>{ "lang" };
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct LanguageString *out,
|
||||
std::string *error
|
||||
) {
|
||||
out->lang = values["lang"];
|
||||
out->text = node->value;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class TextEventParser : public XmlParser<struct TextEventInfo> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>{
|
||||
"character",
|
||||
"emotion"
|
||||
};
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct TextEventInfo *out,
|
||||
std::string *error
|
||||
) {
|
||||
int32_t ret = 0;
|
||||
out->character = values["character"];
|
||||
out->emotion = values["emotion"];
|
||||
|
||||
if(out->key.size() <= 0) {
|
||||
*error = "Text Event requries a language key to be defined.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto itChildren = node->children.begin();
|
||||
while(itChildren != node->children.end()) {
|
||||
auto c = *itChildren;
|
||||
if(c->node == "string") {
|
||||
struct LanguageString str;
|
||||
ret = (TextStringParser()).parse(c, &str, error);
|
||||
str.key = out->key;
|
||||
out->strings.push_back(str);
|
||||
}
|
||||
++itChildren;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
class TextEventGen : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::vector<std::string> *out,
|
||||
struct TextEventInfo *info,
|
||||
std::string tabs = ""
|
||||
) {
|
||||
std::string emo = info->emotion;
|
||||
emo[0] = toupper(emo[0]);
|
||||
|
||||
line(out, "new VisualNovelTextboxEvent(vnManager,", tabs);
|
||||
line(out, "this->" + info->character + "->vnCharacter, ", tabs + " ");
|
||||
line(out, "this->" + info->character + "->emotion" + emo + ", ", tabs + " ");
|
||||
line(out, "\"" + info->key + "\"", tabs + " ");
|
||||
line(out, ")", tabs);
|
||||
}
|
||||
};
|
||||
}
|
121
src/dawntools/tools/vnscenegen/parse/events.hpp
Normal file
121
src/dawntools/tools/vnscenegen/parse/events.hpp
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
#include "parse/event/textevent.hpp"
|
||||
#include "parse/event/characterfadeevent.hpp"
|
||||
#include "parse/event/pauseevent.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
enum EventType {
|
||||
EVENT_TYPE_TEXT,
|
||||
EVENT_TYPE_CHARACTER_FADE,
|
||||
EVENT_TYPE_PAUSE
|
||||
};
|
||||
|
||||
struct EventsInformation {
|
||||
std::map<int32_t, enum EventType> eventTypes;
|
||||
std::map<int32_t, struct TextEventInfo> textEvents;
|
||||
std::map<int32_t, struct CharacterFadeEventInfo> characterFadeEvents;
|
||||
std::map<int32_t, struct PauseEventInfo> pauseEvents;
|
||||
std::vector<std::string> includes;
|
||||
|
||||
std::vector<struct LanguageString> strings;
|
||||
std::string key;
|
||||
};
|
||||
|
||||
class EventsParser : public XmlParser<struct EventsInformation> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>{
|
||||
};
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct EventsInformation *out,
|
||||
std::string *error
|
||||
) {
|
||||
int32_t ret = 0;
|
||||
int32_t i = 0;
|
||||
int32_t languageKeyNumber = 1;
|
||||
|
||||
if(out->key.size() <= 0) {
|
||||
*error = "Events requries a language key to be defined.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto itChildren = node->children.begin();
|
||||
while(itChildren != node->children.end()) {
|
||||
auto c = *itChildren;
|
||||
|
||||
if(c->node == "text") {
|
||||
struct TextEventInfo textEvent;
|
||||
textEvent.key = out->key + "." + std::to_string(languageKeyNumber++);
|
||||
ret = (TextEventParser()).parse(c, &textEvent, error);
|
||||
out->eventTypes[i] = EVENT_TYPE_TEXT;
|
||||
out->textEvents[i++] = textEvent;
|
||||
vectorAppend(&out->strings, textEvent.strings);
|
||||
|
||||
} else if(c->node == "character-fade") {
|
||||
struct CharacterFadeEventInfo charFadeEvent;
|
||||
ret = (CharacterFadeParser()).parse(c, &charFadeEvent, error);
|
||||
out->eventTypes[i] = EVENT_TYPE_CHARACTER_FADE;
|
||||
out->characterFadeEvents[i++] = charFadeEvent;
|
||||
out->includes.push_back(charFadeEvent.include);
|
||||
|
||||
} else if(c->node == "pause") {
|
||||
struct PauseEventInfo pauseEvent;
|
||||
ret = (PauseEventParser()).parse(c, &pauseEvent, error);
|
||||
out->eventTypes[i] = EVENT_TYPE_PAUSE;
|
||||
out->pauseEvents[i++] = pauseEvent;
|
||||
out->includes.push_back(pauseEvent.include);
|
||||
|
||||
}
|
||||
|
||||
++itChildren;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
class EventsGen : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::vector<std::string> *out,
|
||||
struct EventsInformation *info,
|
||||
std::string tabs
|
||||
) {
|
||||
auto itEvents = info->eventTypes.begin();
|
||||
while(itEvents != info->eventTypes.end()) {
|
||||
auto e = *itEvents;
|
||||
line(out, "->then(", tabs);
|
||||
switch(e.second) {
|
||||
case EVENT_TYPE_TEXT:
|
||||
TextEventGen::generate(out, &info->textEvents[e.first], tabs + " ");
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_CHARACTER_FADE:
|
||||
CharacterFadeGen::generate(out, &info->characterFadeEvents[e.first], tabs + " ");
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_PAUSE:
|
||||
PauseEventGen::generate(out, &info->pauseEvents[e.first], tabs + " ");
|
||||
break;
|
||||
|
||||
}
|
||||
line(out, ")", tabs);
|
||||
++itEvents;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
67
src/dawntools/tools/vnscenegen/parse/header.hpp
Normal file
67
src/dawntools/tools/vnscenegen/parse/header.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "parse/include.hpp"
|
||||
#include "parse/character.hpp"
|
||||
#include "parse/scene.hpp"
|
||||
#include "parse/asset.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct HeaderInformation {
|
||||
std::vector<std::string> includes;
|
||||
std::vector<struct CharacterInformation> characters;
|
||||
std::vector<struct AssetInformation> assets;
|
||||
std::map<std::string, std::map<std::string, std::string>> languages;
|
||||
struct SceneInformation scene;
|
||||
};
|
||||
|
||||
class HeaderParser : public XmlParser<struct HeaderInformation> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct HeaderInformation *out,
|
||||
std::string *error
|
||||
) {
|
||||
int32_t ret = 0;
|
||||
auto itChildren = node->children.begin();
|
||||
while(itChildren != node->children.end()) {
|
||||
auto c = *itChildren;
|
||||
|
||||
if(c->node == "include") {
|
||||
ret = (IncludeParser()).parse(c, &out->includes, error);
|
||||
|
||||
} else if (c->node == "character") {
|
||||
struct CharacterInformation character;
|
||||
ret = (CharacterParser()).parse(c, &character, error);
|
||||
if(ret != 0) return ret;
|
||||
out->characters.push_back(character);
|
||||
|
||||
} else if(c->node == "asset") {
|
||||
struct AssetInformation asset;
|
||||
ret = (AssetParser()).parse(c, &asset, error);
|
||||
if(ret != 0) return ret;
|
||||
out->assets.push_back(asset);
|
||||
|
||||
} else if(c->node == "scene") {
|
||||
ret = (SceneParser()).parse(c, &out->scene, error);
|
||||
}
|
||||
|
||||
if(ret != 0) return ret;
|
||||
++itChildren;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
}
|
59
src/dawntools/tools/vnscenegen/parse/include.hpp
Normal file
59
src/dawntools/tools/vnscenegen/parse/include.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
#include "util/CodeGen.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
typedef std::vector<std::string> include_t;
|
||||
|
||||
class IncludeParser : public XmlParser<include_t> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>{
|
||||
"path"
|
||||
};
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
include_t *out,
|
||||
std::string *error
|
||||
) {
|
||||
if(values["path"].size() == 0) {
|
||||
*error = "";
|
||||
return 1;
|
||||
}
|
||||
|
||||
out->push_back(values["path"]);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class IncludeGen : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::vector<std::string> *out,
|
||||
include_t includes,
|
||||
std::string tabs
|
||||
) {
|
||||
std::vector<std::string> generated;
|
||||
auto it = includes.begin();
|
||||
while(it != includes.end()) {
|
||||
if(std::find(generated.begin(), generated.end(), *it) == generated.end()) {
|
||||
line(out, "#include \"" + *it + "\"", tabs);
|
||||
generated.push_back(*it);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
118
src/dawntools/tools/vnscenegen/parse/root.hpp
Normal file
118
src/dawntools/tools/vnscenegen/parse/root.hpp
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "parse/header.hpp"
|
||||
#include "parse/events.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct RootInformation {
|
||||
struct HeaderInformation header;
|
||||
struct EventsInformation events;
|
||||
|
||||
std::vector<struct LanguageString> strings;
|
||||
};
|
||||
|
||||
class RootParser : public XmlParser<struct RootInformation> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>();
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct RootInformation *out,
|
||||
std::string *error
|
||||
) {
|
||||
int32_t ret = 0;
|
||||
auto itChildren = node->children.begin();
|
||||
|
||||
while(itChildren != node->children.end()) {
|
||||
auto c = *itChildren;
|
||||
|
||||
if(c->node == "head") {
|
||||
ret = (HeaderParser()).parse(c, &out->header, error);
|
||||
} else if(c->node == "events") {
|
||||
out->events.key = out->header.scene.name;
|
||||
ret = (EventsParser()).parse(c, &out->events, error);
|
||||
vectorAppend(&out->strings, out->events.strings);
|
||||
}
|
||||
|
||||
if(ret != 0) return ret;
|
||||
++itChildren;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
class RootGen : public CodeGen {
|
||||
public:
|
||||
static void generate(
|
||||
std::vector<std::string> *out,
|
||||
struct RootInformation *info,
|
||||
std::string tabs = ""
|
||||
) {
|
||||
struct ClassGenInfo c;
|
||||
c.clazz = info->header.scene.name;
|
||||
c.extend = info->header.scene.type;
|
||||
c.constructorArgs = "DawnGame *game";
|
||||
c.extendArgs = "game";
|
||||
|
||||
struct MethodGenInfo vnStage;
|
||||
vnStage.name = "vnStage";
|
||||
vnStage.type = "void";
|
||||
vnStage.isOverride = true;
|
||||
line(&vnStage.body, info->header.scene.type+ "::vnStage();", "");
|
||||
|
||||
struct MethodGenInfo getAssets;
|
||||
getAssets.name = "getRequiredAssets";
|
||||
getAssets.type = "std::vector<Asset*>";
|
||||
getAssets.isOverride = true;
|
||||
line(&getAssets.body, "auto man = &this->game->assetManager;", "");
|
||||
line(&getAssets.body, "auto assets = " + info->header.scene.type + "::getRequiredAssets();", "");
|
||||
|
||||
struct MethodGenInfo getVNEvent;
|
||||
getVNEvent.name = "getVNEvent";
|
||||
getVNEvent.type = "IVisualNovelEvent *";
|
||||
getVNEvent.isOverride = true;
|
||||
line(&getVNEvent.body, "auto start = new VisualNovelPauseEvent(vnManager, 1.0f);", "");
|
||||
|
||||
IncludeGen::generate(&c.includes, info->header.includes, "");
|
||||
IncludeGen::generate(&c.includes, info->events.includes, "");
|
||||
|
||||
// Characters
|
||||
auto itChar = info->header.characters.begin();
|
||||
while(itChar != info->header.characters.end()) {
|
||||
CharacterGen::generateProperty(&c.publicProperties, *itChar, "");
|
||||
CharacterGen::generateInitializer(&vnStage.body, *itChar, "");
|
||||
CharacterGen::generateAssets(&getAssets.body, *itChar, "");
|
||||
++itChar;
|
||||
}
|
||||
|
||||
// Events
|
||||
if(info->events.eventTypes.size() > 0) {
|
||||
line(&getVNEvent.body, "start", "");
|
||||
EventsGen::generate(&getVNEvent.body, &info->events, " ");
|
||||
line(&getVNEvent.body, ";", "");
|
||||
}
|
||||
|
||||
// Wrap up methods
|
||||
line(&getAssets.body, "return assets;", "");
|
||||
line(&getVNEvent.body, "return start;", "");
|
||||
|
||||
methodGen(&c.publicCode, vnStage);
|
||||
line(&c.publicCode, "", "");
|
||||
methodGen(&c.publicCode, getAssets);
|
||||
methodGen(&c.publicCode, getVNEvent);
|
||||
classGen(out, c);
|
||||
}
|
||||
};
|
||||
}
|
40
src/dawntools/tools/vnscenegen/parse/scene.hpp
Normal file
40
src/dawntools/tools/vnscenegen/parse/scene.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "util/XmlParser.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct SceneInformation {
|
||||
std::string type;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class SceneParser : public XmlParser<struct SceneInformation> {
|
||||
protected:
|
||||
std::vector<std::string> getRequiredAttributes() {
|
||||
return std::vector<std::string>{
|
||||
"name",
|
||||
};
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getOptionalAttributes() {
|
||||
return std::map<std::string, std::string>{
|
||||
{ "type", "SimpleVNScene" }
|
||||
};
|
||||
}
|
||||
|
||||
int32_t onParse(
|
||||
Xml *node,
|
||||
std::map<std::string, std::string> values,
|
||||
struct SceneInformation *out,
|
||||
std::string *error
|
||||
) {
|
||||
out->name = values["name"];
|
||||
out->type = values["type"];
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user