diff --git a/README.md b/README.md index b11089e..2c191ed 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,15 @@ [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/insality/druid/ci-workflow.yml?branch=master)](https://github.com/Insality/druid/actions) [![codecov](https://codecov.io/gh/Insality/druid/branch/master/graph/badge.svg)](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** - powerful **Defold** component UI framework that empowers developers to create stunning and customizable GUIs by leveraging a wide range of embedded components or effortlessly designing their own game-specific components. +Try the [**HTML5 version**](https://insality.github.io/druid/druid/) of the **Druid** example app. ## Setup ### Dependency -You can use the **Druid** extension in your own project by adding this project as a [Defold library dependency](https://www.defold.com/manuals/libraries/). Open your `game.project` file and in the dependencies field under project add: +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: **Druid v0.10.3** > [https://github.com/Insality/druid/archive/refs/tags/0.10.3.zip](https://github.com/Insality/druid/archive/refs/tags/0.10.3.zip) @@ -26,89 +23,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** utilizes the `/builtins/input/all.input_binding` input bindings. For custom input bindings, refer to the Input Binding section in the **_[Advanced Setup](docs_md/advanced-setup.md)_**. + +### Advanced Setup +If you need to customize **Druid** according to your specific requirements, you can refer to the **_[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 utilize **Druid**, begin by creating a **Druid** instance to instantiate components and include the main functions of **Druid**: *update*, *final*, *on_message*, and *on_input*. -Here is full **Druid** components list: +When using **Druid** components, provide a node name string as an argument. If you don't have the node name available in some cases, you can pass `gui.get_node()` instead. -### 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** and component methods are called with `:` like `self.druid:new_button()`. +All **Druid** and component methods are invoked using the `:` operator, such as `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 the correct Druid workflow function final(self) self.druid:final() end +-- "update" is used in progress bar, scroll, and timer basic components function update(self, dt) self.druid:update(dt) end +-- "on_message" is 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 +-- "on_input" is used in almost all Druid components function on_input(self, action_id, action) return self.druid:on_input(action_id, action) end @@ -117,9 +77,87 @@ end For all **Druid** instance functions, [see here](https://insality.github.io/druid/modules/DruidInstance.html). + +### API Documentation + +**Druid** offers a wide range of components and functions. To facilitate usage, **Druid** provides comprehensive API documentation with examples and annotations. + +Start reading the API documentation [here](https://insality.github.io/druid/modules/Druid.html). + + +### EmmyLua Annotations [optional] + +[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). + +Since dependencies cannot be processed by external editors, to use the EmmyLua annotations, you should copy the _druid/annotations.lua_ file to your project. + +Remember that you can restart the EmmyLua server to refresh the changes if something goes wrong. + +After the annotations are processed, you should specify the type of "Druid" in the "require" statement: + +```lua +---@type druid +local druid = require("druid.druid") + +-- Now the autocomplete is working +``` + + + + +### Create custom components + +If you want to create your own components, refer to the [Create Custom Components](docs_md/create-custom-components.md) section in the documentation. + +Custom components are one of the most powerful features of **Druid**. They allow you to create your own components effortlessly and utilize them 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](https://insality.github.io/druid/druid/?example=general_sliders) | | +| **[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_hotkey) | | +| **[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,71 +167,43 @@ 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** processes input in a stack-based manner. The most recently created button will be checked first. Create your input GUI components from back to front. +- Remember to include `return` in the `on_input` function: `return self.druid:on_input()`. This is necessary if you have multiple input sources (multiple Druid instances, other input systems, etc.). +- Druid automatically calls `acquire_input_focus` if you have input components. Therefore, manual calling of `acquire_input_focus` is not required. +- When deleting a **Druid** component node, make sure to remove it using `druid:remove(component)`. -[See full FAQ here](docs_md/FAQ.md) +[See the 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 +Try the [**HTML5 version**](https://insality.github.io/druid/druid/) of the **Druid** example app. + +Each example page provides a direct link to the corresponding example code, making it easier for you to understand how to use **Druid**. + +### Code Examples + +Refer to the [**example folder**](https://github.com/Insality/druid/tree/develop/example) for code examples demonstrating how to use **Druid**. ## Documentation To better understand **Druid**, read the following documentation: +- [How To GUI in Defold](https://forum.defold.com/t/how-to-gui-in-defold/73256) - [Druid components](docs_md/01-components.md) - [Create custom components](docs_md/02-creating_custom_components.md) - [See FAQ article](docs_md/FAQ.md) - [Druid styles](docs_md/03-styles.md) -You can fund the full **Druid** documentation here: -https://insality.github.io/druid/ +You can find the full **Druid** documentation here: +https://insality.github.io/druid/modules/Druid.html -## License +## Licenses - Developed and supported by [Insality](https://github.com/Insality) - Original idea by [AGulev](https://github.com/AGulev) 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/01-components.md b/docs_md/01-components.md index 892b8d1..16c30b3 100644 --- a/docs_md/01-components.md +++ b/docs_md/01-components.md @@ -133,7 +133,7 @@ Usually, Place _view_node_ and as children add _content_node_: - *on_scroll_to* (self, position, is_instant) On scroll_to function callback - *on_point_scroll* (self, item_index, position) On scroll_to_index function callback - You can adjust scroll content size by `scroll:set_size(node_size)`. It will setup new size to _content node_ -- You can enabled or disable inertion mode via `scroll:set_intert(state)` +- You can enabled or disable inertion mode via `scroll:set_inert(state)` - You can adjust extra stretch size via `scroll:set_extra_stretch_size` - Multitouch is required for scroll. Scroll is correctly handling touch_id swap while dragging scroll diff --git a/docs_md/advanced-setup.md b/docs_md/advanced-setup.md index 0704e26..c8b7463 100644 --- a/docs_md/advanced-setup.md +++ b/docs_md/advanced-setup.md @@ -1,23 +1,30 @@ -## Input bindings +# Advanced Druid Setup + + +## Input Bindings + +By default, **Druid** utilizes the `/builtins/input/all.input_binding` for input bindings. **Druid** requires the following input bindings: -- Mouse trigger - `Button 1` -> `touch` _For basic input components_ -- Mouse trigger - `Wheel up` -> `mouse_wheel_up` _For scroll component_ -- Mouse trigger - `Wheel down` -> `mouse_wheel_down` _For scroll component_ -- Key trigger - `Backspace` -> `key_backspace` _For back_handler component, input component_ -- Key trigger - `Back` -> `key_back` _For back_handler component, Android back button, input component_ -- Key trigger - `Enter` -> `key_enter` _For input component, optional_ -- Key trigger - `Esc` -> `key_esc` _For input component, optional_ -- Touch triggers - `Touch multi` -> `touch_multi` _For scroll component_ +- Mouse trigger: `Button 1` -> `touch` (for basic input components) +- Mouse trigger: `Wheel up` -> `mouse_wheel_up` (for Scroll component) +- Mouse trigger: `Wheel down` -> `mouse_wheel_down` (for Scroll component) +- Key trigger: `Backspace` -> `key_backspace` (for BackHandler component, input component) +- Key trigger: `Back` -> `key_back` (for BackHandler component, Android back button, input component) +- Key trigger: `Enter` -> `key_enter` (for Input component, optional) +- Key trigger: `Esc` -> `key_esc` (for Input component, optional) +- Touch triggers: `Touch multi` -> `touch_multi` (for Scroll component) ![](media/input_binding_2.png) ![](media/input_binding_1.png) -## 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. -Here is current default values for key bindings: +## Changing Key Bindings (optional) + +If you need to use your own key bindings or key names, you can modify them in your *game.project* file. + +Here are the default values for key bindings: ``` [druid] input_text = text @@ -33,22 +40,22 @@ input_scroll_down = mouse_wheel_down ``` -## Input capturing [optional] +## Input Capturing (optional) -By default, **Druid** will auto-capture input focus, if any input component will be created. So you don't need to call `msg.post(".", "acquire_input_focus")` +By default, **Druid** automatically captures input focus if any input component is created. Therefore, you do not need to call `msg.post(".", "acquire_input_focus")`. -If you don't need this behaviour, you can disable it by setting `druid.no_auto_input` field in _game.project_: +If you do not require this behavior, you can disable it by setting the `druid.no_auto_input` field in the _game.project_ file: ``` [druid] no_auto_input = 1 ``` -## Template name check [optional] +## Template Name Check (optional) -By default, **Druid** will auto check the parent component template name to build the full template name for component. +By default, **Druid** automatically checks the parent component's template name to construct the full template name for the component. It's used in user custom components. -If for some reason you want to pass the full template name by yourself, you can disable it by setting `druid.no_auto_template` field in _game.project_: +If, for some reason, you want to pass the full template name manually, you can disable this feature by setting the `druid.no_auto_template` field in the _game.project_ file: ``` [druid] @@ -56,39 +63,49 @@ no_auto_template = 1 ``` -## Stencil check [optional] +## 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. -To disable this feature add next field in your _game.project_ file +When creating input components inside stencil nodes, **Druid** automatically sets up `component:set_click_zone()` during the _late_init_ component step to restrict input clicks outside of the stencil zone. This is particularly useful for buttons inside scroll stencil nodes. + +To disable this feature, add the following field to your _game.project_ file: ``` [druid] no_stencil_check = 1 ``` -## Code [optional] +## Code Bindings (optional) -Adjust **Druid** settings, if needed: +Adjust **Druid** settings as needed: ```lua 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) +-- The callback should play the sound by name: function(sound_id) ... end +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) +-- The callback should return the localized string by locale ID: function(locale_id) ... end +druid.set_text_function(function(locale_id) + -- return lang.get(locale_id) +end) --- Used for change default Druid style +-- Used to change the default Druid style druid.set_default_style(your_style) --- Call this function on language changing in the game, +-- Call this function when the language changes 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: +-- to capture 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/docs_md/components/manual_rich_text.md b/docs_md/components/manual_rich_text.md deleted file mode 100644 index aa4ffef..0000000 --- a/docs_md/components/manual_rich_text.md +++ /dev/null @@ -1,59 +0,0 @@ -# Druid Rich Text - -## Links -[Rich Text API here](https://insality.github.io/druid/modules/RichText.html) - -## Overview - - -## Setup - -Rich Text requires the next GUI Node scheme: -```bash - root - ├── text_prefab - └── node_prefab -``` -or make the copy of `/druid/custom/rich_text/rich_text.gui` and adjust your default settings - -Create Rich Text: -```lua -local RichText = require("druid.custom.rich_text.rich_text") - -function init(self) - self.druid = druid.new(self) - self.rich_text = self.druid:new(RichText, "template_name") - self.rich_text:set_text("Insert your text here") -end -``` - -## Usage - -| Tag | Description | Example | -|---------|------------------------------------------------|---------------------------------------------| -| a | Create a "hyperlink" that generates a message | `Foobar` | -| | when clicked (see `richtext.on_click`) | | -| br | Insert a line break (see notes on linebreak) | `
` | -| color | Change text color | `Foobar` | -| | | `Foobar` | -| | | `Foobar` | -| | | `Foobar` | -| shadow | Change text shadow | `Foobar` | -| | | `Foobar` | -| | | `Foobar` | -| | | `Foobar` | -| outline | Change text shadow | `Foobar` | -| | | `Foobar` | -| | | `Foobar` | -| | | `Foobar` | -| font | Change font | `Foobar` | -| img | Display image | `` | -| | Display image in fixed square | `` | -| | Display image in fixed rectangle | `` | -| nobr | Prevent the text from breaking | `Words inside tag won't break` | -| size | Change text size, relative to default size | `Twice as large` | - - -## Usecases - -## Notes diff --git a/druid.code-workspace b/druid.code-workspace index dab8d24..ac43fbc 100644 --- a/druid.code-workspace +++ b/druid.code-workspace @@ -22,6 +22,7 @@ "input": true, "media": true, "build": true, + "docs": true, ".github": true, ".deployer_cache": true, "dist": true diff --git a/druid/annotations.lua b/druid/annotations.lua index e9fd95f..8ede88e 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 @@ -42,8 +42,8 @@ function druid.set_text_function(callback) end ---@class druid.back_handler : druid.base_component ----@field on_back druid.event @{DruidEvent} function(self, [params]) . ----@field params any Params to pass in the callback +---@field on_back druid.event @{DruidEvent} Event on back handler action. +---@field params any Custom args to pass in the callback local druid__back_handler = {} @@ -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} @@ -147,91 +147,96 @@ function druid__base_component.component:set_template(self, template) end ---@class druid.blocker : druid.base_component ----@field node node Trigger node +---@field node node Blocker node local druid__blocker = {} +--- @{Blocker} constructor +---@param self druid.blocker @{Blocker} +---@param node node Gui node +function druid__blocker.init(self, node) end + --- Return blocker enabled state ---@param self druid.blocker @{Blocker} ---@return bool True, if blocker is enabled function druid__blocker.is_enabled(self) end ---- Set enabled blocker component state +--- Set enabled blocker component state. +--- Don't change node enabled state itself. ---@param self druid.blocker @{Blocker} ---@param state bool Enabled state 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 hover druid.hover @{Hover}: Button Hover component +---@field node Node Button trigger node +---@field node_id hash The GUI node id from button 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} constructor ---@param self druid.button @{Button} ----@param node node Gui node ----@param callback function Button callback ----@param params table Button callback params ----@param anim_node node Button anim node (node, if not provided) -function druid__button.init(self, node, callback, params, anim_node) end +---@param node string|Node Node name or GUI Node itself +---@param callback function On click button callback +---@param custom_args any Button events custom arguments +---@param anim_node string|Node Node to animate instead of trigger node. +function druid__button.init(self, node, callback, custom_args, anim_node) end ---- Return button enabled state +--- Get button enabled state. +--- By default all Buttons is enabled on creating. ---@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 ---@param self druid.button ---@param check_function function Should return true or false. If true - button can be pressed. ----@param failure_callback function Function what will be called on button click, if check function return false +---@param failure_callback function Function will be called on button click, if check function return false ---@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 ----@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 +--- Set Button mode to work inside user HTML5 interaction event. +--- It's required to make protected things like copy & paste text, show mobile keyboard, etc The HTML5 button's doesn't call any events except on_click event. If the game is not HTML, html mode will be not enabled +---@param self druid.button +---@param is_web_mode boolean If true - button will be called inside html5 callback +---@return druid.button Current button instance +function druid__button.set_web_user_interaction(self, is_web_mode) end + ---@class druid.button.style ---@field AUTOHOLD_TRIGGER field Maximum hold time to trigger button release while holding @@ -647,7 +652,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 @@ -715,12 +720,12 @@ local druid__lang_text = {} ---@return druid.lang_text Current instance function druid__lang_text.format(self, a, b, c, d, e, f, g) end ---- Component init function +--- @{LangText} constructor ---@param self druid.lang_text @{LangText} ----@param node node The text node +---@param node string|node Node name or GUI Text Node itself ---@param locale_id string Default locale id or text from node as default ----@param no_adjust bool If true, will not correct text size -function druid__lang_text.init(self, node, locale_id, no_adjust) end +---@param adjust_type string Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference +function druid__lang_text.init(self, node, locale_id, adjust_type) end --- Setup raw text to lang_text component ---@param self druid.lang_text @{LangText} @@ -836,7 +841,7 @@ function druid__pin_knob.set_friction(self, value) end ---@class druid.progress : druid.base_component ----@field key string The progress bar direction +---@field key string The progress bar direction. ---@field max_size number Maximum size of progress bar ---@field node node Progress bar fill node ---@field on_change druid.event On progress bar change callback(self, new_value) @@ -858,9 +863,9 @@ function druid__progress.fill(self) end ---@param self druid.progress @{Progress} function druid__progress.get(self) end ---- Component init function +--- @{Progress} constructor ---@param self druid.progress @{Progress} ----@param node string|node Progress bar fill node or node name +---@param node string|node Node name or GUI Node itself. ---@param key string Progress bar direction: const.SIDE.X or const.SIDE.Y ---@param init_value number Initial value of progress bar function druid__progress.init(self, node, key, init_value) end @@ -942,6 +947,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) @@ -978,10 +1008,10 @@ function druid__scroll.get_percent(self) end ---@return vector3 Available scroll size function druid__scroll.get_scroll_size(self) end ---- Scroll constructor +--- @{Scroll} constructor ---@param self druid.scroll @{Scroll} ----@param view_node node GUI view scroll node ----@param content_node node GUI content scroll node +---@param view_node string|node GUI view scroll node +---@param content_node string|node GUI content scroll node function druid__scroll.init(self, view_node, content_node) end --- Return if scroll have inertion. @@ -1187,9 +1217,9 @@ function druid__static_grid.get_pos(self, index) end ---@return vector3 The grid content size function druid__static_grid.get_size(self) end ---- Component init function +--- @{StaticGrid} constructor ---@param self druid.static_grid @{StaticGrid} ----@param parent node The gui node parent, where items will be placed +---@param parent string|Node The GUI Node container, where grid's items will be placed ---@param element node Element prefab. Need to get it size ---@param in_row number How many nodes in row can be placed function druid__static_grid.init(self, parent, element, in_row) end @@ -1285,11 +1315,11 @@ function druid__text.get_text_adjust(self, adjust_type) end ---@return number Height function druid__text.get_text_size(self, text) end ---- Component init function +--- @{Text} constructor ---@param self druid.text @{Text} ----@param node node Gui text node +---@param node string|node Node name or GUI Text Node itself ---@param value string Initial text. Default value is node text from GUI scene. ----@param adjust_type int Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference +---@param adjust_type string Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference function druid__text.init(self, node, value, adjust_type) end --- Return true, if text with line break @@ -1578,7 +1608,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/back_handler.lua b/druid/base/back_handler.lua index 227103e..93fe989 100644 --- a/druid/base/back_handler.lua +++ b/druid/base/back_handler.lua @@ -1,18 +1,16 @@ -- Copyright (c) 2023 Maksim Tuprikov . This code is licensed under MIT license --- Component with event on back and backspace button. --- # Overview # +-- # Overview # -- -- Back Handler is recommended to put in every game window to close it -- or in main screen to call settings window. -- --- # Tech Info # --- --- Back Handler react on release action ACTION_BACK or ACTION_BACKSPACE --- --- # Notes # +-- # Notes # -- -- • 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 -- @@ -22,7 +20,7 @@ -- @within BaseComponent -- @alias druid.back_handler ---- @{DruidEvent} function(self, [params]) . +--- @{DruidEvent} Event on back handler action. -- -- Trigger on input action ACTION_BACK or ACTION_BACKSPACE -- @usage @@ -30,7 +28,7 @@ -- back_handler.on_back:subscribe(callback) -- @tfield DruidEvent on_back @{DruidEvent} ---- Params to pass in the callback +--- Custom args to pass in the callback -- @usage -- -- Replace params on runtime: -- back_handler.params = { ... } @@ -45,13 +43,13 @@ local component = require("druid.component") local BackHandler = component.create("back_handler") ---- Component initialize function +--- @{BackHandler} constructor -- @tparam BackHandler self @{BackHandler} -- @tparam callback callback On back button --- @tparam[opt] any params Callback argument +-- @tparam[opt] any custom_args Button events custom arguments -- @local -function BackHandler.init(self, callback, params) - self.params = params +function BackHandler.init(self, callback, custom_args) + self.params = custom_args self.on_back = Event(callback) end diff --git a/druid/base/blocker.lua b/druid/base/blocker.lua index 3c232f9..6ee9b26 100644 --- a/druid/base/blocker.lua +++ b/druid/base/blocker.lua @@ -1,19 +1,17 @@ -- Copyright (c) 2023 Maksim Tuprikov . This code is licensed under MIT license ---- Component to block input in special zone defined by GUI node. --- # Overview # +--- Component to consume input in special zone defined by GUI node. +-- # Overview # -- --- Blocker component необходим, чтобы блокировать пользовательский ввод в определенной зоне. --- Зона задается размером ноды, на которой находится компонент. Blocker блокирует ввод только для тех --- элементов, которые находятся перед ним in input stack (созданы до него). --- --- # Tech Info # +-- # Notes # -- -- Blocker consume input if `gui.pick_node` works on it. -- --- # Notes # --- -- • 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) @@ -21,7 +19,7 @@ -- @within BaseComponent -- @alias druid.blocker ----Trigger node +---Blocker node -- @tfield node node --- @@ -32,12 +30,12 @@ local component = require("druid.component") local Blocker = component.create("blocker") ---- Component initialize function +--- @{Blocker} constructor -- @tparam Blocker self @{Blocker} -- @tparam node node Gui node --- @local function Blocker.init(self, node) self.node = self:get_node(node) + self._is_enabled = gui.is_enabled(self.node, true) end @@ -57,6 +55,10 @@ function Blocker.on_input(self, action_id, action) return false end + if not gui.is_enabled(self.node, true) then + return false + end + if gui.pick_node(self.node, action.x, action.y) then return true end @@ -65,11 +67,13 @@ function Blocker.on_input(self, action_id, action) end ---- Set enabled blocker component state +--- Set enabled blocker component state. +-- +-- Don't change node enabled state itself. -- @tparam Blocker self @{Blocker} -- @tparam bool state Enabled state function Blocker.set_enabled(self, state) - gui.set_enabled(self.node, state) + self._is_enabled = state end @@ -77,7 +81,7 @@ end -- @tparam Blocker self @{Blocker} -- @treturn bool True, if blocker is enabled function Blocker.is_enabled(self) - return gui.is_enabled(self.node) + return self._is_enabled end diff --git a/druid/base/button.lua b/druid/base/button.lua index c295480..628b58e 100755 --- a/druid/base/button.lua +++ b/druid/base/button.lua @@ -1,56 +1,137 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license ---- Component to handle basic GUI button +--- Druid Component for Handling User Click Interactions: Click, Long Click, Double Click, and More. +-- +-- # Overview # +-- +-- This component provides a versatile solution for handling user click interactions. +-- It allows you to make any GUI node clickable and define various callbacks for different types of clicks. +-- +-- # Notes # +-- +-- • The click callback will not trigger if the cursor moves outside the node's +-- area between the pressed and released states. +-- +-- • If a button has a double click event subscriber and the double click event is triggered, +-- the regular click callback will not be triggered. +-- +-- • Buttons can be triggered using a keyboard key by calling the button:set_key_trigger method. +-- +-- • To animate a small icon on a big button panel, you can use an animation node. +-- The trigger node name should be set as "big panel," and the animation node should be set as "small icon." +-- +-- Example Link +-- @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 --- @tfield node node +--- Button trigger node +-- @tfield Node node ----The hash of trigger node --- @tfield node_id hash +---The GUI node id from button node +-- @tfield hash node_id ----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 --- @@ -170,7 +251,7 @@ end --- Component style params. --- You can override this component styles params in druid styles table +-- You can override this component styles params in Druid styles table -- or create your own style -- @table style -- @tfield[opt=0.4] number LONGTAP_TIME Minimum time to trigger on_hold_callback @@ -195,13 +276,13 @@ function Button.on_style_change(self, style) end ---- Component init function +--- @{Button} constructor -- @tparam Button self @{Button} --- @tparam node node Gui node --- @tparam function callback Button callback --- @tparam[opt] table params Button callback params --- @tparam[opt] node anim_node Button anim node (node, if not provided) -function Button.init(self, node, callback, params, anim_node) +-- @tparam string|Node node Node name or GUI Node itself +-- @tparam function callback On click button callback +-- @tparam[opt] any custom_args Button events custom arguments +-- @tparam[opt] string|Node anim_node Node to animate instead of trigger node. +function Button.init(self, node, callback, custom_args, anim_node) self.druid = self:get_druid() self.node = self:get_node(node) self.node_id = gui.get_id(self.node) @@ -209,7 +290,7 @@ function Button.init(self, node, callback, params, anim_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 = params + self.params = custom_args self.hover = self.druid:new_hover(node, on_button_hover) self.hover.on_mouse_hover:subscribe(on_button_mouse_hover) self.click_zone = nil @@ -222,7 +303,7 @@ function Button.init(self, node, callback, params, anim_node) self._check_function = nil self._failure_callback = nil - -- Event stubs + -- Events self.on_click = Event(callback) self.on_pressed = Event() self.on_repeated_click = Event() @@ -357,10 +438,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 +456,27 @@ function Button.set_enabled(self, state) end ---- Return button enabled state +--- Get button enabled state. +-- +-- By default all Buttons is enabled on creating. -- @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 +485,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 +498,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 @@ -413,7 +511,7 @@ end --- Set function for additional check for button click availability -- @tparam Button self -- @tparam[opt] function check_function Should return true or false. If true - button can be pressed. --- @tparam[opt] function failure_callback Function what will be called on button click, if check function return false +-- @tparam[opt] function 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) self._check_function = check_function @@ -421,14 +519,19 @@ function Button.set_check_function(self, check_function, failure_callback) 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 Button mode to work inside user HTML5 interaction event. +-- +-- It's required to make protected things like copy & paste text, show mobile keyboard, etc +-- The HTML5 button's doesn't call any events except on_click event. +-- +-- If the game is not HTML, html mode will be not enabled -- @tparam Button self --- @tparam[opt] boolean is_html_mode If true - button will be called inside html5 callback +-- @tparam[opt] boolean is_web_mode If true - button will be called inside html5 callback -- @treturn Button Current button instance -function Button.set_html5_user_interaction(self, is_html_mode) - self._is_html5_mode = is_html_mode and html5 +-- @usage +-- button:set_web_user_interaction(true) +function Button.set_web_user_interaction(self, is_web_mode) + self._is_html5_mode = is_web_mode and html5 return self end diff --git a/druid/base/drag.lua b/druid/base/drag.lua index 2667ca4..5c420db 100644 --- a/druid/base/drag.lua +++ b/druid/base/drag.lua @@ -4,6 +4,8 @@ -- Drag have correct handling for multitouch and swap -- touched while dragging. Drag will be processed even -- the cursor is outside of node, if drag is already started +-- +-- Example Link -- @module Drag -- @within BaseComponent -- @alias druid.drag diff --git a/druid/base/scroll.lua b/druid/base/scroll.lua index 3850e12..a7b510a 100755 --- a/druid/base/scroll.lua +++ b/druid/base/scroll.lua @@ -1,12 +1,38 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Component to handle scroll content. --- Scroll consist from two nodes: scroll parent and scroll input --- Scroll input the user input zone, it's static --- Scroll parent the scroll moving part, it will change position. --- Setup initial scroll size by changing scroll parent size. If scroll parent --- size will be less than scroll_input size, no scroll is available. For scroll --- parent size should be more than input size +-- # Overview # +-- +-- The Scroll component is designed to handle scrollable content and consists of two nodes: the scroll parent and the scroll input. +-- +-- The scroll input represents the user input zone and remains static. +-- +-- The scroll parent is the movable part of the scroll and changes its position. +-- +-- The initial scroll size can be set by adjusting the size of the scroll parent. +-- If the size of the scroll parent is smaller than the scroll input size, scrolling is not available. +-- +-- # Notes # +-- +-- • By default, the scroll style includes inertia and extra size for a stretching effect. +-- These settings can be adjusted using the scroll style settings. +-- For more details, refer to the scroll style settings. +-- +-- • "Points of interest" can be set up for the scroll. +-- The scroll will always be centered on the closest point of interest. +-- This feature allows creating a slider without inertia and with points of interest on each scroll element. +-- +-- • The scroll content size can be adjusted using the scroll:set_size(node_size) method. +-- This method sets a new size for the _content node. +-- +-- • Inertial scrolling mode can be enabled or disabled using the scroll:set_inert(state) method. +-- +-- • The extra stretch size can be adjusted using the scroll:set_extra_stretch_size method. +-- +-- • Multitouch is required for scrolling. The scroll component correctly handles +-- touch ID swaps while dragging the scroll. +-- +-- Example Link -- @module Scroll -- @within BaseComponent -- @alias druid.scroll @@ -132,10 +158,10 @@ function Scroll.on_style_change(self, style) end ---- Scroll constructor +--- @{Scroll} constructor -- @tparam Scroll self @{Scroll} --- @tparam node view_node GUI view scroll node --- @tparam node content_node GUI content scroll node +-- @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) self.druid = self:get_druid() diff --git a/druid/base/static_grid.lua b/druid/base/static_grid.lua index 93e4e86..1274a87 100644 --- a/druid/base/static_grid.lua +++ b/druid/base/static_grid.lua @@ -1,7 +1,36 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license ---- Component to handle placing components by row and columns. --- Grid can anchor your elements, get content size and other +--- Component to handle component's position by row and columns. +-- ## Overview ## +-- +-- The Static Grid component allows for positioning components in rows and columns. +-- It provides a static grid layout with constant node sizes, allowing for pre-calculated +-- node positions and the option to include gaps between nodes. +-- +-- ## Notes ## +-- +-- • In a static grid, the node size remains constant, enabling the calculation of node +-- positions before placement. Nodes can be placed with gaps between them. +-- +-- • The static grid can automatically shift elements when nodes are added or removed. +-- +-- • When a node is added, the grid will set the node's parent to the specified parent_node. +-- +-- • You can obtain an array of positions for each element, which can be used to set +-- points of interest in a scroll component. +-- +-- • The size of all elements can be retrieved for setting up the size in a scroll component. +-- +-- • The grid can be bound to a scroll component for automatic resizing of the scroll content size. +-- +-- • The pivot of the parent_node affects the node placement within the grid. +-- +-- • A prefab node is used to determine the node size and anchor. +-- +-- • You can specify a position_function for animations using the +-- _static_grid:set_position_function(node, pos) callback. The default position function is gui.set_position(). +-- +-- Example Link -- @module StaticGrid -- @within BaseComponent -- @alias druid.static_grid @@ -81,9 +110,9 @@ function StaticGrid.on_style_change(self, style) end ---- Component init function +--- @{StaticGrid} constructor -- @tparam StaticGrid self @{StaticGrid} --- @tparam node parent The gui node parent, where items will be placed +-- @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[opt=1] number in_row How many nodes in row can be placed function StaticGrid.init(self, parent, element, in_row) diff --git a/druid/base/text.lua b/druid/base/text.lua index 5d7d110..1735311 100755 --- a/druid/base/text.lua +++ b/druid/base/text.lua @@ -1,8 +1,36 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license ---- Component to handle all GUI texts. --- Druid text can adjust itself for text node size --- Text will never will be outside of his text size (even multiline) +--- Component for Wrapping GUI Text Nodes: Druid Text +-- +-- ## Overview ## +-- +-- Druid Text is a component that provides various adjustment modes for text nodes. It allows text to be scaled down to fit within the size of the text node. +-- +-- ## Notes ## +-- +-- • The text pivot can be changed using the text:set_pivot method. +-- The anchoring will be inside the text node's area size. +-- +-- • There are several text adjustment types available. The default is DOWNSCALE. +-- You can change the default adjustment type in the Text style. Refer to the example below to see all available adjustment types: +-- +-- - const.TEXT_ADJUST.DOWNSCALE: Changes the text's scale to fit within the text node's size. +-- +-- - const.TEXT_ADJUST.TRIM: Trims the text with a postfix (default: "...", can be overridden in styles) +-- to fit within the text node's size. +-- +-- - const.TEXT_ADJUST.NO_ADJUST: No adjustment is applied, similar +-- to the default Defold Text Node behavior. +-- +-- - const.TEXT_ADJUST.DOWNSCALE_LIMITED: Changes the text's scale +-- with a limited downscale. You can set the minimum scale using the text:set_minimal_scale() function. +-- +-- - const.TEXT_ADJUST.SCROLL: Changes the text's pivot to imitate scrolling within the text box. +-- For better effect, use with a stencil node. +-- +-- - const.TEXT_ADJUST.SCALE_THEN_SCROLL: Combines two modes: limited downscale first, then scroll. +-- +-- Example Link -- @module Text -- @within BaseComponent -- @alias druid.text @@ -188,11 +216,11 @@ function Text.on_style_change(self, style) end ---- Component init function +--- @{Text} constructor -- @tparam Text self @{Text} --- @tparam node node Gui text node +-- @tparam string|node node Node name or GUI Text Node itself -- @tparam[opt] string value Initial text. Default value is node text from GUI scene. --- @tparam[opt=0] int adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference +-- @tparam[opt=downscale] string adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference function Text.init(self, node, value, adjust_type) self.node = self:get_node(node) self.pos = gui.get_position(self.node) 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/const.lua b/druid/const.lua index aedd768..87013a1 100755 --- a/druid/const.lua +++ b/druid/const.lua @@ -52,7 +52,6 @@ M.MESSAGE_INPUT = { BUTTON_LONG_CLICK = "button_long_click", BUTTON_DOUBLE_CLICK = "button_double_click", BUTTON_REPEATED_CLICK = "button_repeated_click", - -- (value) TEXT_SET = "text_set", } diff --git a/druid/custom/rich_text/module/rt.lua b/druid/custom/rich_text/module/rt.lua index 5f3d309..5b82a09 100755 --- a/druid/custom/rich_text/module/rt.lua +++ b/druid/custom/rich_text/module/rt.lua @@ -449,9 +449,9 @@ function M.set_text_scale(words, settings, scale) end ----@param words rich_text.word[] ----@param settings rich_text.settings ----@param lines_metrics rich_text.lines_metrics +---@param words druid.rich_text.word[] +---@param settings druid.rich_text.settings +---@param lines_metrics druid.rich_text.lines_metrics function M.adjust_to_area(words, settings, lines_metrics) local last_line_metrics = lines_metrics @@ -486,7 +486,7 @@ function M.adjust_to_area(words, settings, lines_metrics) end adjust_scale = adjust_scale + step - local lines = M.apply_scale_without_update(words, settings, adjust_scale) + lines = M.apply_scale_without_update(words, settings, adjust_scale) is_fit = M.is_fit_info_area(lines, settings) if i == M.ADJUST_STEPS then @@ -534,52 +534,6 @@ function M.tagged(words, tag) end ---- Split a word into it's characters --- @param word The word to split --- @return The individual characters -function M.characters(word) - assert(word) - - local parent = gui.get_parent(word.node) - local font = gui.get_font(word.node) - local layer = gui.get_layer(word.node) - local pivot = gui.get_pivot(word.node) - - local word_length = utf8.len(word.text) - - -- exit early if word is a single character or empty - if word_length <= 1 then - local char = helper.deepcopy(word) - char.node, char.metrics = create_node(char, parent, font) - gui.set_pivot(char.node, pivot) - gui.set_position(char.node, gui.get_position(word.node)) - gui.set_layer(char.node, layer) - return { char } - end - - -- split word into characters - local chars = {} - local position = gui.get_position(word.node) - local position_x = position.x - - for i = 1, word_length do - local char = helper.deepcopy(word) - chars[#chars + 1] = char - char.text = utf8.sub(word.text, i, i) - char.node, char.metrics = create_node(char, parent, font) - gui.set_layer(char.node, layer) - gui.set_pivot(char.node, pivot) - - local sub_metrics = get_text_metrics(word, font, utf8.sub(word.text, 1, i)) - position.x = position_x + sub_metrics.width - char.metrics.width - char.position = vmath.vector3(position) - gui.set_position(char.node, char.position) - end - - return chars -end - - ---Removes the gui nodes created by rich text function M.remove(words) assert(words) diff --git a/druid/custom/rich_text/rich_text.lua b/druid/custom/rich_text/rich_text.lua index 88bedea..30a6948 100644 --- a/druid/custom/rich_text/rich_text.lua +++ b/druid/custom/rich_text/rich_text.lua @@ -1,6 +1,89 @@ -- Copyright (c) 2022 Maksim Tuprikov . This code is licensed under MIT license ---- Druid Rich Text custom component. +--- Druid Rich Text Custom Component. +-- # Overview # +-- +-- This custom component is inspired by defold-richtext by britzl. +-- It uses a similar syntax for tags but currently supports fewer tags. +-- +-- All parameters for the Rich Text component are adjusted in the GUI scene. +-- +-- This component uses GUI component template. (/druid/custom/rich_text/rich_text.gui). +-- +-- You able to customize it or make your own with the next node scructure: +-- +-- root +-- +-- - text_prefab +-- +-- - icon_prefab +-- +-- # Rich Text Setup # +-- +-- • Root node size: Set the maximum width and height of the text. +-- +-- • Root anchor: Define the alignment of the Rich Text inside the root node size area. +-- +-- • Text prefab: Configure all default text parameters for the text node. +-- +-- • Text prefab anchor: Set the anchor for each text node (adjust this only if animating text). +-- +-- • Icon prefab: Configure all default node parameters for the icon node. +-- +-- • Icon prefab anchor: Set the anchor for each icon node (adjust this only if animating the icon). +-- +-- # Notes # +-- +-- • Nested tags are supported +-- +-- Example Link +-- @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!") +-- @usage +-- type druid.rich_text.word = { +-- node: Node, +-- relative_scale: number, +-- color: vector4, +-- position: vector3, +-- offset: vector3, +-- scale: vector3, +-- size: vector3, +-- metrics: druid.rich_text.metrics, +-- pivot: Pivot, +-- text: string, +-- shadow: vector4, +-- outline: vector4, +-- font: string, +-- image: druid.rich_text.image, +-- default_animation: string, +-- anchor: number, +-- br: boolean, +-- nobr: boolean, +-- } +-- +-- type druid.rich_text.word.image = { +-- texture: string, +-- anim: string, +-- width: number, +-- height: number, +-- } +-- +-- type druid.rich_text.lines_metrics = { +-- text_width: number, +-- text_height: number, +-- lines: table, +-- } +-- +-- type druid.rich_text.metrics = { +-- width: number, +-- height: number, +-- offset_x: number|nil, +-- offset_y: number|nil, +-- node_size: vector3|nil @For images only, +-- } -- @module RichText -- @within BaseComponent -- @alias druid.rich_text @@ -21,7 +104,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 +125,55 @@ 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 druid.rich_text.word[] words +-- @treturn druid.rich_text.lines_metrics line_metrics +-- @usage +-- • color: Change text color +-- +-- Foobar +-- Foobar +-- Foobar +-- Foobar +-- +-- • shadow: Change text shadow +-- +-- Foobar +-- Foobar +-- Foobar +-- Foobar +-- +-- • outline: Change text shadow +-- +-- Foobar +-- Foobar +-- Foobar +-- Foobar +-- +-- • font: Change font +-- +-- Foobar +-- +-- • size: Change text size, relative to default size +-- +-- Twice as large +-- +-- • br: Insert a line break +-- +--
+-- +-- • nobr: Prevent the text from breaking +-- +-- Words inside tag won't break +-- +-- • img: Display image +-- +-- +-- +-- +function RichText.set_text(self, text) self:clean() local words, settings, line_metrics = rich_text.create(text, self._settings) @@ -56,6 +191,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 +203,8 @@ function RichText:tagged(tag) end +--- Get all current words. +-- @treturn table Words function RichText:get_words() return self._words end @@ -99,6 +239,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/druid.lua b/druid/druid.lua index 7132e5e..fe90baf 100644 --- a/druid/druid.lua +++ b/druid/druid.lua @@ -1,15 +1,15 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Druid UI Component Framework. --- # Overview # +-- # Overview # -- -- 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. -- --- To start using Druid, please refer to the Basic Usage section below. +-- To start using Druid, please refer to the Usage section below. -- --- # Tech Info # +-- # Notes # -- -- • Each Druid instance maintains the self context from the constructor and passes it to each Druid callback. -- diff --git a/druid/event.lua b/druid/event.lua index bbd49df..6a61594 100644 --- a/druid/event.lua +++ b/druid/event.lua @@ -1,9 +1,10 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license ---- Druid Event module. +--- Druid Event Module -- --- Event is a simple class to handle callbacks. It's used in many Druid components. --- You can subscribe to event with `:subscribe` method and unsubscribe with `:unsubscribe`. +-- The Event module provides a simple class for handling callbacks. It is used in many Druid components. +-- +-- You can subscribe to an event using the `:subscribe` method and unsubscribe using the `:unsubscribe` method. -- @module DruidEvent -- @alias druid.event diff --git a/druid/extended/checkbox.lua b/druid/extended/checkbox.lua index ef1b295..f3ee5fa 100755 --- a/druid/extended/checkbox.lua +++ b/druid/extended/checkbox.lua @@ -1,6 +1,8 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Druid checkbox component +-- +-- Example Link -- @module Checkbox -- @within BaseComponent -- @alias druid.checkbox diff --git a/druid/extended/checkbox_group.lua b/druid/extended/checkbox_group.lua index 2ca9561..046bbfa 100644 --- a/druid/extended/checkbox_group.lua +++ b/druid/extended/checkbox_group.lua @@ -1,6 +1,8 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Checkbox group module +-- +-- Example Link -- @module CheckboxGroup -- @within BaseComponent -- @alias druid.checkbox_group diff --git a/druid/extended/data_list.lua b/druid/extended/data_list.lua index 2c1b011..f7187b7 100644 --- a/druid/extended/data_list.lua +++ b/druid/extended/data_list.lua @@ -2,6 +2,8 @@ --- Component to manage data for huge dataset in scroll. -- It requires Druid Scroll and Druid Grid (Static or Dynamic) components +-- +-- Example Link -- @module DataList -- @within BaseComponent -- @alias druid.data_list diff --git a/druid/extended/dynamic_grid.lua b/druid/extended/dynamic_grid.lua index 5e8dbc6..1fec83f 100644 --- a/druid/extended/dynamic_grid.lua +++ b/druid/extended/dynamic_grid.lua @@ -1,6 +1,8 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Component to handle placing components in row +-- +-- Example Link -- @module DynamicGrid -- @within BaseComponent -- @alias druid.dynamic_grid diff --git a/druid/extended/hotkey.lua b/druid/extended/hotkey.lua index 23ecd49..6985f15 100644 --- a/druid/extended/hotkey.lua +++ b/druid/extended/hotkey.lua @@ -1,6 +1,8 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Druid hotkey component +-- +-- Example Link -- @module Hotkey -- @within BaseComponent -- @alias druid.hotkey diff --git a/druid/extended/input.lua b/druid/extended/input.lua index 2178d46..3cb2bca 100755 --- a/druid/extended/input.lua +++ b/druid/extended/input.lua @@ -2,6 +2,8 @@ --- Druid input text component. -- Carry on user text input +-- +-- Example Link -- @author Part of code from Britzl gooey input component -- @module Input -- @within BaseComponent @@ -115,7 +117,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/extended/lang_text.lua b/druid/extended/lang_text.lua index f30b48a..6b066c5 100755 --- a/druid/extended/lang_text.lua +++ b/druid/extended/lang_text.lua @@ -1,7 +1,18 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license ---- Component to handle all GUI texts --- Good working with localization system +--- Component to wrap over GUI Text nodes with localization helpers +-- +-- # Overview # +-- +-- • The initialization of druid.set_text_function is required to enable localization +-- using the localization ID. +-- +-- • The LangText component supports up to 7 string format parameters. +-- This limitation exists due to certain issues with using ... arguments. +-- +-- # Notes # +-- +-- Example Link -- @module LangText -- @within BaseComponent -- @alias druid.lang_text @@ -21,14 +32,14 @@ local component = require("druid.component") local LangText = component.create("lang_text") ---- Component init function +--- @{LangText} constructor -- @tparam LangText self @{LangText} --- @tparam node node The text node +-- @tparam string|node node Node name or GUI Text Node itself -- @tparam string locale_id Default locale id or text from node as default --- @tparam bool no_adjust If true, will not correct text size -function LangText.init(self, node, locale_id, no_adjust) +-- @tparam[opt=downscale] string 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) self.druid = self:get_druid() - self.text = self.druid:new_text(node, locale_id, no_adjust) + self.text = self.druid:new_text(node, locale_id, adjust_type) self.node = self.text.node self.last_locale_args = {} diff --git a/druid/extended/layout.lua b/druid/extended/layout.lua index 6e8db43..7bcd8f0 100644 --- a/druid/extended/layout.lua +++ b/druid/extended/layout.lua @@ -1,6 +1,8 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Layout management on node +-- +-- Example Link -- @module Layout -- @within BaseComponent -- @alias druid.layout diff --git a/druid/extended/progress.lua b/druid/extended/progress.lua index ed08326..ac24bba 100644 --- a/druid/extended/progress.lua +++ b/druid/extended/progress.lua @@ -1,7 +1,20 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license ---- Basic progress bar component. --- For correct progress bar init it should be in max size from gui +--- Druid component to handle the progress bars. +-- # Overview # +-- +-- # Notes # +-- +-- • Progress Node should be fully filled in your GUI scene node. It will be the progress maximum size +-- +-- • Progress correct working with Slice9 nodes, it trying to set size by _set_size_ first, if it is not possible, it set up sizing via _set_scale_ +-- +-- • Progress bar can fill only by vertical or horizontal size. If you want make diagonal progress bar, just rotate node in GUI scene +-- +-- • If you have glitchy or dark texture bug with progress bar, try to disable mipmaps in your texture profiles +-- +-- +-- Example Link -- @module Progress -- @within BaseComponent -- @alias druid.progress @@ -12,7 +25,9 @@ --- Progress bar fill node -- @tfield node node ---- The progress bar direction +--- The progress bar direction. +-- +-- The values are: "x" or "y". (const.SIDE.X or const.SIDE.Y) -- @tfield string key --- Current progress bar scale @@ -95,16 +110,16 @@ function Progress.on_style_change(self, style) end ---- Component init function +--- @{Progress} constructor -- @tparam Progress self @{Progress} --- @tparam string|node node Progress bar fill node or node name +-- @tparam string|node node Node name or GUI Node itself. -- @tparam string key Progress bar direction: const.SIDE.X or const.SIDE.Y -- @tparam[opt=1] number init_value Initial value of progress bar function Progress.init(self, node, key, init_value) assert(key == const.SIDE.X or const.SIDE.Y, "Progress bar key should be 'x' or 'y'") - self.prop = hash("scale."..key) self.key = key + self.prop = hash("scale." .. self.key) self._init_value = init_value or 1 self.node = self:get_node(node) @@ -114,7 +129,7 @@ function Progress.init(self, node, key, init_value) self.slice = gui.get_slice9(self.node) self.last_value = self._init_value - if key == const.SIDE.X then + if self.key == const.SIDE.X then self.slice_size = self.slice.x + self.slice.z else self.slice_size = self.slice.y + self.slice.w diff --git a/druid/extended/radio_group.lua b/druid/extended/radio_group.lua index fef1d00..96aa334 100644 --- a/druid/extended/radio_group.lua +++ b/druid/extended/radio_group.lua @@ -1,6 +1,8 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Radio group module +-- +-- Example Link -- @module RadioGroup -- @within BaseComponent -- @alias druid.radio_group diff --git a/druid/extended/slider.lua b/druid/extended/slider.lua index 4f48e8d..8907a8b 100644 --- a/druid/extended/slider.lua +++ b/druid/extended/slider.lua @@ -1,6 +1,8 @@ -- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license --- Druid slider component +-- +-- Example Link -- @module Slider -- @within BaseComponent -- @alias druid.slider diff --git a/druid/extended/swipe.lua b/druid/extended/swipe.lua index d4ecc27..d263686 100644 --- a/druid/extended/swipe.lua +++ b/druid/extended/swipe.lua @@ -3,6 +3,8 @@ --- Component to handle swipe gestures on node. -- Swipe will be triggered, if swipe was started and -- ended on one node +-- +-- Example Link -- @module Swipe -- @within BaseComponent -- @alias druid.swipe diff --git a/druid/helper.lua b/druid/helper.lua index 3759984..d59880a 100644 --- a/druid/helper.lua +++ b/druid/helper.lua @@ -1,12 +1,16 @@ -- Copyright (c) 2021 Maksim Tuprikov . 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 local const = require("druid.const") local M = {} +M._some = { pepepe = true } local function get_text_width(text_node) @@ -390,7 +394,14 @@ end --- Get text metric from GUI node. -- @function helper.get_text_metrics_from_node -- @tparam Node text_node --- @treturn GUITextMetrics Fields: width, height, max_ascent, max_descent +-- @treturn pepepe +-- @usage +-- type GUITextMetrics = { +-- width: number, +-- height: number, +-- max_ascent: number, +-- max_descent: number +-- } function M.get_text_metrics_from_node(text_node) local font_resource = gui.get_font_resource(gui.get_font(text_node)) local options = { diff --git a/druid/styles/default/style.lua b/druid/styles/default/style.lua index 6908005..3c8a543 100644 --- a/druid/styles/default/style.lua +++ b/druid/styles/default/style.lua @@ -150,7 +150,41 @@ M["text"] = { M["hotkey"] = { - MODIFICATORS = { "key_lshift", "key_rshift", "key_lctrl", "key_rctrl", "key_lalt", "key_ralt", "key_lsuper", "key_rsuper" }, -- Add key ids to mark it as modificator keys + -- Add key ids to mark it as modificator keys + MODIFICATORS = { + "key_lshift", + "key_rshift", + "key_lctrl", + "key_rctrl", + "key_lalt", + "key_ralt", + "key_lsuper", + "key_rsuper" + } +} + + +M["rich_text"] = { + COLORS = { + white = "#FFFFFF", + black = "#000000", + red = "#FF0000", + green = "#00FF00", + blue = "#0000FF", + yellow = "#FFFF00", + magenta = "#FF00FF", + cyan = "#00FFFF", + gray = "#808080", + dark_gray = "#404040", + light_gray = "#C0C0C0", + orange = "#FFA500", + pink = "#FFC0CB", + purple = "#800080", + brown = "#A52A2A", + olive = "#808000", + teal = "#008080", + navy = "#000080", + } } diff --git a/druid/system/druid_instance.lua b/druid/system/druid_instance.lua index ece0568..0bb1f8e 100755 --- a/druid/system/druid_instance.lua +++ b/druid/system/druid_instance.lua @@ -6,7 +6,7 @@ -- -- For a list of all available components, please refer to the "See Also" section. -- --- # Notes # +-- # Notes # -- -- Please review the following API pages: -- @@ -43,27 +43,29 @@ -- -- @module DruidInstance -- @alias druid_instance --- @see Button --- @see Blocker -- @see BackHandler --- @see Input --- @see Text --- @see LangText --- @see Timer --- @see Progress --- @see StaticGrid --- @see DynamicGrid --- @see Scroll --- @see Slider +-- @see Blocker +-- @see Button -- @see Checkbox -- @see CheckboxGroup --- @see RadioGroup --- @see Swipe --- @see Drag -- @see DataList --- @see Hover --- @see Layout +-- @see Drag +-- @see DynamicGrid -- @see Hotkey +-- @see Hover +-- @see Input +-- @see LangText +-- @see Layout +-- @see Progress +-- @see RadioGroup +-- @see RichInput +-- @see RichText +-- @see Scroll +-- @see Slider +-- @see StaticGrid +-- @see Swipe +-- @see Text +-- @see Timer local helper = require("druid.helper") local class = require("druid.system.middleclass") @@ -288,7 +290,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/example/example.gui_script b/example/example.gui_script index fded751..7ff6864 100644 --- a/example/example.gui_script +++ b/example/example.gui_script @@ -85,7 +85,7 @@ local function init_top_panel(self) gui.set_enabled(self.button_menu.node, false) self.button_api = self.druid:new_button("button_api/button", function() - sys.open_url("https://insality.github.io/druid/") + sys.open_url("https://insality.github.io/druid/modules/Druid.html") end) self.button_code = self.druid:new_button("button_code/button", function() @@ -311,5 +311,5 @@ end function on_input(self, action_id, action) - self.druid:on_input(action_id, action) + return self.druid:on_input(action_id, action) end 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