This commit is contained in:
Insality
2025-03-06 01:50:31 +02:00
parent ea4ff7eafc
commit 3bb8705444
20 changed files with 2382 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
# Druid Back Handler Component
## Description
The Back Handler component is designed to handle back button actions, including the Android back button and the Backspace key. It provides a simple way to implement back navigation or other actions when the user presses the back button.
## Features
- Handles Android back button and Backspace key presses
- Customizable callback function
- Optional parameters to pass to the callback
- Event-based architecture
## Basic Usage
```lua
local callback = function(self, params)
-- Handle back action here
print("Back button pressed!")
end
local params = { custom_data = "value" }
local back_handler = self.druid:new_back_handler(callback, params)
```
### Parameters
- **callback**: (optional) Function to call when back button is pressed
- **params**: (optional) Custom data to pass to the callback
## Events
The Back Handler component provides an event you can subscribe to:
```lua
-- Subscribe to back event
back_handler.on_back:subscribe(function(self, params)
print("Back button was pressed!")
end)
```
## Notes
- The Back Handler component requires proper key triggers setup in your `input.binding` file for correct operation
- Back Handler is recommended to be placed in every game window to handle closing or in the main screen to call settings windows
- Multiple Back Handlers can be active at the same time, but only the first one that processes the input will trigger its callback
- Back Handler reacts on release action of ACTION_BACK or ACTION_BACKSPACE

View File

@@ -0,0 +1,50 @@
# Druid Blocker Component
## Description
The Blocker component is designed to consume input in a specific zone defined by a GUI node. It's useful for creating unclickable zones within buttons or for creating panels of buttons on top of another button.
## Features
- Blocks input in a specific zone
- Can be enabled or disabled programmatically
- Useful for creating safe zones in UI
## Basic Usage
```lua
local blocker = self.druid:new_blocker("blocker_node")
```
### Parameters
- **node**: The node or node_id of the blocker node
## Methods
```lua
-- Enable or disable the blocker
blocker:set_enabled(true) -- Enable
blocker:set_enabled(false) -- Disable
-- Check if blocker is enabled
local is_enabled = blocker:is_enabled()
```
## Notes
- The Blocker component consumes input if `gui.pick_node` works on it
- The Blocker node should be enabled to capture input
- The initial enabled state is determined by `gui.is_enabled(node, true)`
- Blocker is useful for creating "safe zones" in your UI, where you have large buttons with specific clickable areas
- A common use case is to place a blocker with window content behind a close button, so clicking outside the close button (but still on the window) doesn't trigger actions from elements behind the window
### Example Use Case
![Blocker Scheme](../../../media/blocker_scheme.png)
In this example:
- Blue zone is a **button** with close_window callback
- Yellow zone is a blocker with window content
This setup creates a safe zone where the user can interact with the window content without accidentally triggering actions from elements behind the window.

View File

@@ -0,0 +1,89 @@
# Druid Button Component
## Description
Button component is a basic component that can be used to create a clickable button. It provides various interaction callbacks such as click, long click, double click, and more. The component makes any GUI node clickable and allows you to define different behaviors for various user interactions.
## Features
- Regular click handling
- Long click detection
- Double click detection
- Repeated click handling (while holding)
- Hold state callbacks
- Click outside detection
- Keyboard key triggering
- Custom animation node support
- Enabled/disabled states
- Customizable click zones
- HTML5 interaction support
## Basic Usage
```lua
local button = self.druid:new_button(node, [callback], [params], [anim_node])
```
### Parameters
- **node**: The node or node_id to make clickable
- **callback**: (optional) Function to call when button is clicked
- **params**: (optional) Custom arguments to pass to the callback
- **anim_node**: (optional) Node to animate instead of the trigger node
### Example
```lua
-- Simple button with callback
local button = self.druid:new_button("button_node", function(self, params, button_instance)
print("Button clicked!")
end)
-- Button with custom parameters
local custom_args = "Any data to pass to callback"
local button = self.druid:new_button("button_node", on_button_click, custom_args)
-- Button with separate animation node
local button = self.druid:new_button("big_panel", callback, nil, "small_icon")
```
## HTML5 Interaction
The Button component supports HTML5 interaction mode, which allows you to define different behaviors for various user interactions. Use this mode when you need to use special interactions like copy/paste, keyboard, etc.
```lua
button:set_web_user_interaction(true)
```
## Events
The Button component provides several events you can subscribe to:
- **on_click**: Triggered when button is clicked
- **on_pressed**: Triggered when button is pressed down
- **on_repeated_click**: Triggered repeatedly while holding the button
- **on_long_click**: Triggered when button is held for a certain time
- **on_double_click**: Triggered when button is clicked twice in quick succession
- **on_hold_callback**: Triggered while holding the button, before long_click
- **on_click_outside**: Triggered when click is released outside the button
### Example
```lua
-- Subscribe to double click event
button.on_double_click:subscribe(function(self, params, button_instance, click_amount)
print("Double clicked! Click amount: " .. click_amount)
end)
-- Subscribe to long click event
button.on_long_click:subscribe(function(self, params, button_instance, hold_time)
print("Long press detected! Hold time: " .. hold_time)
end)
```
## Notes
- The click callback will not trigger if the cursor moves outside the node's area between pressed and released states
- If a button has a double click event and it is triggered, the regular click callback will not be invoked
- If you have a stencil on buttons and don't want to trigger them outside the stencil node, use `button:set_click_zone`
- Animation node can be used to animate a small icon on a big panel (trigger zone is the big panel, animation node is the small icon)

