immediate mode scroll regression fixed
This commit is contained in:
75
FlexLove.lua
75
FlexLove.lua
@@ -9,6 +9,7 @@ local utils = req("utils")
|
||||
local Units = req("Units")
|
||||
local Context = req("Context")
|
||||
local StateManager = req("StateManager")
|
||||
local ErrorHandler = req("ErrorHandler")
|
||||
---@type Element
|
||||
local Element = req("Element")
|
||||
|
||||
@@ -26,6 +27,7 @@ local flexlove = Context
|
||||
|
||||
-- Initialize Units module with Context dependency
|
||||
Units.initialize(Context)
|
||||
Units.initializeErrorHandler(ErrorHandler)
|
||||
|
||||
-- Add version and metadata
|
||||
flexlove._VERSION = "0.1.0"
|
||||
@@ -480,10 +482,10 @@ function flexlove.keypressed(key, scancode, isrepeat)
|
||||
end
|
||||
end
|
||||
|
||||
function flexlove.wheelmoved(x, y)
|
||||
function flexlove.wheelmoved(dx, dy)
|
||||
local mx, my = love.mouse.getPosition()
|
||||
|
||||
local function findScrollableAtPosition(elements, mx, my)
|
||||
local function findScrollableAtPosition(elements, x, y)
|
||||
for i = #elements, 1, -1 do
|
||||
local element = elements[i]
|
||||
|
||||
@@ -492,9 +494,9 @@ function flexlove.wheelmoved(x, y)
|
||||
local bw = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right)
|
||||
local bh = element._borderBoxHeight or (element.height + element.padding.top + element.padding.bottom)
|
||||
|
||||
if mx >= bx and mx <= bx + bw and my >= by and my <= by + bh then
|
||||
if x >= bx and x <= bx + bw and y >= by and y <= by + bh then
|
||||
if #element.children > 0 then
|
||||
local childResult = findScrollableAtPosition(element.children, mx, my)
|
||||
local childResult = findScrollableAtPosition(element.children, x, y)
|
||||
if childResult then
|
||||
return childResult
|
||||
end
|
||||
@@ -521,20 +523,79 @@ function flexlove.wheelmoved(x, y)
|
||||
local bw = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right)
|
||||
local bh = element._borderBoxHeight or (element.height + element.padding.top + element.padding.bottom)
|
||||
|
||||
if mx >= bx and mx <= bx + bw and my >= by and my <= by + bh then
|
||||
-- Calculate scroll offset from parent chain
|
||||
local scrollOffsetX = 0
|
||||
local scrollOffsetY = 0
|
||||
local current = element.parent
|
||||
while current do
|
||||
local overflowX = current.overflowX or current.overflow
|
||||
local overflowY = current.overflowY or current.overflow
|
||||
local hasScrollableOverflow = (
|
||||
overflowX == "scroll"
|
||||
or overflowX == "auto"
|
||||
or overflowY == "scroll"
|
||||
or overflowY == "auto"
|
||||
or overflowX == "hidden"
|
||||
or overflowY == "hidden"
|
||||
)
|
||||
if hasScrollableOverflow then
|
||||
scrollOffsetX = scrollOffsetX + (current._scrollX or 0)
|
||||
scrollOffsetY = scrollOffsetY + (current._scrollY or 0)
|
||||
end
|
||||
current = current.parent
|
||||
end
|
||||
|
||||
-- Adjust mouse position by scroll offset
|
||||
local adjustedMx = mx + scrollOffsetX
|
||||
local adjustedMy = my + scrollOffsetY
|
||||
|
||||
-- Check if mouse is within element bounds
|
||||
if adjustedMx >= bx and adjustedMx <= bx + bw and adjustedMy >= by and adjustedMy <= by + bh then
|
||||
-- Check if mouse position is clipped by any parent
|
||||
local isClipped = false
|
||||
local parentCheck = element.parent
|
||||
while parentCheck do
|
||||
local parentOverflowX = parentCheck.overflowX or parentCheck.overflow
|
||||
local parentOverflowY = parentCheck.overflowY or parentCheck.overflow
|
||||
|
||||
if parentOverflowX == "hidden" or parentOverflowX == "scroll" or parentOverflowX == "auto" or
|
||||
parentOverflowY == "hidden" or parentOverflowY == "scroll" or parentOverflowY == "auto" then
|
||||
local parentX = parentCheck.x + parentCheck.padding.left
|
||||
local parentY = parentCheck.y + parentCheck.padding.top
|
||||
local parentW = parentCheck.width
|
||||
local parentH = parentCheck.height
|
||||
|
||||
if mx < parentX or mx > parentX + parentW or my < parentY or my > parentY + parentH then
|
||||
isClipped = true
|
||||
break
|
||||
end
|
||||
end
|
||||
parentCheck = parentCheck.parent
|
||||
end
|
||||
|
||||
if not isClipped then
|
||||
local overflowX = element.overflowX or element.overflow
|
||||
local overflowY = element.overflowY or element.overflow
|
||||
if (overflowX == "scroll" or overflowX == "auto" or overflowY == "scroll" or overflowY == "auto") and (element._overflowX or element._overflowY) then
|
||||
element:_handleWheelScroll(x, y)
|
||||
element:_handleWheelScroll(dx, dy)
|
||||
|
||||
-- Save scroll position to StateManager immediately in immediate mode
|
||||
if element._stateId then
|
||||
StateManager.updateState(element._stateId, {
|
||||
_scrollX = element._scrollX,
|
||||
_scrollY = element._scrollY,
|
||||
})
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- In retained mode, use the old tree traversal method
|
||||
local scrollableElement = findScrollableAtPosition(flexlove.topElements, mx, my)
|
||||
if scrollableElement then
|
||||
scrollableElement:_handleWheelScroll(x, y)
|
||||
scrollableElement:_handleWheelScroll(dx, dy)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 01: Flex Positioning
|
||||
|
||||
This example demonstrates flexbox layouts in FlexLove:
|
||||
- Flex direction (horizontal/vertical)
|
||||
- Justify content (main axis alignment)
|
||||
- Align items (cross axis alignment)
|
||||
- Flex wrap behavior
|
||||
|
||||
Run with: love /path/to/libs/examples/01_flex_positioning.lua
|
||||
]]
|
||||
|
||||
-- Map Love to Lv to avoid duplicate definitions
|
||||
local Lv = love
|
||||
|
||||
-- Load FlexLove from parent directory
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
-- Initialize FlexLove with base scaling
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 },
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 01: Flex Positioning",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 1: Horizontal Flex with Different JustifyContent Values
|
||||
-- ========================================
|
||||
|
||||
local yOffset = 10
|
||||
|
||||
-- Label for justify-content section
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = yOffset .. "vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Horizontal Flex - JustifyContent Options",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
yOffset = yOffset + 4
|
||||
|
||||
-- Demonstrate each justify-content option
|
||||
local justifyOptions = {
|
||||
{ name = "flex-start", value = enums.JustifyContent.FLEX_START },
|
||||
{ name = "center", value = enums.JustifyContent.CENTER },
|
||||
{ name = "flex-end", value = enums.JustifyContent.FLEX_END },
|
||||
{ name = "space-between", value = enums.JustifyContent.SPACE_BETWEEN },
|
||||
{ name = "space-around", value = enums.JustifyContent.SPACE_AROUND },
|
||||
{ name = "space-evenly", value = enums.JustifyContent.SPACE_EVENLY },
|
||||
}
|
||||
|
||||
for _, option in ipairs(justifyOptions) do
|
||||
-- Label for this justify option
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = yOffset .. "vh",
|
||||
width = "15vw",
|
||||
height = "3vh",
|
||||
text = option.name,
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(0.8, 0.8, 1, 1),
|
||||
textAlign = enums.TextAlign.START,
|
||||
})
|
||||
|
||||
-- Container demonstrating this justify-content value
|
||||
local container = FlexLove.new({
|
||||
x = "18vw",
|
||||
y = yOffset .. "vh",
|
||||
width = "78vw",
|
||||
height = "8vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.HORIZONTAL,
|
||||
justifyContent = option.value,
|
||||
alignItems = enums.AlignItems.CENTER,
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Add child elements
|
||||
local colors = {
|
||||
Color.new(0.8, 0.3, 0.3, 1),
|
||||
Color.new(0.3, 0.8, 0.3, 1),
|
||||
Color.new(0.3, 0.3, 0.8, 1),
|
||||
Color.new(0.8, 0.8, 0.3, 1),
|
||||
}
|
||||
|
||||
for j = 1, 4 do
|
||||
FlexLove.new({
|
||||
parent = container,
|
||||
width = "8vw",
|
||||
height = "5vh",
|
||||
backgroundColor = colors[j],
|
||||
text = tostring(j),
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
yOffset = yOffset + 9
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 2: Vertical Flex with Different AlignItems Values
|
||||
-- ========================================
|
||||
|
||||
yOffset = yOffset + 2
|
||||
|
||||
-- Label for align-items section
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = yOffset .. "vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Vertical Flex - AlignItems Options",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
yOffset = yOffset + 4
|
||||
|
||||
-- Note: Due to space constraints, we'll show a subset in a horizontal layout
|
||||
local alignOptions = {
|
||||
{ name = "stretch", value = enums.AlignItems.STRETCH },
|
||||
{ name = "flex-start", value = enums.AlignItems.FLEX_START },
|
||||
{ name = "center", value = enums.AlignItems.CENTER },
|
||||
{ name = "flex-end", value = enums.AlignItems.FLEX_END },
|
||||
}
|
||||
|
||||
local xOffset = 2
|
||||
local containerWidth = 22
|
||||
|
||||
for _, option in ipairs(alignOptions) do
|
||||
-- Label for this align option
|
||||
FlexLove.new({
|
||||
x = xOffset .. "vw",
|
||||
y = yOffset .. "vh",
|
||||
width = containerWidth .. "vw",
|
||||
height = "2.5vh",
|
||||
text = option.name,
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(0.8, 1, 0.8, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Container demonstrating this align-items value
|
||||
local container = FlexLove.new({
|
||||
x = xOffset .. "vw",
|
||||
y = (yOffset + 3) .. "vh",
|
||||
width = containerWidth .. "vw",
|
||||
height = "20vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
justifyContent = enums.JustifyContent.FLEX_START,
|
||||
alignItems = option.value,
|
||||
gap = 5,
|
||||
backgroundColor = Color.new(0.15, 0.2, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.4, 0.3, 1),
|
||||
})
|
||||
|
||||
-- Add child elements with varying widths
|
||||
local widths = { "8vw", "12vw", "6vw" }
|
||||
local colors = {
|
||||
Color.new(0.9, 0.4, 0.4, 1),
|
||||
Color.new(0.4, 0.9, 0.4, 1),
|
||||
Color.new(0.4, 0.4, 0.9, 1),
|
||||
}
|
||||
|
||||
for j = 1, 3 do
|
||||
FlexLove.new({
|
||||
parent = container,
|
||||
width = option.value == enums.AlignItems.STRETCH and "auto" or widths[j],
|
||||
height = "4vh",
|
||||
backgroundColor = colors[j],
|
||||
text = tostring(j),
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
xOffset = xOffset + containerWidth + 2
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,228 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 02: Grid Layout
|
||||
|
||||
This example demonstrates grid layouts in FlexLove:
|
||||
- Different grid configurations (2x2, 3x3, 4x2)
|
||||
- Row and column gaps
|
||||
- AlignItems behavior in grid cells
|
||||
- Automatic grid cell positioning
|
||||
|
||||
Run with: love /path/to/libs/examples/02_grid_layout.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 02: Grid Layout",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 1: 2x2 Grid with Gaps
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "10vh",
|
||||
width = "30vw",
|
||||
height = "3vh",
|
||||
text = "2x2 Grid (rowGap: 10px, columnGap: 10px)",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local grid2x2 = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "14vh",
|
||||
width = "30vw",
|
||||
height = "30vh",
|
||||
positioning = enums.Positioning.GRID,
|
||||
gridRows = 2,
|
||||
gridColumns = 2,
|
||||
rowGap = 10,
|
||||
columnGap = 10,
|
||||
backgroundColor = Color.new(0.1, 0.1, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Add 4 cells to 2x2 grid
|
||||
local colors2x2 = {
|
||||
Color.new(0.8, 0.3, 0.3, 1),
|
||||
Color.new(0.3, 0.8, 0.3, 1),
|
||||
Color.new(0.3, 0.3, 0.8, 1),
|
||||
Color.new(0.8, 0.8, 0.3, 1),
|
||||
}
|
||||
|
||||
for j = 1, 4 do
|
||||
FlexLove.new({
|
||||
parent = grid2x2,
|
||||
backgroundColor = colors2x2[j],
|
||||
text = "Cell " .. j,
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 2: 3x3 Grid with Different Gap Sizes
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "34vw",
|
||||
y = "10vh",
|
||||
width = "30vw",
|
||||
height = "3vh",
|
||||
text = "3x3 Grid (rowGap: 5px, columnGap: 15px)",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local grid3x3 = FlexLove.new({
|
||||
x = "34vw",
|
||||
y = "14vh",
|
||||
width = "30vw",
|
||||
height = "30vh",
|
||||
positioning = enums.Positioning.GRID,
|
||||
gridRows = 3,
|
||||
gridColumns = 3,
|
||||
rowGap = 5,
|
||||
columnGap = 15,
|
||||
backgroundColor = Color.new(0.1, 0.15, 0.1, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.4, 0.3, 1),
|
||||
})
|
||||
|
||||
-- Add 9 cells to 3x3 grid
|
||||
for j = 1, 9 do
|
||||
local hue = (j - 1) / 9
|
||||
FlexLove.new({
|
||||
parent = grid3x3,
|
||||
backgroundColor = Color.new(0.3 + hue * 0.5, 0.5, 0.7 - hue * 0.4, 1),
|
||||
text = tostring(j),
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 3: 4x2 Grid with AlignItems
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "66vw",
|
||||
y = "10vh",
|
||||
width = "32vw",
|
||||
height = "3vh",
|
||||
text = "4x2 Grid (alignItems: center)",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local grid4x2 = FlexLove.new({
|
||||
x = "66vw",
|
||||
y = "14vh",
|
||||
width = "32vw",
|
||||
height = "30vh",
|
||||
positioning = enums.Positioning.GRID,
|
||||
gridRows = 4,
|
||||
gridColumns = 2,
|
||||
rowGap = 8,
|
||||
columnGap = 8,
|
||||
alignItems = enums.AlignItems.CENTER,
|
||||
backgroundColor = Color.new(0.15, 0.1, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.4, 0.3, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Add 8 cells with varying content
|
||||
for j = 1, 8 do
|
||||
FlexLove.new({
|
||||
parent = grid4x2,
|
||||
backgroundColor = Color.new(0.6, 0.4 + j * 0.05, 0.7 - j * 0.05, 1),
|
||||
text = "Item " .. j,
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 4: Grid with Responsive Units (vw/vh gaps)
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "46vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Grid with Responsive Gaps (rowGap: 2vh, columnGap: 2vw)",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local gridResponsive = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "50vh",
|
||||
width = "96vw",
|
||||
height = "45vh",
|
||||
positioning = enums.Positioning.GRID,
|
||||
gridRows = 2,
|
||||
gridColumns = 5,
|
||||
rowGap = "2vh",
|
||||
columnGap = "2vw",
|
||||
backgroundColor = Color.new(0.08, 0.08, 0.12, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.25, 0.25, 0.35, 1),
|
||||
})
|
||||
|
||||
-- Add 10 cells with gradient colors
|
||||
for j = 1, 10 do
|
||||
local progress = (j - 1) / 9
|
||||
FlexLove.new({
|
||||
parent = gridResponsive,
|
||||
backgroundColor = Color.new(
|
||||
0.2 + progress * 0.6,
|
||||
0.4 + math.sin(progress * 3.14) * 0.4,
|
||||
0.8 - progress * 0.4,
|
||||
1
|
||||
),
|
||||
text = "Cell " .. j,
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,300 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 03: Theming System
|
||||
|
||||
This example demonstrates the theming system in FlexLove:
|
||||
- Loading and applying themes
|
||||
- Theme components (button, panel, card)
|
||||
- Theme states (normal, hover, pressed, disabled, active)
|
||||
- Theme colors and fonts
|
||||
|
||||
Run with: love /path/to/libs/examples/03_theming_system.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Load the space theme
|
||||
FlexLove.loadTheme("space", "../themes/space")
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 03: Theming System",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 1: Theme Components
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "10vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Theme Components - Space Theme",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Card component
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "14vh",
|
||||
width = "30vw",
|
||||
height = "20vh",
|
||||
theme = "space",
|
||||
themeComponent = "card",
|
||||
text = "Card Component",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.8, 0.9, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Panel component
|
||||
FlexLove.new({
|
||||
x = "34vw",
|
||||
y = "14vh",
|
||||
width = "30vw",
|
||||
height = "20vh",
|
||||
theme = "space",
|
||||
themeComponent = "panel",
|
||||
text = "Panel Component",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.8, 0.9, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Panel red component
|
||||
FlexLove.new({
|
||||
x = "66vw",
|
||||
y = "14vh",
|
||||
width = "32vw",
|
||||
height = "20vh",
|
||||
theme = "space",
|
||||
themeComponent = "panelred",
|
||||
text = "Panel Red Component",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 0.8, 0.8, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 2: Button States
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "36vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Button States - Hover and Click to See State Changes",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Normal button (hover to see hover state, click to see pressed state)
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "40vh",
|
||||
width = "22vw",
|
||||
height = "8vh",
|
||||
theme = "space",
|
||||
themeComponent = "button",
|
||||
text = "Normal Button",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
print("Normal button clicked!")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Active button (simulating active state)
|
||||
local activeButton = FlexLove.new({
|
||||
x = "26vw",
|
||||
y = "40vh",
|
||||
width = "22vw",
|
||||
height = "8vh",
|
||||
theme = "space",
|
||||
themeComponent = "button",
|
||||
text = "Active Button",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.3, 1, 0.3, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
active = true,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
element.active = not element.active
|
||||
print("Active button toggled:", element.active)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Disabled button
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "40vh",
|
||||
width = "22vw",
|
||||
height = "8vh",
|
||||
theme = "space",
|
||||
themeComponent = "button",
|
||||
text = "Disabled Button",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.5, 0.5, 0.5, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
disabled = true,
|
||||
onEvent = function(element, event)
|
||||
-- This won't be called because button is disabled
|
||||
print("This shouldn't print!")
|
||||
end,
|
||||
})
|
||||
|
||||
-- Button with callback feedback
|
||||
local clickCount = 0
|
||||
local counterButton = FlexLove.new({
|
||||
x = "74vw",
|
||||
y = "40vh",
|
||||
width = "24vw",
|
||||
height = "8vh",
|
||||
theme = "space",
|
||||
themeComponent = "button",
|
||||
text = "Click Me! (0)",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
clickCount = clickCount + 1
|
||||
element.text = "Click Me! (" .. clickCount .. ")"
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 3: Theme Colors and Fonts
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "50vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Theme Colors and Fonts",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Container showing theme colors
|
||||
local colorContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "54vh",
|
||||
width = "96vw",
|
||||
height = "20vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.HORIZONTAL,
|
||||
justifyContent = enums.JustifyContent.SPACE_EVENLY,
|
||||
alignItems = enums.AlignItems.CENTER,
|
||||
backgroundColor = Color.new(0.1, 0.1, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Primary color swatch
|
||||
FlexLove.new({
|
||||
parent = colorContainer,
|
||||
width = "20vw",
|
||||
height = "15vh",
|
||||
backgroundColor = Color.new(0.08, 0.75, 0.95, 1), -- Theme primary color
|
||||
text = "Primary Color",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
-- Secondary color swatch
|
||||
FlexLove.new({
|
||||
parent = colorContainer,
|
||||
width = "20vw",
|
||||
height = "15vh",
|
||||
backgroundColor = Color.new(0.15, 0.20, 0.25, 1), -- Theme secondary color
|
||||
text = "Secondary Color",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.8, 0.9, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
-- Text color swatch
|
||||
FlexLove.new({
|
||||
parent = colorContainer,
|
||||
width = "20vw",
|
||||
height = "15vh",
|
||||
backgroundColor = Color.new(0.2, 0.2, 0.25, 1),
|
||||
text = "Text Color",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.80, 0.90, 1.00, 1), -- Theme text color
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
-- Text dark color swatch
|
||||
FlexLove.new({
|
||||
parent = colorContainer,
|
||||
width = "20vw",
|
||||
height = "15vh",
|
||||
backgroundColor = Color.new(0.25, 0.25, 0.3, 1),
|
||||
text = "Text Dark Color",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.35, 0.40, 0.45, 1), -- Theme textDark color
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 4: Font Family from Theme
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "76vh",
|
||||
width = "96vw",
|
||||
height = "18vh",
|
||||
theme = "space",
|
||||
themeComponent = "card",
|
||||
text = "This text uses the theme's default font (VT323)",
|
||||
textSize = "3vh",
|
||||
textColor = Color.new(0.8, 0.9, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
fontFamily = "default", -- References theme font
|
||||
})
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,240 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 04: Responsive Units
|
||||
|
||||
This example demonstrates responsive unit systems in FlexLove:
|
||||
- Viewport units (vw, vh)
|
||||
- Percentage units (%)
|
||||
- Pixel units (px)
|
||||
- How elements resize with the window
|
||||
|
||||
Run with: love /path/to/libs/examples/04_responsive_units.lua
|
||||
Try resizing the window to see responsive behavior!
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 04: Responsive Units - Try Resizing!",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 1: Viewport Width Units (vw)
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "10vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Viewport Width (vw) - Scales with window width",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local vwContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "14vh",
|
||||
width = "96vw",
|
||||
height = "12vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.HORIZONTAL,
|
||||
justifyContent = enums.JustifyContent.SPACE_EVENLY,
|
||||
alignItems = enums.AlignItems.CENTER,
|
||||
backgroundColor = Color.new(0.1, 0.1, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Elements with vw widths
|
||||
local vwWidths = { "10vw", "15vw", "20vw", "25vw" }
|
||||
local colors = {
|
||||
Color.new(0.8, 0.3, 0.3, 1),
|
||||
Color.new(0.3, 0.8, 0.3, 1),
|
||||
Color.new(0.3, 0.3, 0.8, 1),
|
||||
Color.new(0.8, 0.8, 0.3, 1),
|
||||
}
|
||||
|
||||
for i, width in ipairs(vwWidths) do
|
||||
FlexLove.new({
|
||||
parent = vwContainer,
|
||||
width = width,
|
||||
height = "8vh",
|
||||
backgroundColor = colors[i],
|
||||
text = width,
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 2: Viewport Height Units (vh)
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "28vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Viewport Height (vh) - Scales with window height",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local vhContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "32vh",
|
||||
width = "96vw",
|
||||
height = "30vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.HORIZONTAL,
|
||||
justifyContent = enums.JustifyContent.SPACE_EVENLY,
|
||||
alignItems = enums.AlignItems.FLEX_END,
|
||||
backgroundColor = Color.new(0.1, 0.15, 0.1, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.4, 0.3, 1),
|
||||
})
|
||||
|
||||
-- Elements with vh heights
|
||||
local vhHeights = { "8vh", "12vh", "16vh", "20vh", "24vh" }
|
||||
|
||||
for i, height in ipairs(vhHeights) do
|
||||
local hue = (i - 1) / 4
|
||||
FlexLove.new({
|
||||
parent = vhContainer,
|
||||
width = "16vw",
|
||||
height = height,
|
||||
backgroundColor = Color.new(0.3 + hue * 0.5, 0.5, 0.7 - hue * 0.4, 1),
|
||||
text = height,
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 3: Percentage Units (%)
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "64vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Percentage (%) - Relative to parent",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local percentContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "68vh",
|
||||
width = "46vw",
|
||||
height = "28vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
justifyContent = enums.JustifyContent.SPACE_EVENLY,
|
||||
alignItems = enums.AlignItems.STRETCH,
|
||||
backgroundColor = Color.new(0.15, 0.1, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.4, 0.3, 0.4, 1),
|
||||
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
||||
})
|
||||
|
||||
-- Child elements with percentage widths
|
||||
local percentWidths = { "25%", "50%", "75%", "100%" }
|
||||
|
||||
for i, width in ipairs(percentWidths) do
|
||||
local progress = (i - 1) / 3
|
||||
FlexLove.new({
|
||||
parent = percentContainer,
|
||||
width = width,
|
||||
height = "5vh",
|
||||
backgroundColor = Color.new(0.6, 0.4 + progress * 0.4, 0.7 - progress * 0.4, 1),
|
||||
text = width .. " of parent",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 4: Pixel Units (px) - Fixed Size
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "64vh",
|
||||
width = "48vw",
|
||||
height = "3vh",
|
||||
text = "Pixels (px) - Fixed size (doesn't resize)",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local pxContainer = FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "68vh",
|
||||
width = "48vw",
|
||||
height = "28vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.HORIZONTAL,
|
||||
justifyContent = enums.JustifyContent.CENTER,
|
||||
alignItems = enums.AlignItems.CENTER,
|
||||
gap = 10,
|
||||
backgroundColor = Color.new(0.1, 0.12, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.35, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Fixed pixel size elements
|
||||
local pxSizes = {
|
||||
{ w = 80, h = 80 },
|
||||
{ w = 100, h = 100 },
|
||||
{ w = 120, h = 120 },
|
||||
}
|
||||
|
||||
for i, size in ipairs(pxSizes) do
|
||||
FlexLove.new({
|
||||
parent = pxContainer,
|
||||
width = size.w,
|
||||
height = size.h,
|
||||
backgroundColor = Color.new(0.8 - i * 0.2, 0.3 + i * 0.2, 0.5, 1),
|
||||
text = size.w .. "px",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,246 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 05: Animations
|
||||
|
||||
This example demonstrates animation system in FlexLove:
|
||||
- Fade animations
|
||||
- Scale animations
|
||||
- Custom animations with different easing functions
|
||||
- Animation timing and interpolation
|
||||
|
||||
Run with: love /path/to/libs/examples/05_animations.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local Animation = FlexLove.Animation
|
||||
local enums = FlexLove.enums
|
||||
|
||||
-- Animation control variables
|
||||
local fadeBox, scaleBox, easingBoxes
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 05: Animations",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 1: Fade Animation
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "10vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Fade Animation - Click to trigger",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
fadeBox = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "14vh",
|
||||
width = "46vw",
|
||||
height = "20vh",
|
||||
backgroundColor = Color.new(0.3, 0.6, 0.9, 1),
|
||||
text = "Click me to fade out and back in",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
-- Fade out then fade in
|
||||
local fadeOut = Animation.fade(1.0, 1.0, 0.0)
|
||||
fadeOut.easing = function(t) return t * t end -- easeInQuad
|
||||
element.animation = fadeOut
|
||||
|
||||
-- Queue fade in after fade out completes
|
||||
local startTime = Lv.timer.getTime()
|
||||
element._fadeCallback = function(el, dt)
|
||||
if Lv.timer.getTime() - startTime >= 1.0 then
|
||||
local fadeIn = Animation.fade(1.0, 0.0, 1.0)
|
||||
fadeIn.easing = function(t) return t * (2 - t) end -- easeOutQuad
|
||||
el.animation = fadeIn
|
||||
el._fadeCallback = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 2: Scale Animation
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "10vh",
|
||||
width = "48vw",
|
||||
height = "3vh",
|
||||
text = "Scale Animation - Click to trigger",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
scaleBox = FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "14vh",
|
||||
width = 400,
|
||||
height = 200,
|
||||
backgroundColor = Color.new(0.9, 0.4, 0.4, 1),
|
||||
text = "Click me to scale up",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
-- Scale up
|
||||
local scaleUp = Animation.scale(
|
||||
0.5,
|
||||
{ width = element.width, height = element.height },
|
||||
{ width = element.width * 1.5, height = element.height * 1.5 }
|
||||
)
|
||||
scaleUp.easing = function(t) return t < 0.5 and 2 * t * t or -1 + (4 - 2 * t) * t end -- easeInOutQuad
|
||||
element.animation = scaleUp
|
||||
|
||||
-- Queue scale down
|
||||
local startTime = Lv.timer.getTime()
|
||||
element._scaleCallback = function(el, dt)
|
||||
if Lv.timer.getTime() - startTime >= 0.5 then
|
||||
local scaleDown = Animation.scale(
|
||||
0.5,
|
||||
{ width = el.width, height = el.height },
|
||||
{ width = 400, height = 200 }
|
||||
)
|
||||
scaleDown.easing = function(t) return t < 0.5 and 2 * t * t or -1 + (4 - 2 * t) * t end
|
||||
el.animation = scaleDown
|
||||
el._scaleCallback = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 3: Easing Functions Comparison
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "36vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Easing Functions - Click any box to see different easing",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local easingContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "40vh",
|
||||
width = "96vw",
|
||||
height = "56vh",
|
||||
positioning = enums.Positioning.GRID,
|
||||
gridRows = 3,
|
||||
gridColumns = 3,
|
||||
rowGap = "2vh",
|
||||
columnGap = "2vw",
|
||||
backgroundColor = Color.new(0.08, 0.08, 0.12, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.25, 0.25, 0.35, 1),
|
||||
padding = { top = 20, right = 20, bottom = 20, left = 20 },
|
||||
})
|
||||
|
||||
-- Different easing functions
|
||||
local easings = {
|
||||
{ name = "Linear", func = function(t) return t end },
|
||||
{ name = "EaseInQuad", func = function(t) return t * t end },
|
||||
{ name = "EaseOutQuad", func = function(t) return t * (2 - t) end },
|
||||
{ name = "EaseInOutQuad", func = function(t) return t < 0.5 and 2 * t * t or -1 + (4 - 2 * t) * t end },
|
||||
{ name = "EaseInCubic", func = function(t) return t * t * t end },
|
||||
{ name = "EaseOutCubic", func = function(t) local t1 = t - 1; return t1 * t1 * t1 + 1 end },
|
||||
{ name = "EaseInQuart", func = function(t) return t * t * t * t end },
|
||||
{ name = "EaseOutQuart", func = function(t) local t1 = t - 1; return 1 - t1 * t1 * t1 * t1 end },
|
||||
{ name = "EaseInExpo", func = function(t) return t == 0 and 0 or math.pow(2, 10 * (t - 1)) end },
|
||||
}
|
||||
|
||||
easingBoxes = {}
|
||||
|
||||
for i, easing in ipairs(easings) do
|
||||
local hue = (i - 1) / 8
|
||||
local box = FlexLove.new({
|
||||
parent = easingContainer,
|
||||
backgroundColor = Color.new(0.2 + hue * 0.6, 0.4 + math.sin(hue * 3.14) * 0.4, 0.8 - hue * 0.4, 1),
|
||||
text = easing.name,
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 8,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
-- Fade out and in with this easing
|
||||
local fadeOut = Animation.fade(0.8, 1.0, 0.2)
|
||||
fadeOut.easing = easing.func
|
||||
element.animation = fadeOut
|
||||
|
||||
local startTime = Lv.timer.getTime()
|
||||
element._easingCallback = function(el, dt)
|
||||
if Lv.timer.getTime() - startTime >= 0.8 then
|
||||
local fadeIn = Animation.fade(0.8, 0.2, 1.0)
|
||||
fadeIn.easing = easing.func
|
||||
el.animation = fadeIn
|
||||
el._easingCallback = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
table.insert(easingBoxes, box)
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
-- Handle fade callback
|
||||
if fadeBox and fadeBox._fadeCallback then
|
||||
fadeBox._fadeCallback(fadeBox, dt)
|
||||
end
|
||||
|
||||
-- Handle scale callback
|
||||
if scaleBox and scaleBox._scaleCallback then
|
||||
scaleBox._scaleCallback(scaleBox, dt)
|
||||
end
|
||||
|
||||
-- Handle easing callbacks
|
||||
for _, box in ipairs(easingBoxes) do
|
||||
if box._easingCallback then
|
||||
box._easingCallback(box, dt)
|
||||
end
|
||||
end
|
||||
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,318 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 06: Event System
|
||||
|
||||
This example demonstrates the event system in FlexLove:
|
||||
- Click events (left, right, middle mouse buttons)
|
||||
- Press and release events
|
||||
- Event properties (position, modifiers, click count)
|
||||
- Double-click detection
|
||||
- Keyboard modifiers (Shift, Ctrl, Alt)
|
||||
|
||||
Run with: love /path/to/libs/examples/06_event_system.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
-- Event log
|
||||
local eventLog = {}
|
||||
local maxLogEntries = 15
|
||||
|
||||
local function addLogEntry(text)
|
||||
table.insert(eventLog, 1, text)
|
||||
if #eventLog > maxLogEntries then
|
||||
table.remove(eventLog)
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 06: Event System",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 1: Click Events
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "10vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Click Events - Try left, right, middle mouse buttons",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local clickBox = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "14vh",
|
||||
width = "46vw",
|
||||
height = "20vh",
|
||||
backgroundColor = Color.new(0.3, 0.5, 0.7, 1),
|
||||
text = "Click me with different mouse buttons!",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
onEvent = function(element, event)
|
||||
local buttonName = event.button == 1 and "Left" or (event.button == 2 and "Right" or "Middle")
|
||||
local eventTypeName = event.type:sub(1,1):upper() .. event.type:sub(2)
|
||||
|
||||
if event.type == "click" or event.type == "rightclick" or event.type == "middleclick" then
|
||||
addLogEntry(string.format("%s Click at (%.0f, %.0f) - Count: %d",
|
||||
buttonName, event.x, event.y, event.clickCount))
|
||||
elseif event.type == "press" then
|
||||
addLogEntry(string.format("%s Button Pressed at (%.0f, %.0f)",
|
||||
buttonName, event.x, event.y))
|
||||
elseif event.type == "release" then
|
||||
addLogEntry(string.format("%s Button Released at (%.0f, %.0f)",
|
||||
buttonName, event.x, event.y))
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 2: Keyboard Modifiers
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "10vh",
|
||||
width = "48vw",
|
||||
height = "3vh",
|
||||
text = "Keyboard Modifiers - Hold Shift/Ctrl/Alt while clicking",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local modifierBox = FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "14vh",
|
||||
width = "48vw",
|
||||
height = "20vh",
|
||||
backgroundColor = Color.new(0.7, 0.4, 0.5, 1),
|
||||
text = "Click with modifiers!",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
local mods = {}
|
||||
if event.modifiers.shift then table.insert(mods, "Shift") end
|
||||
if event.modifiers.ctrl then table.insert(mods, "Ctrl") end
|
||||
if event.modifiers.alt then table.insert(mods, "Alt") end
|
||||
if event.modifiers.super then table.insert(mods, "Super") end
|
||||
|
||||
local modText = #mods > 0 and table.concat(mods, "+") or "None"
|
||||
addLogEntry(string.format("Click with modifiers: %s", modText))
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 3: Double-Click Detection
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "36vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Double-Click Detection",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local doubleClickBox = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "40vh",
|
||||
width = "46vw",
|
||||
height = "15vh",
|
||||
backgroundColor = Color.new(0.5, 0.7, 0.4, 1),
|
||||
text = "Double-click me!",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
if event.clickCount == 1 then
|
||||
addLogEntry("Single click detected")
|
||||
elseif event.clickCount == 2 then
|
||||
addLogEntry("DOUBLE CLICK detected!")
|
||||
-- Visual feedback for double-click
|
||||
element.backgroundColor = Color.new(0.9, 0.9, 0.3, 1)
|
||||
elseif event.clickCount >= 3 then
|
||||
addLogEntry(string.format("TRIPLE+ CLICK detected! (count: %d)", event.clickCount))
|
||||
element.backgroundColor = Color.new(0.9, 0.3, 0.9, 1)
|
||||
end
|
||||
|
||||
-- Reset color after a delay (simulated in update)
|
||||
element._resetTime = Lv.timer.getTime() + 0.3
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 4: Event Log Display
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "36vh",
|
||||
width = "48vw",
|
||||
height = "3vh",
|
||||
text = "Event Log (most recent first)",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Event log container
|
||||
local logContainer = FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "40vh",
|
||||
width = "48vw",
|
||||
height = "56vh",
|
||||
backgroundColor = Color.new(0.08, 0.08, 0.12, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.25, 0.25, 0.35, 1),
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 5: Interactive Buttons
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "57vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Interactive Buttons",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local buttonContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "61vh",
|
||||
width = "46vw",
|
||||
height = "35vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
justifyContent = enums.JustifyContent.SPACE_EVENLY,
|
||||
alignItems = enums.AlignItems.STRETCH,
|
||||
backgroundColor = Color.new(0.1, 0.1, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
||||
gap = 10,
|
||||
})
|
||||
|
||||
-- Button 1: Press/Release events
|
||||
FlexLove.new({
|
||||
parent = buttonContainer,
|
||||
height = "8vh",
|
||||
backgroundColor = Color.new(0.4, 0.5, 0.8, 1),
|
||||
text = "Press and Release Events",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "press" then
|
||||
addLogEntry("Button 1: PRESSED")
|
||||
element.backgroundColor = Color.new(0.2, 0.3, 0.6, 1)
|
||||
elseif event.type == "release" then
|
||||
addLogEntry("Button 1: RELEASED")
|
||||
element.backgroundColor = Color.new(0.4, 0.5, 0.8, 1)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Button 2: Click counter
|
||||
local clickCounter = 0
|
||||
FlexLove.new({
|
||||
parent = buttonContainer,
|
||||
height = "8vh",
|
||||
backgroundColor = Color.new(0.8, 0.5, 0.4, 1),
|
||||
text = "Click Counter: 0",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
clickCounter = clickCounter + 1
|
||||
element.text = "Click Counter: " .. clickCounter
|
||||
addLogEntry("Button 2: Click #" .. clickCounter)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Button 3: Clear log
|
||||
FlexLove.new({
|
||||
parent = buttonContainer,
|
||||
height = "8vh",
|
||||
backgroundColor = Color.new(0.6, 0.4, 0.6, 1),
|
||||
text = "Clear Event Log",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
onEvent = function(element, event)
|
||||
if event.type == "click" then
|
||||
eventLog = {}
|
||||
addLogEntry("Log cleared!")
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
-- Reset double-click box color
|
||||
if doubleClickBox and doubleClickBox._resetTime and Lv.timer.getTime() >= doubleClickBox._resetTime then
|
||||
doubleClickBox.backgroundColor = Color.new(0.5, 0.7, 0.4, 1)
|
||||
doubleClickBox._resetTime = nil
|
||||
end
|
||||
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
|
||||
-- Draw event log
|
||||
Lv.graphics.setColor(0.8, 0.9, 1, 1)
|
||||
local logX = Lv.graphics.getWidth() * 0.50 + 10
|
||||
local logY = Lv.graphics.getHeight() * 0.40 + 10
|
||||
local lineHeight = 20
|
||||
|
||||
for i, entry in ipairs(eventLog) do
|
||||
local alpha = 1.0 - (i - 1) / maxLogEntries * 0.5
|
||||
Lv.graphics.setColor(0.8, 0.9, 1, alpha)
|
||||
Lv.graphics.print(entry, logX, logY + (i - 1) * lineHeight)
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,188 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 07: Text Rendering
|
||||
|
||||
This example demonstrates text rendering features in FlexLove:
|
||||
- Text alignment (start, center, end, justify)
|
||||
- Text size presets (xxs, xs, sm, md, lg, xl, xxl, 3xl, 4xl)
|
||||
- Font rendering with custom fonts
|
||||
- Text wrapping and positioning
|
||||
|
||||
Run with: love /path/to/libs/examples/07_text_rendering.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 07: Text Rendering",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 1: Text Alignment
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "10vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Text Alignment Options",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local alignments = {
|
||||
{ name = "START", value = enums.TextAlign.START },
|
||||
{ name = "CENTER", value = enums.TextAlign.CENTER },
|
||||
{ name = "END", value = enums.TextAlign.END },
|
||||
}
|
||||
|
||||
local yOffset = 14
|
||||
|
||||
for _, align in ipairs(alignments) do
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = yOffset .. "vh",
|
||||
width = "30vw",
|
||||
height = "8vh",
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
text = "Align: " .. align.name,
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.8, 0.9, 1, 1),
|
||||
textAlign = align.value,
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
cornerRadius = 5,
|
||||
})
|
||||
yOffset = yOffset + 9
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 2: Text Size Presets
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "34vw",
|
||||
y = "10vh",
|
||||
width = "64vw",
|
||||
height = "3vh",
|
||||
text = "Text Size Presets",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local textSizes = {
|
||||
{ name = "XXS", value = "xxs" },
|
||||
{ name = "XS", value = "xs" },
|
||||
{ name = "SM", value = "sm" },
|
||||
{ name = "MD", value = "md" },
|
||||
{ name = "LG", value = "lg" },
|
||||
{ name = "XL", value = "xl" },
|
||||
{ name = "XXL", value = "xxl" },
|
||||
{ name = "3XL", value = "3xl" },
|
||||
{ name = "4XL", value = "4xl" },
|
||||
}
|
||||
|
||||
local sizeContainer = FlexLove.new({
|
||||
x = "34vw",
|
||||
y = "14vh",
|
||||
width = "64vw",
|
||||
height = "76vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
justifyContent = enums.JustifyContent.FLEX_START,
|
||||
alignItems = enums.AlignItems.STRETCH,
|
||||
gap = 5,
|
||||
backgroundColor = Color.new(0.08, 0.08, 0.12, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.25, 0.25, 0.35, 1),
|
||||
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
||||
})
|
||||
|
||||
for i, size in ipairs(textSizes) do
|
||||
local hue = (i - 1) / 8
|
||||
FlexLove.new({
|
||||
parent = sizeContainer,
|
||||
height = "7vh",
|
||||
backgroundColor = Color.new(0.2 + hue * 0.3, 0.3 + hue * 0.2, 0.5 - hue * 0.2, 1),
|
||||
text = size.name .. " - The quick brown fox jumps over the lazy dog",
|
||||
textSize = size.value,
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.START,
|
||||
cornerRadius = 3,
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 3: Custom Font Sizes (vh units)
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "41vh",
|
||||
width = "30vw",
|
||||
height = "3vh",
|
||||
text = "Custom Text Sizes (vh units)",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local customSizes = { "1vh", "2vh", "3vh", "4vh", "5vh" }
|
||||
|
||||
local customContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "45vh",
|
||||
width = "30vw",
|
||||
height = "45vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
justifyContent = enums.JustifyContent.SPACE_EVENLY,
|
||||
alignItems = enums.AlignItems.STRETCH,
|
||||
backgroundColor = Color.new(0.1, 0.12, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.35, 0.4, 1),
|
||||
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
||||
})
|
||||
|
||||
for i, size in ipairs(customSizes) do
|
||||
FlexLove.new({
|
||||
parent = customContainer,
|
||||
backgroundColor = Color.new(0.3, 0.4 + i * 0.08, 0.6 - i * 0.08, 1),
|
||||
text = size .. " text",
|
||||
textSize = size,
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 3,
|
||||
padding = { top = 5, right = 10, bottom = 5, left = 10 },
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,235 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 08: Absolute vs Relative Positioning
|
||||
|
||||
This example demonstrates positioning modes in FlexLove:
|
||||
- Absolute positioning (fixed coordinates)
|
||||
- Relative positioning (relative to siblings)
|
||||
- Comparison between the two modes
|
||||
- Practical use cases
|
||||
|
||||
Run with: love /path/to/libs/examples/08_absolute_relative_positioning.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 08: Absolute vs Relative Positioning",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 1: Absolute Positioning
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "10vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Absolute Positioning - Fixed coordinates",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local absoluteContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "14vh",
|
||||
width = "46vw",
|
||||
height = "40vh",
|
||||
positioning = enums.Positioning.ABSOLUTE,
|
||||
backgroundColor = Color.new(0.1, 0.1, 0.15, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Absolute positioned children
|
||||
FlexLove.new({
|
||||
parent = absoluteContainer,
|
||||
x = 20,
|
||||
y = 20,
|
||||
width = 150,
|
||||
height = 80,
|
||||
positioning = enums.Positioning.ABSOLUTE,
|
||||
backgroundColor = Color.new(0.8, 0.3, 0.3, 1),
|
||||
text = "x:20, y:20",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = absoluteContainer,
|
||||
x = 200,
|
||||
y = 50,
|
||||
width = 150,
|
||||
height = 80,
|
||||
positioning = enums.Positioning.ABSOLUTE,
|
||||
backgroundColor = Color.new(0.3, 0.8, 0.3, 1),
|
||||
text = "x:200, y:50",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = absoluteContainer,
|
||||
x = 100,
|
||||
y = 150,
|
||||
width = 150,
|
||||
height = 80,
|
||||
positioning = enums.Positioning.ABSOLUTE,
|
||||
backgroundColor = Color.new(0.3, 0.3, 0.8, 1),
|
||||
text = "x:100, y:150",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = absoluteContainer,
|
||||
x = 280,
|
||||
y = 180,
|
||||
width = 150,
|
||||
height = 80,
|
||||
positioning = enums.Positioning.ABSOLUTE,
|
||||
backgroundColor = Color.new(0.8, 0.8, 0.3, 1),
|
||||
text = "x:280, y:180",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 2: Relative Positioning
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "10vh",
|
||||
width = "48vw",
|
||||
height = "3vh",
|
||||
text = "Relative Positioning - Flows with siblings",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local relativeContainer = FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "14vh",
|
||||
width = "48vw",
|
||||
height = "40vh",
|
||||
positioning = enums.Positioning.RELATIVE,
|
||||
backgroundColor = Color.new(0.1, 0.15, 0.1, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.4, 0.3, 1),
|
||||
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
||||
})
|
||||
|
||||
-- Relative positioned children (flow naturally)
|
||||
local relativeColors = {
|
||||
Color.new(0.8, 0.3, 0.3, 1),
|
||||
Color.new(0.3, 0.8, 0.3, 1),
|
||||
Color.new(0.3, 0.3, 0.8, 1),
|
||||
Color.new(0.8, 0.8, 0.3, 1),
|
||||
}
|
||||
|
||||
for i = 1, 4 do
|
||||
FlexLove.new({
|
||||
parent = relativeContainer,
|
||||
width = "45%",
|
||||
height = "8vh",
|
||||
positioning = enums.Positioning.RELATIVE,
|
||||
backgroundColor = relativeColors[i],
|
||||
text = "Element " .. i .. " (relative)",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
margin = { top = 5, right = 5, bottom = 5, left = 5 },
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 3: Comparison with Overlapping
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "56vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Absolute Positioning Allows Overlapping",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local overlapContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "60vh",
|
||||
width = "96vw",
|
||||
height = "36vh",
|
||||
positioning = enums.Positioning.ABSOLUTE,
|
||||
backgroundColor = Color.new(0.08, 0.08, 0.12, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.25, 0.25, 0.35, 1),
|
||||
})
|
||||
|
||||
-- Create overlapping elements
|
||||
local overlapColors = {
|
||||
Color.new(0.9, 0.3, 0.3, 0.7),
|
||||
Color.new(0.3, 0.9, 0.3, 0.7),
|
||||
Color.new(0.3, 0.3, 0.9, 0.7),
|
||||
Color.new(0.9, 0.9, 0.3, 0.7),
|
||||
}
|
||||
|
||||
for i = 1, 4 do
|
||||
FlexLove.new({
|
||||
parent = overlapContainer,
|
||||
x = 50 + (i - 1) * 60,
|
||||
y = 30 + (i - 1) * 40,
|
||||
width = 300,
|
||||
height = 150,
|
||||
positioning = enums.Positioning.ABSOLUTE,
|
||||
backgroundColor = overlapColors[i],
|
||||
text = "Layer " .. i,
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
z = i, -- Z-index for layering
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,280 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 09: Styling and Visual Effects
|
||||
|
||||
This example demonstrates styling and visual effects:
|
||||
- Corner radius (uniform and individual corners)
|
||||
- Borders (different sides)
|
||||
- Opacity levels
|
||||
- Background colors
|
||||
- Blur effects (contentBlur and backdropBlur)
|
||||
|
||||
Run with: love /path/to/libs/examples/09_styling_visual_effects.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "5vh",
|
||||
text = "FlexLove Example 09: Styling and Visual Effects",
|
||||
textSize = "3.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 1: Corner Radius
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "9vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Corner Radius",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Uniform corner radius
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "13vh",
|
||||
width = "14vw",
|
||||
height = "12vh",
|
||||
backgroundColor = Color.new(0.6, 0.3, 0.7, 1),
|
||||
cornerRadius = 5,
|
||||
text = "radius: 5",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
x = "17vw",
|
||||
y = "13vh",
|
||||
width = "14vw",
|
||||
height = "12vh",
|
||||
backgroundColor = Color.new(0.3, 0.6, 0.7, 1),
|
||||
cornerRadius = 15,
|
||||
text = "radius: 15",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Individual corner radius
|
||||
FlexLove.new({
|
||||
x = "32vw",
|
||||
y = "13vh",
|
||||
width = "16vw",
|
||||
height = "12vh",
|
||||
backgroundColor = Color.new(0.7, 0.6, 0.3, 1),
|
||||
cornerRadius = {
|
||||
topLeft = 0,
|
||||
topRight = 20,
|
||||
bottomLeft = 20,
|
||||
bottomRight = 0,
|
||||
},
|
||||
text = "Individual\ncorners",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 2: Borders
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "9vh",
|
||||
width = "48vw",
|
||||
height = "3vh",
|
||||
text = "Borders",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- All borders
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "13vh",
|
||||
width = "14vw",
|
||||
height = "12vh",
|
||||
backgroundColor = Color.new(0.2, 0.2, 0.3, 1),
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.8, 0.4, 0.4, 1),
|
||||
text = "All sides",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Top and bottom borders
|
||||
FlexLove.new({
|
||||
x = "65vw",
|
||||
y = "13vh",
|
||||
width = "14vw",
|
||||
height = "12vh",
|
||||
backgroundColor = Color.new(0.2, 0.3, 0.2, 1),
|
||||
border = { top = true, bottom = true },
|
||||
borderColor = Color.new(0.4, 0.8, 0.4, 1),
|
||||
text = "Top & Bottom",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Left border only
|
||||
FlexLove.new({
|
||||
x = "80vw",
|
||||
y = "13vh",
|
||||
width = "16vw",
|
||||
height = "12vh",
|
||||
backgroundColor = Color.new(0.2, 0.2, 0.3, 1),
|
||||
border = { left = true },
|
||||
borderColor = Color.new(0.4, 0.4, 0.8, 1),
|
||||
text = "Left only",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- ========================================
|
||||
-- Section 3: Opacity
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "27vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Opacity Levels",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local opacityLevels = { 1.0, 0.75, 0.5, 0.25 }
|
||||
|
||||
for i, opacity in ipairs(opacityLevels) do
|
||||
FlexLove.new({
|
||||
x = (2 + (i - 1) * 24) .. "vw",
|
||||
y = "31vh",
|
||||
width = "22vw",
|
||||
height = "12vh",
|
||||
backgroundColor = Color.new(0.8, 0.3, 0.5, 1),
|
||||
opacity = opacity,
|
||||
text = "Opacity: " .. opacity,
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 8,
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 4: Background Colors
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "45vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Background Colors",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Gradient-like colors
|
||||
for i = 1, 8 do
|
||||
local hue = (i - 1) / 7
|
||||
FlexLove.new({
|
||||
x = (2 + (i - 1) * 12) .. "vw",
|
||||
y = "49vh",
|
||||
width = "11vw",
|
||||
height = "18vh",
|
||||
backgroundColor = Color.new(
|
||||
0.3 + hue * 0.5,
|
||||
0.5 + math.sin(hue * 3.14) * 0.3,
|
||||
0.8 - hue * 0.5,
|
||||
1
|
||||
),
|
||||
text = tostring(i),
|
||||
textSize = "3vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
})
|
||||
end
|
||||
|
||||
-- ========================================
|
||||
-- Section 5: Blur Effects (if supported)
|
||||
-- ========================================
|
||||
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "69vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Blur Effects (contentBlur & backdropBlur)",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Content blur example
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "73vh",
|
||||
width = "46vw",
|
||||
height = "22vh",
|
||||
backgroundColor = Color.new(0.3, 0.4, 0.6, 0.8),
|
||||
contentBlur = { intensity = 5, quality = 3 },
|
||||
text = "Content Blur\n(blurs this element)",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
})
|
||||
|
||||
-- Backdrop blur example
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "73vh",
|
||||
width = "46vw",
|
||||
height = "22vh",
|
||||
backgroundColor = Color.new(0.6, 0.4, 0.3, 0.6),
|
||||
backdropBlur = { intensity = 10, quality = 5 },
|
||||
text = "Backdrop Blur\n(blurs background)",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
})
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,205 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 10: Padding and Margins
|
||||
|
||||
This example demonstrates padding and margin spacing:
|
||||
- Uniform padding
|
||||
- Individual padding sides
|
||||
- Uniform margins
|
||||
- Individual margin sides
|
||||
- Visual indicators for spacing
|
||||
|
||||
Run with: love /path/to/libs/examples/10_padding_margins.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "5vh",
|
||||
text = "FlexLove Example 10: Padding and Margins",
|
||||
textSize = "3.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Section 1: Padding Examples
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "9vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Padding (internal spacing)",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Uniform padding
|
||||
local container1 = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "13vh",
|
||||
width = "22vw",
|
||||
height = "18vh",
|
||||
backgroundColor = Color.new(0.3, 0.4, 0.6, 1),
|
||||
padding = { top = 20, right = 20, bottom = 20, left = 20 },
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = container1,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
backgroundColor = Color.new(0.8, 0.6, 0.3, 1),
|
||||
text = "Uniform\npadding: 20px",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Individual padding sides
|
||||
local container2 = FlexLove.new({
|
||||
x = "26vw",
|
||||
y = "13vh",
|
||||
width = "22vw",
|
||||
height = "18vh",
|
||||
backgroundColor = Color.new(0.4, 0.6, 0.3, 1),
|
||||
padding = { top = 30, right = 10, bottom = 30, left = 10 },
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = container2,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
backgroundColor = Color.new(0.8, 0.3, 0.6, 1),
|
||||
text = "Individual\ntop/bottom: 30px\nleft/right: 10px",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Section 2: Margin Examples
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "9vh",
|
||||
width = "48vw",
|
||||
height = "3vh",
|
||||
text = "Margins (external spacing)",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Container to show margins
|
||||
local marginContainer = FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "13vh",
|
||||
width = "46vw",
|
||||
height = "38vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
})
|
||||
|
||||
-- Elements with different margins
|
||||
FlexLove.new({
|
||||
parent = marginContainer,
|
||||
width = "40vw",
|
||||
height = "6vh",
|
||||
backgroundColor = Color.new(0.7, 0.3, 0.3, 1),
|
||||
margin = { top = 10, right = 10, bottom = 10, left = 10 },
|
||||
text = "Uniform margin: 10px",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = marginContainer,
|
||||
width = "40vw",
|
||||
height = "6vh",
|
||||
backgroundColor = Color.new(0.3, 0.7, 0.3, 1),
|
||||
margin = { top = 5, right = 30, bottom = 5, left = 30 },
|
||||
text = "Horizontal margin: 30px",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = marginContainer,
|
||||
width = "40vw",
|
||||
height = "6vh",
|
||||
backgroundColor = Color.new(0.3, 0.3, 0.7, 1),
|
||||
margin = { top = 20, right = 10, bottom = 20, left = 10 },
|
||||
text = "Vertical margin: 20px",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Section 3: Combined Padding and Margins
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "33vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Combined Padding & Margins",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local combinedContainer = FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "37vh",
|
||||
width = "46vw",
|
||||
height = "58vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
backgroundColor = Color.new(0.1, 0.1, 0.15, 1),
|
||||
padding = { top = 15, right = 15, bottom = 15, left = 15 },
|
||||
})
|
||||
|
||||
for i = 1, 3 do
|
||||
local box = FlexLove.new({
|
||||
parent = combinedContainer,
|
||||
width = "auto",
|
||||
height = "14vh",
|
||||
backgroundColor = Color.new(0.5 + i * 0.1, 0.4, 0.6 - i * 0.1, 1),
|
||||
margin = { top = 10, right = 0, bottom = 10, left = 0 },
|
||||
padding = { top = 15, right = 15, bottom = 15, left = 15 },
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = box,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
backgroundColor = Color.new(0.2, 0.2, 0.3, 1),
|
||||
text = "Box " .. i .. "\nPadding: 15px\nMargin: 10px",
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,148 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 11: Input Controls
|
||||
|
||||
This example demonstrates input controls (if available):
|
||||
- Text input fields
|
||||
- Keyboard input handling
|
||||
- Focus management
|
||||
|
||||
Run with: love /path/to/libs/examples/11_input_controls.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 11: Input Controls",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Note: Input controls may require additional setup in FlexLove
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "10vh",
|
||||
width = "96vw",
|
||||
height = "4vh",
|
||||
text = "Note: This example demonstrates basic input handling patterns",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.8, 0.8, 0.8, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Interactive buttons
|
||||
local counter = 0
|
||||
local counterDisplay = FlexLove.new({
|
||||
x = "35vw",
|
||||
y = "20vh",
|
||||
width = "30vw",
|
||||
height = "10vh",
|
||||
backgroundColor = Color.new(0.2, 0.2, 0.3, 1),
|
||||
text = "Counter: 0",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
})
|
||||
|
||||
-- Increment button
|
||||
FlexLove.new({
|
||||
x = "20vw",
|
||||
y = "35vh",
|
||||
width = "20vw",
|
||||
height = "8vh",
|
||||
backgroundColor = Color.new(0.3, 0.6, 0.3, 1),
|
||||
text = "Increment (+)",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 8,
|
||||
onEvent = function()
|
||||
counter = counter + 1
|
||||
counterDisplay.text = "Counter: " .. counter
|
||||
end
|
||||
})
|
||||
|
||||
-- Decrement button
|
||||
FlexLove.new({
|
||||
x = "60vw",
|
||||
y = "35vh",
|
||||
width = "20vw",
|
||||
height = "8vh",
|
||||
backgroundColor = Color.new(0.6, 0.3, 0.3, 1),
|
||||
text = "Decrement (-)",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 8,
|
||||
onEvent = function()
|
||||
counter = counter - 1
|
||||
counterDisplay.text = "Counter: " .. counter
|
||||
end
|
||||
})
|
||||
|
||||
-- Reset button
|
||||
FlexLove.new({
|
||||
x = "40vw",
|
||||
y = "46vh",
|
||||
width = "20vw",
|
||||
height = "8vh",
|
||||
backgroundColor = Color.new(0.4, 0.4, 0.6, 1),
|
||||
text = "Reset",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 8,
|
||||
onEvent = function()
|
||||
counter = 0
|
||||
counterDisplay.text = "Counter: " .. counter
|
||||
end
|
||||
})
|
||||
|
||||
-- Keyboard input info
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "60vh",
|
||||
width = "96vw",
|
||||
height = "30vh",
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
text = "Keyboard Input:\n\nFlexLove supports keyboard input through Element properties:\n\n" ..
|
||||
"- Use 'inputType' property for text input fields\n" ..
|
||||
"- Handle onTextInput, onTextChange, onEnter callbacks\n" ..
|
||||
"- Manage focus with onFocus and onBlur events\n\n" ..
|
||||
"See FlexLove documentation for full input API",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.4, 0.4, 0.5, 1),
|
||||
})
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,203 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 12: Z-Index Layering
|
||||
|
||||
This example demonstrates z-index for element layering:
|
||||
- Different z-index values
|
||||
- Overlapping elements
|
||||
- Layer ordering
|
||||
|
||||
Run with: love /path/to/libs/examples/12_z_index_layering.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 }
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 12: Z-Index Layering",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Description
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "10vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Elements with higher z-index values appear on top",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.8, 0.8, 0.8, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Section 1: Overlapping boxes with different z-index
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "15vh",
|
||||
width = "46vw",
|
||||
height = "3vh",
|
||||
text = "Overlapping Elements",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Box 1 (z-index: 1)
|
||||
FlexLove.new({
|
||||
x = "5vw",
|
||||
y = "20vh",
|
||||
width = "20vw",
|
||||
height = "20vh",
|
||||
z = 1,
|
||||
backgroundColor = Color.new(0.8, 0.3, 0.3, 1),
|
||||
text = "Z-Index: 1",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
})
|
||||
|
||||
-- Box 2 (z-index: 2) - overlaps Box 1
|
||||
FlexLove.new({
|
||||
x = "12vw",
|
||||
y = "25vh",
|
||||
width = "20vw",
|
||||
height = "20vh",
|
||||
z = 2,
|
||||
backgroundColor = Color.new(0.3, 0.8, 0.3, 1),
|
||||
text = "Z-Index: 2",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
})
|
||||
|
||||
-- Box 3 (z-index: 3) - overlaps Box 1 and 2
|
||||
FlexLove.new({
|
||||
x = "19vw",
|
||||
y = "30vh",
|
||||
width = "20vw",
|
||||
height = "20vh",
|
||||
z = 3,
|
||||
backgroundColor = Color.new(0.3, 0.3, 0.8, 1),
|
||||
text = "Z-Index: 3",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
})
|
||||
|
||||
-- Section 2: Cards with different layers
|
||||
FlexLove.new({
|
||||
x = "50vw",
|
||||
y = "15vh",
|
||||
width = "48vw",
|
||||
height = "3vh",
|
||||
text = "Layered Cards",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Create a stack of cards
|
||||
for i = 1, 5 do
|
||||
FlexLove.new({
|
||||
x = (52 + i * 2) .. "vw",
|
||||
y = (18 + i * 3) .. "vh",
|
||||
width = "22vw",
|
||||
height = "15vh",
|
||||
z = i,
|
||||
backgroundColor = Color.new(0.3 + i * 0.1, 0.4, 0.7 - i * 0.1, 1),
|
||||
text = "Card " .. i .. "\nZ-Index: " .. i,
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 8,
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(1, 1, 1, 0.3),
|
||||
})
|
||||
end
|
||||
|
||||
-- Section 3: Interactive z-index demo
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "53vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Click to Bring to Front",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
local maxZ = 10
|
||||
|
||||
-- Create interactive boxes
|
||||
for i = 1, 4 do
|
||||
local box = FlexLove.new({
|
||||
x = (5 + (i - 1) * 22) .. "vw",
|
||||
y = "58vh",
|
||||
width = "20vw",
|
||||
height = "20vh",
|
||||
z = i,
|
||||
backgroundColor = Color.new(
|
||||
0.4 + i * 0.1,
|
||||
0.5 + math.sin(i) * 0.2,
|
||||
0.7 - i * 0.1,
|
||||
1
|
||||
),
|
||||
text = "Box " .. i .. "\nClick me!",
|
||||
textSize = "2.2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 10,
|
||||
})
|
||||
|
||||
-- Add click handler to bring to front
|
||||
box.onEvent = function(element)
|
||||
maxZ = maxZ + 1
|
||||
element.z = maxZ
|
||||
element.text = "Box " .. i .. "\nZ: " .. element.z
|
||||
end
|
||||
end
|
||||
|
||||
-- Info text
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "82vh",
|
||||
width = "96vw",
|
||||
height = "14vh",
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
text = "Z-Index determines the stacking order of elements.\n" ..
|
||||
"Higher values appear on top of lower values.\n" ..
|
||||
"Click the boxes above to bring them to the front!",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 8,
|
||||
})
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,273 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 13: Comprehensive Demo
|
||||
|
||||
This example combines multiple FlexLove features into a polished demo:
|
||||
- Flex and grid layouts
|
||||
- Themed components
|
||||
- Animations
|
||||
- Event handling
|
||||
- Responsive design
|
||||
|
||||
Run with: love /path/to/libs/examples/13_comprehensive_demo.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local Animation = FlexLove.Animation
|
||||
local enums = FlexLove.enums
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 },
|
||||
theme = "space"
|
||||
})
|
||||
|
||||
-- Header
|
||||
local header = FlexLove.new({
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = "100vw",
|
||||
height = "12vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.HORIZONTAL,
|
||||
justifyContent = enums.JustifyContent.SPACE_BETWEEN,
|
||||
alignItems = enums.AlignItems.CENTER,
|
||||
backgroundColor = Color.new(0.1, 0.1, 0.15, 1),
|
||||
padding = { top = 10, right = 20, bottom = 10, left = 20 },
|
||||
border = { bottom = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Logo/Title
|
||||
FlexLove.new({
|
||||
parent = header,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
text = "FlexLove Demo",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(0.8, 0.9, 1, 1),
|
||||
})
|
||||
|
||||
-- Header buttons
|
||||
local headerButtons = FlexLove.new({
|
||||
parent = header,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.HORIZONTAL,
|
||||
gap = 10,
|
||||
})
|
||||
|
||||
local buttonNames = { "Home", "Features", "About" }
|
||||
for _, name in ipairs(buttonNames) do
|
||||
FlexLove.new({
|
||||
parent = headerButtons,
|
||||
width = "8vw",
|
||||
height = "6vh",
|
||||
backgroundColor = Color.new(0.3, 0.4, 0.6, 1),
|
||||
text = name,
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
cornerRadius = 5,
|
||||
themeComponent = "button",
|
||||
})
|
||||
end
|
||||
|
||||
-- Main content area
|
||||
local mainContent = FlexLove.new({
|
||||
x = 0,
|
||||
y = "12vh",
|
||||
width = "100vw",
|
||||
height = "88vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.HORIZONTAL,
|
||||
backgroundColor = Color.new(0.05, 0.05, 0.08, 1),
|
||||
})
|
||||
|
||||
-- Sidebar
|
||||
local sidebar = FlexLove.new({
|
||||
parent = mainContent,
|
||||
width = "20vw",
|
||||
height = "88vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
backgroundColor = Color.new(0.08, 0.08, 0.12, 1),
|
||||
padding = { top = 20, right = 10, bottom = 20, left = 10 },
|
||||
gap = 10,
|
||||
border = { right = true },
|
||||
borderColor = Color.new(0.2, 0.2, 0.3, 1),
|
||||
})
|
||||
|
||||
-- Sidebar menu items
|
||||
local menuItems = {
|
||||
{ icon = "◆", label = "Dashboard" },
|
||||
{ icon = "◇", label = "Analytics" },
|
||||
{ icon = "○", label = "Settings" },
|
||||
{ icon = "□", label = "Profile" },
|
||||
{ icon = "△", label = "Help" },
|
||||
}
|
||||
|
||||
for _, item in ipairs(menuItems) do
|
||||
local menuButton = FlexLove.new({
|
||||
parent = sidebar,
|
||||
width = "auto",
|
||||
height = "7vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.HORIZONTAL,
|
||||
alignItems = enums.AlignItems.CENTER,
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
padding = { top = 10, right = 15, bottom = 10, left = 15 },
|
||||
cornerRadius = 5,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = menuButton,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
text = item.icon .. " " .. item.label,
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
end
|
||||
|
||||
-- Content panel
|
||||
local contentPanel = FlexLove.new({
|
||||
parent = mainContent,
|
||||
width = "80vw",
|
||||
height = "88vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
padding = { top = 20, right = 20, bottom = 20, left = 20 },
|
||||
gap = 15,
|
||||
})
|
||||
|
||||
-- Welcome section
|
||||
FlexLove.new({
|
||||
parent = contentPanel,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
text = "Welcome to FlexLove!",
|
||||
textSize = "3.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
})
|
||||
|
||||
-- Stats grid
|
||||
local statsGrid = FlexLove.new({
|
||||
parent = contentPanel,
|
||||
width = "auto",
|
||||
height = "20vh",
|
||||
positioning = enums.Positioning.GRID,
|
||||
gridRows = 1,
|
||||
gridColumns = 4,
|
||||
columnGap = 15,
|
||||
})
|
||||
|
||||
local stats = {
|
||||
{ label = "Projects", value = "24", color = Color.new(0.3, 0.6, 0.8, 1) },
|
||||
{ label = "Users", value = "1.2K", color = Color.new(0.6, 0.3, 0.8, 1) },
|
||||
{ label = "Revenue", value = "$45K", color = Color.new(0.8, 0.6, 0.3, 1) },
|
||||
{ label = "Growth", value = "+12%", color = Color.new(0.3, 0.8, 0.6, 1) },
|
||||
}
|
||||
|
||||
for _, stat in ipairs(stats) do
|
||||
local statCard = FlexLove.new({
|
||||
parent = statsGrid,
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
justifyContent = enums.JustifyContent.CENTER,
|
||||
alignItems = enums.AlignItems.CENTER,
|
||||
backgroundColor = stat.color,
|
||||
cornerRadius = 8,
|
||||
padding = { top = 15, right = 15, bottom = 15, left = 15 },
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = statCard,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
text = stat.value,
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = statCard,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
text = stat.label,
|
||||
textSize = "1.8vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
-- Feature cards
|
||||
local cardsContainer = FlexLove.new({
|
||||
parent = contentPanel,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
positioning = enums.Positioning.GRID,
|
||||
gridRows = 2,
|
||||
gridColumns = 3,
|
||||
rowGap = 15,
|
||||
columnGap = 15,
|
||||
})
|
||||
|
||||
local features = {
|
||||
"Flexbox Layout",
|
||||
"Grid System",
|
||||
"Theming",
|
||||
"Animations",
|
||||
"Events",
|
||||
"Responsive"
|
||||
}
|
||||
|
||||
for i, feature in ipairs(features) do
|
||||
local card = FlexLove.new({
|
||||
parent = cardsContainer,
|
||||
positioning = enums.Positioning.FLEX,
|
||||
justifyContent = enums.JustifyContent.CENTER,
|
||||
alignItems = enums.AlignItems.CENTER,
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
cornerRadius = 10,
|
||||
padding = { top = 20, right = 20, bottom = 20, left = 20 },
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = card,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
text = feature,
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Add hover animation
|
||||
card.onEvent = function(element)
|
||||
local anim = Animation.new({
|
||||
duration = 0.2,
|
||||
start = { opacity = 1 },
|
||||
final = { opacity = 0.8 },
|
||||
})
|
||||
anim:apply(element)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,305 +0,0 @@
|
||||
--[[
|
||||
FlexLove Example 14: Drag Event - Slider Implementation
|
||||
|
||||
This example demonstrates how to use the new drag event to create
|
||||
interactive sliders without any first-party slider component.
|
||||
|
||||
Features demonstrated:
|
||||
- Using drag events for continuous mouse tracking
|
||||
- Converting mouse coordinates to element-relative positions
|
||||
- Updating UI elements based on drag position
|
||||
- Creating reusable slider components
|
||||
|
||||
Run with: love /path/to/libs/examples/14_drag_slider.lua
|
||||
]]
|
||||
|
||||
local Lv = love
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
|
||||
-- Slider state
|
||||
local volume = 0.5 -- 0.0 to 1.0
|
||||
local brightness = 0.75 -- 0.0 to 1.0
|
||||
local temperature = 20 -- 0 to 40 (degrees)
|
||||
|
||||
-- UI elements
|
||||
local volumeValueText
|
||||
local brightnessValueText
|
||||
local temperatureValueText
|
||||
local volumeHandle
|
||||
local brightnessHandle
|
||||
local temperatureHandle
|
||||
|
||||
--- Helper function to create a slider
|
||||
---@param x string|number
|
||||
---@param y string|number
|
||||
---@param width string|number
|
||||
---@param label string
|
||||
---@param min number
|
||||
---@param max number
|
||||
---@param initialValue number
|
||||
---@param onValueChange function
|
||||
---@return table -- Returns { bg, handle, valueText }
|
||||
local function createSlider(x, y, width, label, min, max, initialValue, onValueChange)
|
||||
-- Container for the slider
|
||||
local container = FlexLove.new({
|
||||
x = x,
|
||||
y = y,
|
||||
width = width,
|
||||
height = "12vh",
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
gap = 5,
|
||||
})
|
||||
|
||||
-- Label
|
||||
FlexLove.new({
|
||||
parent = container,
|
||||
height = "3vh",
|
||||
text = label,
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.9, 0.9, 0.9, 1),
|
||||
})
|
||||
|
||||
-- Slider track background
|
||||
local sliderBg = FlexLove.new({
|
||||
parent = container,
|
||||
height = "4vh",
|
||||
backgroundColor = Color.new(0.2, 0.2, 0.25, 1),
|
||||
cornerRadius = 5,
|
||||
positioning = enums.Positioning.RELATIVE,
|
||||
})
|
||||
|
||||
-- Slider handle
|
||||
local normalized = (initialValue - min) / (max - min)
|
||||
local handle = FlexLove.new({
|
||||
parent = sliderBg,
|
||||
x = (normalized * 95) .. "%",
|
||||
y = "50%",
|
||||
width = "5%",
|
||||
height = "80%",
|
||||
backgroundColor = Color.new(0.4, 0.6, 0.9, 1),
|
||||
cornerRadius = 3,
|
||||
positioning = enums.Positioning.ABSOLUTE,
|
||||
-- Center the handle vertically
|
||||
top = "10%",
|
||||
})
|
||||
|
||||
-- Value display
|
||||
local valueText = FlexLove.new({
|
||||
parent = container,
|
||||
height = "3vh",
|
||||
text = string.format("%.2f", initialValue),
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.7, 0.8, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Make the background track interactive
|
||||
sliderBg.onEvent = function(element, event)
|
||||
if event.type == "press" or event.type == "drag" then
|
||||
-- Get element bounds
|
||||
local bg_x = element.x
|
||||
local bg_width = element.width
|
||||
|
||||
-- Calculate relative position (0 to 1)
|
||||
local mouse_x = event.x
|
||||
local relative_x = mouse_x - bg_x
|
||||
local new_normalized = math.max(0, math.min(1, relative_x / bg_width))
|
||||
|
||||
-- Calculate actual value
|
||||
local new_value = min + (new_normalized * (max - min))
|
||||
|
||||
-- Update handle position (use percentage for responsiveness)
|
||||
handle.x = (new_normalized * 95) .. "%"
|
||||
|
||||
-- Update value text
|
||||
if max - min > 10 then
|
||||
-- For larger ranges (like temperature), show integers
|
||||
valueText.text = string.format("%d", new_value)
|
||||
else
|
||||
-- For smaller ranges (like 0-1), show decimals
|
||||
valueText.text = string.format("%.2f", new_value)
|
||||
end
|
||||
|
||||
-- Call the value change callback
|
||||
if onValueChange then
|
||||
onValueChange(new_value)
|
||||
end
|
||||
|
||||
-- Re-layout to apply position changes
|
||||
element:recalculateUnits(Lv.graphics.getWidth(), Lv.graphics.getHeight())
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
container = container,
|
||||
bg = sliderBg,
|
||||
handle = handle,
|
||||
valueText = valueText,
|
||||
}
|
||||
end
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 },
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 14: Drag Event - Slider Implementation",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Subtitle
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "9vh",
|
||||
width = "96vw",
|
||||
height = "3vh",
|
||||
text = "Drag the sliders to change values - built using only the drag event primitive!",
|
||||
textSize = "2vh",
|
||||
textColor = Color.new(0.7, 0.7, 0.7, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Volume Slider (0.0 - 1.0)
|
||||
local volumeSlider = createSlider("10vw", "18vh", "80vw", "Volume (0.0 - 1.0)", 0.0, 1.0, volume, function(value)
|
||||
volume = value
|
||||
end)
|
||||
volumeValueText = volumeSlider.valueText
|
||||
volumeHandle = volumeSlider.handle
|
||||
|
||||
-- Brightness Slider (0.0 - 1.0)
|
||||
local brightnessSlider = createSlider("10vw", "35vh", "80vw", "Brightness (0.0 - 1.0)", 0.0, 1.0, brightness, function(value)
|
||||
brightness = value
|
||||
end)
|
||||
brightnessValueText = brightnessSlider.valueText
|
||||
brightnessHandle = brightnessSlider.handle
|
||||
|
||||
-- Temperature Slider (0 - 40°C)
|
||||
local temperatureSlider = createSlider("10vw", "52vh", "80vw", "Temperature (0 - 40°C)", 0, 40, temperature, function(value)
|
||||
temperature = value
|
||||
end)
|
||||
temperatureValueText = temperatureSlider.valueText
|
||||
temperatureHandle = temperatureSlider.handle
|
||||
|
||||
-- Visual feedback section
|
||||
FlexLove.new({
|
||||
x = "10vw",
|
||||
y = "70vh",
|
||||
width = "80vw",
|
||||
height = "3vh",
|
||||
text = "Visual Feedback:",
|
||||
textSize = "2.5vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
})
|
||||
|
||||
-- Volume visualization
|
||||
FlexLove.new({
|
||||
x = "10vw",
|
||||
y = "75vh",
|
||||
width = "25vw",
|
||||
height = "20vh",
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
cornerRadius = 10,
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Brightness visualization
|
||||
FlexLove.new({
|
||||
x = "37.5vw",
|
||||
y = "75vh",
|
||||
width = "25vw",
|
||||
height = "20vh",
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
cornerRadius = 10,
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
})
|
||||
|
||||
-- Temperature visualization
|
||||
FlexLove.new({
|
||||
x = "65vw",
|
||||
y = "75vh",
|
||||
width = "25vw",
|
||||
height = "20vh",
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
cornerRadius = 10,
|
||||
border = { top = true, right = true, bottom = true, left = true },
|
||||
borderColor = Color.new(0.3, 0.3, 0.4, 1),
|
||||
})
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
Lv.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
|
||||
-- Draw volume visualization (speaker icon with bars)
|
||||
local volumeX = Lv.graphics.getWidth() * 0.10 + 20
|
||||
local volumeY = Lv.graphics.getHeight() * 0.75 + 30
|
||||
Lv.graphics.setColor(0.4, 0.6, 0.9, 1)
|
||||
Lv.graphics.print("Volume:", volumeX, volumeY, 0, 2, 2)
|
||||
|
||||
-- Volume bars
|
||||
local barCount = 10
|
||||
for i = 1, barCount do
|
||||
if i / barCount <= volume then
|
||||
Lv.graphics.setColor(0.4, 0.8, 0.4, 1)
|
||||
else
|
||||
Lv.graphics.setColor(0.2, 0.2, 0.25, 1)
|
||||
end
|
||||
local barX = volumeX + 20 + (i - 1) * 30
|
||||
local barHeight = 20 + i * 5
|
||||
Lv.graphics.rectangle("fill", barX, volumeY + 60 - barHeight, 20, barHeight, 3)
|
||||
end
|
||||
|
||||
-- Draw brightness visualization (sun icon)
|
||||
local brightnessX = Lv.graphics.getWidth() * 0.375 + 20
|
||||
local brightnessY = Lv.graphics.getHeight() * 0.75 + 30
|
||||
Lv.graphics.setColor(0.4, 0.6, 0.9, 1)
|
||||
Lv.graphics.print("Brightness:", brightnessX, brightnessY, 0, 2, 2)
|
||||
|
||||
-- Sun circle
|
||||
Lv.graphics.setColor(1, 0.9, 0.3, brightness)
|
||||
Lv.graphics.circle("fill", brightnessX + 150, brightnessY + 80, 30 * brightness + 10)
|
||||
|
||||
-- Draw temperature visualization (thermometer)
|
||||
local tempX = Lv.graphics.getWidth() * 0.65 + 20
|
||||
local tempY = Lv.graphics.getHeight() * 0.75 + 30
|
||||
Lv.graphics.setColor(0.4, 0.6, 0.9, 1)
|
||||
Lv.graphics.print("Temperature:", tempX, tempY, 0, 2, 2)
|
||||
|
||||
-- Thermometer
|
||||
local tempNormalized = temperature / 40
|
||||
local tempColor = {
|
||||
1 - tempNormalized * 0.5, -- Red increases with temp
|
||||
0.3,
|
||||
1 - tempNormalized, -- Blue decreases with temp
|
||||
}
|
||||
Lv.graphics.setColor(tempColor[1], tempColor[2], tempColor[3], 1)
|
||||
Lv.graphics.rectangle("fill", tempX + 100, tempY + 50, 40, 100 * tempNormalized, 5)
|
||||
Lv.graphics.setColor(0.3, 0.3, 0.4, 1)
|
||||
Lv.graphics.rectangle("line", tempX + 100, tempY + 50, 40, 100, 5)
|
||||
|
||||
-- Temperature text
|
||||
Lv.graphics.setColor(1, 1, 1, 1)
|
||||
Lv.graphics.print(string.format("%.0f°C", temperature), tempX + 160, tempY + 90, 0, 2, 2)
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
@@ -1,126 +0,0 @@
|
||||
-- Example 15: Scrollable Elements
|
||||
-- Demonstrates scrollable containers with overflow detection and visual scrollbars
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Color = FlexLove.Color
|
||||
local enums = FlexLove.enums
|
||||
local Lv = love
|
||||
|
||||
function Lv.load()
|
||||
FlexLove.init({
|
||||
baseScale = { width = 1920, height = 1080 },
|
||||
})
|
||||
|
||||
-- Title
|
||||
FlexLove.new({
|
||||
x = "2vw",
|
||||
y = "2vh",
|
||||
width = "96vw",
|
||||
height = "6vh",
|
||||
text = "FlexLove Example 15: Scrollable Elements",
|
||||
textSize = "4vh",
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
|
||||
-- Example 1: Vertical scroll with auto scrollbars
|
||||
local verticalScroll = FlexLove.new({
|
||||
x = "5vw",
|
||||
y = "12vh",
|
||||
width = "25vw",
|
||||
height = "35vh",
|
||||
overflow = "auto",
|
||||
backgroundColor = Color.new(0.15, 0.15, 0.2, 1),
|
||||
cornerRadius = 8,
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
gap = 5,
|
||||
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
||||
})
|
||||
|
||||
-- Add many items to create overflow
|
||||
for i = 1, 20 do
|
||||
FlexLove.new({
|
||||
parent = verticalScroll,
|
||||
height = "5vh",
|
||||
backgroundColor = Color.new(0.3 + (i % 3) * 0.1, 0.4, 0.6, 1),
|
||||
cornerRadius = 4,
|
||||
text = "Item " .. i,
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
textAlign = enums.TextAlign.CENTER,
|
||||
})
|
||||
end
|
||||
|
||||
-- Example 2: Custom styled scrollbar
|
||||
local customScroll = FlexLove.new({
|
||||
x = "35vw",
|
||||
y = "12vh",
|
||||
width = "60vw",
|
||||
height = "35vh",
|
||||
overflow = "auto",
|
||||
backgroundColor = Color.new(0.1, 0.1, 0.15, 1),
|
||||
cornerRadius = 8,
|
||||
scrollbarWidth = 16,
|
||||
scrollbarColor = Color.new(0.3, 0.6, 0.9, 1),
|
||||
scrollbarTrackColor = Color.new(0.15, 0.15, 0.2, 0.8),
|
||||
scrollbarRadius = 8,
|
||||
positioning = enums.Positioning.FLEX,
|
||||
flexDirection = enums.FlexDirection.VERTICAL,
|
||||
gap = 10,
|
||||
padding = { top = 15, right = 15, bottom = 15, left = 15 },
|
||||
})
|
||||
|
||||
-- Add content
|
||||
for i = 1, 25 do
|
||||
FlexLove.new({
|
||||
parent = customScroll,
|
||||
height = "6vh",
|
||||
backgroundColor = Color.new(0.2, 0.25, 0.3, 1),
|
||||
cornerRadius = 6,
|
||||
text = "Custom Scrollbar Item " .. i,
|
||||
textColor = Color.new(0.9, 0.9, 1, 1),
|
||||
textSize = "2vh",
|
||||
})
|
||||
end
|
||||
|
||||
-- Instructions
|
||||
FlexLove.new({
|
||||
x = "5vw",
|
||||
y = "52vh",
|
||||
width = "90vw",
|
||||
height = "40vh",
|
||||
backgroundColor = Color.new(0.1, 0.15, 0.2, 0.9),
|
||||
cornerRadius = 8,
|
||||
padding = { top = 15, right = 15, bottom = 15, left = 15 },
|
||||
text = [[Instructions:
|
||||
• Use mouse wheel to scroll elements under cursor
|
||||
• Click and drag scrollbar thumb to scroll
|
||||
• Click on scrollbar track to jump to position
|
||||
• Scrollbars automatically appear when content overflows
|
||||
• overflow="auto" shows scrollbars only when needed
|
||||
• overflow="scroll" always shows scrollbars
|
||||
• overflow="hidden" clips without scrollbars
|
||||
• overflow="visible" shows all content (default)
|
||||
|
||||
Scrollbar colors change on hover and when dragging!]],
|
||||
textColor = Color.new(0.9, 0.9, 1, 1),
|
||||
textSize = "2vh",
|
||||
})
|
||||
end
|
||||
|
||||
function Lv.update(dt)
|
||||
FlexLove.update(dt)
|
||||
end
|
||||
|
||||
function Lv.draw()
|
||||
love.graphics.clear(0.05, 0.05, 0.08, 1)
|
||||
FlexLove.draw()
|
||||
end
|
||||
|
||||
function Lv.resize(w, h)
|
||||
FlexLove.resize(w, h)
|
||||
end
|
||||
|
||||
function Lv.wheelmoved(x, y)
|
||||
FlexLove.wheelmoved(x, y)
|
||||
end
|
||||
@@ -1,123 +0,0 @@
|
||||
--[[
|
||||
InputFieldsDemo.lua
|
||||
Simple input field demo - multiple fields to test all features
|
||||
Uses retained mode - elements are created once and reused
|
||||
--]]
|
||||
|
||||
local FlexLove = require("../FlexLove")
|
||||
local Element = FlexLove.Element
|
||||
local Color = FlexLove.Color
|
||||
|
||||
local InputFieldsDemo = {}
|
||||
|
||||
-- Elements (created once)
|
||||
local elements = {}
|
||||
local initialized = false
|
||||
|
||||
-- Initialize elements once
|
||||
local function initialize()
|
||||
if initialized then
|
||||
return
|
||||
end
|
||||
initialized = true
|
||||
elements.container = Element.new({
|
||||
x = 0,
|
||||
y = 0,
|
||||
padding = { horizontal = "5%", vertical = "5%" },
|
||||
width = love.graphics.getWidth(),
|
||||
height = love.graphics.getHeight(),
|
||||
flexDirection = "vertical",
|
||||
positioning = "flex",
|
||||
gap = 10,
|
||||
})
|
||||
|
||||
-- Title
|
||||
elements.title = Element.new({
|
||||
parent = elements.container,
|
||||
width = 700,
|
||||
height = 40,
|
||||
text = "FlexLove Input Field Demo",
|
||||
textSize = 28,
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
z = 1000,
|
||||
})
|
||||
|
||||
-- Input field 1 - Empty with placeholder
|
||||
elements.inputField1 = Element.new({
|
||||
parent = elements.container,
|
||||
width = 600,
|
||||
height = 50,
|
||||
editable = true,
|
||||
text = "",
|
||||
textSize = 18,
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
backgroundColor = Color.new(0.2, 0.2, 0.3, 0.9),
|
||||
cornerRadius = 8,
|
||||
padding = { horizontal = 15, vertical = 12 },
|
||||
placeholder = "Type here... (empty field with placeholder)",
|
||||
selectOnFocus = false,
|
||||
multiline = true,
|
||||
autoGrow = true,
|
||||
z = 1000,
|
||||
onTextChange = function(element, newText)
|
||||
print("Field 1 changed:", newText)
|
||||
end,
|
||||
})
|
||||
|
||||
-- Input field 2 - Pre-filled with selectOnFocus
|
||||
elements.inputField2 = Element.new({
|
||||
parent = elements.container,
|
||||
width = 600,
|
||||
height = 50,
|
||||
editable = true,
|
||||
text = "Pre-filled text",
|
||||
textSize = 18,
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
backgroundColor = Color.new(0.2, 0.3, 0.2, 0.9),
|
||||
cornerRadius = 8,
|
||||
padding = { horizontal = 15, vertical = 12 },
|
||||
placeholder = "This shouldn't show",
|
||||
selectOnFocus = true,
|
||||
z = 1000,
|
||||
onTextChange = function(_, newText)
|
||||
print("Field 2 changed:", newText)
|
||||
end,
|
||||
})
|
||||
|
||||
elements.inputField3 = Element.new({
|
||||
parent = elements.container,
|
||||
width = 600,
|
||||
height = 50,
|
||||
editable = true,
|
||||
text = "",
|
||||
textSize = 18,
|
||||
textColor = Color.new(1, 1, 1, 1),
|
||||
backgroundColor = Color.new(0.3, 0.2, 0.2, 0.9),
|
||||
cornerRadius = 8,
|
||||
padding = { horizontal = 15, vertical = 12 },
|
||||
placeholder = "Max 20 characters",
|
||||
maxLength = 20,
|
||||
selectOnFocus = false,
|
||||
z = 1000,
|
||||
onTextChange = function(element, newText)
|
||||
print("Field 3 changed:", newText)
|
||||
end,
|
||||
})
|
||||
|
||||
elements.instructions = Element.new({
|
||||
parent = elements.container,
|
||||
width = 700,
|
||||
height = 200,
|
||||
text = "Instructions:\n• Click on a field to focus it\n• Type to enter text\n• Field 1: Empty with placeholder\n• Field 2: Pre-filled, selects all on focus\n• Field 3: Max 20 characters\n• Press ESC to unfocus\n• Use arrow keys to move cursor",
|
||||
textSize = 14,
|
||||
textColor = Color.new(0.8, 0.8, 0.8, 1),
|
||||
z = 1000,
|
||||
})
|
||||
end
|
||||
|
||||
-- Render function (just initializes if needed)
|
||||
function InputFieldsDemo.render()
|
||||
initialize()
|
||||
end
|
||||
|
||||
return InputFieldsDemo
|
||||
@@ -85,7 +85,11 @@ local function isPointInElement(element, x, y)
|
||||
local bw = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right)
|
||||
local bh = element._borderBoxHeight or (element.height + element.padding.top + element.padding.bottom)
|
||||
|
||||
-- Walk up parent chain to check clipping and apply scroll offsets
|
||||
-- Calculate scroll offset from parent chain
|
||||
local scrollOffsetX = 0
|
||||
local scrollOffsetY = 0
|
||||
|
||||
-- Walk up parent chain to check clipping and accumulate scroll offsets
|
||||
local current = element.parent
|
||||
while current do
|
||||
local overflowX = current.overflowX or current.overflow
|
||||
@@ -101,12 +105,20 @@ local function isPointInElement(element, x, y)
|
||||
if x < parentX or x > parentX + parentW or y < parentY or y > parentY + parentH then
|
||||
return false -- Point is clipped by parent
|
||||
end
|
||||
|
||||
-- Accumulate scroll offset
|
||||
scrollOffsetX = scrollOffsetX + (current._scrollX or 0)
|
||||
scrollOffsetY = scrollOffsetY + (current._scrollY or 0)
|
||||
end
|
||||
|
||||
current = current.parent
|
||||
end
|
||||
|
||||
return x >= bx and x <= bx + bw and y >= by and y <= by + bh
|
||||
-- Adjust mouse position by scroll offset for hit testing
|
||||
local adjustedX = x + scrollOffsetX
|
||||
local adjustedY = y + scrollOffsetY
|
||||
|
||||
return adjustedX >= bx and adjustedX <= bx + bw and adjustedY >= by and adjustedY <= by + bh
|
||||
end
|
||||
|
||||
--- Get the topmost element at a screen position
|
||||
|
||||
@@ -540,6 +540,7 @@ function Element.new(props)
|
||||
Grid = Grid,
|
||||
Units = Units,
|
||||
Context = Context,
|
||||
ErrorHandler = ErrorHandler,
|
||||
})
|
||||
self._layoutEngine:initialize(self)
|
||||
|
||||
@@ -633,7 +634,10 @@ function Element.new(props)
|
||||
-- Pixel units
|
||||
self.textSize = value
|
||||
else
|
||||
ErrorHandler.error("Element", "Unknown textSize unit: " .. unit)
|
||||
ErrorHandler.error(
|
||||
"Element",
|
||||
string.format("Unknown textSize unit '%s'. Valid units: px, %%, vw, vh, ew, eh. Or use presets: xs, sm, md, lg, xl, xxl, 2xl, 3xl, 4xl", unit)
|
||||
)
|
||||
end
|
||||
else
|
||||
-- Validate pixel textSize value
|
||||
@@ -835,6 +839,10 @@ function Element.new(props)
|
||||
|
||||
-- Re-resolve ew/eh textSize units now that width/height are set
|
||||
if props.textSize and type(props.textSize) == "string" then
|
||||
-- Check if it's a preset first (presets don't need re-resolution)
|
||||
local presetValue, presetUnit = resolveTextSizePreset(props.textSize)
|
||||
if not presetValue then
|
||||
-- Not a preset, parse and check for ew/eh units
|
||||
local value, unit = Units.parse(props.textSize)
|
||||
if unit == "ew" then
|
||||
-- Element width relative (now that width is set)
|
||||
@@ -844,6 +852,7 @@ function Element.new(props)
|
||||
self.textSize = (value / 100) * self.height
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Apply min/max constraints (also scaled)
|
||||
local minSize = self.minTextSize and (Context.baseScale and (self.minTextSize * scaleY) or self.minTextSize)
|
||||
@@ -1253,16 +1262,36 @@ function Element.new(props)
|
||||
-- Update the LayoutEngine with actual layout properties
|
||||
-- (it was initialized early with defaults for auto-sizing calculations)
|
||||
self._layoutEngine.positioning = self.positioning
|
||||
if self.flexDirection then self._layoutEngine.flexDirection = self.flexDirection end
|
||||
if self.flexWrap then self._layoutEngine.flexWrap = self.flexWrap end
|
||||
if self.justifyContent then self._layoutEngine.justifyContent = self.justifyContent end
|
||||
if self.alignItems then self._layoutEngine.alignItems = self.alignItems end
|
||||
if self.alignContent then self._layoutEngine.alignContent = self.alignContent end
|
||||
if self.gap then self._layoutEngine.gap = self.gap end
|
||||
if self.gridRows then self._layoutEngine.gridRows = self.gridRows end
|
||||
if self.gridColumns then self._layoutEngine.gridColumns = self.gridColumns end
|
||||
if self.columnGap then self._layoutEngine.columnGap = self.columnGap end
|
||||
if self.rowGap then self._layoutEngine.rowGap = self.rowGap end
|
||||
if self.flexDirection then
|
||||
self._layoutEngine.flexDirection = self.flexDirection
|
||||
end
|
||||
if self.flexWrap then
|
||||
self._layoutEngine.flexWrap = self.flexWrap
|
||||
end
|
||||
if self.justifyContent then
|
||||
self._layoutEngine.justifyContent = self.justifyContent
|
||||
end
|
||||
if self.alignItems then
|
||||
self._layoutEngine.alignItems = self.alignItems
|
||||
end
|
||||
if self.alignContent then
|
||||
self._layoutEngine.alignContent = self.alignContent
|
||||
end
|
||||
if self.gap then
|
||||
self._layoutEngine.gap = self.gap
|
||||
end
|
||||
if self.gridRows then
|
||||
self._layoutEngine.gridRows = self.gridRows
|
||||
end
|
||||
if self.gridColumns then
|
||||
self._layoutEngine.gridColumns = self.gridColumns
|
||||
end
|
||||
if self.columnGap then
|
||||
self._layoutEngine.columnGap = self.columnGap
|
||||
end
|
||||
if self.rowGap then
|
||||
self._layoutEngine.rowGap = self.rowGap
|
||||
end
|
||||
|
||||
---animation
|
||||
self.transform = props.transform or {}
|
||||
@@ -1285,6 +1314,7 @@ function Element.new(props)
|
||||
_scrollY = props._scrollY,
|
||||
}, {
|
||||
utils = utils,
|
||||
Color = Color,
|
||||
})
|
||||
self._scrollManager:initialize(self)
|
||||
|
||||
@@ -1464,15 +1494,6 @@ function Element:_handleScrollbarRelease(button)
|
||||
return false
|
||||
end
|
||||
|
||||
--- Scroll to track click position (internal method used by ScrollManager)
|
||||
---@param mouseX number
|
||||
---@param mouseY number
|
||||
---@param component string -- "vertical" or "horizontal"
|
||||
function Element:_scrollToTrackPosition(mouseX, mouseY, component)
|
||||
-- This method is now handled internally by ScrollManager
|
||||
-- Keeping empty stub for backward compatibility
|
||||
end
|
||||
|
||||
--- Handle mouse wheel scrolling (delegates to ScrollManager)
|
||||
---@param x number -- Horizontal scroll amount
|
||||
---@param y number -- Vertical scroll amount
|
||||
@@ -1794,10 +1815,11 @@ function Element:draw(backdropCanvas)
|
||||
self._renderer:drawText(self)
|
||||
|
||||
-- Draw visual feedback when element is pressed (if it has an onEvent handler and highlight is not disabled)
|
||||
if self.onEvent and not self.disableHighlight then
|
||||
if self.onEvent and not self.disableHighlight and self._eventHandler then
|
||||
-- Check if any button is pressed
|
||||
local anyPressed = false
|
||||
for _, pressed in pairs(self._pressed) do
|
||||
local pressedState = self._eventHandler:getState()._pressed or {}
|
||||
for _, pressed in pairs(pressedState) do
|
||||
if pressed then
|
||||
anyPressed = true
|
||||
break
|
||||
|
||||
@@ -57,6 +57,7 @@ function LayoutEngine.new(props, deps)
|
||||
self._Grid = deps.Grid
|
||||
self._Units = deps.Units
|
||||
self._Context = deps.Context
|
||||
self._ErrorHandler = deps.ErrorHandler
|
||||
self._Positioning = Positioning
|
||||
self._FlexDirection = FlexDirection
|
||||
self._JustifyContent = JustifyContent
|
||||
@@ -174,6 +175,22 @@ function LayoutEngine:layoutChildren()
|
||||
local isFlexChild = not (child.positioning == self._Positioning.ABSOLUTE and child._explicitlyAbsolute)
|
||||
if isFlexChild then
|
||||
table.insert(flexChildren, child)
|
||||
|
||||
-- Warn if child uses percentage sizing but parent has autosizing
|
||||
if self._ErrorHandler then
|
||||
if child.units and child.units.width then
|
||||
if child.units.width.unit == "%" and self.element.autosizing and self.element.autosizing.width then
|
||||
self._ErrorHandler.warn("LayoutEngine",
|
||||
string.format("Child '%s' uses percentage width but parent has auto-sizing enabled. This may cause unexpected results", child.id or "unnamed"))
|
||||
end
|
||||
end
|
||||
if child.units and child.units.height then
|
||||
if child.units.height.unit == "%" and self.element.autosizing and self.element.autosizing.height then
|
||||
self._ErrorHandler.warn("LayoutEngine",
|
||||
string.format("Child '%s' uses percentage height but parent has auto-sizing enabled. This may cause unexpected results", child.id or "unnamed"))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local Units = {}
|
||||
|
||||
local Context = nil
|
||||
local ErrorHandler = nil
|
||||
|
||||
--- Initialize Units module with Context dependency
|
||||
---@param context table The Context module
|
||||
@@ -8,6 +9,12 @@ function Units.initialize(context)
|
||||
Context = context
|
||||
end
|
||||
|
||||
--- Initialize ErrorHandler dependency
|
||||
---@param errorHandler table The ErrorHandler module
|
||||
function Units.initializeErrorHandler(errorHandler)
|
||||
ErrorHandler = errorHandler
|
||||
end
|
||||
|
||||
---@param value string|number
|
||||
---@return number, string -- Returns numeric value and unit type ("px", "%", "vw", "vh")
|
||||
function Units.parse(value)
|
||||
@@ -16,20 +23,34 @@ function Units.parse(value)
|
||||
end
|
||||
|
||||
if type(value) ~= "string" then
|
||||
-- Fallback to 0px for invalid types
|
||||
if ErrorHandler then
|
||||
ErrorHandler.error("Units", string.format("Invalid unit value type. Expected string or number, got %s", type(value)))
|
||||
end
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
-- Check for invalid format (space between number and unit)
|
||||
if value:match("%d%s+%a") then
|
||||
if ErrorHandler then
|
||||
ErrorHandler.error("Units", string.format("Invalid unit string '%s' (contains space). Use format like '50px' or '50%%'", value))
|
||||
end
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
-- Match number followed by optional unit
|
||||
local numStr, unit = value:match("^([%-]?[%d%.]+)(.*)$")
|
||||
if not numStr then
|
||||
-- Fallback to 0px for invalid format
|
||||
if ErrorHandler then
|
||||
ErrorHandler.error("Units", string.format("Invalid unit format '%s'. Expected format: number + unit (e.g., '50px', '10%%', '2vw')", value))
|
||||
end
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
local num = tonumber(numStr)
|
||||
if not num then
|
||||
-- Fallback to 0px for invalid numeric value
|
||||
if ErrorHandler then
|
||||
ErrorHandler.error("Units", string.format("Invalid numeric value in '%s'", value))
|
||||
end
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
@@ -40,6 +61,9 @@ function Units.parse(value)
|
||||
|
||||
local validUnits = { px = true, ["%"] = true, vw = true, vh = true, ew = true, eh = true }
|
||||
if not validUnits[unit] then
|
||||
if ErrorHandler then
|
||||
ErrorHandler.error("Units", string.format("Unknown unit '%s' in '%s'. Valid units: px, %%, vw, vh, ew, eh", unit, value))
|
||||
end
|
||||
return num, "px"
|
||||
end
|
||||
|
||||
@@ -59,7 +83,11 @@ function Units.resolve(value, unit, viewportWidth, viewportHeight, parentSize)
|
||||
return value
|
||||
elseif unit == "%" then
|
||||
if not parentSize then
|
||||
error(formatError("Units", "Percentage units require parent dimension"))
|
||||
if ErrorHandler then
|
||||
ErrorHandler.error("Units", "Percentage units require parent dimension. Element has no parent or parent dimension not available")
|
||||
else
|
||||
error("Percentage units require parent dimension")
|
||||
end
|
||||
end
|
||||
return (value / 100) * parentSize
|
||||
elseif unit == "vw" then
|
||||
@@ -67,7 +95,11 @@ function Units.resolve(value, unit, viewportWidth, viewportHeight, parentSize)
|
||||
elseif unit == "vh" then
|
||||
return (value / 100) * viewportHeight
|
||||
else
|
||||
error(formatError("Units", string.format("Unknown unit type: '%s'. Valid units: px, %%, vw, vh, ew, eh", unit)))
|
||||
if ErrorHandler then
|
||||
ErrorHandler.error("Units", string.format("Unknown unit '%s'. Valid units: px, %%, vw, vh, ew, eh", unit))
|
||||
else
|
||||
error(string.format("Unknown unit type: '%s'", unit))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user