From 1c4f476f18b79cc8f3cea45723dd7ca981c1b2f5 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Tue, 25 Nov 2025 19:43:40 +0100 Subject: [PATCH] oh yeah its rewrite time --- examples/HelloUI/main.cpp | 15 ++- .../Crafter.Graphics-UiElement.cpp | 111 +++++++++++++----- implementations/Crafter.Graphics-Window.cpp | 9 ++ .../Crafter.Graphics-Window_wayland.cpp | 50 ++++---- implementations/main.cpp | 68 ----------- interfaces/Crafter.Graphics-UiElement.cppm | 75 ++++++++---- interfaces/Crafter.Graphics-Window.cppm | 9 +- 7 files changed, 183 insertions(+), 154 deletions(-) delete mode 100644 implementations/main.cpp diff --git a/examples/HelloUI/main.cpp b/examples/HelloUI/main.cpp index 0741907..f994317 100644 --- a/examples/HelloUI/main.cpp +++ b/examples/HelloUI/main.cpp @@ -6,7 +6,7 @@ using namespace Crafter; int main() { WindowWayland window(1280, 720, "Hello Input!"); - UiElement* element = new UiElement( + RenderingMouseElement element( 2, //bufferWidth: the width of this elements pixel buffer 1, //bufferHeight: the height of this elements pixel buffer FractionalToMapped(0.5), //anchorX: relative position where this elements x anchor (top-left) is placed to its parent x anchor @@ -19,14 +19,13 @@ int main() { false //ignoreScaling: wether this element ignores the scaling of the window, if true its size will be scaled according to the window scale ); - window.elements.push_back(element); - window.mouseElements.push_back(element); + window.elements.push_back(&element.rendering); + window.mouseElements.push_back(&element.mouse); - element->buffer = {{255, 0, 0 ,255}, {0, 255, 0 ,255}}; - element->UpdatePosition(window); - window.ScaleMouse(element->mouseTransform, element->transform); + element.rendering.buffer = {{255, 0, 0 ,255}, {0, 255, 0 ,255}}; + element.UpdatePosition(window); - EventListener clickListener(&element->onMouseLeftClick, [element, &window](MousePoint point){ + EventListener clickListener(&element.mouse.onMouseLeftClick, [&element, &window](MousePoint point){ // Print the coordinates where the user clicked relative to the element's top left corner. //Mapped space @@ -36,7 +35,7 @@ int main() { std::cout << std::format("Clicked on Fraction X:{} Y:{}!", MappedToFractionalBoundless(point.x), MappedToFractionalBoundless(point.y)) << std::endl; // Screen space - std::cout << std::format("Clicked on Screen X:{} Y:{}!\n", MappedToPixelBoundless(point.x, MappedToPixelBoundless(element->mouseTransform.scaled.width, window.width)), MappedToPixelBoundless(point.y, window.height)) << std::endl; + std::cout << std::format("Clicked on Screen X:{} Y:{}!\n", MappedToPixelBoundless(point.x, MappedToPixelBoundless(element.mouse.transform.scaled.width, window.width)), MappedToPixelBoundless(point.y, MappedToPixelBoundless(element.mouse.transform.scaled.width, window.height))) << std::endl; }); window.Render(); diff --git a/implementations/Crafter.Graphics-UiElement.cpp b/implementations/Crafter.Graphics-UiElement.cpp index 5a38262..e4ca310 100644 --- a/implementations/Crafter.Graphics-UiElement.cpp +++ b/implementations/Crafter.Graphics-UiElement.cpp @@ -31,37 +31,41 @@ import std; using namespace Crafter; -Transform::Transform(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : anchorX(anchorX), anchorY(anchorY), relativeWidth(relativeWidth), relativeHeight(relativeHeight), anchorOffsetX(anchorOffsetX), anchorOffsetY(anchorOffsetY), z(z), ignoreScaling(ignoreScaling) { +Transform::Transform(void* element, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : element(element), anchorX(anchorX), anchorY(anchorY), relativeWidth(relativeWidth), relativeHeight(relativeHeight), anchorOffsetX(anchorOffsetX), anchorOffsetY(anchorOffsetY), z(z), ignoreScaling(ignoreScaling) { } -UiElement::UiElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : transform(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling), mouseTransform(FractionalToMapped(0), FractionalToMapped(0), FractionalToMapped(1), FractionalToMapped(1), FractionalToMapped(0), FractionalToMapped(0), 0, false) { +RenderingElement::RenderingElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : transform(this, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling) { } -UiElement::UiElement(std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : transform(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling), bufferWidth(bufferWidth), bufferHeight(bufferHeight), buffer(bufferWidth*bufferHeight), mouseTransform(FractionalToMapped(0), FractionalToMapped(0), FractionalToMapped(1), FractionalToMapped(1), FractionalToMapped(0), FractionalToMapped(0), 0, false) { +RenderingElement::RenderingElement(std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : bufferWidth(bufferWidth), bufferHeight(bufferHeight), buffer(bufferWidth*bufferHeight), transform(this, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling) { } -UiElement::UiElement(const std::string_view imagePath, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : transform(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling), mouseTransform(FractionalToMapped(0), FractionalToMapped(0), FractionalToMapped(1), FractionalToMapped(1), FractionalToMapped(0), FractionalToMapped(0), 0, false) { +RenderingElement::RenderingElement(const std::string_view imagePath, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : transform(this, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling) { RenderImage(imagePath); } -UiElement::UiElement(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 pixel, Font& font, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : transform(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling), mouseTransform(FractionalToMapped(0), FractionalToMapped(0), FractionalToMapped(1), FractionalToMapped(1), FractionalToMapped(0), FractionalToMapped(0), 0, false) { +RenderingElement::RenderingElement(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 pixel, Font& font, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : transform(this, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling) { RenderText(text, size, pixel, font); } -UiElement::UiElement(Transform transform) : transform(transform), mouseTransform(FractionalToMapped(0), FractionalToMapped(0), FractionalToMapped(1), FractionalToMapped(1), FractionalToMapped(0), FractionalToMapped(0), 0, false) { +RenderingElement::RenderingElement(Transform transform) : transform(transform) { } -void UiElement::ResizeBuffer(std::uint_fast32_t width, std::uint_fast32_t height) { +RenderingElement::RenderingElement(Transform transform, std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight) : transform(transform), bufferWidth(bufferWidth), bufferHeight(bufferHeight), buffer(bufferWidth*bufferHeight) { + +} + +void RenderingElement::ResizeBuffer(std::uint_fast32_t width, std::uint_fast32_t height) { this->bufferWidth = width; this->bufferHeight = height; buffer.resize(width * height); } -void UiElement::RenderImage(const std::string_view path) { +void RenderingElement::RenderImage(const std::string_view path) { std::filesystem::path abs = std::filesystem::absolute(path); int xSize; int ySize; @@ -80,7 +84,7 @@ void UiElement::RenderImage(const std::string_view path) { } } -void UiElement::RenderText(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 color, Font& font) { +void RenderingElement::RenderText(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 color, Font& font) { buffer.clear(); float scale = stbtt_ScaleForPixelHeight(&font.font, size); @@ -127,25 +131,7 @@ void UiElement::RenderText(const std::string_view text, float size, Pixel_BU8_GU } } -void UiElement::UpdatePosition(Window& window) { - window.ScaleElement(transform); - scaled.resize(transform.scaled.width * transform.scaled.height); - CopyNearestNeighbour(scaled.data(), transform.scaled.width, transform.scaled.height); - for(UiElement* child : children) { - child->UpdatePosition(window, *this); - } -} - -void UiElement::UpdatePosition(Window& window, UiElement& parent) { - window.ScaleElement(transform, parent.transform); - scaled.resize(transform.scaled.width * transform.scaled.height); - CopyNearestNeighbour(scaled.data(),transform.scaled.width, transform.scaled.height); - for(UiElement* child : children) { - UpdatePosition(window, *child); - } -} - -void UiElement::CopyNearestNeighbour(Pixel_BU8_GU8_RU8_AU8* dst, std::uint_fast32_t dstWidth, std::uint_fast32_t dstHeight) const { +void RenderingElement::CopyNearestNeighbour(Pixel_BU8_GU8_RU8_AU8* dst, std::uint_fast32_t dstWidth, std::uint_fast32_t dstHeight) const { for (std::uint_fast32_t y = 0; y < dstHeight; y++) { std::uint_fast32_t srcY = y * bufferHeight / dstHeight; for (std::uint_fast32_t x = 0; x < dstWidth; x++) { @@ -153,4 +139,73 @@ void UiElement::CopyNearestNeighbour(Pixel_BU8_GU8_RU8_AU8* dst, std::uint_fast3 dst[y * dstWidth + x] = buffer[srcY * bufferWidth + srcX]; } } +} + +void RenderingElement::UpdatePosition(Window& window) { + window.ScaleElement(transform); + scaled.resize(transform.scaled.width * transform.scaled.height); + CopyNearestNeighbour(scaled.data(), transform.scaled.width, transform.scaled.height); + for(Transform* child : transform.children) { + reinterpret_cast(child->element)->UpdatePosition(window, transform); + } +} + +void RenderingElement::UpdatePosition(Window& window, Transform& parent) { + window.ScaleElement(transform, parent); + scaled.resize(transform.scaled.width * transform.scaled.height); + CopyNearestNeighbour(scaled.data(), transform.scaled.width, transform.scaled.height); + for(Transform* child : transform.children) { + reinterpret_cast(child->element)->UpdatePosition(window, transform); + } +} + + +// MouseElement implementation +MouseElement::MouseElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : transform(this, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling) { + +} + +MouseElement::MouseElement(Transform transform) : transform(transform) { + +} + +void MouseElement::UpdatePosition(Window& window) { + window.ScaleMouse(transform); + for(Transform* child : transform.children) { + reinterpret_cast(child->element)->UpdatePosition(window, transform); + } +} + +void MouseElement::UpdatePosition(Window& window, Transform& parent) { + window.ScaleMouse(transform, parent); + for(Transform* child : transform.children) { + reinterpret_cast(child->element)->UpdatePosition(window, transform); + } +} + + +RenderingMouseElement::RenderingMouseElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : rendering(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling), mouse(FractionalToMapped(0), FractionalToMapped(0), FractionalToMapped(1), FractionalToMapped(1), FractionalToMapped(0), FractionalToMapped(0), 0, false) { + +} + +RenderingMouseElement::RenderingMouseElement(std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : rendering(bufferWidth, bufferHeight, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling), mouse(FractionalToMapped(0), FractionalToMapped(0), FractionalToMapped(1), FractionalToMapped(1), FractionalToMapped(0), FractionalToMapped(0), 0, false) { + +} + +RenderingMouseElement::RenderingMouseElement(const std::string_view imagePath, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : rendering(imagePath, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling), mouse(FractionalToMapped(0), FractionalToMapped(0), FractionalToMapped(1), FractionalToMapped(1), FractionalToMapped(0), FractionalToMapped(0), 0, false) { + +} + +RenderingMouseElement::RenderingMouseElement(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 pixel, Font& font, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : rendering(text, size, pixel, font, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling), mouse(FractionalToMapped(0), FractionalToMapped(0), FractionalToMapped(1), FractionalToMapped(1), FractionalToMapped(0), FractionalToMapped(0), 0, false) { + +} + +RenderingMouseElement::RenderingMouseElement(Transform transform, Transform mouseTransform) : rendering(transform), mouse(mouseTransform) { + +} + + +void RenderingMouseElement::UpdatePosition(Window& window) { + rendering.UpdatePosition(window); + mouse.UpdatePosition(window, rendering.transform); } \ No newline at end of file diff --git a/implementations/Crafter.Graphics-Window.cpp b/implementations/Crafter.Graphics-Window.cpp index 34f9d58..afd21ae 100644 --- a/implementations/Crafter.Graphics-Window.cpp +++ b/implementations/Crafter.Graphics-Window.cpp @@ -51,3 +51,12 @@ void Window::ScaleMouse(Transform& element, Transform& parent) { element.scaled.x = MappedToPixelBoundless(element.anchorX, boundlessWidth) - MappedToPixelBoundless(element.anchorOffsetX, element.scaled.width) + PixelToMappedBoundless(parent.scaled.x, width); element.scaled.y = MappedToPixelBoundless(element.anchorY, boundlessHeight) - MappedToPixelBoundless(element.anchorOffsetY, element.scaled.height) + PixelToMappedBoundless(parent.scaled.y, height); } + +void Window::ScaleMouse(Transform& element) { +// std::int_fast32_t boundlessWidth = PixelToMappedBoundless(parent.scaled.width, width); +// std::int_fast32_t boundlessHeight = PixelToMappedBoundless(parent.scaled.height, height); +// element.scaled.width = BoundToBoundless(MappedToPixel(element.relativeWidth, width)); +// element.scaled.height = BoundToBoundless(MappedToPixel(element.relativeHeight, height)); +// element.scaled.x = MappedToPixelBoundless(element.anchorX, boundlessWidth) - MappedToPixelBoundless(element.anchorOffsetX, element.scaled.width) + PixelToMappedBoundless(parent.scaled.x, width); +// element.scaled.y = MappedToPixelBoundless(element.anchorY, boundlessHeight) - MappedToPixelBoundless(element.anchorOffsetY, element.scaled.height) + PixelToMappedBoundless(parent.scaled.y, height); +} diff --git a/implementations/Crafter.Graphics-Window_wayland.cpp b/implementations/Crafter.Graphics-Window_wayland.cpp index 9bb5c32..0062da7 100644 --- a/implementations/Crafter.Graphics-Window_wayland.cpp +++ b/implementations/Crafter.Graphics-Window_wayland.cpp @@ -135,7 +135,7 @@ void WindowWayland::StartSync() { -void RenderElement(UiElement* element, WindowWayland* window) { +void RenderElement(RenderingElement* element, WindowWayland* window) { for (std::int_fast32_t x = element->transform.scaled.x; x - element->transform.scaled.x < element->transform.scaled.width; x++) { for (std::int_fast32_t y = element->transform.scaled.y; y - element->transform.scaled.y < element->transform.scaled.height; y++) { if (x >= 0 && x < window->width && y >= 0 && y < window->height) { @@ -157,14 +157,14 @@ void RenderElement(UiElement* element, WindowWayland* window) { } } } - std::sort(element->children.begin(), element->children.end(), [](UiElement* a, UiElement* b){ return a->transform.z < b->transform.z; }); - for(UiElement* child : element->children) { - RenderElement(child, window); + std::sort(element->transform.children.begin(), element->transform.children.end(), [](Transform* a, Transform* b){ return a->z < b->z; }); + for(Transform* child : element->transform.children) { + RenderElement(reinterpret_cast(child->element), window); } } void WindowWayland::Render() { - std::sort(elements.begin(), elements.end(), [](UiElement* a, UiElement* b){ return a->transform.z < b->transform.z; }); + std::sort(elements.begin(), elements.end(), [](RenderingElement* a, RenderingElement* b){ return a->transform.z < b->transform.z; }); for (std::uint_fast32_t x = 0; x < width; x++) { for (std::uint_fast32_t y = 0; y - height; y++) { @@ -172,7 +172,7 @@ void WindowWayland::Render() { } } - for(UiElement* element : elements) { + for(RenderingElement* element : elements) { RenderElement(element, this); } @@ -260,17 +260,17 @@ void WindowWayland::pointer_handle_button(void* data, wl_pointer* pointer, std:: if(state == WL_POINTER_BUTTON_STATE_PRESSED) { window->mouseLeftHeld = true; window->onMouseLeftClick.Invoke(window->currentMousePos); - for(UiElement* element : window->mouseElements) { - if(window->currentMousePos.x >= element->mouseTransform.scaled.x && window->currentMousePos.x <= element->mouseTransform.scaled.x+element->mouseTransform.scaled.width && window->currentMousePos.y > element->mouseTransform.scaled.y && window->currentMousePos.y < element->mouseTransform.scaled.y+element->mouseTransform.scaled.height) { - element->onMouseLeftClick.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->mouseTransform.scaled.x) / element->mouseTransform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->mouseTransform.scaled.y) / element->mouseTransform.scaled.height)}); + for(MouseElement* element : window->mouseElements) { + if(window->currentMousePos.x >= element->transform.scaled.x && window->currentMousePos.x <= element->transform.scaled.x+element->transform.scaled.width && window->currentMousePos.y > element->transform.scaled.y && window->currentMousePos.y < element->transform.scaled.y+element->transform.scaled.height) { + element->onMouseLeftClick.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->transform.scaled.x) / element->transform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->transform.scaled.y) / element->transform.scaled.height)}); } } } else { window->mouseLeftHeld = false; window->onMouseLeftRelease.Invoke(window->currentMousePos); - for(UiElement* element : window->mouseElements) { - if(window->currentMousePos.x >= element->mouseTransform.scaled.x && window->currentMousePos.x <= element->mouseTransform.scaled.x+element->mouseTransform.scaled.width && window->currentMousePos.y > element->mouseTransform.scaled.y && window->currentMousePos.y < element->mouseTransform.scaled.y+element->mouseTransform.scaled.height) { - element->onMouseLeftRelease.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->mouseTransform.scaled.x) / element->mouseTransform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->mouseTransform.scaled.y) / element->mouseTransform.scaled.height)}); + for(MouseElement* element : window->mouseElements) { + if(window->currentMousePos.x >= element->transform.scaled.x && window->currentMousePos.x <= element->transform.scaled.x+element->transform.scaled.width && window->currentMousePos.y > element->transform.scaled.y && window->currentMousePos.y < element->transform.scaled.y+element->transform.scaled.height) { + element->onMouseLeftRelease.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->transform.scaled.x) / element->transform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->transform.scaled.y) / element->transform.scaled.height)}); } } } @@ -278,17 +278,17 @@ void WindowWayland::pointer_handle_button(void* data, wl_pointer* pointer, std:: if(state == WL_POINTER_BUTTON_STATE_PRESSED) { window->mouseRightHeld = true; window->onMouseRightClick.Invoke(window->currentMousePos); - for(UiElement* element : window->mouseElements) { - if(window->currentMousePos.x >= element->mouseTransform.scaled.x && window->currentMousePos.x <= element->mouseTransform.scaled.x+element->mouseTransform.scaled.width && window->currentMousePos.y > element->mouseTransform.scaled.y && window->currentMousePos.y < element->mouseTransform.scaled.y+element->mouseTransform.scaled.height) { - element->onMouseRightClick.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->mouseTransform.scaled.x) / element->mouseTransform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->mouseTransform.scaled.y) / element->mouseTransform.scaled.height)}); + for(MouseElement* element : window->mouseElements) { + if(window->currentMousePos.x >= element->transform.scaled.x && window->currentMousePos.x <= element->transform.scaled.x+element->transform.scaled.width && window->currentMousePos.y > element->transform.scaled.y && window->currentMousePos.y < element->transform.scaled.y+element->transform.scaled.height) { + element->onMouseRightClick.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->transform.scaled.x) / element->transform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->transform.scaled.y) / element->transform.scaled.height)}); } } } else { window->mouseRightHeld = true; window->onMouseRightRelease.Invoke(window->currentMousePos); - for(UiElement* element : window->mouseElements) { - if(window->currentMousePos.x >= element->mouseTransform.scaled.x && window->currentMousePos.x <= element->mouseTransform.scaled.x+element->mouseTransform.scaled.width && window->currentMousePos.y > element->mouseTransform.scaled.y && window->currentMousePos.y < element->mouseTransform.scaled.y+element->mouseTransform.scaled.height) { - element->onMouseRightRelease.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->mouseTransform.scaled.x) / element->mouseTransform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->mouseTransform.scaled.y) / element->mouseTransform.scaled.height)}); + for(MouseElement* element : window->mouseElements) { + if(window->currentMousePos.x >= element->transform.scaled.x && window->currentMousePos.x <= element->transform.scaled.x+element->transform.scaled.width && window->currentMousePos.y > element->transform.scaled.y && window->currentMousePos.y < element->transform.scaled.y+element->transform.scaled.height) { + element->onMouseRightRelease.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->transform.scaled.x) / element->transform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->transform.scaled.y) / element->transform.scaled.height)}); } } } @@ -302,14 +302,14 @@ void WindowWayland::PointerListenerHandleMotion(void* data, wl_pointer* wl_point window->currentMousePos = pos; window->mouseDelta = {window->currentMousePos.x-window->lastMousePos.x, window->currentMousePos.y-window->lastMousePos.y}; window->onMouseMove.Invoke({window->lastMousePos, window->currentMousePos, window->mouseDelta}); - for(UiElement* element : window->mouseElements) { - if(window->currentMousePos.x >= element->mouseTransform.scaled.x && window->currentMousePos.x <= element->mouseTransform.scaled.x+element->mouseTransform.scaled.width && window->currentMousePos.y > element->mouseTransform.scaled.y && window->currentMousePos.y < element->mouseTransform.scaled.y+element->mouseTransform.scaled.height) { - element->onMouseMove.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->mouseTransform.scaled.x) / element->mouseTransform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->mouseTransform.scaled.y) / element->mouseTransform.scaled.height)}); - if(!(window->lastMousePos.x >= element->mouseTransform.scaled.x && window->lastMousePos.x <= element->mouseTransform.scaled.x+element->mouseTransform.scaled.width && window->lastMousePos.y > element->mouseTransform.scaled.y && window->lastMousePos.y < element->mouseTransform.scaled.y+element->mouseTransform.scaled.height)) { - element->onMouseEnter.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->mouseTransform.scaled.x) / element->mouseTransform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->mouseTransform.scaled.y) / element->mouseTransform.scaled.height)}); + for(MouseElement* element : window->mouseElements) { + if(window->currentMousePos.x >= element->transform.scaled.x && window->currentMousePos.x <= element->transform.scaled.x+element->transform.scaled.width && window->currentMousePos.y > element->transform.scaled.y && window->currentMousePos.y < element->transform.scaled.y+element->transform.scaled.height) { + element->onMouseMove.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->transform.scaled.x) / element->transform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->transform.scaled.y) / element->transform.scaled.height)}); + if(!(window->lastMousePos.x >= element->transform.scaled.x && window->lastMousePos.x <= element->transform.scaled.x+element->transform.scaled.width && window->lastMousePos.y > element->transform.scaled.y && window->lastMousePos.y < element->transform.scaled.y+element->transform.scaled.height)) { + element->onMouseEnter.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->transform.scaled.x) / element->transform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->transform.scaled.y) / element->transform.scaled.height)}); } - } else if(window->lastMousePos.x >= element->mouseTransform.scaled.x && window->lastMousePos.x <= element->mouseTransform.scaled.x+element->mouseTransform.scaled.width && window->lastMousePos.y > element->mouseTransform.scaled.y && window->lastMousePos.y < element->mouseTransform.scaled.y+element->mouseTransform.scaled.height) { - element->onMouseLeave.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->mouseTransform.scaled.x) / element->mouseTransform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->mouseTransform.scaled.y) / element->mouseTransform.scaled.height)}); + } else if(window->lastMousePos.x >= element->transform.scaled.x && window->lastMousePos.x <= element->transform.scaled.x+element->transform.scaled.width && window->lastMousePos.y > element->transform.scaled.y && window->lastMousePos.y < element->transform.scaled.y+element->transform.scaled.height) { + element->onMouseLeave.Invoke({FractionalToMappedBoundless(static_cast(window->currentMousePos.x - element->transform.scaled.x) / element->transform.scaled.width), FractionalToMappedBoundless(static_cast(window->currentMousePos.y - element->transform.scaled.y) / element->transform.scaled.height)}); } } } diff --git a/implementations/main.cpp b/implementations/main.cpp deleted file mode 100644 index 7c49a8f..0000000 --- a/implementations/main.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -Crafter®.Graphics -Copyright (C) 2025 Catcrafts® -Catcrafts.net - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 3.0 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include -#include -#include -#include -#include -#include "../../lib/VulkanInitializers.hpp" - -import Crafter.Graphics; -import Crafter.Asset; -import Crafter.Event; -import Crafter.Math; -using namespace Crafter; - -typedef VulkanShader<"MeshShaderMixedVoxelGrid.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT, 2, {{{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}}}> MeshVulkanShader; -typedef VulkanShader<"FragmentShaderVertexColor.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT, 0, {}> FragmentShader; -typedef VulkanPipeline Pipeline; - -int main() { - VulkanDevice::CreateDevice(); - MeshVulkanShader::CreateShader(); - FragmentShader::CreateShader(); - Pipeline::CreatePipeline(); - - WindowWaylandVulkan window("Crafter.Graphics", 1280, 720); - - Camera camera(1.57079633, 1280.0f / 720.0f, 0.01, 512); - camera.view = MatrixRowMajor::Translation(0, 0, 10); - camera.Update(); - VkCommandBuffer cmd = window.StartInit(); - - DescriptorSet descriptors; - VoxelShader meshShader(1, 4, 4, &camera); - for(uint32_t i = 0; i < 16; i++) { - meshShader.grid.value[i] = 1; - } - meshShader.WriteDescriptors(descriptors.set[0]); - meshShader.Update(); - - window.FinishInit(); - - EventListener listener(&window.onDraw, [&descriptors, &meshShader](VkCommandBuffer cmd){ - vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, Pipeline::pipelineLayout, 0, 2, &descriptors.set[0], 0, NULL); - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, Pipeline::pipeline); - VulkanDevice::vkCmdDrawMeshTasksEXTProc(cmd, meshShader.threadCount, 1, 1); - }); - - window.StartSync(); -} \ No newline at end of file diff --git a/interfaces/Crafter.Graphics-UiElement.cppm b/interfaces/Crafter.Graphics-UiElement.cppm index 8dbe014..1b11dec 100644 --- a/interfaces/Crafter.Graphics-UiElement.cppm +++ b/interfaces/Crafter.Graphics-UiElement.cppm @@ -25,6 +25,7 @@ import :Types; export namespace Crafter { class Transform { public: + void* element; std::int_fast32_t z; std::int_fast32_t anchorX; std::int_fast32_t anchorY; @@ -34,15 +35,43 @@ export namespace Crafter { std::uint_fast32_t relativeHeight; bool ignoreScaling; ScaleData scaled; - Transform(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + std::vector children; + Transform(void* element, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); }; class Window; class Font; - class UiElement { + + // Base class for rendering elements + class RenderingElement { + public: + Transform transform; + std::vector buffer; + std::vector scaled; + std::uint_fast32_t bufferWidth; + std::uint_fast32_t bufferHeight; + + RenderingElement(Transform transform); + RenderingElement(Transform transform, std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight); + RenderingElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + RenderingElement(std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + RenderingElement(const std::string_view imagePath, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + RenderingElement(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 pixel, Font& font, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + RenderingElement(RenderingElement&) = delete; + RenderingElement& operator=(RenderingElement&) = delete; + + void ResizeBuffer(std::uint_fast32_t width, std::uint_fast32_t height); + void CopyNearestNeighbour(Pixel_BU8_GU8_RU8_AU8* dst, std::uint_fast32_t dstWidth, std::uint_fast32_t dstHeight) const; + void RenderText(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 pixel, Font& font); + void RenderImage(const std::string_view path); + void UpdatePosition(Window& window); + void UpdatePosition(Window& window, Transform& parent); + }; + + // Base class for Mouse elements + class MouseElement { public: Transform transform; - Transform mouseTransform; Event onMouseMove; Event onMouseEnter; Event onMouseLeave; @@ -52,24 +81,28 @@ export namespace Crafter { Event onMouseLeftHold; Event onMouseRightRelease; Event onMouseLeftRelease; - std::vector children; - std::vector buffer; - std::vector scaled; - std::uint_fast32_t bufferWidth; - std::uint_fast32_t bufferHeight; - - UiElement(const std::string_view imagePath, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); - UiElement(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 pixel, Font& font, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); - UiElement(std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); - UiElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); - UiElement(Transform transform); - UiElement(UiElement&) = delete; - UiElement& operator=(UiElement&) = delete; - void ResizeBuffer(std::uint_fast32_t width, std::uint_fast32_t height); + + MouseElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + MouseElement(Transform transform); + MouseElement(MouseElement&) = delete; + MouseElement& operator=(MouseElement&) = delete; void UpdatePosition(Window& window); - void UpdatePosition(Window& window, UiElement& parent); - void CopyNearestNeighbour(Pixel_BU8_GU8_RU8_AU8* dst, std::uint_fast32_t dstWidth, std::uint_fast32_t dstHeight) const; - void RenderText(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 pixel, Font& font); - void RenderImage(const std::string_view path); + void UpdatePosition(Window& window, Transform& parent); + }; + + // Combined UI element that can have both rendering and interaction + class RenderingMouseElement { + public: + RenderingElement rendering; + MouseElement mouse; + RenderingMouseElement(const std::string_view imagePath, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + RenderingMouseElement(const std::string_view text, float size, Pixel_BU8_GU8_RU8_AU8 pixel, Font& font, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + RenderingMouseElement(std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + RenderingMouseElement(std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX = FractionalToMapped(0.5), std::int_fast32_t anchorOffsetY = FractionalToMapped(0.5), std::int_fast32_t z = 0, bool ignoreScaling = false); + RenderingMouseElement(Transform transform, Transform mouseTransform); + RenderingMouseElement(RenderingMouseElement&) = delete; + RenderingMouseElement& operator=(RenderingMouseElement&) = delete; + void UpdatePosition(Window& window); + void UpdatePosition(Window& window, Transform& parent); }; } \ No newline at end of file diff --git a/interfaces/Crafter.Graphics-Window.cppm b/interfaces/Crafter.Graphics-Window.cppm index 5fb1e2a..aab11cb 100644 --- a/interfaces/Crafter.Graphics-Window.cppm +++ b/interfaces/Crafter.Graphics-Window.cppm @@ -44,7 +44,6 @@ import :Types; import Crafter.Event; export namespace Crafter { - class UiElement; class Transform; class Window { public: @@ -67,6 +66,7 @@ export namespace Crafter { void ScaleElement(Transform& element, Transform& parent); void ScaleElement(Transform& element); void ScaleMouse(Transform& element, Transform& parent); + void ScaleMouse(Transform& element); }; class WindowKeyboard { @@ -80,6 +80,7 @@ export namespace Crafter { Event onAnyKeyUp; }; + class MouseElement; class WindowMouse { public: Event onMouseRightClick; @@ -97,7 +98,7 @@ export namespace Crafter { MousePoint mouseDelta; bool mouseLeftHeld = false; bool mouseRightHeld = false; - std::vector mouseElements; + std::vector mouseElements; }; class WindowTitle { @@ -121,11 +122,11 @@ export namespace Crafter { }; #ifdef CRAFTER_GRAPHICS_WAYLAND - class UiElementBufferBuffer; + class RenderingElement; class WindowWayland final : public WindowKeyboard, public WindowMouse, public WindowFramebuffer, public WindowTitle { public: Pixel_BU8_GU8_RU8_AU8* framebuffer = nullptr; - std::vector elements; + std::vector elements; WindowWayland(std::uint_fast32_t width, std::uint_fast32_t height); WindowWayland(std::uint_fast32_t width, std::uint_fast32_t height, const std::string_view title); ~WindowWayland();