UI Border Done
This commit is contained in:
@ -1,8 +1,12 @@
|
||||
<prefab name="VNTextbox" type="">
|
||||
<asset type="truetype" name="font_main" />
|
||||
<UIBorder ref="border" width="64" height="64" />
|
||||
<UIBorder ref="border" borderSize="16, 16" alignment="32, 32, 320, 320" />
|
||||
|
||||
<child alignment="16, 16, -1, -1">
|
||||
<UILabel text="bruh" font="font_main" fontSize="32" />
|
||||
<child>
|
||||
<UILabel text="bruh" font="font_main" fontSize="32"
|
||||
alignment="16, 16, -1, -1"
|
||||
alignX="UI_COMPONENT_ALIGN_STRETCH"
|
||||
alignY="UI_COMPONENT_ALIGN_STRETCH"
|
||||
/>
|
||||
</child>
|
||||
</prefab>
|
@ -7,7 +7,7 @@
|
||||
#include "dawnlibs.hpp"
|
||||
#include "display/Transform.hpp"
|
||||
#include "scene/SceneItem.hpp"
|
||||
#include "state/State.hpp"
|
||||
#include "state/StateOwner.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class DawnGame;
|
||||
|
@ -84,7 +84,7 @@ void UIBorder::onStart() {
|
||||
4 * QUAD_VERTICE_COUNT, 4 * QUAD_INDICE_COUNT
|
||||
);
|
||||
QuadMesh::bufferQuadMesh(&mesh,
|
||||
glm::vec2(iSize.x + bSize.x, 0), tSize + glm::vec2(tSize.x, 0),
|
||||
glm::vec2(iSize.x + bSize.x, bSize.y), tSize + glm::vec2(tSize.x, 0),
|
||||
glm::vec2(this->getWidth(), bSize.y + iSize.y), glm::vec2(1.0f, tSize.y + tSize.y),
|
||||
5 * QUAD_VERTICE_COUNT, 5 * QUAD_INDICE_COUNT
|
||||
);
|
||||
|
@ -35,9 +35,7 @@ namespace Dawn {
|
||||
|
||||
class UIComponent : public SceneItemComponent, public UIComponentDimensional {
|
||||
protected:
|
||||
// @optional
|
||||
float_t width = 1;
|
||||
// @optional
|
||||
float_t height = 1;
|
||||
|
||||
StateEvent<> eventAlignmentUpdated;
|
||||
@ -77,8 +75,11 @@ namespace Dawn {
|
||||
glm::vec2 alignment
|
||||
);
|
||||
|
||||
StateProperty<UIComponentAlign> alignX;
|
||||
StateProperty<UIComponentAlign> alignY;
|
||||
// @optional
|
||||
StateProperty<enum UIComponentAlign> alignX;
|
||||
// @optional
|
||||
StateProperty<enum UIComponentAlign> alignY;
|
||||
// @optional
|
||||
StateProperty<glm::vec4> alignment;
|
||||
|
||||
UIComponent(SceneItem *item);
|
||||
|
@ -4,7 +4,7 @@
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "state/State.hpp"
|
||||
#include "state/StateOwner.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
template<typename D, typename...A>
|
||||
|
@ -31,15 +31,13 @@ namespace Dawn {
|
||||
textbox->transform.setParent(canvas->transform);
|
||||
|
||||
struct Color colors[] = {
|
||||
COLOR_RED, COLOR_MAGENTA, COLOR_RED,
|
||||
COLOR_BLUE, COLOR_MAGENTA, COLOR_WHITE,
|
||||
COLOR_MAGENTA, COLOR_CORNFLOWER_BLUE, COLOR_MAGENTA,
|
||||
COLOR_RED, COLOR_MAGENTA, COLOR_RED
|
||||
COLOR_BLACK, COLOR_MAGENTA, COLOR_BLUE
|
||||
};
|
||||
text.setSize(3, 3);
|
||||
text.buffer(colors);
|
||||
textbox->border->texture = &text;
|
||||
|
||||
textbox->border->alignment = glm::vec4(32, 32, 128, 128);
|
||||
}
|
||||
|
||||
std::vector<Asset*> getRequiredAssets() override {
|
||||
|
@ -78,6 +78,24 @@ namespace Dawn {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
static inline std::string vec4Parser(std::string v, std::string *error) {
|
||||
// Split string by comma into two strings that we pass into float
|
||||
auto split = stringSplit(v, ",");
|
||||
if(split.size() != 4) {
|
||||
*error = "Invalid vec4 value: " + v;
|
||||
return std::string("");
|
||||
}
|
||||
return std::string(
|
||||
"glm::vec4(" +
|
||||
floatParser(split[0], error) + ", " +
|
||||
floatParser(split[1], error) + ", " +
|
||||
floatParser(split[2], error) + ", " +
|
||||
floatParser(split[3], error) +
|
||||
")"
|
||||
);
|
||||
};
|
||||
|
||||
static inline std::string colorParser(std::string v, std::string *error) {
|
||||
return rawParser(v, error);
|
||||
}
|
||||
|
@ -56,6 +56,8 @@ int32_t PrefabComponentParser::onParse(
|
||||
parser = vec2Parser;
|
||||
} else if(type.find("vec3") != std::string::npos) {
|
||||
parser = vec3Parser;
|
||||
} else if(type.find("vec4") != std::string::npos) {
|
||||
parser = vec4Parser;
|
||||
} else if(type == "int32_t" || type == "int") {
|
||||
parser = intParser;
|
||||
} else if(type == "bool_t") {
|
||||
|
@ -7,7 +7,124 @@
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
struct PrefabComponentParserRuleset PrefabRegistry::parseFile(
|
||||
File *file,
|
||||
std::string clazz
|
||||
) {
|
||||
assertNotNull(file);
|
||||
|
||||
std::string data;
|
||||
if(!file->readString(&data)) {
|
||||
std::cout << "Failed to read ruleset file!" << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
// Begin scanning contentsr
|
||||
// std::string include = this->sources;
|
||||
auto toRemove = File::normalizeSlashes(this->sources + FILE_PATH_SEP);
|
||||
auto includePath = file->filename.substr(toRemove.size(), file->filename.size() - toRemove.size());
|
||||
|
||||
// Now locate the first subdir since we don't want to include the root path (e.g. dawn, dawnrose, etc)
|
||||
auto firstSlash = includePath.find(FILE_PATH_SEP);
|
||||
if(firstSlash != std::string::npos) {
|
||||
includePath = includePath.substr(firstSlash + 1, includePath.size() - firstSlash - 1);
|
||||
}
|
||||
|
||||
struct PrefabComponentParserRuleset ruleset;
|
||||
// Replace all file seps with slashes
|
||||
size_t pos = 0;
|
||||
while ((pos = includePath.find(FILE_PATH_SEP, pos)) != std::string::npos) {
|
||||
includePath.replace(pos, 1, "/");
|
||||
pos += 1;
|
||||
}
|
||||
ruleset.include = includePath;
|
||||
ruleset.name = clazz;
|
||||
|
||||
std::regex_constants::syntax_option_type regexFlags;
|
||||
#if defined(__GNUC__)
|
||||
regexFlags = std::regex_constants::ECMAScript | std::regex_constants::multiline;
|
||||
#else
|
||||
regexFlags = std::regex_constants::ECMAScript;
|
||||
#endif
|
||||
|
||||
// First, let's look for what class(es) this class extends
|
||||
std::regex regexClassName("class\\s+\\w+\\s+:\\s+", regexFlags);
|
||||
std::smatch match;
|
||||
if(std::regex_search(data, match, regexClassName)) {
|
||||
// Now find the next "{"
|
||||
auto matchStart = match.position() + match.length();
|
||||
auto openBracePos = data.find("{", matchStart);
|
||||
if(openBracePos == std::string::npos) {
|
||||
std::cout << "Failed to find open brace for class!" << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
// Match each of the class names
|
||||
std::regex regexClass("(public\\s+(\\w+))[,\\s{]+", regexFlags);
|
||||
std::sregex_iterator itClass(data.begin() + matchStart, data.begin() + openBracePos, regexClass);
|
||||
std::sregex_iterator endClass;
|
||||
while(itClass != endClass) {
|
||||
// Get the class name
|
||||
auto className = itClass->str(2);
|
||||
itClass++;
|
||||
|
||||
// We don't parse interface classes
|
||||
if(className[0] == 'I') continue;
|
||||
ruleset.extends.push_back(className);
|
||||
}
|
||||
}
|
||||
|
||||
// Find each instance of "@optional" when it's used within a comment
|
||||
// e.g. // @optional or /* @optional */ in the string data.1
|
||||
std::regex regex("^\\s*(?:\\/\\/|\\/\\*){1}\\s*\\@optional\\s*(?:\\*\\/)?\\s*$", regexFlags);
|
||||
std::sregex_iterator it(data.begin(), data.end(), regex);
|
||||
std::sregex_iterator end;
|
||||
while(it != end) {
|
||||
// Find the next ";"
|
||||
auto endPos = data.find(";", it->position() + it->length());
|
||||
if(endPos == std::string::npos) {
|
||||
std::cout << "Failed to find end of line for optional attribute!" << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
// Go backwards see if there's an equals sign after the match but before endPos
|
||||
auto equalsPos = data.rfind("=", endPos);
|
||||
|
||||
// If there's an equals sign, we search backwards from there,
|
||||
// otherwise we search backwards from the ;
|
||||
auto varStart = it->position() + it->length() + 1;
|
||||
size_t lastSearchPos = (
|
||||
(equalsPos == std::string::npos || equalsPos <= varStart) ?
|
||||
endPos :
|
||||
equalsPos
|
||||
);
|
||||
|
||||
// Now we have our string
|
||||
auto varLength = lastSearchPos - varStart;
|
||||
auto variableString = data.substr(varStart, varLength);
|
||||
|
||||
// Now (should) be able to extract the type;
|
||||
std::regex regex2("^\\s*(?:[\\S]+<)?([\\w*:_\\s]+)(?:[\\S]+)? (\\**[\\w]+)\\s*$", regexFlags);
|
||||
std::smatch match;
|
||||
if(!std::regex_search(variableString, match, regex2)) {
|
||||
std::cout << "Failed to extract type and name from variable string! " << variableString << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
// Now we have our type and name
|
||||
auto type = match[1].str();
|
||||
auto name = match[2].str();
|
||||
ruleset.selfOptional[name] = type;
|
||||
++it;
|
||||
}
|
||||
return ruleset;
|
||||
}
|
||||
|
||||
struct PrefabComponentParserRuleset PrefabRegistry::getRuleset(std::string type) {
|
||||
if(this->rulesets.find(type) != this->rulesets.end()) {
|
||||
return this->rulesets[type];
|
||||
}
|
||||
|
||||
std::vector<std::string> pathsToScan;
|
||||
pathsToScan.push_back(this->sources);
|
||||
|
||||
@ -34,87 +151,32 @@ struct PrefabComponentParserRuleset PrefabRegistry::getRuleset(std::string type)
|
||||
|
||||
|
||||
// Load ruleset
|
||||
std::string data;
|
||||
File file(str + "/" + itChildren->first);
|
||||
if(!file.readString(&data)) {
|
||||
std::cout << "Failed to read ruleset file!" << std::endl;
|
||||
return { .name = "" };
|
||||
auto parsed = PrefabRegistry::parseFile(&file, type);
|
||||
if(parsed.name == "") {
|
||||
std::cout << "Parsing error occured on " << type << std::endl;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
// Begin scanning contentsr
|
||||
// std::string include = this->sources;
|
||||
auto toRemove = File::normalizeSlashes(this->sources + FILE_PATH_SEP);
|
||||
auto includePath = file.filename.substr(toRemove.size(), file.filename.size() - toRemove.size());
|
||||
// Update optionals
|
||||
parsed.optional.insert(parsed.selfOptional.begin(), parsed.selfOptional.end());
|
||||
|
||||
// Now locate the first subdir since we don't want to include the root path (e.g. dawn, dawnrose, etc)
|
||||
auto firstSlash = includePath.find(FILE_PATH_SEP);
|
||||
if(firstSlash != std::string::npos) {
|
||||
includePath = includePath.substr(firstSlash + 1, includePath.size() - firstSlash - 1);
|
||||
}
|
||||
|
||||
struct PrefabComponentParserRuleset ruleset;
|
||||
// Replace all file seps with slashes
|
||||
size_t pos = 0;
|
||||
while ((pos = includePath.find(FILE_PATH_SEP, pos)) != std::string::npos) {
|
||||
includePath.replace(pos, 1, "/");
|
||||
pos += 1;
|
||||
}
|
||||
ruleset.include = includePath;
|
||||
ruleset.name = type;
|
||||
|
||||
// Find each instance of "@optional" when it's used within a comment
|
||||
// e.g. // @optional or /* @optional */ in the string data.
|
||||
|
||||
std::regex_constants::syntax_option_type regexFlags;
|
||||
#if defined(__GNUC__)
|
||||
regexFlags = std::regex_constants::ECMAScript | std::regex_constants::multiline;
|
||||
#else
|
||||
regexFlags = std::regex_constants::ECMAScript;
|
||||
#endif
|
||||
|
||||
std::regex regex("^\\s*(?:\\/\\/|\\/\\*){1}\\s*\\@optional\\s*(?:\\*\\/)?\\s*$", regexFlags);
|
||||
std::sregex_iterator it(data.begin(), data.end(), regex);
|
||||
std::sregex_iterator end;
|
||||
while(it != end) {
|
||||
// Find the next ";"
|
||||
auto endPos = data.find(";", it->position() + it->length());
|
||||
if(endPos == std::string::npos) {
|
||||
std::cout << "Failed to find end of line for optional attribute!" << std::endl;
|
||||
return { .name = "" };
|
||||
// Recursively parse children
|
||||
auto itExtends = parsed.extends.begin();
|
||||
while(itExtends != parsed.extends.end()) {
|
||||
auto ruleset = this->getRuleset(*itExtends);
|
||||
if(ruleset.name == "") {
|
||||
++itExtends;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Go backwards see if there's an equals sign after the match but before endPos
|
||||
auto equalsPos = data.rfind("=", endPos);
|
||||
|
||||
// If there's an equals sign, we search backwards from there,
|
||||
// otherwise we search backwards from the ;
|
||||
auto varStart = it->position() + it->length() + 1;
|
||||
size_t lastSearchPos = (
|
||||
(equalsPos == std::string::npos || equalsPos <= varStart) ?
|
||||
endPos :
|
||||
equalsPos
|
||||
);
|
||||
|
||||
// Now we have our string
|
||||
auto varLength = lastSearchPos - varStart;
|
||||
auto variableString = data.substr(varStart, varLength);
|
||||
|
||||
// Now (should) be able to extract the type;
|
||||
std::regex regex2("^\\s*(?:[\\S]+<)?([\\w*:_\\s]+)(?:[\\S]+)? (\\**[\\w]+)\\s*$", regexFlags);
|
||||
std::smatch match;
|
||||
if(!std::regex_search(variableString, match, regex2)) {
|
||||
std::cout << "Failed to extract type and name from variable string! " << variableString << std::endl;
|
||||
return { .name = "" };
|
||||
}
|
||||
|
||||
// Now we have our type and name
|
||||
auto type = match[1].str();
|
||||
auto name = match[2].str();
|
||||
ruleset.optional[name] = type;
|
||||
++it;
|
||||
// Merge ruleset
|
||||
parsed.optional.insert(ruleset.optional.begin(), ruleset.optional.end());
|
||||
++itExtends;
|
||||
}
|
||||
return ruleset;
|
||||
++itChildren;
|
||||
|
||||
this->rulesets[type] = parsed;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
it = pathsToScan.begin();
|
||||
|
@ -15,11 +15,20 @@ namespace Dawn {
|
||||
struct PrefabComponentParserRuleset {
|
||||
std::string name;
|
||||
std::string include;
|
||||
std::map<std::string, std::string> selfOptional;
|
||||
std::map<std::string, std::string> optional;
|
||||
std::vector<std::string> extends;
|
||||
};
|
||||
|
||||
|
||||
struct PrefabRegistry {
|
||||
std::string sources;
|
||||
std::map<std::string, struct PrefabComponentParserRuleset> rulesets;
|
||||
|
||||
struct PrefabComponentParserRuleset parseFile(
|
||||
File *file,
|
||||
std::string clazz
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets a prefab component ruleset for a specific scene item component type.
|
||||
|
Reference in New Issue
Block a user