View File

@@ -0,0 +1,79 @@
# Druid Drag Component
## Description
The Drag component handles drag actions on a node, allowing users to move UI elements by dragging them. It provides proper handling for multitouch and swap touches while dragging.
## Features
- Handles drag actions on nodes
- Supports multitouch and touch swapping
- Provides drag start, drag, and drag end events
- Customizable drag deadzone
- Optional click zone restriction
## Basic Usage
```lua
local drag = self.druid:new_drag("drag_node", function(self, dx, dy, x, y, touch)
-- Handle drag action
local position = gui.get_position(drag.node)
gui.set_position(drag.node, vmath.vector3(position.x + dx, position.y + dy, position.z))
end)
```
### Parameters
- **node**: The node or node_id of the draggable node
- **on_drag_callback**: (optional) Function to call during drag with parameters (self, dx, dy, total_x, total_y, touch)
## Events
The Drag component provides several events you can subscribe to:
```lua
-- Subscribe to drag start event
drag.on_drag_start:subscribe(function(self, touch)
print("Drag started")
end)
-- Subscribe to drag end event
drag.on_drag_end:subscribe(function(self, x, y, touch)
print("Drag ended, total movement: " .. x .. ", " .. y)
end)
-- Subscribe to touch start/end events
drag.on_touch_start:subscribe(function(self, touch)
print("Touch started")
end)
drag.on_touch_end:subscribe(function(self, touch)
print("Touch ended")
end)
```
## Methods
```lua
-- Set a click zone to restrict drag area
drag:set_click_zone("stencil_node")
-- Enable or disable drag
drag:set_enabled(true) -- Enable
drag:set_enabled(false) -- Disable
-- Check if drag is enabled
local is_enabled = drag:is_enabled()
-- Set drag cursor appearance (requires defos)
drag:set_drag_cursors(true) -- Enable custom cursors
drag:set_drag_cursors(false) -- Disable custom cursors
```
## Notes
- Drag will be processed even if the cursor is outside of the node, as long as the drag has already started
- The component has a configurable deadzone (default: 10 pixels) before drag is triggered
- You can restrict the drag area by setting a click zone, which is useful for stencil nodes
- The drag component automatically detects the closest stencil node and sets it as the click zone if none is specified
- The drag component can be configured to use screen aspect ratio for drag values

View File

