ReiLuaGui basics.

This commit is contained in:
jussi
2022-12-01 23:15:54 +02:00
parent 08ef5b4352
commit 2479049e1a
6 changed files with 617 additions and 2 deletions

View File

@@ -0,0 +1,384 @@
util = require( "utillib" )
Rect = require( "rectangle" )
Vec2 = require( "vector2" )
-- NOTE!!! Work in progress! Do not use.
Gui = {
ALING = {
LEFT = 1,
RIGHT = 2,
CENTER = 3,
TOP = 1,
BOTTOM = 2,
},
CONTAINER = {
HORIZONTAL = 1,
VERTICAL = 2,
},
font = 0,
fontSize = 30,
textSpacing = 1,
padding = 2,
spacing = 4,
_elements = {},
}
function Gui.process( mousePosition )
for _, element in ipairs( Gui._elements ) do
if element.notMouseOver ~= nil then
element:notMouseOver()
end
end
-- Go backwards on process check so we trigger the top most ui first and stop there.
for i = #Gui._elements, 1, -1 do
local element = Gui._elements[i]
if element:isMouseOver( mousePosition ) and not element.disabled then
if element.isClicked ~= nil then
element:isClicked()
end
break
end
end
end
function Gui.draw()
for _, element in ipairs( Gui._elements ) do
if element.draw ~= nil and element.visible then
-- //TODO Check here if needs scrissor mode.
-- if element
element:draw()
end
end
end
-- Label
Label = {}
Label.__index = Label
function Label:new( set )
local o = {
_ID = #Gui._elements + 1,
bounds = set ~= nil and set.bounds ~= nil and set.bounds or Rect:new( 0, 0, 0, 0 ),
font = set ~= nil and set.font ~= nil and set.font or Gui.font,
text = set ~= nil and set.text ~= nil and set.text or "",
fontSize = set ~= nil and set.fontSize ~= nil and set.fontSize or Gui.fontSize,
textSpacing = set ~= nil and set.textSpacing ~= nil and set.textSpacing or Gui.textSpacing,
color = set ~= nil and set.color ~= nil and set.color or BLACK,
maxTextLen = set ~= nil and set.maxTextLen ~= nil and set.maxTextLen or nil,
padding = set ~= nil and set.padding ~= nil and set.padding or Gui.padding,
HAling = set ~= nil and set.HAling ~= nil and set.HAling or Gui.ALING.LEFT,
VAling = set ~= nil and set.VAling ~= nil and set.VAling or Gui.ALING.BOTTOM,
visible = set ~= nil and set.visible ~= nil and set.visible or true,
disabled = set ~= nil and set.disabled ~= nil and set.disabled or false,
drawBounds = set ~= nil and set.drawBounds ~= nil and set.drawBounds or false,
_textRect = Rect:new( 0, 0, 0, 0 ),
_visibilityBounds = nil,
-- Callbacks.
onMouseOver = set ~= nil and set.onMouseOver ~= nil and set.onMouseOver or nil,
notMouseOver = set ~= nil and set.notMouseOver ~= nil and set.notMouseOver or nil,
onClicked = set ~= nil and set.onClicked ~= nil and set.onClicked or nil,
}
setmetatable( o, self )
o:setText( o.text ) -- To measure bounds.
table.insert( Gui._elements, o )
return o
end
function Label:setText( text )
if self.maxTextLen ~= nil then
self.text = text:sub( 1, self.maxTextLen )
else
self.text = text
end
local textSize = Vec2:new( RL_MeasureText( self.font, self.text, self.fontSize, self.textSpacing ) )
-- Set bounds to text size if not given.
if self.bounds.width == nil then
self.bounds.width = textSize.x
end
if self.bounds.height == nil then
self.bounds.height = textSize.y
end
-- Horizontal aling.
if self.HAling == Gui.ALING.CENTER then
self._textRect.x = self.bounds.width / 2 - textSize.x / 2
elseif self.HAling == Gui.ALING.LEFT then
self._textRect.x = self.padding
elseif self.HAling == Gui.ALING.RIGHT then
self._textRect.x = self.bounds.width - textSize.x - self.padding
end
-- Vertical aling.
if self.VAling == Gui.ALING.CENTER then
self._textRect.y = self.bounds.height / 2 - textSize.y / 2
elseif self.VAling == Gui.ALING.TOP then
self._textRect.y = self.padding
elseif self.VAling == Gui.ALING.BOTTOM then
self._textRect.y = self.bounds.height - textSize.y - self.padding
end
self._textRect.width = textSize.x
self._textRect.height = textSize.y
end
function Label:setPosition( pos )
self.bounds.x = pos.x
self.bounds.y = pos.y
end
function Label:isMouseOver( mousePosition )
local over = RL_CheckCollisionPointRec( mousePosition, self.bounds )
if over and self._visibilityBounds ~= nil then
over = RL_CheckCollisionPointRec( mousePosition, self._visibilityBounds )
end
if over and self.onMouseOver ~= nil then
self:onMouseOver()
end
return over
end
function Label:isClicked()
local clicked = RL_IsMouseButtonPressed( MOUSE_BUTTON_LEFT )
if clicked and self.onClicked ~= nil then
self:onClicked()
end
return clicked
end
function Label:draw()
local usedScissor = false
if self._visibilityBounds ~= nil then
local rect = Rect:new( RL_GetCollisionRec( self.bounds, self._visibilityBounds ) )
-- Use scissor mode only on partyally visible.
if rect.width == 0 and rect.height == 0 then
return
elseif math.floor( rect.width ) ~= math.floor( self.bounds.width )
or math.floor( rect.height ) ~= math.floor( self.bounds.height ) then
usedScissor = true
RL_BeginScissorMode( self._visibilityBounds )
end
end
RL_DrawText( self.font, self.text, { self.bounds.x + self._textRect.x, self.bounds.y + self._textRect.y }, self.fontSize, self.textSpacing, self.color )
if self.drawBounds then
RL_DrawRectangleLines( self.bounds, self.color )
end
if usedScissor then
RL_EndScissorMode()
end
end
function Label:delete()
table.remove( Gui._elements, self._ID )
end
function Label:set2Top()
util.tableMove( Gui._elements, self._ID, 1, #Gui._elements )
end
function Label:set2Back()
util.tableMove( Gui._elements, self._ID, 1, 1 )
end
-- Panel.
Panel = {}
Panel.__index = Panel
function Panel:new( set )
local o = {
_ID = #Gui._elements + 1,
bounds = set ~= nil and set.bounds ~= nil and set.bounds or Rect:new( 0, 0, 0, 0 ),
color = set ~= nil and set.color ~= nil and set.color or LIGHTGRAY,
visible = set ~= nil and set.visible ~= nil and set.visible or true,
disabled = set ~= nil and set.disabled ~= nil and set.disabled or false,
}
setmetatable( o, self )
table.insert( Gui._elements, o )
return o
end
function Panel:setPosition( pos )
self.bounds.x = pos.x
self.bounds.y = pos.y
end
function Panel:isMouseOver( mousePosition )
return RL_CheckCollisionPointRec( mousePosition, self.bounds )
end
function Panel:draw()
RL_DrawRectangle( self.bounds, self.color )
end
function Panel:delete()
table.remove( Gui._elements, self._ID )
end
function Panel:set2Top()
util.tableMove( Gui._elements, self._ID, 1, #Gui._elements )
end
function Panel:set2Back()
util.tableMove( Gui._elements, self._ID, 1, 1 )
end
-- Container.
Container = {}
Container.__index = Container
function Container:new( set )
local o = {
_ID = #Gui._elements + 1,
bounds = set ~= nil and set.bounds ~= nil and set.bounds or Rect:new( 0, 0, 0, 0 ),
color = set ~= nil and set.color ~= nil and set.color or LIGHTGRAY,
spacing = set ~= nil and set.spacing ~= nil and set.spacing or Gui.spacing,
type = set ~= nil and set.type ~= nil and set.type or Gui.CONTAINER.VERTICAL,
HAling = set ~= nil and set.HAling ~= nil and set.HAling or Gui.ALING.LEFT,
VAling = set ~= nil and set.VAling ~= nil and set.VAling or Gui.ALING.TOP,
visible = set ~= nil and set.visible ~= nil and set.visible or true,
disabled = set ~= nil and set.disabled ~= nil and set.disabled or false,
drawBounds = set ~= nil and set.drawBounds ~= nil and set.drawBounds or false,
scrollable = set ~= nil and set.scrollable ~= nil and set.scrollable or false,
cells = {},
_visibilityBounds = nil, -- Will give this to it's children.
_scrollRect = Rect:new( 0, 0, 0, 0 ),
}
setmetatable( o, self )
table.insert( Gui._elements, o )
return o
end
function Container:setPosition( pos )
self.bounds.x = pos.x
self.bounds.y = pos.y
end
function Container:isMouseOver( mousePosition )
return RL_CheckCollisionPointRec( mousePosition, self.bounds )
end
function Container:add( cell )
table.insert( self.cells, cell )
self:update()
if cell.update ~= nil then
cell:update()
end
end
function Container:scroll( pos )
if not self.scrollable then
return
end
self._scrollRect.x = util.clamp( pos.x, 0, self._scrollRect.width - self.bounds.width )
self._scrollRect.y = util.clamp( pos.y, 0, self._scrollRect.height - self.bounds.height )
-- self._scrollRect.x = pos.x
-- self._scrollRect.y = pos.y
self:update()
end
function Container:update()
local pos = Vec2:new( self.bounds.x + self.spacing, self.bounds.y + self.spacing )
if self.scrollable then
self._visibilityBounds = self.bounds
self._scrollRect.width = 0
self._scrollRect.height = 0
end
for i, cell in ipairs( self.cells ) do
if self._visibilityBounds ~= nil then
cell._visibilityBounds = self._visibilityBounds
end
if self.type == Gui.CONTAINER.VERTICAL then
if self.HAling == Gui.ALING.CENTER then
pos.x = self.bounds.x + self.bounds.width / 2 - cell.bounds.width / 2
elseif self.HAling == Gui.ALING.RIGHT then
pos.x = self.bounds.x + self.bounds.width - cell.bounds.width - self.spacing
end
cell.bounds.x = pos.x - self._scrollRect.x
cell.bounds.y = pos.y - self._scrollRect.y
self._scrollRect.width = math.max( self._scrollRect.width, pos.x + cell.bounds.width + self.spacing - self.bounds.x )
self._scrollRect.height = math.max( self._scrollRect.height, pos.y + cell.bounds.height + self.spacing - self.bounds.y )
pos.y = pos.y + cell.bounds.height + self.spacing
elseif self.type == Gui.CONTAINER.HORIZONTAL then
if self.VAling == Gui.ALING.CENTER then
pos.y = self.bounds.y + self.bounds.height / 2 - cell.bounds.height / 2
elseif self.VAling == Gui.ALING.BOTTOM then
pos.y = self.bounds.y + self.bounds.height - cell.bounds.height - self.spacing
end
cell.bounds.x = pos.x - self._scrollRect.x
cell.bounds.y = pos.y - self._scrollRect.y
self._scrollRect.width = math.max( self._scrollRect.width, pos.x + cell.bounds.width + self.spacing - self.bounds.x )
self._scrollRect.height = math.max( self._scrollRect.height, pos.y + cell.bounds.height + self.spacing - self.bounds.y )
pos.x = pos.x + cell.bounds.width + self.spacing
end
if cell.update ~= nil then
cell:update()
end
end
end
function Container:draw()
if self.drawBounds then
RL_DrawRectangleLines( self.bounds, self.color )
RL_DrawRectangleLines( {
self.bounds.x - self._scrollRect.x,
self.bounds.y - self._scrollRect.y,
self._scrollRect.width,
self._scrollRect.height,
}, RED )
end
end
function Container:delete()
table.remove( Gui._elements, self._ID )
end
--Assingments.
Gui.label = Label
Gui.panel = Panel
Gui.container = Container
return Gui

View File

@@ -0,0 +1,87 @@
Rectangle = {}
Rectangle.meta = {
__index = Rectangle,
__tostring = function( r )
return "{"..tostring( r.x )..", "..tostring( r.y )..", "..tostring( r.width )..", "..tostring( r.height ).."}"
end,
-- __add = function( v1, v2 )
-- return Vector2:new( v1.x + v2.x, v1.y + v2.y )
-- end,
-- __sub = function( v1, v2 )
-- return Vector2:new( v1.x - v2.x, v1.y - v2.y )
-- end,
-- __mul = function( v1, v2 )
-- return Vector2:new( v1.x * v2.x, v1.y * v2.y )
-- end,
-- __div = function( v1, v2 )
-- return Vector2:new( v1.x / v2.x, v1.y / v2.y )
-- end,
-- __mod = function( v, value )
-- return Vector2:new( math.fmod( v.x, value ), math.fmod( v.y, value ) )
-- end,
-- __pow = function( v, value )
-- return Vector2:new( v.x ^ value, v.y ^ value )
-- end,
-- __unm = function( v )
-- return Vector2:new( -v.x, -v.y )
-- end,
-- __idiv = function( v, value )
-- return Vector2:new( v.x // value, v.y // value )
-- end,
-- __len = function( v )
-- local len = 0
-- for _, _ in pairs( v ) do
-- len = len + 1
-- end
-- return len
-- end,
-- __eq = function( v1, v2 )
-- return v1.x == v2.x and v1.y == v2.y
-- end,
}
function Rectangle:new( x, y, width, height )
if type( x ) == "table" then
x, y, width, height = table.unpack( x )
elseif type( x ) == "nil" then
x, y, width, height = 0, 0, 0, 0
end
local o = {
x = x,
y = y,
width = width,
height = height,
}
setmetatable( o, Rectangle.meta )
return o
end
function Rectangle:set( x, y, width, height )
if type( x ) == "table" then
x, y, width, height = table.unpack( x )
elseif type( x ) == "nil" then
x, y, width, height = 0, 0, 0, 0
end
self.x = x
self.y = y
self.width = width
self.height = height
end
function Rectangle:arr()
return { self.x, self.y, self.width, self.height }
end
function Rectangle:unpack()
return self.x, self.y, self.width, self.height
end
function Rectangle:clone()
return Rectangle:new( self.x, self.y, self.width, self.height )
end
return Rectangle

View File

@@ -163,4 +163,17 @@ function utillib.printt( t )
print( "}" )
end
-- Move secuence of elements inside table.
function utillib.tableMove( t, src, len, dest )
local copy = table.move( t, src, src + len - 1, 1, {} )
if src >= dest then
table.move( t, dest, src - 1, dest + len )
else
table.move( t, src + len, dest + len - 1, src )
end
table.move( copy, 1, len, dest, t )
end
return utillib