Using `margin` is interesting, but, what if I want to put
elements outside of the window? How I need to do this?
If I change window size, element still will be outside.
In element I need to add size
//In slGUIElement
slVec2f m_size;
And I need to change alignment.
I think it will be better to use it as flags
enum Alignment
{
Left = 0x1,
Top = 0x2,
Right = 0x4,
Bottom = 0x8,
Center = Left | Top | Right | Bottom
};
Alignment m_alignment = Alignment::Center;
If size is 0,0 then elements rectangle will be rebuilded
using only margin. If there is size, then `margin` will play `position` role.
And in this case alignment will be applied.
Now, I think... I can create elements without problems.
Rebuild button. First, it will build rects using button parameters,
second, it will take parent rects (and scroll?) and will update rects.
Bebuild rectangles is common thing for all elements so implement Bebuild()
in slGUIElement
void slGUIElement::Rebuild()
{
slGUIElement* parent = dynamic_cast<slGUIElement*>(GetParent());
if (parent)
{
// build buildRect using margin
m_buildRect.x = parent->m_buildRect.x + m_margin.x;
m_buildRect.y = parent->m_buildRect.y + m_margin.y;
// if width or height != 0 then do not use m_margin
if (m_size.x != 0.f)
m_buildRect.z = m_buildRect.x + m_size.x;
else
m_buildRect.z = parent->m_buildRect.z - m_margin.z;
if (m_size.y != 0.f)
m_buildRect.w = m_buildRect.y + m_size.y;
else
m_buildRect.w = parent->m_buildRect.w - m_margin.w;
// scrolling here somewhere
// usuially m_clipRect is == m_buildRect;
m_clipRect = m_buildRect;
// but parent has own clip rect
if (m_clipRect.x < parent->m_clipRect.x)
m_clipRect.x = parent->m_clipRect.x;
if (m_clipRect.y < parent->m_clipRect.y)
m_clipRect.y = parent->m_clipRect.y;
if (m_clipRect.z > parent->m_clipRect.z)
m_clipRect.z = parent->m_clipRect.z;
if (m_clipRect.w > parent->m_clipRect.w)
m_clipRect.w = parent->m_clipRect.w;
m_activeRect = m_clipRect;
// maybe here callback
// OnRects(); or OnRebuild();
}
// else
// only root element without parent
// rebuild root in slGUIWindow::Rebuild();
}
This code without scrolling and alignment.
I need to rebuild root element before rebuild other elements.
Rebuilding will be in GUI window, because root elements must have
area == area of window.
Now it's time to make all that mouse interactions.
All basic things like `mous enter rect` or 'mouse leave'
is common thing for element and for window, so implement
slGUICommon::Update
void slGUICommon::Update(slInputData* id)
{
if (slMath::pointInRect(id->mousePosition, m_activeRect))
{
if ((m_flags & slGUICommon::flag_cursorInRect) == 0)
OnMouseEnter();
m_flags |= slGUICommon::flag_cursorInRect;
}
else
{
if(IsCursorInRect())
OnMouseLeave();
m_flags &= ~slGUICommon::flag_cursorInRect;
}
if (IsEnabled() && IsCursorInRect())
{
if (slInput::IsLMBHit())
{
m_flags |= slGUICommon::flag_clickedLMB;
OnClickLMB();
}
else if (slInput::IsLMBRelease())
{
if (IsClickedLMB())
OnReleaseLMB();
}
if (slInput::IsRMBHit())
{
m_flags |= slGUICommon::flag_clickedRMB;
OnClickRMB();
}
else if (slInput::IsRMBRelease())
{
if (IsClickedRMB())
OnReleaseRMB();
}
if (slInput::IsMMBHit())
{
m_flags |= slGUICommon::flag_clickedMMB;
OnClickMMB();
}
else if (slInput::IsMMBRelease())
{
if (IsClickedMMB())
OnReleaseMMB();
}
if (slInput::IsX1MBHit())
{
m_flags |= slGUICommon::flag_clickedX1MB;
OnClickX1MB();
}
else if (slInput::IsX1MBRelease())
{
if (IsClickedX1MB())
OnReleaseX1MB();
}
if (slInput::IsX2MBHit())
{
m_flags |= slGUICommon::flag_clickedX2MB;
OnClickX2MB();
}
else if (slInput::IsX2MBRelease())
{
if (IsClickedX2MB())
OnReleaseX2MB();
}
}
// I need to remove flags when cursor outside of rect
if (slInput::IsLMBRelease())
m_flags &= ~slGUICommon::flag_clickedLMB;
if (slInput::IsRMBRelease())
m_flags &= ~slGUICommon::flag_clickedRMB;
if (slInput::IsMMBRelease())
m_flags &= ~slGUICommon::flag_clickedMMB;
if (slInput::IsX1MBRelease())
m_flags &= ~slGUICommon::flag_clickedX1MB;
if (slInput::IsX2MBRelease())
m_flags &= ~slGUICommon::flag_clickedX2MB;
}
And I moved all that OnMouseEnter OnClickLMB... methods in slGUICommon
I need to save all that states when mouse entered the area, or area was
clicked by mouse, I added new flags for this, and methods
I forgot something. I want to create GUI elements by creating derived classes.
I need to think how I can do this. Probably, constructor of slGUIElement must
ask slGUWindow for argument