mirror of
https://github.com/Insality/druid.git
synced 2025-06-27 10:27:47 +02:00
Update annotations P.1
This commit is contained in:
parent
a46f38734e
commit
c85d66fdca
48
README.md
48
README.md
@ -17,13 +17,15 @@ In this example you can inspect a variety of **Druid** components and see how th
|
||||
|
||||
## Setup
|
||||
|
||||
### Dependency
|
||||
### [Dependency](https://www.defold.com/manuals/libraries/)
|
||||
|
||||
To integrate the **Druid** extension into your own project, add this project as a [dependency](https://www.defold.com/manuals/libraries/) in your **Defold** game. Open your `game.project` file and add the following line to the dependencies field under the project section:
|
||||
Open your `game.project` file and add the following line to the dependencies field under the project section:
|
||||
|
||||
**Druid v1.0**
|
||||
**[Druid](https://github.com/Insality/druid/archive/refs/tags/1.0.zip)**
|
||||
|
||||
> [https://github.com/Insality/druid/archive/refs/tags/1.0.zip](https://github.com/Insality/druid/archive/refs/tags/1.0.zip)
|
||||
```
|
||||
https://github.com/Insality/druid/archive/refs/tags/1.0.zip
|
||||
```
|
||||
|
||||
Here is a list of [all releases](https://github.com/Insality/druid/releases).
|
||||
|
||||
@ -119,15 +121,15 @@ Here is full **Druid** components list.
|
||||
|
||||
| Name | Description | Example | <div style="width:200px">Preview</div> |
|
||||
|------|-------------|---------|---------|
|
||||
| **[Button](https://insality.github.io/druid/modules/Button.html)** | Logic over GUI Node. Handle the user click interactions: click, long click, double click, etc. | [Button Example](https://insality.github.io/druid/druid/?example=general_buttons) | <img src="media/preview/button.gif" width="200" height="100"> |
|
||||
| **[Text](https://insality.github.io/druid/modules/Text.html)** | Logic over GUI Text. By default Text component fit the text inside text node size area with different adjust modes. | [Text Example](https://insality.github.io/druid/druid/?example=texts_general) | <img src="media/preview/text.gif" width="200" height="100"> |
|
||||
| **[Scroll](https://insality.github.io/druid/modules/Scroll.html)** | Logic over two GUI Nodes: input and content. Provides basic behaviour for scrollable content. | [Scroll Example](https://insality.github.io/druid/druid/?example=general_scroll) | <img src="media/preview/scroll.gif" width="200" height="100"> |
|
||||
| **[Blocker](https://insality.github.io/druid/modules/Blocker.html)** | Logic over GUI Node. Don't pass any user input below node area size. | [Blocker Example](https://insality.github.io/druid/druid/?example=timer) | <img src="media/preview/blocker.gif" width="200" height="100"> |
|
||||
| **[Back Handler](https://insality.github.io/druid/modules/BackHandler.html)** | Call callback on user "Back" action. It's a Android back button or keyboard backspace key | [Back Handler Example](https://insality.github.io/druid/druid/?example=timer) | <img src="media/preview/back_handler.gif" width="200" height="100"> |
|
||||
| **[Static Grid](https://insality.github.io/druid/modules/StaticGrid.html)** | Logic over GUI Node. Component to manage node positions with all equal node sizes. | [Static Gid Example](https://insality.github.io/druid/druid/?example=general_grid) | <img src="media/preview/static_grid.gif" width="200" height="100"> |
|
||||
| **[Hover](https://insality.github.io/druid/modules/Hover.html)** | Logic over GUI Node. Handle hover action over node. For both: mobile touch and mouse cursor. | [Hover Example](https://insality.github.io/druid/druid/?example=timer) | <img src="media/preview/hover.gif" width="200" height="100"> |
|
||||
| **[Swipe](https://insality.github.io/druid/modules/Swipe.html)** | Logic over GUI Node. Handle swipe gestures over node. | [Swipe Example](https://insality.github.io/druid/druid/?example=general_swipe) | <img src="media/preview/swipe.gif" width="200" height="100"> |
|
||||
| **[Drag](https://insality.github.io/druid/modules/Drag.html)** | Logic over GUI Node. Handle drag input actions. Can be useful to make on screen controlls. | [Drag Example](https://insality.github.io/druid/druid/?example=general_drag) | <img src="media/preview/drag.gif" width="200" height="100"> |
|
||||
| **[Button](https://insality.github.io/druid/modules/Button.html)** | Logic over GUI Node. Handle the user click interactions: click, long click, double click, etc. | [Button Example](https://insality.github.io/druid/druid/?example=ui_example_basic_button) | <img src="media/preview/button.gif" width="200" height="100"> |
|
||||
| **[Text](https://insality.github.io/druid/modules/Text.html)** | Logic over GUI Text. By default Text component fit the text inside text node size area with different adjust modes. | [Text Example](https://insality.github.io/druid/druid/?example=ui_example_basic_text) | <img src="media/preview/text.gif" width="200" height="100"> |
|
||||
| **[Scroll](https://insality.github.io/druid/modules/Scroll.html)** | Logic over two GUI Nodes: input and content. Provides basic behaviour for scrollable content. | [Scroll Example](https://insality.github.io/druid/druid/?example=ui_example_basic_scroll) | <img src="media/preview/scroll.gif" width="200" height="100"> |
|
||||
| **[Blocker](https://insality.github.io/druid/modules/Blocker.html)** | Logic over GUI Node. Don't pass any user input below node area size. | [Blocker Example](https://insality.github.io/druid/druid/?example=ui_example_basic_blocker) | <img src="media/preview/blocker.gif" width="200" height="100"> |
|
||||
| **[Back Handler](https://insality.github.io/druid/modules/BackHandler.html)** | Call callback on user "Back" action. It's a Android back button or keyboard backspace key | [Back Handler Example](https://insality.github.io/druid/druid/?example=ui_example_basic_back_handler) | <img src="media/preview/back_handler.gif" width="200" height="100"> |
|
||||
| **[Static Grid](https://insality.github.io/druid/modules/StaticGrid.html)** | Logic over GUI Node. Component to manage node positions with all equal node sizes. | [Static Gid Example](https://insality.github.io/druid/druid/?example=ui_example_basic_grid) | <img src="media/preview/static_grid.gif" width="200" height="100"> |
|
||||
| **[Hover](https://insality.github.io/druid/modules/Hover.html)** | Logic over GUI Node. Handle hover action over node. For both: mobile touch and mouse cursor. | [Hover Example](https://insality.github.io/druid/druid/?example=ui_example_basic_hover) | <img src="media/preview/hover.gif" width="200" height="100"> |
|
||||
| **[Swipe](https://insality.github.io/druid/modules/Swipe.html)** | Logic over GUI Node. Handle swipe gestures over node. | [Swipe Example](https://insality.github.io/druid/druid/?example=ui_example_basic_swipe) | <img src="media/preview/swipe.gif" width="200" height="100"> |
|
||||
| **[Drag](https://insality.github.io/druid/modules/Drag.html)** | Logic over GUI Node. Handle drag input actions. Can be useful to make on screen controlls. | [Drag Example](https://insality.github.io/druid/druid/?example=ui_example_basic_drag) | <img src="media/preview/drag.gif" width="200" height="100"> |
|
||||
|
||||
|
||||
### Extended components
|
||||
@ -141,16 +143,16 @@ druid.register("data_list", data_list)
|
||||
|
||||
| Name | Description | Example | <div style="width:200px">Preview</div> |
|
||||
|------|-------------|---------|---------|
|
||||
| **[Data List](https://insality.github.io/druid/modules/DataList.html)** | Logic over Scroll and Grid components. Create only visible GUI nodes or components to make "infinity" scroll befaviour | [Data List Example](https://insality.github.io/druid/druid/?example=general_data_list) | <img src="media/preview/data_list.gif" width="200" height="100"> |
|
||||
| **[Input](https://insality.github.io/druid/modules/Input.html)** | Logic over GUI Node and GUI Text (or Text component). Provides basic user text input. | [Input Example](https://insality.github.io/druid/druid/?example=general_input) | <img src="media/preview/input.gif" width="200" height="100"> |
|
||||
| **[Lang text](https://insality.github.io/druid/modules/LangText.html)** | Logic over Text component to handle localization. Can be translated in real-time with `druid.on_language_change` | [Lang Text Example](https://insality.github.io/druid/druid/?example=timer) | <img src="media/preview/lang_text.gif" width="200" height="100"> |
|
||||
| **[Progress](https://insality.github.io/druid/modules/Progress.html)** | Logic over GUI Node. Handle node size and scale to handle progress node size. | [Progress Example](https://insality.github.io/druid/druid/?example=general_progress_bar) | <img src="media/preview/progress.gif" width="200" height="100"> |
|
||||
| **[Slider](https://insality.github.io/druid/modules/Slider.html)** | Logic over GUI Node. Handle draggable node with position restrictions. | [Slider Example](https://insality.github.io/druid/druid/?example=general_sliders) | <img src="media/preview/slider.gif" width="200" height="100"> |
|
||||
| **[Timer](https://insality.github.io/druid/modules/Timer.html)** | Logic over GUI Text. Handle basic timer functions. | [Timer Example](https://insality.github.io/druid/druid/?example=timer) | <img src="media/preview/timer.gif" width="200" height="100"> |
|
||||
| **[Hotkey](https://insality.github.io/druid/modules/Hotkey.html)** | Allow to set callbacks for keyboard hotkeys with key modificators. | [Hotkey Example](https://insality.github.io/druid/druid/?example=general_hotkey) | <img src="media/preview/hotkey.gif" width="200" height="100"> |
|
||||
| **[Layout](https://insality.github.io/druid/modules/Layout.html)** | Logic over GUI Node. Arrange nodes inside layout node with margin/paddings settings. | [Layout Example](https://insality.github.io/druid/druid/?example=general_layout) | <img src="media/preview/layout.gif" width="200" height="100"> |
|
||||
| **[Rich Input](https://insality.github.io/druid/modules/RichInput.html)** | Logic over GUI Node and GUI Text (or Text component). Provides rich text input with different styles and text formatting. | [Rich Input Example](https://insality.github.io/druid/druid/?example=general_rich_input) | <img src="media/preview/rich_input.gif" width="200" height="100"> |
|
||||
| **[Rich Text](https://insality.github.io/druid/modules/RichText.html)** | Logic over GUI Text. Provides rich text formatting with different styles and text formatting. | [Rich Text Example](https://insality.github.io/druid/druid/?example=general_rich_text) | <img src="media/preview/rich_text.gif" width="200" height="100"> |
|
||||
| **[Data List](https://insality.github.io/druid/modules/DataList.html)** | Logic over Scroll and Grid components. Create only visible GUI nodes or components to make "infinity" scroll befaviour | [Data List Example](https://insality.github.io/druid/druid/?example=ui_example_data_list_basic) | <img src="media/preview/data_list.gif" width="200" height="100"> |
|
||||
| **[Input](https://insality.github.io/druid/modules/Input.html)** | Logic over GUI Node and GUI Text (or Text component). Provides basic user text input. | [Input Example](https://insality.github.io/druid/druid/?example=ui_example_basic_input) | <img src="media/preview/input.gif" width="200" height="100"> |
|
||||
| **[Lang text](https://insality.github.io/druid/modules/LangText.html)** | Logic over Text component to handle localization. Can be translated in real-time with `druid.on_language_change` | [Lang Text Example](https://insality.github.io/druid/druid/?example=ui_example_window_language) | <img src="media/preview/lang_text.gif" width="200" height="100"> |
|
||||
| **[Progress](https://insality.github.io/druid/modules/Progress.html)** | Logic over GUI Node. Handle node size and scale to handle progress node size. | [Progress Example](https://insality.github.io/druid/druid/?example=ui_example_basic_progress_bar) | <img src="media/preview/progress.gif" width="200" height="100"> |
|
||||
| **[Slider](https://insality.github.io/druid/modules/Slider.html)** | Logic over GUI Node. Handle draggable node with position restrictions. | [Slider Example](https://insality.github.io/druid/druid/?example=ui_example_basic_slider) | <img src="media/preview/slider.gif" width="200" height="100"> |
|
||||
| **[Timer](https://insality.github.io/druid/modules/Timer.html)** | Logic over GUI Text. Handle basic timer functions. | [Timer Example](https://insality.github.io/druid/druid/?example=ui_example_basic_timer) | <img src="media/preview/timer.gif" width="200" height="100"> |
|
||||
| **[Hotkey](https://insality.github.io/druid/modules/Hotkey.html)** | Allow to set callbacks for keyboard hotkeys with key modificators. | [Hotkey Example](https://insality.github.io/druid/druid/?example=ui_example_basic_hotkey) | <img src="media/preview/hotkey.gif" width="200" height="100"> |
|
||||
| **[Layout](https://insality.github.io/druid/modules/Layout.html)** | Logic over GUI Node. Arrange nodes inside layout node with margin/paddings settings. | [Layout Example](https://insality.github.io/druid/druid/?example=ui_example_layout_basic) | <img src="media/preview/layout.gif" width="200" height="100"> |
|
||||
| **[Rich Input](https://insality.github.io/druid/modules/RichInput.html)** | Logic over GUI Node and GUI Text (or Text component). Provides rich text input with different styles and text formatting. | [Rich Input Example](https://insality.github.io/druid/druid/?example=ui_example_basic_rich_input) | <img src="media/preview/rich_input.gif" width="200" height="100"> |
|
||||
| **[Rich Text](https://insality.github.io/druid/modules/RichText.html)** | Logic over GUI Text. Provides rich text formatting with different styles and text formatting. | [Rich Text Example](https://insality.github.io/druid/druid/?example=ui_example_basic_rich_text) | <img src="media/preview/rich_text.gif" width="200" height="100"> |
|
||||
|
||||
For a complete overview, see: **_[components.md](docs_md/01-components.md)_**.
|
||||
|
||||
|
@ -227,33 +227,6 @@ Create component with druid: `grid = druid:new_static_grid(parent_node, prefab_
|
||||
- _Prefab node_ used to get node size and anchor
|
||||
- You can point *position_function* for animations with _static_grid:set_position_function(node, pos)_ callback. Default - *gui.set_position()*
|
||||
|
||||
|
||||
## Dynamic Grid
|
||||
[Dynamic Grid API here](https://insality.github.io/druid/modules/DynamicGrid.html)
|
||||
|
||||
### Overview
|
||||
Component for manage node positions with different node sizes.
|
||||
Unlike Static Grid, Dynamic Grid can place nodes only in one row or in one column.
|
||||
Dynamic Grid can't have gaps between elements
|
||||
- you will get error, if try spawn element far away from others.
|
||||
Dynamic Grid should have __West__, __East__, __South__ or __North__ pivot (vertical or horizontal element placement)
|
||||
|
||||
### Setup
|
||||
Create component with druid: `grid = druid:new_dynamic_grid(parent_node)`
|
||||
|
||||
Check the _parent_node_ have correct pivot point. You will get the error otherwise.
|
||||
|
||||
### Notes
|
||||
- On _add node_ grid will set node parent to _parent_node_
|
||||
- You can get array of position of every element for setup points of interest in scroll component
|
||||
- You can get size of all elements for setup size in scroll component
|
||||
- You can also bind the grid to the scroll component for auto resize scroll content size
|
||||
- Pivot of parent_node matter for node placement
|
||||
- You can point *position_function* for animations with _static_grid:set_position_function(node, pos)_ callback. Default - *gui.set_position()*
|
||||
- First node placed at Grid pivot point. Other nodes placed nearby of other nodes.
|
||||
- On *add/remove* nodes always shifted. You can point the shift side in this functions (*is_shift_left* boolean argumentp
|
||||
|
||||
|
||||
## Data List
|
||||
[Data List API here](https://insality.github.io/druid/modules/DataList.html)
|
||||
|
||||
|
@ -148,7 +148,6 @@ Available keywords:
|
||||
- `text`: Adds a [Druid Text](01-components.md#text) component.
|
||||
- `lang_text`: Adds a [Druid Lang Text](01-components.md#lang-text) component.
|
||||
- `grid` or `static_grid`: Adds a [Druid Static Grid](01-components.md#static-grid) component. You should set up the Grid prefab for this component after generating the file.
|
||||
- `dynamic_grid`: Adds a [Druid Dynamic Grid](01-components.md#dynamic-grid) component.
|
||||
- `scroll_view`: Adds a [Druid Scroll](01-components.md#scroll) component. It also adds a `scroll_content` node with the same postfix. Ensure that it's the correct node.
|
||||
- `blocker`: Adds a [Druid Blocker](01-components.md#blocker) component.
|
||||
- `slider`: Adds a [Druid Slider](01-components.md#slider) component. You should adjust the end position of the Slider after generating the file.
|
||||
|
@ -121,7 +121,7 @@ window.set_listener(on_window_callback)
|
||||
```
|
||||
|
||||
|
||||
## EmmyLua Annotations
|
||||
## Lua Annotations
|
||||
|
||||
[EmmyLua](https://emmylua.github.io/annotation.html) is a Lua annotation library. It is a useful tool for enabling Lua code autocompletion in editors such as [VSCode](https://github.com/EmmyLua/VSCode-EmmyLua) and [IntelliJ IDEA](https://github.com/EmmyLua/IntelliJ-EmmyLua).
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,65 +1,24 @@
|
||||
-- Copyright (c) 2023 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Component with event on back and backspace button.
|
||||
-- <b># Overview #</b>
|
||||
--
|
||||
-- Back Handler is recommended to put in every game window to close it
|
||||
-- or in main screen to call settings window.
|
||||
--
|
||||
-- <b># Notes #</b>
|
||||
--
|
||||
-- • Back Handler inheritance @{BaseComponent}, you can use all of its methods in addition to those described here.
|
||||
--
|
||||
-- • Back Handler react on release action ACTION_BACK or ACTION_BACKSPACE
|
||||
-- @usage
|
||||
-- local callback = function(self, params) ... end
|
||||
--
|
||||
-- local params = {}
|
||||
-- local back_handler = self.druid:new_back_handler(callback, [params])
|
||||
-- @module BackHandler
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.back_handler
|
||||
|
||||
--- The @{DruidEvent} Event on back handler action.
|
||||
--
|
||||
-- Trigger on input action ACTION_BACK or ACTION_BACKSPACE
|
||||
-- @usage
|
||||
-- -- Subscribe additional callbacks:
|
||||
-- back_handler.on_back:subscribe(callback)
|
||||
-- @tfield DruidEvent on_back @{DruidEvent}
|
||||
|
||||
--- Custom args to pass in the callback
|
||||
-- @usage
|
||||
-- -- Replace params on runtime:
|
||||
-- back_handler.params = { ... }
|
||||
-- @tfield any|nil params
|
||||
|
||||
---
|
||||
|
||||
local Event = require("druid.event")
|
||||
local event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local component = require("druid.component")
|
||||
|
||||
local BackHandler = component.create("back_handler")
|
||||
---@class druid.back_handler: druid.base_component
|
||||
---@field on_back druid.event Trigger on back handler action, fun(self, params)
|
||||
---@field params any|nil Custom args to pass in the callback
|
||||
local M = component.create("back_handler")
|
||||
|
||||
|
||||
--- The @{BackHandler} constructor
|
||||
-- @tparam BackHandler self @{BackHandler}
|
||||
-- @tparam function callback @The callback(self, custom_args) to call on back event
|
||||
-- @tparam any|nil custom_args Button events custom arguments
|
||||
-- @local
|
||||
function BackHandler.init(self, callback, custom_args)
|
||||
self.params = custom_args
|
||||
self.on_back = Event(callback)
|
||||
---@param callback function|nil
|
||||
---@param params any|nil
|
||||
function M:init(callback, params)
|
||||
self.params = params
|
||||
self.on_back = event.create(callback)
|
||||
end
|
||||
|
||||
|
||||
--- Component input handler
|
||||
-- @tparam BackHandler self @{BackHandler}
|
||||
-- @tparam string action_id on_input action id
|
||||
-- @tparam table action on_input action
|
||||
-- @local
|
||||
function BackHandler.on_input(self, action_id, action)
|
||||
---@param action_id string
|
||||
---@param action table
|
||||
function M:on_input(action_id, action)
|
||||
if not action.released then
|
||||
return false
|
||||
end
|
||||
@ -73,4 +32,4 @@ function BackHandler.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
return BackHandler
|
||||
return M
|
||||
|
@ -1,50 +1,22 @@
|
||||
-- Copyright (c) 2023 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Component to consume input in special zone defined by GUI node.
|
||||
-- <b># Overview #</b>
|
||||
--
|
||||
-- <b># Notes #</b>
|
||||
--
|
||||
-- Blocker consume input if `gui.pick_node` works on it.
|
||||
--
|
||||
-- • Blocker inheritance @{BaseComponent}, you can use all of its methods in addition to those described here.
|
||||
--
|
||||
-- • Blocker initial enabled state is `gui.is_enabled(node, true)`
|
||||
--
|
||||
-- • The Blocker node should be enabled to capture the input
|
||||
-- @usage
|
||||
-- local node = gui.get_node("blocker_node")
|
||||
-- local blocker = self.druid:new_blocker(node)
|
||||
-- @module Blocker
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.blocker
|
||||
|
||||
---Blocker node
|
||||
-- @tfield node node
|
||||
|
||||
---
|
||||
|
||||
local const = require("druid.const")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Blocker = component.create("blocker")
|
||||
---@class druid.blocker: druid.base_component
|
||||
---@field node node
|
||||
---@field private _is_enabled boolean
|
||||
local M = component.create("blocker")
|
||||
|
||||
|
||||
--- The @{Blocker} constructor
|
||||
-- @tparam Blocker self @{Blocker}
|
||||
-- @tparam node node Gui node
|
||||
function Blocker.init(self, node)
|
||||
---@param node node
|
||||
function M:init(node)
|
||||
self.node = self:get_node(node)
|
||||
self._is_enabled = gui.is_enabled(self.node, true)
|
||||
end
|
||||
|
||||
|
||||
--- Component input handler
|
||||
-- @tparam Blocker self @{Blocker}
|
||||
-- @tparam string action_id on_input action id
|
||||
-- @tparam table action on_input action
|
||||
-- @local
|
||||
function Blocker.on_input(self, action_id, action)
|
||||
---@param action_id string
|
||||
---@param action table
|
||||
function M:on_input(action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH and
|
||||
action_id ~= const.ACTION_MULTITOUCH and
|
||||
action_id ~= nil then
|
||||
@ -67,22 +39,21 @@ function Blocker.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
--- Set enabled blocker component state.
|
||||
--
|
||||
-- Don't change node enabled state itself.
|
||||
-- @tparam Blocker self @{Blocker}
|
||||
-- @tparam boolean|nil state Enabled state
|
||||
function Blocker.set_enabled(self, state)
|
||||
---Set blocker enabled state
|
||||
---@param state boolean
|
||||
---@return druid.blocker self
|
||||
function M:set_enabled(state)
|
||||
self._is_enabled = state
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Return blocker enabled state
|
||||
-- @tparam Blocker self @{Blocker}
|
||||
-- @treturn boolean @True, if blocker is enabled
|
||||
function Blocker.is_enabled(self)
|
||||
---Get blocker enabled state
|
||||
---@return boolean
|
||||
function M:is_enabled()
|
||||
return self._is_enabled
|
||||
end
|
||||
|
||||
|
||||
return Blocker
|
||||
return M
|
||||
|
@ -35,16 +35,16 @@
|
||||
-- @alias druid.button
|
||||
|
||||
|
||||
--- The @{DruidEvent}: Event on successful release action over button.
|
||||
--- The DruidEvent: Event on successful release action over button.
|
||||
-- @usage
|
||||
-- -- Custom args passed in Button constructor
|
||||
-- button.on_click:subscribe(function(self, custom_args, button_instance)
|
||||
-- print("On button click!")
|
||||
-- end)
|
||||
-- @tfield DruidEvent on_click @{DruidEvent}
|
||||
-- @tfield DruidEvent on_click DruidEvent
|
||||
|
||||
|
||||
--- The @{DruidEvent}: Event on repeated action over button.
|
||||
--- The DruidEvent: Event on repeated action over button.
|
||||
--
|
||||
-- This callback will be triggered if user hold the button. The repeat rate pick from `input.repeat_interval` in game.project
|
||||
-- @usage
|
||||
@ -52,10 +52,10 @@
|
||||
-- button.on_repeated_click:subscribe(function(self, custom_args, button_instance, click_count)
|
||||
-- print("On repeated Button click!")
|
||||
-- end)
|
||||
-- @tfield DruidEvent on_repeated_click @{DruidEvent}
|
||||
-- @tfield DruidEvent on_repeated_click DruidEvent
|
||||
|
||||
|
||||
--- The @{DruidEvent}: Event on long tap action over button.
|
||||
--- The DruidEvent: Event on long tap action over button.
|
||||
--
|
||||
-- This callback will be triggered if user pressed the button and hold the some amount of time.
|
||||
-- The amount of time picked from button style param: LONGTAP_TIME
|
||||
@ -64,10 +64,10 @@
|
||||
-- button.on_long_click:subscribe(function(self, custom_args, button_instance, hold_time)
|
||||
-- print("On long Button click!")
|
||||
-- end)
|
||||
-- @tfield DruidEvent on_long_click @{DruidEvent}
|
||||
-- @tfield DruidEvent on_long_click DruidEvent
|
||||
|
||||
|
||||
--- The @{DruidEvent}: Event on double tap action over button.
|
||||
--- The DruidEvent: Event on double tap action over button.
|
||||
--
|
||||
-- If secondary click was too fast after previous one, the double
|
||||
-- click will be called instead usual click (if on_double_click subscriber exists)
|
||||
@ -76,10 +76,10 @@
|
||||
-- button.on_double_click:subscribe(function(self, custom_args, button_instance, click_amount)
|
||||
-- print("On double Button click!")
|
||||
-- end)
|
||||
-- @tfield DruidEvent on_double_click @{DruidEvent}
|
||||
-- @tfield DruidEvent on_double_click DruidEvent
|
||||
|
||||
|
||||
--- The @{DruidEvent}: Event calls every frame before on_long_click event.
|
||||
--- The DruidEvent: Event calls every frame before on_long_click event.
|
||||
--
|
||||
-- If long_click subscriber exists, the on_hold_callback will be called before long_click trigger.
|
||||
--
|
||||
@ -89,10 +89,10 @@
|
||||
-- button.on_double_click:subscribe(function(self, custom_args, button_instance, time)
|
||||
-- print("On hold Button callback!")
|
||||
-- end)
|
||||
-- @tfield DruidEvent on_hold_callback @{DruidEvent}
|
||||
-- @tfield DruidEvent on_hold_callback DruidEvent
|
||||
|
||||
|
||||
--- The @{DruidEvent}: Event calls if click event was outside of button.
|
||||
--- The DruidEvent: Event calls if click event was outside of button.
|
||||
--
|
||||
-- This event will be triggered for each button what was not clicked on user click action
|
||||
--
|
||||
@ -102,16 +102,16 @@
|
||||
-- button.on_click_outside:subscribe(function(self, custom_args, button_instance)
|
||||
-- print("On click Button outside!")
|
||||
-- end)
|
||||
-- @tfield DruidEvent on_click_outside @{DruidEvent}
|
||||
-- @tfield DruidEvent on_click_outside DruidEvent
|
||||
|
||||
|
||||
--- The @{DruidEvent}: Event triggered if button was pressed by user.
|
||||
--- The DruidEvent: Event triggered if button was pressed by user.
|
||||
-- @usage
|
||||
-- -- Custom args passed in Button constructor
|
||||
-- button.on_pressed:subscribe(function(self, custom_args, button_instance)
|
||||
-- print("On Button pressed!")
|
||||
-- end)
|
||||
-- @tfield DruidEvent on_pressed @{DruidEvent}
|
||||
-- @tfield DruidEvent on_pressed DruidEvent
|
||||
|
||||
--- Button trigger node
|
||||
-- @tfield node node
|
||||
@ -128,8 +128,8 @@
|
||||
---Custom args for any Button event. Setup in Button constructor
|
||||
-- @tfield any params
|
||||
|
||||
--- The @{Hover}: Button Hover component
|
||||
-- @tfield Hover hover @{Hover}
|
||||
--- The Hover: Button Hover component
|
||||
-- @tfield Hover hover Hover
|
||||
|
||||
--- Additional button click area, defined by another GUI node
|
||||
-- @tfield node|nil click_zone
|
||||
@ -141,7 +141,26 @@ local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Button = component.create("button")
|
||||
---@class druid.button: druid.base_component
|
||||
---@field on_click druid.event
|
||||
---@field on_pressed druid.event
|
||||
---@field on_repeated_click druid.event
|
||||
---@field on_long_click druid.event
|
||||
---@field on_double_click druid.event
|
||||
---@field on_hold_callback druid.event
|
||||
---@field on_click_outside druid.event
|
||||
---@field node node
|
||||
---@field node_id hash
|
||||
---@field anim_node node
|
||||
---@field params any
|
||||
---@field hover druid.hover
|
||||
---@field click_zone node
|
||||
---@field start_scale vector3
|
||||
---@field start_pos vector3
|
||||
---@field disabled boolean
|
||||
---@field key_trigger hash
|
||||
---@field style table
|
||||
local M = component.create("button")
|
||||
|
||||
|
||||
local function is_input_match(self, action_id)
|
||||
@ -271,7 +290,7 @@ end
|
||||
-- @tfield function on_hover function(self, node, hover_state)
|
||||
-- @tfield function on_mouse_hover function(self, node, hover_state)
|
||||
-- @tfield function on_set_enabled function(self, node, enabled_state)
|
||||
function Button.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.LONGTAP_TIME = style.LONGTAP_TIME or 0.4
|
||||
self.style.AUTOHOLD_TRIGGER = style.AUTOHOLD_TRIGGER or 0.8
|
||||
@ -285,22 +304,21 @@ function Button.on_style_change(self, style)
|
||||
end
|
||||
|
||||
|
||||
--- The @{Button} constructor
|
||||
-- @tparam Button self @{Button}
|
||||
-- @tparam string|node node The node_id or gui.get_node(node_id)
|
||||
-- @tparam function callback On click button callback
|
||||
-- @tparam any|nil custom_args Button events custom arguments
|
||||
-- @tparam string|node|nil anim_node Node to animate instead of trigger node.
|
||||
function Button.init(self, node, callback, custom_args, anim_node)
|
||||
---Button constructor
|
||||
---@param node_or_node_id node|string Node name or GUI Node itself.
|
||||
---@param callback fun()|nil Callback on button click
|
||||
---@param custom_args any|nil Custom args for any Button event
|
||||
---@param anim_node node|string|nil Node to animate instead of trigger node.
|
||||
function M:init(node_or_node_id, callback, custom_args, anim_node)
|
||||
self.druid = self:get_druid()
|
||||
self.node = self:get_node(node)
|
||||
self.node = self:get_node(node_or_node_id)
|
||||
self.node_id = gui.get_id(self.node)
|
||||
|
||||
self.anim_node = anim_node and self:get_node(anim_node) or self.node
|
||||
self.start_scale = gui.get_scale(self.anim_node)
|
||||
self.start_pos = gui.get_position(self.anim_node)
|
||||
self.params = custom_args
|
||||
self.hover = self.druid:new_hover(node, on_button_hover)
|
||||
self.hover = self.druid:new_hover(node_or_node_id, on_button_hover)
|
||||
self.hover.on_mouse_hover:subscribe(on_button_mouse_hover)
|
||||
self.click_zone = nil
|
||||
self.is_repeated_started = false
|
||||
@ -325,7 +343,7 @@ function Button.init(self, node, callback, custom_args, anim_node)
|
||||
end
|
||||
|
||||
|
||||
function Button.on_late_init(self)
|
||||
function M:on_late_init()
|
||||
if not self.click_zone and const.IS_STENCIL_CHECK then
|
||||
local stencil_node = helper.get_closest_stencil_node(self.node)
|
||||
if stencil_node then
|
||||
@ -335,7 +353,7 @@ function Button.on_late_init(self)
|
||||
end
|
||||
|
||||
|
||||
function Button.on_input(self, action_id, action)
|
||||
function M:on_input(action_id, action)
|
||||
if not is_input_match(self, action_id) then
|
||||
return false
|
||||
end
|
||||
@ -416,14 +434,14 @@ function Button.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
function Button.on_input_interrupt(self)
|
||||
function M:on_input_interrupt()
|
||||
self.can_action = false
|
||||
self.hover:set_hover(false)
|
||||
self.hover:set_mouse_hover(false)
|
||||
end
|
||||
|
||||
|
||||
function Button.on_message_input(self, node_id, message)
|
||||
function M:on_message_input(node_id, message)
|
||||
if node_id ~= self.node_id or self.disabled or not gui.is_enabled(self.node) then
|
||||
return false
|
||||
end
|
||||
@ -451,13 +469,13 @@ end
|
||||
--- Set button enabled state.
|
||||
-- The style.on_set_enabled will be triggered.
|
||||
-- Disabled button is not clickable.
|
||||
-- @tparam Button self @{Button}
|
||||
-- @tparam Button self Button
|
||||
-- @tparam boolean|nil state Enabled state
|
||||
-- @treturn Button Current button instance
|
||||
-- @usage
|
||||
-- button:set_enabled(false)
|
||||
-- button:set_enabled(true)
|
||||
function Button.set_enabled(self, state)
|
||||
function M:set_enabled(state)
|
||||
self.disabled = not state
|
||||
self.hover:set_enabled(state)
|
||||
self.style.on_set_enabled(self, self.node, state)
|
||||
@ -469,11 +487,11 @@ end
|
||||
--- Get button enabled state.
|
||||
--
|
||||
-- By default all Buttons is enabled on creating.
|
||||
-- @tparam Button self @{Button}
|
||||
-- @tparam Button self Button
|
||||
-- @treturn boolean @True, if button is enabled now, False overwise
|
||||
-- @usage
|
||||
-- local is_enabled = button:is_enabled()
|
||||
function Button.is_enabled(self)
|
||||
function M:is_enabled()
|
||||
return not self.disabled
|
||||
end
|
||||
|
||||
@ -482,12 +500,12 @@ end
|
||||
-- Useful to restrict click outside out stencil node or scrollable content.
|
||||
--
|
||||
-- This functions calls automatically if you don't disable it in game.project: druid.no_stencil_check
|
||||
-- @tparam Button self @{Button}
|
||||
-- @tparam Button self Button
|
||||
-- @tparam node|string|nil zone Gui node
|
||||
-- @treturn Button Current button instance
|
||||
-- @usage
|
||||
-- button:set_click_zone("stencil_node")
|
||||
function Button.set_click_zone(self, zone)
|
||||
function M:set_click_zone(zone)
|
||||
self.click_zone = self:get_node(zone)
|
||||
self.hover:set_click_zone(zone)
|
||||
|
||||
@ -496,12 +514,12 @@ end
|
||||
|
||||
|
||||
--- Set key name to trigger this button by keyboard.
|
||||
-- @tparam Button self @{Button}
|
||||
-- @tparam Button self Button
|
||||
-- @tparam hash|string key The action_id of the input key
|
||||
-- @treturn Button Current button instance
|
||||
-- @usage
|
||||
-- button:set_key_trigger("key_space")
|
||||
function Button.set_key_trigger(self, key)
|
||||
function M:set_key_trigger(key)
|
||||
self.key_trigger = hash(key)
|
||||
|
||||
return self
|
||||
@ -513,7 +531,7 @@ end
|
||||
-- @treturn hash The action_id of the input key
|
||||
-- @usage
|
||||
-- local key_hash = button:get_key_trigger()
|
||||
function Button.get_key_trigger(self)
|
||||
function M:get_key_trigger()
|
||||
return self.key_trigger
|
||||
end
|
||||
|
||||
@ -523,7 +541,7 @@ end
|
||||
-- @tparam function|nil check_function Should return true or false. If true - button can be pressed.
|
||||
-- @tparam function|nil failure_callback Function will be called on button click, if check function return false
|
||||
-- @treturn Button Current button instance
|
||||
function Button.set_check_function(self, check_function, failure_callback)
|
||||
function M:set_check_function(check_function, failure_callback)
|
||||
self._check_function = check_function
|
||||
self._failure_callback = failure_callback
|
||||
end
|
||||
@ -540,10 +558,10 @@ end
|
||||
-- @treturn Button Current button instance
|
||||
-- @usage
|
||||
-- button:set_web_user_interaction(true)
|
||||
function Button.set_web_user_interaction(self, is_web_mode)
|
||||
function M:set_web_user_interaction(is_web_mode)
|
||||
self._is_html5_mode = not not (is_web_mode and html5)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
return Button
|
||||
return M
|
||||
|
@ -14,19 +14,19 @@
|
||||
-- @tfield node node
|
||||
|
||||
--- Event on touch start callback(self)
|
||||
-- @tfield DruidEvent on_touch_start @{DruidEvent}
|
||||
-- @tfield DruidEvent on_touch_start DruidEvent
|
||||
|
||||
--- Event on touch end callback(self)
|
||||
-- @tfield DruidEvent on_touch_end @{DruidEvent}
|
||||
-- @tfield DruidEvent on_touch_end DruidEvent
|
||||
|
||||
--- Event on drag start callback(self, touch)
|
||||
-- @tfield DruidEvent on_drag_start @{DruidEvent}
|
||||
-- @tfield DruidEvent on_drag_start DruidEvent
|
||||
|
||||
--- on drag progress callback(self, dx, dy, total_x, total_y, touch)
|
||||
-- @tfield DruidEvent on_drag Event @{DruidEvent}
|
||||
-- @tfield DruidEvent on_drag Event DruidEvent
|
||||
|
||||
--- Event on drag end callback(self, total_x, total_y, touch)
|
||||
-- @tfield DruidEvent on_drag_end @{DruidEvent}
|
||||
-- @tfield DruidEvent on_drag_end DruidEvent
|
||||
|
||||
--- Is component now touching
|
||||
-- @tfield boolean is_touch
|
||||
@ -62,7 +62,31 @@ local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Drag = component.create("drag", const.PRIORITY_INPUT_HIGH)
|
||||
---@class druid.drag: druid.base_component
|
||||
---@field node node
|
||||
---@field on_touch_start druid.event
|
||||
---@field on_touch_end druid.event
|
||||
---@field on_drag_start druid.event
|
||||
---@field on_drag druid.event
|
||||
---@field on_drag_end druid.event
|
||||
---@field style table
|
||||
---@field click_zone node
|
||||
---@field is_touch boolean
|
||||
---@field is_drag boolean
|
||||
---@field can_x boolean
|
||||
---@field can_y boolean
|
||||
---@field dx number
|
||||
---@field dy number
|
||||
---@field touch_id number
|
||||
---@field x number
|
||||
---@field y number
|
||||
---@field screen_x number
|
||||
---@field screen_y number
|
||||
---@field touch_start_pos vector3
|
||||
---@field private _is_enabled boolean
|
||||
---@field private _x_koef number
|
||||
---@field private _y_koef number
|
||||
local M = component.create("drag", const.PRIORITY_INPUT_HIGH)
|
||||
|
||||
|
||||
local function start_touch(self, touch)
|
||||
@ -177,19 +201,18 @@ end
|
||||
-- @table style
|
||||
-- @tfield number|nil DRAG_DEADZONE Distance in pixels to start dragging. Default: 10
|
||||
-- @tfield boolean|nil NO_USE_SCREEN_KOEF If screen aspect ratio affects on drag values. Default: false
|
||||
function Drag.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.DRAG_DEADZONE = style.DRAG_DEADZONE or 10
|
||||
self.style.NO_USE_SCREEN_KOEF = style.NO_USE_SCREEN_KOEF or false
|
||||
end
|
||||
|
||||
|
||||
--- The @{Drag} constructor
|
||||
-- @tparam Drag self @{Drag}
|
||||
-- @tparam node node GUI node to detect dragging
|
||||
-- @tparam function on_drag_callback Callback for on_drag_event(self, dx, dy)
|
||||
function Drag.init(self, node, on_drag_callback)
|
||||
self.node = self:get_node(node)
|
||||
---Drag constructor
|
||||
---@param node_or_node_id node|string
|
||||
---@param on_drag_callback function
|
||||
function M:init(node_or_node_id, on_drag_callback)
|
||||
self.node = self:get_node(node_or_node_id)
|
||||
|
||||
self.dx = 0
|
||||
self.dy = 0
|
||||
@ -219,7 +242,7 @@ function Drag.init(self, node, on_drag_callback)
|
||||
end
|
||||
|
||||
|
||||
function Drag.on_late_init(self)
|
||||
function M:on_late_init()
|
||||
if not self.click_zone and const.IS_STENCIL_CHECK then
|
||||
local stencil_node = helper.get_closest_stencil_node(self.node)
|
||||
if stencil_node then
|
||||
@ -229,7 +252,7 @@ function Drag.on_late_init(self)
|
||||
end
|
||||
|
||||
|
||||
function Drag.on_window_resized(self)
|
||||
function M:on_window_resized()
|
||||
local x_koef, y_koef = helper.get_screen_aspect_koef()
|
||||
self._x_koef = x_koef
|
||||
self._y_koef = y_koef
|
||||
@ -237,14 +260,17 @@ function Drag.on_window_resized(self)
|
||||
end
|
||||
|
||||
|
||||
function Drag.on_input_interrupt(self)
|
||||
function M:on_input_interrupt()
|
||||
if self.is_drag or self.is_touch then
|
||||
end_touch(self)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Drag.on_input(self, action_id, action)
|
||||
---@local
|
||||
---@param action_id string
|
||||
---@param action table
|
||||
function M:on_input(action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH and action_id ~= const.ACTION_MULTITOUCH then
|
||||
return false
|
||||
end
|
||||
@ -321,29 +347,31 @@ function Drag.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
--- Strict drag click area. Useful for
|
||||
-- restrict events outside stencil node
|
||||
-- @tparam Drag self @{Drag}
|
||||
-- @tparam node|string|nil node Gui node
|
||||
function Drag.set_click_zone(self, node)
|
||||
---Set Drag click zone
|
||||
---@param node node|string|nil
|
||||
---@return druid.drag self
|
||||
function M:set_click_zone(node)
|
||||
self.click_zone = self:get_node(node)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set Drag input enabled or disabled
|
||||
-- @tparam Drag self @{Drag}
|
||||
-- @tparam boolean|nil is_enabled
|
||||
function Drag.set_enabled(self, is_enabled)
|
||||
---Set Drag component enabled state.
|
||||
---@param is_enabled boolean
|
||||
---@return druid.drag self
|
||||
function M:set_enabled(is_enabled)
|
||||
self._is_enabled = is_enabled
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Check if Drag component is enabled
|
||||
-- @tparam Drag self @{Drag}
|
||||
-- @treturn boolean
|
||||
function Drag.is_enabled(self)
|
||||
---Check if Drag component is enabled
|
||||
---@return boolean
|
||||
function M:is_enabled()
|
||||
return self._is_enabled
|
||||
end
|
||||
|
||||
|
||||
return Drag
|
||||
return M
|
||||
|
@ -9,10 +9,10 @@
|
||||
-- @tfield node node
|
||||
|
||||
--- On hover callback(self, state, hover_instance)
|
||||
-- @tfield DruidEvent on_hover @{DruidEvent}
|
||||
-- @tfield DruidEvent on_hover DruidEvent
|
||||
|
||||
--- On mouse hover callback(self, state, hover_instance)
|
||||
-- @tfield DruidEvent on_mouse_hover @{DruidEvent}
|
||||
-- @tfield DruidEvent on_mouse_hover DruidEvent
|
||||
|
||||
---
|
||||
|
||||
@ -21,15 +21,25 @@ local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Hover = component.create("hover")
|
||||
---@class druid.hover: druid.base_component
|
||||
---@field node node
|
||||
---@field on_hover druid.event
|
||||
---@field on_mouse_hover druid.event
|
||||
---@field style table
|
||||
---@field click_zone node
|
||||
---@field private _is_hovered boolean
|
||||
---@field private _is_mouse_hovered boolean
|
||||
---@field private _is_enabled boolean
|
||||
---@field private _is_mobile boolean
|
||||
local M = component.create("hover")
|
||||
|
||||
|
||||
--- The @{Hover} constructor
|
||||
-- @tparam Hover self @{Hover}
|
||||
--- The Hover constructor
|
||||
-- @tparam Hover self Hover
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function on_hover_callback Hover callback
|
||||
-- @tparam function on_mouse_hover On mouse hover callback
|
||||
function Hover.init(self, node, on_hover_callback, on_mouse_hover)
|
||||
function M:init(node, on_hover_callback, on_mouse_hover)
|
||||
self.node = self:get_node(node)
|
||||
|
||||
self._is_hovered = false
|
||||
@ -42,7 +52,7 @@ function Hover.init(self, node, on_hover_callback, on_mouse_hover)
|
||||
end
|
||||
|
||||
|
||||
function Hover.on_late_init(self)
|
||||
function M:on_late_init()
|
||||
if not self.click_zone and const.IS_STENCIL_CHECK then
|
||||
local stencil_node = helper.get_closest_stencil_node(self.node)
|
||||
if stencil_node then
|
||||
@ -58,14 +68,14 @@ end
|
||||
-- @table style
|
||||
-- @tfield[opt] string ON_HOVER_CURSOR Mouse hover style on node hover
|
||||
-- @tfield[opt] string ON_MOUSE_HOVER_CURSOR Mouse hover style on node mouse hover
|
||||
function Hover.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.ON_HOVER_CURSOR = style.ON_HOVER_CURSOR or nil
|
||||
self.style.ON_MOUSE_HOVER_CURSOR = style.ON_MOUSE_HOVER_CURSOR or nil
|
||||
end
|
||||
|
||||
|
||||
function Hover.on_input(self, action_id, action)
|
||||
function M:on_input(action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH and action_id ~= nil then
|
||||
return false
|
||||
end
|
||||
@ -99,15 +109,15 @@ function Hover.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
function Hover.on_input_interrupt(self)
|
||||
function M:on_input_interrupt()
|
||||
self:set_hover(false)
|
||||
end
|
||||
|
||||
|
||||
--- Set hover state
|
||||
-- @tparam Hover self @{Hover}
|
||||
-- @tparam Hover self Hover
|
||||
-- @tparam boolean|nil state The hover state
|
||||
function Hover.set_hover(self, state)
|
||||
function M:set_hover(state)
|
||||
if self._is_hovered == state then
|
||||
return
|
||||
end
|
||||
@ -122,17 +132,17 @@ end
|
||||
|
||||
|
||||
--- Return current hover state. True if touch action was on the node at current time
|
||||
-- @tparam Hover self @{Hover}
|
||||
-- @tparam Hover self Hover
|
||||
-- @treturn boolean The current hovered state
|
||||
function Hover.is_hovered(self)
|
||||
function M:is_hovered()
|
||||
return self._is_hovered
|
||||
end
|
||||
|
||||
|
||||
--- Set mouse hover state
|
||||
-- @tparam Hover self @{Hover}
|
||||
-- @tparam Hover self Hover
|
||||
-- @tparam boolean|nil state The mouse hover state
|
||||
function Hover.set_mouse_hover(self, state)
|
||||
function M:set_mouse_hover(state)
|
||||
if self._is_mouse_hovered == state then
|
||||
return
|
||||
end
|
||||
@ -147,18 +157,18 @@ end
|
||||
|
||||
|
||||
--- Return current hover state. True if nil action_id (usually desktop mouse) was on the node at current time
|
||||
-- @tparam Hover self @{Hover}
|
||||
-- @tparam Hover self Hover
|
||||
-- @treturn boolean The current hovered state
|
||||
function Hover.is_mouse_hovered(self)
|
||||
function M:is_mouse_hovered()
|
||||
return self._is_mouse_hovered
|
||||
end
|
||||
|
||||
|
||||
--- Strict hover click area. Useful for
|
||||
-- no click events outside stencil node
|
||||
-- @tparam Hover self @{Hover}
|
||||
-- @tparam Hover self Hover
|
||||
-- @tparam node|string|nil zone Gui node
|
||||
function Hover.set_click_zone(self, zone)
|
||||
function M:set_click_zone(zone)
|
||||
self.click_zone = self:get_node(zone)
|
||||
end
|
||||
|
||||
@ -166,9 +176,9 @@ end
|
||||
--- Set enable state of hover component.
|
||||
-- If hover is not enabled, it will not generate
|
||||
-- any hover events
|
||||
-- @tparam Hover self @{Hover}
|
||||
-- @tparam Hover self Hover
|
||||
-- @tparam boolean|nil state The hover enabled state
|
||||
function Hover.set_enabled(self, state)
|
||||
function M:set_enabled(state)
|
||||
self._is_enabled = state
|
||||
|
||||
if not state then
|
||||
@ -183,16 +193,17 @@ end
|
||||
|
||||
|
||||
--- Return current hover enabled state
|
||||
-- @tparam Hover self @{Hover}
|
||||
-- @tparam Hover self Hover
|
||||
-- @treturn boolean The hover enabled state
|
||||
function Hover.is_enabled(self)
|
||||
function M:is_enabled()
|
||||
return self._is_enabled
|
||||
end
|
||||
|
||||
|
||||
-- Internal cursor stack
|
||||
local cursor_stack = {}
|
||||
function Hover:_set_cursor(priority, cursor)
|
||||
---@local
|
||||
function M:_set_cursor(priority, cursor)
|
||||
if not defos then
|
||||
return
|
||||
end
|
||||
@ -217,4 +228,4 @@ function Hover:_set_cursor(priority, cursor)
|
||||
end
|
||||
|
||||
|
||||
return Hover
|
||||
return M
|
||||
|
@ -39,13 +39,13 @@
|
||||
|
||||
|
||||
--- On scroll move callback(self, position)
|
||||
-- @tfield DruidEvent on_scroll @{DruidEvent}
|
||||
-- @tfield DruidEvent on_scroll DruidEvent
|
||||
|
||||
--- On scroll_to function callback(self, target, is_instant)
|
||||
-- @tfield DruidEvent on_scroll_to @{DruidEvent}
|
||||
-- @tfield DruidEvent on_scroll_to DruidEvent
|
||||
|
||||
--- On scroll_to_index function callback(self, index, point)
|
||||
-- @tfield DruidEvent on_point_scroll @{DruidEvent}
|
||||
-- @tfield DruidEvent on_point_scroll DruidEvent
|
||||
|
||||
--- Scroll view node
|
||||
-- @tfield node view_node
|
||||
@ -75,7 +75,7 @@
|
||||
-- @tfield vector3 available_size
|
||||
|
||||
--- Drag Druid component
|
||||
-- @tfield Drag drag @{Drag}
|
||||
-- @tfield Drag drag Drag
|
||||
|
||||
--- Current index of points of interests
|
||||
-- @tfield number|nil selected
|
||||
@ -90,7 +90,16 @@ local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Scroll = component.create("scroll")
|
||||
---@class druid.scroll: druid.base_component
|
||||
---@field on_scroll druid.event
|
||||
---@field on_scroll_to druid.event
|
||||
---@field on_point_scroll druid.event
|
||||
---@field view_node node
|
||||
---@field view_border vector4
|
||||
---@field content_node node
|
||||
---@field view_size vector3
|
||||
---@field position vector3
|
||||
local M = component.create("scroll")
|
||||
|
||||
|
||||
local function inverse_lerp(min, max, current)
|
||||
@ -138,7 +147,7 @@ end
|
||||
-- @tfield boolean|nil WHEEL_SCROLL_SPEED The scroll speed via mouse wheel scroll or touchpad. Set to 0 to disable wheel scrolling. Default: 0
|
||||
-- @tfield boolean|nil WHEEL_SCROLL_INVERTED If true, invert direction for touchpad and mouse wheel scroll. Default: false
|
||||
-- @tfield boolean|nil WHEEL_SCROLL_BY_INERTION If true, wheel will add inertion to scroll. Direct set position otherwise.. Default: false
|
||||
function Scroll.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.EXTRA_STRETCH_SIZE = style.EXTRA_STRETCH_SIZE or 0
|
||||
self.style.ANIM_SPEED = style.ANIM_SPEED or 0.2
|
||||
@ -161,11 +170,11 @@ function Scroll.on_style_change(self, style)
|
||||
end
|
||||
|
||||
|
||||
--- The @{Scroll} constructor
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
--- The Scroll constructor
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam string|node view_node GUI view scroll node
|
||||
-- @tparam string|node content_node GUI content scroll node
|
||||
function Scroll.init(self, view_node, content_node)
|
||||
function M:init(view_node, content_node)
|
||||
self.druid = self:get_druid()
|
||||
|
||||
self.view_node = self:get_node(view_node)
|
||||
@ -203,7 +212,7 @@ function Scroll.init(self, view_node, content_node)
|
||||
end
|
||||
|
||||
|
||||
function Scroll.on_late_init(self)
|
||||
function M:on_late_init()
|
||||
if not self.click_zone and const.IS_STENCIL_CHECK then
|
||||
local stencil_node = helper.get_closest_stencil_node(self.node)
|
||||
if stencil_node then
|
||||
@ -213,12 +222,12 @@ function Scroll.on_late_init(self)
|
||||
end
|
||||
|
||||
|
||||
function Scroll.on_layout_change(self)
|
||||
function M:on_layout_change()
|
||||
gui.set_position(self.content_node, self.position)
|
||||
end
|
||||
|
||||
|
||||
function Scroll.update(self, dt)
|
||||
function M:update(dt)
|
||||
if self.is_animate then
|
||||
self.position.x = gui.get(self.content_node, "position.x")
|
||||
self.position.y = gui.get(self.content_node, "position.y")
|
||||
@ -233,23 +242,23 @@ function Scroll.update(self, dt)
|
||||
end
|
||||
|
||||
|
||||
function Scroll.on_input(self, action_id, action)
|
||||
function M:on_input(action_id, action)
|
||||
return self:_process_scroll_wheel(action_id, action)
|
||||
end
|
||||
|
||||
|
||||
function Scroll.on_remove(self)
|
||||
function M:on_remove()
|
||||
self:bind_grid(nil)
|
||||
end
|
||||
|
||||
|
||||
--- Start scroll to target point.
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam vector3 point Target point
|
||||
-- @tparam boolean|nil is_instant Instant scroll flag
|
||||
-- @usage scroll:scroll_to(vmath.vector3(0, 50, 0))
|
||||
-- @usage scroll:scroll_to(vmath.vector3(0), true)
|
||||
function Scroll.scroll_to(self, point, is_instant)
|
||||
function M:scroll_to(point, is_instant)
|
||||
local b = self.available_pos
|
||||
local target = vmath.vector3(
|
||||
self._is_horizontal_scroll and -point.x or self.target_position.x,
|
||||
@ -278,10 +287,10 @@ end
|
||||
|
||||
|
||||
--- Scroll to item in scroll by point index.
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam number index Point index
|
||||
-- @tparam boolean|nil skip_cb If true, skip the point callback
|
||||
function Scroll.scroll_to_index(self, index, skip_cb)
|
||||
function M:scroll_to_index(index, skip_cb)
|
||||
if not self.points then
|
||||
return
|
||||
end
|
||||
@ -301,11 +310,11 @@ end
|
||||
|
||||
|
||||
--- Start scroll to target scroll percent
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam vector3 percent target percent
|
||||
-- @tparam boolean|nil is_instant instant scroll flag
|
||||
-- @usage scroll:scroll_to_percent(vmath.vector3(0.5, 0, 0))
|
||||
function Scroll.scroll_to_percent(self, percent, is_instant)
|
||||
function M:scroll_to_percent(percent, is_instant)
|
||||
local border = self.available_pos
|
||||
|
||||
local pos = vmath.vector3(
|
||||
@ -327,9 +336,9 @@ end
|
||||
|
||||
--- Return current scroll progress status.
|
||||
-- Values will be in [0..1] interval
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @treturn vector3 New vector with scroll progress values
|
||||
function Scroll.get_percent(self)
|
||||
function M:get_percent()
|
||||
local x_perc = 1 - inverse_lerp(self.available_pos.x, self.available_pos.z, self.position.x)
|
||||
local y_perc = inverse_lerp(self.available_pos.w, self.available_pos.y, self.position.y)
|
||||
|
||||
@ -339,11 +348,11 @@ end
|
||||
|
||||
--- Set scroll content size.
|
||||
-- It will change content gui node size
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam vector3 size The new size for content node
|
||||
-- @tparam vector3|nil offset Offset value to set, where content is starts
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_size(self, size, offset)
|
||||
function M:set_size(size, offset)
|
||||
if offset then
|
||||
self._offset = offset
|
||||
end
|
||||
@ -355,10 +364,10 @@ end
|
||||
|
||||
|
||||
--- Set new scroll view size in case the node size was changed.
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam vector3 size The new size for view node
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_view_size(self, size)
|
||||
function M:set_view_size(size)
|
||||
gui.set_size(self.view_node, size)
|
||||
self.view_size = size
|
||||
self.view_border = helper.get_border(self.view_node)
|
||||
@ -369,8 +378,8 @@ end
|
||||
|
||||
|
||||
--- Refresh scroll view size
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
function Scroll.update_view_size(self)
|
||||
-- @tparam Scroll self Scroll
|
||||
function M:update_view_size()
|
||||
self.view_size = helper.get_scaled_size(self.view_node)
|
||||
self.view_border = helper.get_border(self.view_node)
|
||||
self:_update_size()
|
||||
@ -382,10 +391,10 @@ end
|
||||
--- Enable or disable scroll inert.
|
||||
-- If disabled, scroll through points (if exist)
|
||||
-- If no points, just simple drag without inertion
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam boolean|nil state Inert scroll state
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_inert(self, state)
|
||||
function M:set_inert(state)
|
||||
self._is_inert = state
|
||||
|
||||
return self
|
||||
@ -393,19 +402,19 @@ end
|
||||
|
||||
|
||||
--- Return if scroll have inertion.
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @treturn boolean @If scroll have inertion
|
||||
function Scroll.is_inert(self)
|
||||
function M:is_inert()
|
||||
return self._is_inert
|
||||
end
|
||||
|
||||
|
||||
--- Set extra size for scroll stretching.
|
||||
-- Set 0 to disable stretching effect
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam number|nil stretch_size Size in pixels of additional scroll area
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_extra_stretch_size(self, stretch_size)
|
||||
function M:set_extra_stretch_size(stretch_size)
|
||||
self.style.EXTRA_STRETCH_SIZE = stretch_size or 0
|
||||
self:_update_size()
|
||||
|
||||
@ -414,19 +423,19 @@ end
|
||||
|
||||
|
||||
--- Return vector of scroll size with width and height.
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @treturn vector3 Available scroll size
|
||||
function Scroll.get_scroll_size(self)
|
||||
function M:get_scroll_size()
|
||||
return self.available_size
|
||||
end
|
||||
|
||||
|
||||
--- Set points of interest.
|
||||
-- Scroll will always centered on closer points
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam table points Array of vector3 points
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_points(self, points)
|
||||
function M:set_points(points)
|
||||
self.points = points
|
||||
|
||||
table.sort(self.points, function(a, b)
|
||||
@ -440,10 +449,10 @@ end
|
||||
|
||||
|
||||
--- Lock or unlock horizontal scroll
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam boolean|nil state True, if horizontal scroll is enabled
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_horizontal_scroll(self, state)
|
||||
function M:set_horizontal_scroll(state)
|
||||
self._is_horizontal_scroll = state
|
||||
self.drag.can_x = self.available_size.x > 0 and state
|
||||
return self
|
||||
@ -451,10 +460,10 @@ end
|
||||
|
||||
|
||||
--- Lock or unlock vertical scroll
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam boolean|nil state True, if vertical scroll is enabled
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_vertical_scroll(self, state)
|
||||
function M:set_vertical_scroll(state)
|
||||
self._is_vertical_scroll = state
|
||||
self.drag.can_y = self.available_size.y > 0 and state
|
||||
return self
|
||||
@ -463,10 +472,10 @@ end
|
||||
|
||||
--- Check node if it visible now on scroll.
|
||||
-- Extra border is not affected. Return true for elements in extra scroll zone
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam node node The node to check
|
||||
-- @treturn boolean True if node in visible scroll area
|
||||
function Scroll.is_node_in_view(self, node)
|
||||
function M:is_node_in_view(node)
|
||||
local node_offset_for_view = gui.get_position(node)
|
||||
local parent = gui.get_parent(node)
|
||||
local is_parent_of_view = false
|
||||
@ -504,10 +513,10 @@ end
|
||||
|
||||
--- Bind the grid component (Static or Dynamic) to recalculate
|
||||
-- scroll size on grid changes
|
||||
-- @tparam Scroll self @{Scroll}
|
||||
-- @tparam Scroll self Scroll
|
||||
-- @tparam StaticGrid grid Druid grid component
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.bind_grid(self, grid)
|
||||
function M:bind_grid(grid)
|
||||
if self._grid_on_change then
|
||||
self._grid_on_change:unsubscribe(self._grid_on_change_callback)
|
||||
|
||||
@ -535,12 +544,12 @@ end
|
||||
-- restrict events outside stencil node
|
||||
-- @tparam Drag self
|
||||
-- @tparam node|string node Gui node
|
||||
function Scroll.set_click_zone(self, node)
|
||||
function M:set_click_zone(node)
|
||||
self.drag:set_click_zone(node)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._on_scroll_drag(self, dx, dy)
|
||||
function M:_on_scroll_drag(dx, dy)
|
||||
local t = self.target_position
|
||||
local b = self.available_pos
|
||||
local eb = self.available_pos_extra
|
||||
@ -581,7 +590,7 @@ function Scroll._on_scroll_drag(self, dx, dy)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._check_soft_zone(self)
|
||||
function M:_check_soft_zone()
|
||||
local target = self.target_position
|
||||
local border = self.available_pos
|
||||
local speed = self.style.BACK_SPEED
|
||||
@ -610,7 +619,7 @@ end
|
||||
|
||||
|
||||
-- Cancel animation on other animation or input touch
|
||||
function Scroll._cancel_animate(self)
|
||||
function M:_cancel_animate()
|
||||
self.inertion.x = 0
|
||||
self.inertion.y = 0
|
||||
|
||||
@ -624,7 +633,7 @@ function Scroll._cancel_animate(self)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._set_scroll_position(self, position_x, position_y)
|
||||
function M:_set_scroll_position(position_x, position_y)
|
||||
local available_extra = self.available_pos_extra
|
||||
position_x = helper.clamp(position_x, available_extra.x, available_extra.z)
|
||||
position_y = helper.clamp(position_y, available_extra.w, available_extra.y)
|
||||
@ -643,7 +652,7 @@ end
|
||||
-- if no inert, scroll to next point by scroll direction
|
||||
-- if inert, find next point by scroll director
|
||||
-- @local
|
||||
function Scroll._check_points(self)
|
||||
function M:_check_points()
|
||||
if not self.points then
|
||||
return
|
||||
end
|
||||
@ -699,7 +708,7 @@ function Scroll._check_points(self)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._check_threshold(self)
|
||||
function M:_check_threshold()
|
||||
local is_stopped = false
|
||||
|
||||
if self.drag.can_x and math.abs(self.inertion.x) < self.style.INERT_THRESHOLD then
|
||||
@ -717,7 +726,7 @@ function Scroll._check_threshold(self)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._update_free_scroll(self, dt)
|
||||
function M:_update_free_scroll(dt)
|
||||
if self.is_animate then
|
||||
return
|
||||
end
|
||||
@ -742,7 +751,7 @@ function Scroll._update_free_scroll(self, dt)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._update_hand_scroll(self, dt)
|
||||
function M:_update_hand_scroll(dt)
|
||||
if self.is_animate then
|
||||
self:_cancel_animate()
|
||||
end
|
||||
@ -757,7 +766,7 @@ function Scroll._update_hand_scroll(self, dt)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._on_touch_start(self)
|
||||
function M:_on_touch_start()
|
||||
self.inertion.x = 0
|
||||
self.inertion.y = 0
|
||||
self.target_position.x = self.position.x
|
||||
@ -765,12 +774,12 @@ function Scroll._on_touch_start(self)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._on_touch_end(self)
|
||||
function M:_on_touch_end()
|
||||
self:_check_threshold()
|
||||
end
|
||||
|
||||
|
||||
function Scroll._update_size(self)
|
||||
function M:_update_size()
|
||||
local content_border = helper.get_border(self.content_node)
|
||||
local content_size = helper.get_scaled_size(self.content_node)
|
||||
|
||||
@ -808,7 +817,7 @@ function Scroll._update_size(self)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._process_scroll_wheel(self, action_id, action)
|
||||
function M:_process_scroll_wheel(action_id, action)
|
||||
if not self._is_mouse_hover or self.style.WHEEL_SCROLL_SPEED == 0 then
|
||||
return false
|
||||
end
|
||||
@ -845,9 +854,9 @@ function Scroll._process_scroll_wheel(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
function Scroll._on_mouse_hover(self, state)
|
||||
function M:_on_mouse_hover(state)
|
||||
self._is_mouse_hover = state
|
||||
end
|
||||
|
||||
|
||||
return Scroll
|
||||
return M
|
||||
|
@ -37,19 +37,19 @@
|
||||
-- @alias druid.static_grid
|
||||
|
||||
--- On item add callback(self, node, index)
|
||||
-- @tfield DruidEvent on_add_item @{DruidEvent}
|
||||
-- @tfield DruidEvent on_add_item DruidEvent
|
||||
|
||||
--- On item remove callback(self, index)
|
||||
-- @tfield DruidEvent on_remove_item @{DruidEvent}
|
||||
-- @tfield DruidEvent on_remove_item DruidEvent
|
||||
|
||||
--- On item add, remove or change in_row callback(self, index|nil)
|
||||
-- @tfield DruidEvent on_change_items @{DruidEvent}
|
||||
-- @tfield DruidEvent on_change_items DruidEvent
|
||||
|
||||
--- On grid clear callback(self)
|
||||
-- @tfield DruidEvent on_clear @{DruidEvent}
|
||||
-- @tfield DruidEvent on_clear DruidEvent
|
||||
|
||||
--- On update item positions callback(self)
|
||||
-- @tfield DruidEvent on_update_positions @{DruidEvent}
|
||||
-- @tfield DruidEvent on_update_positions DruidEvent
|
||||
|
||||
--- Parent gui node
|
||||
-- @tfield node parent
|
||||
@ -82,7 +82,23 @@ local Event = require("druid.event")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local StaticGrid = component.create("static_grid")
|
||||
---@class druid.grid: druid.base_component
|
||||
---@field on_add_item druid.event
|
||||
---@field on_remove_item druid.event
|
||||
---@field on_change_items druid.event
|
||||
---@field on_clear druid.event
|
||||
---@field on_update_positions druid.event
|
||||
---@field parent node
|
||||
---@field nodes node[]
|
||||
---@field first_index number
|
||||
---@field last_index number
|
||||
---@field anchor vector3
|
||||
---@field pivot vector3
|
||||
---@field node_size vector3
|
||||
---@field border vector4
|
||||
---@field in_row number
|
||||
---@field style table
|
||||
local M = component.create("static_grid")
|
||||
|
||||
|
||||
local function _extend_border(border, pos, size, pivot)
|
||||
@ -104,23 +120,23 @@ end
|
||||
-- @table style
|
||||
-- @tfield boolean|nil IS_DYNAMIC_NODE_POSES If true, always center grid content as grid pivot sets. Default: false
|
||||
-- @tfield boolean|nil IS_ALIGN_LAST_ROW If true, always align last row of the grid as grid pivot sets. Default: false
|
||||
function StaticGrid.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.IS_DYNAMIC_NODE_POSES = style.IS_DYNAMIC_NODE_POSES or false
|
||||
self.style.IS_ALIGN_LAST_ROW = style.IS_ALIGN_LAST_ROW or false
|
||||
end
|
||||
|
||||
|
||||
--- The @{StaticGrid} constructor
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
--- The StaticGrid constructor
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam string|node parent The GUI Node container, where grid's items will be placed
|
||||
-- @tparam node element Element prefab. Need to get it size
|
||||
-- @tparam number|nil in_row How many nodes in row can be placed. By default 1
|
||||
function StaticGrid.init(self, parent, element, in_row)
|
||||
function M:init(parent, element, in_row)
|
||||
self.parent = self:get_node(parent)
|
||||
self.nodes = {}
|
||||
|
||||
self.pivot = helper.get_pivot_offset(gui.get_pivot(self.parent))
|
||||
self.pivot = helper.get_pivot_offset(self.parent)
|
||||
self.anchor = vmath.vector3(0.5 + self.pivot.x, 0.5 - self.pivot.y, 0)
|
||||
|
||||
self.in_row = in_row or 1
|
||||
@ -149,10 +165,10 @@ end
|
||||
|
||||
local _temp_pos = vmath.vector3(0)
|
||||
--- Return pos for grid node index
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam number index The grid element index
|
||||
-- @treturn vector3 @Node position
|
||||
function StaticGrid.get_pos(self, index)
|
||||
function M:get_pos(index)
|
||||
local row = math.ceil(index / self.in_row) - 1
|
||||
local col = (index - row * self.in_row) - 1
|
||||
|
||||
@ -167,10 +183,10 @@ end
|
||||
|
||||
|
||||
--- Return index for grid pos
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam vector3 pos The node position in the grid
|
||||
-- @treturn number The node index
|
||||
function StaticGrid.get_index(self, pos)
|
||||
function M:get_index(pos)
|
||||
-- Offset to left-top corner from node pivot
|
||||
local node_offset_x = self.node_size.x * (-0.5 + self.node_pivot.x)
|
||||
local node_offset_y = self.node_size.y * (0.5 - self.node_pivot.y)
|
||||
@ -187,10 +203,10 @@ end
|
||||
|
||||
|
||||
--- Return grid index by node
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam node node The gui node in the grid
|
||||
-- @treturn number The node index
|
||||
function StaticGrid.get_index_by_node(self, node)
|
||||
function M:get_index_by_node(node)
|
||||
for index, grid_node in pairs(self.nodes) do
|
||||
if node == grid_node then
|
||||
return index
|
||||
@ -201,28 +217,28 @@ function StaticGrid.get_index_by_node(self, node)
|
||||
end
|
||||
|
||||
|
||||
function StaticGrid.on_layout_change(self)
|
||||
function M:on_layout_change()
|
||||
self:_update(true)
|
||||
end
|
||||
|
||||
|
||||
--- Set grid anchor. Default anchor is equal to anchor of grid parent node
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam vector3 anchor Anchor
|
||||
function StaticGrid.set_anchor(self, anchor)
|
||||
function M:set_anchor(anchor)
|
||||
self.anchor = anchor
|
||||
self:_update()
|
||||
end
|
||||
|
||||
|
||||
--- Update grid content
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
function StaticGrid.refresh(self)
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
function M:refresh()
|
||||
self:_update(true)
|
||||
end
|
||||
|
||||
|
||||
function StaticGrid.set_pivot(self, pivot)
|
||||
function M:set_pivot(pivot)
|
||||
local prev_pivot = helper.get_pivot_offset(gui.get_pivot(self.parent))
|
||||
self.pivot = helper.get_pivot_offset(pivot)
|
||||
|
||||
@ -254,12 +270,12 @@ end
|
||||
|
||||
|
||||
--- Add new item to the grid
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam node item GUI node
|
||||
-- @tparam number|nil index The item position. By default add as last item
|
||||
-- @tparam number|nil shift_policy How shift nodes, if required. Default: const.SHIFT.RIGHT
|
||||
-- @tparam boolean|nil is_instant If true, update node positions instantly
|
||||
function StaticGrid.add(self, item, index, shift_policy, is_instant)
|
||||
function M:add(item, index, shift_policy, is_instant)
|
||||
index = index or ((self.last_index or 0) + 1)
|
||||
|
||||
helper.insert_with_shift(self.nodes, item, index, shift_policy)
|
||||
@ -279,10 +295,10 @@ end
|
||||
|
||||
|
||||
--- Set new items to the grid. All previous items will be removed
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam node[] nodes The new grid nodes
|
||||
-- @tparam[opt=false] boolean is_instant If true, update node positions instantly
|
||||
function StaticGrid.set_items(self, nodes, is_instant)
|
||||
function M:set_items(nodes, is_instant)
|
||||
self.nodes = nodes
|
||||
for index = 1, #nodes do
|
||||
local item = nodes[index]
|
||||
@ -296,12 +312,12 @@ end
|
||||
|
||||
|
||||
--- Remove the item from the grid. Note that gui node will be not deleted
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam number index The grid node index to remove
|
||||
-- @tparam number|nil shift_policy How shift nodes, if required. Default: const.SHIFT.RIGHT
|
||||
-- @tparam boolean|nil is_instant If true, update node positions instantly
|
||||
-- @treturn node The deleted gui node from grid
|
||||
function StaticGrid.remove(self, index, shift_policy, is_instant)
|
||||
function M:remove(index, shift_policy, is_instant)
|
||||
assert(self.nodes[index], "No grid item at given index " .. index)
|
||||
|
||||
local remove_node = self.nodes[index]
|
||||
@ -317,9 +333,9 @@ end
|
||||
|
||||
|
||||
--- Return grid content size
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @treturn vector3 The grid content size
|
||||
function StaticGrid.get_size(self)
|
||||
function M:get_size()
|
||||
return vmath.vector3(
|
||||
self.border.z - self.border.x,
|
||||
self.border.y - self.border.w,
|
||||
@ -327,7 +343,7 @@ function StaticGrid.get_size(self)
|
||||
end
|
||||
|
||||
|
||||
function StaticGrid.get_size_for(self, count)
|
||||
function M:get_size_for(count)
|
||||
if not count or count == 0 then
|
||||
return vmath.vector3(0)
|
||||
end
|
||||
@ -350,17 +366,17 @@ end
|
||||
|
||||
|
||||
--- Return grid content borders
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @treturn vector3 The grid content borders
|
||||
function StaticGrid.get_borders(self)
|
||||
function M:get_borders()
|
||||
return self.border
|
||||
end
|
||||
|
||||
|
||||
--- Return array of all node positions
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @treturn vector3[] All grid node positions
|
||||
function StaticGrid.get_all_pos(self)
|
||||
function M:get_all_pos()
|
||||
local result = {}
|
||||
for i, node in pairs(self.nodes) do
|
||||
table.insert(result, gui.get_position(node))
|
||||
@ -372,10 +388,10 @@ end
|
||||
|
||||
--- Change set position function for grid nodes. It will call on
|
||||
-- update poses on grid elements. Default: gui.set_position
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam function callback Function on node set position
|
||||
-- @treturn druid.static_grid Current grid instance
|
||||
function StaticGrid.set_position_function(self, callback)
|
||||
function M:set_position_function(callback)
|
||||
self._set_position_function = callback or gui.set_position
|
||||
|
||||
return self
|
||||
@ -384,9 +400,9 @@ end
|
||||
|
||||
--- Clear grid nodes array. GUI nodes will be not deleted!
|
||||
-- If you want to delete GUI nodes, use static_grid.nodes array before grid:clear
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @treturn druid.static_grid Current grid instance
|
||||
function StaticGrid.clear(self)
|
||||
function M:clear()
|
||||
self.border.x = 0
|
||||
self.border.y = 0
|
||||
self.border.w = 0
|
||||
@ -403,9 +419,9 @@ end
|
||||
|
||||
|
||||
--- Return StaticGrid offset, where StaticGrid content starts.
|
||||
-- @tparam StaticGrid self @{StaticGrid} The StaticGrid instance
|
||||
-- @tparam StaticGrid self StaticGrid The StaticGrid instance
|
||||
-- @treturn vector3 The StaticGrid offset
|
||||
function StaticGrid:get_offset()
|
||||
function M:get_offset()
|
||||
local borders = self:get_borders()
|
||||
local size = self:get_size()
|
||||
|
||||
@ -419,10 +435,10 @@ end
|
||||
|
||||
|
||||
--- Set new in_row elements for grid
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam number in_row The new in_row value
|
||||
-- @treturn druid.static_grid Current grid instance
|
||||
function StaticGrid.set_in_row(self, in_row)
|
||||
function M:set_in_row(in_row)
|
||||
self.in_row = in_row
|
||||
self._grid_horizonal_offset = self.node_size.x * (self.in_row - 1) * self.anchor.x
|
||||
self._zero_offset = vmath.vector3(
|
||||
@ -438,11 +454,11 @@ end
|
||||
|
||||
|
||||
--- Set new node size for grid
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam[opt] number width The new node width
|
||||
-- @tparam[opt] number height The new node height
|
||||
-- @treturn druid.static_grid Current grid instance
|
||||
function StaticGrid.set_item_size(self, width, height)
|
||||
function M:set_item_size(width, height)
|
||||
if width then
|
||||
self.node_size.x = width
|
||||
end
|
||||
@ -463,20 +479,20 @@ end
|
||||
|
||||
|
||||
--- Sort grid nodes by custom comparator function
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam function comparator The comparator function. (a, b) -> boolean
|
||||
-- @treturn druid.static_grid Current grid instance
|
||||
function StaticGrid.sort_nodes(self, comparator)
|
||||
function M:sort_nodes(comparator)
|
||||
table.sort(self.nodes, comparator)
|
||||
self:_update(true)
|
||||
end
|
||||
|
||||
|
||||
--- Update grid inner state
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam boolean|nil is_instant If true, node position update instantly, otherwise with set_position_function callback
|
||||
-- @local
|
||||
function StaticGrid._update(self, is_instant)
|
||||
function M:_update(is_instant)
|
||||
self:_update_indexes()
|
||||
self:_update_borders()
|
||||
self:_update_pos(is_instant)
|
||||
@ -484,9 +500,9 @@ end
|
||||
|
||||
|
||||
--- Update first and last indexes of grid nodes
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @local
|
||||
function StaticGrid._update_indexes(self)
|
||||
function M:_update_indexes()
|
||||
self.first_index = nil
|
||||
self.last_index = nil
|
||||
for index in pairs(self.nodes) do
|
||||
@ -500,9 +516,9 @@ end
|
||||
|
||||
|
||||
--- Update grid content borders, recalculate min and max values
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @local
|
||||
function StaticGrid._update_borders(self)
|
||||
function M:_update_borders()
|
||||
if not self.first_index then
|
||||
self.border = vmath.vector4(0)
|
||||
return
|
||||
@ -519,10 +535,10 @@ end
|
||||
|
||||
|
||||
--- Update grid nodes position
|
||||
-- @tparam StaticGrid self @{StaticGrid}
|
||||
-- @tparam StaticGrid self StaticGrid
|
||||
-- @tparam boolean|nil is_instant If true, node position update instantly, otherwise with set_position_function callback
|
||||
-- @local
|
||||
function StaticGrid._update_pos(self, is_instant)
|
||||
function M:_update_pos(is_instant)
|
||||
local zero_offset = self:_get_zero_offset()
|
||||
|
||||
for i, node in pairs(self.nodes) do
|
||||
@ -545,7 +561,7 @@ end
|
||||
-- parent pivot node (0:0) with adjusting of node sizes and anchoring
|
||||
-- @treturn vector3 The offset vector
|
||||
-- @local
|
||||
function StaticGrid:_get_zero_offset()
|
||||
function M:_get_zero_offset()
|
||||
if not self.style.IS_DYNAMIC_NODE_POSES then
|
||||
return const.VECTOR_ZERO
|
||||
end
|
||||
@ -562,7 +578,7 @@ end
|
||||
--- Return offset x for last row in grid. Used to align this row accorting to grid's anchor
|
||||
-- @treturn number The offset x value
|
||||
-- @local
|
||||
function StaticGrid:_get_zero_offset_x(row_index)
|
||||
function M:_get_zero_offset_x(row_index)
|
||||
if not self.style.IS_DYNAMIC_NODE_POSES or not self.style.IS_ALIGN_LAST_ROW then
|
||||
return self._zero_offset.x
|
||||
end
|
||||
@ -580,4 +596,4 @@ function StaticGrid:_get_zero_offset_x(row_index)
|
||||
end
|
||||
|
||||
|
||||
return StaticGrid
|
||||
return M
|
||||
|
@ -36,13 +36,13 @@
|
||||
-- @alias druid.text
|
||||
|
||||
--- On set text callback(self, text)
|
||||
-- @tfield DruidEvent on_set_text @{DruidEvent}
|
||||
-- @tfield DruidEvent on_set_text DruidEvent
|
||||
|
||||
--- On adjust text size callback(self, new_scale, text_metrics)
|
||||
-- @tfield DruidEvent on_update_text_scale @{DruidEvent}
|
||||
-- @tfield DruidEvent on_update_text_scale DruidEvent
|
||||
|
||||
--- On change pivot callback(self, pivot)
|
||||
-- @tfield DruidEvent on_set_pivot @{DruidEvent}
|
||||
-- @tfield DruidEvent on_set_pivot DruidEvent
|
||||
|
||||
--- Text node
|
||||
-- @tfield node node
|
||||
@ -83,7 +83,16 @@ local utf8_lua = require("druid.system.utf8")
|
||||
local component = require("druid.component")
|
||||
local utf8 = utf8 or utf8_lua --[[@as utf8]]
|
||||
|
||||
local Text = component.create("text")
|
||||
---@class druid.text: druid.base_component
|
||||
---@field node node
|
||||
---@field on_set_text druid.event
|
||||
---@field on_update_text_scale druid.event
|
||||
---@field on_set_pivot druid.event
|
||||
---@field style table
|
||||
---@field private start_pivot number
|
||||
---@field private start_scale vector3
|
||||
---@field private scale vector3
|
||||
local M = component.create("text")
|
||||
|
||||
local function update_text_size(self)
|
||||
if self.scale.x == 0 or self.scale.y == 0 then
|
||||
@ -269,7 +278,7 @@ end
|
||||
-- @tfield string|nil DEFAULT_ADJUST The default adjust type for any text component. Default: DOWNSCALE
|
||||
-- @tfield string|nil ADJUST_STEPS Amount of iterations for text adjust by height. Default: 20
|
||||
-- @tfield string|nil ADJUST_SCALE_DELTA Scale step on each height adjust step. Default: 0.02
|
||||
function Text.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.TRIM_POSTFIX = style.TRIM_POSTFIX or "..."
|
||||
self.style.DEFAULT_ADJUST = style.DEFAULT_ADJUST or const.TEXT_ADJUST.DOWNSCALE
|
||||
@ -278,12 +287,12 @@ function Text.on_style_change(self, style)
|
||||
end
|
||||
|
||||
|
||||
--- The @{Text} constructor
|
||||
-- @tparam Text self @{Text}
|
||||
--- The Text constructor
|
||||
-- @tparam Text self Text
|
||||
-- @tparam string|node node Node name or GUI Text Node itself
|
||||
-- @tparam string|nil value Initial text. Default value is node text from GUI scene. Default: nil
|
||||
-- @tparam string|nil adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference. Default: DOWNSCALE
|
||||
function Text.init(self, node, value, adjust_type)
|
||||
function M:init(node, value, adjust_type)
|
||||
self.node = self:get_node(node)
|
||||
self.pos = gui.get_position(self.node)
|
||||
self.node_id = gui.get_id(self.node)
|
||||
@ -309,12 +318,12 @@ function Text.init(self, node, value, adjust_type)
|
||||
end
|
||||
|
||||
|
||||
function Text.on_layout_change(self)
|
||||
function M:on_layout_change()
|
||||
self:set_to(self.last_value)
|
||||
end
|
||||
|
||||
|
||||
function Text.on_message_input(self, node_id, message)
|
||||
function M:on_message_input(node_id, message)
|
||||
if node_id ~= self.node_id then
|
||||
return false
|
||||
end
|
||||
@ -326,11 +335,11 @@ end
|
||||
|
||||
|
||||
--- Calculate text width with font with respect to trailing space
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam string text|nil
|
||||
-- @treturn number Width
|
||||
-- @treturn number Height
|
||||
function Text.get_text_size(self, text)
|
||||
function M:get_text_size(text)
|
||||
text = text or self.last_value
|
||||
local font_name = gui.get_font(self.node)
|
||||
local font = gui.get_font_resource(font_name)
|
||||
@ -351,10 +360,10 @@ end
|
||||
|
||||
|
||||
--- Get chars count by width
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam number width
|
||||
-- @treturn number Chars count
|
||||
function Text.get_text_index_by_width(self, width)
|
||||
function M:get_text_index_by_width(width)
|
||||
local text = self.last_value
|
||||
local font_name = gui.get_font(self.node)
|
||||
local font = gui.get_font_resource(font_name)
|
||||
@ -385,10 +394,10 @@ end
|
||||
|
||||
|
||||
--- Set text to text field
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam string set_to Text for node
|
||||
-- @treturn Text Current text instance
|
||||
function Text.set_to(self, set_to)
|
||||
function M:set_to(set_to)
|
||||
set_to = set_to or ""
|
||||
|
||||
self.last_value = set_to
|
||||
@ -403,10 +412,10 @@ end
|
||||
|
||||
|
||||
--- Set text area size
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam vector3 size The new text area size
|
||||
-- @treturn Text Current text instance
|
||||
function Text.set_size(self, size)
|
||||
function M:set_size(size)
|
||||
self.start_size = size
|
||||
self.text_area = vmath.vector3(size)
|
||||
self.text_area.x = self.text_area.x * self.start_scale.x
|
||||
@ -416,10 +425,10 @@ end
|
||||
|
||||
|
||||
--- Set color
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam vector4 color Color for node
|
||||
-- @treturn Text Current text instance
|
||||
function Text.set_color(self, color)
|
||||
function M:set_color(color)
|
||||
self.color = color
|
||||
gui.set_color(self.node, color)
|
||||
|
||||
@ -428,10 +437,10 @@ end
|
||||
|
||||
|
||||
--- Set alpha
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam number alpha Alpha for node
|
||||
-- @treturn Text Current text instance
|
||||
function Text.set_alpha(self, alpha)
|
||||
function M:set_alpha(alpha)
|
||||
self.color.w = alpha
|
||||
gui.set_color(self.node, self.color)
|
||||
|
||||
@ -440,10 +449,10 @@ end
|
||||
|
||||
|
||||
--- Set scale
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam vector3 scale Scale for node
|
||||
-- @treturn Text Current text instance
|
||||
function Text.set_scale(self, scale)
|
||||
function M:set_scale(scale)
|
||||
self.last_scale = scale
|
||||
gui.set_scale(self.node, scale)
|
||||
|
||||
@ -452,10 +461,10 @@ end
|
||||
|
||||
|
||||
--- Set text pivot. Text will re-anchor inside text area
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam number pivot The gui.PIVOT_* constant
|
||||
-- @treturn Text Current text instance
|
||||
function Text.set_pivot(self, pivot)
|
||||
function M:set_pivot(pivot)
|
||||
local prev_pivot = gui.get_pivot(self.node)
|
||||
local prev_offset = const.PIVOTS[prev_pivot]
|
||||
|
||||
@ -478,19 +487,19 @@ end
|
||||
|
||||
|
||||
--- Return true, if text with line break
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @treturn boolean Is text node with line break
|
||||
function Text.is_multiline(self)
|
||||
function M:is_multiline()
|
||||
return gui.get_line_break(self.node)
|
||||
end
|
||||
|
||||
|
||||
--- Set text adjust, refresh the current text visuals, if needed
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam string|nil adjust_type See const.TEXT_ADJUST. If pass nil - use current adjust type
|
||||
-- @tparam number|nil minimal_scale If pass nil - not use minimal scale
|
||||
-- @treturn Text Current text instance
|
||||
function Text.set_text_adjust(self, adjust_type, minimal_scale)
|
||||
function M:set_text_adjust(adjust_type, minimal_scale)
|
||||
self.adjust_type = adjust_type
|
||||
self._minimal_scale = minimal_scale
|
||||
self:set_to(self.last_value)
|
||||
@ -500,10 +509,10 @@ end
|
||||
|
||||
|
||||
--- Set minimal scale for DOWNSCALE_LIMITED or SCALE_THEN_SCROLL adjust types
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam Text self Text
|
||||
-- @tparam number minimal_scale If pass nil - not use minimal scale
|
||||
-- @treturn Text Current text instance
|
||||
function Text.set_minimal_scale(self, minimal_scale)
|
||||
function M:set_minimal_scale(minimal_scale)
|
||||
self._minimal_scale = minimal_scale
|
||||
|
||||
return self
|
||||
@ -512,9 +521,9 @@ end
|
||||
|
||||
--- Return current text adjust type
|
||||
-- @treturn number The current text adjust type
|
||||
function Text.get_text_adjust(self, adjust_type)
|
||||
function M:get_text_adjust(adjust_type)
|
||||
return self.adjust_type
|
||||
end
|
||||
|
||||
|
||||
return Text
|
||||
return M
|
||||
|
@ -1,83 +1,99 @@
|
||||
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Basic class for all Druid components.
|
||||
-- To create you custom component, use static function `component.create`
|
||||
-- @usage
|
||||
-- -- Create your component:
|
||||
-- local component = require("druid.component")
|
||||
--
|
||||
-- local AwesomeComponent = component.create("awesome_component")
|
||||
--
|
||||
-- function AwesomeComponent:init(template, nodes)
|
||||
-- self:set_template(template)
|
||||
-- self:set_nodes(nodes)
|
||||
-- self.druid = self:get_druid()
|
||||
-- end
|
||||
--
|
||||
-- return AwesomeComponent
|
||||
-- @module BaseComponent
|
||||
-- @alias druid.base_component
|
||||
---Base component class for all Druid components.
|
||||
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
|
||||
local BaseComponent = {}
|
||||
---@class druid.base_component.meta
|
||||
---@field template string
|
||||
---@field context table
|
||||
---@field nodes table
|
||||
---@field style table
|
||||
---@field druid druid_instance
|
||||
---@field input_enabled boolean
|
||||
---@field children table
|
||||
---@field parent druid.base_component
|
||||
---@field instance_class table
|
||||
|
||||
---@class druid.base_component.component
|
||||
---@field name string
|
||||
---@field input_priority number
|
||||
---@field default_input_priority number
|
||||
---@field _is_input_priority_changed boolean
|
||||
---@field _uid number
|
||||
|
||||
---@class druid.base_component
|
||||
---@field druid druid_instance Druid instance to create inner components
|
||||
---@field protected init fun(self:druid.base_component, ...)|nil
|
||||
---@field protected update fun(self:druid.base_component, dt:number)|nil
|
||||
---@field protected on_remove fun(self:druid.base_component)|nil
|
||||
---@field protected on_input fun(self:druid.base_component, action_id:number, action:table)|nil
|
||||
---@field protected on_message fun(self:druid.base_component, message_id:hash, message:table, sender:userdata)|nil
|
||||
---@field protected on_late_init fun(self:druid.base_component)|nil
|
||||
---@field protected on_focus_lost fun(self:druid.base_component)|nil
|
||||
---@field protected on_focus_gained fun(self:druid.base_component)|nil
|
||||
---@field protected on_style_change fun(self:druid.base_component, style: table)|nil
|
||||
---@field protected on_layout_change fun(self:druid.base_component)|nil
|
||||
---@field protected on_window_resized fun(self:druid.base_component, width:number, height:number)|nil
|
||||
---@field protected on_language_change fun(self:druid.base_component, language:string)|nil
|
||||
---@field private _component druid.base_component.component
|
||||
---@field private _meta druid.base_component.meta
|
||||
local M = {}
|
||||
|
||||
local INTERESTS = {} -- Cache interests per component class in runtime
|
||||
local IS_AUTO_TEMPLATE = not (sys.get_config_int("druid.no_auto_template", 0) == 1)
|
||||
|
||||
-- Component Interests
|
||||
BaseComponent.ON_INPUT = const.ON_INPUT
|
||||
BaseComponent.ON_UPDATE = const.ON_UPDATE
|
||||
BaseComponent.ON_MESSAGE = const.ON_MESSAGE
|
||||
BaseComponent.ON_LATE_INIT = const.ON_LATE_INIT
|
||||
BaseComponent.ON_FOCUS_LOST = const.ON_FOCUS_LOST
|
||||
BaseComponent.ON_FOCUS_GAINED = const.ON_FOCUS_GAINED
|
||||
BaseComponent.ON_LAYOUT_CHANGE = const.ON_LAYOUT_CHANGE
|
||||
BaseComponent.ON_MESSAGE_INPUT = const.ON_MESSAGE_INPUT
|
||||
BaseComponent.ON_WINDOW_RESIZED = const.ON_WINDOW_RESIZED
|
||||
BaseComponent.ON_LANGUAGE_CHANGE = const.ON_LANGUAGE_CHANGE
|
||||
M.ON_INPUT = const.ON_INPUT
|
||||
M.ON_UPDATE = const.ON_UPDATE
|
||||
M.ON_MESSAGE = const.ON_MESSAGE
|
||||
M.ON_LATE_INIT = const.ON_LATE_INIT
|
||||
M.ON_FOCUS_LOST = const.ON_FOCUS_LOST
|
||||
M.ON_FOCUS_GAINED = const.ON_FOCUS_GAINED
|
||||
M.ON_LAYOUT_CHANGE = const.ON_LAYOUT_CHANGE
|
||||
M.ON_MESSAGE_INPUT = const.ON_MESSAGE_INPUT
|
||||
M.ON_WINDOW_RESIZED = const.ON_WINDOW_RESIZED
|
||||
M.ON_LANGUAGE_CHANGE = const.ON_LANGUAGE_CHANGE
|
||||
|
||||
BaseComponent.ALL_INTERESTS = {
|
||||
BaseComponent.ON_INPUT,
|
||||
BaseComponent.ON_UPDATE,
|
||||
BaseComponent.ON_MESSAGE,
|
||||
BaseComponent.ON_LATE_INIT,
|
||||
BaseComponent.ON_FOCUS_LOST,
|
||||
BaseComponent.ON_FOCUS_GAINED,
|
||||
BaseComponent.ON_LAYOUT_CHANGE,
|
||||
BaseComponent.ON_MESSAGE_INPUT,
|
||||
BaseComponent.ON_WINDOW_RESIZED,
|
||||
BaseComponent.ON_LANGUAGE_CHANGE,
|
||||
M.ALL_INTERESTS = {
|
||||
M.ON_INPUT,
|
||||
M.ON_UPDATE,
|
||||
M.ON_MESSAGE,
|
||||
M.ON_LATE_INIT,
|
||||
M.ON_FOCUS_LOST,
|
||||
M.ON_FOCUS_GAINED,
|
||||
M.ON_LAYOUT_CHANGE,
|
||||
M.ON_MESSAGE_INPUT,
|
||||
M.ON_WINDOW_RESIZED,
|
||||
M.ON_LANGUAGE_CHANGE,
|
||||
}
|
||||
|
||||
-- Mapping from on_message method to specific method name
|
||||
BaseComponent.SPECIFIC_UI_MESSAGES = {
|
||||
[hash("layout_changed")] = BaseComponent.ON_LAYOUT_CHANGE, -- The message_id from Defold
|
||||
[hash(BaseComponent.ON_FOCUS_LOST)] = BaseComponent.ON_FOCUS_LOST,
|
||||
[hash(BaseComponent.ON_FOCUS_GAINED)] = BaseComponent.ON_FOCUS_GAINED,
|
||||
[hash(BaseComponent.ON_WINDOW_RESIZED)] = BaseComponent.ON_WINDOW_RESIZED,
|
||||
[hash(BaseComponent.ON_MESSAGE_INPUT)] = BaseComponent.ON_MESSAGE_INPUT,
|
||||
[hash(BaseComponent.ON_LANGUAGE_CHANGE)] = BaseComponent.ON_LANGUAGE_CHANGE,
|
||||
M.SPECIFIC_UI_MESSAGES = {
|
||||
[hash("layout_changed")] = M.ON_LAYOUT_CHANGE, -- The message_id from Defold
|
||||
[hash(M.ON_FOCUS_LOST)] = M.ON_FOCUS_LOST,
|
||||
[hash(M.ON_FOCUS_GAINED)] = M.ON_FOCUS_GAINED,
|
||||
[hash(M.ON_WINDOW_RESIZED)] = M.ON_WINDOW_RESIZED,
|
||||
[hash(M.ON_MESSAGE_INPUT)] = M.ON_MESSAGE_INPUT,
|
||||
[hash(M.ON_LANGUAGE_CHANGE)] = M.ON_LANGUAGE_CHANGE,
|
||||
}
|
||||
|
||||
|
||||
local uid = 0
|
||||
function BaseComponent.create_uid()
|
||||
---@private
|
||||
function M.create_uid()
|
||||
uid = uid + 1
|
||||
return uid
|
||||
end
|
||||
|
||||
|
||||
--- Set current component style table.
|
||||
--
|
||||
-- Invoke `on_style_change` on component, if exist. Component should handle
|
||||
-- their style changing and store all style params
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam table|nil druid_style Druid style module
|
||||
-- @treturn BaseComponent @{BaseComponent}
|
||||
-- @local
|
||||
function BaseComponent.set_style(self, druid_style)
|
||||
---Set component style. Pass nil to clear style
|
||||
---@generic T
|
||||
---@param self T
|
||||
---@param druid_style table|nil
|
||||
---@return T self The component itself for chaining
|
||||
function M.set_style(self, druid_style)
|
||||
---@cast self druid.base_component
|
||||
|
||||
self._meta.style = druid_style or {}
|
||||
local component_style = self._meta.style[self._component.name] or {}
|
||||
|
||||
@ -89,15 +105,16 @@ function BaseComponent.set_style(self, druid_style)
|
||||
end
|
||||
|
||||
|
||||
--- Set component template name.
|
||||
--
|
||||
-- Use on all your custom components with GUI layouts used as templates.
|
||||
-- It will check parent template name to build full template name in self:get_node()
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam string template BaseComponent template name
|
||||
-- @treturn BaseComponent @{BaseComponent}
|
||||
-- @local
|
||||
function BaseComponent.set_template(self, template)
|
||||
---Set component template name. Pass nil to clear template.
|
||||
---This template id used to access nodes inside the template on GUI scene.
|
||||
---Parent template will be added automatically if exist.
|
||||
---@generic T
|
||||
---@param self T
|
||||
---@param template string|nil
|
||||
---@return T self The component itself for chaining
|
||||
function M.set_template(self, template)
|
||||
---@cast self druid.base_component
|
||||
|
||||
template = template or ""
|
||||
|
||||
local parent = self:get_parent_component()
|
||||
@ -116,101 +133,49 @@ function BaseComponent.set_template(self, template)
|
||||
end
|
||||
|
||||
|
||||
--- Get current component template name.
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @treturn string Component full template name
|
||||
function BaseComponent.get_template(self)
|
||||
---Get full template name.
|
||||
---@return string
|
||||
function M:get_template()
|
||||
return self._meta.template
|
||||
end
|
||||
|
||||
|
||||
--- Set current component nodes.
|
||||
-- Use if your component nodes was cloned with `gui.clone_tree` and you got the node tree.
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam table nodes BaseComponent nodes table
|
||||
-- @treturn BaseComponent @{BaseComponent}
|
||||
-- @usage
|
||||
-- local nodes = gui.clone_tree(self.prefab)
|
||||
-- ... In your component:
|
||||
-- self:set_nodes(nodes)
|
||||
-- @local
|
||||
function BaseComponent.set_nodes(self, nodes)
|
||||
---Set current component nodes, returned from `gui.clone_tree` function.
|
||||
---@param nodes table<hash, node>
|
||||
---@return druid.base_component
|
||||
function M.set_nodes(self, nodes)
|
||||
self._meta.nodes = nodes
|
||||
|
||||
-- When we use gui.clone_tree in inner template (template inside other template)
|
||||
-- this nodes have no id. We have table: hash(correct_id) : hash("")
|
||||
-- It's wrong and we use this hack to fix this
|
||||
if nodes then
|
||||
for id, node in pairs(nodes) do
|
||||
gui.set_id(node, id)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Context used as first arg in all Druid events
|
||||
--
|
||||
-- Context is usually self of gui_script.
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @treturn table BaseComponent context
|
||||
function BaseComponent.get_context(self)
|
||||
---Return current component context
|
||||
---@return any context Usually it's self of script but can be any other Druid component
|
||||
function M.get_context(self)
|
||||
return self._meta.context
|
||||
end
|
||||
|
||||
|
||||
--- Increase input priority in input stack
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @local
|
||||
function BaseComponent.increase_input_priority(self)
|
||||
helper.deprecated("The component:increase_input_priority is deprecated. Please use component:set_input_priority(druid_const.PRIORITY_INPUT_MAX) instead")
|
||||
end
|
||||
|
||||
|
||||
--- Get component node by name.
|
||||
--
|
||||
-- If component has nodes, node_or_name should be string
|
||||
-- It autopick node by template name or from nodes by gui.clone_tree
|
||||
-- if they was setup via component:set_nodes, component:set_template.
|
||||
-- If node is not found, the exception will fired
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam string|node node_or_name Node name or node itself
|
||||
-- @treturn node Gui node
|
||||
function BaseComponent.get_node(self, node_or_name)
|
||||
if type(node_or_name) ~= "string" then
|
||||
---Get component node by node_id. Respect to current template and nodes.
|
||||
---@param node_id string|node
|
||||
---@return node
|
||||
function M.get_node(self, node_id)
|
||||
if type(node_id) ~= "string" then
|
||||
-- Assume it's already node from gui.get_node
|
||||
return node_or_name
|
||||
return node_id
|
||||
end
|
||||
|
||||
local template_name = self:get_template()
|
||||
local nodes = self:__get_nodes()
|
||||
|
||||
if #template_name > 0 then
|
||||
template_name = template_name .. "/"
|
||||
end
|
||||
|
||||
local node
|
||||
if nodes then
|
||||
node = nodes[template_name .. node_or_name]
|
||||
else
|
||||
node = gui.get_node(template_name .. node_or_name)
|
||||
end
|
||||
|
||||
if not node then
|
||||
assert(node, "No component with name: " .. (template_name or "") .. (node_or_name or ""))
|
||||
end
|
||||
|
||||
return node
|
||||
local nodes = self:get_nodes()
|
||||
return helper.get_node(node_id, template_name, nodes)
|
||||
end
|
||||
|
||||
|
||||
--- Get Druid instance for inner component creation.
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam string|nil template The template name
|
||||
-- @tparam table|nil nodes The nodes table
|
||||
-- @treturn DruidInstance Druid instance with component context
|
||||
function BaseComponent.get_druid(self, template, nodes)
|
||||
---Get Druid instance for inner component creation.
|
||||
---@param template string|nil
|
||||
---@param nodes table<hash, node>|nil
|
||||
---@return druid_instance
|
||||
function M:get_druid(template, nodes)
|
||||
local context = { _context = self }
|
||||
local druid_instance = setmetatable(context, { __index = self._meta.druid })
|
||||
|
||||
@ -226,39 +191,33 @@ function BaseComponent.get_druid(self, template, nodes)
|
||||
end
|
||||
|
||||
|
||||
--- Return component name
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @treturn string The component name
|
||||
function BaseComponent.get_name(self)
|
||||
return self._component.name .. BaseComponent.create_uid()
|
||||
---Get component name
|
||||
---@return string name The component name + uid
|
||||
function M.get_name(self)
|
||||
return self._component.name .. M.create_uid()
|
||||
end
|
||||
|
||||
|
||||
--- Return parent component name
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @treturn string|nil The parent component name if exist or bil
|
||||
function BaseComponent.get_parent_name(self)
|
||||
---Get parent component name
|
||||
---@return string|nil parent_name The parent component name if exist or nil
|
||||
function M.get_parent_name(self)
|
||||
local parent = self:get_parent_component()
|
||||
return parent and parent:get_name()
|
||||
end
|
||||
|
||||
|
||||
--- Return component input priority
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @treturn number The component input priority
|
||||
function BaseComponent.get_input_priority(self)
|
||||
---Get component input priority, the bigger number processed first. Default value: 10
|
||||
---@return number
|
||||
function M.get_input_priority(self)
|
||||
return self._component.input_priority
|
||||
end
|
||||
|
||||
|
||||
--- Set component input priority
|
||||
--
|
||||
-- Default value: 10
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam number value The new input priority value
|
||||
-- @tparam boolean|nil is_temporary If true, the reset input priority will return to previous value
|
||||
-- @treturn number The component input priority
|
||||
function BaseComponent.set_input_priority(self, value, is_temporary)
|
||||
---Set component input priority, the bigger number processed first. Default value: 10
|
||||
---@param value number
|
||||
---@param is_temporary boolean|nil If true, the reset input priority will return to previous value
|
||||
---@return druid.base_component self The component itself for chaining
|
||||
function M.set_input_priority(self, value, is_temporary)
|
||||
assert(value)
|
||||
|
||||
if self._component.input_priority == value then
|
||||
@ -281,32 +240,27 @@ function BaseComponent.set_input_priority(self, value, is_temporary)
|
||||
end
|
||||
|
||||
|
||||
--- Reset component input priority to default value
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @treturn number The component input priority
|
||||
function BaseComponent.reset_input_priority(self)
|
||||
---Reset component input priority to it's default value, that was set in `create` function or `set_input_priority`
|
||||
---@return druid.base_component self The component itself for chaining
|
||||
function M.reset_input_priority(self)
|
||||
self:set_input_priority(self._component.default_input_priority)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Return component UID.
|
||||
--
|
||||
-- UID generated in component creation order.
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @treturn number The component uid
|
||||
function BaseComponent.get_uid(self)
|
||||
---Get component UID, unique identifier created in component creation order.
|
||||
---@return number uid The component uid
|
||||
function M.get_uid(self)
|
||||
return self._component._uid
|
||||
end
|
||||
|
||||
|
||||
--- Set component input state. By default it enabled
|
||||
--
|
||||
-- If input is disabled, the component will not receive input events
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam boolean|nil state The component input state
|
||||
-- @treturn BaseComponent BaseComponent itself
|
||||
function BaseComponent.set_input_enabled(self, state)
|
||||
---Set component input state. By default it's enabled.
|
||||
---If input is disabled, the component will not receive input events.
|
||||
---Recursive for all children components.
|
||||
---@param state boolean
|
||||
---@return druid.base_component self The component itself for chaining
|
||||
function M.set_input_enabled(self, state)
|
||||
self._meta.input_enabled = state
|
||||
|
||||
for index = 1, #self._meta.children do
|
||||
@ -317,23 +271,22 @@ function BaseComponent.set_input_enabled(self, state)
|
||||
end
|
||||
|
||||
|
||||
--- Return the parent component if exist
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @treturn BaseComponent|nil The druid component instance or nil
|
||||
function BaseComponent.get_parent_component(self)
|
||||
---Get parent component
|
||||
---@return druid.base_component|nil parent The parent component if exist or nil
|
||||
function M.get_parent_component(self)
|
||||
return self._meta.parent
|
||||
end
|
||||
|
||||
|
||||
--- Setup component context and his style table
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam BaseComponent self BaseComponent
|
||||
-- @tparam table druid_instance The parent druid instance
|
||||
-- @tparam table context Druid context. Usually it is self of script
|
||||
-- @tparam table style Druid style module
|
||||
-- @tparam table instance_class The component instance class
|
||||
-- @treturn component BaseComponent itself
|
||||
-- @local
|
||||
function BaseComponent.setup_component(self, druid_instance, context, style, instance_class)
|
||||
---@private
|
||||
function M:setup_component(druid_instance, context, style, instance_class)
|
||||
self._meta = {
|
||||
template = "",
|
||||
context = context,
|
||||
@ -357,62 +310,35 @@ function BaseComponent.setup_component(self, druid_instance, context, style, ins
|
||||
end
|
||||
|
||||
|
||||
--- Print log information if debug mode is enabled
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam string message
|
||||
-- @tparam table context
|
||||
-- @local
|
||||
function BaseComponent.log_message(self, message, context)
|
||||
if not self._component.is_debug then
|
||||
return
|
||||
end
|
||||
print("[" .. self:get_name() .. "]:", message, helper.table_to_string(context))
|
||||
end
|
||||
|
||||
|
||||
--- Set debug logs for component enabled or disabled
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam boolean|nil is_debug
|
||||
-- @local
|
||||
function BaseComponent.set_debug(self, is_debug)
|
||||
self._component.is_debug = is_debug
|
||||
end
|
||||
|
||||
|
||||
--- Return true, if input priority was changed
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @local
|
||||
function BaseComponent._is_input_priority_changed(self)
|
||||
-- @tparam BaseComponent self BaseComponent
|
||||
---@private
|
||||
function M._is_input_priority_changed(self)
|
||||
return self._component._is_input_priority_changed
|
||||
end
|
||||
|
||||
|
||||
--- Reset is_input_priority_changed field
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @local
|
||||
function BaseComponent._reset_input_priority_changed(self)
|
||||
-- @tparam BaseComponent self BaseComponent
|
||||
---@private
|
||||
function M._reset_input_priority_changed(self)
|
||||
self._component._is_input_priority_changed = false
|
||||
end
|
||||
|
||||
|
||||
function BaseComponent.__tostring(self)
|
||||
return self._component.name
|
||||
end
|
||||
|
||||
|
||||
--- Get current component interests
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam BaseComponent self BaseComponent
|
||||
-- @treturn table List of component interests
|
||||
-- @local
|
||||
function BaseComponent.__get_interests(self)
|
||||
---@private
|
||||
function M.__get_interests(self)
|
||||
local instance_class = self._meta.instance_class
|
||||
if INTERESTS[instance_class] then
|
||||
return INTERESTS[instance_class]
|
||||
end
|
||||
|
||||
local interests = {}
|
||||
for index = 1, #BaseComponent.ALL_INTERESTS do
|
||||
local interest = BaseComponent.ALL_INTERESTS[index]
|
||||
for index = 1, #M.ALL_INTERESTS do
|
||||
local interest = M.ALL_INTERESTS[index]
|
||||
if self[interest] and type(self[interest]) == "function" then
|
||||
table.insert(interests, interest)
|
||||
end
|
||||
@ -423,34 +349,31 @@ function BaseComponent.__get_interests(self)
|
||||
end
|
||||
|
||||
|
||||
--- Get current component nodes
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @treturn table BaseComponent nodes table
|
||||
-- @local
|
||||
function BaseComponent.__get_nodes(self)
|
||||
---Get current component nodes
|
||||
---@return table<hash, node>
|
||||
function M.get_nodes(self)
|
||||
local nodes = self._meta.nodes
|
||||
local parent = self:get_parent_component()
|
||||
if parent then
|
||||
nodes = nodes or parent:__get_nodes()
|
||||
nodes = nodes or parent:get_nodes()
|
||||
end
|
||||
return nodes
|
||||
end
|
||||
|
||||
|
||||
--- Add child to component children list
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam component child The druid component instance
|
||||
-- @local
|
||||
function BaseComponent.__add_child(self, child)
|
||||
---Add child to component children list
|
||||
---@param child druid.base_component The druid component instance
|
||||
---@private
|
||||
function M:__add_child(child)
|
||||
table.insert(self._meta.children, child)
|
||||
end
|
||||
|
||||
|
||||
--- Remove child from component children list
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam BaseComponent self BaseComponent
|
||||
-- @tparam component child The druid component instance
|
||||
-- @local
|
||||
function BaseComponent.__remove_child(self, child)
|
||||
---@private
|
||||
function M.__remove_child(self, child)
|
||||
for i = #self._meta.children, 1, -1 do
|
||||
if self._meta.children[i] == child then
|
||||
table.remove(self._meta.children, i)
|
||||
@ -461,9 +384,9 @@ end
|
||||
|
||||
|
||||
--- Return all children components, recursive
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam BaseComponent self BaseComponent
|
||||
-- @treturn table Array of childrens if the Druid component instance
|
||||
function BaseComponent.get_childrens(self)
|
||||
function M.get_childrens(self)
|
||||
local childrens = {}
|
||||
|
||||
for i = 1, #self._meta.children do
|
||||
@ -477,23 +400,21 @@ function BaseComponent.get_childrens(self)
|
||||
end
|
||||
|
||||
|
||||
--- Create new component. It will inheritance from basic Druid component.
|
||||
-- @function BaseComponent.create
|
||||
-- @tparam string name BaseComponent name
|
||||
-- @tparam number|nil input_priority The input priority. The bigger number processed first
|
||||
-- @local
|
||||
function BaseComponent.create(name, input_priority)
|
||||
---Сreate a new component class, which will inherit from the base Druid component.
|
||||
---@param name string|nil The name of the component
|
||||
---@param input_priority number|nil The input priority. The bigger number processed first. Default value: 10
|
||||
---@return druid.base_component
|
||||
function M.create(name, input_priority)
|
||||
local new_class = setmetatable({}, {
|
||||
__index = BaseComponent,
|
||||
__index = M,
|
||||
__call = function(cls, ...)
|
||||
local self = setmetatable({
|
||||
_component = {
|
||||
name = name,
|
||||
name = name or "Druid Component",
|
||||
input_priority = input_priority or const.PRIORITY_INPUT,
|
||||
default_input_priority = input_priority or const.PRIORITY_INPUT,
|
||||
is_debug = false,
|
||||
_is_input_priority_changed = true, -- Default true for sort once time after GUI init
|
||||
_uid = BaseComponent.create_uid()
|
||||
_uid = M.create_uid()
|
||||
}
|
||||
}, {
|
||||
__index = cls
|
||||
@ -506,4 +427,4 @@ function BaseComponent.create(name, input_priority)
|
||||
end
|
||||
|
||||
|
||||
return BaseComponent
|
||||
return M
|
||||
|
@ -1,10 +1,4 @@
|
||||
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Druid constants
|
||||
-- @local
|
||||
-- @module DruidConst
|
||||
-- @alias druid_const
|
||||
|
||||
---@class druid.system.const
|
||||
local M = {}
|
||||
|
||||
M.ACTION_TEXT = hash(sys.get_config_string("druid.input_text", "text"))
|
||||
@ -25,7 +19,6 @@ M.ACTION_LCMD = hash(sys.get_config_string("druid.input_key_lsuper", "key_lsuper
|
||||
|
||||
M.IS_STENCIL_CHECK = not (sys.get_config_int("druid.no_stencil_check", 0) == 1)
|
||||
|
||||
|
||||
M.ON_INPUT = "on_input"
|
||||
M.ON_UPDATE = "update"
|
||||
M.ON_MESSAGE = "on_message"
|
||||
@ -123,10 +116,6 @@ M.SWIPE = {
|
||||
RIGHT = "right",
|
||||
}
|
||||
|
||||
M.ERRORS = {
|
||||
GRID_DYNAMIC_ANCHOR = "The pivot of dynamic grid node should be West, East, South or North"
|
||||
}
|
||||
|
||||
M.EMPTY_FUNCTION = function() end
|
||||
|
||||
return M
|
||||
|
@ -1,11 +1,11 @@
|
||||
script: ""
|
||||
fonts {
|
||||
name: "game"
|
||||
font: "/example/assets/fonts/game.font"
|
||||
name: "text_bold"
|
||||
font: "/example/assets/fonts/text_bold.font"
|
||||
}
|
||||
textures {
|
||||
name: "kenney"
|
||||
texture: "/example/assets/images/kenney.atlas"
|
||||
name: "druid"
|
||||
texture: "/example/assets/druid.atlas"
|
||||
}
|
||||
background_color {
|
||||
x: 0.0
|
||||
@ -33,8 +33,8 @@ nodes {
|
||||
w: 1.0
|
||||
}
|
||||
size {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
x: 500.0
|
||||
y: 80.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
@ -46,7 +46,7 @@ nodes {
|
||||
}
|
||||
type: TYPE_BOX
|
||||
blend_mode: BLEND_MODE_ALPHA
|
||||
texture: "kenney/empty"
|
||||
texture: ""
|
||||
id: "root"
|
||||
xanchor: XANCHOR_NONE
|
||||
yanchor: YANCHOR_NONE
|
||||
@ -65,7 +65,11 @@ nodes {
|
||||
clipping_inverted: false
|
||||
alpha: 1.0
|
||||
template_node_child: false
|
||||
size_mode: SIZE_MODE_AUTO
|
||||
size_mode: SIZE_MODE_MANUAL
|
||||
custom_type: 0
|
||||
enabled: true
|
||||
visible: false
|
||||
material: ""
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
@ -87,8 +91,8 @@ nodes {
|
||||
w: 1.0
|
||||
}
|
||||
size {
|
||||
x: 190.0
|
||||
y: 45.0
|
||||
x: 500.0
|
||||
y: 80.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
@ -100,7 +104,7 @@ nodes {
|
||||
}
|
||||
type: TYPE_BOX
|
||||
blend_mode: BLEND_MODE_ALPHA
|
||||
texture: "kenney/progress_back"
|
||||
texture: "druid/rect_round2_width1"
|
||||
id: "button"
|
||||
xanchor: XANCHOR_NONE
|
||||
yanchor: YANCHOR_NONE
|
||||
@ -110,17 +114,21 @@ nodes {
|
||||
layer: ""
|
||||
inherit_alpha: true
|
||||
slice9 {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
w: 0.0
|
||||
x: 4.0
|
||||
y: 4.0
|
||||
z: 4.0
|
||||
w: 4.0
|
||||
}
|
||||
clipping_mode: CLIPPING_MODE_NONE
|
||||
clipping_visible: true
|
||||
clipping_inverted: false
|
||||
alpha: 1.0
|
||||
template_node_child: false
|
||||
size_mode: SIZE_MODE_AUTO
|
||||
size_mode: SIZE_MODE_MANUAL
|
||||
custom_type: 0
|
||||
enabled: true
|
||||
visible: true
|
||||
material: ""
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
@ -136,27 +144,27 @@ nodes {
|
||||
w: 1.0
|
||||
}
|
||||
scale {
|
||||
x: 0.5
|
||||
y: 0.5
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
w: 1.0
|
||||
}
|
||||
size {
|
||||
x: 300.0
|
||||
x: 480.0
|
||||
y: 60.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
color {
|
||||
x: 0.9490196
|
||||
y: 0.9490196
|
||||
z: 0.9490196
|
||||
x: 0.31
|
||||
y: 0.318
|
||||
z: 0.322
|
||||
w: 1.0
|
||||
}
|
||||
type: TYPE_TEXT
|
||||
blend_mode: BLEND_MODE_ALPHA
|
||||
text: "Placeholder"
|
||||
font: "game"
|
||||
font: "text_bold"
|
||||
id: "placeholder_text"
|
||||
xanchor: XANCHOR_NONE
|
||||
yanchor: YANCHOR_NONE
|
||||
@ -179,11 +187,15 @@ nodes {
|
||||
layer: ""
|
||||
inherit_alpha: true
|
||||
alpha: 1.0
|
||||
outline_alpha: 1.0
|
||||
outline_alpha: 0.0
|
||||
shadow_alpha: 0.0
|
||||
template_node_child: false
|
||||
text_leading: 1.0
|
||||
text_tracking: 0.0
|
||||
custom_type: 0
|
||||
enabled: true
|
||||
visible: true
|
||||
material: ""
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
@ -199,27 +211,27 @@ nodes {
|
||||
w: 1.0
|
||||
}
|
||||
scale {
|
||||
x: 0.6
|
||||
y: 0.6
|
||||
z: 1.0
|
||||
w: 1.0
|
||||
}
|
||||
size {
|
||||
x: 300.0
|
||||
y: 60.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
color {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
w: 1.0
|
||||
}
|
||||
size {
|
||||
x: 480.0
|
||||
y: 60.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
color {
|
||||
x: 0.722
|
||||
y: 0.741
|
||||
z: 0.761
|
||||
w: 1.0
|
||||
}
|
||||
type: TYPE_TEXT
|
||||
blend_mode: BLEND_MODE_ALPHA
|
||||
text: "User input"
|
||||
font: "game"
|
||||
font: "text_bold"
|
||||
id: "input_text"
|
||||
xanchor: XANCHOR_NONE
|
||||
yanchor: YANCHOR_NONE
|
||||
@ -242,15 +254,19 @@ nodes {
|
||||
layer: ""
|
||||
inherit_alpha: true
|
||||
alpha: 1.0
|
||||
outline_alpha: 1.0
|
||||
outline_alpha: 0.0
|
||||
shadow_alpha: 0.0
|
||||
template_node_child: false
|
||||
text_leading: 1.0
|
||||
text_tracking: 0.0
|
||||
custom_type: 0
|
||||
enabled: true
|
||||
visible: true
|
||||
material: ""
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: 67.0
|
||||
x: 118.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
@ -262,26 +278,26 @@ nodes {
|
||||
w: 1.0
|
||||
}
|
||||
scale {
|
||||
x: 0.6
|
||||
y: 0.6
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
w: 1.0
|
||||
}
|
||||
size {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
x: 16.0
|
||||
y: 50.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
color {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
x: 0.631
|
||||
y: 0.843
|
||||
z: 0.961
|
||||
w: 1.0
|
||||
}
|
||||
type: TYPE_BOX
|
||||
blend_mode: BLEND_MODE_ALPHA
|
||||
texture: "kenney/empty"
|
||||
texture: "druid/ui_circle_16"
|
||||
id: "cursor_node"
|
||||
xanchor: XANCHOR_NONE
|
||||
yanchor: YANCHOR_NONE
|
||||
@ -291,22 +307,26 @@ nodes {
|
||||
layer: ""
|
||||
inherit_alpha: true
|
||||
slice9 {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
w: 0.0
|
||||
x: 8.0
|
||||
y: 8.0
|
||||
z: 8.0
|
||||
w: 8.0
|
||||
}
|
||||
clipping_mode: CLIPPING_MODE_NONE
|
||||
clipping_visible: true
|
||||
clipping_inverted: false
|
||||
alpha: 1.0
|
||||
alpha: 0.5
|
||||
template_node_child: false
|
||||
size_mode: SIZE_MODE_AUTO
|
||||
size_mode: SIZE_MODE_MANUAL
|
||||
custom_type: 0
|
||||
enabled: true
|
||||
visible: true
|
||||
material: ""
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: 0.0
|
||||
y: 2.0
|
||||
y: 4.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
@ -317,8 +337,8 @@ nodes {
|
||||
w: 1.0
|
||||
}
|
||||
scale {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
x: 1.2
|
||||
y: 1.2
|
||||
z: 1.0
|
||||
w: 1.0
|
||||
}
|
||||
@ -329,15 +349,15 @@ nodes {
|
||||
w: 1.0
|
||||
}
|
||||
color {
|
||||
x: 0.2
|
||||
y: 0.2
|
||||
z: 0.2
|
||||
x: 0.722
|
||||
y: 0.741
|
||||
z: 0.761
|
||||
w: 1.0
|
||||
}
|
||||
type: TYPE_TEXT
|
||||
blend_mode: BLEND_MODE_ALPHA
|
||||
text: "|"
|
||||
font: "game"
|
||||
font: "text_bold"
|
||||
id: "cursor_text"
|
||||
xanchor: XANCHOR_NONE
|
||||
yanchor: YANCHOR_NONE
|
||||
@ -358,13 +378,17 @@ nodes {
|
||||
line_break: false
|
||||
parent: "cursor_node"
|
||||
layer: ""
|
||||
inherit_alpha: true
|
||||
inherit_alpha: false
|
||||
alpha: 1.0
|
||||
outline_alpha: 0.0
|
||||
shadow_alpha: 0.0
|
||||
template_node_child: false
|
||||
text_leading: 1.0
|
||||
text_tracking: 0.0
|
||||
custom_type: 0
|
||||
enabled: true
|
||||
visible: true
|
||||
material: ""
|
||||
}
|
||||
material: "/builtins/materials/gui.material"
|
||||
adjust_reference: ADJUST_REFERENCE_PARENT
|
||||
|
@ -6,13 +6,13 @@
|
||||
-- @alias druid.rich_input
|
||||
|
||||
--- The component druid instance
|
||||
-- @tfield DruidInstance druid @{DruidInstance}
|
||||
-- @tfield DruidInstance druid DruidInstance
|
||||
|
||||
--- Root node
|
||||
-- @tfield node root
|
||||
|
||||
--- On input field text change callback(self, input_text)
|
||||
-- @tfield Input input @{Input}
|
||||
-- @tfield Input input Input
|
||||
|
||||
--- On input field text change to empty string callback(self, input_text)
|
||||
-- @tfield node cursor
|
||||
@ -44,16 +44,23 @@ local utf8_lua = require("druid.system.utf8")
|
||||
local utf8 = utf8 or utf8_lua
|
||||
|
||||
local input = require("druid.extended.input")
|
||||
local RichInput = component.create("druid.rich_input")
|
||||
|
||||
local SCHEME = {
|
||||
ROOT = "root",
|
||||
BUTTON = "button",
|
||||
PLACEHOLDER = "placeholder_text",
|
||||
INPUT = "input_text",
|
||||
CURSOR = "cursor_node",
|
||||
CURSOR_TEXT = "cursor_text",
|
||||
}
|
||||
---@class druid.rich_input: druid.base_component
|
||||
---@field root node
|
||||
---@field input druid.input
|
||||
---@field cursor node
|
||||
---@field cursor_text node
|
||||
---@field cursor_position vector3
|
||||
local M = component.create("druid.rich_input")
|
||||
|
||||
--local SCHEME = {
|
||||
-- ROOT = "root",
|
||||
-- BUTTON = "button",
|
||||
-- PLACEHOLDER = "placeholder_text",
|
||||
-- INPUT = "input_text",
|
||||
-- CURSOR = "cursor_node",
|
||||
-- CURSOR_TEXT = "cursor_text",
|
||||
--}
|
||||
|
||||
local DOUBLE_CLICK_TIME = 0.35
|
||||
|
||||
@ -189,13 +196,11 @@ local function on_drag_callback(self, dx, dy, x, y, touch)
|
||||
end
|
||||
|
||||
|
||||
--- The @{RichInput} constructor
|
||||
-- @tparam RichInput self @{RichInput}
|
||||
-- @tparam string template The template string name
|
||||
-- @tparam table nodes Nodes table from gui.clone_tree
|
||||
function RichInput.init(self, template, nodes)
|
||||
---@param template string The template string name
|
||||
---@param nodes table Nodes table from gui.clone_tree
|
||||
function M:init(template, nodes)
|
||||
self.druid = self:get_druid(template, nodes)
|
||||
self.root = self:get_node(SCHEME.ROOT)
|
||||
self.root = self:get_node("root")
|
||||
|
||||
self._last_touch_info = {
|
||||
cursor_index = nil,
|
||||
@ -204,20 +209,20 @@ function RichInput.init(self, template, nodes)
|
||||
self.is_lshift = false
|
||||
self.is_lctrl = false
|
||||
|
||||
self.input = self.druid:new(input, self:get_node(SCHEME.BUTTON), self:get_node(SCHEME.INPUT))
|
||||
self.input = self.druid:new(input, "button", "input_text")
|
||||
self.is_button_input_enabled = gui.is_enabled(self.input.button.node)
|
||||
|
||||
self.cursor = self:get_node(SCHEME.CURSOR)
|
||||
self.cursor = self:get_node("cursor_node")
|
||||
self.cursor_position = gui.get_position(self.cursor)
|
||||
self.cursor_text = self:get_node(SCHEME.CURSOR_TEXT)
|
||||
self.cursor_text = self:get_node("cursor_text")
|
||||
|
||||
self.drag = self.druid:new_drag(self:get_node(SCHEME.BUTTON), on_drag_callback)
|
||||
self.drag = self.druid:new_drag("button", on_drag_callback)
|
||||
self.drag.on_touch_start:subscribe(on_touch_start_callback)
|
||||
self.drag:set_input_priority(const.PRIORITY_INPUT_MAX + 1)
|
||||
self.drag:set_enabled(false)
|
||||
|
||||
self.input:set_text("")
|
||||
self.placeholder = self.druid:new_text(self:get_node(SCHEME.PLACEHOLDER))
|
||||
self.placeholder = self.druid:new_text("placeholder_text")
|
||||
self.text_position = gui.get_position(self.input.text.node)
|
||||
|
||||
self.input.on_input_text:subscribe(update_text)
|
||||
@ -230,7 +235,7 @@ function RichInput.init(self, template, nodes)
|
||||
end
|
||||
|
||||
|
||||
function RichInput.on_input(self, action_id, action)
|
||||
function M:on_input(action_id, action)
|
||||
if action_id == const.ACTION_LSHIFT then
|
||||
if action.pressed then
|
||||
self.is_lshift = true
|
||||
@ -258,26 +263,26 @@ end
|
||||
|
||||
|
||||
--- Set placeholder text
|
||||
-- @tparam RichInput self @{RichInput}
|
||||
-- @tparam RichInput self RichInput
|
||||
-- @tparam string placeholder_text The placeholder text
|
||||
function RichInput.set_placeholder(self, placeholder_text)
|
||||
function M:set_placeholder(placeholder_text)
|
||||
self.placeholder:set_to(placeholder_text)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Select input field
|
||||
-- @tparam RichInput self @{RichInput}
|
||||
function RichInput.select(self)
|
||||
-- @tparam RichInput self RichInput
|
||||
function M:select()
|
||||
self.input:select()
|
||||
end
|
||||
|
||||
|
||||
--- Set input field text
|
||||
-- @tparam RichInput self @{RichInput}
|
||||
-- @tparam RichInput self RichInput
|
||||
-- @treturn druid.input Current input instance
|
||||
-- @tparam string text The input text
|
||||
function RichInput.set_text(self, text)
|
||||
function M:set_text(text)
|
||||
self.input:set_text(text)
|
||||
gui.set_enabled(self.placeholder.node, true and #self.input:get_text() == 0)
|
||||
|
||||
@ -286,10 +291,10 @@ end
|
||||
|
||||
|
||||
--- Set input field font
|
||||
-- @tparam RichInput self @{RichInput}
|
||||
-- @tparam RichInput self RichInput
|
||||
-- @tparam hash font The font hash
|
||||
-- @treturn druid.input Current input instance
|
||||
function RichInput.set_font(self, font)
|
||||
function M:set_font(font)
|
||||
gui.set_font(self.input.text.node, font)
|
||||
gui.set_font(self.placeholder.node, font)
|
||||
|
||||
@ -298,8 +303,8 @@ end
|
||||
|
||||
|
||||
--- Set input field text
|
||||
-- @tparam RichInput self @{RichInput}
|
||||
function RichInput.get_text(self)
|
||||
-- @tparam RichInput self RichInput
|
||||
function M:get_text()
|
||||
return self.input:get_text()
|
||||
end
|
||||
|
||||
@ -307,14 +312,14 @@ end
|
||||
--- Set allowed charaters for input field.
|
||||
-- See: https://defold.com/ref/stable/string/
|
||||
-- ex: [%a%d] for alpha and numeric
|
||||
-- @tparam RichInput self @{RichInput}
|
||||
-- @tparam RichInput self RichInput
|
||||
-- @tparam string characters Regulax exp. for validate user input
|
||||
-- @treturn RichInput Current instance
|
||||
function RichInput.set_allowed_characters(self, characters)
|
||||
function M:set_allowed_characters(characters)
|
||||
self.input:set_allowed_characters(characters)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
return RichInput
|
||||
return M
|
||||
|
@ -63,7 +63,7 @@
|
||||
-- @alias druid.rich_text
|
||||
|
||||
--- The component druid instance
|
||||
-- @tfield DruidInstance druid @{DruidInstance}
|
||||
-- @tfield DruidInstance druid DruidInstance
|
||||
|
||||
--- The root node of the Rich Text
|
||||
-- @tfield node root
|
||||
@ -76,14 +76,19 @@
|
||||
local component = require("druid.component")
|
||||
local rich_text = require("druid.custom.rich_text.module.rt")
|
||||
|
||||
local RichText = component.create("rich_text")
|
||||
---@class druid.rich_text: druid.base_component
|
||||
---@field root node
|
||||
---@field text_prefab node
|
||||
---@field private _last_value string
|
||||
---@field private _settings table
|
||||
local M = component.create("rich_text")
|
||||
|
||||
|
||||
--- The @{RichText} constructor
|
||||
-- @tparam RichText self @{RichText}
|
||||
--- The RichText constructor
|
||||
-- @tparam RichText self RichText
|
||||
-- @tparam node|string text_node The text node to make Rich Text
|
||||
-- @tparam string|nil value The initial text value. Default will be gui.get_text(text_node)
|
||||
function RichText.init(self, text_node, value)
|
||||
function M:init(text_node, value)
|
||||
self.root = self:get_node(text_node)
|
||||
self.text_prefab = self.root
|
||||
|
||||
@ -98,7 +103,7 @@ function RichText.init(self, text_node, value)
|
||||
end
|
||||
|
||||
|
||||
function RichText.on_layout_change(self)
|
||||
function M:on_layout_change()
|
||||
if self._last_value then
|
||||
self:set_text(self._last_value)
|
||||
end
|
||||
@ -112,7 +117,7 @@ end
|
||||
-- @tfield table|nil COLORS Rich Text color aliases. Default: {}
|
||||
-- @tfield number|nil ADJUST_STEPS Amount steps of attemps text adjust by height. Default: 20
|
||||
-- @tfield number|nil ADJUST_SCALE_DELTA Scale step on each height adjust step. Default: 0.02
|
||||
function RichText.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.COLORS = style.COLORS or {}
|
||||
self.style.ADJUST_STEPS = style.ADJUST_STEPS or 20
|
||||
@ -121,7 +126,7 @@ end
|
||||
|
||||
|
||||
--- Set text for Rich Text
|
||||
-- @tparam RichText self @{RichText}
|
||||
-- @tparam RichText self RichText
|
||||
-- @tparam string|nil text The text to set
|
||||
-- @treturn druid.rich_text.word[] words
|
||||
-- @treturn druid.rich_text.lines_metrics line_metrics
|
||||
@ -168,7 +173,7 @@ end
|
||||
-- <img=texture:image/>
|
||||
-- <img=texture:image,size/>
|
||||
-- <img=texture:image,width,height/>
|
||||
function RichText.set_text(self, text)
|
||||
function M:set_text(text)
|
||||
text = text or ""
|
||||
self:clear()
|
||||
self._last_value = text
|
||||
@ -184,14 +189,14 @@ end
|
||||
|
||||
|
||||
--- Get current text
|
||||
-- @tparam RichText self @{RichText}
|
||||
-- @tparam RichText self RichText
|
||||
-- @treturn string text
|
||||
function RichText.get_text(self)
|
||||
function M:get_text()
|
||||
return self._last_value
|
||||
end
|
||||
|
||||
|
||||
function RichText:on_remove()
|
||||
function M:on_remove()
|
||||
gui.set_scale(self.root, self._default_scale)
|
||||
gui.set_size(self.root, self._default_size)
|
||||
self:clear()
|
||||
@ -199,7 +204,7 @@ end
|
||||
|
||||
|
||||
--- Clear all created words.
|
||||
function RichText:clear()
|
||||
function M:clear()
|
||||
if self._words then
|
||||
rich_text.remove(self._words)
|
||||
self._words = nil
|
||||
@ -209,10 +214,10 @@ end
|
||||
|
||||
|
||||
--- Get all words, which has a passed tag.
|
||||
-- @tparam RichText self @{RichText}
|
||||
-- @tparam RichText self RichText
|
||||
-- @tparam string tag
|
||||
-- @treturn druid.rich_text.word[] words
|
||||
function RichText.tagged(self, tag)
|
||||
function M:tagged(tag)
|
||||
if not self._words then
|
||||
return
|
||||
end
|
||||
@ -222,29 +227,29 @@ end
|
||||
|
||||
|
||||
---Split a word into it's characters
|
||||
-- @tparam RichText self @{RichText}
|
||||
-- @tparam RichText self RichText
|
||||
-- @tparam druid.rich_text.word word
|
||||
-- @treturn druid.rich_text.word[] characters
|
||||
function RichText.characters(self, word)
|
||||
function M:characters(word)
|
||||
return rich_text.characters(word)
|
||||
end
|
||||
|
||||
|
||||
--- Get all current words.
|
||||
-- @treturn table druid.rich_text.word[]
|
||||
function RichText:get_words()
|
||||
function M:get_words()
|
||||
return self._words
|
||||
end
|
||||
|
||||
|
||||
--- Get current line metrics
|
||||
--- @treturn druid.rich_text.lines_metrics
|
||||
function RichText:get_line_metric()
|
||||
function M:get_line_metric()
|
||||
return self._line_metrics
|
||||
end
|
||||
|
||||
|
||||
function RichText:_create_settings()
|
||||
function M:_create_settings()
|
||||
local root_size = gui.get_size(self.root)
|
||||
local scale = gui.get_scale(self.root)
|
||||
|
||||
@ -280,4 +285,4 @@ function RichText:_create_settings()
|
||||
end
|
||||
|
||||
|
||||
return RichText
|
||||
return M
|
||||
|
107
druid/druid.lua
107
druid/druid.lua
@ -13,7 +13,7 @@
|
||||
--
|
||||
-- • Each Druid instance maintains the self context from the constructor and passes it to each Druid callback.
|
||||
--
|
||||
-- See next: @{DruidInstance}
|
||||
-- See next: DruidInstance
|
||||
--
|
||||
-- @usage
|
||||
-- local druid = require("druid.druid")
|
||||
@ -52,15 +52,15 @@ local druid_instance = require("druid.system.druid_instance")
|
||||
|
||||
local default_style = require("druid.styles.default.style")
|
||||
|
||||
---@class druid
|
||||
local M = {}
|
||||
|
||||
local _instances = {}
|
||||
local druid_instances = {}
|
||||
|
||||
|
||||
local function clean_deleted_druid_instances()
|
||||
for i = #_instances, 1, -1 do
|
||||
if _instances[i]._deleted then
|
||||
table.remove(_instances, i)
|
||||
for i = #druid_instances, 1, -1 do
|
||||
if druid_instances[i]._deleted then
|
||||
table.remove(druid_instances, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -68,45 +68,27 @@ end
|
||||
|
||||
local function get_druid_instances()
|
||||
clean_deleted_druid_instances()
|
||||
return _instances
|
||||
return druid_instances
|
||||
end
|
||||
|
||||
|
||||
--- Register a new external Druid component.
|
||||
--
|
||||
-- You can register your own components to make new alias: the druid:new_{name} function.
|
||||
-- For example, if you want to register a component called "my_component", you can create it using druid:new_my_component(...).
|
||||
-- This can be useful if you have your own "basic" components that you don't want to re-create each time.
|
||||
-- @function druid.register
|
||||
-- @tparam string name module name
|
||||
-- @tparam table module lua table with component
|
||||
-- @usage
|
||||
-- local my_component = require("path.to.my.component")
|
||||
-- druid.register("my_component", my_component)
|
||||
-- ...
|
||||
-- local druid = druid.new(self)
|
||||
-- local component_instance = self.druid:new_my_component(...)
|
||||
---Register a new external Druid component.
|
||||
---You can register your own components to make new alias: the druid:new_{name} function.
|
||||
---For example, if you want to register a component called "my_component", you can create it using druid:new_my_component(...).
|
||||
---This can be useful if you have your own "basic" components that you don't want to re-create each time.
|
||||
---@param name string Module name
|
||||
---@param module table Lua table with component
|
||||
function M.register(name, module)
|
||||
druid_instance["new_" .. name] = function(self, ...)
|
||||
return druid_instance.new(self, module, ...)
|
||||
end
|
||||
|
||||
return druid_instance["new_" .. name]
|
||||
end
|
||||
|
||||
|
||||
--- Create a new Druid instance for creating GUI components.
|
||||
--
|
||||
-- @function druid.new
|
||||
-- @tparam table context The Druid context. Usually, this is the self of the gui_script. It is passed into all Druid callbacks.
|
||||
-- @tparam table|nil style The Druid style table to override style parameters for this Druid instance.
|
||||
-- @treturn druid_instance The Druid instance @{DruidInstance}.
|
||||
-- @usage
|
||||
-- local druid = require("druid.druid")
|
||||
--
|
||||
-- function init(self)
|
||||
-- self.druid = druid.new(self)
|
||||
-- end
|
||||
---Create a new Druid instance for creating GUI components.
|
||||
---@param context table The Druid context. Usually, this is the self of the gui_script. It is passed into all Druid callbacks.
|
||||
---@param style table|nil The Druid style table to override style parameters for this Druid instance.
|
||||
---@return druid_instance druid_instance The new Druid instance
|
||||
function M.new(context, style)
|
||||
clean_deleted_druid_instances()
|
||||
|
||||
@ -117,65 +99,35 @@ function M.new(context, style)
|
||||
local new_instance = setmetatable({}, { __index = druid_instance })
|
||||
new_instance:initialize(context, style)
|
||||
|
||||
table.insert(_instances, new_instance)
|
||||
table.insert(druid_instances, new_instance)
|
||||
return new_instance
|
||||
end
|
||||
|
||||
|
||||
--- Set your own default style for all Druid instances.
|
||||
--
|
||||
-- To create your own style file, copy the default style file and make changes to it.
|
||||
-- Register the new style before creating your Druid instances.
|
||||
-- @function druid.set_default_style
|
||||
-- @tparam table style Druid style module
|
||||
-- @usage
|
||||
-- local my_style = require("path.to.my.style")
|
||||
-- druid.set_default_style(my_style)
|
||||
---Set the default style for all Druid instances.
|
||||
---@param style table Default style
|
||||
function M.set_default_style(style)
|
||||
settings.default_style = style or {}
|
||||
end
|
||||
|
||||
|
||||
--- Set the text function for the LangText component.
|
||||
--
|
||||
-- The Druid locale component will call this function to get translated text.
|
||||
-- After setting the text function, all existing locale components will be updated.
|
||||
-- @function druid.set_text_function
|
||||
-- @tparam function callback Get localized text function
|
||||
-- @usage
|
||||
-- druid.set_text_function(function(text_id)
|
||||
-- return lang_data[text_id] -- Replace with your real function
|
||||
-- end)
|
||||
---Set the text function for the LangText component.
|
||||
---@param callback fun(text_id: string): string Get localized text function
|
||||
function M.set_text_function(callback)
|
||||
settings.get_text = callback or const.EMPTY_FUNCTION
|
||||
M.on_language_change()
|
||||
end
|
||||
|
||||
|
||||
--- Set the Druid sound function to play UI sounds if used.
|
||||
--
|
||||
-- Set a function to play a sound given a sound_id. This function is used for button clicks to play the "click" sound.
|
||||
-- It can also be used to play sounds in your custom components (see the default Druid style file for an example).
|
||||
-- @function druid.set_sound_function
|
||||
-- @tparam function callback Sound play callback
|
||||
-- @usage
|
||||
-- druid.set_sound_function(function(sound_id)
|
||||
-- sound.play(sound_id) -- Replace with your real function
|
||||
-- end)
|
||||
---Set the sound function to able components to play sounds.
|
||||
---@param callback fun(sound_id: string) Sound play callback
|
||||
function M.set_sound_function(callback)
|
||||
settings.play_sound = callback or const.EMPTY_FUNCTION
|
||||
end
|
||||
|
||||
|
||||
--- Set the window callback to enable on_focus_gain and on_focus_lost functions.
|
||||
--
|
||||
-- This is used to trigger the on_focus_lost and on_focus_gain functions in Druid components.
|
||||
-- @function druid.on_window_callback
|
||||
-- @tparam string event Event param from window listener
|
||||
-- @usage
|
||||
-- window.set_listener(function(_, event)
|
||||
-- druid.on_window_callback(event)
|
||||
-- end)
|
||||
---Set the window callback to enable Druid window events.
|
||||
---@param event constant Event param from window listener
|
||||
function M.on_window_callback(event)
|
||||
local instances = get_druid_instances()
|
||||
|
||||
@ -195,12 +147,7 @@ function M.on_window_callback(event)
|
||||
end
|
||||
|
||||
|
||||
--- Call this function when the game language changes.
|
||||
--
|
||||
-- This function will translate all current LangText components.
|
||||
-- @function druid.on_language_change
|
||||
-- @usage
|
||||
-- druid.on_language_change()
|
||||
---Call this function when the game language changes.
|
||||
function M.on_language_change()
|
||||
local instances = get_druid_instances()
|
||||
|
||||
|
@ -48,10 +48,6 @@ def process_component(node_name, component_name):
|
||||
component_define += "\n--TODO: Replace prefab_name with grid element prefab"
|
||||
component_define += "\n\tself.{0} = self.druid:new_static_grid(\"{1}\", \"prefab_name\", 1)".format(node_name, node_name)
|
||||
|
||||
if node_name.startswith("dynamic_grid"):
|
||||
component_annotations += "\n---@field {0} druid.dynamic_grid".format(node_name)
|
||||
component_define += "\n\tself.{0} = self.druid:new_dynamic_grid(\"{1}\")".format(node_name, node_name)
|
||||
|
||||
if node_name.startswith("scroll_view"):
|
||||
field_name = node_name.replace("_view", "")
|
||||
content_name = node_name.replace("_view", "_content")
|
||||
|
@ -8,6 +8,7 @@
|
||||
-- @module DruidEvent
|
||||
-- @alias druid.event
|
||||
|
||||
---@class druid.event
|
||||
local M = {}
|
||||
M.COUNTER = 0
|
||||
|
||||
@ -39,11 +40,11 @@ end
|
||||
|
||||
|
||||
--- Check is event subscribed.
|
||||
-- @tparam DruidEvent self @{DruidEvent}
|
||||
-- @tparam DruidEvent self DruidEvent
|
||||
-- @tparam function callback Callback itself
|
||||
-- @tparam any|nil callback_context Additional context as first param to callback call
|
||||
-- @treturn boolean, number|nil @Is event subscribed, return index of callback in event as second param
|
||||
function M.is_subscribed(self, callback, callback_context)
|
||||
function M:is_subscribed(callback, callback_context)
|
||||
if #self == 0 then
|
||||
return false, nil
|
||||
end
|
||||
@ -60,7 +61,7 @@ end
|
||||
|
||||
|
||||
--- Subscribe callback on event
|
||||
-- @tparam DruidEvent self @{DruidEvent}
|
||||
-- @tparam DruidEvent self DruidEvent
|
||||
-- @tparam function callback Callback itself
|
||||
-- @tparam any|nil callback_context Additional context as first param to callback call, usually it's self
|
||||
-- @treturn boolean True if callback was subscribed
|
||||
@ -71,7 +72,7 @@ end
|
||||
-- ...
|
||||
-- local button = self.druid:new_button("button", callback)
|
||||
-- button.on_long_click:subscribe(on_long_callback, self)
|
||||
function M.subscribe(self, callback, callback_context)
|
||||
function M:subscribe(callback, callback_context)
|
||||
assert(type(self) == "table", "You should subscribe to event with : syntax")
|
||||
assert(callback, "A function must be passed to subscribe to an event")
|
||||
|
||||
@ -85,7 +86,7 @@ end
|
||||
|
||||
|
||||
--- Unsubscribe callback on event
|
||||
-- @tparam DruidEvent self @{DruidEvent}
|
||||
-- @tparam DruidEvent self DruidEvent
|
||||
-- @tparam function callback Callback itself
|
||||
-- @tparam any|nil callback_context Additional context as first param to callback call
|
||||
-- @usage
|
||||
@ -94,7 +95,7 @@ end
|
||||
-- end
|
||||
-- ...
|
||||
-- button.on_long_click:unsubscribe(on_long_callback, self)
|
||||
function M.unsubscribe(self, callback, callback_context)
|
||||
function M:unsubscribe(callback, callback_context)
|
||||
assert(callback, "A function must be passed to subscribe to an event")
|
||||
|
||||
local _, event_index = self:is_subscribed(callback, callback_context)
|
||||
@ -108,17 +109,17 @@ end
|
||||
|
||||
|
||||
--- Return true, if event have at lease one handler
|
||||
-- @tparam DruidEvent self @{DruidEvent}
|
||||
-- @tparam DruidEvent self DruidEvent
|
||||
-- @treturn boolean True if event have handlers
|
||||
-- @usage
|
||||
-- local is_long_click_handler_exists = button.on_long_click:is_exist()
|
||||
function M.is_exist(self)
|
||||
function M:is_exist()
|
||||
return #self > 0
|
||||
end
|
||||
|
||||
|
||||
--- Return true, if event not have handler
|
||||
--- @tparam DruidEvent self @{DruidEvent}
|
||||
--- @tparam DruidEvent self DruidEvent
|
||||
--- @treturn boolean True if event not have handlers
|
||||
--- @usage
|
||||
--- local is_long_click_handler_not_exists = button.on_long_click:is_empty()
|
||||
@ -128,10 +129,10 @@ end
|
||||
|
||||
|
||||
--- Clear the all event handlers
|
||||
-- @tparam DruidEvent self @{DruidEvent}
|
||||
-- @tparam DruidEvent self DruidEvent
|
||||
-- @usage
|
||||
-- button.on_long_click:clear()
|
||||
function M.clear(self)
|
||||
function M:clear()
|
||||
for index = #self, 1, -1 do
|
||||
self[index] = nil
|
||||
end
|
||||
@ -139,14 +140,14 @@ end
|
||||
|
||||
|
||||
--- Trigger the event and call all subscribed callbacks
|
||||
-- @tparam DruidEvent self @{DruidEvent}
|
||||
-- @tparam DruidEvent self DruidEvent
|
||||
-- @tparam any ... All event params
|
||||
-- @usage
|
||||
-- local Event = require("druid.event")
|
||||
-- ...
|
||||
-- local event = Event()
|
||||
-- event:trigger("Param1", "Param2")
|
||||
function M.trigger(self, ...)
|
||||
function M:trigger(...)
|
||||
if #self == 0 then
|
||||
return
|
||||
end
|
||||
|
@ -10,10 +10,10 @@
|
||||
|
||||
|
||||
--- The Druid scroll component
|
||||
-- @tfield Scroll scroll @{Scroll}
|
||||
-- @tfield Scroll scroll Scroll
|
||||
|
||||
--- The Druid Grid component
|
||||
-- @tfield StaticGrid grid @{StaticGrid}, @{DynamicGrid}
|
||||
-- @tfield StaticGrid grid StaticGrid}, @{DynamicGrid
|
||||
|
||||
--- The current progress of scroll posititon
|
||||
-- @tfield number scroll_progress
|
||||
@ -25,13 +25,13 @@
|
||||
-- @tfield number last_index
|
||||
|
||||
--- Event triggered when scroll progress is changed; event(self, progress_value)
|
||||
-- @tfield DruidEvent on_scroll_progress_change @{DruidEvent}
|
||||
-- @tfield DruidEvent on_scroll_progress_change DruidEvent
|
||||
|
||||
---On DataList visual element created Event callback(self, index, node, instance)
|
||||
-- @tfield DruidEvent on_element_add @{DruidEvent}
|
||||
-- @tfield DruidEvent on_element_add DruidEvent
|
||||
|
||||
---On DataList visual element created Event callback(self, index)
|
||||
-- @tfield DruidEvent on_element_remove @{DruidEvent}
|
||||
-- @tfield DruidEvent on_element_remove DruidEvent
|
||||
|
||||
---
|
||||
|
||||
@ -40,15 +40,27 @@ local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
local Event = require("druid.event")
|
||||
|
||||
local DataList = component.create("data_list")
|
||||
---@class druid.data_list: druid.base_component
|
||||
---@field scroll druid.scroll
|
||||
---@field grid druid.grid
|
||||
---@field on_scroll_progress_change druid.event
|
||||
---@field on_element_add druid.event
|
||||
---@field on_element_remove druid.event
|
||||
---@field private _create_function function
|
||||
---@field private _is_use_cache boolean
|
||||
---@field private _cache table
|
||||
---@field private _data table
|
||||
---@field private _data_visual table
|
||||
---@field private top_index number
|
||||
local M = component.create("data_list")
|
||||
|
||||
|
||||
--- The @{DataList} constructor
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam Scroll scroll The @{Scroll} instance for Data List component
|
||||
-- @tparam StaticGrid grid The @{StaticGrid} or @{DynamicGrid} instance for Data List component
|
||||
--- The DataList constructor
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam Scroll scroll The Scroll instance for Data List component
|
||||
-- @tparam StaticGrid grid The StaticGrid} or @{DynamicGrid instance for Data List component
|
||||
-- @tparam function create_function The create function callback(self, data, index, data_list). Function should return (node, [component])
|
||||
function DataList.init(self, scroll, grid, create_function)
|
||||
function M:init(scroll, grid, create_function)
|
||||
self.scroll = scroll
|
||||
self.grid = grid
|
||||
if self.grid.style then
|
||||
@ -75,28 +87,28 @@ end
|
||||
|
||||
|
||||
--- Druid System on_remove function
|
||||
-- @tparam DataList self @{DataList}
|
||||
function DataList.on_remove(self)
|
||||
-- @tparam DataList self DataList
|
||||
function M:on_remove()
|
||||
self:clear()
|
||||
self.scroll.on_scroll:unsubscribe(self._refresh, self)
|
||||
end
|
||||
|
||||
|
||||
--- Set refresh function for DataList component
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam boolean is_use_cache Use cache version of DataList. Requires make setup of components in on_element_add callback and clean in on_element_remove
|
||||
-- @treturn druid.data_list Current DataList instance
|
||||
function DataList.set_use_cache(self, is_use_cache)
|
||||
function M:set_use_cache(is_use_cache)
|
||||
self._is_use_cache = is_use_cache
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set new data set for DataList component
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam table data The new data array
|
||||
-- @treturn druid.data_list Current DataList instance
|
||||
function DataList.set_data(self, data)
|
||||
function M:set_data(data)
|
||||
self._data = data or {}
|
||||
self:_refresh()
|
||||
|
||||
@ -105,19 +117,19 @@ end
|
||||
|
||||
|
||||
--- Return current data from DataList component
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @treturn table The current data array
|
||||
function DataList.get_data(self)
|
||||
function M:get_data()
|
||||
return self._data
|
||||
end
|
||||
|
||||
|
||||
--- Add element to DataList. Currenly untested
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam table data
|
||||
-- @tparam number|nil index
|
||||
-- @tparam number|nil shift_policy The constant from const.SHIFT.*
|
||||
function DataList.add(self, data, index, shift_policy)
|
||||
function M:add(data, index, shift_policy)
|
||||
index = index or #self._data + 1
|
||||
shift_policy = shift_policy or const.SHIFT.RIGHT
|
||||
|
||||
@ -127,20 +139,20 @@ end
|
||||
|
||||
|
||||
--- Remove element from DataList. Currenly untested
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam number|nil index
|
||||
-- @tparam number|nil shift_policy The constant from const.SHIFT.*
|
||||
function DataList.remove(self, index, shift_policy)
|
||||
function M:remove(index, shift_policy)
|
||||
helper.remove_with_shift(self._data, index, shift_policy)
|
||||
self:_refresh()
|
||||
end
|
||||
|
||||
|
||||
--- Remove element from DataList by data value. Currenly untested
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam table data
|
||||
-- @tparam number|nil shift_policy The constant from const.SHIFT.*
|
||||
function DataList.remove_by_data(self, data, shift_policy)
|
||||
function M:remove_by_data(data, shift_policy)
|
||||
local index = helper.contains(self._data, data)
|
||||
if index then
|
||||
helper.remove_with_shift(self._data, index, shift_policy)
|
||||
@ -150,17 +162,17 @@ end
|
||||
|
||||
|
||||
--- Clear the DataList and refresh visuals
|
||||
-- @tparam DataList self @{DataList}
|
||||
function DataList.clear(self)
|
||||
-- @tparam DataList self DataList
|
||||
function M:clear()
|
||||
self._data = {}
|
||||
self:_refresh()
|
||||
end
|
||||
|
||||
|
||||
--- Return index for data value
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam table data
|
||||
function DataList.get_index(self, data)
|
||||
function M:get_index(data)
|
||||
for index, value in pairs(self._data) do
|
||||
if value == data then
|
||||
return index
|
||||
@ -172,9 +184,9 @@ end
|
||||
|
||||
|
||||
--- Return all currenly created nodes in DataList
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @treturn node[] List of created nodes
|
||||
function DataList.get_created_nodes(self)
|
||||
function M:get_created_nodes()
|
||||
local nodes = {}
|
||||
|
||||
for index, data in pairs(self._data_visual) do
|
||||
@ -186,9 +198,9 @@ end
|
||||
|
||||
|
||||
--- Return all currenly created components in DataList
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @treturn druid.base_component[] List of created nodes
|
||||
function DataList.get_created_components(self)
|
||||
function M:get_created_components()
|
||||
local components = {}
|
||||
|
||||
for index, data in pairs(self._data_visual) do
|
||||
@ -200,19 +212,19 @@ end
|
||||
|
||||
|
||||
--- Instant scroll to element with passed index
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam number index
|
||||
function DataList.scroll_to_index(self, index)
|
||||
function M:scroll_to_index(index)
|
||||
local pos = self.grid:get_pos(index)
|
||||
self.scroll:scroll_to(pos)
|
||||
end
|
||||
|
||||
|
||||
--- Add element at passed index using cache or create new
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam number index
|
||||
-- @local
|
||||
function DataList._add_at(self, index)
|
||||
function M:_add_at(index)
|
||||
if self._data_visual[index] then
|
||||
self:_remove_at(index)
|
||||
end
|
||||
@ -243,10 +255,10 @@ end
|
||||
|
||||
|
||||
--- Remove element from passed index and add it to cache if applicable
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @tparam number index
|
||||
-- @local
|
||||
function DataList._remove_at(self, index)
|
||||
function M:_remove_at(index)
|
||||
self.grid:remove(index, const.SHIFT.NO_SHIFT)
|
||||
|
||||
local visual_data = self._data_visual[index]
|
||||
@ -274,9 +286,9 @@ end
|
||||
|
||||
|
||||
--- Refresh all elements in DataList
|
||||
-- @tparam DataList self @{DataList}
|
||||
-- @tparam DataList self DataList
|
||||
-- @local
|
||||
function DataList._refresh(self)
|
||||
function M:_refresh()
|
||||
self.scroll:set_size(self.grid:get_size_for(#self._data))
|
||||
|
||||
local start_pos = -self.scroll.position --[[@as vector3]]
|
||||
@ -313,4 +325,4 @@ function DataList._refresh(self)
|
||||
end
|
||||
|
||||
|
||||
return DataList
|
||||
return M
|
||||
|
@ -1,427 +0,0 @@
|
||||
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Component to handle placing components in row
|
||||
--
|
||||
-- <a href="https://insality.github.io/druid/druid/index.html?example=general_grid" target="_blank"><b>Example Link</b></a>
|
||||
-- @module DynamicGrid
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.dynamic_grid
|
||||
|
||||
--- On item add callback(self, node, index)
|
||||
-- @tfield DruidEvent on_add_item @{DruidEvent}
|
||||
|
||||
--- On item remove callback(self, index)
|
||||
-- @tfield DruidEvent on_remove_item @{DruidEvent}
|
||||
|
||||
--- On item add or remove callback(self, index)
|
||||
-- @tfield DruidEvent on_change_items @{DruidEvent}
|
||||
|
||||
--- On grid clear callback(self)
|
||||
-- @tfield DruidEvent on_clear @{DruidEvent}
|
||||
|
||||
--- On update item positions callback(self)
|
||||
-- @tfield DruidEvent on_update_positions @{DruidEvent}
|
||||
|
||||
--- Parent gui node
|
||||
-- @tfield node parent
|
||||
|
||||
--- List of all grid elements. Contains from node, pos, size, pivot
|
||||
-- @tfield node[] nodes
|
||||
|
||||
--- The first index of node in grid
|
||||
-- @tfield number first_index
|
||||
|
||||
--- The last index of node in grid
|
||||
-- @tfield number last_index
|
||||
|
||||
--- Item size
|
||||
-- @tfield vector3 node_size
|
||||
|
||||
--- The size of item content
|
||||
-- @tfield vector4 border
|
||||
|
||||
---
|
||||
|
||||
local const = require("druid.const")
|
||||
local Event = require("druid.event")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local DynamicGrid = component.create("dynamic_grid")
|
||||
|
||||
|
||||
local SIDE_VECTORS = {
|
||||
LEFT = vmath.vector3(-1, 0, 0),
|
||||
RIGHT = vmath.vector3(1, 0, 0),
|
||||
TOP = vmath.vector3(0, -1, 0),
|
||||
BOT = vmath.vector3(0, 1, 0),
|
||||
}
|
||||
|
||||
local AVAILABLE_PIVOTS = {
|
||||
gui.PIVOT_N,
|
||||
gui.PIVOT_S,
|
||||
gui.PIVOT_W,
|
||||
gui.PIVOT_E,
|
||||
}
|
||||
|
||||
|
||||
--- The @{DynamicGrid} constructor
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @tparam node parent The gui node parent, where items will be placed
|
||||
function DynamicGrid.init(self, parent)
|
||||
self.parent = self:get_node(parent)
|
||||
|
||||
local parent_pivot = gui.get_pivot(self.parent)
|
||||
self.pivot = helper.get_pivot_offset(parent_pivot)
|
||||
|
||||
assert(helper.contains(AVAILABLE_PIVOTS, parent_pivot), const.ERRORS.GRID_DYNAMIC_ANCHOR)
|
||||
self.side = ((parent_pivot == gui.PIVOT_W or parent_pivot == gui.PIVOT_E)
|
||||
and const.SIDE.X or const.SIDE.Y)
|
||||
|
||||
self.nodes = {}
|
||||
self.border = vmath.vector4(0) -- Current grid content size
|
||||
|
||||
self.on_add_item = Event()
|
||||
self.on_remove_item = Event()
|
||||
self.on_change_items = Event()
|
||||
self.on_clear = Event()
|
||||
self.on_update_positions = Event()
|
||||
|
||||
self._set_position_function = gui.set_position
|
||||
end
|
||||
|
||||
|
||||
function DynamicGrid.on_layout_change(self)
|
||||
self:_update(true)
|
||||
end
|
||||
|
||||
|
||||
--- Return pos for grid node index
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @tparam number index The grid element index
|
||||
-- @tparam node node The node to be placed
|
||||
-- @tparam number|nil origin_index Index of nearby node
|
||||
-- @treturn vector3 node position
|
||||
function DynamicGrid.get_pos(self, index, node, origin_index)
|
||||
local origin_node = self.nodes[origin_index]
|
||||
|
||||
-- If anchor node is not exist, check around nodes
|
||||
if not origin_node then
|
||||
if self.nodes[index + 1] then
|
||||
origin_index = index + 1
|
||||
end
|
||||
if self.nodes[index - 1] then
|
||||
origin_index = index - 1
|
||||
end
|
||||
origin_node = self.nodes[origin_index]
|
||||
end
|
||||
|
||||
if not origin_node then
|
||||
assert(not self.first_index, "Dynamic Grid can't have gaps between nodes. Error on grid:add")
|
||||
|
||||
-- If not origin node, so it should be first element in the grid
|
||||
local size = helper.get_scaled_size(node)
|
||||
local pivot = const.PIVOTS[gui.get_pivot(node)]
|
||||
return vmath.vector3(
|
||||
size.x * pivot.x - size.x * self.pivot.x,
|
||||
size.y * pivot.y - size.y * self.pivot.y,
|
||||
0)
|
||||
end
|
||||
|
||||
if origin_node then
|
||||
-- Other nodes spawn from other side of the origin node
|
||||
local is_forward = origin_index < index
|
||||
local delta = is_forward and 1 or -1
|
||||
return self:_get_next_node_pos(index - delta, node, self:_get_side_vector(self.side, is_forward))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Add new node to the grid
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam number|nil index The node position. By default add as last node
|
||||
-- @tparam number|nil shift_policy How shift nodes, if required. Default: const.SHIFT.RIGHT
|
||||
-- @tparam boolean|nil is_instant If true, update node positions instantly
|
||||
function DynamicGrid.add(self, node, index, shift_policy, is_instant)
|
||||
shift_policy = shift_policy or const.SHIFT.RIGHT
|
||||
local delta = shift_policy -- -1 or 1 or 0
|
||||
|
||||
-- By default add node at end
|
||||
index = index or ((self.last_index or 0) + 1)
|
||||
|
||||
-- If node exist at index place, shifting them
|
||||
local is_shift = self.nodes[index] and shift_policy ~= const.SHIFT.NO_SHIFT
|
||||
if is_shift then
|
||||
-- We need to iterate from index to start or end grid, depends of shift side
|
||||
local start_index = shift_policy == const.SHIFT.LEFT and self.first_index or self.last_index
|
||||
for i = start_index, index, -delta do
|
||||
self.nodes[i + delta] = self.nodes[i]
|
||||
end
|
||||
end
|
||||
|
||||
self:_add_node(node, index, index - delta)
|
||||
|
||||
-- After shifting we should recalc node poses
|
||||
if is_shift then
|
||||
-- We need to iterate from placed node to start or end grid, depends of shift side
|
||||
local target_index = shift_policy == const.SHIFT.LEFT and self.first_index or self.last_index
|
||||
for i = index + delta, target_index + delta, delta do
|
||||
local move_node = self.nodes[i]
|
||||
move_node.pos = self:get_pos(i, move_node.node, i - delta)
|
||||
end
|
||||
end
|
||||
|
||||
-- Sync grid data
|
||||
self:_update(is_instant)
|
||||
|
||||
self.on_add_item:trigger(self:get_context(), node, index)
|
||||
self.on_change_items:trigger(self:get_context(), index)
|
||||
end
|
||||
|
||||
|
||||
--- Remove the item from the grid. Note that gui node will be not deleted
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @tparam number index The grid node index to remove
|
||||
-- @tparam number|nil shift_policy How shift nodes, if required. Default: const.SHIFT.RIGHT
|
||||
-- @tparam boolean|nil is_instant If true, update node positions instantly
|
||||
-- @treturn node The deleted gui node from grid
|
||||
function DynamicGrid.remove(self, index, shift_policy, is_instant)
|
||||
shift_policy = shift_policy or const.SHIFT.RIGHT
|
||||
local delta = shift_policy -- -1 or 1 or 0
|
||||
|
||||
assert(self.nodes[index], "No grid item at given index " .. index)
|
||||
|
||||
-- Just set nil for delete node data
|
||||
local removed_node = self.nodes[index].node
|
||||
self.nodes[index] = nil
|
||||
|
||||
-- After delete node, we should shift nodes and recalc their poses, depends from is_shift_left
|
||||
if shift_policy ~= const.SHIFT.NO_SHIFT then
|
||||
local target_index = shift_policy == const.SHIFT.LEFT and self.first_index or self.last_index
|
||||
for i = index, target_index, delta do
|
||||
self.nodes[i] = self.nodes[i + delta]
|
||||
if self.nodes[i] then
|
||||
self.nodes[i].pos = self:get_pos(i, self.nodes[i].node, i - delta)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Sync grid data
|
||||
self:_update(is_instant)
|
||||
|
||||
self.on_remove_item:trigger(self:get_context(), index)
|
||||
self.on_change_items:trigger(self:get_context(), index)
|
||||
|
||||
return removed_node
|
||||
end
|
||||
|
||||
|
||||
--- Return grid content size
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @tparam vector3 border
|
||||
-- @treturn vector3 The grid content size
|
||||
function DynamicGrid.get_size(self, border)
|
||||
border = border or self.border
|
||||
return vmath.vector3(
|
||||
border.z - border.x,
|
||||
border.y - border.w,
|
||||
0)
|
||||
end
|
||||
|
||||
|
||||
--- Return DynamicGrid offset, where DynamicGrid content starts.
|
||||
-- @tparam DynamicGrid self @{DynamicGrid} The DynamicGrid instance
|
||||
-- @treturn vector3 The DynamicGrid offset
|
||||
function DynamicGrid.get_offset(self)
|
||||
local size = self:get_size()
|
||||
local borders = self:get_borders()
|
||||
local offset = vmath.vector3(
|
||||
(borders.z + borders.x)/2 + size.x * self.pivot.x,
|
||||
(borders.y + borders.w)/2 + size.y * self.pivot.y,
|
||||
0)
|
||||
|
||||
return offset
|
||||
end
|
||||
|
||||
|
||||
--- Return grid content borders
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @treturn vector3 The grid content borders
|
||||
function DynamicGrid.get_borders(self)
|
||||
return self.border
|
||||
end
|
||||
|
||||
|
||||
--- Return grid index by node
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @tparam node node The gui node in the grid
|
||||
-- @treturn number The node index
|
||||
function DynamicGrid.get_index_by_node(self, node)
|
||||
for index, node_info in pairs(self.nodes) do
|
||||
if node == node_info.node then
|
||||
return index
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Return array of all node positions
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @treturn vector3[] All grid node positions
|
||||
function DynamicGrid.get_all_pos(self)
|
||||
local result = {}
|
||||
for i, node in pairs(self.nodes) do
|
||||
table.insert(result, gui.get_position(node.node))
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
--- Change set position function for grid nodes. It will call on
|
||||
-- update poses on grid elements. Default: gui.set_position
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @tparam function callback Function on node set position
|
||||
-- @treturn druid.dynamic_grid Current grid instance
|
||||
function DynamicGrid.set_position_function(self, callback)
|
||||
self._set_position_function = callback or gui.set_position
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Clear grid nodes array. GUI nodes will be not deleted!
|
||||
-- If you want to delete GUI nodes, use dynamic_grid.nodes array before grid:clear
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @treturn druid.dynamic_grid Current grid instance
|
||||
function DynamicGrid.clear(self)
|
||||
self.nodes = {}
|
||||
self:_update()
|
||||
|
||||
self.on_clear:trigger(self:get_context())
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function DynamicGrid._add_node(self, node, index, origin_index)
|
||||
self.nodes[index] = {
|
||||
node = node,
|
||||
pos = self:get_pos(index, node, origin_index),
|
||||
size = helper.get_scaled_size(node),
|
||||
pivot = const.PIVOTS[gui.get_pivot(node)]
|
||||
}
|
||||
|
||||
-- Add new item instantly in new pos
|
||||
gui.set_parent(node, self.parent)
|
||||
gui.set_position(node, self.nodes[index].pos)
|
||||
end
|
||||
|
||||
|
||||
--- Update grid inner state
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @tparam boolean|nil is_instant If true, node position update instantly, otherwise with set_position_function callback
|
||||
-- @local
|
||||
function DynamicGrid._update(self, is_instant)
|
||||
self:_update_indexes()
|
||||
self:_update_borders()
|
||||
self:_update_pos(is_instant)
|
||||
end
|
||||
|
||||
|
||||
--- Update first and last indexes of grid nodes
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @local
|
||||
function DynamicGrid._update_indexes(self)
|
||||
self.first_index = nil
|
||||
self.last_index = nil
|
||||
for index in pairs(self.nodes) do
|
||||
self.first_index = self.first_index or index
|
||||
self.last_index = self.last_index or index
|
||||
|
||||
self.first_index = math.min(self.first_index, index)
|
||||
self.last_index = math.max(self.last_index, index)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Update grid content borders, recalculate min and max values
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @local
|
||||
function DynamicGrid._update_borders(self)
|
||||
if not self.first_index then
|
||||
self.border = vmath.vector4(0)
|
||||
return
|
||||
end
|
||||
|
||||
self.border = vmath.vector4(math.huge, -math.huge, -math.huge, math.huge)
|
||||
|
||||
for index, node in pairs(self.nodes) do
|
||||
local pos = node.pos
|
||||
local size = node.size
|
||||
local pivot = node.pivot
|
||||
|
||||
local left = pos.x - size.x/2 - (size.x * pivot.x)
|
||||
local right = pos.x + size.x/2 - (size.x * pivot.x)
|
||||
local top = pos.y + size.y/2 - (size.y * pivot.y)
|
||||
local bottom = pos.y - size.y/2 - (size.y * pivot.y)
|
||||
|
||||
self.border.x = math.min(self.border.x, left)
|
||||
self.border.y = math.max(self.border.y, top)
|
||||
self.border.z = math.max(self.border.z, right)
|
||||
self.border.w = math.min(self.border.w, bottom)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Update grid nodes position
|
||||
-- @tparam DynamicGrid self @{DynamicGrid}
|
||||
-- @tparam boolean|nil is_instant If true, node position update instantly, otherwise with set_position_function callback
|
||||
-- @local
|
||||
function DynamicGrid._update_pos(self, is_instant)
|
||||
for index, node in pairs(self.nodes) do
|
||||
if is_instant then
|
||||
gui.set_position(node.node, node.pos)
|
||||
else
|
||||
self._set_position_function(node.node, node.pos)
|
||||
end
|
||||
end
|
||||
|
||||
self.on_update_positions:trigger(self:get_context())
|
||||
end
|
||||
|
||||
|
||||
function DynamicGrid._get_next_node_pos(self, origin_node_index, new_node, place_side)
|
||||
local node = self.nodes[origin_node_index]
|
||||
|
||||
local new_node_size = helper.get_scaled_size(new_node)
|
||||
local new_pivot = const.PIVOTS[gui.get_pivot(new_node)]
|
||||
|
||||
local dist_x = (node.size.x/2 + new_node_size.x/2) * place_side.x
|
||||
local dist_y = (node.size.y/2 + new_node_size.y/2) * place_side.y
|
||||
local node_center_x = node.pos.x - node.size.x * node.pivot.x
|
||||
local node_center_y = node.pos.y - node.size.y * node.pivot.y
|
||||
|
||||
return vmath.vector3(
|
||||
node_center_x + dist_x + new_node_size.x * new_pivot.x,
|
||||
node_center_y - dist_y + new_node_size.y * new_pivot.y,
|
||||
0
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
--- Return side vector to correct node shifting
|
||||
function DynamicGrid._get_side_vector(self, side, is_forward)
|
||||
if side == const.SIDE.X then
|
||||
return is_forward and SIDE_VECTORS.RIGHT or SIDE_VECTORS.LEFT
|
||||
end
|
||||
|
||||
if side == const.SIDE.Y then
|
||||
return is_forward and SIDE_VECTORS.BOT or SIDE_VECTORS.TOP
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return DynamicGrid
|
@ -8,10 +8,10 @@
|
||||
-- @alias druid.hotkey
|
||||
|
||||
--- On hotkey released callback(self, argument)
|
||||
-- @tfield DruidEvent on_hotkey_pressed @{DruidEvent}
|
||||
-- @tfield DruidEvent on_hotkey_pressed DruidEvent
|
||||
|
||||
--- On hotkey released callback(self, argument)
|
||||
-- @tfield DruidEvent on_hotkey_released @{DruidEvent}
|
||||
-- @tfield DruidEvent on_hotkey_released DruidEvent
|
||||
|
||||
--- Visual node
|
||||
-- @tfield node node
|
||||
@ -20,7 +20,7 @@
|
||||
-- @tfield node|nil click_node
|
||||
|
||||
--- Button component from click_node
|
||||
-- @tfield Button button @{Button}
|
||||
-- @tfield Button button Button
|
||||
|
||||
---
|
||||
|
||||
@ -28,15 +28,21 @@ local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
local Event = require("druid.event")
|
||||
|
||||
local Hotkey = component.create("hotkey")
|
||||
---@class druid.hotkey: druid.base_component
|
||||
---@field on_hotkey_pressed druid.event
|
||||
---@field on_hotkey_released druid.event
|
||||
---@field style table
|
||||
---@field private _hotkeys table
|
||||
---@field private _modificators table
|
||||
local M = component.create("hotkey")
|
||||
|
||||
|
||||
--- The @{Hotkey} constructor
|
||||
-- @tparam Hotkey self @{Hotkey}
|
||||
--- The Hotkey constructor
|
||||
-- @tparam Hotkey self Hotkey
|
||||
-- @tparam string[]|string keys The keys to be pressed for trigger callback. Should contains one key and any modificator keys
|
||||
-- @tparam function callback The callback function
|
||||
-- @tparam any|nil callback_argument The argument to pass into the callback function
|
||||
function Hotkey.init(self, keys, callback, callback_argument)
|
||||
function M:init(keys, callback, callback_argument)
|
||||
self.druid = self:get_druid()
|
||||
|
||||
self._hotkeys = {}
|
||||
@ -56,7 +62,7 @@ end
|
||||
-- or create your own style
|
||||
-- @table style
|
||||
-- @tfield string[] MODIFICATORS The list of action_id as hotkey modificators
|
||||
function Hotkey.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.MODIFICATORS = style.MODIFICATORS or {}
|
||||
|
||||
@ -67,11 +73,11 @@ end
|
||||
|
||||
|
||||
--- Add hotkey for component callback
|
||||
-- @tparam Hotkey self @{Hotkey}
|
||||
-- @tparam Hotkey self Hotkey
|
||||
-- @tparam string[]|hash[]|string|hash keys that have to be pressed before key pressed to activate
|
||||
-- @tparam any|nil callback_argument The argument to pass into the callback function
|
||||
-- @treturn Hotkey Current instance
|
||||
function Hotkey.add_hotkey(self, keys, callback_argument)
|
||||
function M:add_hotkey(keys, callback_argument)
|
||||
keys = keys or {}
|
||||
if type(keys) == "string" then
|
||||
keys = { keys }
|
||||
@ -110,14 +116,14 @@ function Hotkey.add_hotkey(self, keys, callback_argument)
|
||||
end
|
||||
|
||||
|
||||
function Hotkey.on_focus_gained(self)
|
||||
function M:on_focus_gained()
|
||||
for k, v in pairs(self._modificators) do
|
||||
self._modificators[k] = false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Hotkey.on_input(self, action_id, action)
|
||||
function M:on_input(action_id, action)
|
||||
if not action_id or #self._hotkeys == 0 then
|
||||
return false
|
||||
end
|
||||
@ -168,13 +174,13 @@ end
|
||||
|
||||
|
||||
--- If true, the callback will be triggered on action.repeated
|
||||
-- @tparam Hotkey self @{Hotkey}
|
||||
-- @tparam Hotkey self Hotkey
|
||||
-- @tparam bool is_enabled_repeated The flag value
|
||||
-- @treturn Hotkey
|
||||
function Hotkey.set_repeat(self, is_enabled_repeated)
|
||||
function M:set_repeat(is_enabled_repeated)
|
||||
self._is_process_repeated = is_enabled_repeated
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
return Hotkey
|
||||
return M
|
||||
|
@ -10,25 +10,25 @@
|
||||
-- @alias druid.input
|
||||
|
||||
--- On input field select callback(self, input_instance)
|
||||
-- @tfield DruidEvent on_input_select @{DruidEvent}
|
||||
-- @tfield DruidEvent on_input_select DruidEvent
|
||||
|
||||
--- On input field unselect callback(self, input_text, input_instance)
|
||||
-- @tfield DruidEvent on_input_unselect @{DruidEvent}
|
||||
-- @tfield DruidEvent on_input_unselect DruidEvent
|
||||
|
||||
--- On input field text change callback(self, input_text)
|
||||
-- @tfield DruidEvent on_input_text @{DruidEvent}
|
||||
-- @tfield DruidEvent on_input_text DruidEvent
|
||||
|
||||
--- On input field text change to empty string callback(self, input_text)
|
||||
-- @tfield DruidEvent on_input_empty @{DruidEvent}
|
||||
-- @tfield DruidEvent on_input_empty DruidEvent
|
||||
|
||||
--- On input field text change to max length string callback(self, input_text)
|
||||
-- @tfield DruidEvent on_input_full @{DruidEvent}
|
||||
-- @tfield DruidEvent on_input_full DruidEvent
|
||||
|
||||
--- On trying user input with not allowed character callback(self, params, input_text)
|
||||
-- @tfield DruidEvent on_input_wrong @{DruidEvent}
|
||||
-- @tfield DruidEvent on_input_wrong DruidEvent
|
||||
|
||||
--- On cursor position change callback(self, cursor_index, start_index, end_index)
|
||||
-- @tfield DruidEvent on_select_cursor_change @{DruidEvent}
|
||||
-- @tfield DruidEvent on_select_cursor_change DruidEvent
|
||||
|
||||
--- The cursor index. The index of letter cursor after. Leftmost cursor - 0
|
||||
-- @tfield number cursor_index
|
||||
@ -40,7 +40,7 @@
|
||||
-- @tfield number end_index
|
||||
|
||||
--- Text component
|
||||
-- @tfield Text text @{Text}
|
||||
-- @tfield Text text Text
|
||||
|
||||
--- Current input value
|
||||
-- @tfield string value
|
||||
@ -61,7 +61,7 @@
|
||||
-- @tfield number marked_text_width
|
||||
|
||||
--- Button component
|
||||
-- @tfield Button button @{Button}
|
||||
-- @tfield Button button Button
|
||||
|
||||
--- Is current input selected now
|
||||
-- @tfield boolean is_selected
|
||||
@ -87,9 +87,19 @@ local component = require("druid.component")
|
||||
local utf8_lua = require("druid.system.utf8")
|
||||
local utf8 = utf8 or utf8_lua
|
||||
|
||||
local Input = component.create("input")
|
||||
---@class druid.input: druid.base_component
|
||||
---@field on_input_select druid.event
|
||||
---@field on_input_unselect druid.event
|
||||
---@field on_input_text druid.event
|
||||
---@field on_input_empty druid.event
|
||||
---@field on_input_full druid.event
|
||||
---@field on_input_wrong druid.event
|
||||
---@field on_select_cursor_change druid.event
|
||||
---@field style table
|
||||
---@field text druid.text
|
||||
local M = component.create("input")
|
||||
|
||||
Input.ALLOWED_ACTIONS = {
|
||||
M.ALLOWED_ACTIONS = {
|
||||
[const.ACTION_TOUCH] = true,
|
||||
[const.ACTION_TEXT] = true,
|
||||
[const.ACTION_MARKED_TEXT] = true,
|
||||
@ -132,7 +142,7 @@ end
|
||||
-- @tfield function on_select (self, button_node) Callback on input field selecting
|
||||
-- @tfield function on_unselect (self, button_node) Callback on input field unselecting
|
||||
-- @tfield function on_input_wrong (self, button_node) Callback on wrong user input
|
||||
function Input.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
|
||||
self.style.IS_LONGTAP_ERASE = style.IS_LONGTAP_ERASE or false
|
||||
@ -145,12 +155,12 @@ function Input.on_style_change(self, style)
|
||||
end
|
||||
|
||||
|
||||
--- The @{Input} constructor
|
||||
-- @tparam Input self @{Input}
|
||||
--- The Input constructor
|
||||
-- @tparam Input self Input
|
||||
-- @tparam node click_node Node to enabled input component
|
||||
-- @tparam node|Text text_node Text node what will be changed on user input. You can pass text component instead of text node name @{Text}
|
||||
-- @tparam node|Text text_node Text node what will be changed on user input. You can pass text component instead of text node name Text
|
||||
-- @tparam number|nil keyboard_type Gui keyboard type for input field
|
||||
function Input.init(self, click_node, text_node, keyboard_type)
|
||||
function M:init(click_node, text_node, keyboard_type)
|
||||
self.druid = self:get_druid()
|
||||
|
||||
if type(text_node) == "table" then
|
||||
@ -201,8 +211,8 @@ function Input.init(self, click_node, text_node, keyboard_type)
|
||||
end
|
||||
|
||||
|
||||
function Input.on_input(self, action_id, action)
|
||||
if not (action_id == nil or Input.ALLOWED_ACTIONS[action_id]) then
|
||||
function M:on_input(action_id, action)
|
||||
if not (action_id == nil or M.ALLOWED_ACTIONS[action_id]) then
|
||||
return false
|
||||
end
|
||||
|
||||
@ -299,17 +309,17 @@ function Input.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
function Input.on_focus_lost(self)
|
||||
function M:on_focus_lost()
|
||||
self:unselect()
|
||||
end
|
||||
|
||||
|
||||
function Input.on_input_interrupt(self)
|
||||
function M:on_input_interrupt()
|
||||
--self:unselect()
|
||||
end
|
||||
|
||||
|
||||
function Input.get_text_selected(self)
|
||||
function M:get_text_selected()
|
||||
if self.start_index == self.end_index then
|
||||
return self.value
|
||||
end
|
||||
@ -318,10 +328,10 @@ function Input.get_text_selected(self)
|
||||
end
|
||||
|
||||
--- Replace selected text with new text
|
||||
-- @tparam Input self @{Input}
|
||||
-- @tparam Input self Input
|
||||
-- @tparam string text The text to replace selected text
|
||||
-- @treturn string New input text
|
||||
function Input.get_text_selected_replaced(self, text)
|
||||
function M:get_text_selected_replaced(text)
|
||||
local left_part = utf8.sub(self.value, 1, self.start_index)
|
||||
local right_part = utf8.sub(self.value, self.end_index + 1, utf8.len(self.value))
|
||||
local result = left_part .. text .. right_part
|
||||
@ -336,9 +346,9 @@ end
|
||||
|
||||
|
||||
--- Set text for input field
|
||||
-- @tparam Input self @{Input}
|
||||
-- @tparam Input self Input
|
||||
-- @tparam string input_text The string to apply for input field
|
||||
function Input.set_text(self, input_text)
|
||||
function M:set_text(input_text)
|
||||
input_text = tostring(input_text or "")
|
||||
|
||||
-- Case when update with marked text
|
||||
@ -385,8 +395,8 @@ end
|
||||
|
||||
|
||||
--- Select input field. It will show the keyboard and trigger on_select events
|
||||
-- @tparam Input self @{Input}
|
||||
function Input.select(self)
|
||||
-- @tparam Input self Input
|
||||
function M:select()
|
||||
gui.reset_keyboard()
|
||||
self.marked_value = ""
|
||||
if not self.is_selected then
|
||||
@ -410,8 +420,8 @@ end
|
||||
|
||||
|
||||
--- Remove selection from input. It will hide the keyboard and trigger on_unselect events
|
||||
-- @tparam Input self @{Input}
|
||||
function Input.unselect(self)
|
||||
-- @tparam Input self Input
|
||||
function M:unselect()
|
||||
gui.reset_keyboard()
|
||||
self.marked_value = ""
|
||||
self.value = self.current_value
|
||||
@ -429,9 +439,9 @@ end
|
||||
|
||||
|
||||
--- Return current input field text
|
||||
-- @tparam Input self @{Input}
|
||||
-- @tparam Input self Input
|
||||
-- @treturn string The current input field text
|
||||
function Input.get_text(self)
|
||||
function M:get_text()
|
||||
if self.marked_value ~= "" then
|
||||
return self.value .. self.marked_value
|
||||
end
|
||||
@ -442,10 +452,10 @@ end
|
||||
|
||||
--- Set maximum length for input field.
|
||||
-- Pass nil to make input field unliminted (by default)
|
||||
-- @tparam Input self @{Input}
|
||||
-- @tparam Input self Input
|
||||
-- @tparam number max_length Maximum length for input text field
|
||||
-- @treturn druid.input Current input instance
|
||||
function Input.set_max_length(self, max_length)
|
||||
function M:set_max_length(max_length)
|
||||
self.max_length = max_length
|
||||
return self
|
||||
end
|
||||
@ -454,19 +464,19 @@ end
|
||||
--- Set allowed charaters for input field.
|
||||
-- See: https://defold.com/ref/stable/string/
|
||||
-- ex: [%a%d] for alpha and numeric
|
||||
-- @tparam Input self @{Input}
|
||||
-- @tparam Input self Input
|
||||
-- @tparam string characters Regulax exp. for validate user input
|
||||
-- @treturn druid.input Current input instance
|
||||
function Input.set_allowed_characters(self, characters)
|
||||
function M:set_allowed_characters(characters)
|
||||
self.allowed_characters = characters
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Reset current input selection and return previous value
|
||||
-- @tparam Input self @{Input}
|
||||
-- @tparam Input self Input
|
||||
-- @treturn druid.input Current input instance
|
||||
function Input.reset_changes(self)
|
||||
function M:reset_changes()
|
||||
self:set_text(self.previous_value)
|
||||
self:unselect()
|
||||
return self
|
||||
@ -474,12 +484,12 @@ end
|
||||
|
||||
|
||||
--- Set cursor position in input field
|
||||
-- @tparam Input self @{Input}
|
||||
-- @tparam Input self Input
|
||||
-- @tparam number|nil cursor_index Cursor index for cursor position, if nil - will be set to the end of the text
|
||||
-- @tparam number|nil start_index Start index for cursor position, if nil - will be set to the end of the text
|
||||
-- @tparam number|nil end_index End index for cursor position, if nil - will be set to the start_index
|
||||
-- @treturn druid.input Current input instance
|
||||
function Input.select_cursor(self, cursor_index, start_index, end_index)
|
||||
function M:select_cursor(cursor_index, start_index, end_index)
|
||||
local len = utf8.len(self.value)
|
||||
|
||||
self.cursor_index = cursor_index or len
|
||||
@ -497,11 +507,11 @@ end
|
||||
|
||||
|
||||
--- Change cursor position by delta
|
||||
-- @tparam Input self @{Input}
|
||||
-- @tparam Input self Input
|
||||
-- @tparam number delta side for cursor position, -1 for left, 1 for right
|
||||
-- @tparam boolean is_add_to_selection (Shift key)
|
||||
-- @tparam boolean is_move_to_end (Ctrl key)
|
||||
function Input.move_selection(self, delta, is_add_to_selection, is_move_to_end)
|
||||
function M:move_selection(delta, is_add_to_selection, is_move_to_end)
|
||||
local len = utf8.len(self.value)
|
||||
local cursor_index = self.cursor_index
|
||||
local start_index, end_index -- if nil, the selection will be 0 at cursor position
|
||||
@ -559,4 +569,4 @@ function Input.move_selection(self, delta, is_add_to_selection, is_move_to_end)
|
||||
end
|
||||
|
||||
|
||||
return Input
|
||||
return M
|
||||
|
@ -18,10 +18,10 @@
|
||||
-- @alias druid.lang_text
|
||||
|
||||
--- On change text callback
|
||||
-- @tfield DruidEvent on_change @{DruidEvent}
|
||||
-- @tfield DruidEvent on_change DruidEvent
|
||||
|
||||
--- The text component
|
||||
-- @tfield Text text @{Text}
|
||||
-- @tfield Text text Text
|
||||
|
||||
--- Text node
|
||||
-- @tfield node node
|
||||
@ -32,15 +32,21 @@ local Event = require("druid.event")
|
||||
local settings = require("druid.system.settings")
|
||||
local component = require("druid.component")
|
||||
|
||||
local LangText = component.create("lang_text")
|
||||
---@class druid.lang_text: druid.base_component
|
||||
---@field text druid.text
|
||||
---@field node node
|
||||
---@field on_change druid.event
|
||||
---@field private last_locale_args table
|
||||
---@field private last_locale string
|
||||
local M = component.create("lang_text")
|
||||
|
||||
|
||||
--- The @{LangText} constructor
|
||||
-- @tparam LangText self @{LangText}
|
||||
--- The LangText constructor
|
||||
-- @tparam LangText self LangText
|
||||
-- @tparam string|node node The node_id or gui.get_node(node_id)
|
||||
-- @tparam string|nil locale_id Default locale id or text from node as default
|
||||
-- @tparam string|nil adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
|
||||
function LangText.init(self, node, locale_id, adjust_type)
|
||||
function M:init(node, locale_id, adjust_type)
|
||||
self.druid = self:get_druid()
|
||||
self.text = self.druid:new_text(node, locale_id, adjust_type)
|
||||
self.node = self.text.node
|
||||
@ -55,7 +61,7 @@ function LangText.init(self, node, locale_id, adjust_type)
|
||||
end
|
||||
|
||||
|
||||
function LangText.on_language_change(self)
|
||||
function M:on_language_change()
|
||||
if self.last_locale then
|
||||
self:translate(self.last_locale, unpack(self.last_locale_args))
|
||||
end
|
||||
@ -63,10 +69,10 @@ end
|
||||
|
||||
|
||||
--- Setup raw text to lang_text component
|
||||
-- @tparam LangText self @{LangText}
|
||||
-- @tparam LangText self LangText
|
||||
-- @tparam string text Text for text node
|
||||
-- @treturn LangText Current instance
|
||||
function LangText.set_to(self, text)
|
||||
function M:set_to(text)
|
||||
self.last_locale = false
|
||||
self.text:set_to(text)
|
||||
self.on_change:trigger()
|
||||
@ -76,7 +82,7 @@ end
|
||||
|
||||
|
||||
--- Translate the text by locale_id
|
||||
-- @tparam LangText self @{LangText}
|
||||
-- @tparam LangText self LangText
|
||||
-- @tparam string locale_id Locale id
|
||||
-- @tparam string|nil a Optional param to string.format
|
||||
-- @tparam string|nil b Optional param to string.format
|
||||
@ -86,7 +92,7 @@ end
|
||||
-- @tparam string|nil f Optional param to string.format
|
||||
-- @tparam string|nil g Optional param to string.format
|
||||
-- @treturn LangText Current instance
|
||||
function LangText.translate(self, locale_id, a, b, c, d, e, f, g)
|
||||
function M:translate(locale_id, a, b, c, d, e, f, g)
|
||||
self.last_locale_args = { a, b, c, d, e, f, g }
|
||||
self.last_locale = locale_id or self.last_locale
|
||||
self.text:set_to(settings.get_text(self.last_locale, a, b, c, d, e, f, g) or "")
|
||||
@ -96,7 +102,7 @@ end
|
||||
|
||||
|
||||
--- Format string with new text params on localized text
|
||||
-- @tparam LangText self @{LangText}
|
||||
-- @tparam LangText self LangText
|
||||
-- @tparam string|nil a Optional param to string.format
|
||||
-- @tparam string|nil b Optional param to string.format
|
||||
-- @tparam string|nil c Optional param to string.format
|
||||
@ -105,11 +111,11 @@ end
|
||||
-- @tparam string|nil f Optional param to string.format
|
||||
-- @tparam string|nil g Optional param to string.format
|
||||
-- @treturn LangText Current instance
|
||||
function LangText.format(self, a, b, c, d, e, f, g)
|
||||
function M:format(a, b, c, d, e, f, g)
|
||||
self.last_locale_args = { a, b, c, d, e, f, g }
|
||||
self.text:set_to(settings.get_text(self.last_locale, a, b, c, d, e, f, g) or "")
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
return LangText
|
||||
return M
|
||||
|
@ -1,45 +1,41 @@
|
||||
-- Copyright (c) 2024 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Layout management on node
|
||||
--
|
||||
-- <a href="https://insality.github.io/druid/druid/index.html?example=general_layout" target="_blank"><b>Example Link</b></a>
|
||||
-- @module Layout
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.layout
|
||||
|
||||
--- Layout node
|
||||
-- @tfield node node
|
||||
|
||||
--- Current layout mode
|
||||
-- @tfield string mode
|
||||
|
||||
---
|
||||
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
-- @class druid.layout.row_data
|
||||
-- @tfield width number
|
||||
-- @tfield height number
|
||||
-- @tfield count number
|
||||
---@alias druid.layout.mode
|
||||
---| "horizontal" Elements are placed horizontally
|
||||
---| "vertical" Elements are placed vertically
|
||||
---| "horizontal_wrap" Elements are placed horizontally, but if the row width is greater than the parent width, the next row is created
|
||||
|
||||
-- @class druid.layout.rows_data
|
||||
-- @tfield total_width number
|
||||
-- @tfield total_height number
|
||||
-- @tfield nodes_width table<node, number>
|
||||
-- @tfield nodes_height table<node, number>
|
||||
-- @tfield rows druid.layout.row_data[]>
|
||||
---@class druid.layout.row_data
|
||||
---@field width number
|
||||
---@field height number
|
||||
---@field count number
|
||||
|
||||
-- @class druid.layout: druid.base_component
|
||||
---@class druid.layout.rows_data
|
||||
---@field total_width number
|
||||
---@field total_height number
|
||||
---@field nodes_width table<node, number>
|
||||
---@field nodes_height table<node, number>
|
||||
---@field rows druid.layout.row_data[]>
|
||||
|
||||
---@class druid.layout: druid.base_component
|
||||
---@field node node
|
||||
---@field is_dirty boolean
|
||||
---@field entities node[]
|
||||
---@field margin {x: number, y: number}
|
||||
---@field padding vector4
|
||||
---@field type string
|
||||
---@field is_resize_width boolean
|
||||
---@field is_resize_height boolean
|
||||
---@field is_justify boolean
|
||||
local M = component.create("layout")
|
||||
|
||||
-- The @{Layout} constructor
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam string layout_type The layout mode (from const.LAYOUT_MODE)
|
||||
-- @tparam function|nil on_size_changed_callback The callback on window resize
|
||||
function M.init(self, node, layout_type)
|
||||
self.node = self:get_node(node)
|
||||
---Layout component constructor
|
||||
---@local
|
||||
---@param node_or_node_id node|string
|
||||
---@param layout_type druid.layout.mode
|
||||
function M:init(node_or_node_id, layout_type)
|
||||
self.node = self:get_node(node_or_node_id)
|
||||
|
||||
self.is_dirty = true
|
||||
self.entities = {}
|
||||
@ -51,6 +47,8 @@ function M.init(self, node, layout_type)
|
||||
self.is_justify = false
|
||||
end
|
||||
|
||||
|
||||
---@local
|
||||
function M:update()
|
||||
if not self.is_dirty then
|
||||
return
|
||||
@ -60,11 +58,10 @@ function M:update()
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @tparam number|nil margin_x
|
||||
-- @tparam number|nil margin_y
|
||||
-- @treturn druid.layout @{Layout}
|
||||
function M.set_margin(self, margin_x, margin_y)
|
||||
---@param margin_x number|nil
|
||||
---@param margin_y number|nil
|
||||
---@return druid.layout
|
||||
function M:set_margin(margin_x, margin_y)
|
||||
self.margin.x = margin_x or self.margin.x
|
||||
self.margin.y = margin_y or self.margin.y
|
||||
self.is_dirty = true
|
||||
@ -73,10 +70,9 @@ function M.set_margin(self, margin_x, margin_y)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @tparam vector4 padding The vector4 with padding values, where x - left, y - top, z - right, w - bottom
|
||||
-- @treturn druid.layout @{Layout}
|
||||
function M.set_padding(self, padding)
|
||||
---@param padding vector4 The vector4 with padding values, where x - left, y - top, z - right, w - bottom
|
||||
---@return druid.layout
|
||||
function M:set_padding(padding)
|
||||
self.padding = padding
|
||||
self.is_dirty = true
|
||||
|
||||
@ -84,19 +80,17 @@ function M.set_padding(self, padding)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @treturn druid.layout @{Layout}
|
||||
function M.set_dirty(self)
|
||||
---@return druid.layout
|
||||
function M:set_dirty()
|
||||
self.is_dirty = true
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @tparam boolean is_justify
|
||||
-- @treturn druid.layout @{Layout}
|
||||
function M.set_justify(self, is_justify)
|
||||
---@param is_justify boolean
|
||||
---@return druid.layout
|
||||
function M:set_justify(is_justify)
|
||||
self.is_justify = is_justify
|
||||
self.is_dirty = true
|
||||
|
||||
@ -104,10 +98,9 @@ function M.set_justify(self, is_justify)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @tparam string type The layout type: "horizontal", "vertical", "horizontal_wrap"
|
||||
-- @treturn druid.layout @{Layout}
|
||||
function M.set_type(self, type)
|
||||
---@param type string The layout type: "horizontal", "vertical", "horizontal_wrap"
|
||||
---@return druid.layout
|
||||
function M:set_type(type)
|
||||
self.type = type
|
||||
self.is_dirty = true
|
||||
|
||||
@ -115,11 +108,10 @@ function M.set_type(self, type)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @tparam boolean is_hug_width
|
||||
-- @tparam boolean is_hug_height
|
||||
-- @treturn druid.layout @{Layout}
|
||||
function M.set_hug_content(self, is_hug_width, is_hug_height)
|
||||
---@param is_hug_width boolean
|
||||
---@param is_hug_height boolean
|
||||
---@return druid.layout
|
||||
function M:set_hug_content(is_hug_width, is_hug_height)
|
||||
self.is_resize_width = is_hug_width or false
|
||||
self.is_resize_height = is_hug_height or false
|
||||
self.is_dirty = true
|
||||
@ -128,21 +120,20 @@ function M.set_hug_content(self, is_hug_width, is_hug_height)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @tparam string|node node_or_node_id
|
||||
-- @treturn druid.layout @{Layout}
|
||||
function M.add(self, node_or_node_id)
|
||||
---@param node_or_node_id node|string node_or_node_id
|
||||
---@return druid.layout
|
||||
function M:add(node_or_node_id)
|
||||
-- Acquire node from entity or by id
|
||||
local node = node_or_node_id
|
||||
if type(node_or_node_id) == "table" then
|
||||
assert(node_or_node_id.node, "The entity should have a node")
|
||||
node = node_or_node_id.node
|
||||
else
|
||||
-- @cast node_or_node_id string|node
|
||||
---@cast node_or_node_id string|node
|
||||
node = self:get_node(node_or_node_id)
|
||||
end
|
||||
|
||||
-- @cast node node
|
||||
---@cast node node
|
||||
table.insert(self.entities, node)
|
||||
gui.set_parent(node, self.node)
|
||||
|
||||
@ -152,9 +143,8 @@ function M.add(self, node_or_node_id)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @treturn druid.layout @{Layout}
|
||||
function M.refresh_layout(self)
|
||||
---@return druid.layout
|
||||
function M:refresh_layout()
|
||||
local layout_node = self.node
|
||||
|
||||
local entities = self.entities
|
||||
@ -289,9 +279,8 @@ function M.refresh_layout(self)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- @treturn druid.layout @{Layout}
|
||||
function M.clear_layout(self)
|
||||
---@return druid.layout
|
||||
function M:clear_layout()
|
||||
for index = #self.entities, 1, -1 do
|
||||
self.entities[index] = nil
|
||||
end
|
||||
@ -302,10 +291,9 @@ function M.clear_layout(self)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam node node
|
||||
-- @treturn number, number
|
||||
-- @local
|
||||
function M.get_node_size(node)
|
||||
---@param node node
|
||||
---@return number, number
|
||||
function M:get_node_size(node)
|
||||
if not gui.is_enabled(node, false) then
|
||||
return 0, 0
|
||||
end
|
||||
@ -323,11 +311,10 @@ function M.get_node_size(node)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Layout self @{Layout}
|
||||
-- Calculate rows data for layout. Contains total width, height and rows info (width, height, count of elements in row)
|
||||
-- @treturn druid.layout.rows_data
|
||||
-- @local
|
||||
function M.calculate_rows_data(self)
|
||||
---Calculate rows data for layout. Contains total width, height and rows info (width, height, count of elements in row)
|
||||
---@local
|
||||
---@return druid.layout.rows_data
|
||||
function M:calculate_rows_data()
|
||||
local entities = self.entities
|
||||
local margin = self.margin
|
||||
local type = self.type
|
||||
@ -353,7 +340,7 @@ function M.calculate_rows_data(self)
|
||||
|
||||
-- Get node size if it's not calculated yet
|
||||
if not node_width or not node_height then
|
||||
node_width, node_height = M.get_node_size(node)
|
||||
node_width, node_height = self:get_node_size(node)
|
||||
rows_data.nodes_width[node] = node_width
|
||||
rows_data.nodes_height[node] = node_height
|
||||
end
|
||||
@ -407,11 +394,10 @@ function M.calculate_rows_data(self)
|
||||
end
|
||||
|
||||
|
||||
-- @tparam node node
|
||||
-- @tparam number x
|
||||
-- @tparam number y
|
||||
-- @treturn node
|
||||
-- @local
|
||||
---@param node node
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@return node
|
||||
function M:set_node_position(node, x, y)
|
||||
local position = gui.get_position(node)
|
||||
position.x = x
|
||||
|
@ -20,7 +20,7 @@
|
||||
-- @alias druid.progress
|
||||
|
||||
--- On progress bar change callback(self, new_value)
|
||||
-- @tfield DruidEvent on_change @{DruidEvent}
|
||||
-- @tfield DruidEvent on_change DruidEvent
|
||||
|
||||
--- Progress bar fill node
|
||||
-- @tfield node node
|
||||
@ -49,7 +49,13 @@ local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Progress = component.create("progress")
|
||||
---@class druid.progress: druid.base_component
|
||||
---@field node node
|
||||
---@field on_change druid.event
|
||||
---@field style table
|
||||
---@field key string
|
||||
---@field prop hash
|
||||
local M = component.create("progress")
|
||||
|
||||
|
||||
local function check_steps(self, from, to, exactly)
|
||||
@ -117,19 +123,19 @@ end
|
||||
-- @table style
|
||||
-- @tfield number|nil SPEED Progress bas fill rate. More -> faster. Default: 5
|
||||
-- @tfield number|nil MIN_DELTA Minimum step to fill progress bar. Default: 0.005
|
||||
function Progress.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.SPEED = style.SPEED or 5
|
||||
self.style.MIN_DELTA = style.MIN_DELTA or 0.005
|
||||
end
|
||||
|
||||
|
||||
--- The @{Progress} constructor
|
||||
-- @tparam Progress self @{Progress}
|
||||
--- The Progress constructor
|
||||
-- @tparam Progress self Progress
|
||||
-- @tparam string|node node Node name or GUI Node itself.
|
||||
-- @tparam string key Progress bar direction: const.SIDE.X or const.SIDE.Y
|
||||
-- @tparam number|nil init_value Initial value of progress bar. Default: 1
|
||||
function Progress.init(self, node, key, init_value)
|
||||
function M:init(node, key, init_value)
|
||||
assert(key == const.SIDE.X or const.SIDE.Y, "Progress bar key should be 'x' or 'y'")
|
||||
|
||||
self.key = key
|
||||
@ -155,18 +161,18 @@ function Progress.init(self, node, key, init_value)
|
||||
end
|
||||
|
||||
|
||||
function Progress.on_layout_change(self)
|
||||
function M:on_layout_change()
|
||||
self:set_to(self.last_value)
|
||||
end
|
||||
|
||||
|
||||
function Progress.on_remove(self)
|
||||
function M:on_remove()
|
||||
-- Return default size
|
||||
gui.set_size(self.node, self.max_size)
|
||||
end
|
||||
|
||||
|
||||
function Progress.update(self, dt)
|
||||
function M:update(dt)
|
||||
if self.target then
|
||||
local prev_value = self.last_value
|
||||
local step = math.abs(self.last_value - self.target) * (self.style.SPEED*dt)
|
||||
@ -187,51 +193,51 @@ end
|
||||
|
||||
|
||||
--- Fill a progress bar and stop progress animation
|
||||
-- @tparam Progress self @{Progress}
|
||||
function Progress.fill(self)
|
||||
-- @tparam Progress self Progress
|
||||
function M:fill()
|
||||
set_bar_to(self, 1, true)
|
||||
end
|
||||
|
||||
|
||||
--- Empty a progress bar
|
||||
-- @tparam Progress self @{Progress}
|
||||
function Progress.empty(self)
|
||||
-- @tparam Progress self Progress
|
||||
function M:empty()
|
||||
set_bar_to(self, 0, true)
|
||||
end
|
||||
|
||||
|
||||
--- Instant fill progress bar to value
|
||||
-- @tparam Progress self @{Progress}
|
||||
-- @tparam Progress self Progress
|
||||
-- @tparam number to Progress bar value, from 0 to 1
|
||||
function Progress.set_to(self, to)
|
||||
function M:set_to(to)
|
||||
to = helper.clamp(to, 0, 1)
|
||||
set_bar_to(self, to)
|
||||
end
|
||||
|
||||
|
||||
--- Return current progress bar value
|
||||
-- @tparam Progress self @{Progress}
|
||||
function Progress.get(self)
|
||||
-- @tparam Progress self Progress
|
||||
function M:get()
|
||||
return self.last_value
|
||||
end
|
||||
|
||||
|
||||
--- Set points on progress bar to fire the callback
|
||||
-- @tparam Progress self @{Progress}
|
||||
-- @tparam Progress self Progress
|
||||
-- @tparam number[] steps Array of progress bar values
|
||||
-- @tparam function callback Callback on intersect step value
|
||||
-- @usage progress:set_steps({0, 0.3, 0.6, 1}, function(self, step) end)
|
||||
function Progress.set_steps(self, steps, callback)
|
||||
function M:set_steps(steps, callback)
|
||||
self.steps = steps
|
||||
self.step_callback = callback
|
||||
end
|
||||
|
||||
|
||||
--- Start animation of a progress bar
|
||||
-- @tparam Progress self @{Progress}
|
||||
-- @tparam Progress self Progress
|
||||
-- @tparam number to value between 0..1
|
||||
-- @tparam function|nil callback Callback on animation ends
|
||||
function Progress.to(self, to, callback)
|
||||
function M:to(to, callback)
|
||||
to = helper.clamp(to, 0, 1)
|
||||
-- cause of float error
|
||||
local value = helper.round(to, 5)
|
||||
@ -247,14 +253,14 @@ end
|
||||
|
||||
|
||||
--- Set progress bar max node size
|
||||
-- @tparam Progress self @{Progress}
|
||||
-- @tparam Progress self Progress
|
||||
-- @tparam vector3 max_size The new node maximum (full) size
|
||||
-- @treturn Progress @{Progress}
|
||||
function Progress.set_max_size(self, max_size)
|
||||
-- @treturn Progress Progress
|
||||
function M:set_max_size(max_size)
|
||||
self.max_size[self.key] = max_size[self.key]
|
||||
self:set_to(self.last_value)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
return Progress
|
||||
return M
|
||||
|
@ -8,7 +8,7 @@
|
||||
-- @alias druid.slider
|
||||
|
||||
--- On change value callback(self, value)
|
||||
-- @tfield DruidEvent on_change_value @{DruidEvent}
|
||||
-- @tfield DruidEvent on_change_value DruidEvent
|
||||
|
||||
--- Slider pin node
|
||||
-- @tfield node node
|
||||
@ -42,7 +42,19 @@ local helper = require("druid.helper")
|
||||
local const = require("druid.const")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Slider = component.create("slider", const.PRIORITY_INPUT_HIGH)
|
||||
---@class druid.slider: druid.base_component
|
||||
---@field node node
|
||||
---@field on_change_value druid.event
|
||||
---@field style table
|
||||
---@field private start_pos vector3
|
||||
---@field private pos vector3
|
||||
---@field private target_pos vector3
|
||||
---@field private end_pos vector3
|
||||
---@field private dist vector3
|
||||
---@field private is_drag boolean
|
||||
---@field private value number
|
||||
---@field private steps number[]
|
||||
local M = component.create("slider", const.PRIORITY_INPUT_HIGH)
|
||||
|
||||
|
||||
local function on_change_value(self)
|
||||
@ -56,12 +68,12 @@ local function set_position(self, value)
|
||||
end
|
||||
|
||||
|
||||
--- The @{Slider} constructor
|
||||
-- @tparam Slider self @{Slider}
|
||||
--- The Slider constructor
|
||||
-- @tparam Slider self Slider
|
||||
-- @tparam node node Gui pin node
|
||||
-- @tparam vector3 end_pos The end position of slider
|
||||
-- @tparam function|nil callback On slider change callback
|
||||
function Slider.init(self, node, end_pos, callback)
|
||||
function M:init(node, end_pos, callback)
|
||||
self.node = self:get_node(node)
|
||||
|
||||
self.start_pos = gui.get_position(self.node)
|
||||
@ -81,18 +93,18 @@ function Slider.init(self, node, end_pos, callback)
|
||||
end
|
||||
|
||||
|
||||
function Slider.on_layout_change(self)
|
||||
function M:on_layout_change()
|
||||
self:set(self.value)
|
||||
end
|
||||
|
||||
|
||||
function Slider.on_remove(self)
|
||||
function M:on_remove()
|
||||
-- Return pin to start position
|
||||
gui.set_position(self.node, self.start_pos)
|
||||
end
|
||||
|
||||
|
||||
function Slider.on_window_resized(self)
|
||||
function M:on_window_resized()
|
||||
local x_koef, y_koef = helper.get_screen_aspect_koef()
|
||||
self._x_koef = x_koef
|
||||
self._y_koef = y_koef
|
||||
@ -100,7 +112,7 @@ function Slider.on_window_resized(self)
|
||||
end
|
||||
|
||||
|
||||
function Slider.on_input(self, action_id, action)
|
||||
function M:on_input(action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH then
|
||||
return false
|
||||
end
|
||||
@ -185,10 +197,10 @@ end
|
||||
|
||||
|
||||
--- Set value for slider
|
||||
-- @tparam Slider self @{Slider}
|
||||
-- @tparam Slider self Slider
|
||||
-- @tparam number value Value from 0 to 1
|
||||
-- @tparam boolean|nil is_silent Don't trigger event if true
|
||||
function Slider.set(self, value, is_silent)
|
||||
function M:set(value, is_silent)
|
||||
value = helper.clamp(value, 0, 1)
|
||||
set_position(self, value)
|
||||
self.value = value
|
||||
@ -200,11 +212,11 @@ end
|
||||
|
||||
--- Set slider steps. Pin node will
|
||||
-- apply closest step position
|
||||
-- @tparam Slider self @{Slider}
|
||||
-- @tparam Slider self Slider
|
||||
-- @tparam number[] steps Array of steps
|
||||
-- @usage slider:set_steps({0, 0.2, 0.6, 1})
|
||||
-- @treturn Slider @{Slider}
|
||||
function Slider.set_steps(self, steps)
|
||||
-- @treturn Slider Slider
|
||||
function M:set_steps(steps)
|
||||
self.steps = steps
|
||||
return self
|
||||
end
|
||||
@ -214,29 +226,29 @@ end
|
||||
-- User can touch any place of node, pin instantly will
|
||||
-- move at this position and node drag will start.
|
||||
-- This function require the Defold version 1.3.0+
|
||||
-- @tparam Slider self @{Slider}
|
||||
-- @tparam Slider self Slider
|
||||
-- @tparam node|string|nil input_node
|
||||
-- @treturn Slider @{Slider}
|
||||
function Slider.set_input_node(self, input_node)
|
||||
-- @treturn Slider Slider
|
||||
function M:set_input_node(input_node)
|
||||
self._input_node = self:get_node(input_node)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set Slider input enabled or disabled
|
||||
-- @tparam Slider self @{Slider}
|
||||
-- @tparam Slider self Slider
|
||||
-- @tparam boolean is_enabled
|
||||
function Slider.set_enabled(self, is_enabled)
|
||||
function M:set_enabled(is_enabled)
|
||||
self._is_enabled = is_enabled
|
||||
end
|
||||
|
||||
|
||||
--- Check if Slider component is enabled
|
||||
-- @tparam Slider self @{Slider}
|
||||
-- @tparam Slider self Slider
|
||||
-- @treturn boolean
|
||||
function Slider.is_enabled(self)
|
||||
function M:is_enabled()
|
||||
return self._is_enabled
|
||||
end
|
||||
|
||||
|
||||
return Slider
|
||||
return M
|
||||
|
@ -16,7 +16,7 @@
|
||||
-- @tparam node|nil click_zone
|
||||
|
||||
--- Trigger on swipe event(self, swipe_side, dist, delta_time)
|
||||
-- @tfield DruidEvent on_swipe) @{DruidEvent}
|
||||
-- @tfield DruidEvent on_swipe) DruidEvent
|
||||
|
||||
---
|
||||
|
||||
@ -25,7 +25,17 @@ local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Swipe = component.create("swipe")
|
||||
---@class druid.swipe: druid.base_component
|
||||
---@field node node
|
||||
---@field on_swipe druid.event
|
||||
---@field style table
|
||||
---@field click_zone node
|
||||
---@field private _trigger_on_move boolean
|
||||
---@field private _swipe_start_time number
|
||||
---@field private _start_pos vector3
|
||||
---@field private _is_enabled boolean
|
||||
---@field private _is_mobile boolean
|
||||
local M = component.create("swipe")
|
||||
|
||||
|
||||
local function start_swipe(self, action)
|
||||
@ -36,7 +46,7 @@ end
|
||||
|
||||
|
||||
local function reset_swipe(self, action)
|
||||
self._swipe_start_time = false
|
||||
self._swipe_start_time = 0
|
||||
end
|
||||
|
||||
|
||||
@ -77,7 +87,7 @@ end
|
||||
-- @tfield number|nil SWIPE_TIME Maximum time for swipe trigger. Default: 0.4
|
||||
-- @tfield number|nil SWIPE_THRESHOLD Minimum distance for swipe trigger. Default: 50
|
||||
-- @tfield boolean|nil SWIPE_TRIGGER_ON_MOVE If true, trigger on swipe moving, not only release action. Default: false
|
||||
function Swipe.on_style_change(self, style)
|
||||
function M:on_style_change(style)
|
||||
self.style = {}
|
||||
self.style.SWIPE_TIME = style.SWIPE_TIME or 0.4
|
||||
self.style.SWIPE_THRESHOLD = style.SWIPE_THRESHOLD or 50
|
||||
@ -85,15 +95,19 @@ function Swipe.on_style_change(self, style)
|
||||
end
|
||||
|
||||
|
||||
--- The @{Swipe} constructor
|
||||
-- @tparam Swipe self @{Swipe}
|
||||
--- The Swipe constructor
|
||||
-- @tparam Swipe self Swipe
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function on_swipe_callback Swipe callback for on_swipe_end event
|
||||
function Swipe.init(self, node, on_swipe_callback)
|
||||
self._trigger_on_move = self.style.SWIPE_TRIGGER_ON_MOVE
|
||||
self.node = self:get_node(node)
|
||||
|
||||
self._swipe_start_time = false
|
||||
---Swipe constructor
|
||||
---@param node_or_node_id node|string
|
||||
---@param on_swipe_callback function
|
||||
function M:init(node_or_node_id, on_swipe_callback)
|
||||
self._trigger_on_move = self.style.SWIPE_TRIGGER_ON_MOVE
|
||||
self.node = self:get_node(node_or_node_id)
|
||||
|
||||
self._swipe_start_time = 0
|
||||
self._start_pos = vmath.vector3(0)
|
||||
|
||||
self.click_zone = nil
|
||||
@ -101,7 +115,7 @@ function Swipe.init(self, node, on_swipe_callback)
|
||||
end
|
||||
|
||||
|
||||
function Swipe.on_late_init(self)
|
||||
function M:on_late_init()
|
||||
if not self.click_zone and const.IS_STENCIL_CHECK then
|
||||
local stencil_node = helper.get_closest_stencil_node(self.node)
|
||||
if stencil_node then
|
||||
@ -111,7 +125,7 @@ function Swipe.on_late_init(self)
|
||||
end
|
||||
|
||||
|
||||
function Swipe.on_input(self, action_id, action)
|
||||
function M:on_input(action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH then
|
||||
return false
|
||||
end
|
||||
@ -126,7 +140,7 @@ function Swipe.on_input(self, action_id, action)
|
||||
return false
|
||||
end
|
||||
|
||||
if self._swipe_start_time and (self._trigger_on_move or action.released) then
|
||||
if self._swipe_start_time ~= 0 and (self._trigger_on_move or action.released) then
|
||||
check_swipe(self, action)
|
||||
end
|
||||
|
||||
@ -142,18 +156,18 @@ function Swipe.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
function Swipe.on_input_interrupt(self)
|
||||
function M:on_input_interrupt()
|
||||
reset_swipe(self)
|
||||
end
|
||||
|
||||
|
||||
--- Strict swipe click area. Useful for
|
||||
-- restrict events outside stencil node
|
||||
-- @tparam Swipe self @{Swipe}
|
||||
-- @tparam Swipe self Swipe
|
||||
-- @tparam node|string|nil zone Gui node
|
||||
function Swipe.set_click_zone(self, zone)
|
||||
function M:set_click_zone(zone)
|
||||
self.click_zone = self:get_node(zone)
|
||||
end
|
||||
|
||||
|
||||
return Swipe
|
||||
return M
|
||||
|
@ -1,40 +1,18 @@
|
||||
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Component to handle GUI timers.
|
||||
-- Timer updating by game delta time. If game is not focused -
|
||||
-- timer will be not updated.
|
||||
-- @module Timer
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.timer
|
||||
|
||||
--- On timer tick. Fire every second callback(self, value)
|
||||
-- @tfield DruidEvent on_tick @{DruidEvent}
|
||||
|
||||
--- On timer change enabled state callback(self, is_enabled)
|
||||
-- @tfield DruidEvent on_set_enabled @{DruidEvent}
|
||||
|
||||
--- On timer end callback
|
||||
-- @tfield DruidEvent on_timer_end(self, Timer) @{DruidEvent}
|
||||
|
||||
--- Trigger node
|
||||
-- @tfield node node
|
||||
|
||||
--- Initial timer value
|
||||
-- @tfield number from
|
||||
|
||||
--- Target timer value
|
||||
-- @tfield number target
|
||||
|
||||
--- Current timer value
|
||||
-- @tfield number value
|
||||
|
||||
---
|
||||
|
||||
local Event = require("druid.event")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Timer = component.create("timer")
|
||||
---@class druid.timer: druid.base_component
|
||||
---@field on_tick druid.event
|
||||
---@field on_set_enabled druid.event
|
||||
---@field on_timer_end druid.event
|
||||
---@field style table
|
||||
---@field node node
|
||||
---@field from number
|
||||
---@field target number
|
||||
---@field value number
|
||||
---@field is_on boolean|nil
|
||||
local M = component.create("timer")
|
||||
|
||||
|
||||
local function second_string_min(sec)
|
||||
@ -44,13 +22,12 @@ local function second_string_min(sec)
|
||||
end
|
||||
|
||||
|
||||
--- The @{Timer} constructor
|
||||
-- @tparam Timer self @{Timer}
|
||||
-- @tparam node node Gui text node
|
||||
-- @tparam number|nil seconds_from Start timer value in seconds
|
||||
-- @tparam number|nil seconds_to End timer value in seconds
|
||||
-- @tparam function|nil callback Function on timer end
|
||||
function Timer.init(self, node, seconds_from, seconds_to, callback)
|
||||
---The Timer constructor
|
||||
---@param node node Gui text node
|
||||
---@param seconds_from number|nil Start timer value in seconds
|
||||
---@param seconds_to number|nil End timer value in seconds
|
||||
---@param callback function|nil Function on timer end
|
||||
function M:init(node, seconds_from, seconds_to, callback)
|
||||
self.node = self:get_node(node)
|
||||
seconds_to = math.max(seconds_to or 0, 0)
|
||||
|
||||
@ -73,7 +50,7 @@ function Timer.init(self, node, seconds_from, seconds_to, callback)
|
||||
end
|
||||
|
||||
|
||||
function Timer.update(self, dt)
|
||||
function M:update(dt)
|
||||
if not self.is_on then
|
||||
return
|
||||
end
|
||||
@ -96,42 +73,47 @@ function Timer.update(self, dt)
|
||||
end
|
||||
|
||||
|
||||
function Timer.on_layout_change(self)
|
||||
function M:on_layout_change()
|
||||
self:set_to(self.last_value)
|
||||
end
|
||||
|
||||
|
||||
--- Set text to text field
|
||||
-- @tparam Timer self @{Timer}
|
||||
-- @tparam number set_to Value in seconds
|
||||
function Timer.set_to(self, set_to)
|
||||
---@param self druid.timer
|
||||
---@param set_to number Value in seconds
|
||||
---@return druid.timer self
|
||||
function M:set_to(set_to)
|
||||
self.last_value = set_to
|
||||
gui.set_text(self.node, second_string_min(set_to))
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Called when update
|
||||
-- @tparam Timer self @{Timer}
|
||||
-- @tparam boolean|nil is_on Timer enable state
|
||||
function Timer.set_state(self, is_on)
|
||||
---@param self druid.timer
|
||||
---@param is_on boolean|nil Timer enable state
|
||||
---@return druid.timer self
|
||||
function M:set_state(is_on)
|
||||
self.is_on = is_on
|
||||
|
||||
self.on_set_enabled:trigger(self:get_context(), is_on)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set time interval
|
||||
-- @tparam Timer self @{Timer}
|
||||
-- @tparam number from Start time in seconds
|
||||
-- @tparam number to Target time in seconds
|
||||
function Timer.set_interval(self, from, to)
|
||||
---@param self druid.timer
|
||||
---@param from number Start time in seconds
|
||||
---@param to number Target time in seconds
|
||||
---@return druid.timer self
|
||||
function M:set_interval(from, to)
|
||||
self.from = from
|
||||
self.value = from
|
||||
self.temp = 0
|
||||
self.target = to
|
||||
self:set_state(true)
|
||||
self:set_to(from)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
return Timer
|
||||
return M
|
||||
|
237
druid/helper.lua
237
druid/helper.lua
@ -1,15 +1,13 @@
|
||||
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Helper module with various usefull GUI functions.
|
||||
-- @usage
|
||||
-- local helper = require("druid.helper")
|
||||
-- helper.centrate_nodes(0, node_1, node_2)
|
||||
-- @module Helper
|
||||
-- @alias druid.helper
|
||||
--- Druid Helper module
|
||||
|
||||
local const = require("druid.const")
|
||||
|
||||
local gui_get_node = gui.get_node
|
||||
|
||||
|
||||
---@class druid.system.helper
|
||||
local M = {}
|
||||
|
||||
local POSITION_X = hash("position.x")
|
||||
local SCALE_X = hash("scale.x")
|
||||
local SIZE_X = hash("size.x")
|
||||
@ -46,39 +44,35 @@ local function get_width(node)
|
||||
end
|
||||
|
||||
|
||||
--- Center two nodes.
|
||||
-- Nodes will be center around 0 x position
|
||||
-- text_node will be first (at left side)
|
||||
-- @function helper.centrate_text_with_icon
|
||||
-- @tparam text|nil text_node Gui text node
|
||||
-- @tparam box|nil icon_node Gui box node
|
||||
-- @tparam number margin Offset between nodes
|
||||
-- @local
|
||||
---Center two nodes.
|
||||
--Nodes will be center around 0 x position
|
||||
--text_node will be first (at left side)
|
||||
---@param text_node node|nil Gui text node
|
||||
---@param icon_node node|nil Gui box node
|
||||
---@param margin number Offset between nodes
|
||||
---@local
|
||||
function M.centrate_text_with_icon(text_node, icon_node, margin)
|
||||
return M.centrate_nodes(margin, text_node, icon_node)
|
||||
end
|
||||
|
||||
|
||||
--- Center two nodes.
|
||||
-- Nodes will be center around 0 x position
|
||||
-- icon_node will be first (at left side)
|
||||
-- @function helper.centrate_icon_with_text
|
||||
-- @tparam box|nil icon_node Gui box node
|
||||
-- @tparam text|nil text_node Gui text node
|
||||
-- @tparam number|nil margin Offset between nodes
|
||||
-- @local
|
||||
---Center two nodes.
|
||||
--Nodes will be center around 0 x position
|
||||
--icon_node will be first (at left side)
|
||||
---@param icon_node node|nil Gui box node
|
||||
---@param text_node node|nil Gui text node
|
||||
---@param margin number|nil Offset between nodes
|
||||
---@local
|
||||
function M.centrate_icon_with_text(icon_node, text_node, margin)
|
||||
return M.centrate_nodes(margin, icon_node, text_node)
|
||||
end
|
||||
|
||||
|
||||
--- Centerate nodes by x position with margin.
|
||||
--
|
||||
-- This functions calculate total width of nodes and set position for each node.
|
||||
-- The centrate will be around 0 x position.
|
||||
-- @function helper.centrate_nodes
|
||||
-- @tparam number|nil margin Offset between nodes
|
||||
-- @param ... Gui nodes
|
||||
---Centerate nodes by x position with margin.
|
||||
---
|
||||
---This functions calculate total width of nodes and set position for each node.
|
||||
---The centrate will be around 0 x position.
|
||||
---@param margin number|nil Offset between nodes
|
||||
---@param ... node Nodes to centrate
|
||||
function M.centrate_nodes(margin, ...)
|
||||
margin = margin or 0
|
||||
|
||||
@ -113,10 +107,33 @@ function M.centrate_nodes(margin, ...)
|
||||
end
|
||||
|
||||
|
||||
--- Get current screen stretch multiplier for each side
|
||||
-- @function helper.get_screen_aspect_koef
|
||||
-- @treturn number stretch_x
|
||||
-- @treturn number stretch_y
|
||||
---@param node_id string|node
|
||||
---@param template string|nil @Full Path to the template
|
||||
---@param nodes table<hash, node>|nil @Nodes what created with gui.clone_tree
|
||||
---@return node
|
||||
function M.get_node(node_id, template, nodes)
|
||||
if type(node_id) ~= "string" then
|
||||
-- Assume it's already node from gui.get_node
|
||||
return node_id
|
||||
end
|
||||
|
||||
-- If template is set, then add it to the node_id
|
||||
if template and #template > 0 then
|
||||
node_id = template .. "/" .. node_id
|
||||
end
|
||||
|
||||
-- If nodes is set, then try to find node in it
|
||||
if nodes then
|
||||
return nodes[node_id]
|
||||
end
|
||||
|
||||
return gui_get_node(node_id)
|
||||
end
|
||||
|
||||
|
||||
---Get current screen stretch multiplier for each side
|
||||
---@return number stretch_x
|
||||
---@return number stretch_y
|
||||
function M.get_screen_aspect_koef()
|
||||
local window_x, window_y = window.get_size()
|
||||
local stretch_x = window_x / gui.get_width()
|
||||
@ -126,10 +143,8 @@ function M.get_screen_aspect_koef()
|
||||
end
|
||||
|
||||
|
||||
--- Get current GUI scale for each side
|
||||
-- @function helper.get_gui_scale
|
||||
-- @treturn number scale_x
|
||||
-- @treturn number scale_y
|
||||
---Get current GUI scale for each side
|
||||
---@return number scale_x
|
||||
function M.get_gui_scale()
|
||||
local window_x, window_y = window.get_size()
|
||||
return math.min(window_x / gui.get_width(),
|
||||
@ -137,12 +152,11 @@ function M.get_gui_scale()
|
||||
end
|
||||
|
||||
|
||||
--- Move value from current to target value with step amount
|
||||
-- @function helper.step
|
||||
-- @tparam number current Current value
|
||||
-- @tparam number target Target value
|
||||
-- @tparam number step Step amount
|
||||
-- @treturn number New value
|
||||
---Move value from current to target value with step amount
|
||||
---@param current number Current value
|
||||
---@param target number Target value
|
||||
---@param step number Step amount
|
||||
---@return number New value
|
||||
function M.step(current, target, step)
|
||||
if current < target then
|
||||
return math.min(current + step, target)
|
||||
@ -152,12 +166,11 @@ function M.step(current, target, step)
|
||||
end
|
||||
|
||||
|
||||
--- Clamp value between min and max
|
||||
-- @function helper.clamp
|
||||
-- @tparam number a Value
|
||||
-- @tparam number min Min value
|
||||
-- @tparam number max Max value
|
||||
-- @treturn number Clamped value
|
||||
---Clamp value between min and max
|
||||
---@param a number Value
|
||||
---@param min number Min value
|
||||
---@param max number Max value
|
||||
---@return number value Clamped value
|
||||
function M.clamp(a, min, max)
|
||||
if min > max then
|
||||
min, max = max, min
|
||||
@ -173,22 +186,20 @@ function M.clamp(a, min, max)
|
||||
end
|
||||
|
||||
|
||||
--- Calculate distance between two points
|
||||
-- @function helper.distance
|
||||
-- @tparam number x1 First point x
|
||||
-- @tparam number y1 First point y
|
||||
-- @tparam number x2 Second point x
|
||||
-- @tparam number y2 Second point y
|
||||
-- @treturn number Distance
|
||||
---Calculate distance between two points
|
||||
---@param x1 number First point x
|
||||
---@param y1 number First point y
|
||||
---@param x2 number Second point x
|
||||
---@param y2 number Second point y
|
||||
---@return number Distance
|
||||
function M.distance(x1, y1, x2, y2)
|
||||
return math.sqrt((x2 - x1) ^ 2 + (y2 - y1) ^ 2)
|
||||
end
|
||||
|
||||
|
||||
--- Return sign of value (-1, 0, 1)
|
||||
-- @function helper.sign
|
||||
-- @tparam number val Value
|
||||
-- @treturn number Sign
|
||||
---Return sign of value
|
||||
---@param val number Value
|
||||
---@return number sign Sign of value, -1, 0 or 1
|
||||
function M.sign(val)
|
||||
if val == 0 then
|
||||
return 0
|
||||
@ -198,47 +209,42 @@ function M.sign(val)
|
||||
end
|
||||
|
||||
|
||||
--- Round number to specified decimal places
|
||||
-- @function helper.round
|
||||
-- @tparam number num Number
|
||||
-- @tparam number|nil num_decimal_places Decimal places
|
||||
-- @treturn number Rounded number
|
||||
---Round number to specified decimal places
|
||||
---@param num number Number
|
||||
---@param num_decimal_places number|nil Decimal places
|
||||
---@return number value Rounded number
|
||||
function M.round(num, num_decimal_places)
|
||||
local mult = 10^(num_decimal_places or 0)
|
||||
return math.floor(num * mult + 0.5) / mult
|
||||
end
|
||||
|
||||
|
||||
--- Lerp between two values
|
||||
-- @function helper.lerp
|
||||
-- @tparam number a First value
|
||||
-- @tparam number b Second value
|
||||
-- @tparam number t Lerp amount
|
||||
-- @treturn number Lerped value
|
||||
---Lerp between two values
|
||||
---@param a number First value
|
||||
---@param b number Second value
|
||||
---@param t number Lerp amount
|
||||
---@return number value Lerped value
|
||||
function M.lerp(a, b, t)
|
||||
return a + (b - a) * t
|
||||
end
|
||||
|
||||
|
||||
--- Check if value is in array and return index of it
|
||||
-- @function helper.contains
|
||||
-- @tparam table t Array
|
||||
-- @param value Value
|
||||
-- @treturn number|nil Index of value or nil
|
||||
function M.contains(t, value)
|
||||
for i = 1, #t do
|
||||
if t[i] == value then
|
||||
return i
|
||||
---Check if value contains in array
|
||||
---@param array any[] Array to check
|
||||
---@param value any Value
|
||||
function M.contains(array, value)
|
||||
for index = 1, #array do
|
||||
if array[index] == value then
|
||||
return index
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Make a copy table with all nested tables
|
||||
-- @function helper.deepcopy
|
||||
-- @tparam table orig_table Original table
|
||||
-- @treturn table Copy of original table
|
||||
---Make a copy table with all nested tables
|
||||
---@param orig_table table Original table
|
||||
---@return table Copy of original table
|
||||
function M.deepcopy(orig_table)
|
||||
local orig_type = type(orig_table)
|
||||
local copy
|
||||
@ -254,11 +260,10 @@ function M.deepcopy(orig_table)
|
||||
end
|
||||
|
||||
|
||||
--- Add all elements from source array to the target array
|
||||
-- @function helper.add_array
|
||||
-- @tparam any[] target Array to put elements from source
|
||||
-- @tparam any[]|nil source The source array to get elements from
|
||||
-- @treturn any[] The target array
|
||||
---Add all elements from source array to the target array
|
||||
---@param target any[] Array to put elements from source
|
||||
---@param source any[]|nil The source array to get elements from
|
||||
---@return any[] The target array
|
||||
function M.add_array(target, source)
|
||||
assert(target)
|
||||
|
||||
@ -274,13 +279,12 @@ function M.add_array(target, source)
|
||||
end
|
||||
|
||||
|
||||
--- Make a check with gui.pick_node, but with additional node_click_area check.
|
||||
-- @function helper.pick_node
|
||||
-- @tparam node node
|
||||
-- @tparam number x
|
||||
-- @tparam number y
|
||||
-- @tparam node|nil node_click_area
|
||||
-- @local
|
||||
---Make a check with gui.pick_node, but with additional node_click_area check.
|
||||
---@param node node
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param node_click_area node|nil
|
||||
---@local
|
||||
function M.pick_node(node, x, y, node_click_area)
|
||||
local is_pick = gui.pick_node(node, x, y)
|
||||
|
||||
@ -291,20 +295,19 @@ function M.pick_node(node, x, y, node_click_area)
|
||||
return is_pick
|
||||
end
|
||||
|
||||
--- Get node size adjusted by scale
|
||||
-- @function helper.get_scaled_size
|
||||
-- @tparam node node GUI node
|
||||
-- @treturn vector3 Scaled size
|
||||
|
||||
---Get size of node with scale multiplier
|
||||
---@param node node GUI node
|
||||
---@treturn vector3 Scaled size
|
||||
function M.get_scaled_size(node)
|
||||
return vmath.mul_per_elem(gui.get_size(node), gui.get_scale(node))
|
||||
end
|
||||
|
||||
|
||||
--- Get cumulative parent's node scale
|
||||
-- @function helper.get_scene_scale
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam boolean|nil include_passed_node_scale True if add current node scale to result
|
||||
-- @treturn vector3 The scene node scale
|
||||
---Get cumulative parent's node scale
|
||||
---@param node node Gui node
|
||||
---@param include_passed_node_scale boolean|nil True if add current node scale to result
|
||||
---@return vector3 The scene node scale
|
||||
function M.get_scene_scale(node, include_passed_node_scale)
|
||||
local scale = include_passed_node_scale and gui.get_scale(node) or vmath.vector3(1)
|
||||
local parent = gui.get_parent(node)
|
||||
@ -317,10 +320,9 @@ function M.get_scene_scale(node, include_passed_node_scale)
|
||||
end
|
||||
|
||||
|
||||
--- Return closest non inverted clipping parent node for given node
|
||||
-- @function helper.get_closest_stencil_node
|
||||
-- @tparam node node GUI node
|
||||
-- @treturn node|nil The closest stencil node or nil
|
||||
---Return closest non inverted clipping parent node for given node
|
||||
---@param node node GUI node
|
||||
---@return node|nil stencil_node The closest stencil node or nil
|
||||
function M.get_closest_stencil_node(node)
|
||||
if not node then
|
||||
return nil
|
||||
@ -348,8 +350,15 @@ end
|
||||
-- @function helper.get_pivot_offset
|
||||
-- @tparam number pivot The gui.PIVOT_* constant
|
||||
-- @treturn vector3 Vector offset with [-0.5..0.5] values
|
||||
function M.get_pivot_offset(pivot)
|
||||
return const.PIVOTS[pivot]
|
||||
|
||||
---Get pivot offset for given pivot or node
|
||||
---@param pivot_or_node number|node GUI pivot or node
|
||||
---@return vector3 offset The pivot offset
|
||||
function M.get_pivot_offset(pivot_or_node)
|
||||
if type(pivot_or_node) == "number" then
|
||||
return const.PIVOTS[pivot_or_node]
|
||||
end
|
||||
return const.PIVOTS[gui.get_pivot(pivot_or_node)]
|
||||
end
|
||||
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
local const = require("druid.const")
|
||||
local settings = require("druid.system.settings")
|
||||
|
||||
|
@ -10,11 +10,11 @@
|
||||
--
|
||||
-- Please review the following API pages:
|
||||
--
|
||||
-- @{Helper} - A useful set of functions for working with GUI nodes, such as centering nodes, get GUI scale ratio, etc
|
||||
-- Helper - A useful set of functions for working with GUI nodes, such as centering nodes, get GUI scale ratio, etc
|
||||
--
|
||||
-- @{DruidEvent} - The core event system in Druid. Learn how to subscribe to any event in every Druid component.
|
||||
-- DruidEvent - The core event system in Druid. Learn how to subscribe to any event in every Druid component.
|
||||
--
|
||||
-- @{BaseComponent} - The parent class of all Druid components. You can find all default component methods there.
|
||||
-- BaseComponent - The parent class of all Druid components. You can find all default component methods there.
|
||||
--
|
||||
-- # Tech Info #
|
||||
--
|
||||
@ -89,7 +89,21 @@ local back_handler = require("druid.base.back_handler")
|
||||
-- local lang_text = require("druid.extended.lang_text")
|
||||
-- local timer_component = require("druid.extended.timer")
|
||||
|
||||
local DruidInstance = {}
|
||||
---@class druid_instance
|
||||
---@field components_all druid.base_component[] All created components
|
||||
---@field components_interest table<string, druid.base_component[]> All components sorted by interest
|
||||
---@field url url
|
||||
---@field private _context table Druid context
|
||||
---@field private _style table Druid style table
|
||||
---@field private _deleted boolean
|
||||
---@field private _is_late_remove_enabled boolean
|
||||
---@field private _late_remove druid.base_component[]
|
||||
---@field private _input_blacklist druid.base_component[]|nil
|
||||
---@field private _input_whitelist druid.base_component[]|nil
|
||||
---@field private _input_inited boolean
|
||||
---@field private _late_init_timer_id number
|
||||
---@field private _input_components druid.base_component[]
|
||||
local M = {}
|
||||
|
||||
local MSG_ADD_FOCUS = hash("acquire_input_focus")
|
||||
local MSG_REMOVE_FOCUS = hash("release_input_focus")
|
||||
@ -219,17 +233,15 @@ end
|
||||
|
||||
|
||||
--- Druid class constructor
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam table context Druid context. Usually it is self of gui script
|
||||
-- @tparam table style Druid style table
|
||||
-- @local
|
||||
function DruidInstance.initialize(self, context, style)
|
||||
function M:initialize(context, style)
|
||||
self._context = context
|
||||
self._style = style or settings.default_style
|
||||
self._deleted = false
|
||||
self._is_late_remove_enabled = false
|
||||
self._late_remove = {}
|
||||
self._is_debug = false
|
||||
self.url = msg.url()
|
||||
|
||||
self._input_blacklist = nil
|
||||
@ -244,11 +256,10 @@ end
|
||||
|
||||
|
||||
-- Create new component.
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam BaseComponent component Component module
|
||||
-- @tparam any ... Other component params to pass it to component:init function
|
||||
-- @treturn BaseComponent Component instance
|
||||
function DruidInstance.new(self, component, ...)
|
||||
function M:new(component, ...)
|
||||
local instance = create(self, component)
|
||||
|
||||
if instance.init then
|
||||
@ -263,8 +274,7 @@ end
|
||||
|
||||
|
||||
--- Call this in gui_script final function.
|
||||
-- @tparam DruidInstance self
|
||||
function DruidInstance.final(self)
|
||||
function M:final()
|
||||
local components = self.components_all
|
||||
|
||||
for i = #components, 1, -1 do
|
||||
@ -282,10 +292,9 @@ end
|
||||
--- Remove created component from Druid instance.
|
||||
--
|
||||
-- Component `on_remove` function will be invoked, if exist.
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam BaseComponent component Component instance
|
||||
-- @treturn boolean True if component was removed
|
||||
function DruidInstance.remove(self, component)
|
||||
function M:remove(component)
|
||||
if self._is_late_remove_enabled then
|
||||
table.insert(self._late_remove, component)
|
||||
return false
|
||||
@ -334,9 +343,8 @@ end
|
||||
--- Druid late update function called after initialization and before the regular update step
|
||||
-- This function is used to check the GUI state and perform actions after all components and nodes have been created.
|
||||
-- An example use case is performing an auto stencil check in the GUI hierarchy for input components.
|
||||
-- @tparam DruidInstance self
|
||||
-- @local
|
||||
function DruidInstance.late_init(self)
|
||||
function M:late_init()
|
||||
local late_init_components = self.components_interest[base_component.ON_LATE_INIT]
|
||||
while late_init_components[1] do
|
||||
late_init_components[1]:on_late_init()
|
||||
@ -353,9 +361,8 @@ end
|
||||
--- Call this in gui_script update function.
|
||||
--
|
||||
-- Used for: scroll, progress, timer components
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam number dt Delta time
|
||||
function DruidInstance.update(self, dt)
|
||||
function M:update(dt)
|
||||
self._is_late_remove_enabled = true
|
||||
|
||||
local components = self.components_interest[base_component.ON_UPDATE]
|
||||
@ -371,11 +378,10 @@ end
|
||||
--- Call this in gui_script on_input function.
|
||||
--
|
||||
-- Used for almost all components
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam hash action_id Action_id from on_input
|
||||
-- @tparam table action Action from on_input
|
||||
-- @treturn boolean The boolean value is input was consumed
|
||||
function DruidInstance.on_input(self, action_id, action)
|
||||
function M:on_input(action_id, action)
|
||||
self._is_late_remove_enabled = true
|
||||
|
||||
local components = self.components_interest[base_component.ON_INPUT]
|
||||
@ -392,11 +398,10 @@ end
|
||||
--- Call this in gui_script on_message function.
|
||||
--
|
||||
-- Used for special actions. See SPECIFIC_UI_MESSAGES table
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam hash message_id Message_id from on_message
|
||||
-- @tparam table message Message from on_message
|
||||
-- @tparam url sender Sender from on_message
|
||||
function DruidInstance.on_message(self, message_id, message, sender)
|
||||
function M:on_message(message_id, message, sender)
|
||||
local specific_ui_message = base_component.SPECIFIC_UI_MESSAGES[message_id]
|
||||
|
||||
if specific_ui_message == base_component.ON_MESSAGE_INPUT then
|
||||
@ -431,9 +436,8 @@ end
|
||||
|
||||
--- Calls the on_focus_lost function in all related components
|
||||
-- This one called by on_window_callback by global window listener
|
||||
-- @tparam DruidInstance self
|
||||
-- @local
|
||||
function DruidInstance.on_focus_lost(self)
|
||||
function M:on_focus_lost()
|
||||
local components = self.components_interest[base_component.ON_FOCUS_LOST]
|
||||
for i = 1, #components do
|
||||
components[i]:on_focus_lost()
|
||||
@ -443,9 +447,8 @@ end
|
||||
|
||||
--- Calls the on_focus_gained function in all related components
|
||||
-- This one called by on_window_callback by global window listener
|
||||
-- @tparam DruidInstance self
|
||||
-- @local
|
||||
function DruidInstance.on_focus_gained(self)
|
||||
function M:on_focus_gained()
|
||||
local components = self.components_interest[base_component.ON_FOCUS_GAINED]
|
||||
for i = 1, #components do
|
||||
components[i]:on_focus_gained()
|
||||
@ -456,9 +459,8 @@ end
|
||||
--- Calls the on_language_change function in all related components
|
||||
-- This one called by global druid.on_language_change, but can be
|
||||
-- call manualy to update all translations
|
||||
-- @tparam DruidInstance self
|
||||
-- @local
|
||||
function DruidInstance.on_language_change(self)
|
||||
function M:on_language_change()
|
||||
local components = self.components_interest[base_component.ON_LANGUAGE_CHANGE]
|
||||
for i = 1, #components do
|
||||
components[i]:on_language_change()
|
||||
@ -470,10 +472,9 @@ end
|
||||
--
|
||||
-- If whitelist is not empty and component not contains in this list,
|
||||
-- component will be not processed on input step
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam table|BaseComponent|nil whitelist_components The array of component to whitelist
|
||||
-- @treturn self @{DruidInstance}
|
||||
function DruidInstance.set_whitelist(self, whitelist_components)
|
||||
-- @treturn self DruidInstance
|
||||
function M:set_whitelist(whitelist_components)
|
||||
if whitelist_components and whitelist_components._component then
|
||||
whitelist_components = { whitelist_components }
|
||||
end
|
||||
@ -491,11 +492,10 @@ end
|
||||
--- Set blacklist components for input processing.
|
||||
--
|
||||
-- If blacklist is not empty and component contains in this list,
|
||||
-- component will be not processed on input step
|
||||
-- @tparam DruidInstance self @{DruidInstance}
|
||||
-- component will be not processed on input step DruidInstance
|
||||
-- @tparam table|BaseComponent|nil blacklist_components The array of component to blacklist
|
||||
-- @treturn self @{DruidInstance}
|
||||
function DruidInstance.set_blacklist(self, blacklist_components)
|
||||
-- @treturn self DruidInstance
|
||||
function M:set_blacklist(blacklist_components)
|
||||
if blacklist_components and blacklist_components._component then
|
||||
blacklist_components = { blacklist_components }
|
||||
end
|
||||
@ -510,35 +510,9 @@ function DruidInstance.set_blacklist(self, blacklist_components)
|
||||
end
|
||||
|
||||
|
||||
--- Set debug mode for current Druid instance. It's enable debug log messages
|
||||
-- @tparam DruidInstance self @{DruidInstance}
|
||||
-- @tparam boolean|nil is_debug
|
||||
-- @treturn self @{DruidInstance}
|
||||
--- Remove all components on late remove step DruidInstance
|
||||
-- @local
|
||||
function DruidInstance.set_debug(self, is_debug)
|
||||
self._is_debug = is_debug
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Log message, if is_debug mode is enabled
|
||||
-- @tparam DruidInstance self @{DruidInstance}
|
||||
-- @tparam string message
|
||||
-- @tparam table|nil context
|
||||
-- @local
|
||||
function DruidInstance.log_message(self, message, context)
|
||||
if not self._is_debug then
|
||||
return
|
||||
end
|
||||
|
||||
print("[Druid]:", message, helper.table_to_string(context))
|
||||
end
|
||||
|
||||
|
||||
--- Remove all components on late remove step
|
||||
-- @tparam DruidInstance self @{DruidInstance}
|
||||
-- @local
|
||||
function DruidInstance._clear_late_remove(self)
|
||||
function M:_clear_late_remove()
|
||||
if #self._late_remove == 0 then
|
||||
return
|
||||
end
|
||||
@ -550,229 +524,188 @@ function DruidInstance._clear_late_remove(self)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Button} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node The node_id or gui.get_node(node_id)
|
||||
-- @tparam function|nil callback Button callback
|
||||
-- @tparam any|nil params Button callback params
|
||||
-- @tparam node|string|nil anim_node Button anim node (node, if not provided)
|
||||
-- @treturn Button @{Button} component
|
||||
function DruidInstance.new_button(self, node, callback, params, anim_node)
|
||||
return DruidInstance.new(self, button, node, callback, params, anim_node)
|
||||
--- Create Button component
|
||||
---@param node string|node The node_id or gui.get_node(node_id)
|
||||
---@param callback function|nil Button callback
|
||||
---@param params any|nil Button callback params
|
||||
---@param anim_node node|string|nil Button anim node (node, if not provided)
|
||||
---@return druid.button Button component
|
||||
function M:new_button(node, callback, params, anim_node)
|
||||
return self:new(button, node, callback, params, anim_node)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Blocker} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node The node_id or gui.get_node(node_id)
|
||||
-- @treturn Blocker @{Blocker} component
|
||||
function DruidInstance.new_blocker(self, node)
|
||||
return DruidInstance.new(self, blocker, node)
|
||||
--- Create Blocker component
|
||||
---@param node string|node The node_id or gui.get_node(node_id)
|
||||
---@return druid.blocker Blocker component
|
||||
function M:new_blocker(node)
|
||||
return self:new(blocker, node)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{BackHandler} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam function|nil callback @The callback(self, custom_args) to call on back event
|
||||
-- @tparam any|nil params Callback argument
|
||||
-- @treturn BackHandler @{BackHandler} component
|
||||
function DruidInstance.new_back_handler(self, callback, params)
|
||||
return DruidInstance.new(self, back_handler, callback, params)
|
||||
--- Create BackHandler component
|
||||
---@param callback function|nil The callback(self, custom_args) to call on back event
|
||||
---@param params any|nil Callback argument
|
||||
---@return druid.back_handler BackHandler component
|
||||
function M:new_back_handler(callback, params)
|
||||
return self:new(back_handler, callback, params)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Hover} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node The node_id or gui.get_node(node_id)
|
||||
-- @tparam function|nil on_hover_callback Hover callback
|
||||
-- @tparam function|nil on_mouse_hover_callback Mouse hover callback
|
||||
-- @treturn Hover @{Hover} component
|
||||
function DruidInstance.new_hover(self, node, on_hover_callback, on_mouse_hover_callback)
|
||||
return DruidInstance.new(self, hover, node, on_hover_callback, on_mouse_hover_callback)
|
||||
--- Create Hover component
|
||||
---@param node string|node The node_id or gui.get_node(node_id)
|
||||
---@param on_hover_callback function|nil Hover callback
|
||||
---@param on_mouse_hover_callback function|nil Mouse hover callback
|
||||
---@return druid.hover Hover component
|
||||
function M:new_hover(node, on_hover_callback, on_mouse_hover_callback)
|
||||
return self:new(hover, node, on_hover_callback, on_mouse_hover_callback)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Text} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node The node_id or gui.get_node(node_id)
|
||||
-- @tparam string|nil value Initial text. Default value is node text from GUI scene.
|
||||
-- @tparam boolean|nil no_adjust If true, text will be not auto-adjust size
|
||||
-- @treturn Text @{Text} component
|
||||
function DruidInstance.new_text(self, node, value, no_adjust)
|
||||
return DruidInstance.new(self, text, node, value, no_adjust)
|
||||
--- Create Text component
|
||||
---@param node string|node The node_id or gui.get_node(node_id)
|
||||
---@param value string|nil Initial text. Default value is node text from GUI scene.
|
||||
---@param no_adjust boolean|nil If true, text will be not auto-adjust size
|
||||
---@return druid.text Text component
|
||||
function M:new_text(node, value, no_adjust)
|
||||
return self:new(text, node, value, no_adjust)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{StaticGrid} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node parent_node The node_id or gui.get_node(node_id). Parent of all Grid items.
|
||||
-- @tparam node item Element prefab. Required to get grid's item size. Can be adjusted separately.
|
||||
-- @tparam number|nil in_row How many nodes in row can be placed
|
||||
-- @treturn StaticGrid @{StaticGrid} component
|
||||
-- @local
|
||||
function DruidInstance.new_grid(self, parent_node, item, in_row)
|
||||
return DruidInstance.new(self, static_grid, parent_node, item, in_row)
|
||||
--- Create StaticGrid component
|
||||
---@param parent_node string|node The node_id or gui.get_node(node_id). Parent of all Grid items.
|
||||
---@param item node Element prefab. Required to get grid's item size. Can be adjusted separately.
|
||||
---@param in_row number|nil How many nodes in row can be placed
|
||||
---@return druid.grid StaticGrid component
|
||||
function M:new_grid(parent_node, item, in_row)
|
||||
return self:new(static_grid, parent_node, item, in_row)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{StaticGrid} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node parent_node The node_id or gui.get_node(node_id). Parent of all Grid items.
|
||||
-- @tparam string|node item Item prefab. Required to get grid's item size. Can be adjusted separately.
|
||||
-- @tparam number|nil in_row How many nodes in row can be placed
|
||||
-- @treturn StaticGrid @{StaticGrid} component
|
||||
function DruidInstance.new_static_grid(self, parent_node, item, in_row)
|
||||
return DruidInstance.new(self, static_grid, parent_node, item, in_row)
|
||||
--- Create StaticGrid component
|
||||
---@param parent_node string|node The node_id or gui.get_node(node_id). Parent of all Grid items.
|
||||
---@param item string|node Item prefab. Required to get grid's item size. Can be adjusted separately.
|
||||
---@param in_row number|nil How many nodes in row can be placed
|
||||
---@return druid.grid StaticGrid component
|
||||
function M:new_static_grid(parent_node, item, in_row)
|
||||
return self:new(static_grid, parent_node, item, in_row)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Scroll} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node view_node The node_id or gui.get_node(node_id). Will used as user input node.
|
||||
-- @tparam string|node content_node The node_id or gui.get_node(node_id). Will used as scrollable node inside view_node.
|
||||
-- @treturn Scroll @{Scroll} component
|
||||
function DruidInstance.new_scroll(self, view_node, content_node)
|
||||
return DruidInstance.new(self, scroll, view_node, content_node)
|
||||
--- Create Scroll component
|
||||
---@param view_node string|node The node_id or gui.get_node(node_id). Will used as user input node.
|
||||
---@param content_node string|node The node_id or gui.get_node(node_id). Will used as scrollable node inside view_node.
|
||||
---@return druid.scroll Scroll component
|
||||
function M:new_scroll(view_node, content_node)
|
||||
return self:new(scroll, view_node, content_node)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Drag} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node The node_id or gui.get_node(node_id). Will used as user input node.
|
||||
-- @tparam function|nil on_drag_callback Callback for on_drag_event(self, dx, dy)
|
||||
-- @treturn Drag @{Drag} component
|
||||
function DruidInstance.new_drag(self, node, on_drag_callback)
|
||||
return DruidInstance.new(self, drag, node, on_drag_callback)
|
||||
--- Create Drag component
|
||||
---@param node string|node The node_id or gui.get_node(node_id). Will used as user input node.
|
||||
---@param on_drag_callback function|nil Callback for on_drag_event(self, dx, dy)
|
||||
---@return druid.drag Drag component
|
||||
function M:new_drag(node, on_drag_callback)
|
||||
return self:new(drag, node, on_drag_callback)
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Swipe} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node The node_id or gui.get_node(node_id). Will used as user input node.
|
||||
-- @tparam function|nil on_swipe_callback Swipe callback for on_swipe_end event
|
||||
-- @treturn Swipe @{Swipe} component
|
||||
function DruidInstance.new_swipe(self, node, on_swipe_callback)
|
||||
return helper.require_component_message("swipe")
|
||||
--- Create Swipe component
|
||||
---@param node string|node The node_id or gui.get_node(node_id). Will used as user input node.
|
||||
---@param on_swipe_callback function|nil Swipe callback for on_swipe_end event
|
||||
---@return druid.swipe Swipe component
|
||||
function M:new_swipe(node, on_swipe_callback)
|
||||
return helper.require_component_message("swipe") --[[@as druid.swipe]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{DynamicGrid} component
|
||||
-- Deprecated
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node parent_node The node_id or gui.get_node(node_id). Parent of all Grid items.
|
||||
-- @treturn DynamicGrid @{DynamicGrid} component
|
||||
function DruidInstance.new_dynamic_grid(self, parent_node)
|
||||
return helper.require_component_message("dynamic_grid")
|
||||
--- Create LangText component
|
||||
---@param node string|node The_node id or gui.get_node(node_id)
|
||||
---@param locale_id string|nil Default locale id or text from node as default
|
||||
---@param adjust_type string|nil Adjust type for text node. Default: const.TEXT_ADJUST.DOWNSCALE
|
||||
---@return druid.lang_text LangText component
|
||||
function M:new_lang_text(node, locale_id, adjust_type)
|
||||
return helper.require_component_message("lang_text") --[[@as druid.lang_text]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{LangText} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node The_node id or gui.get_node(node_id)
|
||||
-- @tparam string|nil locale_id Default locale id or text from node as default
|
||||
-- @tparam string|nil adjust_type Adjust type for text node. Default: const.TEXT_ADJUST.DOWNSCALE
|
||||
-- @treturn LangText @{LangText} component
|
||||
function DruidInstance.new_lang_text(self, node, locale_id, adjust_type)
|
||||
return helper.require_component_message("lang_text")
|
||||
--- Create Slider component
|
||||
---@param pin_node string|node The_node id or gui.get_node(node_id).
|
||||
---@param end_pos vector3 The end position of slider
|
||||
---@param callback function|nil On slider change callback
|
||||
---@return druid.slider Slider component
|
||||
function M:new_slider(pin_node, end_pos, callback)
|
||||
return helper.require_component_message("slider") --[[@as druid.slider]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Slider} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node pin_node The_node id or gui.get_node(node_id).
|
||||
-- @tparam vector3 end_pos The end position of slider
|
||||
-- @tparam function|nil callback On slider change callback
|
||||
-- @treturn Slider @{Slider} component
|
||||
function DruidInstance.new_slider(self, pin_node, end_pos, callback)
|
||||
return helper.require_component_message("slider")
|
||||
--- Create Input component
|
||||
---@param click_node string|node Button node to enabled input component
|
||||
---@param text_node string|node|druid.text Text node what will be changed on user input
|
||||
---@param keyboard_type number|nil Gui keyboard type for input field
|
||||
---@return druid.input Input component
|
||||
function M:new_input(click_node, text_node, keyboard_type)
|
||||
return helper.require_component_message("input") --[[@as druid.input]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Input} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node click_node Button node to enabled input component
|
||||
-- @tparam string|node|druid.text text_node Text node what will be changed on user input
|
||||
-- @tparam number|nil keyboard_type Gui keyboard type for input field
|
||||
-- @treturn Input @{Input} component
|
||||
function DruidInstance.new_input(self, click_node, text_node, keyboard_type)
|
||||
return helper.require_component_message("input")
|
||||
--- Create DataList component
|
||||
---@param druid_scroll druid.scroll The Scroll instance for Data List component
|
||||
---@param druid_grid druid.grid The StaticGrid} or @{DynamicGrid instance for Data List component
|
||||
---@param create_function function The create function callback(self, data, index, data_list). Function should return (node, [component])
|
||||
---@return druid.data_list DataList component
|
||||
function M:new_data_list(druid_scroll, druid_grid, create_function)
|
||||
return helper.require_component_message("data_list") --[[@as druid.data_list]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{DataList} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam Scroll druid_scroll The Scroll instance for Data List component
|
||||
-- @tparam StaticGrid druid_grid The @{StaticGrid} or @{DynamicGrid} instance for Data List component
|
||||
-- @tparam function create_function The create function callback(self, data, index, data_list). Function should return (node, [component])
|
||||
-- @treturn DataList @{DataList} component
|
||||
function DruidInstance.new_data_list(self, druid_scroll, druid_grid, create_function)
|
||||
return helper.require_component_message("data_list")
|
||||
--- Create Timer component
|
||||
---@param node string|node Gui text node
|
||||
---@param seconds_from number Start timer value in seconds
|
||||
---@param seconds_to number|nil End timer value in seconds
|
||||
---@param callback function|nil Function on timer end
|
||||
---@return druid.timer Timer component
|
||||
function M:new_timer(node, seconds_from, seconds_to, callback)
|
||||
return helper.require_component_message("timer") --[[@as druid.timer]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Timer} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node Gui text node
|
||||
-- @tparam number seconds_from Start timer value in seconds
|
||||
-- @tparam number|nil seconds_to End timer value in seconds
|
||||
-- @tparam function|nil callback Function on timer end
|
||||
-- @treturn Timer @{Timer} component
|
||||
function DruidInstance.new_timer(self, node, seconds_from, seconds_to, callback)
|
||||
return helper.require_component_message("timer")
|
||||
--- Create Progress component
|
||||
---@param node string|node Progress bar fill node or node name
|
||||
---@param key string Progress bar direction: const.SIDE.X or const.SIDE.Y
|
||||
---@param init_value number|nil Initial value of progress bar. Default: 1
|
||||
---@return druid.progress Progress component
|
||||
function M:new_progress(node, key, init_value)
|
||||
return helper.require_component_message("progress") --[[@as druid.progress]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Progress} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node Progress bar fill node or node name
|
||||
-- @tparam string key Progress bar direction: const.SIDE.X or const.SIDE.Y
|
||||
-- @tparam number|nil init_value Initial value of progress bar. Default: 1
|
||||
-- @treturn Progress @{Progress} component
|
||||
function DruidInstance.new_progress(self, node, key, init_value)
|
||||
return helper.require_component_message("progress")
|
||||
--- Create Layout component
|
||||
---@param node string|node The_node id or gui.get_node(node_id).
|
||||
---@param mode string The layout mode
|
||||
---@return druid.layout Layout component
|
||||
function M:new_layout(node, mode)
|
||||
return helper.require_component_message("layout") --[[@as druid.layout]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Layout} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node The_node id or gui.get_node(node_id).
|
||||
-- @tparam string mode The layout mode
|
||||
-- @treturn Layout @{Layout} component
|
||||
function DruidInstance.new_layout(self, node, mode)
|
||||
return helper.require_component_message("layout")
|
||||
--- Create Hotkey component
|
||||
---@param keys_array string|string[] Keys for trigger action. Should contains one action key and any amount of modificator keys
|
||||
---@param callback function The callback function
|
||||
---@param callback_argument any|nil The argument to pass into the callback function
|
||||
---@return druid.hotkey Hotkey component
|
||||
function M:new_hotkey(keys_array, callback, callback_argument)
|
||||
return helper.require_component_message("hotkey") --[[@as druid.hotkey]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{Hotkey} component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|string[] keys_array Keys for trigger action. Should contains one action key and any amount of modificator keys
|
||||
-- @tparam function callback The callback function
|
||||
-- @tparam any|nil callback_argument The argument to pass into the callback function
|
||||
-- @treturn Hotkey @{Hotkey} component
|
||||
function DruidInstance.new_hotkey(self, keys_array, callback, callback_argument)
|
||||
return helper.require_component_message("hotkey")
|
||||
--- Create RichText component.
|
||||
---@param text_node string|node The text node to make Rich Text
|
||||
---@param value string|nil The initial text value. Default will be gui.get_text(text_node)
|
||||
---@return druid.rich_text RichText component
|
||||
function M:new_rich_text(text_node, value)
|
||||
return helper.require_component_message("rich_text", "custom") --[[@as druid.rich_text]]
|
||||
end
|
||||
|
||||
|
||||
--- Create @{RichText} component.
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node text_node The text node to make Rich Text
|
||||
-- @tparam string|nil value The initial text value. Default will be gui.get_text(text_node)
|
||||
-- @treturn RichText @{RichText} component
|
||||
function DruidInstance.new_rich_text(self, text_node, value)
|
||||
return helper.require_component_message("rich_text", "custom")
|
||||
end
|
||||
|
||||
|
||||
--- Create @{RichInput} component.
|
||||
--- Create RichInput component.
|
||||
-- As a template please check rich_input.gui layout.
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string template The template string name
|
||||
-- @tparam table nodes Nodes table from gui.clone_tree
|
||||
-- @treturn RichInput @{RichInput} component
|
||||
function DruidInstance.new_rich_input(self, template, nodes)
|
||||
return helper.require_component_message("rich_input", "custom")
|
||||
---@param template string The template string name
|
||||
---@param nodes table Nodes table from gui.clone_tree
|
||||
---@return druid.rich_input RichInput component
|
||||
function M:new_rich_input(template, nodes)
|
||||
return helper.require_component_message("rich_input", "custom") --[[@as druid.rich_input]]
|
||||
end
|
||||
|
||||
|
||||
return DruidInstance
|
||||
return M
|
||||
|
@ -1,21 +1,15 @@
|
||||
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Druid settings file
|
||||
-- @module settings
|
||||
-- @local
|
||||
|
||||
---@class druid.system.settings
|
||||
local M = {}
|
||||
|
||||
M.default_style = nil
|
||||
|
||||
|
||||
function M.get_text(name, a, b, c, d, e, f, g)
|
||||
---@param text_id string
|
||||
---@vararg any
|
||||
function M.get_text(text_id, ...)
|
||||
return "[Druid]: locales not inited"
|
||||
end
|
||||
|
||||
|
||||
function M.play_sound(name)
|
||||
function M.play_sound(sound_id)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
|
@ -1,11 +1,11 @@
|
||||
local component = require("druid.component")
|
||||
|
||||
---@class component_name : druid.base_component
|
||||
local Component = component.create("component_name")
|
||||
local M = component.create("component_name")
|
||||
|
||||
|
||||
-- Component constructor. Template name and nodes are optional. Pass it if you use it in your component
|
||||
function Component:init(template, nodes)
|
||||
function M:init(template, nodes)
|
||||
self.druid = self:get_druid(template, nodes)
|
||||
self.root = self:get_node("root")
|
||||
|
||||
@ -13,9 +13,4 @@ function Component:init(template, nodes)
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call on component remove or on druid:final
|
||||
function Component:on_remove()
|
||||
end
|
||||
|
||||
|
||||
return Component
|
||||
return M
|
||||
|
@ -1,10 +1,10 @@
|
||||
local component = require("druid.component")
|
||||
|
||||
---@class component_name : druid.base_component
|
||||
local Component = component.create("component_name")
|
||||
---@class new_component: druid.base_component
|
||||
local M = component.create("new_component")
|
||||
|
||||
-- Component constructor. Template name and nodes are optional. Pass it if you use it in your component
|
||||
function Component:init(template, nodes)
|
||||
function M:init(template, nodes)
|
||||
-- If your component is gui template, pass the template name and set it
|
||||
-- If your component is cloned my gui.clone_tree, pass nodes to component and set it
|
||||
-- Use inner druid instance to create components inside this component
|
||||
@ -17,55 +17,55 @@ end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call every update step
|
||||
function Component:update(dt)
|
||||
function M:update(dt)
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call default on_input from gui script
|
||||
function Component:on_input(action_id, action)
|
||||
function M:on_input(action_id, action)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call on component creation and on component:set_style() function
|
||||
function Component:on_style_change(style)
|
||||
function M:on_style_change(style)
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call default on_message from gui script
|
||||
function Component:on_message(message_id, message, sender)
|
||||
function M:on_message(message_id, message, sender)
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call if druid has triggered on_language_change
|
||||
function Component:on_language_change()
|
||||
function M:on_language_change()
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call if game layout has changed and need to restore values in component
|
||||
function Component:on_layout_change()
|
||||
function M:on_layout_change()
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call, if input was capturing before this component
|
||||
-- Example: scroll is start scrolling, so you need unhover button
|
||||
function Component:on_input_interrupt()
|
||||
function M:on_input_interrupt()
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call, if game lost focus
|
||||
function Component:on_focus_lost()
|
||||
function M:on_focus_lost()
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call, if game gained focus
|
||||
function Component:on_focus_gained()
|
||||
function M:on_focus_gained()
|
||||
end
|
||||
|
||||
|
||||
-- [OPTIONAL] Call on component remove or on druid:final
|
||||
function Component:on_remove()
|
||||
function M:on_remove()
|
||||
end
|
||||
|
||||
|
||||
return Component
|
||||
return M
|
||||
|
@ -134,7 +134,7 @@ end
|
||||
--- Set new size of layout node
|
||||
---@param width number|nil
|
||||
---@param height number|nil
|
||||
---@return druid.container @{Container}
|
||||
---@return druid.container Container
|
||||
function M:set_size(width, height)
|
||||
width = width or self.size.x
|
||||
height = height or self.size.y
|
||||
@ -191,7 +191,7 @@ end
|
||||
|
||||
--- Set size for layout node to fit inside it
|
||||
---@param target_size vector3
|
||||
---@return druid.container @{Container}
|
||||
---@return druid.container Container
|
||||
function M:fit_into_size(target_size)
|
||||
self.fit_size = target_size
|
||||
self:refresh()
|
||||
@ -200,7 +200,7 @@ end
|
||||
|
||||
|
||||
--- Set current size for layout node to fit inside it
|
||||
---@return druid.container @{Container}
|
||||
---@return druid.container Container
|
||||
function M:fit_into_window()
|
||||
return self:fit_into_size(vmath.vector3(gui.get_width(), gui.get_height(), 0))
|
||||
end
|
||||
@ -221,7 +221,7 @@ end
|
||||
---@param node_or_container node|string|druid.container|table
|
||||
---@param mode string|nil stretch, fit, stretch_x, stretch_y. Default: Pick from node, "fit" or "stretch"
|
||||
---@param on_resize_callback fun(self: userdata, size: vector3)|nil
|
||||
---@return druid.container @{Container} New created layout instance
|
||||
---@return druid.container Container New created layout instance
|
||||
function M:add_container(node_or_container, mode, on_resize_callback)
|
||||
local container = nil
|
||||
local node = node_or_container
|
||||
@ -422,7 +422,7 @@ function M:update_child_containers()
|
||||
end
|
||||
|
||||
|
||||
---@return druid.container @{Container}
|
||||
---@return druid.container Container
|
||||
function M:create_draggable_corners()
|
||||
self:clear_draggable_corners()
|
||||
|
||||
@ -452,7 +452,7 @@ function M:create_draggable_corners()
|
||||
end
|
||||
|
||||
|
||||
---@return druid.container @{Container}
|
||||
---@return druid.container Container
|
||||
function M:clear_draggable_corners()
|
||||
for index = 1, #self._draggable_corners do
|
||||
local drag_component = self._draggable_corners[index]
|
||||
@ -505,7 +505,7 @@ end
|
||||
|
||||
--- Set node for layout node to fit inside it. Pass nil to reset
|
||||
---@param node string|node The node_id or gui.get_node(node_id)
|
||||
---@return druid.container @{Layout}
|
||||
---@return druid.container Layout
|
||||
function M:fit_into_node(node)
|
||||
self._fit_node = self:get_node(node)
|
||||
self:refresh_scale()
|
||||
|
@ -1,6 +1,6 @@
|
||||
local component = require("druid.component")
|
||||
|
||||
---@class basic_blocker: druid.component
|
||||
---@class basic_blocker: druid.base_component
|
||||
---@field druid druid_instance
|
||||
---@field root node
|
||||
---@field blocker druid.blocker
|
||||
|
@ -104,23 +104,23 @@ function druid_instance.new(self, component, ...) end
|
||||
--- Set current component style table.
|
||||
--- Invoke `on_style_change` on component, if exist. Component should handle their style changing and store all style params
|
||||
---@generic T: druid.base_component
|
||||
---@param self T @{BaseComponent}
|
||||
---@param self T BaseComponent
|
||||
---@param druid_style table|nil Druid style module
|
||||
---@return T @{BaseComponent}
|
||||
---@return T BaseComponent
|
||||
function druid__base_component.set_style(self, druid_style) end
|
||||
|
||||
--- Set component template name.
|
||||
--- Use on all your custom components with GUI layouts used as templates. It will check parent template name to build full template name in self:get_node()
|
||||
---@generic T: druid.base_component
|
||||
---@param self T @{BaseComponent}
|
||||
---@param self T BaseComponent
|
||||
---@param template string BaseComponent template name
|
||||
---@return T @{BaseComponent}
|
||||
---@return T BaseComponent
|
||||
function druid__base_component.set_template(self, template) end
|
||||
|
||||
--- Set current component nodes.
|
||||
--- Use if your component nodes was cloned with `gui.clone_tree` and you got the node tree.
|
||||
---@generic T: druid.base_component
|
||||
---@param self T @{BaseComponent}
|
||||
---@param self T BaseComponent
|
||||
---@param nodes table BaseComponent nodes table
|
||||
---@return T @{BaseComponent}
|
||||
---@return T BaseComponent
|
||||
function druid__base_component.set_nodes(self, nodes) end
|
||||
|
Loading…
x
Reference in New Issue
Block a user