From 79908a12a572fd2699afe83ca2081511880449a1 Mon Sep 17 00:00:00 2001 From: antopilo Date: Sat, 14 Sep 2024 13:54:23 -0400 Subject: [PATCH] More accurate text size when using px font-size. Added CSS imports to canvas sourceFiles for live reload + started implement descendant css rules --- Nuake/src/UI/Nodes/Canvas.cpp | 64 ++++++++++--------- Nuake/src/UI/Nodes/Text.cpp | 10 +-- Nuake/src/UI/Parsers/CanvasParser.cpp | 1 + Nuake/src/UI/Parsers/StyleSheetParser.cpp | 76 +++++++++++++++++++++-- Nuake/src/UI/Renderer.cpp | 3 +- Nuake/src/UI/Styles/StyleSheet.h | 3 +- 6 files changed, 115 insertions(+), 42 deletions(-) diff --git a/Nuake/src/UI/Nodes/Canvas.cpp b/Nuake/src/UI/Nodes/Canvas.cpp index aafd1bf1..dc2c4585 100644 --- a/Nuake/src/UI/Nodes/Canvas.cpp +++ b/Nuake/src/UI/Nodes/Canvas.cpp @@ -104,46 +104,48 @@ namespace NuakeUI for (auto& rule : mStyleSheet->Rules) { bool respectSelector = true; + // TODO: Apply descendant selectors to child nodes. for (StyleSelector& selector : rule.Selector) { bool foundSelector = false; + switch (selector.Type) { - case StyleSelectorType::Class: + case StyleSelectorType::Class: + { + for (auto& c : node->Classes) { - for (auto& c : node->Classes) - { - if (c == selector.Value) - foundSelector = true; - } - break; - } - case StyleSelectorType::Pseudo: - { - const bool isHover = selector.Value == "hover" && node->State == NodeState::Hover; - const bool isActive = selector.Value == "active" && node->State == NodeState::Clicked; - if (isHover || isActive) - { + if (c == selector.Value) foundSelector = true; - } - break; } - case StyleSelectorType::Id: + break; + } + case StyleSelectorType::Pseudo: + { + const bool isHover = selector.Value == "hover" && node->State == NodeState::Hover; + const bool isActive = selector.Value == "active" && node->State == NodeState::Clicked; + if (isHover || isActive) { - if (selector.Value == node->GetID()) - { - foundSelector = true; - } - break; + foundSelector = true; } - case StyleSelectorType::Tag: + break; + } + case StyleSelectorType::Id: + { + if (selector.Value == node->GetID()) { - if (selector.Value == node->GetType()) - { - foundSelector = true; - } - break; + foundSelector = true; } + break; + } + case StyleSelectorType::Tag: + { + if (selector.Value == node->GetType()) + { + foundSelector = true; + } + break; + } } if (!foundSelector) @@ -153,7 +155,11 @@ namespace NuakeUI } if (respectSelector) - node->ApplyStyleProperties(rule.Properties); + { + + } + + node->ApplyStyleProperties(rule.Properties); } for (auto& c : node->GetChildrens()) diff --git a/Nuake/src/UI/Nodes/Text.cpp b/Nuake/src/UI/Nodes/Text.cpp index 03b5382c..825f6a0d 100644 --- a/Nuake/src/UI/Nodes/Text.cpp +++ b/Nuake/src/UI/Nodes/Text.cpp @@ -22,7 +22,7 @@ namespace NuakeUI mFont = Renderer::Get().mDefaultFont; SetText(text); - float height = ((mFont->LineHeight) / 32.f) * ComputedStyle.FontSize * Lines.size(); + float height = ((mFont->LineHeight) / 32.f) * (ComputedStyle.FontSize * 2.0) * Lines.size(); YGNodeStyleSetHeight(mNode, height); YGNodeStyleSetMinHeight(mNode, height); YGNodeStyleSetMinWidth(mNode, CalculateWidth()); @@ -63,7 +63,7 @@ namespace NuakeUI float y = YGNodeLayoutGetTop(mNode); // Centers the text in the line height. - y += (ComputedStyle.FontFamily->LineHeight / 64.0f) * (ComputedStyle.FontSize) / 2.0f; + y += (ComputedStyle.FontFamily->LineHeight / 64.0f) * (ComputedStyle.FontSize * 2.0) / 2.0f; x += YGNodeLayoutGetPadding(mNode, YGEdgeLeft); y += YGNodeLayoutGetPadding(mNode, YGEdgeTop); @@ -100,7 +100,7 @@ namespace NuakeUI //glScissor(clipX, clipY, clipWidth, clipHeight); } - const float lineYOffset = (ComputedStyle.FontFamily->LineHeight / 32.0f) * (ComputedStyle.FontSize); + const float lineYOffset = (ComputedStyle.FontFamily->LineHeight / 32.0f) * (ComputedStyle.FontSize * 2.0); // Draw each line and offset the Y of the position by the line height. for(int i = 0; i < Lines.size(); i++) { @@ -120,7 +120,7 @@ namespace NuakeUI // If theres no text, then assume it's 0; if (Lines.size() == 0) return 0.f; - const float fontSize = ComputedStyle.FontSize / 64.f; + const float fontSize = ComputedStyle.FontSize * 2.0 / 64.f; // Find the largest line. float maxWidth = 0.f; @@ -145,7 +145,7 @@ namespace NuakeUI void Text::Calculate() { const float halfLineHeight = ComputedStyle.FontFamily->LineHeight / 32.f; - const float linesHeight = Lines.size() * ComputedStyle.FontSize; + const float linesHeight = Lines.size() * ComputedStyle.FontSize * 2.0; YGNodeStyleSetHeight(mNode, halfLineHeight * linesHeight); YGNodeStyleSetWidth(mNode, CalculateWidth()); } diff --git a/Nuake/src/UI/Parsers/CanvasParser.cpp b/Nuake/src/UI/Parsers/CanvasParser.cpp index 149fb15c..10d90938 100644 --- a/Nuake/src/UI/Parsers/CanvasParser.cpp +++ b/Nuake/src/UI/Parsers/CanvasParser.cpp @@ -365,6 +365,7 @@ Ref CanvasParser::Parse(CanvasPtr canvas, const std::string& path) } } + canvas->AddSourceFile(FileSystem::GetFile(FileSystem::AbsoluteToRelative(path))); canvas->SetRoot(root); IterateOverElement(firstNode, root); diff --git a/Nuake/src/UI/Parsers/StyleSheetParser.cpp b/Nuake/src/UI/Parsers/StyleSheetParser.cpp index ecf880f8..94d8e22b 100644 --- a/Nuake/src/UI/Parsers/StyleSheetParser.cpp +++ b/Nuake/src/UI/Parsers/StyleSheetParser.cpp @@ -181,35 +181,64 @@ void StyleSheetParser::ParseStyleRule(KatanaRule* rule, StyleSheetPtr styleSheet while (selector) { auto match = selector->match; // tag, id or class + StyleSelector currentStyleSelector = {}; switch (match) { case KatanaSelectorMatchPseudoClass: { std::string matchPseudo = selector->data->value; - styleSelector.push_back({ StyleSelectorType::Pseudo, matchPseudo }); + KatanaPseudoType pseudoType = selector->pseudo; + KatanaSelectorRelation relation = selector->relation; + currentStyleSelector.Type = StyleSelectorType::Pseudo; + currentStyleSelector.Value = matchPseudo; } break; case KatanaSelectorMatchTag: { std::string matchTag = selector->tag->local; - styleSelector.push_back({ StyleSelectorType::Tag, matchTag }); + currentStyleSelector.Type = StyleSelectorType::Tag; + currentStyleSelector.Value = matchTag; } break; case KatanaSelectorMatchId: { std::string matchId = selector->data->value; - styleSelector.push_back({ StyleSelectorType::Id, matchId }); + currentStyleSelector.Type = StyleSelectorType::Id; + currentStyleSelector.Value = matchId; } break; case KatanaSelectorMatchClass: { std::string matchClass = selector->data->value; - styleSelector.push_back({ StyleSelectorType::Class, matchClass }); + currentStyleSelector.Type = StyleSelectorType::Class; + currentStyleSelector.Value = matchClass; } break; } + KatanaSelectorRelation relation = selector->relation; + switch (relation) + { + case KatanaSelectorRelationDescendant: + currentStyleSelector.SelectorRelation = Relation::Descendant; + break; + + case KatanaSelectorRelationChild: + currentStyleSelector.SelectorRelation = Relation::Child; + break; + + case KatanaSelectorRelationSubSelector: + currentStyleSelector.SelectorRelation = Relation::SubSelection; + break; + + default: + currentStyleSelector.SelectorRelation = Relation::None; + break; + } + selector = selector->tagHistory; + + styleSelector.push_back(currentStyleSelector); } // Added the new rule with selectors. @@ -234,7 +263,7 @@ void StyleSheetParser::ParseStyleRule(KatanaRule* rule, StyleSheetPtr styleSheet switch (value->unit) { - case KatanaValueUnit::KATANA_VALUE_STRING: + case KatanaValueUnit::KATANA_VALUE_STRING: { std::string stringValue = value->string; if (propType == StyleProperties::BackgroundImage || propType == StyleProperties::Font) @@ -260,6 +289,43 @@ void StyleSheetParser::ParseStyleRule(KatanaRule* rule, StyleSheetPtr styleSheet propValue.type = PropValueType::Color; } break; + case KatanaValueUnit::KATANA_VALUE_RGBCOLOR: + { + int r, g, b, a = 255; + Logger::Log("RGB COLOR DETECTED" + std::string(value->string)); + propValue.value.Color = Color(r, g, b, a); + propValue.type = PropValueType::Color; + } + break; + case KatanaValueUnit::KATANA_VALUE_PARSER_FUNCTION: + { + const std::string& functionName = std::string(value->function->name); + if (functionName == "rgb(" || functionName == "rgba(") + { + int r = 0, g = 0, b = 0, a = 255; + int colorChannel = 0; // commas are considered as args. + for (int i = 0; i < value->function->args->length; i++) + { + KatanaValue* arg = reinterpret_cast(value->function->args->data[i]); + if (arg->unit == KatanaValueUnit::KATANA_VALUE_NUMBER) // Check if it's a number + { + int colorComponent = static_cast(arg->fValue); // Retrieve float value and cast to int + + // Assign to r, g, b based on index + if (colorChannel == 0) r = colorComponent; + else if (colorChannel == 1) g = colorComponent; + else if (colorChannel == 2) b = colorComponent; + else if (colorChannel == 4) a = colorComponent; + + colorChannel++; + } + } + + propValue.value.Color = Color(r, g, b, a); + propValue.type = PropValueType::Color; + } + } + break; case KatanaValueUnit::KATANA_VALUE_UNKNOWN: { std::string valueStr = value->string; diff --git a/Nuake/src/UI/Renderer.cpp b/Nuake/src/UI/Renderer.cpp index 0f2598e9..e28fa035 100644 --- a/Nuake/src/UI/Renderer.cpp +++ b/Nuake/src/UI/Renderer.cpp @@ -94,7 +94,6 @@ void Renderer::DrawNode(std::shared_ptr node, int z) const float left = YGNodeLayoutGetLeft(yogaNode); const float top = YGNodeLayoutGetTop(yogaNode) - parentScroll; const float borderLeft = YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft); - float parentLeft = 0.f; float parentTop = 0.f; @@ -158,7 +157,7 @@ void Renderer::DrawNode(std::shared_ptr node, int z) void Renderer::DrawString(const std::string& string, NodeStyle& nodeStyle, std::shared_ptr font, Vector3 position) { - const float fontSize = nodeStyle.FontSize / 64.f; + const float fontSize = nodeStyle.FontSize * 2.0 / 64.f; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); mSDFShader->Bind(); diff --git a/Nuake/src/UI/Styles/StyleSheet.h b/Nuake/src/UI/Styles/StyleSheet.h index bfc3683d..bd80c59b 100644 --- a/Nuake/src/UI/Styles/StyleSheet.h +++ b/Nuake/src/UI/Styles/StyleSheet.h @@ -83,11 +83,12 @@ namespace NuakeUI // Selector enum class StyleSelectorType { Id, Class, Tag, Pseudo }; - + enum class Relation { None, Descendant, Child, SubSelection }; struct StyleSelector { StyleSelectorType Type; std::string Value; + Relation SelectorRelation; }; class StyleRule