@@ -0,0 +1,84 @@
# Druid Hover Component
## Description
The Hover component handles hover interactions with nodes, providing callbacks for both touch hover and mouse hover states. It's useful for creating interactive UI elements that respond to user hover actions.
## Features
- Handles touch hover (with pressed action)
- Handles mouse hover (without pressing)
- Provides hover state tracking
- Customizable cursor styles (with defos)
- Optional click zone restriction
## Basic Usage
```lua
-- Basic hover with touch hover callback
local hover = self.druid:new_hover("node", function(self, is_hover)
-- Handle hover state change
local color = is_hover and vmath.vector4(1, 0.8, 0.8, 1) or vmath.vector4(1, 1, 1, 1)
gui.animate(hover.node, "color", color, gui.EASING_LINEAR, 0.2)
end)
-- Hover with both touch and mouse hover callbacks
local hover = self.druid:new_hover("node",
function(self, is_hover)
-- Handle touch hover
end,
function(self, is_hover)
-- Handle mouse hover
end
)
```
### Parameters
- **node**: The node or node_id of the hover node
- **on_hover_callback**: (optional) Function to call on touch hover state change
- **on_mouse_hover_callback**: (optional) Function to call on mouse hover state change
## Events
The Hover component provides two events you can subscribe to:
```lua
-- Subscribe to touch hover event
hover.on_hover:subscribe(function(self, is_hover)
print("Touch hover state: " .. tostring(is_hover))
end)
-- Subscribe to mouse hover event
hover.on_mouse_hover:subscribe(function(self, is_hover)
print("Mouse hover state: " .. tostring(is_hover))
end)
```
## Methods
```lua
-- Set hover state manually
hover:set_hover(true)
hover:set_hover(false)
-- Set mouse hover state manually
hover:set_mouse_hover(true)
hover:set_mouse_hover(false)
-- Check current hover states
local is_hovered = hover:is_hovered()
local is_mouse_hovered = hover:is_mouse_hovered()
-- Set a click zone to restrict hover area
hover:set_click_zone("stencil_node")
```
## Notes
- By default, hover handles the "hover event" with pressed touch action_id, meaning the mouse or touch has to be pressed
- On desktop platforms, there is an "on_mouse_hover" event that triggers on mouse hover without any action id
- By default, the component assumes the node is in a non-hovered state (both hover and mouse_hover)
- The hover component automatically detects the closest stencil node and sets it as the click zone if none is specified
- You can customize cursor styles for hover states if you're using the defos extension
- Hover state is automatically reset when input is interrupted or the node is disabled

View File

@@ -0,0 +1,106 @@
# Druid Scroll Component
## Description
The Scroll component handles scrollable content in your UI. It consists of two main parts: a static view node that captures user input, and a dynamic content node that moves in response to user interaction.
## Features
- Horizontal and vertical scrolling
- Inertial scrolling with customizable friction
- Points of interest for snap-to-position scrolling
- Scroll-to-position and scroll-to-percent functions
- Mouse wheel support
- Stretch effect for overscrolling
- Grid binding for automatic content size adjustment
## Basic Usage
```lua
local scroll = self.druid:new_scroll("view_node", "content_node")
```
### Parameters
- **view_node**: The node or node_id of the static view part (captures input)
- **content_node**: The node or node_id of the dynamic content part (moves when scrolling)
## Setup
The typical setup involves placing a view_node and adding a content_node as its child:
![Scroll Scheme](../../../media/scroll_scheme.png)
The view_node captures user input and defines the visible area, while the content_node contains all the scrollable content and moves in response to user interaction.
## Methods
```lua
-- Scroll to a specific position
scroll:scroll_to(vmath.vector3(100, 200, 0), false) -- Animated scroll
scroll:scroll_to(vmath.vector3(100, 200, 0), true) -- Instant scroll
-- Scroll to a percentage of the content
scroll:scroll_to_percent(vmath.vector3(0.5, 0.5, 0), false) -- Scroll to middle
-- Get current scroll percentage
local percent = scroll:get_percent()
-- Set content size
scroll:set_size(vmath.vector3(500, 1000, 0))
-- Update view size if it changes
scroll:update_view_size()
-- Enable/disable inertial scrolling
scroll:set_inert(true)
scroll:set_inert(false)
-- Set points of interest for snap-to-position scrolling
scroll:set_points({
vmath.vector3(0, 0, 0),
vmath.vector3(0, 200, 0),
vmath.vector3(0, 400, 0)
})
-- Scroll to a specific point of interest
scroll:scroll_to_index(2)
-- Enable/disable horizontal or vertical scrolling
scroll:set_horizontal_scroll(true)
scroll:set_vertical_scroll(true)
-- Check if a node is visible in the scroll view
local is_visible = scroll:is_node_in_view(node)
-- Bind a grid to automatically adjust scroll size
scroll:bind_grid(grid)
```
## Events
```lua
-- Subscribe to scroll movement
scroll.on_scroll:subscribe(function(self, position)
print("Scroll position: " .. position.x .. ", " .. position.y)
end)
-- Subscribe to scroll_to events
scroll.on_scroll_to:subscribe(function(self, target, is_instant)
print("Scrolling to: " .. target.x .. ", " .. target.y)
end)
-- Subscribe to point scroll events
scroll.on_point_scroll:subscribe(function(self, index, point)
print("Scrolled to point: " .. index)
end)
```
## Notes
- The scroll component has customizable style parameters for friction, inertia, and stretch effects
- By default, scroll has inertia and a stretching effect, which can be adjusted via style settings
- You can set up "points of interest" to make the scroll always center on the closest point
- When using a stencil node with the scroll, buttons inside the scroll may be clickable outside the stencil bounds. Use `button:set_click_zone(scroll.view_node)` to restrict button clicks to the visible area
- The scroll component automatically detects the closest stencil node and sets it as the click zone if none is specified
- Mouse wheel scrolling is supported and can be customized or disabled via style settings

