sync
This commit is contained in:
165
CHANGELOG.md
Normal file
165
CHANGELOG.md
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to FlexLove will be documented in this file.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Corner Radius Support**: Added `cornerRadius` property for rounded corners
|
||||||
|
- Supports uniform radius (single number) or individual corners (table)
|
||||||
|
- Automatically clips children to parent's rounded corners using stencil buffer
|
||||||
|
- Works with backgroundColor, borders, and themes
|
||||||
|
- Added `CornerRadiusDemo.lua` example
|
||||||
|
|
||||||
|
- **Disable Highlight Property**: Added `disableHighlight` property to control pressed overlay
|
||||||
|
- Automatically defaults to `true` when `themeComponent` is set
|
||||||
|
- Can be explicitly overridden for custom behavior
|
||||||
|
- Added `DisableHighlightDemo.lua` example
|
||||||
|
|
||||||
|
- **Theme Layering System**: Improved rendering order for better visual control
|
||||||
|
- Layer 1: backgroundColor (behind everything)
|
||||||
|
- Layer 2: Theme 9-slice (on top of backgroundColor)
|
||||||
|
- Layer 3: Borders (on top of theme)
|
||||||
|
- Layer 4: Text (on top of everything)
|
||||||
|
- Added `ThemeLayeringDemo.lua` example
|
||||||
|
|
||||||
|
- **Rounded Rectangle Helper**: Added `RoundedRect` module for smooth corner rendering
|
||||||
|
- `RoundedRect.draw()` - Draw filled or outlined rounded rectangles
|
||||||
|
- `RoundedRect.getPoints()` - Generate polygon points for rounded shapes
|
||||||
|
- `RoundedRect.stencilFunction()` - Create stencil functions for clipping
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **Property Rename**: `background` → `backgroundColor` (breaking change)
|
||||||
|
- More explicit and consistent with CSS naming
|
||||||
|
- All examples and tests updated
|
||||||
|
|
||||||
|
- **Theme Rendering**: Themes now render on top of backgroundColor instead of replacing it
|
||||||
|
- Allows tinting themed elements with semi-transparent backgrounds
|
||||||
|
- Borders always render on top of themes when specified
|
||||||
|
|
||||||
|
- **9-Slice Scaling**: Improved scaling algorithm for theme images
|
||||||
|
- Properly handles elements smaller than corner sizes
|
||||||
|
- Proportional corner scaling prevents overlap
|
||||||
|
- Better handling of edge cases
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Theme images now scale correctly to any element size
|
||||||
|
- Corner regions no longer overlap when element is too small
|
||||||
|
- Stencil clipping properly contains children within rounded corners
|
||||||
|
|
||||||
|
## Previous Changes
|
||||||
|
|
||||||
|
### Theme System
|
||||||
|
- 9-slice/9-patch theming with state support
|
||||||
|
- State-based rendering (normal, hover, pressed, disabled, active)
|
||||||
|
- Flexible atlas organization (separate images, single atlas, or hybrid)
|
||||||
|
- Theme loading and activation system
|
||||||
|
|
||||||
|
### Layout System
|
||||||
|
- Flexbox layout with full flex properties
|
||||||
|
- Grid layout system
|
||||||
|
- Absolute and relative positioning
|
||||||
|
- Automatic sizing and responsive design
|
||||||
|
|
||||||
|
### Event System
|
||||||
|
- Enhanced event handling with detailed event information
|
||||||
|
- Support for click, press, release, right-click, middle-click
|
||||||
|
- Modifier key detection (shift, ctrl, alt, gui)
|
||||||
|
- Double-click and multi-click detection
|
||||||
|
|
||||||
|
### Styling
|
||||||
|
- Color utilities with hex support
|
||||||
|
- Text rendering with alignment and auto-scaling
|
||||||
|
- Text size presets (xs, sm, md, lg, xl, etc.)
|
||||||
|
- Viewport-relative units (vw, vh, %)
|
||||||
|
- Border control (individual sides)
|
||||||
|
- Opacity support
|
||||||
|
|
||||||
|
### Animation
|
||||||
|
- Built-in animation system
|
||||||
|
- Fade and scale animations
|
||||||
|
- Custom animation support with easing
|
||||||
|
- Smooth transitions
|
||||||
|
|
||||||
|
## Migration Guide
|
||||||
|
|
||||||
|
### From `background` to `backgroundColor`
|
||||||
|
|
||||||
|
If you're updating existing code, replace all instances of `background` with `backgroundColor`:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- Old
|
||||||
|
Gui.new({
|
||||||
|
background = Color.new(0.2, 0.2, 0.2, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
-- New
|
||||||
|
Gui.new({
|
||||||
|
backgroundColor = Color.new(0.2, 0.2, 0.2, 1)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Corner Radius
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- Uniform radius
|
||||||
|
Gui.new({
|
||||||
|
cornerRadius = 10,
|
||||||
|
-- ...
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Individual corners
|
||||||
|
Gui.new({
|
||||||
|
cornerRadius = {
|
||||||
|
topLeft = 20,
|
||||||
|
topRight = 10,
|
||||||
|
bottomLeft = 10,
|
||||||
|
bottomRight = 20
|
||||||
|
},
|
||||||
|
-- ...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Controlling Highlight Overlay
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- Regular button (highlight enabled by default)
|
||||||
|
Gui.new({
|
||||||
|
callback = function(element, event) end
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Themed button (highlight disabled by default)
|
||||||
|
Gui.new({
|
||||||
|
themeComponent = "button",
|
||||||
|
callback = function(element, event) end
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Override default behavior
|
||||||
|
Gui.new({
|
||||||
|
themeComponent = "button",
|
||||||
|
disableHighlight = false, -- Force enable
|
||||||
|
callback = function(element, event) end
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
- **Lua**: 5.1+
|
||||||
|
- **LÖVE**: 11.x (tested)
|
||||||
|
- **LuaJIT**: Compatible
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
- Some type annotations show warnings in Lua language servers (cosmetic only)
|
||||||
|
- Theme system requires proper atlas setup for visual feedback
|
||||||
|
- Very small elements may have visual artifacts with complex corner radii
|
||||||
|
|
||||||
|
## Future Plans
|
||||||
|
|
||||||
|
- Input field components
|
||||||
|
- Scrollable containers
|
||||||
|
- Dropdown menus
|
||||||
|
- Tooltip system
|
||||||
|
- More built-in themes
|
||||||
|
- Performance optimizations
|
||||||
|
- Additional layout modes
|
||||||
397
README.md
397
README.md
@@ -1,124 +1,381 @@
|
|||||||
# FlexLöve
|
# FlexLöve
|
||||||
|
|
||||||
A Löve Gui based on Flexbox
|
A Löve GUI library based on Flexbox with theming and animation support
|
||||||
|
|
||||||
FlexLöve is a lightweight, flexible GUI library for Löve2D that implements a flexbox-based layout system. It provides a simple way to create and manage UI elements like windows and buttons with automatic layout calculations, animations, and responsive design.
|
FlexLöve is a lightweight, flexible GUI library for Löve2D that implements a flexbox-based layout system. It provides a simple way to create and manage UI elements with automatic layout calculations, animations, theming, and responsive design.
|
||||||
|
|
||||||
# NOTE: This library is no where near ready for sane use, there are many broken, incomplete and missing features.
|
## ⚠️ Development Status
|
||||||
|
|
||||||
|
This library is under active development. While many features are functional, some aspects may change or have incomplete implementations.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Flexbox Layout**: Implement modern flexbox layouts for UI elements
|
- **Flexbox Layout**: Modern flexbox layouts for UI elements with full flex properties
|
||||||
- **Window Management**: Create hierarchical window structures with automatic sizing
|
- **Grid Layout**: CSS-like (but simplified) grid system for structured layouts
|
||||||
- **Button System**: Interactive buttons with click detection and callbacks
|
- **Element Management**: Hierarchical element structures with automatic sizing
|
||||||
|
- **Interactive Elements**: Buttons with click detection, event system, and callbacks
|
||||||
|
- **Theme System**: 9-slice/9-patch theming with state support (normal, hover, pressed, disabled)
|
||||||
- **Animations**: Built-in animation support for transitions and effects
|
- **Animations**: Built-in animation support for transitions and effects
|
||||||
- **Responsive Design**: Automatic resizing based on window dimensions
|
- **Responsive Design**: Automatic resizing with viewport units (vw, vh, %)
|
||||||
- **Color Handling**: Utility classes for managing colors in various formats
|
- **Color Handling**: Utility classes for managing colors in various formats
|
||||||
- **Text Rendering**: Flexible text display with alignment options
|
- **Text Rendering**: Flexible text display with alignment and auto-scaling
|
||||||
|
- **Corner Radius**: Rounded corners with individual corner control
|
||||||
|
- **Advanced Positioning**: Absolute, relative, flex, and grid positioning modes
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To use FlexLove, simply copy the `FlexLove.lua` file into your project's `libs` directory and require it in your main application:
|
Copy the `FlexLove.lua` file into your project and require it:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local FlexLove = require("FlexLove")
|
local FlexLove = require("FlexLove")
|
||||||
|
local Gui = FlexLove.GUI
|
||||||
|
local Color = FlexLove.Color
|
||||||
```
|
```
|
||||||
|
|
||||||
## Basic Usage
|
## Quick Start
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local FlexLove = require("FlexLove")
|
local FlexLove = require("FlexLove")
|
||||||
local Gui, Color = Flexlove.GUI, Flexlove.Color
|
local Gui = FlexLove.GUI
|
||||||
-- Create a main window
|
local Color = FlexLove.Color
|
||||||
local mainWindow = Gui.new({
|
|
||||||
|
function love.load()
|
||||||
|
-- Initialize GUI system
|
||||||
|
Gui.init({
|
||||||
|
baseScale = { width = 1920, height = 1080 }
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Create a container
|
||||||
|
local container = Gui.new({
|
||||||
x = 100,
|
x = 100,
|
||||||
y = 100,
|
y = 100,
|
||||||
w = 400,
|
width = 400,
|
||||||
h = 300,
|
height = 300,
|
||||||
background = Color.new(0.2, 0.2, 0.2, 1),
|
backgroundColor = Color.new(0.2, 0.2, 0.2, 1),
|
||||||
text = "Main Window",
|
cornerRadius = 10,
|
||||||
})
|
border = { top = true, bottom = true, left = true, right = true },
|
||||||
|
borderColor = Color.new(0.8, 0.8, 0.8, 1),
|
||||||
|
positioning = "flex",
|
||||||
|
flexDirection = "vertical",
|
||||||
|
gap = 10,
|
||||||
|
padding = { top = 20, right = 20, bottom = 20, left = 20 }
|
||||||
|
})
|
||||||
|
|
||||||
-- Create a button inside the window
|
-- Create a button
|
||||||
local button = Gui.new({
|
local button = Gui.new({
|
||||||
parent = mainWindow,
|
parent = container,
|
||||||
x = 50,
|
width = 200,
|
||||||
y = 50,
|
height = 50,
|
||||||
w = 100,
|
|
||||||
h = 40,
|
|
||||||
text = "Click Me",
|
text = "Click Me",
|
||||||
callback = function(button)
|
textAlign = "center",
|
||||||
|
textColor = Color.new(1, 1, 1, 1),
|
||||||
|
backgroundColor = Color.new(0.2, 0.6, 0.9, 1),
|
||||||
|
cornerRadius = 8,
|
||||||
|
callback = function(element, event)
|
||||||
|
if event.type == "click" then
|
||||||
print("Button clicked!")
|
print("Button clicked!")
|
||||||
end,
|
end
|
||||||
})
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
-- In your love.update function
|
|
||||||
function love.update(dt)
|
function love.update(dt)
|
||||||
Gui.update(dt)
|
Gui.update(dt)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- In your love.draw function
|
|
||||||
function love.draw()
|
function love.draw()
|
||||||
Gui.draw()
|
Gui.draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function love.resize(w, h)
|
||||||
|
Gui.resize()
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Core Concepts
|
||||||
|
|
||||||
|
### Element Properties
|
||||||
|
|
||||||
|
Common properties for all elements:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
{
|
||||||
|
-- Positioning & Size
|
||||||
|
x = 0, -- X position (number or string with units)
|
||||||
|
y = 0, -- Y position
|
||||||
|
width = 100, -- Width (number, string, or "auto")
|
||||||
|
height = 100, -- Height
|
||||||
|
z = 0, -- Z-index for layering
|
||||||
|
|
||||||
|
-- Visual Styling
|
||||||
|
backgroundColor = Color.new(0, 0, 0, 0), -- Background color
|
||||||
|
cornerRadius = 0, -- Uniform radius or {topLeft, topRight, bottomLeft, bottomRight}
|
||||||
|
border = {}, -- {top, right, bottom, left} boolean flags
|
||||||
|
borderColor = Color.new(0, 0, 0, 1),
|
||||||
|
opacity = 1, -- 0 to 1
|
||||||
|
|
||||||
|
-- Layout
|
||||||
|
positioning = "flex", -- "absolute", "relative", "flex", or "grid"
|
||||||
|
padding = {}, -- {top, right, bottom, left} or shortcuts
|
||||||
|
margin = {}, -- {top, right, bottom, left} or shortcuts
|
||||||
|
gap = 10, -- Space between children
|
||||||
|
|
||||||
|
-- Flexbox Properties
|
||||||
|
flexDirection = "horizontal", -- "horizontal" or "vertical"
|
||||||
|
justifyContent = "flex-start", -- Main axis alignment
|
||||||
|
alignItems = "stretch", -- Cross axis alignment
|
||||||
|
flexWrap = "nowrap", -- "nowrap" or "wrap"
|
||||||
|
|
||||||
|
-- Grid Properties
|
||||||
|
gridRows = 1,
|
||||||
|
gridColumns = 1,
|
||||||
|
rowGap = 10,
|
||||||
|
columnGap = 10,
|
||||||
|
|
||||||
|
-- Text
|
||||||
|
text = "Hello",
|
||||||
|
textColor = Color.new(1, 1, 1, 1),
|
||||||
|
textAlign = "start", -- "start", "center", "end"
|
||||||
|
textSize = "md", -- Number or preset ("xs", "sm", "md", "lg", "xl", etc.)
|
||||||
|
|
||||||
|
-- Theming
|
||||||
|
theme = "space", -- Theme name
|
||||||
|
themeComponent = "button", -- Component type from theme
|
||||||
|
|
||||||
|
-- Interaction
|
||||||
|
callback = function(element, event) end,
|
||||||
|
disabled = false,
|
||||||
|
disableHighlight = false, -- Disable pressed overlay (auto-true for themed elements)
|
||||||
|
|
||||||
|
-- Hierarchy
|
||||||
|
parent = nil, -- Parent element
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Layout Modes
|
||||||
|
|
||||||
|
#### Absolute Positioning
|
||||||
|
```lua
|
||||||
|
local element = Gui.new({
|
||||||
|
positioning = "absolute",
|
||||||
|
x = 100,
|
||||||
|
y = 50,
|
||||||
|
width = 200,
|
||||||
|
height = 100
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Flexbox Layout
|
||||||
|
```lua
|
||||||
|
local container = Gui.new({
|
||||||
|
positioning = "flex",
|
||||||
|
flexDirection = "horizontal",
|
||||||
|
justifyContent = "center",
|
||||||
|
alignItems = "center",
|
||||||
|
gap = 10
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Grid Layout
|
||||||
|
```lua
|
||||||
|
local grid = Gui.new({
|
||||||
|
positioning = "grid",
|
||||||
|
gridRows = 3,
|
||||||
|
gridColumns = 3,
|
||||||
|
rowGap = 10,
|
||||||
|
columnGap = 10
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Corner Radius
|
||||||
|
|
||||||
|
Supports uniform or individual corner radii:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- Uniform radius
|
||||||
|
cornerRadius = 15
|
||||||
|
|
||||||
|
-- Individual corners
|
||||||
|
cornerRadius = {
|
||||||
|
topLeft = 20,
|
||||||
|
topRight = 10,
|
||||||
|
bottomLeft = 10,
|
||||||
|
bottomRight = 20
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Theme System
|
||||||
|
|
||||||
|
Load and apply themes for consistent styling:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local Theme = FlexLove.Theme
|
||||||
|
|
||||||
|
-- Load a theme
|
||||||
|
Theme.load("space")
|
||||||
|
Theme.setActive("space")
|
||||||
|
|
||||||
|
-- Use theme on elements
|
||||||
|
local button = Gui.new({
|
||||||
|
width = 200,
|
||||||
|
height = 60,
|
||||||
|
text = "Themed Button",
|
||||||
|
themeComponent = "button", -- Uses "button" component from active theme
|
||||||
|
backgroundColor = Color.new(0.5, 0.5, 1, 0.3) -- Renders behind theme
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Themes support state-based rendering:
|
||||||
|
- `normal` - Default state
|
||||||
|
- `hover` - Mouse over element
|
||||||
|
- `pressed` - Element being clicked
|
||||||
|
- `disabled` - Element is disabled
|
||||||
|
- `active` - Element is active/focused
|
||||||
|
|
||||||
|
### Event System
|
||||||
|
|
||||||
|
Enhanced event handling with detailed event information:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
callback = function(element, event)
|
||||||
|
-- event.type: "click", "press", "release", "rightclick", "middleclick"
|
||||||
|
-- event.button: 1 (left), 2 (right), 3 (middle)
|
||||||
|
-- event.x, event.y: Mouse position
|
||||||
|
-- event.clickCount: Number of clicks (for double-click detection)
|
||||||
|
-- event.modifiers: { shift, ctrl, alt, gui }
|
||||||
|
|
||||||
|
if event.type == "click" and event.modifiers.shift then
|
||||||
|
print("Shift-clicked!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Responsive Units
|
||||||
|
|
||||||
|
Support for viewport-relative units:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local element = Gui.new({
|
||||||
|
width = "50vw", -- 50% of viewport width
|
||||||
|
height = "30vh", -- 30% of viewport height
|
||||||
|
x = "25%", -- 25% of parent width
|
||||||
|
textSize = "3vh" -- 3% of viewport height
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Animations
|
||||||
|
|
||||||
|
Create smooth transitions:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local Animation = FlexLove.Animation
|
||||||
|
|
||||||
|
-- Fade animation
|
||||||
|
element.animation = Animation.fade(1.0, 0, 1)
|
||||||
|
|
||||||
|
-- Scale animation
|
||||||
|
element.animation = Animation.scale(0.5, 1, 1.2)
|
||||||
|
|
||||||
|
-- Custom animation
|
||||||
|
element.animation = Animation.new({
|
||||||
|
duration = 1.0,
|
||||||
|
from = { width = 100, height = 50 },
|
||||||
|
to = { width = 200, height = 100 },
|
||||||
|
easing = "easeInOut"
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## API Reference
|
## API Reference
|
||||||
|
|
||||||
|
### Gui (Main Module)
|
||||||
|
|
||||||
|
- `Gui.init(props)` - Initialize GUI system with base scale
|
||||||
|
- `Gui.new(props)` - Create a new element
|
||||||
|
- `Gui.update(dt)` - Update all elements
|
||||||
|
- `Gui.draw()` - Draw all elements
|
||||||
|
- `Gui.resize()` - Handle window resize
|
||||||
|
|
||||||
### Color
|
### Color
|
||||||
|
|
||||||
Utility class for color handling with RGB and RGBA components.
|
- `Color.new(r, g, b, a)` - Create color (values 0-1)
|
||||||
|
- `Color.fromHex(hex)` - Create from hex string
|
||||||
- `Color.new(r, g, b, a)` - Create new color instance
|
- `Color:toHex()` - Convert to hex string
|
||||||
- `Color.fromHex(hex)` - Convert hex string to color
|
|
||||||
- `Color:toHex()` - Convert color to hex string
|
|
||||||
- `Color:toRGBA()` - Get RGBA values
|
- `Color:toRGBA()` - Get RGBA values
|
||||||
|
|
||||||
### Window
|
### Theme
|
||||||
|
|
||||||
Main window class for creating UI containers.
|
- `Theme.load(name)` - Load theme by name
|
||||||
|
- `Theme.setActive(name)` - Set active theme
|
||||||
- `Window.new(props)` - Create a new window
|
- `Theme.getActive()` - Get current active theme
|
||||||
- `Window:addChild(child)` - Add child elements to the window
|
|
||||||
- `Window:draw()` - Draw the window and all its children
|
|
||||||
- `Window:update(dt)` - Update window state (propagates to children)
|
|
||||||
- `Window:resize(newWidth, newHeight)` - Resize window based on game size change
|
|
||||||
|
|
||||||
### Button
|
|
||||||
|
|
||||||
Interactive button element.
|
|
||||||
|
|
||||||
- `Button.new(props)` - Create a new button
|
|
||||||
- `Button:draw()` - Draw the button
|
|
||||||
- `Button:update(dt)` - Update button state (handles click detection)
|
|
||||||
- `Button:updateText(newText, autoresize)` - Update button text
|
|
||||||
|
|
||||||
### Animation
|
### Animation
|
||||||
|
|
||||||
Animation system for UI transitions.
|
- `Animation.new(props)` - Create custom animation
|
||||||
|
- `Animation.fade(duration, from, to)` - Fade animation
|
||||||
- `Animation.new(props)` - Create a new animation
|
- `Animation.scale(duration, from, to)` - Scale animation
|
||||||
- `Animation:interpolate()` - Get interpolated values during animation
|
|
||||||
- `Animation:apply(element)` - Apply animation to a GUI element
|
|
||||||
- `Animation.fade(duration, fromOpacity, toOpacity)` - Create a fade animation
|
|
||||||
- `Animation.scale(duration, fromScale, toScale)` - Create a scale animation
|
|
||||||
|
|
||||||
## Enums
|
## Enums
|
||||||
|
|
||||||
Predefined enums for various layout and styling options:
|
### TextAlign
|
||||||
|
- `START` - Align to start
|
||||||
|
- `CENTER` - Center align
|
||||||
|
- `END` - Align to end
|
||||||
|
- `JUSTIFY` - Justify text
|
||||||
|
|
||||||
- TextAlign: START, CENTER, END, JUSTIFY
|
### Positioning
|
||||||
- Positioning: ABSOLUTE, FLEX
|
- `ABSOLUTE` - Absolute positioning
|
||||||
- FlexDirection: HORIZONTAL, VERTICAL
|
- `RELATIVE` - Relative positioning
|
||||||
- JustifyContent: FLEX_START, CENTER, SPACE_AROUND, FLEX_END, SPACE_EVENLY, SPACE_BETWEEN
|
- `FLEX` - Flexbox layout
|
||||||
- AlignItems: STRETCH, FLEX_START, FLEX_END, CENTER, BASELINE
|
- `GRID` - Grid layout
|
||||||
- AlignSelf: AUTO, STRETCH, FLEX_START, FLEX_END, CENTER, BASELINE
|
|
||||||
- AlignContent: STRETCH, FLEX_START, FLEX_END, CENTER, SPACE_BETWEEN, SPACE_AROUND
|
### FlexDirection
|
||||||
|
- `HORIZONTAL` - Horizontal flex
|
||||||
|
- `VERTICAL` - Vertical flex
|
||||||
|
|
||||||
|
### JustifyContent
|
||||||
|
- `FLEX_START` - Align to start
|
||||||
|
- `CENTER` - Center align
|
||||||
|
- `FLEX_END` - Align to end
|
||||||
|
- `SPACE_AROUND` - Space around items
|
||||||
|
- `SPACE_BETWEEN` - Space between items
|
||||||
|
- `SPACE_EVENLY` - Even spacing
|
||||||
|
|
||||||
|
### AlignItems / AlignSelf
|
||||||
|
- `STRETCH` - Stretch to fill
|
||||||
|
- `FLEX_START` - Align to start
|
||||||
|
- `FLEX_END` - Align to end
|
||||||
|
- `CENTER` - Center align
|
||||||
|
- `BASELINE` - Baseline align
|
||||||
|
|
||||||
|
### FlexWrap
|
||||||
|
- `NOWRAP` - No wrapping
|
||||||
|
- `WRAP` - Wrap items
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
See the `examples/` directory for complete usage examples.
|
The `examples/` directory contains comprehensive demos:
|
||||||
|
|
||||||
|
- `EventSystemDemo.lua` - Event handling and callbacks
|
||||||
|
- `CornerRadiusDemo.lua` - Rounded corners showcase
|
||||||
|
- `ThemeLayeringDemo.lua` - Theme system with layering
|
||||||
|
- `DisableHighlightDemo.lua` - Highlight control
|
||||||
|
- `SimpleGrid.lua` - Grid layout examples
|
||||||
|
- `TextSizePresets.lua` - Text sizing options
|
||||||
|
- `OnClickAnimations.lua` - Animation examples
|
||||||
|
- `ZIndexDemo.lua` - Layering demonstration
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Run tests with:
|
||||||
|
```bash
|
||||||
|
cd testing
|
||||||
|
lua runAll.lua
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT License - see LICENSE file for details.
|
MIT License - see LICENSE file for details.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
This library is under active development. Contributions, bug reports, and feature requests are welcome!
|
||||||
|
|||||||
157
themes/README.md
157
themes/README.md
@@ -2,7 +2,15 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
FlexLove supports a flexible 9-slice/9-patch theming system that allows you to create scalable UI components using texture atlases.
|
FlexLove supports a flexible 9-slice/9-patch theming system that allows you to create scalable UI components using texture atlases. Themes provide state-based visual feedback and automatically handle element sizing.
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
- **9-Slice Scaling**: Images scale properly to any size without distortion
|
||||||
|
- **State Management**: Automatic visual feedback for hover, pressed, disabled, and active states
|
||||||
|
- **Layered Rendering**: Themes render on top of backgroundColor, with borders on top
|
||||||
|
- **Flexible Organization**: Use separate images, single atlas, or hybrid approach
|
||||||
|
- **Automatic Highlight Disable**: Elements with themes automatically disable the pressed overlay
|
||||||
|
|
||||||
## Image Organization Options
|
## Image Organization Options
|
||||||
|
|
||||||
@@ -166,6 +174,7 @@ Legend:
|
|||||||
local FlexLove = require("FlexLove")
|
local FlexLove = require("FlexLove")
|
||||||
local Theme = FlexLove.Theme
|
local Theme = FlexLove.Theme
|
||||||
local Gui = FlexLove.GUI
|
local Gui = FlexLove.GUI
|
||||||
|
local Color = FlexLove.Color
|
||||||
|
|
||||||
-- Load theme
|
-- Load theme
|
||||||
Theme.load("my_theme")
|
Theme.load("my_theme")
|
||||||
@@ -176,9 +185,14 @@ local button = Gui.new({
|
|||||||
width = 150,
|
width = 150,
|
||||||
height = 40,
|
height = 40,
|
||||||
text = "Click Me",
|
text = "Click Me",
|
||||||
theme = "button", -- Uses button component from active theme
|
textAlign = "center",
|
||||||
|
textColor = Color.new(1, 1, 1, 1),
|
||||||
|
backgroundColor = Color.new(0.2, 0.4, 0.8, 0.3), -- Shows behind theme
|
||||||
|
themeComponent = "button", -- Uses button component from active theme
|
||||||
callback = function(element, event)
|
callback = function(element, event)
|
||||||
print("Clicked!")
|
if event.type == "click" then
|
||||||
|
print("Clicked!")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -186,16 +200,34 @@ local button = Gui.new({
|
|||||||
local panel = Gui.new({
|
local panel = Gui.new({
|
||||||
width = 300,
|
width = 300,
|
||||||
height = 200,
|
height = 200,
|
||||||
theme = "panel"
|
backgroundColor = Color.new(0.1, 0.1, 0.2, 0.5), -- Background tint
|
||||||
|
themeComponent = "panel"
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Rendering Layers
|
||||||
|
|
||||||
|
Elements with themes render in this order:
|
||||||
|
|
||||||
|
1. **backgroundColor** - Rendered first (behind everything)
|
||||||
|
2. **Theme 9-slice** - Rendered on top of backgroundColor
|
||||||
|
3. **Borders** - Rendered on top of theme (if specified)
|
||||||
|
4. **Text** - Rendered last (on top of everything)
|
||||||
|
|
||||||
|
This allows you to:
|
||||||
|
- Tint themed elements with backgroundColor
|
||||||
|
- Add custom borders on top of themes
|
||||||
|
- Layer visual effects
|
||||||
|
|
||||||
## Component States
|
## Component States
|
||||||
|
|
||||||
Buttons automatically handle three states:
|
Themes automatically handle visual states for interactive elements:
|
||||||
|
|
||||||
- **normal**: Default appearance
|
- **normal**: Default appearance
|
||||||
- **hover**: When mouse is over the button
|
- **hover**: When mouse is over the element
|
||||||
- **pressed**: When button is being clicked
|
- **pressed**: When element is being clicked
|
||||||
|
- **disabled**: When element.disabled = true
|
||||||
|
- **active**: When element.active = true (for inputs/focused elements)
|
||||||
|
|
||||||
Define state-specific images in your theme:
|
Define state-specific images in your theme:
|
||||||
|
|
||||||
@@ -211,11 +243,110 @@ button = {
|
|||||||
pressed = {
|
pressed = {
|
||||||
atlas = "themes/button_pressed.png",
|
atlas = "themes/button_pressed.png",
|
||||||
regions = { ... }
|
regions = { ... }
|
||||||
|
},
|
||||||
|
disabled = {
|
||||||
|
atlas = "themes/button_disabled.png",
|
||||||
|
regions = { ... }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Theme Definition Example
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- themes/my_theme.lua
|
||||||
|
return {
|
||||||
|
name = "My Theme",
|
||||||
|
atlas = "themes/my_theme/atlas.png",
|
||||||
|
|
||||||
|
components = {
|
||||||
|
panel = {
|
||||||
|
regions = {
|
||||||
|
topLeft = {x=0, y=0, w=8, h=8},
|
||||||
|
topCenter = {x=8, y=0, w=8, h=8},
|
||||||
|
topRight = {x=16, y=0, w=8, h=8},
|
||||||
|
middleLeft = {x=0, y=8, w=8, h=8},
|
||||||
|
middleCenter = {x=8, y=8, w=8, h=8},
|
||||||
|
middleRight = {x=16, y=8, w=8, h=8},
|
||||||
|
bottomLeft = {x=0, y=16, w=8, h=8},
|
||||||
|
bottomCenter = {x=8, y=16, w=8, h=8},
|
||||||
|
bottomRight = {x=16, y=16, w=8, h=8}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
button = {
|
||||||
|
regions = {
|
||||||
|
topLeft = {x=24, y=0, w=8, h=8},
|
||||||
|
topCenter = {x=32, y=0, w=8, h=8},
|
||||||
|
topRight = {x=40, y=0, w=8, h=8},
|
||||||
|
middleLeft = {x=24, y=8, w=8, h=8},
|
||||||
|
middleCenter = {x=32, y=8, w=8, h=8},
|
||||||
|
middleRight = {x=40, y=8, w=8, h=8},
|
||||||
|
bottomLeft = {x=24, y=16, w=8, h=8},
|
||||||
|
bottomCenter = {x=32, y=16, w=8, h=8},
|
||||||
|
bottomRight = {x=40, y=16, w=8, h=8}
|
||||||
|
},
|
||||||
|
states = {
|
||||||
|
hover = {
|
||||||
|
regions = {
|
||||||
|
-- Different region coordinates for hover state
|
||||||
|
topLeft = {x=48, y=0, w=8, h=8},
|
||||||
|
-- ... etc
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pressed = {
|
||||||
|
regions = {
|
||||||
|
-- Different region coordinates for pressed state
|
||||||
|
topLeft = {x=72, y=0, w=8, h=8},
|
||||||
|
-- ... etc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Features
|
||||||
|
|
||||||
|
### Automatic Highlight Disable
|
||||||
|
|
||||||
|
Elements with `themeComponent` automatically set `disableHighlight = true` to prevent the default gray pressed overlay from interfering with theme visuals. You can override this:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
Gui.new({
|
||||||
|
themeComponent = "button",
|
||||||
|
disableHighlight = false, -- Force enable highlight overlay
|
||||||
|
-- ...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Combining with Corner Radius
|
||||||
|
|
||||||
|
You can use cornerRadius with themed elements:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
Gui.new({
|
||||||
|
themeComponent = "button",
|
||||||
|
cornerRadius = 10, -- Clips theme to rounded corners
|
||||||
|
-- ...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Border Overlay
|
||||||
|
|
||||||
|
Add custom borders on top of themes:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
Gui.new({
|
||||||
|
themeComponent = "panel",
|
||||||
|
border = { top = true, bottom = true, left = true, right = true },
|
||||||
|
borderColor = Color.new(1, 1, 0, 1), -- Yellow border on top of theme
|
||||||
|
-- ...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
## Tips
|
## Tips
|
||||||
|
|
||||||
1. **Start Simple**: Begin with one component (button) before creating a full theme
|
1. **Start Simple**: Begin with one component (button) before creating a full theme
|
||||||
@@ -223,6 +354,7 @@ button = {
|
|||||||
3. **Consistent Style**: Keep corner sizes consistent across components
|
3. **Consistent Style**: Keep corner sizes consistent across components
|
||||||
4. **State Variations**: For button states, change colors/brightness rather than structure
|
4. **State Variations**: For button states, change colors/brightness rather than structure
|
||||||
5. **Atlas Packing**: Use tools like TexturePacker or Aseprite to create efficient atlases
|
5. **Atlas Packing**: Use tools like TexturePacker or Aseprite to create efficient atlases
|
||||||
|
6. **Transparency**: Use semi-transparent backgroundColor to tint themed elements
|
||||||
|
|
||||||
## Tools for Creating Atlases
|
## Tools for Creating Atlases
|
||||||
|
|
||||||
@@ -231,8 +363,15 @@ button = {
|
|||||||
- **Shoebox**: Free sprite sheet packer
|
- **Shoebox**: Free sprite sheet packer
|
||||||
- **GIMP/Photoshop**: Manual layout with guides
|
- **GIMP/Photoshop**: Manual layout with guides
|
||||||
|
|
||||||
|
## Example Themes
|
||||||
|
|
||||||
|
See the `space/` directory for a complete theme example with:
|
||||||
|
- Panel component
|
||||||
|
- Button component with states (normal, hover, pressed, disabled)
|
||||||
|
- Compressed and uncompressed versions
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- `default.lua` - Example theme with single atlas
|
- `space.lua` - Complete theme definition example
|
||||||
- `separate_images_example.lua` - Example with separate images per component
|
|
||||||
- `ThemeSystemDemo.lua` - Interactive demo of theme system
|
- `ThemeSystemDemo.lua` - Interactive demo of theme system
|
||||||
|
- `ThemeLayeringDemo.lua` - Demo of backgroundColor/theme/border layering
|
||||||
|
|||||||
Reference in New Issue
Block a user