starting theme system
This commit is contained in:
238
themes/README.md
Normal file
238
themes/README.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# FlexLove Theme System
|
||||
|
||||
## Overview
|
||||
|
||||
FlexLove supports a flexible 9-slice/9-patch theming system that allows you to create scalable UI components using texture atlases.
|
||||
|
||||
## Image Organization Options
|
||||
|
||||
You have **three ways** to organize your theme images:
|
||||
|
||||
### Option 1: Separate Images Per Component (Recommended for Beginners)
|
||||
|
||||
Each component gets its own image file:
|
||||
|
||||
```
|
||||
themes/
|
||||
panel.png (24x24 pixels - 9-slice for panels)
|
||||
button_normal.png (24x24 pixels - 9-slice for buttons)
|
||||
button_hover.png (24x24 pixels - hover state)
|
||||
button_pressed.png (24x24 pixels - pressed state)
|
||||
input.png (24x24 pixels - 9-slice for inputs)
|
||||
```
|
||||
|
||||
**Theme definition:**
|
||||
```lua
|
||||
return {
|
||||
name = "My Theme",
|
||||
components = {
|
||||
panel = {
|
||||
atlas = "themes/panel.png",
|
||||
regions = { ... }
|
||||
},
|
||||
button = {
|
||||
atlas = "themes/button_normal.png",
|
||||
regions = { ... },
|
||||
states = {
|
||||
hover = {
|
||||
atlas = "themes/button_hover.png",
|
||||
regions = { ... }
|
||||
},
|
||||
pressed = {
|
||||
atlas = "themes/button_pressed.png",
|
||||
regions = { ... }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option 2: Single Atlas (Recommended for Performance)
|
||||
|
||||
All components in one texture atlas:
|
||||
|
||||
```
|
||||
themes/
|
||||
default_atlas.png (96x48 pixels containing all components)
|
||||
```
|
||||
|
||||
**Theme definition:**
|
||||
```lua
|
||||
return {
|
||||
name = "My Theme",
|
||||
atlas = "themes/default_atlas.png", -- Global atlas
|
||||
components = {
|
||||
panel = {
|
||||
regions = {
|
||||
topLeft = {x=0, y=0, w=8, h=8},
|
||||
-- ... regions reference positions in atlas
|
||||
}
|
||||
},
|
||||
button = {
|
||||
regions = {
|
||||
topLeft = {x=24, y=0, w=8, h=8}, -- Different position in same atlas
|
||||
-- ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option 3: Hybrid (Best of Both Worlds)
|
||||
|
||||
Mix global atlas with component-specific images:
|
||||
|
||||
```lua
|
||||
return {
|
||||
name = "My Theme",
|
||||
atlas = "themes/global_atlas.png", -- Fallback atlas
|
||||
components = {
|
||||
panel = {
|
||||
-- Uses global atlas
|
||||
regions = {x=0, y=0, ...}
|
||||
},
|
||||
button = {
|
||||
atlas = "themes/button.png", -- Override with specific image
|
||||
regions = {x=0, y=0, ...}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 9-Slice Structure
|
||||
|
||||
Each component image is divided into 9 regions:
|
||||
|
||||
```
|
||||
┌─────┬──────────┬─────┐
|
||||
│ TL │ TC │ TR │ (Top: fixed height)
|
||||
├─────┼──────────┼─────┤
|
||||
│ ML │ MC │ MR │ (Middle: stretches)
|
||||
├─────┼──────────┼─────┤
|
||||
│ BL │ BC │ BR │ (Bottom: fixed height)
|
||||
└─────┴──────────┴─────┘
|
||||
Fixed Stretch Fixed
|
||||
```
|
||||
|
||||
- **Corners** (TL, TR, BL, BR): Fixed size, never stretched
|
||||
- **Edges** (TC, BC, ML, MR): Stretched in one direction
|
||||
- **Center** (MC): Stretched in both directions
|
||||
|
||||
## Creating Theme Images
|
||||
|
||||
### Minimum Image Size
|
||||
|
||||
For a 9-slice image, you need at least **24x24 pixels**:
|
||||
- 8px for each corner
|
||||
- 8px for stretchable middle section
|
||||
|
||||
### Image Requirements
|
||||
|
||||
1. **Format**: PNG with transparency
|
||||
2. **Color Mode**: RGBA
|
||||
3. **Border Style**: Draw borders in the corner/edge regions
|
||||
4. **Center**: Can be solid color or transparent
|
||||
|
||||
## Example: Creating a Button Image
|
||||
|
||||
For a button with rounded corners and a border:
|
||||
|
||||
```
|
||||
button_normal.png (24x24 pixels)
|
||||
|
||||
Pixel layout:
|
||||
┌────────┬────────────┬────────┐
|
||||
│ ●●●●●● │ ██████████ │ ●●●●●● │ 8px
|
||||
│ ●●●●●● │ ██████████ │ ●●●●●● │
|
||||
├────────┼────────────┼────────┤
|
||||
│ ██████ │ ░░░░░░░░░░ │ ██████ │ 8px (stretch)
|
||||
│ ██████ │ ░░░░░░░░░░ │ ██████ │
|
||||
├────────┼────────────┼────────┤
|
||||
│ ●●●●●● │ ██████████ │ ●●●●●● │ 8px
|
||||
│ ●●●●●● │ ██████████ │ ●●●●●● │
|
||||
└────────┴────────────┴────────┘
|
||||
8px 8px(stretch) 8px
|
||||
|
||||
Legend:
|
||||
● = Corner (fixed)
|
||||
█ = Border edge (stretched)
|
||||
░ = Fill/background (stretched both ways)
|
||||
```
|
||||
|
||||
## Usage in Code
|
||||
|
||||
```lua
|
||||
local FlexLove = require("FlexLove")
|
||||
local Theme = FlexLove.Theme
|
||||
local Gui = FlexLove.GUI
|
||||
|
||||
-- Load theme
|
||||
Theme.load("my_theme")
|
||||
Theme.setActive("my_theme")
|
||||
|
||||
-- Create themed button
|
||||
local button = Gui.new({
|
||||
width = 150,
|
||||
height = 40,
|
||||
text = "Click Me",
|
||||
theme = "button", -- Uses button component from active theme
|
||||
callback = function(element, event)
|
||||
print("Clicked!")
|
||||
end
|
||||
})
|
||||
|
||||
-- Create themed panel
|
||||
local panel = Gui.new({
|
||||
width = 300,
|
||||
height = 200,
|
||||
theme = "panel"
|
||||
})
|
||||
```
|
||||
|
||||
## Component States
|
||||
|
||||
Buttons automatically handle three states:
|
||||
- **normal**: Default appearance
|
||||
- **hover**: When mouse is over the button
|
||||
- **pressed**: When button is being clicked
|
||||
|
||||
Define state-specific images in your theme:
|
||||
|
||||
```lua
|
||||
button = {
|
||||
atlas = "themes/button_normal.png",
|
||||
regions = { ... },
|
||||
states = {
|
||||
hover = {
|
||||
atlas = "themes/button_hover.png",
|
||||
regions = { ... }
|
||||
},
|
||||
pressed = {
|
||||
atlas = "themes/button_pressed.png",
|
||||
regions = { ... }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Tips
|
||||
|
||||
1. **Start Simple**: Begin with one component (button) before creating a full theme
|
||||
2. **Test Scaling**: Make sure your 9-slice regions stretch properly at different sizes
|
||||
3. **Consistent Style**: Keep corner sizes consistent across components
|
||||
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
|
||||
|
||||
## Tools for Creating Atlases
|
||||
|
||||
- **TexturePacker**: Professional sprite sheet tool
|
||||
- **Aseprite**: Pixel art editor with export options
|
||||
- **Shoebox**: Free sprite sheet packer
|
||||
- **GIMP/Photoshop**: Manual layout with guides
|
||||
|
||||
## See Also
|
||||
|
||||
- `default.lua` - Example theme with single atlas
|
||||
- `separate_images_example.lua` - Example with separate images per component
|
||||
- `ThemeSystemDemo.lua` - Interactive demo of theme system
|
||||
Reference in New Issue
Block a user