Fixed some bugs and added parsing

This commit is contained in:
2023-06-16 15:48:33 -07:00
parent 2964aa4a95
commit e6350d99e9
17 changed files with 157 additions and 42 deletions

View File

@ -25,6 +25,14 @@ float_t UIBorder::getContentHeight() {
return this->height;
}
float_t UIBorder::getChildOffsetX() {
return this->borderSize._realValue.x;
}
float_t UIBorder::getChildOffsetY() {
return this->borderSize._realValue.y;
}
std::vector<struct ShaderPassItem> UIBorder::getUIRenderPasses() {
struct ShaderPassItem item;
auto shader = getGame()->renderManager.uiShader;

View File

@ -24,6 +24,8 @@ namespace Dawn {
float_t getContentWidth() override;
float_t getContentHeight() override;
float_t getChildOffsetX() override;
float_t getChildOffsetY() override;
std::vector<struct ShaderPassItem> getUIRenderPasses() override;
void onStart() override;
};

View File

@ -62,6 +62,14 @@ float_t UICanvas::getContentHeight() {
return this->getHeight();
}
float_t UICanvas::getChildOffsetX() {
return 0.0f;
}
float_t UICanvas::getChildOffsetY() {
return 0.0f;
}
void UICanvas::onStart() {
if(camera == nullptr) camera = getScene()->findComponent<Camera>();

View File

@ -39,6 +39,20 @@ namespace Dawn {
* @return Content height of this item.
*/
virtual float_t getContentHeight() = 0;
/**
* Returns the offset of the child elements of this UI item.
*
* @return Offset of the child elements of this UI item.
*/
virtual float_t getChildOffsetX() = 0;
/**
* Returns the offset of the child elements of this UI item.
*
* @return Offset of the child elements of this UI item.
*/
virtual float_t getChildOffsetY() = 0;
};
enum UIDrawType {
@ -86,6 +100,8 @@ namespace Dawn {
float_t getHeight() override;
float_t getContentWidth() override;
float_t getContentHeight() override;
float_t getChildOffsetX() override;
float_t getChildOffsetY() override;
void onStart() override;
void onDispose() override;
};

View File

@ -39,8 +39,8 @@ void UIComponent::updateAlignment() {
assertNotNull(dimensional);
float_t parentWidth, parentHeight;
parentWidth = dimensional->getWidth();
parentHeight = dimensional->getHeight();
parentWidth = dimensional->getContentWidth();
parentHeight = dimensional->getContentHeight();
UIComponent::calculateDimensions(
this->alignX,
@ -63,6 +63,9 @@ void UIComponent::updateAlignment() {
glm::vec2(align[1], align[3])
);
translate.x += dimensional->getChildOffsetX();
translate.y += dimensional->getChildOffsetY();
this->transform->setLocalPosition(translate);
this->alignmentNeedsUpdating = false;
this->eventAlignmentUpdated.invoke();
@ -180,6 +183,14 @@ float_t UIComponent::getHeight() {
return this->height;
}
float_t UIComponent::getChildOffsetX() {
return 0;
}
float_t UIComponent::getChildOffsetY() {
return 0;
}
void UIComponent::onStart() {
useEffect([&]{
this->alignmentNeedsUpdating = true;

View File

@ -109,6 +109,8 @@ namespace Dawn {
float_t getWidth() override;
float_t getHeight() override;
float_t getChildOffsetX() override;
float_t getChildOffsetY() override;
void onStart() override;
friend class UICanvas;

View File

@ -25,7 +25,7 @@ void UILabel::onStart() {
}
std::vector<struct ShaderPassItem> UILabel::getUIRenderPasses() {
// if(this->texts.size() == 0) return {};
if(this->textsBuffered.empty()) return {};
auto canvas = this->getCanvas();
auto shader = getGame()->renderManager.fontShader;
@ -264,10 +264,12 @@ void UILabel::rebufferQuads(const std::vector<struct UILabelText> newTexts) {
}
// Create mesh
this->mesh.createBuffers(
QUAD_VERTICE_COUNT * vertices.size(),
QUAD_INDICE_COUNT * vertices.size()
);
if(!vertices.empty()) {
this->mesh.createBuffers(
QUAD_VERTICE_COUNT * vertices.size(),
QUAD_INDICE_COUNT * vertices.size()
);
}
// Now buffer the quads.
int32_t j = 0;

View File

@ -22,6 +22,11 @@ void UIRichTextLabel::onStart() {
struct UILabelStyle current;
styleStack.push_back(current);
std::vector<struct UILabelText> bufferTexts;
if(this->richText._realValue.empty()) {
this->rebufferQuads(bufferTexts);
return;
}
std::function<void(Xml*)> parseChildren = [&](Xml *node) {
if(node->children.empty()) {

View File

@ -9,6 +9,7 @@
namespace Dawn {
class UIRichTextLabel : public UILabel {
public:
// @innerXml
StateProperty<std::string> richText;
UIRichTextLabel(SceneItem *item);

View File

@ -8,6 +8,7 @@
#include "prefabs/SimpleSpinningCubePrefab.hpp"
#include "scene/components/display/Camera.hpp"
#include "scene/components/ui/text/UIRichTextLabel.hpp"
#include "prefabs/VNTextbox.hpp"
namespace Dawn {
class HelloWorldScene : public Scene {
@ -25,38 +26,15 @@ namespace Dawn {
auto canvas = canvasItem->addComponent<UICanvas>();
canvas->camera = camera;
auto newLabelItem = this->createSceneItem();
auto newLabel = newLabelItem->addComponent<UIRichTextLabel>();
newLabel->alignment = glm::vec4(0, 0, 0, 0);
newLabel->alignX = UI_COMPONENT_ALIGN_STRETCH;
newLabel->alignY = UI_COMPONENT_ALIGN_STRETCH;
// newLabel->maxWidth = 300.0f;
newLabel->richText = std::string(
"<font font=\"font_arial\" size=\"32\" color=\"COLOR_BLUE\">"
"Hello World\nHow are you?"
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
"</font>"
);
newLabelItem->transform.setParent(canvas->transform);
auto vnTextbox = VNTextbox::prefabCreate(this);
vnTextbox->transform.setParent(canvas->transform);
}
std::vector<Asset*> getRequiredAssets() override {
auto assMan = &this->game->assetManager;
std::vector<Asset*> assets;
vectorAppend(&assets, SimpleSpinningCubePrefab::getRequiredAssets(assMan));
assets.push_back(assMan->get<TrueTypeAsset>("font_arial"));
vectorAppend(&assets, VNTextbox::prefabAssets(assMan));
return assets;
}

View File

@ -31,6 +31,10 @@ void Xml::load(Xml *xml, std::string data, size_t *j) {
size_t i = *j;
while(c = data[i++]) {
if(insideTag) {
xml->outerXml += c;
}
switch(doing) {
case XML_PARSE_STATE_DOING_NOTHING:
if(c == '>') continue;
@ -49,15 +53,23 @@ void Xml::load(Xml *xml, std::string data, size_t *j) {
Xml::load(child, data, &i);
xml->children.push_back(child);
doing = XML_PARSE_STATE_PARSING_CHILD;
// Remove last char since we kinda already parsed it.
xml->innerXml += child->outerXml;
xml->outerXml = xml->outerXml.substr(0, xml->outerXml.size()-1);
xml->outerXml += child->outerXml;
}
} else {
doing = XML_PARSE_STATE_PARSING_TAG_NAME;
level++;
insideTag = true;
xml->outerXml += c;
}
continue;
}
xml->innerXml += c;
if(Xml::isWhitespace(c)) continue;
doing = XML_PARSE_STATE_PARSING_VALUE;
buffer += c;
@ -123,7 +135,9 @@ void Xml::load(Xml *xml, std::string data, size_t *j) {
case XML_PARSE_STATE_PARSING_ATTRIBUTE_VALUE:
// Parse the attribute value until we find a quote mark.
if(c == '"') {
if(c == '\\') {
c = data[i++];
} else if(c == '"') {
doing = XML_PARSE_STATE_LOOKING_FOR_ATTRIBUTE;
xml->attributes[attrKey] = buffer;
buffer = "";
@ -144,6 +158,8 @@ void Xml::load(Xml *xml, std::string data, size_t *j) {
continue;
}
xml->innerXml += c;
if(Xml::isWhitespace(c)) {
if(!valueIsInWhitespace) {
bufferWhitespaces.clear();
@ -183,9 +199,16 @@ void Xml::load(Xml *xml, std::string data, size_t *j) {
i -= 1;
Xml::load(child, data, &i);
xml->children.push_back(child);
xml->innerXml += child->outerXml;
xml->outerXml = xml->outerXml.substr(0, xml->outerXml.size()-1);
xml->outerXml += child->outerXml;
}
if(Xml::isWhitespace(c)) continue;
if(Xml::isWhitespace(c)) {
xml->innerXml += c;
continue;
}
// In HTML Spec there's a chance for there to be a value here, but not
// in the XML spec.

View File

@ -32,6 +32,8 @@ namespace Dawn {
std::string node;
std::string value;
std::string innerXml;
std::string outerXml;
std::map<std::string, std::string> attributes;
std::vector<Xml*> children;

View File

@ -12,6 +12,13 @@ namespace Dawn {
};
static inline std::string stringParser(std::string v, std::string *error) {
// Replace slashes and quotes
v = stringReplaceAll(v, "\\", "\\\\\\");
v = stringReplaceAll(v, "\"", "\\\"");
// Newlines.
v = stringReplaceAll(v, "\n", "\\n");
return "\"" + v + "\"";
};

View File

@ -125,4 +125,26 @@ static inline std::string stringToLowercase(const std::string &str) {
}
);
return data;
}
/**
* Replace all instances of a string with another string within a string.
*
* @param str String to replace the contents of.
* @param needle Needle to look for.
* @param replace String to replace the needle with.
* @return A new string instance with the replacements made.
*/
static inline std::string stringReplaceAll(
const std::string &str,
const std::string &needle,
const std::string &replace
) {
std::string newString = str;
size_t startPos = 0;
while((startPos = newString.find(needle, startPos)) != std::string::npos) {
newString.replace(startPos, needle.length(), replace);
startPos += replace.length();
}
return newString;
}

View File

@ -66,5 +66,15 @@ int32_t SceneItemComponentParser::onParse(
++itOptional;
}
auto itInnerXml = ruleset.innerXml.begin();
while(itInnerXml != ruleset.innerXml.end()) {
auto name = itInnerXml->first;
auto type = itInnerXml->second;
out->values[name] = stringParser(node->innerXml, error);
if(error->size() != 0) return 1;
++itInnerXml;
}
return 0;
}

View File

@ -76,14 +76,23 @@ struct SceneItemComponentRuleset SceneItemComponentRegistry::parseFile(
// 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::regex regex("^\\s*(?:\\/\\/|\\/\\*){1}\\s*\\@(optional|innerXml)\\s*(?:\\*\\/)?\\s*$", regexFlags);
std::sregex_iterator it(data.begin(), data.end(), regex);
std::sregex_iterator end;
while(it != end) {
// Extract the kind of parameter this is
std::smatch match;
if(!std::regex_search(data, match, regex)) {
std::cout << "Failed to determine parameter type!" << std::endl;
return { .name = "" };
}
std::string paramType = match[1].str();
// 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;
std::cout << "Failed to find end of line for attribute!" << std::endl;
return { .name = "" };
}
@ -105,16 +114,24 @@ struct SceneItemComponentRuleset SceneItemComponentRegistry::parseFile(
// 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::smatch match2;
if(!std::regex_search(variableString, match2, 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;
auto type = match2[1].str();
auto name = match2[2].str();
// Now store depending on the type
if(paramType == "optional") {
ruleset.selfOptional[name] = type;
} else if(paramType == "innerXml") {
ruleset.innerXml[name] = type;
} else {
assertUnreachable();
}
++it;
}
return ruleset;

View File

@ -16,6 +16,7 @@ namespace Dawn {
std::string name;
std::string include;
std::map<std::string, std::string> selfOptional;
std::map<std::string, std::string> innerXml;
std::map<std::string, std::string> optional;
std::vector<std::string> extends;
};