diff --git a/README.md b/README.md
index b11089e..c2fd370 100644
--- a/README.md
+++ b/README.md
@@ -7,11 +7,7 @@
[](https://github.com/Insality/druid/actions)
[](https://codecov.io/gh/Insality/druid)
-**Druid** - powerful Defold component UI library. Use basic and extended **Druid** components or make your own game-specific components to make amazing GUI in your games.
-
-
-## Overview
-
+**Druid** - most powerful Defold component UI framework. Use basic and extended **Druid** components or make your own game-specific components with ease to make stunning and customizable GUI in your games.
## Setup
@@ -26,89 +22,52 @@ You can use the **Druid** extension in your own project by adding this project a
Here is a list of [all releases](https://github.com/Insality/druid/releases).
### Input Bindings
-Druid uses `/builtins/input/all.input_binding` input bindins. For advanced setup see the Input Binding section in Advanced Setup.
+**Druid** uses `/builtins/input/all.input_binding` input bindings. For custom input bindings see the Input Binding section in **_[Advanced Setup](docs_md/advanced-setup.md)_**.
+
+### Advanced Setup
+In case you want to adjust **Druid** to your needs, you can use **_[Advanced Setup](docs_md/advanced-setup.md)_** section.
## Usage
-Here only basic usage.
-How to read this doc.
-Annotations.
-Example of advanced usage - different doc.
-Example of custom components - different doc.
+### Basic usage
-## Components
+To use **Druid**, first you should create a **Druid** instance to spawn components and add Druids main functions: *update*, *final*, *on_message* and *on_input*.
-Here is full **Druid** components list:
-
-### Basic Components
-
-| Name | Description | Example |
Preview
|
-|------|-------------|---------|---------|
-| **[Button](https://insality.github.io/druid/modules/Button.html)** | Basic input component. Handles all types of interactions: click, long click, hold click, double click, etc | [Button Example](https://insality.github.io/druid/druid/?example=general_buttons) |
|
-| **[Text](https://insality.github.io/druid/modules/Text.html)** | Wrap on GUI text node, handle different text size adjusting, providing additional text API | [Text Example](https://insality.github.io/druid/druid/?example=texts_general) |
|
-| **[Scroll](https://insality.github.io/druid/modules/Scroll.html)** | Scroll component | [Scroll Example](https://insality.github.io/druid/druid/?example=general_scroll) |
|
-| **[Blocker](https://insality.github.io/druid/modules/Blocker.html)** | Block user input in node zone area | ❌ | |
-| **[Back Handler](https://insality.github.io/druid/modules/BackHandler.html)** | Handle back button (Android back button, backspace key) | ❌ | |
-| **[Static Grid](https://insality.github.io/druid/modules/StaticGrid.html)** | Component to manage node positions with equal sizes | [Static Gid Example](https://insality.github.io/druid/druid/?example=general_grid) |
|
-| **[Hover](https://insality.github.io/druid/modules/Hover.html)** | Handle hover node state on node | ❌ |
|
-| **[Swipe](https://insality.github.io/druid/modules/Swipe.html)** | Handle swipe gestures on node | [Swipe Example](https://insality.github.io/druid/druid/?example=general_swipe) |
|
-| **[Drag](https://insality.github.io/druid/modules/Drag.html)** | Handle drag input on node | [Drag Example](https://insality.github.io/druid/druid/?example=general_drag) |
|
-
-
-### Extended components
-> Extended components before usage should be registered in **Druid** with `druid.register()` function.
-
-| Name | Description | Example | Preview
|
-|------|-------------|---------|---------|
-| **[Checkbox](https://insality.github.io/druid/modules/Checkbox.html)** | Checkbox component | [Checkbox Example](https://insality.github.io/druid/druid/?example=general_checkboxes) |
|
-| **[Checkbox group](https://insality.github.io/druid/modules/CheckboxGroup.html)** | Several checkboxes in one group | [Checkbox group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) |
|
-| **[Radio group](https://insality.github.io/druid/modules/RadioGroup.html)** | Several checkboxes in one group with a single choice | [Radio Group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) |
|
-| **[Dynamic Grid](https://insality.github.io/druid/modules/DynamicGrid.html)** | Component to manage node positions with different sizes. Only in one row or column | [Dynamic Grid Example](https://insality.github.io/druid/druid/?example=general_grid) |
|
-| **[Data List](https://insality.github.io/druid/modules/DataList.html)** | Component to manage data for huge datasets in scroll | [Data List Example](https://insality.github.io/druid/druid/?example=general_data_list) |
|
-| **[Input](https://insality.github.io/druid/modules/Input.html)** | User text input component | [Input Example](https://insality.github.io/druid/druid/?example=general_input) |
|
-| **[Lang text](https://insality.github.io/druid/modules/LangText.html)** | Wrap on Text component to handle localization | ❌ |
|
-| **[Progress](https://insality.github.io/druid/modules/Progress.html)** | Progress bar component | [Progress Example](https://insality.github.io/druid/druid/?example=general_progress_bar) |
|
-| **[Slider](https://insality.github.io/druid/modules/Slider.html)** | Slider component | [Slider Example]() |
|
-| **[Timer](https://insality.github.io/druid/modules/Timer.html)** | Handle timers on GUI text node | ❌ |
|
-| **[Hotkey](https://insality.github.io/druid/modules/Hotkey.html)** | Handle keyboard hotkeys with key modificators | [Hotkey Example](https://insality.github.io/druid/druid/?example=general_hokey) |
|
-| **[Layout](https://insality.github.io/druid/modules/Layout.html)** | Handle node size depends on layout mode and screen aspect ratio | [Layout Example](https://insality.github.io/druid/druid/?example=general_layout) |
|
-
-For a complete overview, see: **_[components.md](docs_md/01-components.md)_**.
-
-
-## Basic usage
-
-To use **Druid**, first you should create a Druid instance to spawn components and add Druids main engine functions: *update*, *final*, *on_message* and *on_input*.
-
-All **Druid** components take node name string as arguments, don't do `gui.get_node()` before.
+All **Druid** components take node name string as argument. In in some cases you don't have the node name you can pass the `gui.get_node()` instead.
All **Druid** and component methods are called with `:` like `self.druid:new_button()`.
```lua
local druid = require("druid.druid")
-local function button_callback(self)
- print("Button was clicked!")
+-- All component callbacks pass "self" as first argument
+-- This self is a context data passed in `druid.new(context)`
+local function on_button_callback(self)
+ print("The button clicked!")
end
function init(self)
self.druid = druid.new(self)
- self.druid:new_button("button_node_name", button_callback)
+ self.button = self.druid:new_button("button_node_name", on_button_callback)
end
+-- Final is a required function for a correct Druid workflow
function final(self)
self.druid:final()
end
+-- The update used in progress bar, scroll and timer basic components
function update(self, dt)
self.druid:update(dt)
end
+-- The on_message used for specific Druid events, like language change or layout change
function on_message(self, message_id, message, sender)
self.druid:on_message(message_id, message, sender)
end
+-- The on_input used in almost all Druid components
function on_input(self, action_id, action)
return self.druid:on_input(action_id, action)
end
@@ -117,9 +76,89 @@ end
For all **Druid** instance functions, [see here](https://insality.github.io/druid/modules/DruidInstance.html).
+
+### API Documentation
+
+**Druid** has a lot of components and functions. To make it easier to use, **Druid** has a full API documentation with examples and annotations.
+
+Start read the API documentation [here](hhttps://insality.github.io/druid/modules/Druid.html).
+
+### EmmyLua Annotations [optional]
+
+[EmmyLua](https://emmylua.github.io/annotation.html) - annotations for Lua. It's a great tool for Lua code autocompletion in editors like [VSCode](https://github.com/EmmyLua/VSCode-EmmyLua), [IntelliJ IDEA](https://github.com/EmmyLua/IntelliJ-EmmyLua).
+
+Since the dependencies can't be processed by external editors, for use generated EmmyLua annotations you should copy the _druid/annotations.lua_ to your project.
+
+For EmmyLua it will be enough. Remember you can _restart emmylua server_ for refresh the changes, if something goes wrong.
+
+After the annotations is processed, you should point the type of Druid in requires:
+```lua
+---@type druid
+local druid = require("druid.druid")
+
+-- Now the autocomplete is working
+```
+
+
+
+### Advanced Usage
+
+If you looking for more advanced usage, see the [Advanced Usage](docs_md/advanced-usage.md) section.
+
+
+### Create custom components
+
+If you want to create your own components, see the [Create Custom Components](docs_md/create-custom-components.md) section.
+
+The custom components is the most powerful feature of **Druid**. You can create your own components with ease and use it in your game.
+
+
+## Druid Components
+
+Here is full **Druid** components list.
+
+### Basic Components
+
+> Basic components always included in the build and available for use.
+
+| Name | Description | Example | Preview
|
+|------|-------------|---------|---------|
+| **[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) |
|
+| **[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) |
|
+| **[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) |
|
+| **[Blocker](https://insality.github.io/druid/modules/Blocker.html)** | Logic over GUI Node. Don't pass any user input below node area size. | ❌ | |
+| **[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 | ❌ | |
+| **[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) |
|
+| **[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. | ❌ |
|
+| **[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) |
|
+| **[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) |
|
+
+
+### Extended components
+
+> Extended components before usage should be registered in **Druid** with `druid.register()` function.
+
+| Name | Description | Example | Preview
|
+|------|-------------|---------|---------|
+| **[Checkbox](https://insality.github.io/druid/modules/Checkbox.html)** | Switch node state on click event. | [Checkbox Example](https://insality.github.io/druid/druid/?example=general_checkboxes) |
|
+| **[Checkbox group](https://insality.github.io/druid/modules/CheckboxGroup.html)** | Group of checkbox components. | [Checkbox group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) |
|
+| **[Radio group](https://insality.github.io/druid/modules/RadioGroup.html)** | Like checkbox group but with single choise only. | [Radio Group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) |
|
+| **[Dynamic Grid](https://insality.github.io/druid/modules/DynamicGrid.html)** | Logic over GUI Node. Component to manage node positions with all different node sizes. Only one direction: horizontal or vertical. | [Dynamic Grid Example](https://insality.github.io/druid/druid/?example=general_grid) |
|
+| **[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) |
|
+| **[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) |
|
+| **[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` | ❌ |
|
+| **[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) |
|
+| **[Slider](https://insality.github.io/druid/modules/Slider.html)** | Logic over GUI Node. Handle draggable node with position restrictions. | [Slider Example]() |
|
+| **[Timer](https://insality.github.io/druid/modules/Timer.html)** | Logic over GUI Text. Handle basic timer functions. | ❌ |
|
+| **[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_hokey) |
|
+| **[Layout](https://insality.github.io/druid/modules/Layout.html)** | Logic over GUI Node. Handle node size depends on layout mode and screen aspect ratio. Contains helpers to build more complex UI layout. | [Layout Example](https://insality.github.io/druid/druid/?example=general_layout) |
|
+
+For a complete overview, see: **_[components.md](docs_md/01-components.md)_**.
+
+
## Druid Events
-Any **Druid** components as callbacks use [Druid Events](https://insality.github.io/druid/modules/DruidEvent.html). In component API ([button example](https://insality.github.io/druid/modules/Button.html#on_click)) pointed list of component events. You can manually subscribe to those events with the following API:
+Any **Druid** components as callbacks use [Druid Events](https://insality.github.io/druid/modules/DruidEvent.html). In component API ([button example](https://insality.github.io/druid/modules/Button.html#on_click)) pointed list of component events. You can manually subscribe to these events with the following API:
- **event:subscribe**(callback)
@@ -129,57 +168,29 @@ Any **Druid** components as callbacks use [Druid Events](https://insality.github
You can subscribe several callbacks to a single event.
-## Druid Lifecycle
-
-Here is full Druid lifecycle setup for your ***.gui_script** file:
-```lua
-local druid = require("druid.druid")
-
-function init(self)
- self.druid = druid.new(self)
-end
-
-function final(self)
- self.druid:final()
-end
-
-function update(self, dt)
- self.druid:update(dt)
-end
-
-function on_input(self, action_id, action)
- return self.druid:on_input(action_id, action)
-end
-
-function on_message(self, message_id, message, sender)
- self.druid:on_message(message_id, message, sender)
-end
-```
-
-- *final* is a **required** function for a correct Druid lifecycle
-- *on_input* is used in almost all Druid components
-- *update* in used in progress bar, scroll and timer base components
-- *on_message* is used for specific Druid events, like language change or layout change
-
-It is recommended to fully integrate all **Druid** lifecycles functions.
-
-
## Details
-- Druid input goes as stack. Last created button will checked first. So create your GUI from back
-- Don't forget about `return` in `on_input`: `return self.druid:on_input()`. It is needed if you have more than 1 acquire inputs (several Druid, other input system, etc)
-- By default, Druid will automatically _acquire_input_focus_. So you don't need do it manually. But only if you have components which require _on_input_
-- If you want to delete a node which has a Druid component, don't forget to remove it via `druid:remove(component)`
+- **Druid** input goes as stack. Last created button will be checked first. Create your input GUI component from back to front.
+- Don't forget about `return` in `on_input`: `return self.druid:on_input()`. It is required if you have more than 1 acquire inputs (several Druid, other input system, etc)
+- Druid automatically call _acquire_input_focus_ if you have input components. So you don't required to call it manually.
+- If you want to delete a **Druid** component node, don't forget to remove it via `druid:remove(component)`
[See full FAQ here](docs_md/FAQ.md)
## Examples
-See the [**example folder**](https://github.com/Insality/druid/tree/develop/example) for examples of how to use **Druid**
+### HTML5 Live Examples
Try the [**HTML5 version**](https://insality.github.io/druid/druid/) of the **Druid** example app
+Each example page has a link to the example code directly, so it will help you to faster understand how to use **Druid**
+
+
+### Code examples
+
+See the [**example folder**](https://github.com/Insality/druid/tree/develop/example) for examples of how to use **Druid**
+
## Documentation
diff --git a/deployer_build_stats.csv b/deployer_build_stats.csv
index 09bbddc..d42a7dd 100644
--- a/deployer_build_stats.csv
+++ b/deployer_build_stats.csv
@@ -9,3 +9,4 @@ date,sha,version,build_size,build_time,platform,mode,is_cache_using,commits_coun
2022-08-29T18:46:47Z,13003e472169cbd261e703eca7b133adf64a24f7,0.9.592,2316,40,js-web,release,true,592
2022-09-09T17:55:42Z,072507cc9e715541bdee7636d2e5eeeb3c22a57d,0.10.603,2340,43,js-web,release,true,603
2022-09-09T18:00:07Z,072507cc9e715541bdee7636d2e5eeeb3c22a57d,0.10.603,2340,5,js-web,release,true,603
+2023-07-05T20:19:22Z,d0062c2a78e618871ebb4c8ee66b1509b763f069,0.10.671,3292,12,x86_64-linux,headless,true,671
diff --git a/docs_md/advanced-setup.md b/docs_md/advanced-setup.md
index 0704e26..1c1393b 100644
--- a/docs_md/advanced-setup.md
+++ b/docs_md/advanced-setup.md
@@ -1,5 +1,10 @@
+# Advanced Druid setup
+
+
## Input bindings
+As default input bindings **Druid** uses the `/builtins/input/all.input_binding`.
+
**Druid** requires the following input bindings:
- Mouse trigger - `Button 1` -> `touch` _For basic input components_
@@ -14,6 +19,7 @@


+
## Change key bindings [optional]
If you have to use your own key bindings (and key name), you can change it in your *game.project* file.
@@ -59,6 +65,8 @@ no_auto_template = 1
## Stencil check [optional]
When creating input components inside stencil nodes, **Druid** automatically setup `component:set_click_zone()` on _late_init_ component step to restrict input clicks outside this stencil zone.
+For example: button inside scroll stencil nodes.
+
To disable this feature add next field in your _game.project_ file
```
[druid]
@@ -66,7 +74,7 @@ no_stencil_check = 1
```
-## Code [optional]
+## Code bindings [optional]
Adjust **Druid** settings, if needed:
```lua
@@ -74,21 +82,30 @@ local druid = require("druid.druid")
-- Used for button component and custom components
-- Callback should play sound by name: function(sound_id) ... end
-druid.set_sound_function(callback)
+druid.set_sound_function(function(sound_id)
+ -- sound_system.play(sound_id)
+end)
-- Used for lang_text component
-- Callback should return localized string by locale id: function(locale_id) ... end
-druid.set_text_function(callback)
+druid.set_text_function(function(locale_id)
+ -- return lang.get(locale_id)
+end)
-- Used for change default Druid style
druid.set_default_style(your_style)
-- Call this function on language changing in the game,
-- to retranslate all lang_text components:
-druid.on_language_change()
+local function on_language_change()
+ druid.on_language_change()
+end
-- Call this function inside window.set_listener
-- to catch game focus lost/gained callbacks:
-- window.set_listener(function(self, event, data) druid.on_window_callback(event, data) end))
-druid.on_window_callback(event)
+local function on_window_callback(self, event, data)
+ druid.on_window_callback(event)
+end
+window.set_listener(on_window_callback)
```
diff --git a/druid/annotations.lua b/druid/annotations.lua
index e9fd95f..159a221 100644
--- a/druid/annotations.lua
+++ b/druid/annotations.lua
@@ -20,7 +20,7 @@ function druid.on_language_change() end
function druid.on_window_callback(event) end
--- Register a new external Druid component.
---- You can register your own components by creating them with 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.
+--- 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 druid.register(name, module) end
@@ -125,7 +125,7 @@ function druid__base_component.component:set_input_enabled(self, state) end
function druid__base_component.component:set_input_priority(self, value, is_temporary) end
--- Set current component nodes
---- Used if your component nodes was cloned with `gui.clone_tree`
+--- Use if your component nodes was cloned with `gui.clone_tree` and you got the node tree.
---@param self druid.base_component @{BaseComponent}
---@param nodes table BaseComponent nodes table
---@return druid.base_component @{BaseComponent}
@@ -162,31 +162,28 @@ function druid__blocker.set_enabled(self, state) end
---@class druid.button : druid.base_component
----@field anim_node node Animation node
----@field click_zone node Restriction zone
----@field hash node_id The hash of trigger node
----@field hover druid.hover Druid hover logic component
----@field node node Trigger node
----@field on_click druid.event On release button callback(self, params, button_instance)
----@field on_click_outside druid.event On click outside of button(self, params, button_instance)
----@field on_double_click druid.event On double tap button callback(self, params, button_instance, click_amount)
----@field on_hold_callback druid.event On button hold before long_click callback(self, params, button_instance, time)
----@field on_long_click druid.event On long tap button callback(self, params, button_instance, time)
----@field on_pressed druid.event On pressed button callback(self, params, button_instance)
----@field on_repeated_click druid.event On repeated action button callback(self, params, button_instance, click_amount)
----@field params any Params to click callbacks
----@field pos vector3 Initial pos of anim_node
----@field start_pos vector3 Initial pos of anim_node
----@field start_scale vector3 Initial scale of anim_node
+---@field anim_node node Button animation node.
+---@field click_zone node Additional button click area, defined by another GUI Node
+---@field hash node_id The GUI node id from button node
+---@field hover druid.hover @{Hover}: Button Hover component
+---@field node node Button clickable node
+---@field on_click druid.event @{DruidEvent}: Event on successful release action over button.
+---@field on_click_outside druid.event @{DruidEvent}: Event calls if click event was outside of button.
+---@field on_double_click druid.event @{DruidEvent}: Event on double tap action over button.
+---@field on_hold_callback druid.event @{DruidEvent}: Event calls every frame before on_long_click event.
+---@field on_long_click druid.event @{DruidEvent}: Event on long tap action over button.
+---@field on_pressed druid.event @{DruidEvent}: Event triggered if button was pressed by user.
+---@field on_repeated_click druid.event @{DruidEvent}: Event on repeated action over button.
+---@field params any Custom args for any Button event.
---@field style druid.button.style Component style params.
local druid__button = {}
---- Get key-code to trigger this button
+--- Get current key name to trigger this button.
---@param self druid.button
----@return hash The action_id of the key
+---@return hash The action_id of the input key
function druid__button.get_key_trigger(self) end
---- Component init function
+--- Button component constructor
---@param self druid.button @{Button}
---@param node node Gui node
---@param callback function Button callback
@@ -194,9 +191,9 @@ function druid__button.get_key_trigger(self) end
---@param anim_node node Button anim node (node, if not provided)
function druid__button.init(self, node, callback, params, anim_node) end
---- Return button enabled state
+--- Get button enabled state.
---@param self druid.button @{Button}
----@return bool True, if button is enabled
+---@return bool True, if button is enabled now, False overwise
function druid__button.is_enabled(self) end
--- Set function for additional check for button click availability
@@ -206,29 +203,30 @@ function druid__button.is_enabled(self) end
---@return druid.button Current button instance
function druid__button.set_check_function(self, check_function, failure_callback) end
---- Strict button click area.
---- Useful for no click events outside stencil node
+--- Set additional button click area.
+--- 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
---@param self druid.button @{Button}
---@param zone node Gui node
---@return druid.button Current button instance
function druid__button.set_click_zone(self, zone) end
---- Set enabled button component state
+--- Set button enabled state.
+--- The style.on_set_enabled will be triggered. Disabled button is not clickable.
---@param self druid.button @{Button}
---@param state bool Enabled state
---@return druid.button Current button instance
function druid__button.set_enabled(self, state) end
---- Set buttom click mode to call itself inside html5 callback in user interaction event It required to do protected stuff like copy/paste text, show html keyboard, etc The HTML5 button don't call any events except on_click
+--- Set buttom click mode to call itself inside html5 callback in user interaction event It required to do protected stuff like copy/paste text, show html keyboard, etc The HTML5 button doesn't call any events except on_click event
---@protected
---@param self druid.button
---@param is_html_mode boolean If true - button will be called inside html5 callback
---@return druid.button Current button instance
function druid__button.set_html5_user_interaction(self, is_html_mode) end
---- Set key-code to trigger this button
+--- Set key name to trigger this button by keyboard.
---@param self druid.button @{Button}
----@param key hash The action_id of the key
+---@param key hash The action_id of the input key
---@return druid.button Current button instance
function druid__button.set_key_trigger(self, key) end
@@ -647,7 +645,7 @@ function druid__input.get_text(self) end
--- Component init function
---@param self druid.input @{Input}
----@param click_node node Button node to enabled input component
+---@param click_node node Node to enabled input component
---@param text_node node|druid.text Text node what will be changed on user input. You can pass text component instead of text node name @{Text}
---@param keyboard_type number Gui keyboard type for input field
function druid__input.init(self, click_node, text_node, keyboard_type) end
@@ -942,6 +940,31 @@ function druid__rich_input.set_placeholder(self, placeholder_text) end
---@field component field The component druid instance
local druid__rich_text = {}
+--- Clear all created words.
+function druid__rich_text.clean() end
+
+--- Get all current words.
+---@return table Words
+function druid__rich_text.get_words() end
+
+--- Rich Text component constructor
+---@param self druid.rich_text @{RichText}
+---@param template string The Rich Text template name
+---@param nodes table The node table, if prefab was copied by gui.clone_tree()
+function druid__rich_text.init(self, template, nodes) end
+
+--- Set text for Rich Text
+---@param self druid.rich_text @{RichText}
+---@param text string The text to set
+---@return table words
+---@return table line_metrics
+function druid__rich_text.set_text(self, text) end
+
+--- Get all words, which has a passed tag
+---@param tag string
+---@return table Words
+function druid__rich_text.tagged(tag) end
+
---@class druid.scroll : druid.base_component
---@field available_pos vector4 Available position for content node: (min_x, max_y, max_x, min_y)
@@ -1578,7 +1601,7 @@ function druid_instance.on_input(self, action_id, action) end
---@param sender hash Sender from on_message
function druid_instance.on_message(self, message_id, message, sender) end
---- Remove component from Druid instance.
+--- Remove created component from Druid instance.
--- Component `on_remove` function will be invoked, if exist.
---@param self druid_instance
---@param component Component Component instance
diff --git a/druid/base/button.lua b/druid/base/button.lua
index c295480..d13bed5 100755
--- a/druid/base/button.lua
+++ b/druid/base/button.lua
@@ -1,56 +1,131 @@
-- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license
---- Component to handle basic GUI button
+--- Druid Component to handle the user click interactions: click, long click, double click, etc.
+-- # Overview #
+--
+-- The most generic and useful component you can use. Set any GUI node clickable and providing different callbacks.
+--
+-- # Notes #
+--
+-- • The click callback will not trigger if between pressed and released state cursor was outside of node zone
+--
+-- • If button have double click event subscriber and it is triggered, usual callback will be not triggered
+--
+-- • Button can have key trigger to use then by key: `button:set_key_trigger`
+--
+-- • Animation node can be used for example to animate small icon on big panel. Node name of trigger zone will be `big panel` and animation node will be `small icon`
+--
+-- @usage
+-- local function on_button_click(self, args, button)
+-- print("Button has clicked with params: " .. args)
+-- print("Also the button component is passed in callback params")
+-- end
+--
+-- local custom_args = "Any variable to pass inside callback"
+-- local button = self.druid:new_button("button_name", on_button_click, custom_args)
+--
-- @module Button
-- @within BaseComponent
-- @alias druid.button
---- On release button callback(self, params, button_instance)
+
+--- @{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}
---- On repeated action button callback(self, params, button_instance, click_amount)
+
+--- @{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
+-- -- Custom args passed in Button constructor
+-- 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}
----On long tap button callback(self, params, button_instance, time)
+
+--- @{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
+-- @usage
+-- -- Custom args passed in Button constructor
+-- 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}
----On double tap button callback(self, params, button_instance, click_amount)
+
+--- @{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)
+-- @usage
+-- -- Custom args passed in Button constructor
+-- 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}
----On button hold before long_click callback(self, params, button_instance, time)
+
+--- @{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.
+--
+-- Usecase: Animate button progress of long tap
+-- @usage
+-- -- Custom args passed in Button constructor
+-- button.on_double_click:subscribe(function(self, custom_args, button_instance, time)
+-- print("On hold Button callback!")
+-- end)
-- @tfield DruidEvent on_hold_callback @{DruidEvent}
----On click outside of button(self, params, button_instance)
+
+--- @{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
+--
+-- Usecase: Hide the popup when click outside
+-- @usage
+-- -- Custom args passed in Button constructor
+-- button.on_click_outside:subscribe(function(self, custom_args, button_instance)
+-- print("On click Button outside!")
+-- end)
-- @tfield DruidEvent on_click_outside @{DruidEvent}
----On pressed button callback(self, params, button_instance)
+
+--- @{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}
----Trigger node
+--- Button clickable node
-- @tfield node node
----The hash of trigger node
+---The GUI node id from button node
-- @tfield node_id hash
----Animation node
+--- Button animation node.
+-- In default case equals to clickable node.
+--
+-- Usecase: You have the big clickable panel, but want to animate only one small icon on it.
-- @tfield[opt=node] node anim_node
----Initial scale of anim_node
--- @tfield vector3 start_scale
-
----Initial pos of anim_node
--- @tfield vector3 start_pos
-
----Initial pos of anim_node
--- @tfield vector3 pos
-
----Params to click callbacks
+---Custom args for any Button event. Setup in Button constructor
-- @tfield any params
----Druid hover logic component
+--- @{Hover}: Button Hover component
-- @tfield Hover hover @{Hover}
----Restriction zone
+--- Additional button click area, defined by another GUI Node
-- @tfield[opt] node click_zone
---
@@ -195,7 +270,7 @@ function Button.on_style_change(self, style)
end
---- Component init function
+--- Button component constructor
-- @tparam Button self @{Button}
-- @tparam node node Gui node
-- @tparam function callback Button callback
@@ -357,10 +432,15 @@ function Button.on_message_input(self, node_id, message)
end
---- Set enabled button component state
+--- Set button enabled state.
+-- The style.on_set_enabled will be triggered.
+-- Disabled button is not clickable.
-- @tparam Button self @{Button}
-- @tparam bool state Enabled state
-- @treturn Button Current button instance
+-- @usage
+-- button:set_enabled(false)
+-- button:set_enabled(true)
function Button.set_enabled(self, state)
self.disabled = not state
self.hover:set_enabled(state)
@@ -370,19 +450,25 @@ function Button.set_enabled(self, state)
end
---- Return button enabled state
+--- Get button enabled state.
-- @tparam Button self @{Button}
--- @treturn bool True, if button is enabled
+-- @treturn bool True, if button is enabled now, False overwise
+-- @usage
+-- local is_enabled = button:is_enabled()
function Button.is_enabled(self)
return not self.disabled
end
---- Strict button click area. Useful for
--- no click events outside stencil node
+--- Set additional button click area.
+-- 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 node zone Gui node
-- @treturn Button Current button instance
+-- @usage
+-- button:set_click_zone("stencil_node")
function Button.set_click_zone(self, zone)
self.click_zone = self:get_node(zone)
self.hover:set_click_zone(zone)
@@ -391,10 +477,12 @@ function Button.set_click_zone(self, zone)
end
---- Set key-code to trigger this button
+--- Set key name to trigger this button by keyboard.
-- @tparam Button self @{Button}
--- @tparam hash key The action_id of the key
+-- @tparam hash 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)
self.key_trigger = hash(key)
@@ -402,9 +490,11 @@ function Button.set_key_trigger(self, key)
end
---- Get key-code to trigger this button
+--- Get current key name to trigger this button.
-- @tparam Button self
--- @treturn hash The action_id of the key
+-- @treturn hash The action_id of the input key
+-- @usage
+-- local key_hash = button:get_key_trigger()
function Button.get_key_trigger(self)
return self.key_trigger
end
@@ -423,10 +513,12 @@ end
--- Set buttom click mode to call itself inside html5 callback in user interaction event
-- It required to do protected stuff like copy/paste text, show html keyboard, etc
--- The HTML5 button don't call any events except on_click
+-- The HTML5 button doesn't call any events except on_click event
-- @tparam Button self
-- @tparam[opt] boolean is_html_mode If true - button will be called inside html5 callback
-- @treturn Button Current button instance
+-- @usage
+-- button:set_html5_user_interaction(true)
function Button.set_html5_user_interaction(self, is_html_mode)
self._is_html5_mode = is_html_mode and html5
return self
diff --git a/druid/component.lua b/druid/component.lua
index 2e1e1b6..fb29b40 100644
--- a/druid/component.lua
+++ b/druid/component.lua
@@ -64,7 +64,7 @@ BaseComponent.SPECIFIC_UI_MESSAGES = {
local uid = 0
-function BaseComponent.static.get_uid()
+function BaseComponent.create_uid()
uid = uid + 1
return uid
end
@@ -128,7 +128,7 @@ end
--- Set current component nodes
--
--- Used if your component nodes was cloned with `gui.clone_tree`
+-- Use if your component nodes was cloned with `gui.clone_tree` and you got the node tree.
-- @function component:set_nodes
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam table nodes BaseComponent nodes table
@@ -226,7 +226,7 @@ end
-- @tparam BaseComponent self @{BaseComponent}
-- @treturn string The component name
function BaseComponent.get_name(self)
- return self._component.name .. self:get_uid()
+ return self._component.name .. BaseComponent.create_uid()
end
@@ -362,7 +362,7 @@ end
--- Basic constructor of component. It will call automaticaly
--- by `BaseComponent.static.create`
+-- by `BaseComponent.create`
-- @function component:initialize
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam string name BaseComponent name
@@ -375,7 +375,7 @@ function BaseComponent.initialize(self, name, input_priority)
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.get_uid()
+ _uid = BaseComponent.create_uid()
}
end
@@ -512,11 +512,11 @@ end
--- Create new component. It will inheritance from basic Druid component.
--- @function BaseComponent.static.create
+-- @function BaseComponent.create
-- @tparam string name BaseComponent name
-- @tparam[opt=DEFAULT] number input_priority The input priority. The bigger number processed first
-- @local
-function BaseComponent.static.create(name, input_priority)
+function BaseComponent.create(name, input_priority)
-- Yea, inheritance here
local new_class = class(name, BaseComponent)
diff --git a/druid/custom/rich_text/rich_text.lua b/druid/custom/rich_text/rich_text.lua
index 88bedea..b84191f 100644
--- a/druid/custom/rich_text/rich_text.lua
+++ b/druid/custom/rich_text/rich_text.lua
@@ -1,6 +1,18 @@
-- Copyright (c) 2022 Maksim Tuprikov . This code is licensed under MIT license
--- Druid Rich Text custom component.
+-- # Overview #
+--
+--
+--
+-- # Notes #
+--
+-- @usage
+-- local RichText = require("druid.custom.rich_text.rich_text")
+-- ...
+-- self.rich_text = self.druid:new(RichText, "rich_text")
+-- self.rich_text:set_text("Hello, Druid Rich Text!")
+--
-- @module RichText
-- @within BaseComponent
-- @alias druid.rich_text
@@ -21,7 +33,11 @@ local SCHEME = {
}
-function RichText:init(template, nodes)
+--- Rich Text component constructor
+-- @tparam RichText self @{RichText}
+-- @tparam string template The Rich Text template name
+-- @tparam table nodes The node table, if prefab was copied by gui.clone_tree()
+function RichText.init(self, template, nodes)
self:set_template(template)
self:set_nodes(nodes)
@@ -38,7 +54,12 @@ function RichText:init(template, nodes)
end
-function RichText:set_text(text)
+--- Set text for Rich Text
+-- @tparam RichText self @{RichText}
+-- @tparam string text The text to set
+-- @treturn table words
+-- @treturn table line_metrics
+function RichText.set_text(self, text)
self:clean()
local words, settings, line_metrics = rich_text.create(text, self._settings)
@@ -56,6 +77,9 @@ function RichText:on_remove()
end
+--- Get all words, which has a passed tag
+-- @tparam string tag
+-- @treturn table Words
function RichText:tagged(tag)
if not self._words then
return
@@ -65,6 +89,8 @@ function RichText:tagged(tag)
end
+--- Get all current words.
+-- @treturn table Words
function RichText:get_words()
return self._words
end
@@ -99,6 +125,7 @@ function RichText:_create_settings()
end
+--- Clear all created words.
function RichText:clean()
if self._words then
rich_text.remove(self._words)
diff --git a/druid/extended/input.lua b/druid/extended/input.lua
index 2178d46..da1b220 100755
--- a/druid/extended/input.lua
+++ b/druid/extended/input.lua
@@ -115,7 +115,7 @@ end
--- Component init function
-- @tparam Input self @{Input}
--- @tparam node click_node Button node to enabled input component
+-- @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[opt] number keyboard_type Gui keyboard type for input field
function Input.init(self, click_node, text_node, keyboard_type)
diff --git a/druid/system/druid_instance.lua b/druid/system/druid_instance.lua
index ece0568..7f1a45b 100755
--- a/druid/system/druid_instance.lua
+++ b/druid/system/druid_instance.lua
@@ -288,7 +288,7 @@ function DruidInstance.final(self)
end
---- Remove component from Druid instance.
+--- Remove created component from Druid instance.
--
-- Component `on_remove` function will be invoked, if exist.
-- @tparam DruidInstance self
diff --git a/media/emmy_lua_preview.png b/media/emmy_lua_preview.png
new file mode 100644
index 0000000..eb138a4
Binary files /dev/null and b/media/emmy_lua_preview.png differ