#GUI logic

13 messages · Page 1 of 1 (latest)

exotic hill
#

I need help with implementing the logic of anchoring to a location aswell as putting things in relation to their parent. The rendering logic is completly fine. Its just the positions are not what i want and i dont know how to fix it.

gui::Rect2D rect2;
rect2.extent = { 200, 200 };
rect2.anchorParent = gui::Anchor::TopLeft;
rect2.anchorSelf = gui::Anchor::TopLeft;
rect2.offset = { 0, 0 };
mesh = rect2.refreshMesh(windowExtent);
StaticRenderable testRend2(mesh);
testRend2.draw();
        
gui::Rect2D rect3;
rect3.extent = { 100, 100 };
rect3.parent = &rect2;
rect3.anchorParent = gui::Anchor::MiddleMiddle;
rect3.anchorSelf = gui::Anchor::MiddleMiddle;
rect3.offset = { 0, 0 };
mesh = rect3.refreshMesh(windowExtent);
StaticRenderable testRend3(mesh);
testRend3.draw();

This is how i define my rectangles. I want to, at the end of it, have the parent anchor point overlap with the child anchor point, + any offset, for example: Trying to bind a childs MiddleLeft anchor point to the parents MiddleRight anchor point with 50 x offset, should cause 50 pixels of space between the two objects.

More stuff coming

copper mapleBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

exotic hill
#
class Rect2D {
public:
    // if nullptr, parent has extend of window
    Rect2D* parent = nullptr;                    
    // where to anchor to parent
    Anchor anchorParent = Anchor::MiddleMiddle; 
    // what point on self to anchor to parent
    Anchor anchorSelf = Anchor::MiddleMiddle;    
        
    // How big the object is
    Extent extent;
    // Offset from the anchor point on parent, eg -> make it +20 pixels from RightMiddle with LeftMiddle to have 20 pixels between them
    Offset offset;  
    inline void dirty() { _dirty = true; }
    bool isDirty() const { return _dirty; }
    // recursivly gets the true position
    Point truePosition(const Extent& windowExtent) const;
    // clean wrapper for _dirty
    virtual gfx::Mesh refreshMesh(const Extent windowExtent);

    // mesh getter
    inline gfx::Mesh getMesh() { return mesh; }

private:
    inline void _clean() { _dirty = false; }
    gfx::Mesh mesh;
    bool _dirty = true;
};

This is my Rect2D header

#

and i have these helper structs

#
struct Offset {
    int x = 0;
    int y = 0;
    Offset  operator+ (const Offset& other) const;
    Offset& operator+=(const Offset& other);
};
typedef Offset LocalOffset;
struct Point : Offset {
    glm::vec2 normalize(Extent windowExtent) const;
    // operator overloads
    Point  operator+ (const Offset& other) const;
    Point& operator+=(const Offset& other);


};
struct Extent {
    LocalOffset getOffsetOnSelf(Anchor anchor) const;
    int x = 0;
    int y = 0;
};

Conceptually, a point is the same as an offset, but in relation to the window. thats why i used a subclass

#

local offset as a concept in my head refers to where to find an anchor point in relation to the top left corner of an object

#

This is my current calculation implementation

#
////////// RECT2D //////////
Point Rect2D::truePosition(const Extent& windowExtent) const {
    Point result;
    Extent parentExtent = parent ? parent->extent : windowExtent;

    LocalOffset selfOffset = extent.getOffsetOnSelf(anchorSelf);
    LocalOffset parentOffset = parentExtent.getOffsetOnSelf(anchorParent);

    // recursion
    Point parentPosition = parent ? parent->truePosition(windowExtent) : Point{ 0, 0 };
    // Calculate the true position
    result = parentPosition + parentOffset + offset;
    return result;
}

gfx::Mesh Rect2D::refreshMesh(Extent windowExtent) {
    gfx::Mesh result;

    // Initialize with quad
    result.vertices = {
        gfx::Vertex{ glm::vec3(0.0f, 0.0f, 0.0f), glm::vec2(1.0f, 1.0f) },
        gfx::Vertex{ glm::vec3(0.0f, 0.0f, 0.0f), glm::vec2(1.0f, 0.0f) },
        gfx::Vertex{ glm::vec3(0.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f) },
        gfx::Vertex{ glm::vec3(0.0f, 0.0f, 0.0f), glm::vec2(0.0f, 1.0f) }
    };
    result.indices = { 0, 1, 3, 1, 2, 3 };

    // Get the true position of the object
    Point topLeft = truePosition(windowExtent);
    Point topRight = topLeft + Point{ extent.x, 0 };
    Point bottomRight = topLeft + Point{ extent.x, extent.y };
    Point bottomLeft = topLeft + Point{ 0, extent.y };

    // put the points into the mesh as normalized
    result.vertices[0].position = glm::vec3(topLeft.normalize(windowExtent), 0.0f);
    result.vertices[1].position = glm::vec3(topRight.normalize(windowExtent), 0.0f);
    result.vertices[2].position = glm::vec3(bottomRight.normalize(windowExtent), 0.0f);
    result.vertices[3].position = glm::vec3(bottomLeft.normalize(windowExtent), 0.0f);

    // Mark as clean and return the result
    _clean();
    mesh = result;
    return result;
}
#

More helper functions that should be correct

////////// OFFSET //////////
Offset  Offset::operator+ (const Offset& other) const { return { x + other.x, y + other.y }; }
Offset& Offset::operator+=(const Offset& other) { x += other.x; y += other.y; return *this; }

////////// POINT ////////// 
glm::vec2 Point::normalize(Extent windowExtent) const {
    float normalizedX = static_cast<float>(x) / static_cast<float>(windowExtent.x) - 1.0f;
    float normalizedY = static_cast<float>(y) / static_cast<float>(windowExtent.y) - 1.0f;
    return glm::vec2(normalizedX, normalizedY);
}
Point Point::operator+(const Offset& other) const { return { x + other.x, y + other.y }; }
Point& Point::operator+=(const Offset& other) { x += other.x; y += other.y; return *this; }


////////// EXTEND //////////
Offset Extent::getOffsetOnSelf(Anchor anchor) const {
    switch (anchor) {
    case Anchor::TopLeft:        return { 0     , 0     };
    case Anchor::TopMiddle:      return { x / 2 , 0     };
    case Anchor::TopRight:       return { x     , 0     };

    case Anchor::MiddleLeft:     return { 0     , y / 2 };
    case Anchor::MiddleMiddle:   return { x / 2 , y / 2 };
    case Anchor::MiddleRight:    return { x     , y / 2 };
        
    case Anchor::BottomLeft:     return { 0     , y     };
    case Anchor::BottomMiddle:   return { x / 2 , y     };
    case Anchor::BottomRight:    return { x     , y     };
    default:                     return { 0     , 0     };
    }
}
#

The rectangles described very far above end up at these locations

#

i hope that is enough data to actually help me lmao

exotic hill
#

issue was in normilization and one value had to be negative

#

!solved