View File

@@ -0,0 +1,119 @@
# Druid Static Grid Component
## Description
The Static Grid component handles the positioning of UI elements in a grid layout with rows and columns. It provides a way to organize nodes in a structured grid with consistent spacing.
## Features
- Automatic positioning of nodes in rows and columns
- Customizable number of elements per row
- Dynamic addition and removal of nodes
- Node sorting capabilities
- Events for grid changes
- Automatic size calculation
## Basic Usage
```lua
local grid = self.druid:new_grid("parent_node", "item_prefab", 3)
-- Add nodes to the grid
local node1 = gui.clone(prefab)
local node2 = gui.clone(prefab)
grid:add(node1)
grid:add(node2)
```
### Parameters
- **parent_node**: The node or node_id of the parent container where grid items will be placed
- **item_prefab**: The node or node_id of the item prefab (used to determine item size)
- **in_row**: (optional) Number of items per row (default: 1)
## Methods
```lua
-- Add a node to the grid
local node = gui.clone(prefab)
grid:add(node)
-- Add multiple nodes
grid:add_many({node1, node2, node3})
-- Remove a node from the grid
grid:remove(node)
-- Clear all nodes from the grid
grid:clear()
-- Get node position by index
local position = grid:get_pos(5)
-- Get grid size for a specific number of elements
local size = grid:get_size_for(10)
-- Get current grid borders
local borders = grid:get_borders()
-- Get all node positions
local positions = grid:get_all_pos()
-- Set custom position function
grid:set_position_function(function(node, pos)
-- Custom positioning logic
gui.set_position(node, pos)
end)
-- Change items per row
grid:set_in_row(4)
-- Set item size
grid:set_item_size(100, 50)
-- Sort grid nodes
grid:sort_nodes(function(a, b)
-- Custom sorting logic
return gui.get_id(a) < gui.get_id(b)
end)
```
## Events
```lua
-- Subscribe to node addition
grid.on_add_item:subscribe(function(self, node)
print("Node added to grid")
end)
-- Subscribe to node removal
grid.on_remove_item:subscribe(function(self, node)
print("Node removed from grid")
end)
-- Subscribe to grid changes
grid.on_change_items:subscribe(function(self)
print("Grid items changed")
end)
-- Subscribe to grid clear
grid.on_clear:subscribe(function(self)
print("Grid cleared")
end)
-- Subscribe to position updates
grid.on_update_positions:subscribe(function(self)
print("Grid positions updated")
end)
```
## Notes
- The grid component calculates positions based on the size of the item prefab
- The grid's pivot point affects how items are positioned within the grid
- You can customize the grid's behavior with style settings:
- `IS_DYNAMIC_NODE_POSES`: If true, always centers grid content based on the grid's pivot
- `IS_ALIGN_LAST_ROW`: If true, always aligns the last row of the grid based on the grid's pivot
- The grid component does not automatically delete GUI nodes when cleared or when nodes are removed
- The grid can be used with the Scroll component to create scrollable lists
- When used with DataList, the grid can efficiently handle large collections of data

View File

@@ -0,0 +1,141 @@
# Druid Text Component
## Description
Text component is a basic component that provides various adjustment modes for text nodes. It allows text to be scaled down to fit within the size of the text node, trimmed, scrolled, or a combination of these adjustments. The component makes it easy to handle text display in different scenarios.
## Features
- Automatic text size adjustment
- Multiple text adjustment modes (downscale, trim, scroll, etc.)
- Text pivot control
- Text color and alpha management
- Text size and scale control
- Text metrics calculation
- Event-based architecture for text changes
## Basic Usage
```lua
local text = self.druid:new_text(node, [initial_value], [adjust_type])
```
### Parameters
- **node**: The node or node_id of the text node
- **initial_value**: (optional) Initial text value. Default is the text from the GUI node
- **adjust_type**: (optional) Adjustment type for text. Default is "DOWNSCALE". See adjustment types below
### Example
```lua
-- Simple text component
local text = self.druid:new_text("text_node")
-- Text with initial value
local text = self.druid:new_text("text_node", "Hello, World!")
-- Text with specific adjustment type
local text = self.druid:new_text("text_node", "Hello, World!", const.TEXT_ADJUST.TRIM)
```
## Text Adjustment Types
The Text component supports several adjustment types to handle different text display scenarios:
- **DOWNSCALE**: Scales down the text to fit within the text node's size
- **NO_ADJUST**: No adjustment, text displays as is
- **TRIM**: Trims the text with an ellipsis (...) if it doesn't fit
- **TRIM_LEFT**: Trims the text from the left with an ellipsis if it doesn't fit
- **DOWNSCALE_LIMITED**: Scales down the text but not below a minimum scale
- **SCROLL**: Shifts the text anchor when it doesn't fit
- **SCALE_THEN_SCROLL**: First scales down the text, then scrolls if needed
- **SCALE_THEN_TRIM**: First scales down the text, then trims if needed
- **SCALE_THEN_TRIM_LEFT**: First scales down the text, then trims from the left if needed
### Example
```lua
-- Import constants
local const = require("druid.const")
-- Create text with TRIM adjustment
local text = self.druid:new_text("text_node", "Long text that might not fit", const.TEXT_ADJUST.TRIM)
-- Change adjustment type later
text:set_text_adjust(const.TEXT_ADJUST.SCALE_THEN_TRIM)
```
## Events
The Text component provides several events you can subscribe to:
- **on_set_text**: Triggered when text is set or changed
- **on_update_text_scale**: Triggered when text scale is updated
- **on_set_pivot**: Triggered when text pivot is changed
### Example
```lua
-- Subscribe to text change event
text.on_set_text:subscribe(function(self, text_value)
print("Text changed to: " .. text_value)
end)
-- Subscribe to scale update event
text.on_update_text_scale:subscribe(function(self, scale, metrics)
print("Text scale updated to: " .. scale.x)
end)
```
## Methods
```lua
-- Set text content
text:set_text("New text content")
-- Get current text content
local current_text = text:get_text()
-- Set text area size
text:set_size(vmath.vector3(200, 100, 0))
-- Set text color
text:set_color(vmath.vector4(1, 0, 0, 1)) -- Red color
-- Set text alpha
text:set_alpha(0.5) -- 50% opacity
-- Set text scale
text:set_scale(vmath.vector3(1.5, 1.5, 1)) -- 150% scale
-- Set text pivot
text:set_pivot(gui.PIVOT_CENTER)
-- Check if text is multiline
local is_multiline = text:is_multiline()
-- Set text adjustment type
text:set_text_adjust(const.TEXT_ADJUST.TRIM)
-- Set minimal scale for limited adjustment types
text:set_minimal_scale(0.5) -- 50% minimum scale
-- Get current text adjustment type
local adjust_type = text:get_text_adjust()
-- Get text size (width and height)
local width, height = text:get_text_size()
-- Get text index by width (useful for cursor positioning)
local char_index = text:get_text_index_by_width(100)
```
## Notes
- Text component by default has auto-adjust text sizing. Text will never be bigger than the text node size, which you can set up in the GUI scene.
- Auto-adjustment can be disabled by setting the adjustment type to `NO_ADJUST`.
- Text pivot can be changed with `text:set_pivot()`, and the text will maintain its position inside the text size box.
- For multiline text, the component will try to fit the text within both width and height constraints.
- The trim postfix (default: "...") can be customized in the style settings.
- When using `DOWNSCALE_LIMITED` or `SCALE_THEN_SCROLL`, you can set a minimal scale to prevent text from becoming too small.