Merge pull request #275 from Insality/update

Prepare for release 12
This commit is contained in:
Maksim Tuprikov
2024-10-17 01:07:21 +03:00
committed by GitHub
103 changed files with 4078 additions and 13492 deletions

View File

@@ -17,7 +17,7 @@ jobs:
- name: Build && Run
run: |
deployer_url="https://raw.githubusercontent.com/Insality/defold-deployer/1/deployer.sh"
curl -s ${deployer_url} | bash -s lbd --headless --settings ./unit_test.txt
curl -s ${deployer_url} | bash -s lbd --headless --settings ./test/test.ini
- name: Upload test report
run: bash <(curl -s https://codecov.io/bash)

4
.gitignore vendored
View File

@@ -10,4 +10,8 @@ Thumbs.db
builtins
dist
deployer_version_settings.txt
.deployer_cache
bob*.jar
manifest.private.der
manifest.public.der

View File

@@ -1,56 +0,0 @@
std = "max"
files['.luacheckrc'].global = false
unused_args = false
max_code_line_length = 120
max_comment_line_length = false
globals = {
"sys",
"go",
"gui",
"label",
"render",
"crash",
"sprite",
"sound",
"tilemap",
"spine",
"particlefx",
"physics",
"factory",
"collectionfactory",
"iac",
"msg",
"vmath",
"url",
"http",
"image",
"json",
"zlib",
"iap",
"push",
"facebook",
"hash",
"hash_to_hex",
"pprint",
"init",
"final",
"update",
"on_input",
"on_message",
"on_reload",
"socket",
"table",
"debug",
"timer",
"window",
"buffer",
"resource",
"defos",
"html5",
"describe",
"before",
"after",
"it",
}

38
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,38 @@
{
"Lua.diagnostics.globals": [
"init",
"final",
"update",
"on_message",
"on_input",
"describe",
"before",
"after",
"it",
"utf8",
"defos",
"clipboard",
"editor"
],
"Lua.workspace.checkThirdParty": false,
"Lua.diagnostics.neededFileStatus": {
"undefined-field": "Any",
"assign-type-mismatch": "Any",
"missing-return": "Any",
"missing-fields": "Any",
"return-type-mismatch": "Any",
"lowercase-global": "Any"
},
"Lua.workspace.ignoreDir": [
".vscode",
"test/tests/*.lua",
"utils/annotations_manual.lua"
],
"Lua.runtime.pathStrict": true,
"Lua.diagnostics.libraryFiles": "Enable",
"Lua.runtime.version": "Lua 5.1",
"Lua.workspace.library": [
"~/Library/Application Support/Code/User/globalStorage/astronachos.defold",
"~/Library/Application Support/Code/User/workspaceStorage/72e25b7e0fdc873ee6f7baa61edbd6b1/astronachos.defold"
]
}

View File

@@ -1,11 +1,11 @@
[![](media/druid_logo.png)](https://insality.github.io/druid/)
[![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#EA4AAA)](https://github.com/sponsors/insality) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/insality) [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/insality)
[![GitHub release (latest by date)](https://img.shields.io/github/v/tag/insality/druid?style=for-the-badge&label=Release)](https://github.com/Insality/druid/tags)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/insality/druid/ci-workflow.yml?branch=master&style=for-the-badge)](https://github.com/Insality/druid/actions)
[![codecov](https://img.shields.io/codecov/c/github/Insality/druid?style=for-the-badge)](https://codecov.io/gh/Insality/druid)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/insality/druid)](https://github.com/Insality/druid/releases)
[![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)
[![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#EA4AAA)](https://github.com/sponsors/insality) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/insality) [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/insality)
**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.
@@ -17,18 +17,26 @@ Try the [**HTML5 version**](https://insality.github.io/druid/druid/) of the **Dr
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.11.0**
**Druid v0.12.0**
> [https://github.com/Insality/druid/archive/refs/tags/0.11.0.zip](https://github.com/Insality/druid/archive/refs/tags/0.11.0.zip)
> [https://github.com/Insality/druid/archive/refs/tags/0.12.0.zip](https://github.com/Insality/druid/archive/refs/tags/0.12.0.zip)
Here is a list of [all releases](https://github.com/Insality/druid/releases).
Size: **67.16 KB**
> The size metrics exlcude the extended components, which are including only on demand.
### Library Size
> **Note:** The library size is calculated based on the build report per platform. The extended components are exlcuded, which are including only on demand.
| Platform | Library Size |
| ---------------- | ------------- |
| HTML5 | **38.96 KB** |
| Desktop / Mobile | **65.97 KB** |
### Input Bindings
**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#input-bindings)_**.
**Druid** utilizes the `/builtins/input/all.input_binding` input bindings. Either use this file for your project by setting the `Runtime -> Input -> Game Binding` field in the `game.project` input section to `/builtins/input/all.input_binding`, or add the specific bindings you need to your game's input binding file. For custom input bindings, refer to the Input Binding section in the [Advanced Setup](https://github.com/Insality/druid/blob/master/docs_md/advanced-setup.md#input-bindings).
## Usage
@@ -140,7 +148,7 @@ druid.register("data_list", data_list)
| **[Slider](https://insality.github.io/druid/modules/Slider.html)** | Logic over GUI Node. Handle draggable node with position restrictions. | [Slider Example](https://insality.github.io/druid/druid/?example=general_sliders) | <img src="media/preview/slider.gif" width="200" height="100"> |
| **[Timer](https://insality.github.io/druid/modules/Timer.html)** | Logic over GUI Text. Handle basic timer functions. | ❌ | <img src="media/preview/timer.gif" width="200" height="100"> |
| **[Hotkey](https://insality.github.io/druid/modules/Hotkey.html)** | Allow to set callbacks for keyboard hotkeys with key modificators. | [Hotkey Example](https://insality.github.io/druid/druid/?example=general_hotkey) | <img src="media/preview/hotkey.gif" width="200" height="100"> |
| **[Layout](https://insality.github.io/druid/modules/Layout.html)** | Logic over GUI Node. 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) | <img src="media/preview/layout.gif" width="200" height="100"> |
| **[Layout](https://insality.github.io/druid/modules/Layout.html)** | Logic over GUI Node. Arrange nodes inside layout node with margin/paddings settings. | [Layout Example](https://insality.github.io/druid/druid/?example=general_layout) | <img src="media/preview/layout.gif" width="200" height="100"> |
For a complete overview, see: **_[components.md](docs_md/01-components.md)_**.
@@ -173,8 +181,6 @@ Each example page provides a direct link to the corresponding example code, maki
Or refer directly to the [**example folder**](https://github.com/Insality/druid/tree/develop/example) for code examples demonstrating how to use **Druid**.
If you want to see examples of GUIs created with Druid, please refer to the [game_examples.md](docs_md/game_examples.md) file.
## Documentation
To better understand **Druid**, read the following documentation:

View File

@@ -4,7 +4,6 @@ description='Documentation for Druid Framework'
file={"./druid",
exclude = {
"./druid/styles/",
"./druid/system/middleclass.lua",
"./druid/templates/",
"./druid/annotations.lua",
"./druid/custom/rich_text/module",

View File

@@ -17,3 +17,4 @@ date,sha,version,build_size,build_time,platform,mode,is_cache_using,commits_coun
2023-08-05T16:31:19Z,37fff52aa59feb20f761ef4d340d9f677743d54b,0.11.693,2456,43,js-web,release,true,693
2023-08-05T16:41:25Z,d7dd4a86b81d73d345ad7e136de9c2c488bc4d8b,0.11.694,2452,43,js-web,release,true,694
2023-10-20T08:23:33Z,9132dc477b645d674ec21efbfcf85f48ef0ea8a6,0.11.718,2544,47,js-web,release,true,718
2024-10-15T16:54:05Z,ea80c874f6c0ea175b317d01ac45c567db9179c7,0.11.0,1840,24,js-web,release,true,796
1 date sha version build_size build_time platform mode is_cache_using commits_count
17 2023-08-05T16:31:19Z 37fff52aa59feb20f761ef4d340d9f677743d54b 0.11.693 2456 43 js-web release true 693
18 2023-08-05T16:41:25Z d7dd4a86b81d73d345ad7e136de9c2c488bc4d8b 0.11.694 2452 43 js-web release true 694
19 2023-10-20T08:23:33Z 9132dc477b645d674ec21efbfcf85f48ef0ea8a6 0.11.718 2544 47 js-web release true 718
20 2024-10-15T16:54:05Z ea80c874f6c0ea175b317d01ac45c567db9179c7 0.11.0 1840 24 js-web release true 796

View File

@@ -147,9 +147,8 @@ local back_handler = self.druid:new_back_handler(callback, [params])
<ul>
<li><span class="parameter">params</span>
<span class="types"><span class="type">any</span></span>
<span class="types"><span class="type">any</span> or <span class="type">nil</span></span>
(<em>optional</em>)
</li>
</ul>

View File

@@ -106,7 +106,7 @@ return AwesomeComponent
<td class="summary">Context used as first arg in all Druid events</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_druid">get_druid(self)</a></td>
<td class="name" nowrap><a href="#get_druid">get_druid(self, template, nodes)</a></td>
<td class="summary">Get Druid instance for inner component creation.</td>
</tr>
<tr>
@@ -226,7 +226,7 @@ return AwesomeComponent
</dd>
<dt>
<a name = "get_druid"></a>
<strong>get_druid(self)</strong>
<strong>get_druid(self, template, nodes)</strong>
</dt>
<dd>
Get Druid instance for inner component creation.
@@ -238,6 +238,14 @@ return AwesomeComponent
<span class="types"><span class="type">BaseComponent</span></span>
<a href="../modules/BaseComponent.html#">BaseComponent</a>
</li>
<li><span class="parameter">template</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
The template name
</li>
<li><span class="parameter">nodes</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a> or <span class="type">nil</span></span>
The nodes table
</li>
</ul>
<h3>Returns:</h3>

View File

@@ -97,7 +97,7 @@
print(&quot;Also the button component is passed in callback params&quot;)
end
local custom_args = &quot;any variable to pass inside callback&quot;
local custom_args = &quot;Any variable to pass inside callback&quot;
local button = self.druid:new_button(&quot;button_name&quot;, on_button_click, custom_args)
</pre>
</ul>
@@ -153,7 +153,7 @@ local button = self.druid:new_button(&quot;button_name&quot;, on_button_click, c
</tr>
<tr>
<td class="name" nowrap><a href="#click_zone">click_zone</a></td>
<td class="summary">Additional button click area, defined by another GUI Node</td>
<td class="summary">Additional button click area, defined by another GUI node</td>
</tr>
<tr>
<td class="name" nowrap><a href="#hover">hover</a></td>
@@ -360,7 +360,7 @@ local button = self.druid:new_button(&quot;button_name&quot;, on_button_click, c
<a href="../modules/Button.html#">Button</a>
</li>
<li><span class="parameter">zone</span>
<span class="types"><a class="type" href="../modules/Button.html#node">node</a> or <span class="type">nil</span></span>
<span class="types"><a class="type" href="../modules/Button.html#node">node</a>, <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Gui node
</li>
</ul>
@@ -433,7 +433,7 @@ button:set_enabled(<span class="keyword">true</span>)</pre>
<a href="../modules/Button.html#">Button</a>
</li>
<li><span class="parameter">key</span>
<span class="types"><span class="type">hash</span></span>
<span class="types"><span class="type">hash</span> or <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The action_id of the input key
</li>
</ul>
@@ -508,19 +508,16 @@ button:set_enabled(<span class="keyword">true</span>)</pre>
<h3>Fields:</h3>
<ul>
<li><span class="parameter">LONGTAP_TIME</span>
<span class="types"><span class="type">number</span></span>
Minimum time to trigger on_hold_callback
(<em>default</em> 0.4)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Minimum time to trigger on_hold_callback. Default: 0.4
</li>
<li><span class="parameter">AUTOHOLD_TRIGGER</span>
<span class="types"><span class="type">number</span></span>
Maximum hold time to trigger button release while holding
(<em>default</em> 0.8)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Maximum hold time to trigger button release while holding. Default: 0.8
</li>
<li><span class="parameter">DOUBLETAP_TIME</span>
<span class="types"><span class="type">number</span></span>
Time between double taps
(<em>default</em> 0.4)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Time between double taps. Default: 0.4
</li>
<li><span class="parameter">on_click</span>
<span class="types"><span class="type">function</span></span>
@@ -565,9 +562,8 @@ button:set_enabled(<span class="keyword">true</span>)</pre>
<ul>
<li><span class="parameter">anim_node</span>
<span class="types"><a class="type" href="../modules/Button.html#node">node</a></span>
(<em>default</em> node)
<span class="types"><a class="type" href="../modules/Button.html#node">node</a> or <span class="type">nil</span></span>
Default node
</li>
</ul>
@@ -581,14 +577,13 @@ button:set_enabled(<span class="keyword">true</span>)</pre>
<strong>click_zone</strong>
</dt>
<dd>
Additional button click area, defined by another GUI Node
Additional button click area, defined by another GUI node
<ul>
<li><span class="parameter">click_zone</span>
<span class="types"><a class="type" href="../modules/Button.html#node">node</a></span>
<span class="types"><a class="type" href="../modules/Button.html#node">node</a> or <span class="type">nil</span></span>
(<em>optional</em>)
</li>
</ul>

View File

@@ -87,7 +87,7 @@
<td class="summary">Return checkbox state</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, node, callback[, click_node=node[, initial_state=false]])</a></td>
<td class="name" nowrap><a href="#init">init(self, node, callback, click_node, initial_state)</a></td>
<td class="summary">The <a href="../modules/Checkbox.html#">Checkbox</a> constructor</td>
</tr>
<tr>
@@ -158,7 +158,7 @@
</dd>
<dt>
<a name = "init"></a>
<strong>init(self, node, callback[, click_node=node[, initial_state=false]])</strong>
<strong>init(self, node, callback, click_node, initial_state)</strong>
</dt>
<dd>
The <a href="../modules/Checkbox.html#">Checkbox</a> constructor
@@ -179,14 +179,12 @@
Checkbox callback
</li>
<li><span class="parameter">click_node</span>
<span class="types"><a class="type" href="../modules/Checkbox.html#node">node</a></span>
Trigger node, by default equals to node
(<em>default</em> node)
<span class="types"><a class="type" href="../modules/Checkbox.html#node">node</a> or <span class="type">nil</span></span>
Trigger node, by default equals to node. Default: node
</li>
<li><span class="parameter">initial_state</span>
<span class="types"><span class="type">boolean</span></span>
<span class="types"><span class="type">boolean</span> or <span class="type">nil</span></span>
The initial state of checkbox, default - false
(<em>default</em> false)
</li>
</ul>
@@ -289,9 +287,8 @@
<ul>
<li><span class="parameter">click_node</span>
<span class="types"><a class="type" href="../modules/Checkbox.html#node">node</a></span>
<span class="types"><a class="type" href="../modules/Checkbox.html#node">node</a> or <span class="type">nil</span></span>
(<em>default</em> node)
</li>
</ul>

View File

@@ -86,7 +86,7 @@
<td class="summary">Return checkbox group state</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, nodes, callback[, click_nodes=node])</a></td>
<td class="name" nowrap><a href="#init">init(self, nodes, callback, click_nodes)</a></td>
<td class="summary">The <a href="../modules/CheckboxGroup.html#">CheckboxGroup</a> constructor</td>
</tr>
<tr>
@@ -142,7 +142,7 @@
</dd>
<dt>
<a name = "init"></a>
<strong>init(self, nodes, callback[, click_nodes=node])</strong>
<strong>init(self, nodes, callback, click_nodes)</strong>
</dt>
<dd>
The <a href="../modules/CheckboxGroup.html#">CheckboxGroup</a> constructor
@@ -163,9 +163,8 @@
Checkbox callback
</li>
<li><span class="parameter">click_nodes</span>
<span class="types"><span class="type">node[]</span></span>
<span class="types"><span class="type">node[]</span> or <span class="type">nil</span></span>
Array of trigger nodes, by default equals to nodes
(<em>default</em> node)
</li>
</ul>

View File

@@ -83,6 +83,10 @@
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#add">add(self, data, index, shift_policy)</a></td>
<td class="summary">Add element to DataList.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#clear">clear(self)</a></td>
<td class="summary">Clear the DataList and refresh visuals</td>
@@ -100,22 +104,10 @@
<td class="summary">Return current data from DataList component</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_first_index">get_first_index(self)</a></td>
<td class="summary">Return first index from data.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_index">get_index(self, data)</a></td>
<td class="summary">Return index for data value</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_last_index">get_last_index(self)</a></td>
<td class="summary">Return last index from data</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_length">get_length(self)</a></td>
<td class="summary">Return amount of data</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, scroll, grid, create_function)</a></td>
<td class="summary">The <a href="../modules/DataList.html#">DataList</a> constructor</td>
</tr>
@@ -124,6 +116,14 @@
<td class="summary">Druid System on_remove function</td>
</tr>
<tr>
<td class="name" nowrap><a href="#remove">remove(self, index, shift_policy)</a></td>
<td class="summary">Remove element from DataList.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#remove_by_data">remove_by_data(self, data, shift_policy)</a></td>
<td class="summary">Remove element from DataList by data value.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#scroll_to_index">scroll_to_index(self, index)</a></td>
<td class="summary">Instant scroll to element with passed index</td>
</tr>
@@ -131,6 +131,10 @@
<td class="name" nowrap><a href="#set_data">set_data(self, data)</a></td>
<td class="summary">Set new data set for DataList component</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_use_cache">set_use_cache(self, is_use_cache)</a></td>
<td class="summary">Set refresh function for DataList component</td>
</tr>
</table>
<h2><a href="#Fields">Fields</a></h2>
<table class="function_list">
@@ -140,7 +144,7 @@
</tr>
<tr>
<td class="name" nowrap><a href="#last_index">last_index</a></td>
<td class="summary">The current visual last data index</td>
<td class="summary">The current last index of visual elements</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_element_add">on_element_add</a></td>
@@ -164,7 +168,7 @@
</tr>
<tr>
<td class="name" nowrap><a href="#top_index">top_index</a></td>
<td class="summary">The current visual top data index</td>
<td class="summary">The current top index of visual elements</td>
</tr>
</table>
@@ -175,6 +179,39 @@
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "add"></a>
<strong>add(self, data, index, shift_policy)</strong>
</dt>
<dd>
Add element to DataList. Currenly untested
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DataList</span></span>
<a href="../modules/DataList.html#">DataList</a>
</li>
<li><span class="parameter">data</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
</li>
<li><span class="parameter">index</span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
</li>
<li><span class="parameter">shift_policy</span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
The constant from const.SHIFT.*
</li>
</ul>
</dd>
<dt>
<a name = "clear"></a>
<strong>clear(self)</strong>
@@ -276,27 +313,6 @@
</dd>
<dt>
<a name = "get_first_index"></a>
<strong>get_first_index(self)</strong>
</dt>
<dd>
Return first index from data. It not always equals to 1
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DataList</span></span>
<a href="../modules/DataList.html#">DataList</a>
</li>
</ul>
</dd>
<dt>
<a name = "get_index"></a>
@@ -322,48 +338,6 @@
</dd>
<dt>
<a name = "get_last_index"></a>
<strong>get_last_index(self)</strong>
</dt>
<dd>
Return last index from data
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DataList</span></span>
<a href="../modules/DataList.html#">DataList</a>
</li>
</ul>
</dd>
<dt>
<a name = "get_length"></a>
<strong>get_length(self)</strong>
</dt>
<dd>
Return amount of data
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DataList</span></span>
<a href="../modules/DataList.html#">DataList</a>
</li>
</ul>
</dd>
<dt>
<a name = "init"></a>
@@ -418,6 +392,64 @@
</dd>
<dt>
<a name = "remove"></a>
<strong>remove(self, index, shift_policy)</strong>
</dt>
<dd>
Remove element from DataList. Currenly untested
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DataList</span></span>
<a href="../modules/DataList.html#">DataList</a>
</li>
<li><span class="parameter">index</span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
</li>
<li><span class="parameter">shift_policy</span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
The constant from const.SHIFT.*
</li>
</ul>
</dd>
<dt>
<a name = "remove_by_data"></a>
<strong>remove_by_data(self, data, shift_policy)</strong>
</dt>
<dd>
Remove element from DataList by data value. Currenly untested
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DataList</span></span>
<a href="../modules/DataList.html#">DataList</a>
</li>
<li><span class="parameter">data</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
</li>
<li><span class="parameter">shift_policy</span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
The constant from const.SHIFT.*
</li>
</ul>
</dd>
<dt>
<a name = "scroll_to_index"></a>
@@ -474,6 +506,37 @@
</dd>
<dt>
<a name = "set_use_cache"></a>
<strong>set_use_cache(self, is_use_cache)</strong>
</dt>
<dd>
Set refresh function for DataList component
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DataList</span></span>
<a href="../modules/DataList.html#">DataList</a>
</li>
<li><span class="parameter">is_use_cache</span>
<span class="types"><span class="type">boolean</span></span>
Use cache version of DataList. Requires make setup of components in on_element_add callback and clean in on_element_remove
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">druid.data_list</span></span>
Current DataList instance
</ol>
</dd>
</dl>
<h2 class="section-header "><a name="Fields"></a>Fields</h2>
@@ -504,7 +567,7 @@
<strong>last_index</strong>
</dt>
<dd>
The current visual last data index
The current last index of visual elements
<ul>
@@ -624,7 +687,7 @@
<strong>top_index</strong>
</dt>
<dd>
The current visual top data index
The current top index of visual elements
<ul>

View File

@@ -129,16 +129,20 @@
<td class="summary">Is component now touching</td>
</tr>
<tr>
<td class="name" nowrap><a href="#node">node</a></td>
<td class="summary">Drag node</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_drag">on_drag</a></td>
<td class="summary">on drag progress callback(self, dx, dy, total_x, total_y)</td>
<td class="summary">on drag progress callback(self, dx, dy, total_x, total_y, touch)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_drag_end">on_drag_end</a></td>
<td class="summary">Event on drag end callback(self, total_x, total_y)</td>
<td class="summary">Event on drag end callback(self, total_x, total_y, touch)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_drag_start">on_drag_start</a></td>
<td class="summary">Event on drag start callback(self)</td>
<td class="summary">Event on drag start callback(self, touch)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_touch_end">on_touch_end</a></td>
@@ -149,6 +153,14 @@
<td class="summary">Event on touch start callback(self)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#screen_x">screen_x</a></td>
<td class="summary">Current touch x screen position</td>
</tr>
<tr>
<td class="name" nowrap><a href="#screen_y">screen_y</a></td>
<td class="summary">Current touch y screen position</td>
</tr>
<tr>
<td class="name" nowrap><a href="#touch_start_pos">touch_start_pos</a></td>
<td class="summary">Touch start position</td>
</tr>
@@ -184,7 +196,7 @@
<a href="../modules/Drag.html#">Drag</a>
</li>
<li><span class="parameter">node</span>
<span class="types"><span class="type">node</span></span>
<span class="types"><a class="type" href="../modules/Drag.html#node">node</a></span>
GUI node to detect dragging
</li>
<li><span class="parameter">on_drag_callback</span>
@@ -241,7 +253,7 @@
<a href="../modules/Drag.html#">Drag</a>
</li>
<li><span class="parameter">node</span>
<span class="types"><span class="type">node</span></span>
<span class="types"><a class="type" href="../modules/Drag.html#node">node</a>, <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Gui node
</li>
</ul>
@@ -293,14 +305,12 @@
<h3>Fields:</h3>
<ul>
<li><span class="parameter">DRAG_DEADZONE</span>
<span class="types"><span class="type">number</span></span>
Distance in pixels to start dragging
(<em>default</em> 10)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Distance in pixels to start dragging. Default: 10
</li>
<li><span class="parameter">NO_USE_SCREEN_KOEF</span>
<span class="types"><span class="type">boolean</span></span>
If screen aspect ratio affects on drag values
(<em>default</em> false)
<span class="types"><span class="type">boolean</span> or <span class="type">nil</span></span>
If screen aspect ratio affects on drag values. Default: false
</li>
</ul>
@@ -392,13 +402,33 @@
</dd>
<dt>
<a name = "node"></a>
<strong>node</strong>
</dt>
<dd>
Drag node
<ul>
<li><span class="parameter">node</span>
<span class="types"><a class="type" href="../modules/Drag.html#node">node</a></span>
</li>
</ul>
</dd>
<dt>
<a name = "on_drag"></a>
<strong>on_drag</strong>
</dt>
<dd>
on drag progress callback(self, dx, dy, total_x, total_y)
on drag progress callback(self, dx, dy, total_x, total_y, touch)
<ul>
@@ -418,7 +448,7 @@
<strong>on_drag_end</strong>
</dt>
<dd>
Event on drag end callback(self, total_x, total_y)
Event on drag end callback(self, total_x, total_y, touch)
<ul>
@@ -438,7 +468,7 @@
<strong>on_drag_start</strong>
</dt>
<dd>
Event on drag start callback(self)
Event on drag start callback(self, touch)
<ul>
@@ -492,6 +522,46 @@
</dd>
<dt>
<a name = "screen_x"></a>
<strong>screen_x</strong>
</dt>
<dd>
Current touch x screen position
<ul>
<li><span class="parameter">screen_x</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "screen_y"></a>
<strong>screen_y</strong>
</dt>
<dd>
Current touch y screen position
<ul>
<li><span class="parameter">screen_y</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "touch_start_pos"></a>

View File

@@ -87,15 +87,23 @@
<td class="summary">Clear the all event handlers</td>
</tr>
<tr>
<td class="name" nowrap><a href="#initialize">initialize(self, initial_callback)</a></td>
<td class="name" nowrap><a href="#create">create(callback, callback_context)</a></td>
<td class="summary">DruidEvent constructor</td>
</tr>
<tr>
<td class="name" nowrap><a href="#is_empty">is_empty(self)</a></td>
<td class="summary">Return true, if event not have handler</td>
</tr>
<tr>
<td class="name" nowrap><a href="#is_exist">is_exist(self)</a></td>
<td class="summary">Return true, if event have at lease one handler</td>
</tr>
<tr>
<td class="name" nowrap><a href="#subscribe">subscribe(self, callback, context)</a></td>
<td class="name" nowrap><a href="#is_subscribed">is_subscribed(self, callback, callback_context)</a></td>
<td class="summary">Check is event subscribed.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#subscribe">subscribe(self, callback, callback_context)</a></td>
<td class="summary">Subscribe callback on event</td>
</tr>
<tr>
@@ -103,7 +111,7 @@
<td class="summary">Trigger the event and call all subscribed callbacks</td>
</tr>
<tr>
<td class="name" nowrap><a href="#unsubscribe">unsubscribe(self, callback, context)</a></td>
<td class="name" nowrap><a href="#unsubscribe">unsubscribe(self, callback, callback_context)</a></td>
<td class="summary">Unsubscribe callback on event</td>
</tr>
</table>
@@ -141,8 +149,8 @@
</dd>
<dt>
<a name = "initialize"></a>
<strong>initialize(self, initial_callback)</strong>
<a name = "create"></a>
<strong>create(callback, callback_context)</strong>
</dt>
<dd>
DruidEvent constructor
@@ -150,14 +158,14 @@
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DruidEvent</span></span>
<a href="../modules/DruidEvent.html#">DruidEvent</a>
</li>
<li><span class="parameter">initial_callback</span>
<li><span class="parameter">callback</span>
<span class="types"><span class="type">function</span> or <span class="type">nil</span></span>
Subscribe the callback on new event, if callback exist
</li>
<li><span class="parameter">callback_context</span>
<span class="types"><span class="type">any</span> or <span class="type">nil</span></span>
Additional context as first param to callback call
</li>
</ul>
@@ -167,7 +175,38 @@
<ul>
<pre class="example"><span class="keyword">local</span> Event = <span class="global">require</span>(<span class="string">"druid.event"</span>)
...
<span class="keyword">local</span> event = Event(initial_callback)</pre>
<span class="keyword">local</span> event = Event(callback)</pre>
</ul>
</dd>
<dt>
<a name = "is_empty"></a>
<strong>is_empty(self)</strong>
</dt>
<dd>
Return true, if event not have handler
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DruidEvent</span></span>
<a href="../modules/DruidEvent.html#">DruidEvent</a>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
True if event not have handlers
</ol>
<h3>Usage:</h3>
<ul>
<pre class="example"><span class="keyword">local</span> is_long_click_handler_not_exists = button.on_long_click:is_empty()</pre>
</ul>
</dd>
@@ -201,10 +240,45 @@
<pre class="example"><span class="keyword">local</span> is_long_click_handler_exists = button.on_long_click:is_exist()</pre>
</ul>
</dd>
<dt>
<a name = "is_subscribed"></a>
<strong>is_subscribed(self, callback, callback_context)</strong>
</dt>
<dd>
Check is event subscribed.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DruidEvent</span></span>
<a href="../modules/DruidEvent.html#">DruidEvent</a>
</li>
<li><span class="parameter">callback</span>
<span class="types"><span class="type">function</span></span>
Callback itself
</li>
<li><span class="parameter">callback_context</span>
<span class="types"><span class="type">any</span> or <span class="type">nil</span></span>
Additional context as first param to callback call
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean,</span></span>
number|nil @Is event subscribed, return index of callback in event as second param
</ol>
</dd>
<dt>
<a name = "subscribe"></a>
<strong>subscribe(self, callback, context)</strong>
<strong>subscribe(self, callback, callback_context)</strong>
</dt>
<dd>
Subscribe callback on event
@@ -220,12 +294,18 @@
<span class="types"><span class="type">function</span></span>
Callback itself
</li>
<li><span class="parameter">context</span>
<li><span class="parameter">callback_context</span>
<span class="types"><span class="type">any</span> or <span class="type">nil</span></span>
Additional context as first param to callback call, usually it's self
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
True if callback was subscribed
</ol>
@@ -274,7 +354,7 @@ event:trigger(<span class="string">"Param1"</span>, <span class="string">"Param2
</dd>
<dt>
<a name = "unsubscribe"></a>
<strong>unsubscribe(self, callback, context)</strong>
<strong>unsubscribe(self, callback, callback_context)</strong>
</dt>
<dd>
Unsubscribe callback on event
@@ -290,7 +370,7 @@ event:trigger(<span class="string">"Param1"</span>, <span class="string">"Param2
<span class="types"><span class="type">function</span></span>
Callback itself
</li>
<li><span class="parameter">context</span>
<li><span class="parameter">callback_context</span>
<span class="types"><span class="type">any</span> or <span class="type">nil</span></span>
Additional context as first param to callback call
</li>

View File

@@ -142,10 +142,6 @@ end
<td class="summary">Call this in gui_script final function.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#new">new(self, component, ...)</a></td>
<td class="summary">Create new component.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#new_back_handler">new_back_handler(self, callback, params)</a></td>
<td class="summary">Create <a href="../modules/BackHandler.html#">BackHandler</a> component</td>
</tr>
@@ -162,7 +158,7 @@ end
<td class="summary">Create <a href="../modules/Checkbox.html#">Checkbox</a> component</td>
</tr>
<tr>
<td class="name" nowrap><a href="#new_checkbox_group">new_checkbox_group(self, nodes, callback[, click_nodes=node])</a></td>
<td class="name" nowrap><a href="#new_checkbox_group">new_checkbox_group(self, nodes, callback, click_nodes)</a></td>
<td class="summary">Create <a href="../modules/CheckboxGroup.html#">CheckboxGroup</a> component</td>
</tr>
<tr>
@@ -182,7 +178,7 @@ end
<td class="summary">Create <a href="../modules/Hotkey.html#">Hotkey</a> component</td>
</tr>
<tr>
<td class="name" nowrap><a href="#new_hover">new_hover(self, node, on_hover_callback)</a></td>
<td class="name" nowrap><a href="#new_hover">new_hover(self, node, on_hover_callback, on_mouse_hover_callback)</a></td>
<td class="summary">Create <a href="../modules/Hover.html#">Hover</a> component</td>
</tr>
<tr>
@@ -202,7 +198,7 @@ end
<td class="summary">Create <a href="../modules/Progress.html#">Progress</a> component</td>
</tr>
<tr>
<td class="name" nowrap><a href="#new_radio_group">new_radio_group(self, nodes, callback[, click_nodes=node])</a></td>
<td class="name" nowrap><a href="#new_radio_group">new_radio_group(self, nodes, callback, click_nodes)</a></td>
<td class="summary">Create <a href="../modules/RadioGroup.html#">RadioGroup</a> component</td>
</tr>
<tr>
@@ -246,11 +242,11 @@ end
<td class="summary">Remove created component from Druid instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_blacklist">set_blacklist(self[, blacklist_components=nil])</a></td>
<td class="name" nowrap><a href="#set_blacklist">set_blacklist(self, blacklist_components)</a></td>
<td class="summary">Set blacklist components for input processing.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_whitelist">set_whitelist(self[, whitelist_components=nil])</a></td>
<td class="name" nowrap><a href="#set_whitelist">set_whitelist(self, whitelist_components)</a></td>
<td class="summary">Set whitelist components for input processing.</td>
</tr>
<tr>
@@ -286,41 +282,6 @@ end
</dd>
<dt>
<a name = "new"></a>
<strong>new(self, component, ...)</strong>
</dt>
<dd>
Create new component.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">DruidInstance</span></span>
</li>
<li><span class="parameter">component</span>
<span class="types"><span class="type">BaseComponent</span></span>
Component module
</li>
<li><span class="parameter">...</span>
<span class="types"><span class="type">any</span></span>
Other component params to pass it to component:init function
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">BaseComponent</span></span>
Component instance
</ol>
</dd>
<dt>
<a name = "new_back_handler"></a>
@@ -411,11 +372,11 @@ end
Button callback
</li>
<li><span class="parameter">params</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a> or <span class="type">nil</span></span>
<span class="types"><span class="type">any</span> or <span class="type">nil</span></span>
Button callback params
</li>
<li><span class="parameter">anim_node</span>
<span class="types"><span class="type">node</span> or <span class="type">nil</span></span>
<span class="types"><span class="type">node</span>, <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Button anim node (node, if not provided)
</li>
</ul>
@@ -476,7 +437,7 @@ end
</dd>
<dt>
<a name = "new_checkbox_group"></a>
<strong>new_checkbox_group(self, nodes, callback[, click_nodes=node])</strong>
<strong>new_checkbox_group(self, nodes, callback, click_nodes)</strong>
</dt>
<dd>
Create <a href="../modules/CheckboxGroup.html#">CheckboxGroup</a> component
@@ -489,7 +450,7 @@ end
</li>
<li><span class="parameter">nodes</span>
<span class="types"><span class="type">node[]</span></span>
<span class="types"><span class="type">(node</span> or <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string)[]</a></span>
Array of gui node
</li>
<li><span class="parameter">callback</span>
@@ -497,9 +458,8 @@ end
Checkbox callback
</li>
<li><span class="parameter">click_nodes</span>
<span class="types"><span class="type">node[]</span></span>
<span class="types"><span class="type">(node</span>, <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string)[]</a> or <span class="type">nil</span></span>
Array of trigger nodes, by default equals to nodes
(<em>default</em> node)
</li>
</ul>
@@ -660,7 +620,7 @@ end
</dd>
<dt>
<a name = "new_hover"></a>
<strong>new_hover(self, node, on_hover_callback)</strong>
<strong>new_hover(self, node, on_hover_callback, on_mouse_hover_callback)</strong>
</dt>
<dd>
Create <a href="../modules/Hover.html#">Hover</a> component
@@ -680,6 +640,10 @@ end
<span class="types"><span class="type">function</span> or <span class="type">nil</span></span>
Hover callback
</li>
<li><span class="parameter">on_mouse_hover_callback</span>
<span class="types"><span class="type">function</span> or <span class="type">nil</span></span>
Mouse hover callback
</li>
</ul>
<h3>Returns:</h3>
@@ -712,7 +676,7 @@ end
Button node to enabled input component
</li>
<li><span class="parameter">text_node</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">node</span></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a>, <span class="type">node</span> or <span class="type">druid.text</span></span>
Text node what will be changed on user input
</li>
<li><span class="parameter">keyboard_type</span>
@@ -847,7 +811,7 @@ end
</dd>
<dt>
<a name = "new_radio_group"></a>
<strong>new_radio_group(self, nodes, callback[, click_nodes=node])</strong>
<strong>new_radio_group(self, nodes, callback, click_nodes)</strong>
</dt>
<dd>
Create <a href="../modules/RadioGroup.html#">RadioGroup</a> component
@@ -860,7 +824,7 @@ end
</li>
<li><span class="parameter">nodes</span>
<span class="types"><span class="type">node[]</span></span>
<span class="types"><span class="type">(node</span> or <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string)[]</a></span>
Array of gui node
</li>
<li><span class="parameter">callback</span>
@@ -868,9 +832,8 @@ end
Radio callback
</li>
<li><span class="parameter">click_nodes</span>
<span class="types"><span class="type">node[]</span></span>
<span class="types"><span class="type">(node</span>, <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string)[]</a> or <span class="type">nil</span></span>
Array of trigger nodes, by default equals to nodes
(<em>default</em> node)
</li>
</ul>
@@ -1211,7 +1174,7 @@ end
Message from on_message
</li>
<li><span class="parameter">sender</span>
<span class="types"><span class="type">hash</span></span>
<span class="types"><span class="type">url</span></span>
Sender from on_message
</li>
</ul>
@@ -1242,6 +1205,12 @@ end
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
True if component was removed
</ol>
@@ -1249,7 +1218,7 @@ end
</dd>
<dt>
<a name = "set_blacklist"></a>
<strong>set_blacklist(self[, blacklist_components=nil])</strong>
<strong>set_blacklist(self, blacklist_components)</strong>
</dt>
<dd>
Set blacklist components for input processing.
@@ -1264,9 +1233,8 @@ end
<a href="../modules/DruidInstance.html#">DruidInstance</a>
</li>
<li><span class="parameter">blacklist_components</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a> or <span class="type">BaseComponent</span></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a>, <span class="type">BaseComponent</span> or <span class="type">nil</span></span>
The array of component to blacklist
(<em>default</em> nil)
</li>
</ul>
@@ -1283,7 +1251,7 @@ end
</dd>
<dt>
<a name = "set_whitelist"></a>
<strong>set_whitelist(self[, whitelist_components=nil])</strong>
<strong>set_whitelist(self, whitelist_components)</strong>
</dt>
<dd>
Set whitelist components for input processing.
@@ -1298,9 +1266,8 @@ end
</li>
<li><span class="parameter">whitelist_components</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a> or <span class="type">BaseComponent</span></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a>, <span class="type">BaseComponent</span> or <span class="type">nil</span></span>
The array of component to whitelist
(<em>default</em> nil)
</li>
</ul>

View File

@@ -420,7 +420,7 @@
<ol>
<span class="types"><span class="type">vector3</span></span>
Node position
node position
</ol>

View File

@@ -151,10 +151,18 @@ helper.centrate_nodes(0, node_1, node_2)
<td class="summary">Check if device is native mobile (Android or iOS)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#helper.is_multitouch_supported">helper.is_multitouch_supported()</a></td>
<td class="summary">Check if device is mobile and can support multitouch</td>
</tr>
<tr>
<td class="name" nowrap><a href="#helper.is_web">helper.is_web()</a></td>
<td class="summary">Check if device is HTML5</td>
</tr>
<tr>
<td class="name" nowrap><a href="#helper.is_web_mobile">helper.is_web_mobile()</a></td>
<td class="summary">Check if device is HTML5 mobile</td>
</tr>
<tr>
<td class="name" nowrap><a href="#helper.lerp">helper.lerp(a, b, t)</a></td>
<td class="summary">Lerp between two values</td>
</tr>
@@ -658,6 +666,26 @@ helper.centrate_nodes(0, node_1, node_2)
</dd>
<dt>
<a name = "helper.is_multitouch_supported"></a>
<strong>helper.is_multitouch_supported()</strong>
</dt>
<dd>
Check if device is mobile and can support multitouch
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
Is multitouch supported
</ol>
</dd>
<dt>
<a name = "helper.is_web"></a>
@@ -678,6 +706,26 @@ helper.centrate_nodes(0, node_1, node_2)
</dd>
<dt>
<a name = "helper.is_web_mobile"></a>
<strong>helper.is_web_mobile()</strong>
</dt>
<dd>
Check if device is HTML5 mobile
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
Is web mobile
</ol>
</dd>
<dt>
<a name = "helper.lerp"></a>

View File

@@ -90,6 +90,10 @@
<td class="name" nowrap><a href="#init">init(self, keys, callback, callback_argument)</a></td>
<td class="summary">The <a href="../modules/Hotkey.html#">Hotkey</a> constructor</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_repeat">set_repeat(self, is_enabled_repeated)</a></td>
<td class="summary">If true, the callback will be triggered on action.repeated</td>
</tr>
</table>
<h2><a href="#Tables">Tables</a></h2>
<table class="function_list">
@@ -113,8 +117,12 @@
<td class="summary">Visual node</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_change_state">on_change_state</a></td>
<td class="summary">On change state callback(self, state)</td>
<td class="name" nowrap><a href="#on_hotkey_pressed">on_hotkey_pressed</a></td>
<td class="summary">On hotkey released callback(self, argument)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_hotkey_released">on_hotkey_released</a></td>
<td class="summary">On hotkey released callback(self, argument)</td>
</tr>
</table>
@@ -192,6 +200,37 @@
</dd>
<dt>
<a name = "set_repeat"></a>
<strong>set_repeat(self, is_enabled_repeated)</strong>
</dt>
<dd>
If true, the callback will be triggered on action.repeated
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Hotkey</span></span>
<a href="../modules/Hotkey.html#">Hotkey</a>
</li>
<li><span class="parameter">is_enabled_repeated</span>
<span class="types"><span class="type">bool</span></span>
The flag value
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">Hotkey</span></span>
</ol>
</dd>
</dl>
<h2 class="section-header "><a name="Tables"></a>Tables</h2>
@@ -254,9 +293,8 @@
<ul>
<li><span class="parameter">click_node</span>
<span class="types"><a class="type" href="../modules/Hotkey.html#node">node</a></span>
<span class="types"><a class="type" href="../modules/Hotkey.html#node">node</a> or <span class="type">nil</span></span>
(<em>default</em> node)
</li>
</ul>
@@ -286,15 +324,35 @@
</dd>
<dt>
<a name = "on_change_state"></a>
<strong>on_change_state</strong>
<a name = "on_hotkey_pressed"></a>
<strong>on_hotkey_pressed</strong>
</dt>
<dd>
On change state callback(self, state)
On hotkey released callback(self, argument)
<ul>
<li><span class="parameter">on_change_state</span>
<li><span class="parameter">on_hotkey_pressed</span>
<span class="types"><span class="type">DruidEvent</span></span>
<a href="../modules/DruidEvent.html#">DruidEvent</a>
</li>
</ul>
</dd>
<dt>
<a name = "on_hotkey_released"></a>
<strong>on_hotkey_released</strong>
</dt>
<dd>
On hotkey released callback(self, argument)
<ul>
<li><span class="parameter">on_hotkey_released</span>
<span class="types"><span class="type">DruidEvent</span></span>
<a href="../modules/DruidEvent.html#">DruidEvent</a>
</li>

View File

@@ -33,6 +33,7 @@
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
<li><a href="#Tables">Tables</a></li>
<li><a href="#Fields">Fields</a></li>
</ul>
@@ -82,7 +83,7 @@
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#init">init(self, node, on_hover_callback)</a></td>
<td class="name" nowrap><a href="#init">init(self, node, on_hover_callback, on_mouse_hover)</a></td>
<td class="summary">The <a href="../modules/Hover.html#">Hover</a> constructor</td>
</tr>
<tr>
@@ -114,8 +115,19 @@
<td class="summary">Set mouse hover state</td>
</tr>
</table>
<h2><a href="#Tables">Tables</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#style">style</a></td>
<td class="summary">Component style params.</td>
</tr>
</table>
<h2><a href="#Fields">Fields</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#node">node</a></td>
<td class="summary">Hover node</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_hover">on_hover</a></td>
<td class="summary">On hover callback(self, state, hover_instance)</td>
@@ -135,7 +147,7 @@
<dl class="function">
<dt>
<a name = "init"></a>
<strong>init(self, node, on_hover_callback)</strong>
<strong>init(self, node, on_hover_callback, on_mouse_hover)</strong>
</dt>
<dd>
The <a href="../modules/Hover.html#">Hover</a> constructor
@@ -148,13 +160,17 @@
<a href="../modules/Hover.html#">Hover</a>
</li>
<li><span class="parameter">node</span>
<span class="types"><span class="type">node</span></span>
<span class="types"><a class="type" href="../modules/Hover.html#node">node</a></span>
Gui node
</li>
<li><span class="parameter">on_hover_callback</span>
<span class="types"><span class="type">function</span></span>
Hover callback
</li>
<li><span class="parameter">on_mouse_hover</span>
<span class="types"><span class="type">function</span></span>
On mouse hover callback
</li>
</ul>
@@ -259,7 +275,7 @@
<a href="../modules/Hover.html#">Hover</a>
</li>
<li><span class="parameter">zone</span>
<span class="types"><span class="type">node</span></span>
<span class="types"><a class="type" href="../modules/Hover.html#node">node</a>, <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Gui node
</li>
</ul>
@@ -345,11 +361,64 @@
</dd>
</dl>
<h2 class="section-header "><a name="Tables"></a>Tables</h2>
<dl class="function">
<dt>
<a name = "style"></a>
<strong>style</strong>
</dt>
<dd>
Component style params.
You can override this component styles params in druid styles table
or create your own style
<h3>Fields:</h3>
<ul>
<li><span class="parameter">ON_HOVER_CURSOR</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Mouse hover style on node hover
(<em>optional</em>)
</li>
<li><span class="parameter">ON_MOUSE_HOVER_CURSOR</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Mouse hover style on node mouse hover
(<em>optional</em>)
</li>
</ul>
</dd>
</dl>
<h2 class="section-header "><a name="Fields"></a>Fields</h2>
<dl class="function">
<dt>
<a name = "node"></a>
<strong>node</strong>
</dt>
<dd>
Hover node
<ul>
<li><span class="parameter">node</span>
<span class="types"><a class="type" href="../modules/Hover.html#node">node</a></span>
</li>
</ul>
</dd>
<dt>
<a name = "on_hover"></a>
<strong>on_hover</strong>

View File

@@ -93,10 +93,18 @@
<td class="summary">Return current input field text</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_text_selected_replaced">get_text_selected_replaced(self, text)</a></td>
<td class="summary">Replace selected text with new text</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, click_node, text_node, keyboard_type)</a></td>
<td class="summary">The <a href="../modules/Input.html#">Input</a> constructor</td>
</tr>
<tr>
<td class="name" nowrap><a href="#move_selection">move_selection(self, delta, is_add_to_selection, is_move_to_end)</a></td>
<td class="summary">Change cursor position by delta</td>
</tr>
<tr>
<td class="name" nowrap><a href="#reset_changes">reset_changes(self)</a></td>
<td class="summary">Reset current input selection and return previous value</td>
</tr>
@@ -105,6 +113,10 @@
<td class="summary">Select input field.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#select_cursor">select_cursor(self, cursor_index, start_index, end_index)</a></td>
<td class="summary">Set cursor position in input field</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_allowed_characters">set_allowed_characters(self, characters)</a></td>
<td class="summary">Set allowed charaters for input field.</td>
</tr>
@@ -139,6 +151,18 @@
<td class="summary">Button component</td>
</tr>
<tr>
<td class="name" nowrap><a href="#current_value">current_value</a></td>
<td class="summary">Current input value with marked text</td>
</tr>
<tr>
<td class="name" nowrap><a href="#cursor_index">cursor_index</a></td>
<td class="summary">The cursor index.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#end_index">end_index</a></td>
<td class="summary">Theselection end index.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#is_empty">is_empty</a></td>
<td class="summary">Is current input is empty now</td>
</tr>
@@ -151,6 +175,14 @@
<td class="summary">Gui keyboard type for input field</td>
</tr>
<tr>
<td class="name" nowrap><a href="#marked_text_width">marked_text_width</a></td>
<td class="summary">Marked text width</td>
</tr>
<tr>
<td class="name" nowrap><a href="#marked_value">marked_value</a></td>
<td class="summary">Marked text for input field.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#max_length">max_length</a></td>
<td class="summary">Max length for input text</td>
</tr>
@@ -164,7 +196,7 @@
</tr>
<tr>
<td class="name" nowrap><a href="#on_input_select">on_input_select</a></td>
<td class="summary">On input field select callback(self, button_node)</td>
<td class="summary">On input field select callback(self, input_instance)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_input_text">on_input_text</a></td>
@@ -172,16 +204,36 @@
</tr>
<tr>
<td class="name" nowrap><a href="#on_input_unselect">on_input_unselect</a></td>
<td class="summary">On input field unselect callback(self, input_text)</td>
<td class="summary">On input field unselect callback(self, input_text, input_instance)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_input_wrong">on_input_wrong</a></td>
<td class="summary">On trying user input with not allowed character callback(self, params, button_instance)</td>
<td class="summary">On trying user input with not allowed character callback(self, params, input_text)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_select_cursor_change">on_select_cursor_change</a></td>
<td class="summary">On cursor position change callback(self, cursor_index, start_index, end_index)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#previous_value">previous_value</a></td>
<td class="summary">Previous input value</td>
</tr>
<tr>
<td class="name" nowrap><a href="#start_index">start_index</a></td>
<td class="summary">The selection start index.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#text">text</a></td>
<td class="summary">Text component</td>
</tr>
<tr>
<td class="name" nowrap><a href="#text_width">text_width</a></td>
<td class="summary">Text width</td>
</tr>
<tr>
<td class="name" nowrap><a href="#value">value</a></td>
<td class="summary">Current input value</td>
</tr>
</table>
<br/>
@@ -217,6 +269,37 @@
</dd>
<dt>
<a name = "get_text_selected_replaced"></a>
<strong>get_text_selected_replaced(self, text)</strong>
</dt>
<dd>
Replace selected text with new text
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Input</span></span>
<a href="../modules/Input.html#">Input</a>
</li>
<li><span class="parameter">text</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The text to replace selected text
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
New input text
</ol>
</dd>
<dt>
<a name = "init"></a>
@@ -250,6 +333,39 @@
</dd>
<dt>
<a name = "move_selection"></a>
<strong>move_selection(self, delta, is_add_to_selection, is_move_to_end)</strong>
</dt>
<dd>
Change cursor position by delta
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Input</span></span>
<a href="../modules/Input.html#">Input</a>
</li>
<li><span class="parameter">delta</span>
<span class="types"><span class="type">number</span></span>
side for cursor position, -1 for left, 1 for right
</li>
<li><span class="parameter">is_add_to_selection</span>
<span class="types"><span class="type">boolean</span></span>
(Shift key)
</li>
<li><span class="parameter">is_move_to_end</span>
<span class="types"><span class="type">boolean</span></span>
(Ctrl key)
</li>
</ul>
</dd>
<dt>
<a name = "reset_changes"></a>
@@ -267,6 +383,12 @@
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">druid.input</span></span>
Current input instance
</ol>
@@ -292,6 +414,45 @@
</dd>
<dt>
<a name = "select_cursor"></a>
<strong>select_cursor(self, cursor_index, start_index, end_index)</strong>
</dt>
<dd>
Set cursor position in input field
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Input</span></span>
<a href="../modules/Input.html#">Input</a>
</li>
<li><span class="parameter">cursor_index</span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Cursor index for cursor position, if nil - will be set to the end of the text
</li>
<li><span class="parameter">start_index</span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Start index for cursor position, if nil - will be set to the end of the text
</li>
<li><span class="parameter">end_index</span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
End index for cursor position, if nil - will be set to the start_index
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">druid.input</span></span>
Current input instance
</ol>
</dd>
<dt>
<a name = "set_allowed_characters"></a>
@@ -422,23 +583,15 @@
<ul>
<li><span class="parameter">IS_LONGTAP_ERASE</span>
<span class="types"><span class="type">boolean</span></span>
Is long tap will erase current input data
(<em>default</em> false)
Is long tap will erase current input data. Default: false
</li>
<li><span class="parameter">MASK_DEFAULT_CHAR</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Default character mask for password input
(<em>default</em> *)
Default character mask for password input. Default: *]
</li>
<li><span class="parameter">IS_UNSELECT_ON_RESELECT</span>
<span class="types"><span class="type">boolean</span></span>
If true, call unselect on select selected input
(<em>default</em> false)
</li>
<li><span class="parameter">NO_CONSUME_INPUT_WHILE_SELECTED</span>
<span class="types"><span class="type">boolean</span></span>
If true, will not consume input while input is selected. It's allow to interact with other components while input is selected (text input still captured)
(<em>default</em> false)
If true, call unselect on select selected input. Default: false
</li>
<li><span class="parameter">on_select</span>
<span class="types"><span class="type">function</span></span>
@@ -477,9 +630,8 @@
<ul>
<li><span class="parameter">allowerd_characters</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
(<em>optional</em>)
</li>
</ul>
@@ -507,6 +659,66 @@
</dd>
<dt>
<a name = "current_value"></a>
<strong>current_value</strong>
</dt>
<dd>
Current input value with marked text
<ul>
<li><span class="parameter">current_value</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</li>
</ul>
</dd>
<dt>
<a name = "cursor_index"></a>
<strong>cursor_index</strong>
</dt>
<dd>
The cursor index. The index of letter cursor after. Leftmost cursor - 0
<ul>
<li><span class="parameter">cursor_index</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "end_index"></a>
<strong>end_index</strong>
</dt>
<dd>
Theselection end index. The index of letter cursor before. Rightmost selection - #text
<ul>
<li><span class="parameter">end_index</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "is_empty"></a>
@@ -567,6 +779,46 @@
</dd>
<dt>
<a name = "marked_text_width"></a>
<strong>marked_text_width</strong>
</dt>
<dd>
Marked text width
<ul>
<li><span class="parameter">marked_text_width</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "marked_value"></a>
<strong>marked_value</strong>
</dt>
<dd>
Marked text for input field. Info: https://defold.com/manuals/input-key-and-text/#marked-text
<ul>
<li><span class="parameter">marked_value</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</li>
</ul>
</dd>
<dt>
<a name = "max_length"></a>
@@ -578,9 +830,8 @@
<ul>
<li><span class="parameter">max_length</span>
<span class="types"><span class="type">number</span></span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
(<em>optional</em>)
</li>
</ul>
@@ -634,7 +885,7 @@
<strong>on_input_select</strong>
</dt>
<dd>
On input field select callback(self, button_node)
On input field select callback(self, input_instance)
<ul>
@@ -674,7 +925,7 @@
<strong>on_input_unselect</strong>
</dt>
<dd>
On input field unselect callback(self, input_text)
On input field unselect callback(self, input_text, input_instance)
<ul>
@@ -694,7 +945,7 @@
<strong>on_input_wrong</strong>
</dt>
<dd>
On trying user input with not allowed character callback(self, params, button_instance)
On trying user input with not allowed character callback(self, params, input_text)
<ul>
@@ -708,6 +959,66 @@
</dd>
<dt>
<a name = "on_select_cursor_change"></a>
<strong>on_select_cursor_change</strong>
</dt>
<dd>
On cursor position change callback(self, cursor_index, start_index, end_index)
<ul>
<li><span class="parameter">on_select_cursor_change</span>
<span class="types"><span class="type">DruidEvent</span></span>
<a href="../modules/DruidEvent.html#">DruidEvent</a>
</li>
</ul>
</dd>
<dt>
<a name = "previous_value"></a>
<strong>previous_value</strong>
</dt>
<dd>
Previous input value
<ul>
<li><span class="parameter">previous_value</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</li>
</ul>
</dd>
<dt>
<a name = "start_index"></a>
<strong>start_index</strong>
</dt>
<dd>
The selection start index. The index of letter cursor after. Leftmost selection - 0
<ul>
<li><span class="parameter">start_index</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "text"></a>
@@ -728,6 +1039,46 @@
</dd>
<dt>
<a name = "text_width"></a>
<strong>text_width</strong>
</dt>
<dd>
Text width
<ul>
<li><span class="parameter">text_width</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "value"></a>
<strong>value</strong>
</dt>
<dd>
Current input value
<ul>
<li><span class="parameter">value</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</li>
</ul>
</dd>
</dl>

View File

@@ -93,7 +93,7 @@
<td class="summary">Format string with new text params on localized text</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, node[, locale_id=node_text[, adjust_type=downscale]])</a></td>
<td class="name" nowrap><a href="#init">init(self, node, locale_id, adjust_type)</a></td>
<td class="summary">The <a href="../modules/LangText.html#">LangText</a> constructor</td>
</tr>
<tr>
@@ -185,7 +185,7 @@
</dd>
<dt>
<a name = "init"></a>
<strong>init(self, node[, locale_id=node_text[, adjust_type=downscale]])</strong>
<strong>init(self, node, locale_id, adjust_type)</strong>
</dt>
<dd>
The <a href="../modules/LangText.html#">LangText</a> constructor
@@ -202,14 +202,12 @@
The node_id or gui.get_node(node_id)
</li>
<li><span class="parameter">locale_id</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Default locale id or text from node as default
(<em>default</em> node_text)
</li>
<li><span class="parameter">adjust_type</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
(<em>default</em> downscale)
</li>
</ul>

View File

@@ -32,7 +32,6 @@
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
<li><a href="#Fields">Fields</a></li>
</ul>
@@ -79,45 +78,6 @@
<p> <a href="https://insality.github.io/druid/druid/index.html?example=general_layout" target="_blank"><b>Example Link</b></a></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#fit_into_node">fit_into_node(self, node)</a></td>
<td class="summary">Set node for layout node to fit inside it.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#fit_into_size">fit_into_size(self, target_size)</a></td>
<td class="summary">Set size for layout node to fit inside it</td>
</tr>
<tr>
<td class="name" nowrap><a href="#fit_into_window">fit_into_window(self)</a></td>
<td class="summary">Set current size for layout node to fit inside it</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, node, mode, on_size_changed_callback)</a></td>
<td class="summary">The <a href="../modules/Layout.html#">Layout</a> constructor</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_max_gui_upscale">set_max_gui_upscale(self, max_gui_upscale)</a></td>
<td class="summary">Set max gui upscale for FIT adjust mode (or side).</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_max_size">set_max_size(self, max_size)</a></td>
<td class="summary">Set maximum size of layout node</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_min_size">set_min_size(self, min_size)</a></td>
<td class="summary">Set minimal size of layout node</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_origin_position">set_origin_position(self, new_origin_position)</a></td>
<td class="summary">Set new origin position of layout node.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_origin_size">set_origin_size(self, new_origin_size)</a></td>
<td class="summary">Set new origin size of layout node.</td>
</tr>
</table>
<h2><a href="#Fields">Fields</a></h2>
<table class="function_list">
<tr>
@@ -128,297 +88,12 @@
<td class="name" nowrap><a href="#node">node</a></td>
<td class="summary">Layout node</td>
</tr>
<tr>
<td class="name" nowrap><a href="#on_size_changed">on_size_changed</a></td>
<td class="summary">On window resize callback(self, new_size)</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "fit_into_node"></a>
<strong>fit_into_node(self, node)</strong>
</dt>
<dd>
Set node for layout node to fit inside it. Pass nil to reset
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</li>
<li><span class="parameter">node</span>
<span class="types"><a class="type" href="../modules/Layout.html#node">node</a> or <span class="type">nil</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</ol>
</dd>
<dt>
<a name = "fit_into_size"></a>
<strong>fit_into_size(self, target_size)</strong>
</dt>
<dd>
Set size for layout node to fit inside it
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</li>
<li><span class="parameter">target_size</span>
<span class="types"><span class="type">vector3</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</ol>
</dd>
<dt>
<a name = "fit_into_window"></a>
<strong>fit_into_window(self)</strong>
</dt>
<dd>
Set current size for layout node to fit inside it
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</ol>
</dd>
<dt>
<a name = "init"></a>
<strong>init(self, node, mode, on_size_changed_callback)</strong>
</dt>
<dd>
The <a href="../modules/Layout.html#">Layout</a> constructor
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</li>
<li><span class="parameter">node</span>
<span class="types"><a class="type" href="../modules/Layout.html#node">node</a></span>
Gui node
</li>
<li><span class="parameter">mode</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The layout mode (from const.LAYOUT_MODE)
</li>
<li><span class="parameter">on_size_changed_callback</span>
<span class="types"><span class="type">function</span> or <span class="type">nil</span></span>
The callback on window resize
</li>
</ul>
</dd>
<dt>
<a name = "set_max_gui_upscale"></a>
<strong>set_max_gui_upscale(self, max_gui_upscale)</strong>
</dt>
<dd>
Set max gui upscale for FIT adjust mode (or side). It happens on bigger render gui screen
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</li>
<li><span class="parameter">max_gui_upscale</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</ol>
</dd>
<dt>
<a name = "set_max_size"></a>
<strong>set_max_size(self, max_size)</strong>
</dt>
<dd>
Set maximum size of layout node
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</li>
<li><span class="parameter">max_size</span>
<span class="types"><span class="type">vector3</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</ol>
</dd>
<dt>
<a name = "set_min_size"></a>
<strong>set_min_size(self, min_size)</strong>
</dt>
<dd>
Set minimal size of layout node
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</li>
<li><span class="parameter">min_size</span>
<span class="types"><span class="type">vector3</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</ol>
</dd>
<dt>
<a name = "set_origin_position"></a>
<strong>set_origin_position(self, new_origin_position)</strong>
</dt>
<dd>
Set new origin position of layout node. You should apply this on node movement
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</li>
<li><span class="parameter">new_origin_position</span>
<span class="types"><span class="type">vector3</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</ol>
</dd>
<dt>
<a name = "set_origin_size"></a>
<strong>set_origin_size(self, new_origin_size)</strong>
</dt>
<dd>
Set new origin size of layout node. You should apply this on node manual size change
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</li>
<li><span class="parameter">new_origin_size</span>
<span class="types"><span class="type">vector3</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">Layout</span></span>
<a href="../modules/Layout.html#">Layout</a>
</ol>
</dd>
</dl>
<h2 class="section-header "><a name="Fields"></a>Fields</h2>
<dl class="function">
@@ -461,26 +136,6 @@
</dd>
<dt>
<a name = "on_size_changed"></a>
<strong>on_size_changed</strong>
</dt>
<dd>
On window resize callback(self, new_size)
<ul>
<li><span class="parameter">on_size_changed</span>
<span class="types"><span class="type">DruidEvent</span></span>
<a href="../modules/DruidEvent.html#">DruidEvent</a>
</li>
</ul>
</dd>
</dl>

View File

@@ -91,7 +91,7 @@
<td class="summary">Set current and min/max angles for component</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_friction">set_friction(self[, value=1])</a></td>
<td class="name" nowrap><a href="#set_friction">set_friction(self, value)</a></td>
<td class="summary">Set current and min/max angles for component</td>
</tr>
</table>
@@ -192,7 +192,7 @@
</dd>
<dt>
<a name = "set_friction"></a>
<strong>set_friction(self[, value=1])</strong>
<strong>set_friction(self, value)</strong>
</dt>
<dd>
Set current and min/max angles for component
@@ -205,9 +205,8 @@
<a href="../modules/PinKnob.html#">PinKnob</a>
</li>
<li><span class="parameter">value</span>
<span class="types"><span class="type">number</span></span>
The spin speed multiplier
(<em>default</em> 1)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
The spin speed multiplier. Default: 1
</li>
</ul>

View File

@@ -103,7 +103,7 @@
<td class="summary">Return current progress bar value</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, node, key[, init_value=1])</a></td>
<td class="name" nowrap><a href="#init">init(self, node, key, init_value)</a></td>
<td class="summary">The <a href="../modules/Progress.html#">Progress</a> constructor</td>
</tr>
<tr>
@@ -234,7 +234,7 @@
</dd>
<dt>
<a name = "init"></a>
<strong>init(self, node, key[, init_value=1])</strong>
<strong>init(self, node, key, init_value)</strong>
</dt>
<dd>
The <a href="../modules/Progress.html#">Progress</a> constructor
@@ -255,9 +255,8 @@
Progress bar direction: const.SIDE.X or const.SIDE.Y
</li>
<li><span class="parameter">init_value</span>
<span class="types"><span class="type">number</span></span>
Initial value of progress bar
(<em>default</em> 1)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Initial value of progress bar. Default: 1
</li>
</ul>
@@ -401,14 +400,12 @@
<h3>Fields:</h3>
<ul>
<li><span class="parameter">SPEED</span>
<span class="types"><span class="type">number</span></span>
Progress bas fill rate. More -> faster
(<em>default</em> 5)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Progress bas fill rate. More -> faster. Default: 5
</li>
<li><span class="parameter">MIN_DELTA</span>
<span class="types"><span class="type">number</span></span>
Minimum step to fill progress bar
(<em>default</em> 0.005)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Minimum step to fill progress bar. Default: 0.005
</li>
</ul>

View File

@@ -86,7 +86,7 @@
<td class="summary">Return radio group state</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, nodes, callback[, click_nodes=node])</a></td>
<td class="name" nowrap><a href="#init">init(self, nodes, callback, click_nodes)</a></td>
<td class="summary">The <a href="../modules/RadioGroup.html#">RadioGroup</a> constructor</td>
</tr>
<tr>
@@ -142,7 +142,7 @@
</dd>
<dt>
<a name = "init"></a>
<strong>init(self, nodes, callback[, click_nodes=node])</strong>
<strong>init(self, nodes, callback, click_nodes)</strong>
</dt>
<dd>
The <a href="../modules/RadioGroup.html#">RadioGroup</a> constructor
@@ -163,9 +163,8 @@
Radio callback
</li>
<li><span class="parameter">click_nodes</span>
<span class="types"><span class="type">node[]</span></span>
Array of trigger nodes, by default equals to nodes
(<em>default</em> node)
<span class="types"><span class="type">node[]</span> or <span class="type">nil</span></span>
Array of trigger nodes, by default equals to nodes. Default - nodes
</li>
</ul>

View File

@@ -84,20 +84,32 @@
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#get_text">get_text(self)</a></td>
<td class="summary">GSet input field text</td>
<td class="summary">Set input field text</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, template, nodes)</a></td>
<td class="summary">The <a href="../modules/RichInput.html#">RichInput</a> constructor</td>
</tr>
<tr>
<td class="name" nowrap><a href="#select">select(self)</a></td>
<td class="summary">Select input field</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_allowed_characters">set_allowed_characters(self, characters)</a></td>
<td class="summary">Set allowed charaters for input field.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_font">set_font(self, font)</a></td>
<td class="summary">Set input field font</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_placeholder">set_placeholder(self, placeholder_text)</a></td>
<td class="summary">Set placeholder text</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_text">set_text(self, text)</a></td>
<td class="summary">Set input field text</td>
</tr>
</table>
<h2><a href="#Fields">Fields</a></h2>
<table class="function_list">
@@ -135,7 +147,7 @@
<strong>get_text(self)</strong>
</dt>
<dd>
GSet input field text
Set input field text
<h3>Parameters:</h3>
@@ -146,12 +158,6 @@
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Current input text
</ol>
@@ -185,6 +191,27 @@
</dd>
<dt>
<a name = "select"></a>
<strong>select(self)</strong>
</dt>
<dd>
Select input field
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">RichInput</span></span>
<a href="../modules/RichInput.html#">RichInput</a>
</li>
</ul>
</dd>
<dt>
<a name = "set_allowed_characters"></a>
@@ -218,6 +245,37 @@
</dd>
<dt>
<a name = "set_font"></a>
<strong>set_font(self, font)</strong>
</dt>
<dd>
Set input field font
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">RichInput</span></span>
<a href="../modules/RichInput.html#">RichInput</a>
</li>
<li><span class="parameter">font</span>
<span class="types"><span class="type">hash</span></span>
The font hash
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">druid.input</span></span>
Current input instance
</ol>
</dd>
<dt>
<a name = "set_placeholder"></a>
@@ -234,16 +292,41 @@
<a href="../modules/RichInput.html#">RichInput</a>
</li>
<li><span class="parameter">placeholder_text</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The placeholder text
</li>
</ul>
</dd>
<dt>
<a name = "set_text"></a>
<strong>set_text(self, text)</strong>
</dt>
<dd>
Set input field text
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">RichInput</span></span>
<a href="../modules/RichInput.html#">RichInput</a>
</li>
<li><span class="parameter">text</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The input text
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">RichInput</span></span>
Current instance
<span class="types"><span class="type">druid.input</span></span>
Current input instance
</ol>

View File

@@ -81,19 +81,7 @@
<b># Overview #</b>
<p> This custom component is inspired by <a href="https://github.com/britzl/defold-richtext" target="_blank">defold-richtext</a> by britzl.
It uses a similar syntax for tags but currently supports fewer tags.
<p> All parameters for the Rich Text component are adjusted in the GUI scene.
<p> This component uses GUI component template. (/druid/custom/rich_text/rich_text.gui).
<p> You able to customize it or make your own with the next node scructure:
<p> root
<p> - text_prefab
<p> - icon_prefab
<p> <b># Rich Text Setup #</b>
<p> • Root node size: Set the maximum width and height of the text.
<p> • Root anchor: Define the alignment of the Rich Text inside the root node size area.
<p> • Text prefab: Configure all default text parameters for the text node.
<p> • Text prefab anchor: Set the anchor for each text node (adjust this only if animating text).
<p> • Icon prefab: Configure all default node parameters for the icon node.
<p> • Icon prefab anchor: Set the anchor for each icon node (adjust this only if animating the icon).
<p> Create Rich Text on your GUI Text Node. All properties of the text node will be used as default for the text.
<p> <b># Notes #</b>
<p> • Nested tags are supported
<p> <a href="https://insality.github.io/druid/druid/index.html?example=custom_rich_text" target="_blank"><b>Example Link</b></a></p>
@@ -119,7 +107,6 @@ self.rich_text:set_text(&quot;Hello, Druid Rich Text!&quot;)
outline: vector4,
font: string,
image: druid.rich_text.image,
default_animation: string,
br: boolean,
nobr: boolean,
}
@@ -150,6 +137,10 @@ type druid.rich_text.metrics = {
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#characters">characters(self, word)</a></td>
<td class="summary">Split a word into it's characters</td>
</tr>
<tr>
<td class="name" nowrap><a href="#clear">clear()</a></td>
<td class="summary">Clear all created words.</td>
@@ -159,11 +150,15 @@ type druid.rich_text.metrics = {
<td class="summary">Get current line metrics</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_text">get_text(self)</a></td>
<td class="summary">Get current text</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_words">get_words()</a></td>
<td class="summary">Get all current words.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, template, nodes)</a></td>
<td class="name" nowrap><a href="#init">init(self, text_node, value)</a></td>
<td class="summary">The <a href="../modules/RichText.html#">RichText</a> constructor</td>
</tr>
<tr>
@@ -171,7 +166,7 @@ type druid.rich_text.metrics = {
<td class="summary">Set text for Rich Text</td>
</tr>
<tr>
<td class="name" nowrap><a href="#tagged">tagged(tag)</a></td>
<td class="name" nowrap><a href="#tagged">tagged(self, tag)</a></td>
<td class="summary">Get all words, which has a passed tag.</td>
</tr>
</table>
@@ -188,6 +183,18 @@ type druid.rich_text.metrics = {
<td class="name" nowrap><a href="#druid">druid</a></td>
<td class="summary">The component druid instance</td>
</tr>
<tr>
<td class="name" nowrap><a href="#icon_prefab">icon_prefab</a></td>
<td class="summary">The icon prefab node</td>
</tr>
<tr>
<td class="name" nowrap><a href="#root">root</a></td>
<td class="summary">The root node of the Rich Text</td>
</tr>
<tr>
<td class="name" nowrap><a href="#text_prefab">text_prefab</a></td>
<td class="summary">The text prefab node</td>
</tr>
</table>
<br/>
@@ -197,6 +204,37 @@ type druid.rich_text.metrics = {
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "characters"></a>
<strong>characters(self, word)</strong>
</dt>
<dd>
Split a word into it's characters
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">RichText</span></span>
<a href="../modules/RichText.html#">RichText</a>
</li>
<li><span class="parameter">word</span>
<span class="types"><span class="type">druid.rich_text.word</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">druid.rich_text.word[]</span></span>
characters
</ol>
</dd>
<dt>
<a name = "clear"></a>
<strong>clear()</strong>
@@ -230,6 +268,33 @@ type druid.rich_text.metrics = {
</dd>
<dt>
<a name = "get_text"></a>
<strong>get_text(self)</strong>
</dt>
<dd>
Get current text
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">RichText</span></span>
<a href="../modules/RichText.html#">RichText</a>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
text
</ol>
</dd>
<dt>
<a name = "get_words"></a>
@@ -253,7 +318,7 @@ type druid.rich_text.metrics = {
</dd>
<dt>
<a name = "init"></a>
<strong>init(self, template, nodes)</strong>
<strong>init(self, text_node, value)</strong>
</dt>
<dd>
The <a href="../modules/RichText.html#">RichText</a> constructor
@@ -265,13 +330,13 @@ type druid.rich_text.metrics = {
<span class="types"><span class="type">RichText</span></span>
<a href="../modules/RichText.html#">RichText</a>
</li>
<li><span class="parameter">template</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The Rich Text template name
<li><span class="parameter">text_node</span>
<span class="types"><span class="type">node</span> or <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The text node to make Rich Text
</li>
<li><span class="parameter">nodes</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
The node table, if prefab was copied by gui.clone_tree()
<li><span class="parameter">value</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
The initial text value. Default will be gui.get_text(text_node)
</li>
</ul>
@@ -295,7 +360,7 @@ type druid.rich_text.metrics = {
<a href="../modules/RichText.html#">RichText</a>
</li>
<li><span class="parameter">text</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
The text to set
</li>
</ul>
@@ -361,7 +426,7 @@ Words &lt;nobr&gt;inside tag&lt;/nobr&gt; won't <span class="keyword">break</spa
</dd>
<dt>
<a name = "tagged"></a>
<strong>tagged(tag)</strong>
<strong>tagged(self, tag)</strong>
</dt>
<dd>
Get all words, which has a passed tag.
@@ -369,6 +434,10 @@ Words &lt;nobr&gt;inside tag&lt;/nobr&gt; won't <span class="keyword">break</spa
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">RichText</span></span>
<a href="../modules/RichText.html#">RichText</a>
</li>
<li><span class="parameter">tag</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
@@ -403,19 +472,16 @@ Words &lt;nobr&gt;inside tag&lt;/nobr&gt; won't <span class="keyword">break</spa
<h3>Fields:</h3>
<ul>
<li><span class="parameter">COLORS</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
Rich Text color aliases
(<em>default</em> {})
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a> or <span class="type">nil</span></span>
Rich Text color aliases. Default: {}
</li>
<li><span class="parameter">ADJUST_STEPS</span>
<span class="types"><span class="type">number</span></span>
Amount steps of attemps text adjust by height
(<em>default</em> 20)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Amount steps of attemps text adjust by height. Default: 20
</li>
<li><span class="parameter">ADJUST_SCALE_DELTA</span>
<span class="types"><span class="type">number</span></span>
Scale step on each height adjust step
(<em>default</em> 0.02)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Scale step on each height adjust step. Default: 0.02
</li>
</ul>
@@ -447,6 +513,66 @@ Words &lt;nobr&gt;inside tag&lt;/nobr&gt; won't <span class="keyword">break</spa
</dd>
<dt>
<a name = "icon_prefab"></a>
<strong>icon_prefab</strong>
</dt>
<dd>
The icon prefab node
<ul>
<li><span class="parameter">icon_prefab</span>
<span class="types"><span class="type">node</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "root"></a>
<strong>root</strong>
</dt>
<dd>
The root node of the Rich Text
<ul>
<li><span class="parameter">root</span>
<span class="types"><span class="type">node</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "text_prefab"></a>
<strong>text_prefab</strong>
</dt>
<dd>
The text prefab node
<ul>
<li><span class="parameter">text_prefab</span>
<span class="types"><span class="type">node</span></span>
</li>
</ul>
</dd>
</dl>

View File

@@ -167,6 +167,14 @@
<td class="name" nowrap><a href="#set_vertical_scroll">set_vertical_scroll(self, state)</a></td>
<td class="summary">Lock or unlock vertical scroll</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_view_size">set_view_size(self, size)</a></td>
<td class="summary">Set new scroll view size in case the node size was changed.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#update_view_size">update_view_size(self)</a></td>
<td class="summary">Refresh scroll view size</td>
</tr>
</table>
<h2><a href="#Tables">Tables</a></h2>
<table class="function_list">
@@ -177,6 +185,10 @@
</table>
<h2><a href="#Fields">Fields</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#_is_inert">_is_inert</a></td>
<td class="summary">Flag, if scroll now moving by inertion</td>
</tr>
<tr>
<td class="name" nowrap><a href="#available_pos">available_pos</a></td>
<td class="summary">Available position for content node: (min_x, max_y, max_x, min_y)</td>
@@ -229,6 +241,10 @@
<td class="name" nowrap><a href="#view_node">view_node</a></td>
<td class="summary">Scroll view node</td>
</tr>
<tr>
<td class="name" nowrap><a href="#view_size">view_size</a></td>
<td class="summary">Scroll view size</td>
</tr>
</table>
<br/>
@@ -525,7 +541,7 @@
</li>
<li><span class="parameter">node</span>
<span class="types"><span class="type">node</span></span>
<span class="types"><span class="type">node</span> or <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Gui node
</li>
</ul>
@@ -683,7 +699,7 @@
The new size for content node
</li>
<li><span class="parameter">offset</span>
<span class="types"><span class="type">vector3</span></span>
<span class="types"><span class="type">vector3</span> or <span class="type">nil</span></span>
Offset value to set, where content is starts
</li>
</ul>
@@ -729,6 +745,58 @@
</dd>
<dt>
<a name = "set_view_size"></a>
<strong>set_view_size(self, size)</strong>
</dt>
<dd>
Set new scroll view size in case the node size was changed.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Scroll</span></span>
<a href="../modules/Scroll.html#">Scroll</a>
</li>
<li><span class="parameter">size</span>
<span class="types"><span class="type">vector3</span></span>
The new size for view node
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">druid.scroll</span></span>
Current scroll instance
</ol>
</dd>
<dt>
<a name = "update_view_size"></a>
<strong>update_view_size(self)</strong>
</dt>
<dd>
Refresh scroll view size
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Scroll</span></span>
<a href="../modules/Scroll.html#">Scroll</a>
</li>
</ul>
</dd>
</dl>
<h2 class="section-header "><a name="Tables"></a>Tables</h2>
@@ -747,64 +815,52 @@
<h3>Fields:</h3>
<ul>
<li><span class="parameter">FRICT</span>
<span class="types"><span class="type">number</span></span>
Multiplier for free inertion
(<em>default</em> 0)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Multiplier for free inertion. Default: 0
</li>
<li><span class="parameter">FRICT_HOLD</span>
<span class="types"><span class="type">number</span></span>
Multiplier for inertion, while touching
(<em>default</em> 0)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Multiplier for inertion, while touching. Default: 0
</li>
<li><span class="parameter">INERT_THRESHOLD</span>
<span class="types"><span class="type">number</span></span>
Scroll speed to stop inertion
(<em>default</em> 3)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Scroll speed to stop inertion. Default: 3
</li>
<li><span class="parameter">INERT_SPEED</span>
<span class="types"><span class="type">number</span></span>
Multiplier for inertion speed
(<em>default</em> 30)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Multiplier for inertion speed. Default: 30
</li>
<li><span class="parameter">POINTS_DEADZONE</span>
<span class="types"><span class="type">number</span></span>
Speed to check points of interests in no_inertion mode
(<em>default</em> 20)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Speed to check points of interests in no_inertion mode. Default: 20
</li>
<li><span class="parameter">BACK_SPEED</span>
<span class="types"><span class="type">number</span></span>
Scroll back returning lerp speed
(<em>default</em> 0.35)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Scroll back returning lerp speed. Default: 35
</li>
<li><span class="parameter">ANIM_SPEED</span>
<span class="types"><span class="type">number</span></span>
Scroll gui.animation speed for scroll_to function
(<em>default</em> 0.2)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Scroll gui.animation speed for scroll_to function. Default: 2
</li>
<li><span class="parameter">EXTRA_STRETCH_SIZE</span>
<span class="types"><span class="type">number</span></span>
extra size in pixels outside of scroll (stretch effect)
(<em>default</em> 0)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
extra size in pixels outside of scroll (stretch effect). Default: 0
</li>
<li><span class="parameter">SMALL_CONTENT_SCROLL</span>
<span class="types"><span class="type">boolean</span></span>
If true, content node with size less than view node size can be scrolled
(<em>default</em> false)
<span class="types"><span class="type">boolean</span> or <span class="type">nil</span></span>
If true, content node with size less than view node size can be scrolled. Default: false
</li>
<li><span class="parameter">WHEEL_SCROLL_SPEED</span>
<span class="types"><span class="type">boolean</span></span>
The scroll speed via mouse wheel scroll or touchpad. Set to 0 to disable wheel scrolling
(<em>default</em> 0)
<span class="types"><span class="type">boolean</span> or <span class="type">nil</span></span>
The scroll speed via mouse wheel scroll or touchpad. Set to 0 to disable wheel scrolling. Default: 0
</li>
<li><span class="parameter">WHEEL_SCROLL_INVERTED</span>
<span class="types"><span class="type">boolean</span></span>
If true, invert direction for touchpad and mouse wheel scroll
(<em>default</em> false)
<span class="types"><span class="type">boolean</span> or <span class="type">nil</span></span>
If true, invert direction for touchpad and mouse wheel scroll. Default: false
</li>
<li><span class="parameter">WHEEL_SCROLL_BY_INERTION</span>
<span class="types"><span class="type">boolean</span></span>
If true, wheel will add inertion to scroll. Direct set position otherwise.
(<em>default</em> false)
<span class="types"><span class="type">boolean</span> or <span class="type">nil</span></span>
If true, wheel will add inertion to scroll. Direct set position otherwise.. Default: false
</li>
</ul>
@@ -817,6 +873,26 @@
<h2 class="section-header "><a name="Fields"></a>Fields</h2>
<dl class="function">
<dt>
<a name = "_is_inert"></a>
<strong>_is_inert</strong>
</dt>
<dd>
Flag, if scroll now moving by inertion
<ul>
<li><span class="parameter">_is_inert</span>
<span class="types"><span class="type">boolean</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "available_pos"></a>
<strong>available_pos</strong>
@@ -1027,9 +1103,8 @@
<ul>
<li><span class="parameter">selected</span>
<span class="types"><span class="type">number</span></span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
(<em>optional</em>)
</li>
</ul>
@@ -1077,6 +1152,26 @@
</dd>
<dt>
<a name = "view_size"></a>
<strong>view_size</strong>
</dt>
<dd>
Scroll view size
<ul>
<li><span class="parameter">view_size</span>
<span class="types"><span class="type">vector3</span></span>
</li>
</ul>
</dd>
</dl>

View File

@@ -86,10 +86,18 @@
<td class="summary">The <a href="../modules/Slider.html#">Slider</a> constructor</td>
</tr>
<tr>
<td class="name" nowrap><a href="#is_enabled">is_enabled(self)</a></td>
<td class="summary">Check if Slider component is enabled</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set">set(self, value, is_silent)</a></td>
<td class="summary">Set value for slider</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_enabled">set_enabled(self, is_enabled)</a></td>
<td class="summary">Set Slider input enabled or disabled</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_input_node">set_input_node(self, input_node)</a></td>
<td class="summary">Set input zone for slider.</td>
</tr>
@@ -177,6 +185,33 @@
</dd>
<dt>
<a name = "is_enabled"></a>
<strong>is_enabled(self)</strong>
</dt>
<dd>
Check if Slider component is enabled
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Slider</span></span>
<a href="../modules/Slider.html#">Slider</a>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "set"></a>
@@ -206,6 +241,31 @@
</dd>
<dt>
<a name = "set_enabled"></a>
<strong>set_enabled(self, is_enabled)</strong>
</dt>
<dd>
Set Slider input enabled or disabled
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Slider</span></span>
<a href="../modules/Slider.html#">Slider</a>
</li>
<li><span class="parameter">is_enabled</span>
<span class="types"><span class="type">boolean</span></span>
</li>
</ul>
</dd>
<dt>
<a name = "set_input_node"></a>
@@ -225,7 +285,7 @@
<a href="../modules/Slider.html#">Slider</a>
</li>
<li><span class="parameter">input_node</span>
<span class="types"><a class="type" href="../modules/Slider.html#node">node</a></span>
<span class="types"><a class="type" href="../modules/Slider.html#node">node</a>, <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
</li>
</ul>
@@ -291,7 +351,7 @@
<ul>
<li><span class="parameter">dist</span>
<span class="types"><span class="type">number</span></span>
<span class="types"><span class="type">vector3</span></span>
</li>
</ul>

View File

@@ -138,7 +138,7 @@
<td class="summary">Return grid content size</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, parent, element[, in_row=1])</a></td>
<td class="name" nowrap><a href="#init">init(self, parent, element, in_row)</a></td>
<td class="summary">The <a href="../modules/StaticGrid.html#">StaticGrid</a> constructor</td>
</tr>
<tr>
@@ -154,9 +154,21 @@
<td class="summary">Set new in_row elements for grid</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_item_size">set_item_size(self[, width[, height]])</a></td>
<td class="summary">Set new node size for grid</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_items">set_items(self, nodes[, is_instant=false])</a></td>
<td class="summary">Set new items to the grid.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_position_function">set_position_function(self, callback)</a></td>
<td class="summary">Change set position function for grid nodes.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#sort_nodes">sort_nodes(self, comparator)</a></td>
<td class="summary">Sort grid nodes by custom comparator function</td>
</tr>
</table>
<h2><a href="#Tables">Tables</a></h2>
<table class="function_list">
@@ -496,7 +508,7 @@
</dd>
<dt>
<a name = "init"></a>
<strong>init(self, parent, element[, in_row=1])</strong>
<strong>init(self, parent, element, in_row)</strong>
</dt>
<dd>
The <a href="../modules/StaticGrid.html#">StaticGrid</a> constructor
@@ -517,9 +529,8 @@
Element prefab. Need to get it size
</li>
<li><span class="parameter">in_row</span>
<span class="types"><span class="type">number</span></span>
How many nodes in row can be placed
(<em>default</em> 1)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
How many nodes in row can be placed. By default 1
</li>
</ul>
@@ -622,6 +633,73 @@
</dd>
<dt>
<a name = "set_item_size"></a>
<strong>set_item_size(self[, width[, height]])</strong>
</dt>
<dd>
Set new node size for grid
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">StaticGrid</span></span>
<a href="../modules/StaticGrid.html#">StaticGrid</a>
</li>
<li><span class="parameter">width</span>
<span class="types"><span class="type">number</span></span>
The new node width
(<em>optional</em>)
</li>
<li><span class="parameter">height</span>
<span class="types"><span class="type">number</span></span>
The new node height
(<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">druid.static_grid</span></span>
Current grid instance
</ol>
</dd>
<dt>
<a name = "set_items"></a>
<strong>set_items(self, nodes[, is_instant=false])</strong>
</dt>
<dd>
Set new items to the grid. All previous items will be removed
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">StaticGrid</span></span>
<a href="../modules/StaticGrid.html#">StaticGrid</a>
</li>
<li><span class="parameter">nodes</span>
<span class="types"><span class="type">node[]</span></span>
The new grid nodes
</li>
<li><span class="parameter">is_instant</span>
<span class="types"><span class="type">boolean</span></span>
If true, update node positions instantly
(<em>default</em> false)
</li>
</ul>
</dd>
<dt>
<a name = "set_position_function"></a>
@@ -654,6 +732,37 @@
</dd>
<dt>
<a name = "sort_nodes"></a>
<strong>sort_nodes(self, comparator)</strong>
</dt>
<dd>
Sort grid nodes by custom comparator function
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">StaticGrid</span></span>
<a href="../modules/StaticGrid.html#">StaticGrid</a>
</li>
<li><span class="parameter">comparator</span>
<span class="types"><span class="type">function</span></span>
The comparator function. (a, b) -> boolean
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">druid.static_grid</span></span>
Current grid instance
</ol>
</dd>
</dl>
<h2 class="section-header "><a name="Tables"></a>Tables</h2>
@@ -672,14 +781,12 @@
<h3>Fields:</h3>
<ul>
<li><span class="parameter">IS_DYNAMIC_NODE_POSES</span>
<span class="types"><span class="type">boolean</span></span>
If true, always center grid content as grid pivot sets
(<em>default</em> false)
<span class="types"><span class="type">boolean</span> or <span class="type">nil</span></span>
If true, always center grid content as grid pivot sets. Default: false
</li>
<li><span class="parameter">IS_ALIGN_LAST_ROW</span>
<span class="types"><span class="type">boolean</span></span>
If true, always align last row of the grid as grid pivot sets
(<em>default</em> false)
<span class="types"><span class="type">boolean</span> or <span class="type">nil</span></span>
If true, always align last row of the grid as grid pivot sets. Default: false
</li>
</ul>

View File

@@ -169,7 +169,7 @@
<a href="../modules/Swipe.html#">Swipe</a>
</li>
<li><span class="parameter">zone</span>
<span class="types"><a class="type" href="../modules/Swipe.html#node">node</a></span>
<span class="types"><a class="type" href="../modules/Swipe.html#node">node</a>, <a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Gui node
</li>
</ul>
@@ -196,19 +196,16 @@
<h3>Fields:</h3>
<ul>
<li><span class="parameter">SWIPE_TIME</span>
<span class="types"><span class="type">number</span></span>
Maximum time for swipe trigger
(<em>default</em> 0.4)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Maximum time for swipe trigger. Default: 0.4
</li>
<li><span class="parameter">SWIPE_THRESHOLD</span>
<span class="types"><span class="type">number</span></span>
Minimum distance for swipe trigger
(<em>default</em> 50)
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Minimum distance for swipe trigger. Default: 50
</li>
<li><span class="parameter">SWIPE_TRIGGER_ON_MOVE</span>
<span class="types"><span class="type">boolean</span></span>
If true, trigger on swipe moving, not only release action
(<em>default</em> false)
<span class="types"><span class="type">boolean</span> or <span class="type">nil</span></span>
If true, trigger on swipe moving, not only release action. Default: false
</li>
</ul>

View File

@@ -105,11 +105,15 @@
<td class="summary">Return current text adjust type</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_text_index_by_width">get_text_index_by_width(self, width)</a></td>
<td class="summary">Get chars count by width</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get_text_size">get_text_size(self, text)</a></td>
<td class="summary">Calculate text width with font with respect to trailing space</td>
</tr>
<tr>
<td class="name" nowrap><a href="#init">init(self, node, value[, adjust_type=downscale])</a></td>
<td class="name" nowrap><a href="#init">init(self, node, value, adjust_type)</a></td>
<td class="summary">The <a href="../modules/Text.html#">Text</a> constructor</td>
</tr>
<tr>
@@ -247,6 +251,37 @@
</dd>
<dt>
<a name = "get_text_index_by_width"></a>
<strong>get_text_index_by_width(self, width)</strong>
</dt>
<dd>
Get chars count by width
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">self</span>
<span class="types"><span class="type">Text</span></span>
<a href="../modules/Text.html#">Text</a>
</li>
<li><span class="parameter">width</span>
<span class="types"><span class="type">number</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">number</span></span>
Chars count
</ol>
</dd>
<dt>
<a name = "get_text_size"></a>
@@ -263,8 +298,8 @@
<a href="../modules/Text.html#">Text</a>
</li>
<li><span class="parameter">text</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
|nil
</li>
</ul>
@@ -284,7 +319,7 @@
</dd>
<dt>
<a name = "init"></a>
<strong>init(self, node, value[, adjust_type=downscale])</strong>
<strong>init(self, node, value, adjust_type)</strong>
</dt>
<dd>
The <a href="../modules/Text.html#">Text</a> constructor
@@ -302,12 +337,11 @@
</li>
<li><span class="parameter">value</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Initial text. Default value is node text from GUI scene.
Initial text. Default value is node text from GUI scene. Default: nil
</li>
<li><span class="parameter">adjust_type</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
(<em>default</em> downscale)
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference. Default: DOWNSCALE
</li>
</ul>
@@ -544,7 +578,7 @@
<a href="../modules/Text.html#">Text</a>
</li>
<li><span class="parameter">adjust_type</span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
See const.TEXT_ADJUST. If pass nil - use current adjust type
</li>
<li><span class="parameter">minimal_scale</span>
@@ -612,14 +646,20 @@
<h3>Fields:</h3>
<ul>
<li><span class="parameter">TRIM_POSTFIX</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The postfix for TRIM adjust type
(<em>default</em> ...)
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
The postfix for TRIM adjust type. Default: ...
</li>
<li><span class="parameter">DEFAULT_ADJUST</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
The default adjust type for any text component
(<em>default</em> DOWNSCALE)
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
The default adjust type for any text component. Default: DOWNSCALE
</li>
<li><span class="parameter">ADJUST_STEPS</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Amount of iterations for text adjust by height. Default: 20
</li>
<li><span class="parameter">ADJUST_SCALE_DELTA</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <span class="type">nil</span></span>
Scale step on each height adjust step. Default: 0.02
</li>
</ul>

View File

@@ -158,7 +158,7 @@
Gui text node
</li>
<li><span class="parameter">seconds_from</span>
<span class="types"><span class="type">number</span></span>
<span class="types"><span class="type">number</span> or <span class="type">nil</span></span>
Start timer value in seconds
</li>
<li><span class="parameter">seconds_to</span>

View File

@@ -0,0 +1,95 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Defold Druid UI Framework</title>
<link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Druid</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/BackHandler.html">BackHandler</a></li>
<li><a href="../modules/BaseComponent.html">BaseComponent</a></li>
<li><a href="../modules/Blocker.html">Blocker</a></li>
<li><a href="../modules/Button.html">Button</a></li>
<li><a href="../modules/Checkbox.html">Checkbox</a></li>
<li><a href="../modules/CheckboxGroup.html">CheckboxGroup</a></li>
<li><a href="../modules/DataList.html">DataList</a></li>
<li><a href="../modules/Drag.html">Drag</a></li>
<li><a href="../modules/Druid.html">Druid</a></li>
<li><a href="../modules/DruidEvent.html">DruidEvent</a></li>
<li><a href="../modules/DruidInstance.html">DruidInstance</a></li>
<li><a href="../modules/DynamicGrid.html">DynamicGrid</a></li>
<li><a href="../modules/Helper.html">Helper</a></li>
<li><a href="../modules/Hotkey.html">Hotkey</a></li>
<li><a href="../modules/Hover.html">Hover</a></li>
<li><a href="../modules/Input.html">Input</a></li>
<li><a href="../modules/LangText.html">LangText</a></li>
<li><a href="../modules/PinKnob.html">PinKnob</a></li>
<li><a href="../modules/Progress.html">Progress</a></li>
<li><a href="../modules/RadioGroup.html">RadioGroup</a></li>
<li><a href="../modules/RichInput.html">RichInput</a></li>
<li><a href="../modules/RichText.html">RichText</a></li>
<li><a href="../modules/Scroll.html">Scroll</a></li>
<li><a href="../modules/Slider.html">Slider</a></li>
<li><a href="../modules/StaticGrid.html">StaticGrid</a></li>
<li><a href="../modules/Swipe.html">Swipe</a></li>
<li><a href="../modules/Text.html">Text</a></li>
<li><a href="../modules/Timer.html">Timer</a></li>
<li><strong>druid.extended.layout</strong></li>
</ul>
</div>
<div id="content">
<h1>Module <code>druid.extended.layout</code></h1>
<p>Druid layout module
<p> <b># Overview #</b>
<p> Layout component works like Dynamic Grid before - for aligning elements in a row or column.</p>
<p> Works like a Figma layout.
<p> <b># Notes</p>
<br/>
<br/>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc TESTING</a></i>
<i style="float:right;">Last updated 2015-01-01 12:00:00 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View File

@@ -0,0 +1,93 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Defold Druid UI Framework</title>
<link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Druid</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/BackHandler.html">BackHandler</a></li>
<li><a href="../modules/BaseComponent.html">BaseComponent</a></li>
<li><a href="../modules/Blocker.html">Blocker</a></li>
<li><a href="../modules/Button.html">Button</a></li>
<li><a href="../modules/Checkbox.html">Checkbox</a></li>
<li><a href="../modules/CheckboxGroup.html">CheckboxGroup</a></li>
<li><a href="../modules/DataList.html">DataList</a></li>
<li><a href="../modules/Drag.html">Drag</a></li>
<li><a href="../modules/Druid.html">Druid</a></li>
<li><a href="../modules/DruidEvent.html">DruidEvent</a></li>
<li><a href="../modules/DruidInstance.html">DruidInstance</a></li>
<li><a href="../modules/DynamicGrid.html">DynamicGrid</a></li>
<li><a href="../modules/Helper.html">Helper</a></li>
<li><a href="../modules/Hotkey.html">Hotkey</a></li>
<li><a href="../modules/Hover.html">Hover</a></li>
<li><a href="../modules/Input.html">Input</a></li>
<li><a href="../modules/LangText.html">LangText</a></li>
<li><a href="../modules/Layout.html">Layout</a></li>
<li><a href="../modules/PinKnob.html">PinKnob</a></li>
<li><a href="../modules/Progress.html">Progress</a></li>
<li><a href="../modules/RadioGroup.html">RadioGroup</a></li>
<li><a href="../modules/RichInput.html">RichInput</a></li>
<li><a href="../modules/RichText.html">RichText</a></li>
<li><a href="../modules/Scroll.html">Scroll</a></li>
<li><a href="../modules/Slider.html">Slider</a></li>
<li><a href="../modules/StaticGrid.html">StaticGrid</a></li>
<li><a href="../modules/Swipe.html">Swipe</a></li>
<li><a href="../modules/Text.html">Text</a></li>
<li><a href="../modules/Timer.html">Timer</a></li>
<li><strong>druid.system.utf8</strong></li>
</ul>
</div>
<div id="content">
<h1>Module <code>druid.system.utf8</code></h1>
<p></p>
<p></p>
<br/>
<br/>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc TESTING</a></i>
<i style="float:right;">Last updated 2015-01-01 12:00:00 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View File

@@ -17,18 +17,11 @@ local component = require("druid.component")
---@class component_name: druid.base_component
local Component = component.create("component_name")
local SCHEME = {
ROOT = "root",
BUTTON = "button",
}
function Component:init(template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.root = self:get_node(SCHEME.ROOT)
self.druid = self:get_druid()
self.druid = self:get_druid(template, nodes)
self.root = self:get_node("root")
self.button = self.druid:new_button(SCHEME.BUTTON, function() end)
self.button = self.druid:new_button("button", function() end)
end
function Component:on_remove() end
@@ -45,16 +38,10 @@ local component = require("druid.component")
---@class component_name: druid.base_component
local Component = component.create("component_name")
local SCHEME = {
ROOT = "root",
BUTTON = "button",
}
function Component:init(template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.root = self:get_node(SCHEME.ROOT)
self.druid = self:get_druid()
self.druid = self:get_druid(template, nodes)
self.root = self:get_node("root")
end
function Component:update(dt) end
@@ -92,7 +79,7 @@ local my_component = require("my.amazing.component")
function init(self)
self.druid = druid.new(self)
self.druid:new(my_component, "template_name", nodes)
self.druid:new(my_component, "template_name")
end
```
@@ -107,6 +94,7 @@ local druid = require("druid.druid")
local my_component = require("my.amazing.component")
function init(self)
-- Register makes a "druid:new_{component_name}" function available
druid.register("my_component", my_component)
end
```
@@ -145,36 +133,7 @@ Available keywords:
- `blocker`: Adds a [Druid Blocker](01-components.md#blocker) component.
- `slider`: Adds a [Druid Slider](01-components.md#slider) component. You should adjust the end position of the Slider after generating the file.
- `progress`: Adds a [Druid Progress](01-components.md#progress) component.
- `timer`: Adds a [Dr
uid Timer](01-components.md#timer) component.
## Best Practices for Custom Components
When working with each component, it's recommended to describe the component scheme in the following way:
```lua
-- Component module
local component = require("druid.component")
local M = component.create("your_component")
local SCHEME = {
ROOT = "root",
ITEM = "item",
TITLE = "title"
}
function M.init(self, template_name, node_table)
self:set_template(template_name)
self:set_nodes(node_table)
local root = self:get_node(SCHEME.ROOT)
local druid = self:get_druid()
-- Create components inside this component using the inner druid instance
end
```
- `timer`: Adds a [Druid Timer](01-components.md#timer) component.
## The Power of Using Templates

View File

@@ -3,7 +3,7 @@
## Input Bindings
By default, **Druid** utilizes the `/builtins/input/all.input_binding` for input bindings.
By default, **Druid** uses all key names from Defold's default `/builtins/input/all.input_binding` for input bindings.
**Druid** requires the following input bindings:
@@ -14,6 +14,11 @@ By default, **Druid** utilizes the `/builtins/input/all.input_binding` for input
- 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)
- Key trigger: `Left` -> `key_left` (for Rich Input component, optional)
- Key trigger: `Right` -> `key_right` (for Rich Input component, optional)
- Key trigger: `Shift` -> `key_lshift` (for Rich Input component, optional)
- Key trigger: `Ctrl` -> `key_lctrl` (for Rich Input component, optional)
- Key trigger: `Super` -> `key_lsuper` (for Rich Input component, optional)
- Touch triggers: `Touch multi` -> `touch_multi` (for Scroll component)
![](../media/input_binding_2.png)
@@ -37,6 +42,11 @@ input_key_backspace = key_backspace
input_multitouch = touch_multi
input_scroll_up = mouse_wheel_up
input_scroll_down = mouse_wheel_down
input_key_left = key_left
input_key_right = key_right
input_key_lshift = key_lshift
input_key_lctrl = key_lctrl
input_key_lsuper = key_lsuper
```

View File

@@ -500,3 +500,28 @@ Thanks to the my supporters:
Please support me if you like this project! It will help me keep engaged to update **Druid** and make it even better!
[![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#EA4AAA)](https://github.com/sponsors/insality) [![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/insality) [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/insality)
### Druid 0.12.0
**Changelog 0.12.0**
- New Logo!
- [Example] New Example Page with 40+ examples
- [Data List] Rework Data List. Now only works with Static Grid only. Now the Data List more stable with extended API.
- Add Cached Data List option. This used less memory (it's really much optimized) but requires uses the `on_add_element` and `on_remove_element` events to setup your nodes. All components should be the same class.
- [Rich Text] The Rich Text now applied to the text node instead of Rich Text Template (contained 3 nodes before - root, text and image prefabs)
- [Rich Input] Updated Rich Input. Now it goes with selection and cursor navigation. Added new input keys for setup in Druid (arrows keys, ctrl, shift)
- [System] Updated and fixed annotations
- [System] Removed `middleclass.lua`
- [System] Add `self:get_druid(template, nodes)` to escape the `self:set_template(template)` and `self:set_nodes(nodes)` calls in custom components
- [Input] Now user can tap from one text input area to another with one click. Before first tap is closed the focus on selected input.
- [Layout] Removed Layout component. Add new Layout component what do a some different things. It's like Dynamic Grid but with more control and settings.
- [Dynamic Grid] Deprecated Dynamic Grid. Layout will be instead of it.
- [Drag] Add touch param to Drag callbacks, it's much easier to add custom logic with knowledge of input action data.
- [Scroll] Add `scroll.view_size`, `scroll:set_view_size(size)` and `scroll:update_view_size()` functions to manage with current scroll input area and scroll visible part
- [Static Grid] Add `grid:set_item_size(size)`, `grid:sort_nodes(comparator)` functions
- [Text] Seems adjust by height for multiline text is workings good now
- [Rich Input] Extended Rich Input API
- [Progress Bar] More accurate scaling for progress bars fow images with slice9 params
- [Slider] Fix several slider issues in slider setup

View File

@@ -1,8 +0,0 @@
# Game Examples
## Family Island
## Sea Battle: Universe
## Monkey Mart

View File

@@ -63,8 +63,10 @@ function druid__base_component.get_context(self) end
--- Get Druid instance for inner component creation.
---@param self druid.base_component @{BaseComponent}
---@param template string|nil The template name
---@param nodes table|nil The nodes table
---@return druid_instance Druid instance with component context
function druid__base_component.get_druid(self) end
function druid__base_component.get_druid(self, template, nodes) end
--- Return component input priority
---@param self druid.base_component @{BaseComponent}
@@ -168,7 +170,7 @@ function druid__blocker.set_enabled(self, state) end
---@class druid.button : druid.base_component
---@field anim_node node Button animation node.
---@field anim_node node|nil Button animation node.
---@field click_zone node|nil Additional button click area, defined by another GUI node
---@field hover druid.hover The @{Hover}: Button Hover component
---@field node node Button trigger node
@@ -213,7 +215,7 @@ function druid__button.set_check_function(self, check_function, failure_callback
--- 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|nil Gui node
---@param zone node|string|nil Gui node
---@return druid.button Current button instance
function druid__button.set_click_zone(self, zone) end
@@ -239,9 +241,9 @@ function druid__button.set_web_user_interaction(self, is_web_mode) end
---@class druid.button.style
---@field AUTOHOLD_TRIGGER number Maximum hold time to trigger button release while holding
---@field DOUBLETAP_TIME number Time between double taps
---@field LONGTAP_TIME number Minimum time to trigger on_hold_callback
---@field AUTOHOLD_TRIGGER number|nil Maximum hold time to trigger button release while holding. Default: 0.8
---@field DOUBLETAP_TIME number|nil Time between double taps. Default: 0.4
---@field LONGTAP_TIME number|nil Minimum time to trigger on_hold_callback. Default: 0.4
---@field on_click function function(self, node)
---@field on_click_disabled function function(self, node)
---@field on_hover function function(self, node, hover_state)
@@ -252,7 +254,7 @@ local druid__button__style = {}
---@class druid.checkbox : druid.base_component
---@field button druid.button Button component from click_node
---@field click_node node Button trigger node
---@field click_node node|nil Button trigger node
---@field node node Visual node
---@field on_change_state druid.event On change state callback(self, state)
---@field style druid.checkbox.style Component style params.
@@ -267,8 +269,8 @@ function druid__checkbox.get_state(self) end
---@param self druid.checkbox @{Checkbox}
---@param node node Gui node
---@param callback function Checkbox callback
---@param click_node node Trigger node, by default equals to node
---@param initial_state boolean The initial state of checkbox, default - false
---@param click_node node|nil Trigger node, by default equals to node. Default: node
---@param initial_state boolean|nil The initial state of checkbox, default - false
function druid__checkbox.init(self, node, callback, click_node, initial_state) end
--- Set checkbox state
@@ -298,7 +300,7 @@ function druid__checkbox_group.get_state(self) end
---@param self druid.checkbox_group @{CheckboxGroup}
---@param nodes node[] Array of gui node
---@param callback function Checkbox callback
---@param click_nodes node[] Array of trigger nodes, by default equals to nodes
---@param click_nodes node[]|nil Array of trigger nodes, by default equals to nodes
function druid__checkbox_group.init(self, nodes, callback, click_nodes) end
--- Set checkbox group state
@@ -310,15 +312,23 @@ function druid__checkbox_group.set_state(self, indexes, is_instant) end
---@class druid.data_list : druid.base_component
---@field grid druid.static_grid|druid.dynamic_grid The Druid Grid component
---@field last_index number The current visual last data index
---@field last_index number The current last index of visual elements
---@field on_element_add druid.event On DataList visual element created Event callback(self, index, node, instance)
---@field on_element_remove druid.event On DataList visual element created Event callback(self, index)
---@field on_scroll_progress_change druid.event Event triggered when scroll progress is changed; event(self, progress_value)
---@field scroll druid.scroll The Druid scroll component
---@field scroll_progress number The current progress of scroll posititon
---@field top_index number The current visual top data index
---@field top_index number The current top index of visual elements
local druid__data_list = {}
--- Add element to DataList.
--- Currenly untested
---@param self druid.data_list @{DataList}
---@param data table
---@param index number|nil
---@param shift_policy number|nil The constant from const.SHIFT.*
function druid__data_list.add(self, data, index, shift_policy) end
--- Clear the DataList and refresh visuals
---@param self druid.data_list @{DataList}
function druid__data_list.clear(self) end
@@ -338,24 +348,11 @@ function druid__data_list.get_created_nodes(self) end
---@return table The current data array
function druid__data_list.get_data(self) end
--- Return first index from data.
--- It not always equals to 1
---@param self druid.data_list @{DataList}
function druid__data_list.get_first_index(self) end
--- Return index for data value
---@param self druid.data_list @{DataList}
---@param data table
function druid__data_list.get_index(self, data) end
--- Return last index from data
---@param self druid.data_list @{DataList}
function druid__data_list.get_last_index(self) end
--- Return amount of data
---@param self druid.data_list @{DataList}
function druid__data_list.get_length(self) end
--- The @{DataList} constructor
---@param self druid.data_list @{DataList}
---@param scroll druid.scroll The @{Scroll} instance for Data List component
@@ -367,6 +364,20 @@ function druid__data_list.init(self, scroll, grid, create_function) end
---@param self druid.data_list @{DataList}
function druid__data_list.on_remove(self) end
--- Remove element from DataList.
--- Currenly untested
---@param self druid.data_list @{DataList}
---@param index number|nil
---@param shift_policy number|nil The constant from const.SHIFT.*
function druid__data_list.remove(self, index, shift_policy) end
--- Remove element from DataList by data value.
--- Currenly untested
---@param self druid.data_list @{DataList}
---@param data table
---@param shift_policy number|nil The constant from const.SHIFT.*
function druid__data_list.remove_by_data(self, data, shift_policy) end
--- Instant scroll to element with passed index
---@param self druid.data_list @{DataList}
---@param index number
@@ -378,6 +389,12 @@ function druid__data_list.scroll_to_index(self, index) end
---@return druid.data_list Current DataList instance
function druid__data_list.set_data(self, data) end
--- Set refresh function for DataList component
---@param self druid.data_list @{DataList}
---@param is_use_cache boolean Use cache version of DataList. Requires make setup of components in on_element_add callback and clean in on_element_remove
---@return druid.data_list Current DataList instance
function druid__data_list.set_use_cache(self, is_use_cache) end
---@class druid.drag : druid.base_component
---@field can_x boolean Is drag component process vertical dragging.
@@ -385,17 +402,17 @@ function druid__data_list.set_data(self, data) end
---@field is_drag boolean Is component now dragging
---@field is_touch boolean Is component now touching
---@field node node Drag node
---@field on_drag druid.event on drag progress callback(self, dx, dy, total_x, total_y)
---@field on_drag_end druid.event Event on drag end callback(self, total_x, total_y)
---@field on_drag druid.event on drag progress callback(self, dx, dy, total_x, total_y, touch)
---@field on_drag_end druid.event Event on drag end callback(self, total_x, total_y, touch)
---@field on_drag_start druid.event Event on drag start callback(self, touch)
---@field on_touch_end druid.event Event on touch end callback(self)
---@field on_touch_start druid.event Event on touch start callback(self)
---@field screen_x number Current touch x screen position
---@field screen_y number Current touch y screen position
---@field style druid.drag.style Component style params.
---@field touch_start_pos vector3 Touch start position
---@field x number Current touch x position
---@field y number Current touch y position
---@field screen_x number Current touch x screen position
---@field screen_y number Current touch y screen position
local druid__drag = {}
--- The @{Drag} constructor
@@ -412,7 +429,7 @@ function druid__drag.is_enabled(self) end
--- Strict drag click area.
--- Useful for restrict events outside stencil node
---@param self druid.drag @{Drag}
---@param node node Gui node
---@param node node|string|nil Gui node
function druid__drag.set_click_zone(self, node) end
--- Set Drag input enabled or disabled
@@ -422,8 +439,8 @@ function druid__drag.set_enabled(self, is_enabled) end
---@class druid.drag.style
---@field DRAG_DEADZONE number Distance in pixels to start dragging
---@field NO_USE_SCREEN_KOEF boolean If screen aspect ratio affects on drag values
---@field DRAG_DEADZONE number|nil Distance in pixels to start dragging. Default: 10
---@field NO_USE_SCREEN_KOEF boolean|nil If screen aspect ratio affects on drag values. Default: false
local druid__drag__style = {}
@@ -487,7 +504,7 @@ function druid__dynamic_grid.get_offset(self) end
---@param index number The grid element index
---@param node node The node to be placed
---@param origin_index number|nil Index of nearby node
---@return vector3 Node position
---@return vector3 node position
function druid__dynamic_grid.get_pos(self, index, node, origin_index) end
--- Return grid content size
@@ -526,20 +543,33 @@ local druid__event = {}
function druid__event.clear(self) end
--- DruidEvent constructor
---@param callback function|nil Subscribe the callback on new event, if callback exist
---@param callback_context any|nil Additional context as first param to callback call
function druid__event.create(callback, callback_context) end
--- Return true, if event not have handler
---@param self druid.event @{DruidEvent}
---@param initial_callback function|nil Subscribe the callback on new event, if callback exist
function druid__event.initialize(self, initial_callback) end
---@return boolean True if event not have handlers
function druid__event.is_empty(self) end
--- Return true, if event have at lease one handler
---@param self druid.event @{DruidEvent}
---@return boolean True if event have handlers
function druid__event.is_exist(self) end
--- Check is event subscribed.
---@param self druid.event @{DruidEvent}
---@param callback function Callback itself
---@param callback_context any|nil Additional context as first param to callback call
---@return boolean, number|nil @Is event subscribed, return index of callback in event as second param
function druid__event.is_subscribed(self, callback, callback_context) end
--- Subscribe callback on event
---@param self druid.event @{DruidEvent}
---@param callback function Callback itself
---@param context any|nil Additional context as first param to callback call, usually it's self
function druid__event.subscribe(self, callback, context) end
---@param callback_context any|nil Additional context as first param to callback call, usually it's self
---@return boolean True if callback was subscribed
function druid__event.subscribe(self, callback, callback_context) end
--- Trigger the event and call all subscribed callbacks
---@param self druid.event @{DruidEvent}
@@ -549,15 +579,16 @@ function druid__event.trigger(self, ...) end
--- Unsubscribe callback on event
---@param self druid.event @{DruidEvent}
---@param callback function Callback itself
---@param context any|nil Additional context as first param to callback call
function druid__event.unsubscribe(self, callback, context) end
---@param callback_context any|nil Additional context as first param to callback call
function druid__event.unsubscribe(self, callback, callback_context) end
---@class druid.hotkey : druid.base_component
---@field button druid.button Button component from click_node
---@field click_node node Button trigger node
---@field click_node node|nil Button trigger node
---@field node node Visual node
---@field on_change_state druid.event On change state callback(self, state)
---@field on_hotkey_pressed druid.event On hotkey released callback(self, argument)
---@field on_hotkey_released druid.event On hotkey released callback(self, argument)
---@field style druid.hotkey.style Component style params.
local druid__hotkey = {}
@@ -588,15 +619,18 @@ local druid__hotkey__style = {}
---@class druid.hover : druid.base_component
---@field node node Hover node
---@field on_hover druid.event On hover callback(self, state, hover_instance)
---@field on_mouse_hover druid.event On mouse hover callback(self, state, hover_instance)
---@field style druid.hover.style Component style params.
local druid__hover = {}
--- The @{Hover} constructor
---@param self druid.hover @{Hover}
---@param node node Gui node
---@param on_hover_callback function Hover callback
function druid__hover.init(self, node, on_hover_callback) end
---@param on_mouse_hover function On mouse hover callback
function druid__hover.init(self, node, on_hover_callback, on_mouse_hover) end
--- Return current hover enabled state
---@param self druid.hover @{Hover}
@@ -618,7 +652,7 @@ function druid__hover.is_mouse_hovered(self) end
--- Strict hover click area.
--- Useful for no click events outside stencil node
---@param self druid.hover @{Hover}
---@param zone node Gui node
---@param zone node|string|nil Gui node
function druid__hover.set_click_zone(self, zone) end
--- Set enable state of hover component.
@@ -638,21 +672,37 @@ function druid__hover.set_hover(self, state) end
function druid__hover.set_mouse_hover(self, state) end
---@class druid.hover.style
---@field ON_HOVER_CURSOR string Mouse hover style on node hover
---@field ON_MOUSE_HOVER_CURSOR string Mouse hover style on node mouse hover
local druid__hover__style = {}
---@class druid.input : druid.base_component
---@field allowerd_characters string|nil Pattern matching for user input
---@field button druid.button Button component
---@field current_value string Current input value with marked text
---@field cursor_index number The cursor index.
---@field end_index number Theselection end index.
---@field is_empty boolean Is current input is empty now
---@field is_selected boolean Is current input selected now
---@field keyboard_type number Gui keyboard type for input field
---@field marked_text_width number Marked text width
---@field marked_value string Marked text for input field.
---@field max_length number|nil Max length for input text
---@field on_input_empty druid.event On input field text change to empty string callback(self, input_text)
---@field on_input_full druid.event On input field text change to max length string callback(self, input_text)
---@field on_input_select druid.event On input field select callback(self, button_node)
---@field on_input_select druid.event On input field select callback(self, input_instance)
---@field on_input_text druid.event On input field text change callback(self, input_text)
---@field on_input_unselect druid.event On input field unselect callback(self, input_text)
---@field on_input_wrong druid.event On trying user input with not allowed character callback(self, params, button_instance)
---@field on_input_unselect druid.event On input field unselect callback(self, input_text, input_instance)
---@field on_input_wrong druid.event On trying user input with not allowed character callback(self, params, input_text)
---@field on_select_cursor_change druid.event On cursor position change callback(self, cursor_index, start_index, end_index)
---@field previous_value string Previous input value
---@field start_index number The selection start index.
---@field style druid.input.style Component style params.
---@field text druid.text Text component
---@field text_width number Text width
---@field value string Current input value
local druid__input = {}
--- Return current input field text
@@ -660,6 +710,12 @@ local druid__input = {}
---@return string The current input field text
function druid__input.get_text(self) end
--- Replace selected text with new text
---@param self druid.input @{Input}
---@param text string The text to replace selected text
---@return string New input text
function druid__input.get_text_selected_replaced(self, text) end
--- The @{Input} constructor
---@param self druid.input @{Input}
---@param click_node node Node to enabled input component
@@ -667,8 +723,16 @@ function druid__input.get_text(self) end
---@param keyboard_type number|nil Gui keyboard type for input field
function druid__input.init(self, click_node, text_node, keyboard_type) end
--- Change cursor position by delta
---@param self druid.input @{Input}
---@param delta number side for cursor position, -1 for left, 1 for right
---@param is_add_to_selection boolean (Shift key)
---@param is_move_to_end boolean (Ctrl key)
function druid__input.move_selection(self, delta, is_add_to_selection, is_move_to_end) end
--- Reset current input selection and return previous value
---@param self druid.input @{Input}
---@return druid.input Current input instance
function druid__input.reset_changes(self) end
--- Select input field.
@@ -676,6 +740,14 @@ function druid__input.reset_changes(self) end
---@param self druid.input @{Input}
function druid__input.select(self) end
--- Set cursor position in input field
---@param self druid.input @{Input}
---@param cursor_index number|nil Cursor index for cursor position, if nil - will be set to the end of the text
---@param start_index number|nil Start index for cursor position, if nil - will be set to the end of the text
---@param end_index number|nil End index for cursor position, if nil - will be set to the start_index
---@return druid.input Current input instance
function druid__input.select_cursor(self, cursor_index, start_index, end_index) end
--- Set allowed charaters for input field.
--- See: https://defold.com/ref/stable/string/ ex: [%a%d] for alpha and numeric
---@param self druid.input @{Input}
@@ -702,11 +774,9 @@ function druid__input.unselect(self) end
---@class druid.input.style
---@field IS_LONGTAP_ERASE boolean Is long tap will erase current input data
---@field IS_UNSELECT_ON_RESELECT boolean If true, call unselect on select selected input
---@field MASK_DEFAULT_CHAR string Default character mask for password input
---@field NO_CONSUME_INPUT_WHILE_SELECTED boolean If true, will not consume input while input is selected. It's allow to interact with other components while input is selected (text input still captured)
---@field button_style table Custom button style for input node
---@field IS_LONGTAP_ERASE boolean Is long tap will erase current input data. Default: false
---@field IS_UNSELECT_ON_RESELECT boolean If true, call unselect on select selected input. Default: false
---@field MASK_DEFAULT_CHAR string Default character mask for password input. Default: *]
---@field on_input_wrong function (self, button_node) Callback on wrong user input
---@field on_select function (self, button_node) Callback on input field selecting
---@field on_unselect function (self, button_node) Callback on input field unselecting
@@ -734,8 +804,8 @@ function druid__lang_text.format(self, a, b, c, d, e, f, g) end
--- The @{LangText} constructor
---@param self druid.lang_text @{LangText}
---@param node string|node The node_id or gui.get_node(node_id)
---@param locale_id string Default locale id or text from node as default
---@param adjust_type string Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
---@param locale_id string|nil Default locale id or text from node as default
---@param adjust_type string|nil 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
@@ -761,67 +831,8 @@ function druid__lang_text.translate(self, locale_id, a, b, c, d, e, f, g) end
---@class druid.layout : druid.base_component
---@field mode string Current layout mode
---@field node node Layout node
---@field on_size_changed druid.event On window resize callback(self, new_size)
local druid__layout = {}
--- Set node for layout node to fit inside it.
--- Pass nil to reset
---@param self druid.layout @{Layout}
---@param node node|nil
---@return druid.layout @{Layout}
function druid__layout.fit_into_node(self, node) end
--- Set size for layout node to fit inside it
---@param self druid.layout @{Layout}
---@param target_size vector3
---@return druid.layout @{Layout}
function druid__layout.fit_into_size(self, target_size) end
--- Set current size for layout node to fit inside it
---@param self druid.layout @{Layout}
---@return druid.layout @{Layout}
function druid__layout.fit_into_window(self) end
--- The @{Layout} constructor
---@param self druid.layout @{Layout}
---@param node node Gui node
---@param mode string The layout mode (from const.LAYOUT_MODE)
---@param on_size_changed_callback function|nil The callback on window resize
function druid__layout.init(self, node, mode, on_size_changed_callback) end
--- Set max gui upscale for FIT adjust mode (or side).
--- It happens on bigger render gui screen
---@param self druid.layout @{Layout}
---@param max_gui_upscale number
---@return druid.layout @{Layout}
function druid__layout.set_max_gui_upscale(self, max_gui_upscale) end
--- Set maximum size of layout node
---@param self druid.layout @{Layout}
---@param max_size vector3
---@return druid.layout @{Layout}
function druid__layout.set_max_size(self, max_size) end
--- Set minimal size of layout node
---@param self druid.layout @{Layout}
---@param min_size vector3
---@return druid.layout @{Layout}
function druid__layout.set_min_size(self, min_size) end
--- Set new origin position of layout node.
--- You should apply this on node movement
---@param self druid.layout @{Layout}
---@param new_origin_position vector3
---@return druid.layout @{Layout}
function druid__layout.set_origin_position(self, new_origin_position) end
--- Set new origin size of layout node.
--- You should apply this on node manual size change
---@param self druid.layout @{Layout}
---@param new_origin_size vector3
---@return druid.layout @{Layout}
function druid__layout.set_origin_size(self, new_origin_size) end
---@class druid.pin_knob : druid.base_component
---@field druid druid_instance The component druid instance
@@ -846,7 +857,7 @@ function druid__pin_knob.set_angle(self, cur_value, min, max) end
--- Set current and min/max angles for component
---@param self druid.pin_knob @{PinKnob}
---@param value number The spin speed multiplier
---@param value number|nil The spin speed multiplier. Default: 1
---@return druid.pin_knob @{PinKnob}
function druid__pin_knob.set_friction(self, value) end
@@ -878,7 +889,7 @@ function druid__progress.get(self) end
---@param self druid.progress @{Progress}
---@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
---@param init_value number|nil Initial value of progress bar. Default: 1
function druid__progress.init(self, node, key, init_value) end
--- Set progress bar max node size
@@ -906,8 +917,8 @@ function druid__progress.to(self, to, callback) end
---@class druid.progress.style
---@field MIN_DELTA number Minimum step to fill progress bar
---@field SPEED number Progress bas fill rate. More -> faster
---@field MIN_DELTA number|nil Minimum step to fill progress bar. Default: 0.005
---@field SPEED number|nil Progress bas fill rate. More -> faster. Default: 5
local druid__progress__style = {}
@@ -925,7 +936,7 @@ function druid__radio_group.get_state(self) end
---@param self druid.radio_group @{RadioGroup}
---@param nodes node[] Array of gui node
---@param callback function Radio callback
---@param click_nodes node[] Array of trigger nodes, by default equals to nodes
---@param click_nodes node[]|nil Array of trigger nodes, by default equals to nodes. Default - nodes
function druid__radio_group.init(self, nodes, callback, click_nodes) end
--- Set radio group state
@@ -935,7 +946,7 @@ function druid__radio_group.init(self, nodes, callback, click_nodes) end
function druid__radio_group.set_state(self, index, is_instant) end
---@class druid.rich_input : druid.input
---@class druid.rich_input
---@field cursor node On input field text change to empty string callback(self, input_text)
---@field druid druid_instance The component druid instance
---@field input druid.input On input field text change callback(self, input_text)
@@ -943,9 +954,8 @@ function druid__radio_group.set_state(self, index, is_instant) end
---@field root node Root node
local druid__rich_input = {}
--- GSet input field text
--- Set input field text
---@param self druid.rich_input @{RichInput}
---@return string Current input text
function druid__rich_input.get_text(self) end
--- The @{RichInput} constructor
@@ -954,6 +964,10 @@ function druid__rich_input.get_text(self) end
---@param nodes table Nodes table from gui.clone_tree
function druid__rich_input.init(self, template, nodes) end
--- Select input field
---@param self druid.rich_input @{RichInput}
function druid__rich_input.select(self) end
--- Set allowed charaters for input field.
--- See: https://defold.com/ref/stable/string/ ex: [%a%d] for alpha and numeric
---@param self druid.rich_input @{RichInput}
@@ -961,18 +975,38 @@ function druid__rich_input.init(self, template, nodes) end
---@return druid.rich_input Current instance
function druid__rich_input.set_allowed_characters(self, characters) end
--- Set input field font
---@param self druid.rich_input @{RichInput}
---@param font hash The font hash
---@return druid.input Current input instance
function druid__rich_input.set_font(self, font) end
--- Set placeholder text
---@param self druid.rich_input @{RichInput}
---@param placeholder_text string|nil The placeholder text
---@return druid.rich_input Current instance
---@param placeholder_text string The placeholder text
function druid__rich_input.set_placeholder(self, placeholder_text) end
--- Set input field text
---@param self druid.rich_input @{RichInput}
---@param text string The input text
---@return druid.input Current input instance
function druid__rich_input.set_text(self, text) end
---@class druid.rich_text : druid.base_component
---@field druid druid_instance The component druid instance
---@field icon_prefab node The icon prefab node
---@field root node The root node of the Rich Text
---@field style druid.rich_text.style Component style params.
---@field text_prefab node The text prefab node
local druid__rich_text = {}
--- Split a word into it's characters
---@param self druid.rich_text @{RichText}
---@param word druid.rich_text.word
---@return druid.rich_text.word[] characters
function druid__rich_text.characters(self, word) end
--- Clear all created words.
function druid__rich_text.clear() end
@@ -980,38 +1014,44 @@ function druid__rich_text.clear() end
---@return druid.rich_text.lines_metrics
function druid__rich_text.get_line_metric() end
--- Get current text
---@param self druid.rich_text @{RichText}
---@return string text
function druid__rich_text.get_text(self) end
--- Get all current words.
---@return table druid.rich_text.word[]
function druid__rich_text.get_words() end
--- The @{RichText} 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
---@param text_node node|string The text node to make Rich Text
---@param value string|nil The initial text value. Default will be gui.get_text(text_node)
function druid__rich_text.init(self, text_node, value) end
--- Set text for Rich Text
---@param self druid.rich_text @{RichText}
---@param text string The text to set
---@param text string|nil The text to set
---@return druid.rich_text.word[] words
---@return druid.rich_text.lines_metrics line_metrics
function druid__rich_text.set_text(self, text) end
--- Get all words, which has a passed tag.
---@param self druid.rich_text @{RichText}
---@param tag string
---@return druid.rich_text.word[] words
function druid__rich_text.tagged(tag) end
function druid__rich_text.tagged(self, tag) end
---@class druid.rich_text.style
---@field ADJUST_SCALE_DELTA number Scale step on each height adjust step
---@field ADJUST_STEPS number Amount steps of attemps text adjust by height
---@field COLORS table Rich Text color aliases
---@field ADJUST_SCALE_DELTA number|nil Scale step on each height adjust step. Default: 0.02
---@field ADJUST_STEPS number|nil Amount steps of attemps text adjust by height. Default: 20
---@field COLORS table|nil Rich Text color aliases. Default: {}
local druid__rich_text__style = {}
---@class druid.scroll : druid.base_component
---@field _is_inert bool Flag, if scroll now moving by inertion
---@field _is_inert boolean Flag, if scroll now moving by inertion
---@field available_pos vector4 Available position for content node: (min_x, max_y, max_x, min_y)
---@field available_size vector3 Size of available positions: (width, height, 0)
---@field content_node node Scroll content node
@@ -1026,6 +1066,7 @@ local druid__rich_text__style = {}
---@field style druid.scroll.style Component style params.
---@field target_position vector3 Current scroll target position
---@field view_node node Scroll view node
---@field view_size vector3 Scroll view size
local druid__scroll = {}
--- Bind the grid component (Static or Dynamic) to recalculate scroll size on grid changes
@@ -1084,7 +1125,7 @@ function druid__scroll.scroll_to_percent(self, percent, is_instant) end
--- Strict drag scroll area.
--- Useful for restrict events outside stencil node
---@param self druid.drag
---@param node node Gui node
---@param node node|string Gui node
function druid__scroll.set_click_zone(self, node) end
--- Set extra size for scroll stretching.
@@ -1118,7 +1159,7 @@ function druid__scroll.set_points(self, points) end
--- It will change content gui node size
---@param self druid.scroll @{Scroll}
---@param size vector3 The new size for content node
---@param offset vector3 Offset value to set, where content is starts
---@param offset vector3|nil Offset value to set, where content is starts
---@return druid.scroll Current scroll instance
function druid__scroll.set_size(self, size, offset) end
@@ -1128,25 +1169,35 @@ function druid__scroll.set_size(self, size, offset) end
---@return druid.scroll Current scroll instance
function druid__scroll.set_vertical_scroll(self, state) end
--- Set new scroll view size in case the node size was changed.
---@param self druid.scroll @{Scroll}
---@param size vector3 The new size for view node
---@return druid.scroll Current scroll instance
function druid__scroll.set_view_size(self, size) end
--- Refresh scroll view size
---@param self druid.scroll @{Scroll}
function druid__scroll.update_view_size(self) end
---@class druid.scroll.style
---@field ANIM_SPEED number Scroll gui.animation speed for scroll_to function
---@field BACK_SPEED number Scroll back returning lerp speed
---@field EXTRA_STRETCH_SIZE number extra size in pixels outside of scroll (stretch effect)
---@field FRICT number Multiplier for free inertion
---@field FRICT_HOLD number Multiplier for inertion, while touching
---@field INERT_SPEED number Multiplier for inertion speed
---@field INERT_THRESHOLD number Scroll speed to stop inertion
---@field POINTS_DEADZONE number Speed to check points of interests in no_inertion mode
---@field SMALL_CONTENT_SCROLL boolean If true, content node with size less than view node size can be scrolled
---@field WHEEL_SCROLL_BY_INERTION boolean If true, wheel will add inertion to scroll. Direct set position otherwise.
---@field WHEEL_SCROLL_INVERTED boolean If true, invert direction for touchpad and mouse wheel scroll
---@field WHEEL_SCROLL_SPEED boolean The scroll speed via mouse wheel scroll or touchpad. Set to 0 to disable wheel scrolling
---@field ANIM_SPEED number|nil Scroll gui.animation speed for scroll_to function. Default: 2
---@field BACK_SPEED number|nil Scroll back returning lerp speed. Default: 35
---@field EXTRA_STRETCH_SIZE number|nil extra size in pixels outside of scroll (stretch effect). Default: 0
---@field FRICT number|nil Multiplier for free inertion. Default: 0
---@field FRICT_HOLD number|nil Multiplier for inertion, while touching. Default: 0
---@field INERT_SPEED number|nil Multiplier for inertion speed. Default: 30
---@field INERT_THRESHOLD number|nil Scroll speed to stop inertion. Default: 3
---@field POINTS_DEADZONE number|nil Speed to check points of interests in no_inertion mode. Default: 20
---@field SMALL_CONTENT_SCROLL boolean|nil If true, content node with size less than view node size can be scrolled. Default: false
---@field WHEEL_SCROLL_BY_INERTION boolean|nil If true, wheel will add inertion to scroll. Direct set position otherwise.. Default: false
---@field WHEEL_SCROLL_INVERTED boolean|nil If true, invert direction for touchpad and mouse wheel scroll. Default: false
---@field WHEEL_SCROLL_SPEED boolean|nil The scroll speed via mouse wheel scroll or touchpad. Set to 0 to disable wheel scrolling. Default: 0
local druid__scroll__style = {}
---@class druid.slider : druid.base_component
---@field dist number Length between start and end position
---@field dist vector3 Length between start and end position
---@field end_pos vector3 End pin node position
---@field is_drag boolean Current drag state
---@field node node Slider pin node
@@ -1164,16 +1215,26 @@ local druid__slider = {}
---@param callback function|nil On slider change callback
function druid__slider.init(self, node, end_pos, callback) end
--- Check if Slider component is enabled
---@param self druid.slider @{Slider}
---@return boolean
function druid__slider.is_enabled(self) end
--- Set value for slider
---@param self druid.slider @{Slider}
---@param value number Value from 0 to 1
---@param is_silent boolean|nil Don't trigger event if true
function druid__slider.set(self, value, is_silent) end
--- Set Slider input enabled or disabled
---@param self druid.slider @{Slider}
---@param is_enabled boolean
function druid__slider.set_enabled(self, is_enabled) end
--- Set input zone for slider.
--- User can touch any place of node, pin instantly will move at this position and node drag will start. This function require the Defold version 1.3.0+
---@param self druid.slider @{Slider}
---@param input_node node
---@param input_node node|string|nil
---@return druid.slider @{Slider}
function druid__slider.set_input_node(self, input_node) end
@@ -1258,7 +1319,7 @@ function druid__static_grid.get_size(self) end
---@param self druid.static_grid @{StaticGrid}
---@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
---@param in_row number|nil How many nodes in row can be placed. By default 1
function druid__static_grid.init(self, parent, element, in_row) end
--- Remove the item from the grid.
@@ -1282,6 +1343,20 @@ function druid__static_grid.set_anchor(self, anchor) end
---@return druid.static_grid Current grid instance
function druid__static_grid.set_in_row(self, in_row) end
--- Set new node size for grid
---@param self druid.static_grid @{StaticGrid}
---@param width number The new node width
---@param height number The new node height
---@return druid.static_grid Current grid instance
function druid__static_grid.set_item_size(self, width, height) end
--- Set new items to the grid.
--- All previous items will be removed
---@param self druid.static_grid @{StaticGrid}
---@param nodes node[] The new grid nodes
---@param is_instant boolean If true, update node positions instantly
function druid__static_grid.set_items(self, nodes, is_instant) end
--- Change set position function for grid nodes.
--- It will call on update poses on grid elements. Default: gui.set_position
---@param self druid.static_grid @{StaticGrid}
@@ -1289,10 +1364,16 @@ function druid__static_grid.set_in_row(self, in_row) end
---@return druid.static_grid Current grid instance
function druid__static_grid.set_position_function(self, callback) end
--- Sort grid nodes by custom comparator function
---@param self druid.static_grid @{StaticGrid}
---@param comparator function The comparator function. (a, b) -> boolean
---@return druid.static_grid Current grid instance
function druid__static_grid.sort_nodes(self, comparator) end
---@class druid.static_grid.style
---@field IS_ALIGN_LAST_ROW boolean If true, always align last row of the grid as grid pivot sets
---@field IS_DYNAMIC_NODE_POSES boolean If true, always center grid content as grid pivot sets
---@field IS_ALIGN_LAST_ROW boolean|nil If true, always align last row of the grid as grid pivot sets. Default: false
---@field IS_DYNAMIC_NODE_POSES boolean|nil If true, always center grid content as grid pivot sets. Default: false
local druid__static_grid__style = {}
@@ -1312,14 +1393,14 @@ function druid__swipe.init(self, node, on_swipe_callback) end
--- Strict swipe click area.
--- Useful for restrict events outside stencil node
---@param self druid.swipe @{Swipe}
---@param zone node Gui node
---@param zone node|string|nil Gui node
function druid__swipe.set_click_zone(self, zone) end
---@class druid.swipe.style
---@field SWIPE_THRESHOLD number Minimum distance for swipe trigger
---@field SWIPE_TIME number Maximum time for swipe trigger
---@field SWIPE_TRIGGER_ON_MOVE boolean If true, trigger on swipe moving, not only release action
---@field SWIPE_THRESHOLD number|nil Minimum distance for swipe trigger. Default: 50
---@field SWIPE_TIME number|nil Maximum time for swipe trigger. Default: 0.4
---@field SWIPE_TRIGGER_ON_MOVE boolean|nil If true, trigger on swipe moving, not only release action. Default: false
local druid__swipe__style = {}
@@ -1346,6 +1427,12 @@ local druid__text = {}
---@return number The current text adjust type
function druid__text.get_text_adjust(self, adjust_type) end
--- Get chars count by width
---@param self druid.text @{Text}
---@param width number
---@return number Chars count
function druid__text.get_text_index_by_width(self, width) end
--- Calculate text width with font with respect to trailing space
---@param self druid.text @{Text}
---@param text string |nil
@@ -1356,8 +1443,8 @@ function druid__text.get_text_size(self, text) end
--- The @{Text} constructor
---@param self druid.text @{Text}
---@param node string|node Node name or GUI Text Node itself
---@param value string|nil Initial text. Default value is node text from GUI scene.
---@param adjust_type string Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
---@param value string|nil Initial text. Default value is node text from GUI scene. Default: nil
---@param adjust_type string|nil Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference. Default: DOWNSCALE
function druid__text.init(self, node, value, adjust_type) end
--- Return true, if text with line break
@@ -1417,8 +1504,10 @@ function druid__text.set_to(self, set_to) end
---@class druid.text.style
---@field DEFAULT_ADJUST string The default adjust type for any text component
---@field TRIM_POSTFIX string The postfix for TRIM adjust type
---@field ADJUST_SCALE_DELTA string|nil Scale step on each height adjust step. Default: 0.02
---@field ADJUST_STEPS string|nil Amount of iterations for text adjust by height. Default: 20
---@field DEFAULT_ADJUST string|nil The default adjust type for any text component. Default: DOWNSCALE
---@field TRIM_POSTFIX string|nil The postfix for TRIM adjust type. Default: ...
local druid__text__style = {}
@@ -1435,7 +1524,7 @@ local druid__timer = {}
--- The @{Timer} constructor
---@param self druid.timer @{Timer}
---@param node node Gui text node
---@param seconds_from number Start timer value in seconds
---@param seconds_from number|nil Start timer value in seconds
---@param seconds_to number|nil End timer value in seconds
---@param callback function|nil Function on timer end
function druid__timer.init(self, node, seconds_from, seconds_to, callback) end
@@ -1464,13 +1553,6 @@ local druid_instance = {}
---@param self druid_instance
function druid_instance.final(self) end
--- Create new component.
---@param self druid_instance
---@param component druid.base_component Component module
---@param ... any Other component params to pass it to component:init function
---@return druid.base_component Component instance
function druid_instance.new(self, component, ...) end
--- Create @{BackHandler} component
---@param self druid_instance
---@param callback function|nil @The callback(self, custom_args) to call on back event
@@ -1488,8 +1570,8 @@ function druid_instance.new_blocker(self, node) end
---@param self druid_instance
---@param node string|node The node_id or gui.get_node(node_id)
---@param callback function|nil Button callback
---@param params table|nil Button callback params
---@param anim_node node|nil Button anim node (node, if not provided)
---@param params any|nil Button callback params
---@param anim_node node|string|nil Button anim node (node, if not provided)
---@return druid.button @{Button} component
function druid_instance.new_button(self, node, callback, params, anim_node) end
@@ -1504,9 +1586,9 @@ function druid_instance.new_checkbox(self, node, callback, click_node, initial_s
--- Create @{CheckboxGroup} component
---@param self druid_instance
---@param nodes node[] Array of gui node
---@param nodes (node|string)[] Array of gui node
---@param callback function Checkbox callback
---@param click_nodes node[] Array of trigger nodes, by default equals to nodes
---@param click_nodes (node|string)[]|nil Array of trigger nodes, by default equals to nodes
---@return druid.checkbox_group @{CheckboxGroup} component
function druid_instance.new_checkbox_group(self, nodes, callback, click_nodes) end
@@ -1543,13 +1625,14 @@ function druid_instance.new_hotkey(self, keys_array, callback, callback_argument
---@param self druid_instance
---@param node string|node The node_id or gui.get_node(node_id)
---@param on_hover_callback function|nil Hover callback
---@param on_mouse_hover_callback function|nil Mouse hover callback
---@return druid.hover @{Hover} component
function druid_instance.new_hover(self, node, on_hover_callback) end
function druid_instance.new_hover(self, node, on_hover_callback, on_mouse_hover_callback) end
--- Create @{Input} component
---@param self druid_instance
---@param click_node string|node Button node to enabled input component
---@param text_node string|node Text node what will be changed on user input
---@param text_node string|node|druid.text Text node what will be changed on user input
---@param keyboard_type number|nil Gui keyboard type for input field
---@return druid.input @{Input} component
function druid_instance.new_input(self, click_node, text_node, keyboard_type) end
@@ -1579,9 +1662,9 @@ function druid_instance.new_progress(self, node, key, init_value) end
--- Create @{RadioGroup} component
---@param self druid_instance
---@param nodes node[] Array of gui node
---@param nodes (node|string)[] Array of gui node
---@param callback function Radio callback
---@param click_nodes node[] Array of trigger nodes, by default equals to nodes
---@param click_nodes (node|string)[]|nil Array of trigger nodes, by default equals to nodes
---@return druid.radio_group @{RadioGroup} component
function druid_instance.new_radio_group(self, nodes, callback, click_nodes) end
@@ -1660,19 +1743,20 @@ function druid_instance.on_message(self, message_id, message, sender) end
--- Component `on_remove` function will be invoked, if exist.
---@param self druid_instance
---@param component druid.base_component Component instance
---@return boolean True if component was removed
function druid_instance.remove(self, component) end
--- Set blacklist components for input processing.
--- If blacklist is not empty and component contains in this list, component will be not processed on input step
---@param self druid_instance @{DruidInstance}
---@param blacklist_components table|druid.base_component The array of component to blacklist
---@param blacklist_components table|druid.base_component|nil The array of component to blacklist
---@return self @{DruidInstance}
function druid_instance.set_blacklist(self, blacklist_components) end
--- Set whitelist components for input processing.
--- If whitelist is not empty and component not contains in this list, component will be not processed on input step
---@param self druid_instance
---@param whitelist_components table|druid.base_component The array of component to whitelist
---@param whitelist_components table|druid.base_component|nil The array of component to whitelist
---@return self @{DruidInstance}
function druid_instance.set_whitelist(self, whitelist_components) end
@@ -1780,10 +1864,18 @@ function helper.insert_with_shift(array, any, index, shift_policy) end
---@return boolean Is mobile
function helper.is_mobile() end
--- Check if device is mobile and can support multitouch
---@return boolean Is multitouch supported
function helper.is_multitouch_supported() end
--- Check if device is HTML5
---@return boolean Is web
function helper.is_web() end
--- Check if device is HTML5 mobile
---@return boolean Is web mobile
function helper.is_web_mobile() end
--- Lerp between two values
---@param a number First value
---@param b number Second value
@@ -1825,11 +1917,15 @@ function helper.table_to_string(t) end
-- Manual Annotations --
---@class druid.component: druid.base_component
---@class druid.rich_text.metrics
---@field width number
---@field height number
---@field offset_x number|nil
---@field offset_y number|nil
---@field max_ascent number
---@field max_descent number
---@field node_size vector3|nil @For images only
---@class druid.rich_text.lines_metrics
@@ -1846,7 +1942,7 @@ function helper.table_to_string(t) end
---@field scale vector3
---@field size vector3
---@field metrics druid.rich_text.metrics
---@field pivot number @ The gui.PIVOT_* constant
---@field pivot userdata @ The gui.PIVOT_* constant
---@field text string
---@field shadow vector4
---@field outline vector4
@@ -1856,6 +1952,9 @@ function helper.table_to_string(t) end
---@field anchor number
---@field br boolean
---@field nobr boolean
---@field source_text string
---@field image_color vector4
---@field text_color vector4
---@class druid.rich_text.image
---@field texture string
@@ -1867,6 +1966,7 @@ function helper.table_to_string(t) end
---@field parent node
---@field size number
---@field fonts table<string, string>
---@field scale vector3
---@field color vector4
---@field shadow vector4
---@field outline vector4
@@ -1874,11 +1974,46 @@ function helper.table_to_string(t) end
---@field image_pixel_grid_snap boolean
---@field combine_words boolean
---@field default_animation string
---@field node_prefab node
---@field text_prefab node
---@field adjust_scale number
---@field default_texture string
---@field is_multiline boolean
---@field text_leading number
---@field font hash
---@field width number
---@field height number
---@class GUITextMetrics
---@field width number
---@field height number
---@field max_ascent number
---@field max_descent number
---@class utf8
---@field len fun(s: string):number
---@field sub fun(s: string, start_index: number, length: number)
---@field reverse fun()
---@field char fun()
---@field unicode fun()
---@field gensub fun()
---@field byte fun()
---@field find fun()
---@field match fun(s: string, m: string)
---@field gmatch fun(s: string, m: string)
---@field gsub fun()
---@field dump fun()
---@field format fun()
---@field lower fun()
---@field upper fun()
---@field rep fun()
---Add generics to some functions.
---Create new component.
---@generic T: druid.base_component
---@param self druid_instance
---@param component T Component module
---@param ... any Other component params to pass it to component:init function
---@return T Component instance
function druid_instance.new(self, component, ...) end

View File

@@ -123,7 +123,7 @@
-- 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
-- @tfield node|nil anim_node Default node
---Custom args for any Button event. Setup in Button constructor
-- @tfield any params
@@ -240,7 +240,12 @@ local function on_button_release(self)
is_double_click = is_double_click and self.on_double_click:is_exist()
if is_long_click then
local is_hold_complete = (time - self.last_pressed_time) >= self.style.AUTOHOLD_TRIGGER
if is_hold_complete then
on_button_long_click(self)
else
self.on_click_outside:trigger(self:get_context(), self.params, self)
end
elseif is_double_click then
on_button_double_click(self)
else
@@ -258,9 +263,9 @@ end
-- 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
-- @tfield[opt=0.8] number AUTOHOLD_TRIGGER Maximum hold time to trigger button release while holding
-- @tfield[opt=0.4] number DOUBLETAP_TIME Time between double taps
-- @tfield number|nil LONGTAP_TIME Minimum time to trigger on_hold_callback. Default: 0.4
-- @tfield number|nil AUTOHOLD_TRIGGER Maximum hold time to trigger button release while holding. Default: 0.8
-- @tfield number|nil DOUBLETAP_TIME Time between double taps. Default: 0.4
-- @tfield function on_click function(self, node)
-- @tfield function on_click_disabled function(self, node)
-- @tfield function on_hover function(self, node, hover_state)
@@ -339,10 +344,7 @@ function Button.on_input(self, action_id, action)
return false
end
if not self:is_enabled() then
return false
end
local is_consume = true
local is_pick = true
local is_key_trigger = (action_id == self.key_trigger)
if not is_key_trigger then
@@ -365,6 +367,7 @@ function Button.on_input(self, action_id, action)
if is_key_trigger then
self.hover:set_hover(not action.released)
is_consume = false
end
if action.pressed then
@@ -380,19 +383,19 @@ function Button.on_input(self, action_id, action)
on_button_click(self)
end)
end
return true
return is_consume
end
-- While hold button, repeat rate pick from input.repeat_interval
if action.repeated then
if self.on_repeated_click:is_exist() and self.can_action then
on_button_repeated_click(self)
return true
return is_consume
end
end
if action.released then
return on_button_release(self)
return on_button_release(self) and is_consume
end
if self.can_action and self.on_long_click:is_exist() then
@@ -400,21 +403,23 @@ function Button.on_input(self, action_id, action)
if self.style.AUTOHOLD_TRIGGER <= press_time then
on_button_release(self)
return true
return is_consume
end
if press_time >= self.style.LONGTAP_TIME then
on_button_hold(self, press_time)
return true
return is_consume
end
end
return not self.disabled
return not self.disabled and is_consume
end
function Button.on_input_interrupt(self)
self.can_action = false
self.hover:set_hover(false)
self.hover:set_mouse_hover(false)
end
@@ -478,7 +483,7 @@ end
--
-- This functions calls automatically if you don't disable it in game.project: druid.no_stencil_check
-- @tparam Button self @{Button}
-- @tparam node|nil zone Gui node
-- @tparam node|string|nil zone Gui node
-- @treturn Button Current button instance
-- @usage
-- button:set_click_zone("stencil_node")

View File

@@ -22,10 +22,10 @@
--- Event on drag start callback(self, touch)
-- @tfield DruidEvent on_drag_start @{DruidEvent}
--- on drag progress callback(self, dx, dy, total_x, total_y)
--- on drag progress callback(self, dx, dy, total_x, total_y, touch)
-- @tfield DruidEvent on_drag Event @{DruidEvent}
--- Event on drag end callback(self, total_x, total_y)
--- Event on drag end callback(self, total_x, total_y, touch)
-- @tfield DruidEvent on_drag_end @{DruidEvent}
--- Is component now touching
@@ -175,8 +175,8 @@ end
-- You can override this component styles params in druid styles table
-- or create your own style
-- @table style
-- @tfield[opt=10] number DRAG_DEADZONE Distance in pixels to start dragging
-- @tfield[opt=false] boolean NO_USE_SCREEN_KOEF If screen aspect ratio affects on drag values
-- @tfield number|nil DRAG_DEADZONE Distance in pixels to start dragging. Default: 10
-- @tfield boolean|nil NO_USE_SCREEN_KOEF If screen aspect ratio affects on drag values. Default: false
function Drag.on_style_change(self, style)
self.style = {}
self.style.DRAG_DEADZONE = style.DRAG_DEADZONE or 10
@@ -324,7 +324,7 @@ end
--- Strict drag click area. Useful for
-- restrict events outside stencil node
-- @tparam Drag self @{Drag}
-- @tparam node node Gui node
-- @tparam node|string|nil node Gui node
function Drag.set_click_zone(self, node)
self.click_zone = self:get_node(node)
end

View File

@@ -5,6 +5,9 @@
-- @within BaseComponent
-- @alias druid.hover
--- Hover node
-- @tfield node node
--- On hover callback(self, state, hover_instance)
-- @tfield DruidEvent on_hover @{DruidEvent}
@@ -25,7 +28,8 @@ local Hover = component.create("hover")
-- @tparam Hover self @{Hover}
-- @tparam node node Gui node
-- @tparam function on_hover_callback Hover callback
function Hover.init(self, node, on_hover_callback)
-- @tparam function on_mouse_hover On mouse hover callback
function Hover.init(self, node, on_hover_callback, on_mouse_hover)
self.node = self:get_node(node)
self._is_hovered = false
@@ -34,7 +38,7 @@ function Hover.init(self, node, on_hover_callback)
self._is_mobile = helper.is_mobile()
self.on_hover = Event(on_hover_callback)
self.on_mouse_hover = Event()
self.on_mouse_hover = Event(on_mouse_hover)
end
@@ -48,6 +52,19 @@ function Hover.on_late_init(self)
end
--- Component style params.
-- You can override this component styles params in druid styles table
-- or create your own style
-- @table style
-- @tfield[opt] string ON_HOVER_CURSOR Mouse hover style on node hover
-- @tfield[opt] string ON_MOUSE_HOVER_CURSOR Mouse hover style on node mouse hover
function Hover.on_style_change(self, style)
self.style = {}
self.style.ON_HOVER_CURSOR = style.ON_HOVER_CURSOR or nil
self.style.ON_MOUSE_HOVER_CURSOR = style.ON_MOUSE_HOVER_CURSOR or nil
end
function Hover.on_input(self, action_id, action)
if action_id ~= const.ACTION_TOUCH and action_id ~= nil then
return false
@@ -91,9 +108,15 @@ end
-- @tparam Hover self @{Hover}
-- @tparam boolean|nil state The hover state
function Hover.set_hover(self, state)
if self._is_hovered ~= state then
if self._is_hovered == state then
return
end
self._is_hovered = state
self.on_hover:trigger(self:get_context(), state, self)
if defos and self.style.ON_HOVER_CURSOR then
self:_set_cursor(3, state and self.style.ON_HOVER_CURSOR or nil)
end
end
@@ -110,9 +133,15 @@ end
-- @tparam Hover self @{Hover}
-- @tparam boolean|nil state The mouse hover state
function Hover.set_mouse_hover(self, state)
if self._is_mouse_hovered ~= state then
if self._is_mouse_hovered == state then
return
end
self._is_mouse_hovered = state
self.on_mouse_hover:trigger(self:get_context(), state, self)
if defos and self.style.ON_MOUSE_HOVER_CURSOR then
self:_set_cursor(2, state and self.style.ON_MOUSE_HOVER_CURSOR or nil)
end
end
@@ -128,7 +157,7 @@ end
--- Strict hover click area. Useful for
-- no click events outside stencil node
-- @tparam Hover self @{Hover}
-- @tparam node zone Gui node
-- @tparam node|string|nil zone Gui node
function Hover.set_click_zone(self, zone)
self.click_zone = self:get_node(zone)
end
@@ -161,4 +190,31 @@ function Hover.is_enabled(self)
end
-- Internal cursor stack
local cursor_stack = {}
function Hover:_set_cursor(priority, cursor)
if not defos then
return
end
local uid = self:get_uid()
cursor_stack[uid] = cursor_stack[uid] or {}
cursor_stack[uid][priority] = cursor
-- set cursor with high priority via pairs
local priority = nil
local cursor_to_set = nil
for _, stack in pairs(cursor_stack) do
for pr, _ in pairs(stack) do
if pr > (priority or 0) then
priority = pr
cursor_to_set = stack[priority]
end
end
end
defos.set_cursor(cursor_to_set)
end
return Hover

View File

@@ -50,11 +50,14 @@
--- Scroll view node
-- @tfield node view_node
--- Scroll view size
-- @tfield vector3 view_size
--- Scroll content node
-- @tfield node content_node
--- Flag, if scroll now moving by inertion
-- @tfield bool _is_inert
-- @tfield boolean _is_inert
--- Current inert speed
-- @tfield vector3 inertion
@@ -123,18 +126,18 @@ end
-- You can override this component styles params in druid styles table
-- or create your own style
-- @table style
-- @tfield[opt=0] number FRICT Multiplier for free inertion
-- @tfield[opt=0] number FRICT_HOLD Multiplier for inertion, while touching
-- @tfield[opt=3] number INERT_THRESHOLD Scroll speed to stop inertion
-- @tfield[opt=30] number INERT_SPEED Multiplier for inertion speed
-- @tfield[opt=20] number POINTS_DEADZONE Speed to check points of interests in no_inertion mode
-- @tfield[opt=0.35] number BACK_SPEED Scroll back returning lerp speed
-- @tfield[opt=0.2] number ANIM_SPEED Scroll gui.animation speed for scroll_to function
-- @tfield[opt=0] number EXTRA_STRETCH_SIZE extra size in pixels outside of scroll (stretch effect)
-- @tfield[opt=false] boolean SMALL_CONTENT_SCROLL If true, content node with size less than view node size can be scrolled
-- @tfield[opt=0] boolean WHEEL_SCROLL_SPEED The scroll speed via mouse wheel scroll or touchpad. Set to 0 to disable wheel scrolling
-- @tfield[opt=false] boolean WHEEL_SCROLL_INVERTED If true, invert direction for touchpad and mouse wheel scroll
-- @tfield[opt=false] boolean WHEEL_SCROLL_BY_INERTION If true, wheel will add inertion to scroll. Direct set position otherwise.
-- @tfield number|nil FRICT Multiplier for free inertion. Default: 0
-- @tfield number|nil FRICT_HOLD Multiplier for inertion, while touching. Default: 0
-- @tfield number|nil INERT_THRESHOLD Scroll speed to stop inertion. Default: 3
-- @tfield number|nil INERT_SPEED Multiplier for inertion speed. Default: 30
-- @tfield number|nil POINTS_DEADZONE Speed to check points of interests in no_inertion mode. Default: 20
-- @tfield number|nil BACK_SPEED Scroll back returning lerp speed. Default: 35
-- @tfield number|nil ANIM_SPEED Scroll gui.animation speed for scroll_to function. Default: 2
-- @tfield number|nil EXTRA_STRETCH_SIZE extra size in pixels outside of scroll (stretch effect). Default: 0
-- @tfield boolean|nil SMALL_CONTENT_SCROLL If true, content node with size less than view node size can be scrolled. Default: false
-- @tfield boolean|nil WHEEL_SCROLL_SPEED The scroll speed via mouse wheel scroll or touchpad. Set to 0 to disable wheel scrolling. Default: 0
-- @tfield boolean|nil WHEEL_SCROLL_INVERTED If true, invert direction for touchpad and mouse wheel scroll. Default: false
-- @tfield boolean|nil WHEEL_SCROLL_BY_INERTION If true, wheel will add inertion to scroll. Direct set position otherwise.. Default: false
function Scroll.on_style_change(self, style)
self.style = {}
self.style.EXTRA_STRETCH_SIZE = style.EXTRA_STRETCH_SIZE or 0
@@ -216,6 +219,12 @@ end
function Scroll.update(self, dt)
if self.is_animate then
self.position.x = gui.get(self.content_node, "position.x")
self.position.y = gui.get(self.content_node, "position.y")
self.on_scroll:trigger(self:get_context(), self.position)
end
if self.drag.is_drag then
self:_update_hand_scroll(dt)
else
@@ -255,12 +264,12 @@ function Scroll.scroll_to(self, point, is_instant)
if is_instant then
self.target_position = target
self:_set_scroll_position(target)
self:_set_scroll_position(target.x, target.y)
else
gui.animate(self.content_node, gui.PROP_POSITION, target, gui.EASING_OUTSINE, self.style.ANIM_SPEED, 0, function()
self.is_animate = false
self.target_position = target
self:_set_scroll_position(target)
self:_set_scroll_position(target.x, target.y)
end)
end
@@ -305,6 +314,13 @@ function Scroll.scroll_to_percent(self, percent, is_instant)
0
)
if not self.drag.can_x then
pos.x = self.position.x
end
if not self.drag.can_y then
pos.y = self.position.y
end
self:scroll_to(pos, is_instant)
end
@@ -325,7 +341,7 @@ end
-- It will change content gui node size
-- @tparam Scroll self @{Scroll}
-- @tparam vector3 size The new size for content node
-- @tparam vector3 offset Offset value to set, where content is starts
-- @tparam vector3|nil offset Offset value to set, where content is starts
-- @treturn druid.scroll Current scroll instance
function Scroll.set_size(self, size, offset)
if offset then
@@ -338,6 +354,31 @@ function Scroll.set_size(self, size, offset)
end
--- Set new scroll view size in case the node size was changed.
-- @tparam Scroll self @{Scroll}
-- @tparam vector3 size The new size for view node
-- @treturn druid.scroll Current scroll instance
function Scroll.set_view_size(self, size)
gui.set_size(self.view_node, size)
self.view_size = size
self.view_border = helper.get_border(self.view_node)
self:_update_size()
return self
end
--- Refresh scroll view size
-- @tparam Scroll self @{Scroll}
function Scroll.update_view_size(self)
self.view_size = helper.get_scaled_size(self.view_node)
self.view_border = helper.get_border(self.view_node)
self:_update_size()
return self
end
--- Enable or disable scroll inert.
-- If disabled, scroll through points (if exist)
-- If no points, just simple drag without inertion
@@ -464,7 +505,7 @@ end
--- Bind the grid component (Static or Dynamic) to recalculate
-- scroll size on grid changes
-- @tparam Scroll self @{Scroll}
-- @tparam StaticGrid|DynamicGrid grid Druid grid component
-- @tparam StaticGrid grid Druid grid component
-- @treturn druid.scroll Current scroll instance
function Scroll.bind_grid(self, grid)
if self._grid_on_change then
@@ -493,7 +534,7 @@ end
--- Strict drag scroll area. Useful for
-- restrict events outside stencil node
-- @tparam Drag self
-- @tparam node node Gui node
-- @tparam node|string node Gui node
function Scroll.set_click_zone(self, node)
self.drag:set_click_zone(node)
end
@@ -583,14 +624,14 @@ function Scroll._cancel_animate(self)
end
function Scroll._set_scroll_position(self, position)
function Scroll._set_scroll_position(self, position_x, position_y)
local available_extra = self.available_pos_extra
position.x = helper.clamp(position.x, available_extra.x, available_extra.z)
position.y = helper.clamp(position.y, available_extra.w, available_extra.y)
position_x = helper.clamp(position_x, available_extra.x, available_extra.z)
position_y = helper.clamp(position_y, available_extra.w, available_extra.y)
if self.position.x ~= position.x or self.position.y ~= position.y then
self.position.x = position.x
self.position.y = position.y
if self.position.x ~= position_x or self.position.y ~= position_y then
self.position.x = position_x
self.position.y = position_y
gui.set_position(self.content_node, self.position)
self.on_scroll:trigger(self:get_context(), self.position)
@@ -677,6 +718,10 @@ end
function Scroll._update_free_scroll(self, dt)
if self.is_animate then
return
end
local target = self.target_position
if self._is_inert and (self.inertion.x ~= 0 or self.inertion.y ~= 0) then
@@ -692,19 +737,23 @@ function Scroll._update_free_scroll(self, dt)
self:_check_soft_zone()
if self.position.x ~= target.x or self.position.y ~= target.y then
self:_set_scroll_position(target)
self:_set_scroll_position(target.x, target.y)
end
end
function Scroll._update_hand_scroll(self, dt)
if self.is_animate then
self:_cancel_animate()
end
local dx = self.target_position.x - self.position.x
local dy = self.target_position.y - self.position.y
self.inertion.x = (self.inertion.x + dx) * self.style.FRICT_HOLD
self.inertion.y = (self.inertion.y + dy) * self.style.FRICT_HOLD
self:_set_scroll_position(self.target_position)
self:_set_scroll_position(self.target_position.x, self.target_position.y)
end
@@ -746,14 +795,14 @@ function Scroll._update_size(self)
content_border_extra.w = content_border_extra.w - stretch_size * sign_y
if not self.style.SMALL_CONTENT_SCROLL then
self.drag.can_x = content_size.x > self.view_size.x
self.drag.can_y = content_size.y > self.view_size.y
self.drag.can_x = content_size.x > self.view_size.x and self._is_horizontal_scroll
self.drag.can_y = content_size.y > self.view_size.y and self._is_vertical_scroll
end
self.available_pos_extra = get_border_vector(self.view_border - content_border_extra, self._offset)
self.available_size_extra = get_size_vector(self.available_pos_extra)
self:_set_scroll_position(self.position)
self:_set_scroll_position(self.position.x, self.position.y)
self.target_position.x = self.position.x
self.target_position.y = self.position.y
end
@@ -788,7 +837,7 @@ function Scroll._process_scroll_wheel(self, action_id, action)
self.inertion.x = 0
end
self:_set_scroll_position(self.target_position)
self:_set_scroll_position(self.target_position.x, self.target_position.y)
end
return true

View File

@@ -102,8 +102,8 @@ end
-- You can override this component styles params in druid styles table
-- or create your own style
-- @table style
-- @tfield[opt=false] boolean IS_DYNAMIC_NODE_POSES If true, always center grid content as grid pivot sets
-- @tfield[opt=false] boolean IS_ALIGN_LAST_ROW If true, always align last row of the grid as grid pivot sets
-- @tfield boolean|nil IS_DYNAMIC_NODE_POSES If true, always center grid content as grid pivot sets. Default: false
-- @tfield boolean|nil IS_ALIGN_LAST_ROW If true, always align last row of the grid as grid pivot sets. Default: false
function StaticGrid.on_style_change(self, style)
self.style = {}
self.style.IS_DYNAMIC_NODE_POSES = style.IS_DYNAMIC_NODE_POSES or false
@@ -115,7 +115,7 @@ end
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam string|node parent The GUI Node container, where grid's items will be placed
-- @tparam node element Element prefab. Need to get it size
-- @tparam[opt=1] number in_row How many nodes in row can be placed
-- @tparam number|nil in_row How many nodes in row can be placed. By default 1
function StaticGrid.init(self, parent, element, in_row)
self.parent = self:get_node(parent)
self.nodes = {}
@@ -171,8 +171,12 @@ end
-- @tparam vector3 pos The node position in the grid
-- @treturn number The node index
function StaticGrid.get_index(self, pos)
local col = pos.x / self.node_size.x + 1
local row = -pos.y / self.node_size.y
-- Offset to left-top corner from node pivot
local node_offset_x = self.node_size.x * (-0.5 + self.node_pivot.x)
local node_offset_y = self.node_size.y * (0.5 - self.node_pivot.y)
local col = (pos.x + node_offset_x) / self.node_size.x + 1
local row = -(pos.y + node_offset_y) / self.node_size.y
col = helper.round(col)
row = helper.round(row)
@@ -236,6 +240,23 @@ function StaticGrid.add(self, item, index, shift_policy, is_instant)
end
--- Set new items to the grid. All previous items will be removed
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam node[] nodes The new grid nodes
-- @tparam[opt=false] boolean is_instant If true, update node positions instantly
function StaticGrid.set_items(self, nodes, is_instant)
self.nodes = nodes
for index = 1, #nodes do
local item = nodes[index]
gui.set_parent(item, self.parent)
end
self:_update(is_instant)
self.on_change_items:trigger(self:get_context())
end
--- Remove the item from the grid. Note that gui node will be not deleted
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam number index The grid node index to remove
@@ -337,6 +358,7 @@ function StaticGrid.clear(self)
self:_update()
self.on_clear:trigger(self:get_context())
self.on_change_items:trigger(self:get_context())
return self
end
@@ -377,6 +399,35 @@ function StaticGrid.set_in_row(self, in_row)
end
--- Set new node size for grid
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam[opt] number width The new node width
-- @tparam[opt] number height The new node height
-- @treturn druid.static_grid Current grid instance
function StaticGrid.set_item_size(self, width, height)
if width then
self.node_size.x = width
end
if height then
self.node_size.y = height
end
self:_update()
self.on_change_items:trigger(self:get_context())
return self
end
--- Sort grid nodes by custom comparator function
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam function comparator The comparator function. (a, b) -> boolean
-- @treturn druid.static_grid Current grid instance
function StaticGrid.sort_nodes(self, comparator)
table.sort(self.nodes, comparator)
self:_update(true)
end
--- Update grid inner state
-- @tparam StaticGrid self @{StaticGrid}
-- @tparam boolean|nil is_instant If true, node position update instantly, otherwise with set_position_function callback

View File

@@ -81,12 +81,18 @@ local const = require("druid.const")
local helper = require("druid.helper")
local utf8_lua = require("druid.system.utf8")
local component = require("druid.component")
local utf8 = utf8 or utf8_lua
local utf8 = utf8 or utf8_lua --[[@as utf8]]
local Text = component.create("text")
local function update_text_size(self)
if self.scale.x == 0 or self.scale.y == 0 then
return
end
if self.start_scale.x == 0 or self.start_scale.y == 0 then
return
end
local size = vmath.vector3(
self.start_size.x * (self.start_scale.x / self.scale.x),
self.start_size.y * (self.start_scale.y / self.scale.y),
@@ -98,19 +104,24 @@ end
--- Reset initial scale for text
local function reset_default_scale(self)
self.scale = self.start_scale
self.scale.x = self.start_scale.x
self.scale.y = self.start_scale.y
self.scale.z = self.start_scale.z
gui.set_scale(self.node, self.start_scale)
gui.set_size(self.node, self.start_size)
end
local function is_fit_info_area(self, metrics)
return metrics.width * self.scale.x <= self.text_area.x and
metrics.height * self.scale.y <= self.text_area.y
end
--- Setup scale x, but can only be smaller, than start text scale
local function update_text_area_size(self)
reset_default_scale(self)
local max_width = self.text_area.x
local max_height = self.text_area.y
local metrics = helper.get_text_metrics_from_node(self.node)
if metrics.width == 0 then
@@ -119,15 +130,56 @@ local function update_text_area_size(self)
return
end
local scale_modifier = max_width / metrics.width
local text_area_width = self.text_area.x
local text_area_height = self.text_area.y
-- Adjust by width
local scale_modifier = text_area_width / metrics.width
-- Adjust by height
if self:is_multiline() then
-- Approximate scale by height to start adjust scale
scale_modifier = math.sqrt(text_area_height / metrics.height)
if metrics.width * scale_modifier > text_area_width then
scale_modifier = text_area_width / metrics.width
end
-- #RMME
if self._minimal_scale then
scale_modifier = math.max(scale_modifier, self._minimal_scale)
end
-- Limit max scale by initial scale
scale_modifier = math.min(scale_modifier, self.start_scale.x)
-- #RMME
local is_fit = is_fit_info_area(self, metrics)
local step = is_fit and self.style.ADJUST_SCALE_DELTA or -self.style.ADJUST_SCALE_DELTA
for i = 1, self.style.ADJUST_STEPS do
-- Grow down to check if we fit
if step < 0 and is_fit then
break
end
-- Grow up to check if we still fit
if step > 0 and not is_fit then
break
end
scale_modifier = scale_modifier + step
if self._minimal_scale then
scale_modifier = math.max(scale_modifier, self._minimal_scale)
end
-- Limit max scale by initial scale
scale_modifier = math.min(scale_modifier, self.start_scale.x)
if self:is_multiline() then
local scale_modifier_by_height = math.sqrt(max_height / metrics.height)
scale_modifier = math.min(self.start_scale.y, scale_modifier_by_height)
if metrics.width * scale_modifier > max_width then
scale_modifier = math.min(max_width / metrics.width, self.start_scale.x)
self.scale.x = scale_modifier
self.scale.y = scale_modifier
self.scale.z = self.start_scale.z
gui.set_scale(self.node, self.scale)
update_text_size(self)
metrics = helper.get_text_metrics_from_node(self.node)
is_fit = is_fit_info_area(self, metrics)
end
end
@@ -135,12 +187,16 @@ local function update_text_area_size(self)
scale_modifier = math.max(scale_modifier, self._minimal_scale)
end
local new_scale = vmath.vector3(scale_modifier, scale_modifier, self.start_scale.z)
gui.set_scale(self.node, new_scale)
self.scale = new_scale
-- Limit max scale by initial scale
scale_modifier = math.min(scale_modifier, self.start_scale.x)
self.scale.x = scale_modifier
self.scale.y = scale_modifier
self.scale.z = self.start_scale.z
gui.set_scale(self.node, self.scale)
update_text_size(self)
self.on_update_text_scale:trigger(self:get_context(), new_scale, metrics)
self.on_update_text_scale:trigger(self:get_context(), self.scale, metrics)
end
@@ -155,9 +211,14 @@ local function update_text_with_trim(self, trim_postfix)
text_length = text_length - 1
new_text = utf8.sub(self.last_value, 1, text_length)
text_width = self:get_text_size(new_text .. trim_postfix)
if text_length == 0 then
break
end
end
gui.set_text(self.node, new_text .. trim_postfix)
else
gui.set_text(self.node, self.last_value)
end
end
@@ -171,18 +232,6 @@ local function update_text_with_anchor_shift(self)
end
-- calculate space width with font
local function get_space_width(self, font)
if not self._space_width[font] then
local no_space = resource.get_text_metrics(font, "1").width
local with_space = resource.get_text_metrics(font, " 1").width
self._space_width[font] = with_space - no_space
end
return self._space_width[font]
end
local function update_adjust(self)
if not self.adjust_type or self.adjust_type == const.TEXT_ADJUST.NO_ADJUST then
reset_default_scale(self)
@@ -216,20 +265,24 @@ end
-- You can override this component styles params in druid styles table
-- or create your own style
-- @table style
-- @tfield[opt=...] string TRIM_POSTFIX The postfix for TRIM adjust type
-- @tfield[opt=DOWNSCALE] string DEFAULT_ADJUST The default adjust type for any text component
-- @tfield string|nil TRIM_POSTFIX The postfix for TRIM adjust type. Default: ...
-- @tfield string|nil DEFAULT_ADJUST The default adjust type for any text component. Default: DOWNSCALE
-- @tfield string|nil ADJUST_STEPS Amount of iterations for text adjust by height. Default: 20
-- @tfield string|nil ADJUST_SCALE_DELTA Scale step on each height adjust step. Default: 0.02
function Text.on_style_change(self, style)
self.style = {}
self.style.TRIM_POSTFIX = style.TRIM_POSTFIX or "..."
self.style.DEFAULT_ADJUST = style.DEFAULT_ADJUST or const.TEXT_ADJUST.DOWNSCALE
self.style.ADJUST_STEPS = style.ADJUST_STEPS or 20
self.style.ADJUST_SCALE_DELTA = style.ADJUST_SCALE_DELTA or 0.02
end
--- The @{Text} constructor
-- @tparam Text self @{Text}
-- @tparam string|node node Node name or GUI Text Node itself
-- @tparam string|nil value Initial text. Default value is node text from GUI scene.
-- @tparam[opt=downscale] string adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
-- @tparam string|nil value Initial text. Default value is node text from GUI scene. Default: nil
-- @tparam string|nil adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference. Default: DOWNSCALE
function Text.init(self, node, value, adjust_type)
self.node = self:get_node(node)
self.pos = gui.get_position(self.node)
@@ -251,8 +304,6 @@ function Text.init(self, node, value, adjust_type)
self.on_set_pivot = Event()
self.on_update_text_scale = Event()
self._space_width = {}
self:set_to(value or gui.get_text(self.node))
return self
end
@@ -276,32 +327,60 @@ end
--- Calculate text width with font with respect to trailing space
-- @tparam Text self @{Text}
-- @tparam string|nil text
-- @tparam string text|nil
-- @treturn number Width
-- @treturn number Height
function Text.get_text_size(self, text)
text = text or self.last_value
local font_name = gui.get_font(self.node)
local font = gui.get_font_resource(font_name)
local scale = gui.get_scale(self.node)
local scale = self.last_scale or gui.get_scale(self.node)
local linebreak = gui.get_line_break(self.node)
local metrics = resource.get_text_metrics(font, text, {
local dot_width = resource.get_text_metrics(font, ".").width
local metrics = resource.get_text_metrics(font, text .. ".", {
line_break = linebreak,
leading = 1,
tracking = 0,
width = self.start_size.x
})
local width = metrics.width
for i = #text, 1, -1 do
local c = string.sub(text, i, i)
if c ~= ' ' then
local width = metrics.width - dot_width
return width * scale.x, metrics.height * scale.y
end
--- Get chars count by width
-- @tparam Text self @{Text}
-- @tparam number width
-- @treturn number Chars count
function Text.get_text_index_by_width(self, width)
local text = self.last_value
local font_name = gui.get_font(self.node)
local font = gui.get_font_resource(font_name)
local scale = self.last_scale or gui.get_scale(self.node)
local text_index = 0
local text_width = 0
local text_length = utf8.len(text)
local dot_width = resource.get_text_metrics(font, ".").width
local previous_width = 0
for i = 1, text_length do
local subtext = utf8.sub(text, 1, i) .. "."
local subtext_width = resource.get_text_metrics(font, subtext).width
subtext_width = subtext_width - dot_width
text_width = subtext_width * scale.x
local width_delta = text_width - previous_width
previous_width = text_width
if (text_width - width_delta/2) < width then
text_index = i
else
break
end
width = width + get_space_width(self, font)
end
return width * scale.x, metrics.height * scale.y
return text_index
end

View File

@@ -19,13 +19,12 @@
-- @alias druid.base_component
local const = require("druid.const")
local class = require("druid.system.middleclass")
local helper = require("druid.helper")
local BaseComponent = class("druid.component")
local BaseComponent = {}
local INTERESTS = {} -- Cache interests per component class in runtime
local IS_AUTO_TEMPLATE = not (sys.get_config("druid.no_auto_template") == "1")
local IS_AUTO_TEMPLATE = not (sys.get_config_int("druid.no_auto_template", 0) == 1)
-- Component Interests
BaseComponent.ON_INPUT = const.ON_INPUT
@@ -205,10 +204,22 @@ end
--- Get Druid instance for inner component creation.
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam string|nil template The template name
-- @tparam table|nil nodes The nodes table
-- @treturn DruidInstance Druid instance with component context
function BaseComponent.get_druid(self)
function BaseComponent.get_druid(self, template, nodes)
local context = { _context = self }
return setmetatable(context, { __index = self._meta.druid })
local druid_instance = setmetatable(context, { __index = self._meta.druid })
if template then
self:set_template(template)
end
if nodes then
self:set_nodes(nodes)
end
return druid_instance
end
@@ -336,31 +347,13 @@ function BaseComponent.setup_component(self, druid_instance, context, style, ins
self:set_template("")
if self._meta.parent then
self._meta.parent:__add_children(self)
self._meta.parent:__add_child(self)
end
return self
end
--- Basic constructor of component. It will call automaticaly
-- by `BaseComponent.create`
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam string name BaseComponent name
-- @tparam number|nil input_priority The input priority. The bigger number processed first
-- @local
function BaseComponent.initialize(self, name, input_priority)
self._component = {
name = name,
input_priority = input_priority or const.PRIORITY_INPUT,
default_input_priority = input_priority or const.PRIORITY_INPUT,
is_debug = false,
_is_input_priority_changed = true, -- Default true for sort once time after GUI init
_uid = BaseComponent.create_uid()
}
end
--- Print log information if debug mode is enabled
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam string message
@@ -443,21 +436,22 @@ end
--- Add child to component children list
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam component children The druid component instance
-- @tparam component child The druid component instance
-- @local
function BaseComponent.__add_children(self, children)
table.insert(self._meta.children, children)
function BaseComponent.__add_child(self, child)
table.insert(self._meta.children, child)
end
--- Remove child from component children list
-- @tparam BaseComponent self @{BaseComponent}
-- @tparam component children The druid component instance
-- @tparam component child The druid component instance
-- @local
function BaseComponent.__remove_children(self, children)
function BaseComponent.__remove_child(self, child)
for i = #self._meta.children, 1, -1 do
if self._meta.children[i] == children then
if self._meta.children[i] == child then
table.remove(self._meta.children, i)
return true
end
end
end
@@ -486,12 +480,24 @@ end
-- @tparam number|nil input_priority The input priority. The bigger number processed first
-- @local
function BaseComponent.create(name, input_priority)
-- Yea, inheritance here
local new_class = class(name, BaseComponent)
new_class.initialize = function(self)
BaseComponent.initialize(self, name, input_priority)
local new_class = setmetatable({}, {
__index = BaseComponent,
__call = function(cls, ...)
local self = setmetatable({
_component = {
name = name,
input_priority = input_priority or const.PRIORITY_INPUT,
default_input_priority = input_priority or const.PRIORITY_INPUT,
is_debug = false,
_is_input_priority_changed = true, -- Default true for sort once time after GUI init
_uid = BaseComponent.create_uid()
}
}, {
__index = cls
})
return self
end
})
return new_class
end

View File

@@ -17,8 +17,13 @@ M.ACTION_MULTITOUCH = hash(sys.get_config_string("druid.input_multitouch", "touc
M.ACTION_BACKSPACE = hash(sys.get_config_string("druid.input_key_backspace", "key_backspace"))
M.ACTION_SCROLL_UP = hash(sys.get_config_string("druid.input_scroll_up", "mouse_wheel_up"))
M.ACTION_SCROLL_DOWN = hash(sys.get_config_string("druid.input_scroll_down", "mouse_wheel_down"))
M.ACTION_LEFT = hash(sys.get_config_string("druid.input_key_left", "key_left"))
M.ACTION_RIGHT = hash(sys.get_config_string("druid.input_key_right", "key_right"))
M.ACTION_LSHIFT = hash(sys.get_config_string("druid.input_key_lshift", "key_lshift"))
M.ACTION_LCTRL = hash(sys.get_config_string("druid.input_key_lctrl", "key_lctrl"))
M.ACTION_LCMD = hash(sys.get_config_string("druid.input_key_lsuper", "key_lsuper"))
M.IS_STENCIL_CHECK = not (sys.get_config_string("druid.no_stencil_check") == "1")
M.IS_STENCIL_CHECK = not (sys.get_config_int("druid.no_stencil_check", 0) == 1)
M.ON_INPUT = "on_input"

View File

@@ -1,182 +0,0 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 2.0
y: 2.0
z: 1.0
w: 1.0
}
size {
x: 36.0
y: 36.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/slider_move"
id: "pin"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 13.5
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.2
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 17.0
y: 17.0
z: 0.0
w: 1.0
}
color {
x: 0.101960786
y: 0.101960786
z: 0.101960786
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/tick"
id: "notch"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -1,123 +0,0 @@
-- Copyright (c) 2022 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid pin knob custom component.
-- It's simple rotating input element
-- @module PinKnob
-- @within BaseComponent
-- @alias druid.pin_knob
--- The component druid instance
-- @tfield DruidInstance druid @{DruidInstance}
--- Is currently under user control
-- @tfield boolean is_drag
--- The pin node
-- @tfield node node
---
local const = require("druid.const")
local component = require("druid.component")
local PinKnob = component.create("druid.pin_knob", { const.ON_INPUT })
local SCHEME = {
ROOT = "root",
PIN = "pin",
}
local function update_visual(self)
local rotation = vmath.vector3(0, 0, self.angle)
gui.set_rotation(self.node, rotation)
end
local function set_angle(self, value)
local prev_value = self.angle
self.angle = value
self.angle = math.min(self.angle, self.angle_max)
self.angle = math.max(self.angle, self.angle_min)
update_visual(self)
if prev_value ~= self.angle and self.callback then
local output_value = self.angle
if output_value ~= 0 then
output_value = -output_value
end
self.callback(self:get_context(), output_value)
end
end
--- The @{PinKnob} constructor
-- @tparam PinKnob self @{PinKnob}
-- @tparam function callback Callback(self, value) on value changed
-- @tparam string template The template string name
-- @tparam table nodes Nodes table from gui.clone_tree
function PinKnob.init(self, callback, template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.druid = self:get_druid()
self.node = self:get_node(SCHEME.PIN)
self.is_drag = false
self.callback = callback
self:set_angle(0, -100, 100)
self._friction = 0.75
end
--- Set current and min/max angles for component
-- @tparam PinKnob self @{PinKnob}
-- @tparam number cur_value The new value for pin knob
-- @tparam number min The minimum value for pin knob
-- @tparam number max The maximum value for pin knob
-- @treturn PinKnob @{PinKnob}
function PinKnob.set_angle(self, cur_value, min, max)
self.angle_min = min or self.angle_min
self.angle_max = max or self.angle_max
set_angle(self, cur_value)
return self
end
--- Set current and min/max angles for component
-- @tparam PinKnob self @{PinKnob}
-- @tparam[opt=1] number value The spin speed multiplier
-- @treturn PinKnob @{PinKnob}
function PinKnob.set_friction(self, value)
self._friction = value or 1
return self
end
function PinKnob.on_input(self, action_id, action)
if action_id ~= const.ACTION_TOUCH then
return false
end
if gui.pick_node(self.node, action.x, action.y) then
if action.pressed then
self.pos = gui.get_position(self.node)
self.is_drag = true
end
end
if self.is_drag and not action.pressed then
set_angle(self, self.angle - action.dx * self._friction - action.dy * self._friction)
end
if action.released then
self.is_drag = false
end
return self.is_drag
end
return PinKnob

View File

@@ -3,7 +3,6 @@
--- Druid Rich Input custom component.
-- It's wrapper on Input component with cursor and placeholder text
-- @module RichInput
-- @within Input
-- @alias druid.rich_input
--- The component druid instance
@@ -18,13 +17,36 @@
--- On input field text change to empty string callback(self, input_text)
-- @tfield node cursor
--- On input field text change to empty string callback(self, input_text)
-- @tfield node cursor_text
--- On input field text change to empty string callback(self, input_text)
-- @tfield vector3 cursor_position
--- On input field text change to empty string callback(self, input_text)
-- @tfield druid.text input_text
--- On input field text change to empty string callback(self, input_text)
-- @tfield druid.drag drag
--- On input field text change to empty string callback(self, input_text)
-- @tfield druid.text placeholder
--- On input field text change to empty string callback(self, input_text)
-- @tfield vector3 text_position
--- On input field text change to max length string callback(self, input_text)
-- @tfield druid.text placeholder @{Text}
---
local component = require("druid.component")
local helper = require("druid.helper")
local const = require("druid.const")
local utf8_lua = require("druid.system.utf8")
local utf8 = utf8 or utf8_lua
local input = require("druid.extended.input")
local RichInput = component.create("druid.rich_input")
local SCHEME = {
@@ -33,34 +55,140 @@ local SCHEME = {
PLACEHOLDER = "placeholder_text",
INPUT = "input_text",
CURSOR = "cursor_node",
CURSOR_TEXT = "cursor_text",
}
local DOUBLE_CLICK_TIME = 0.35
local function animate_cursor(self)
gui.cancel_animation(self.cursor, gui.PROP_COLOR)
gui.set_color(self.cursor, vmath.vector4(1))
gui.animate(self.cursor, gui.PROP_COLOR, vmath.vector4(1,1,1,0), gui.EASING_INSINE, 0.8, 0, nil, gui.PLAYBACK_LOOP_PINGPONG)
gui.cancel_animation(self.cursor_text, "color.w")
gui.set_alpha(self.cursor_text, 1)
gui.animate(self.cursor_text, "color.w", 0, gui.EASING_INSINE, 0.8, 0, nil, gui.PLAYBACK_LOOP_PINGPONG)
end
local function update_text(self, text)
local text_width = self.input.total_width
animate_cursor(self)
gui.set_position(self.cursor, vmath.vector3(text_width/2, 0, 0))
local function set_selection_width(self, selection_width)
gui.set_visible(self.cursor, selection_width > 0)
local width = selection_width / self.input.text.scale.x
local height = gui.get_size(self.cursor).y
gui.set_size(self.cursor, vmath.vector3(width, height, 0))
local is_selection_to_right = self.input.cursor_index == self.input.end_index
gui.set_pivot(self.cursor, is_selection_to_right and gui.PIVOT_E or gui.PIVOT_W)
end
local function update_text(self)
local left_text_part = utf8.sub(self.input:get_text(), 0, self.input.cursor_index)
local selected_text_part = utf8.sub(self.input:get_text(), self.input.start_index + 1, self.input.end_index)
local left_part_width = self.input.text:get_text_size(left_text_part)
local selected_part_width = self.input.text:get_text_size(selected_text_part)
local pivot_text = gui.get_pivot(self.input.text.node)
local pivot_offset = helper.get_pivot_offset(pivot_text)
self.cursor_position.x = self.text_position.x - self.input.total_width * (0.5 + pivot_offset.x) + left_part_width
gui.set_position(self.cursor, self.cursor_position)
gui.set_scale(self.cursor, self.input.text.scale)
set_selection_width(self, selected_part_width)
end
local function on_select(self)
gui.set_enabled(self.cursor, true)
gui.set_enabled(self.placeholder.node, false)
gui.set_enabled(self.input.button.node, true)
animate_cursor(self)
self.drag:set_enabled(true)
end
local function on_unselect(self)
gui.cancel_animation(self.cursor, gui.PROP_COLOR)
gui.set_enabled(self.cursor, false)
gui.set_enabled(self.input.button.node, self.is_button_input_enabled)
gui.set_enabled(self.placeholder.node, true and #self.input:get_text() == 0)
self.drag:set_enabled(false)
end
--- Update selection
local function update_selection(self)
update_text(self)
end
local TEMP_VECTOR = vmath.vector3(0)
local function get_index_by_touch(self, touch)
local text_node = self.input.text.node
TEMP_VECTOR.x = touch.screen_x
TEMP_VECTOR.y = touch.screen_y
-- Distance to the text node position
local scene_scale = helper.get_scene_scale(text_node)
local local_pos = gui.screen_to_local(text_node, TEMP_VECTOR)
local_pos.x = local_pos.x / scene_scale.x
-- Offset to the left side of the text node
local pivot_offset = helper.get_pivot_offset(gui.get_pivot(text_node))
local_pos.x = local_pos.x + self.input.total_width * (0.5 + pivot_offset.x)
local_pos.x = local_pos.x - self.text_position.x
local cursor_index = self.input.text:get_text_index_by_width(local_pos.x)
return cursor_index
end
local function on_touch_start_callback(self, touch)
local cursor_index = get_index_by_touch(self, touch)
if self._last_touch_info.cursor_index == cursor_index then
local time = socket.gettime()
if time - self._last_touch_info.time < DOUBLE_CLICK_TIME then
local len = utf8.len(self.input:get_text())
self.input:select_cursor(len, 0, len)
self._last_touch_info.cursor_index = nil
return
end
end
self._last_touch_info.cursor_index = cursor_index
self._last_touch_info.time = socket.gettime()
if self.input.is_lshift then
local start_index = self.input.start_index
local end_index = self.input.end_index
if cursor_index < start_index then
self.input:select_cursor(cursor_index, cursor_index, end_index)
elseif cursor_index > end_index then
self.input:select_cursor(cursor_index, start_index, cursor_index)
end
else
self.input:select_cursor(cursor_index)
end
end
local function on_drag_callback(self, dx, dy, x, y, touch)
if not self._last_touch_info.cursor_index then
return
end
local index = get_index_by_touch(self, touch)
if self._last_touch_info.cursor_index <= index then
self.input:select_cursor(index, self._last_touch_info.cursor_index, index)
else
self.input:select_cursor(index, index, self._last_touch_info.cursor_index)
end
end
@@ -69,38 +197,111 @@ end
-- @tparam string template The template string name
-- @tparam table nodes Nodes table from gui.clone_tree
function RichInput.init(self, template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.druid = self:get_druid()
self.druid = self:get_druid(template, nodes)
self.root = self:get_node(SCHEME.ROOT)
self.input = self.druid:new_input(self:get_node(SCHEME.BUTTON), self:get_node(SCHEME.INPUT))
self._last_touch_info = {
cursor_index = nil,
time = 0,
}
self.is_lshift = false
self.is_lctrl = false
self.input = self.druid:new(input, self:get_node(SCHEME.BUTTON), self:get_node(SCHEME.INPUT))
self.is_button_input_enabled = gui.is_enabled(self.input.button.node)
self.cursor = self:get_node(SCHEME.CURSOR)
self.cursor_position = gui.get_position(self.cursor)
self.cursor_text = self:get_node(SCHEME.CURSOR_TEXT)
self.drag = self.druid:new_drag(self:get_node(SCHEME.BUTTON), on_drag_callback)
self.drag.on_touch_start:subscribe(on_touch_start_callback)
self.drag:set_input_priority(const.PRIORITY_INPUT_MAX + 1)
self.drag:set_enabled(false)
self.input:set_text("")
self.placeholder = self.druid:new_text(self:get_node(SCHEME.PLACEHOLDER))
self.text_position = gui.get_position(self.input.text.node)
self.input.on_input_text:subscribe(update_text)
self.input.on_input_select:subscribe(on_select)
self.input.on_input_unselect:subscribe(on_unselect)
self.input.on_select_cursor_change:subscribe(update_selection)
on_unselect(self)
update_text(self, "")
update_text(self)
end
function RichInput.on_input(self, action_id, action)
if action_id == const.ACTION_LSHIFT then
if action.pressed then
self.is_lshift = true
elseif action.released then
self.is_lshift = false
end
end
if action_id == const.ACTION_LCTRL or action_id == const.ACTION_LCMD then
if action.pressed then
self.is_lctrl = true
elseif action.released then
self.is_lctrl = false
end
end
if action_id == const.ACTION_LEFT and (action.pressed or action.repeated) then
self.input:move_selection(-1, self.is_lshift, self.is_lctrl)
end
if action_id == const.ACTION_RIGHT and (action.pressed or action.repeated) then
self.input:move_selection(1, self.is_lshift, self.is_lctrl)
end
end
--- Set placeholder text
-- @tparam RichInput self @{RichInput}
-- @tparam string|nil placeholder_text The placeholder text
-- @treturn RichInput Current instance
-- @tparam string placeholder_text The placeholder text
function RichInput.set_placeholder(self, placeholder_text)
self.placeholder:set_to(placeholder_text)
return self
end
---GSet input field text
--- Select input field
-- @tparam RichInput self @{RichInput}
function RichInput.select(self)
self.input:select()
end
--- Set input field text
-- @tparam RichInput self @{RichInput}
-- @treturn druid.input Current input instance
-- @tparam string text The input text
function RichInput.set_text(self, text)
self.input:set_text(text)
gui.set_enabled(self.placeholder.node, true and #self.input:get_text() == 0)
return self
end
--- Set input field font
-- @tparam RichInput self @{RichInput}
-- @tparam hash font The font hash
-- @treturn druid.input Current input instance
function RichInput.set_font(self, font)
gui.set_font(self.input.text.node, font)
gui.set_font(self.placeholder.node, font)
return self
end
--- Set input field text
-- @tparam RichInput self @{RichInput}
-- @treturn string Current input text
function RichInput.get_text(self)
return self.input:get_text()
end

View File

@@ -11,6 +11,9 @@ local parser = require("druid.custom.rich_text.module.rt_parse")
local utf8_lua = require("druid.system.utf8")
local utf8 = utf8 or utf8_lua
local VECTOR_ZERO = vmath.vector3(0)
local COLOR_WHITE = vmath.vector4(1)
local M = {}
-- Trim spaces on string start
@@ -71,18 +74,18 @@ function M.length(text)
end
---@param word rich_text.word
---@param previous_word rich_text.word|nil
---@param settings rich_text.settings
---@return rich_text.metrics
---@param word druid.rich_text.word
---@param previous_word druid.rich_text.word|nil
---@param settings druid.rich_text.settings
---@return druid.rich_text.metrics
local function get_text_metrics(word, previous_word, settings)
local text = word.text
local font_resource = gui.get_font_resource(word.font)
---@type druid.rich_text.metrics
local metrics
local word_scale_x = word.relative_scale * settings.text_scale.x * settings.adjust_scale
local word_scale_y = word.relative_scale * settings.text_scale.y * settings.adjust_scale
local word_scale_x = word.relative_scale * settings.scale.x * settings.adjust_scale
local word_scale_y = word.relative_scale * settings.scale.y * settings.adjust_scale
if utf8.len(text) == 0 then
metrics = resource.get_text_metrics(font_resource, "|")
@@ -116,16 +119,17 @@ end
---@param settings druid.rich_text.settings
---@return druid.rich_text.metrics
local function get_image_metrics(word, settings)
local node_prefab = settings.node_prefab
gui.play_flipbook(node_prefab, word.image.anim)
local node_size = gui.get_size(node_prefab)
local node = word.node
gui.set_texture(node, word.image.texture)
gui.play_flipbook(node, word.image.anim)
local node_size = gui.get_size(node)
local aspect = node_size.x / node_size.y
node_size.x = word.image.width or node_size.x
node_size.y = word.image.height or (node_size.x / aspect)
return {
width = node_size.x * word.relative_scale * settings.node_scale.x * settings.adjust_scale,
height = node_size.y * word.relative_scale * settings.node_scale.y * settings.adjust_scale,
width = node_size.x * word.relative_scale * settings.scale.x * settings.adjust_scale,
height = node_size.y * word.relative_scale * settings.scale.y * settings.adjust_scale,
node_size = node_size,
}
end
@@ -136,6 +140,16 @@ end
---@param previous_word druid.rich_text.word|nil
---@return druid.rich_text.metrics
local function measure_node(word, settings, previous_word)
do -- Clone node if required
local node
if word.image then
node = word.node or gui.new_box_node(vmath.vector3(0), vmath.vector3(word.image.width, word.image.height, 0))
else
node = word.node or gui.clone(settings.text_prefab)
end
word.node = node
end
local metrics = word.image and get_image_metrics(word, settings) or get_text_metrics(word, previous_word, settings)
return metrics
end
@@ -145,14 +159,14 @@ end
--- @param text string The text to create rich text nodes from
--- @param settings table Optional settings table (refer to documentation for details)
--- @param style druid.rich_text.style
--- @return words
--- @return metrics
--- @return druid.rich_text.word[]
--- @return druid.rich_text.settings
--- @return druid.rich_text.lines_metrics
function M.create(text, settings, style)
assert(text, "You must provide a text")
-- default settings for a word
-- will be assigned to each word unless tags override the values
local font = gui.get_font(settings.text_prefab)
local word_params = {
node = nil, -- Autofill on node creation
relative_scale = 1,
@@ -169,12 +183,10 @@ function M.create(text, settings, style)
text_color = gui.get_color(settings.text_prefab),
shadow = settings.shadow,
outline = settings.outline,
font = font,
font = gui.get_font(settings.text_prefab),
-- Image params
---@type rich_text.word.image
---@type druid.rich_text.image
image = nil,
image_color = gui.get_color(settings.node_prefab),
default_animation = nil,
-- Tags
br = nil,
nobr = nil,
@@ -203,8 +215,8 @@ function M._fill_properties(word, metrics, settings)
if word.image then
-- Image properties
word.scale = gui.get_scale(settings.node_prefab) * word.relative_scale * settings.adjust_scale
word.pivot = gui.get_pivot(settings.node_prefab)
word.scale = vmath.vector3(word.relative_scale * settings.adjust_scale)
word.pivot = gui.PIVOT_CENTER
word.size = metrics.node_size
word.offset = vmath.vector3(0, 0, 0)
if word.image.width then
@@ -213,8 +225,8 @@ function M._fill_properties(word, metrics, settings)
end
else
-- Text properties
word.scale = gui.get_scale(settings.text_prefab) * word.relative_scale * settings.adjust_scale
word.pivot = gui.get_pivot(settings.text_prefab)
word.scale = settings.scale * word.relative_scale * settings.adjust_scale
word.pivot = gui.PIVOT_SW -- With this pivot adjustments works more correctly than with other pivots
word.size = vmath.vector3(metrics.width, metrics.height, 0)
word.offset = vmath.vector3(metrics.offset_x, metrics.offset_y, 0)
end
@@ -234,8 +246,8 @@ function M._split_on_lines(words, settings)
repeat
local word = words[i]
if word.image then
word.default_animation = settings.default_animation
if word == nil then
break
end
-- Reset texts to start measure again
@@ -305,9 +317,9 @@ function M._split_on_lines(words, settings)
end
---@param lines rich_text.word[][]
---@param settings rich_text.settings
---@return rich_text.lines_metrics
---@param lines druid.rich_text.word[][]
---@param settings druid.rich_text.settings
---@return druid.rich_text.lines_metrics
function M._position_lines(lines, settings)
local lines_metrics = M._get_lines_metrics(lines, settings)
-- current x-y is left top point of text spawn
@@ -352,9 +364,9 @@ function M._position_lines(lines, settings)
end
---@param lines rich_text.word[][]
---@param settings rich_text.settings
---@return rich_text.lines_metrics
---@param lines druid.rich_text.word[][]
---@param settings druid.rich_text.settings
---@return druid.rich_text.lines_metrics
function M._get_lines_metrics(lines, settings)
local metrics = {}
local text_width = 0
@@ -386,7 +398,7 @@ function M._get_lines_metrics(lines, settings)
}
end
---@type rich_text.lines_metrics
---@type druid.rich_text.lines_metrics
local lines_metrics = {
text_width = text_width,
text_height = text_height,
@@ -397,8 +409,8 @@ function M._get_lines_metrics(lines, settings)
end
---@param lines rich_text.word[][]
---@param settings rich_text.settings
---@param lines druid.rich_text.word[][]
---@param settings druid.rich_text.settings
function M._update_nodes(lines, settings)
for line_index = 1, #lines do
local line = lines[line_index]
@@ -406,10 +418,11 @@ function M._update_nodes(lines, settings)
local word = line[word_index]
local node
if word.image then
node = word.node or gui.clone(settings.node_prefab)
node = word.node or gui.new_box_node(VECTOR_ZERO, word.size)
gui.set_size_mode(node, gui.SIZE_MODE_MANUAL)
gui.play_flipbook(node, hash(word.image.anim or word.default_animation))
gui.set_color(node, word.color or word.image_color)
gui.set_texture(node, word.image.texture)
gui.play_flipbook(node, hash(word.image.anim))
gui.set_color(node, word.color or COLOR_WHITE)
else
node = word.node or gui.clone(settings.text_prefab)
gui.set_outline(node, word.outline)
@@ -421,6 +434,7 @@ function M._update_nodes(lines, settings)
word.node = node
gui.set_enabled(node, true)
gui.set_parent(node, settings.parent)
gui.set_pivot(node, word.pivot)
gui.set_size(node, word.size)
gui.set_scale(node, word.scale)
gui.set_position(node, word.position)
@@ -429,10 +443,10 @@ function M._update_nodes(lines, settings)
end
---@param words rich_text.word[]
---@param settings rich_text.settings
---@param words druid.rich_text.word[]
---@param settings druid.rich_text.settings
---@param scale number
---@return rich_text.lines_metrics
---@return druid.rich_text.lines_metrics
function M.set_text_scale(words, settings, scale)
settings.adjust_scale = scale
@@ -463,7 +477,7 @@ function M.adjust_to_area(words, settings, lines_metrics, style)
if lines_metrics.text_width * scale_koef > settings.width then
scale_koef = math.sqrt(settings.width / lines_metrics.text_width)
end
local adjust_scale = math.min(scale_koef, 1)
local adjust_scale = math.min(scale_koef, settings.scale.x)
local lines = M.apply_scale_without_update(words, settings, adjust_scale)
local is_fit = M.is_fit_info_area(lines, settings)
@@ -496,15 +510,15 @@ function M.adjust_to_area(words, settings, lines_metrics, style)
end
---@return boolean @If we fit into area size
---@return druid.rich_text.word[][] lines
function M.apply_scale_without_update(words, settings, scale)
settings.adjust_scale = scale
return M._split_on_lines(words, settings)
end
---@param lines rich_text.word[][]
---@param settings rich_text.settings
---@param lines druid.rich_text.word[][]
---@param settings druid.rich_text.settings
function M.is_fit_info_area(lines, settings)
local lines_metrics = M._get_lines_metrics(lines, settings)
local area_size = gui.get_size(settings.parent)

View File

@@ -117,6 +117,10 @@ function M.parse(text, default_settings, style)
assert(default_settings)
text = text:gsub("&zwsp;", "<zwsp>\226\128\139</zwsp>")
-- Replace all \n with <br/> to make it easier to split the text
text = text:gsub("\n", "<br/>")
local all_words = {}
local open_tags = {}
@@ -145,7 +149,7 @@ function M.parse(text, default_settings, style)
end
-- parse the tag, split into name and optional parameters
local endtag, name, params, empty = tag:match("<(/?)(%a+)=?(%S-)(/?)>")
local endtag, name, params, empty = tag:match("<(/?)([%a_]+)=?(%S-)(/?)>")
local is_endtag = endtag == "/"
local is_empty = empty == "/"

View File

@@ -93,11 +93,6 @@ M.register("img", function(params, settings)
width, params = split(params, ",")
height = split(params, ",")
local texture, anim = split(texture_and_anim, ":")
if not anim then
anim = texture
texture = nil
end
width = width and tonumber(width)
height = height and tonumber(height)
@@ -105,7 +100,7 @@ M.register("img", function(params, settings)
texture = texture,
anim = anim,
width = width,
height = height
height = height or width,
}
end)

View File

@@ -1,199 +0,0 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "items"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
}
nodes {
position {
x: -200.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Rich text"
font: "game"
id: "text_prefab"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 21.0
y: 20.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "items/checkmark"
id: "icon_prefab"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: true
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -6,31 +6,7 @@
-- This custom component is inspired by <a href="https://github.com/britzl/defold-richtext" target="_blank">defold-richtext</a> 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
--
-- <b># Rich Text Setup #</b>
--
-- • 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).
-- Create Rich Text on your GUI Text Node. All properties of the text node will be used as default for the text.
--
-- <b># Notes #</b>
--
@@ -58,7 +34,6 @@
-- outline: vector4,
-- font: string,
-- image: druid.rich_text.image,
-- default_animation: string,
-- br: boolean,
-- nobr: boolean,
-- }
@@ -90,6 +65,12 @@
--- The component druid instance
-- @tfield DruidInstance druid @{DruidInstance}
--- The root node of the Rich Text
-- @tfield node root
--- The text prefab node
-- @tfield node text_prefab
--
local component = require("druid.component")
@@ -97,37 +78,28 @@ local rich_text = require("druid.custom.rich_text.module.rt")
local RichText = component.create("rich_text")
local SCHEME = {
ROOT = "root",
TEXT_PREFAB = "text_prefab",
ICON_PREFAB = "icon_prefab"
}
--- The @{RichText} 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)
self.root = self:get_node(SCHEME.ROOT)
self.druid = self:get_druid()
self.text_prefab = self:get_node(SCHEME.TEXT_PREFAB)
self.icon_prefab = self:get_node(SCHEME.ICON_PREFAB)
gui.set_enabled(self.text_prefab, false)
gui.set_enabled(self.icon_prefab, false)
-- @tparam node|string text_node The text node to make Rich Text
-- @tparam string|nil value The initial text value. Default will be gui.get_text(text_node)
function RichText.init(self, text_node, value)
self.root = self:get_node(text_node)
self.text_prefab = self.root
self._last_value = value or gui.get_text(self.text_prefab)
self._settings = self:_create_settings()
gui.set_text(self.root, "")
if value then
self:set_text(value)
end
end
function RichText.on_layout_change(self)
gui.set_enabled(self.text_prefab, false)
gui.set_enabled(self.icon_prefab, false)
if self._last_value then
self:set_text(self._last_value)
end
@@ -138,9 +110,9 @@ end
-- You can override this component styles params in Druid styles table
-- or create your own style
-- @table style
-- @tfield[opt={}] table COLORS Rich Text color aliases
-- @tfield[opt=20] number ADJUST_STEPS Amount steps of attemps text adjust by height
-- @tfield[opt=0.02] number ADJUST_SCALE_DELTA Scale step on each height adjust step
-- @tfield table|nil COLORS Rich Text color aliases. Default: {}
-- @tfield number|nil ADJUST_STEPS Amount steps of attemps text adjust by height. Default: 20
-- @tfield number|nil ADJUST_SCALE_DELTA Scale step on each height adjust step. Default: 0.02
function RichText.on_style_change(self, style)
self.style = {}
self.style.COLORS = style.COLORS or {}
@@ -151,7 +123,7 @@ end
--- Set text for Rich Text
-- @tparam RichText self @{RichText}
-- @tparam string text The text to set
-- @tparam string|nil text The text to set
-- @treturn druid.rich_text.word[] words
-- @treturn druid.rich_text.lines_metrics line_metrics
-- @usage
@@ -198,6 +170,7 @@ end
-- <img=texture:image,size/>
-- <img=texture:image,width,height/>
function RichText.set_text(self, text)
text = text or ""
self:clear()
self._last_value = text
@@ -211,6 +184,14 @@ function RichText.set_text(self, text)
end
--- Get current text
-- @tparam RichText self @{RichText}
-- @treturn string text
function RichText.get_text(self)
return self._last_value
end
function RichText:on_remove()
self:clear()
end
@@ -227,9 +208,10 @@ end
--- Get all words, which has a passed tag.
-- @tparam RichText self @{RichText}
-- @tparam string tag
-- @treturn druid.rich_text.word[] words
function RichText:tagged(tag)
function RichText.tagged(self, tag)
if not self._words then
return
end
@@ -238,6 +220,15 @@ function RichText:tagged(tag)
end
---Split a word into it's characters
-- @tparam RichText self @{RichText}
-- @tparam druid.rich_text.word word
-- @treturn druid.rich_text.word[] characters
function RichText.characters(self, word)
return rich_text.characters(word)
end
--- Get all current words.
-- @treturn table druid.rich_text.word[]
function RichText:get_words()
@@ -254,29 +245,33 @@ end
function RichText:_create_settings()
local root_size = gui.get_size(self.root)
local scale = gui.get_scale(self.root)
root_size.x = root_size.x * scale.x
root_size.y = root_size.y * scale.y
gui.set_size(self.root, root_size)
gui.set_scale(self.root, vmath.vector3(1))
return {
-- General settings
-- Adjust scale using to fit the text to the root node area
adjust_scale = 1,
parent = self.root,
scale = scale,
width = root_size.x,
height = root_size.y,
combine_words = false, -- disabled now
text_prefab = self.text_prefab,
node_prefab = self.icon_prefab,
pivot = gui.get_pivot(self.root),
-- Text Settings
shadow = gui.get_shadow(self.text_prefab),
outline = gui.get_outline(self.text_prefab),
text_scale = gui.get_scale(self.text_prefab),
text_leading = gui.get_leading(self.text_prefab),
is_multiline = gui.get_line_break(self.text_prefab),
shadow = gui.get_shadow(self.root),
outline = gui.get_outline(self.root),
text_leading = gui.get_leading(self.root),
is_multiline = gui.get_line_break(self.root),
-- Image settings
image_pixel_grid_snap = false, -- disabled now
node_scale = gui.get_scale(self.icon_prefab),
image_scale = gui.get_scale(self.icon_prefab),
default_animation = gui.get_flipbook(self.icon_prefab),
}
end

View File

@@ -107,7 +107,9 @@ function M.new(context, style)
M.set_default_style(default_style)
end
local new_instance = druid_instance(context, style)
local new_instance = setmetatable({}, { __index = druid_instance })
new_instance:initialize(context, style)
table.insert(_instances, new_instance)
return new_instance
end

View File

@@ -1,32 +1,22 @@
--- For component interest functions
--- see https://github.com/Insality/druid/blob/develop/docs_md/02-creating_custom_components.md
--- see https://github.com/Insality/druid/blob/master/docs_md/02-creating_custom_components.md
--- Require this component in you gui file:
--- local {COMPONENT_NAME} = require("{COMPONENT_PATH}")
--- $ local {COMPONENT_NAME} = require("{COMPONENT_PATH}")
--- And create this component via:
--- self.{COMPONENT_TYPE} = self.druid:new({COMPONENT_NAME}, template, nodes)
--- $ self.{COMPONENT_TYPE} = self.druid:new({COMPONENT_NAME}, template, nodes)
local component = require("druid.component")
---@class {COMPONENT_TYPE}: druid.base_component{COMPONENT_ANNOTATIONS}
---@field druid druid_instance
local {COMPONENT_NAME} = component.create("{COMPONENT_TYPE}")
local SCHEME = {
{SCHEME_LIST}
}
---@class {COMPONENT_TYPE}: druid.component
---@field druid druid_instance{COMPONENT_ANNOTATIONS}
local M = component.create("{COMPONENT_TYPE}")
---@param template string
---@param nodes table<hash, node>
function {COMPONENT_NAME}:init(template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.druid = self:get_druid(){COMPONENT_DEFINE}
end
function {COMPONENT_NAME}:on_remove()
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes){COMPONENT_DEFINE}
end
{COMPONENT_FUNCTIONS}
return {COMPONENT_NAME}
return M

View File

@@ -28,54 +28,54 @@ def process_component(node_name, component_name):
if node_name == "root":
component_annotations += "\n---@field root node"
component_define += "\n\tself.root = self:get_node(SCHEME.ROOT)"
component_define += "\n\tself.root = self:get_node(\"root\")"
if node_name.startswith("button"):
component_annotations += "\n---@field {0} druid.button".format(node_name)
component_functions += "\nfunction {1}:_on_{0}()\n\tprint(\"Click on {0}\")\nend\n\n".format(node_name, component_name)
component_define += "\n\tself.{0} = self.druid:new_button(SCHEME.{1}, self._on_{0})".format(node_name, get_id(node_name))
component_functions += "\nfunction M:_on_{0}()\n\tprint(\"Click on {0}\")\nend\n\n".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_button(\"{1}\", self._on_{0})".format(node_name, node_name)
if node_name.startswith("text"):
component_annotations += "\n---@field {0} druid.text".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_text(SCHEME.{1})".format(node_name, get_id(node_name))
component_define += "\n\tself.{0} = self.druid:new_text(\"{1}\")".format(node_name, node_name)
if node_name.startswith("lang_text"):
component_annotations += "\n---@field {0} druid.text".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_lang_text(SCHEME.{1}, \"lang_id\")".format(node_name, get_id(node_name))
component_define += "\n\tself.{0} = self.druid:new_lang_text(\"{1}\", \"lang_id\")".format(node_name, node_name)
if node_name.startswith("grid") or node_name.startswith("static_grid"):
component_annotations += "\n---@field {0} druid.static_grid".format(node_name)
component_define += "\n--TODO: Replace prefab_name with grid element prefab"
component_define += "\n\tself.{0} = self.druid:new_static_grid(SCHEME.{1}, \"prefab_name\", 1)".format(node_name, get_id(node_name))
component_define += "\n\tself.{0} = self.druid:new_static_grid(\"{1}\", \"prefab_name\", 1)".format(node_name, node_name)
if node_name.startswith("dynamic_grid"):
component_annotations += "\n---@field {0} druid.dynamic_grid".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_dynamic_grid(SCHEME.{1})".format(node_name, get_id(node_name))
component_define += "\n\tself.{0} = self.druid:new_dynamic_grid(\"{1}\")".format(node_name, node_name)
if node_name.startswith("scroll_view"):
field_name = node_name.replace("_view", "")
content_name = node_name.replace("_view", "_content")
component_annotations += "\n---@field {0} druid.scroll".format(field_name)
component_define += "\n\tself.{0} = self.druid:new_scroll(SCHEME.{1}, SCHEME.{2})".format(field_name, get_id(node_name), get_id(content_name))
component_define += "\n\tself.{0} = self.druid:new_scroll(\"{1}\", \"{2}\")".format(field_name, node_name, content_name)
if node_name.startswith("blocker"):
component_annotations += "\n---@field {0} druid.blocker".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_blocker(SCHEME.{1})".format(node_name, get_id(node_name))
component_define += "\n\tself.{0} = self.druid:new_blocker(\"{1}\")".format(node_name, node_name)
if node_name.startswith("slider"):
component_annotations += "\n---@field {0} druid.slider".format(node_name)
component_define += "\n--TODO: Replace slider end position. It should be only vertical or horizontal"
component_define += "\n\tself.{0} = self.druid:new_slider(SCHEME.{1}, vmath.vector3(100, 0, 0), self._on_{0}_change)".format(node_name, get_id(node_name))
component_functions += "\nfunction {1}:_on_{0}_change(value)\n\tprint(\"Slider change:\", value)\nend\n\n".format(node_name, component_name)
component_define += "\n\tself.{0} = self.druid:new_slider(\"{1}\", vmath.vector3(100, 0, 0), self._on_{0}_change)".format(node_name, node_name)
component_functions += "\nfunction M:_on_{0}_change(value)\n\tprint(\"Slider change:\", value)\nend\n\n".format(node_name)
if node_name.startswith("progress"):
component_annotations += "\n---@field {0} druid.progress".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_progress(SCHEME.{1}, \"x\")".format(node_name, get_id(node_name))
component_define += "\n\tself.{0} = self.druid:new_progress(\"{1}\", \"x\")".format(node_name, get_id(node_name))
if node_name.startswith("timer"):
component_annotations += "\n---@field {0} druid.timer".format(node_name)
component_define += "\n\tself.{0} = self.druid:new_timer(SCHEME.{1}, 59, 0, self._on_{0}_end)".format(node_name, get_id(node_name))
component_functions += "\nfunction {1}:_on_{0}_end()\n\tprint(\"Timer {0} trigger\")\nend\n\n".format(node_name, component_name)
component_define += "\n\tself.{0} = self.druid:new_timer(\"{1}\", 59, 0, self._on_{0}_end)".format(node_name, get_id(node_name))
component_functions += "\nfunction M:_on_{0}_end()\n\tprint(\"Timer {0} trigger\")\nend\n\n".format(node_name)
def main():
@@ -126,7 +126,7 @@ def main():
filedata = filedata.replace("{COMPONENT_DEFINE}", component_define)
filedata = filedata.replace("{COMPONENT_FUNCTIONS}", component_functions)
filedata = filedata.replace("{COMPONENT_ANNOTATIONS}", component_annotations)
filedata = filedata.replace("{SCHEME_LIST}", ",\n".join(scheme_list))
#filedata = filedata.replace("{SCHEME_LIST}", ",\n".join(scheme_list))
output_file = open(output_full_path, "w")
output_file.write(filedata)

View File

@@ -26,36 +26,7 @@ end
function M.get_commands()
return {
{
label = "Print GUI Scheme",
locations = { "Outline" },
query = {
selection = {type = "outline", cardinality = "many"}
},
active = function(opts)
return true
end,
run = function(opts)
print("local SCHEME = {")
for i = 1, #opts.selection do
local file = opts.selection[i]
if editor.can_get(file, "id") then
local id = editor.get(file, "id")
print("\t" .. string.upper(id) .. " = \"" .. id .. "\",")
end
end
print("}")
print("")
end
},
{
label = "Assign layers",
label = "Assign Layers",
locations = {"Edit"},

View File

@@ -5,11 +5,20 @@
echo "Run bash for $1"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
is_defree_installed=$(pip3 list --disable-pip-version-check | grep -E "deftree")
# Check if pip3 is installed
if command -v pip3 &> /dev/null; then
PIP_CMD="pip3"
PYTHON_CMD="python3"
else
PIP_CMD="pip"
PYTHON_CMD="python"
fi
is_defree_installed=$($PIP_CMD list --disable-pip-version-check | grep -E "deftree")
if [ -z "$is_defree_installed" ]; then
echo "The python deftree is not installed. Please install it via"
echo "pip3 install deftree"
echo "$ $PIP_CMD install deftree"
exit 0
fi
python3 $1 $2
$PYTHON_CMD $1 $2

View File

@@ -8,31 +8,62 @@
-- @module DruidEvent
-- @alias druid.event
local class = require("druid.system.middleclass")
local M = {}
M.COUNTER = 0
local DruidEvent = class("druid.event")
-- Forward declaration
local EVENT_METATABLE
-- Local versions
local pcall = pcall
local tinsert = table.insert
local tremove = table.remove
--- DruidEvent constructor
-- @tparam DruidEvent self @{DruidEvent}
-- @tparam function|nil initial_callback Subscribe the callback on new event, if callback exist
-- @tparam function|nil callback Subscribe the callback on new event, if callback exist
-- @tparam any|nil callback_context Additional context as first param to callback call
-- @usage
-- local Event = require("druid.event")
-- ...
-- local event = Event(initial_callback)
function DruidEvent.initialize(self, initial_callback)
self._callbacks = nil -- initialize later
-- local event = Event(callback)
function M.create(callback, callback_context)
local instance = setmetatable({}, EVENT_METATABLE)
if initial_callback then
self:subscribe(initial_callback)
if callback then
instance:subscribe(callback, callback_context)
end
M.COUNTER = M.COUNTER + 1
return instance
end
--- Check is event subscribed.
-- @tparam DruidEvent self @{DruidEvent}
-- @tparam function callback Callback itself
-- @tparam any|nil callback_context Additional context as first param to callback call
-- @treturn boolean, number|nil @Is event subscribed, return index of callback in event as second param
function M.is_subscribed(self, callback, callback_context)
if #self == 0 then
return false, nil
end
for index = 1, #self do
local cb = self[index]
if cb[1] == callback and cb[2] == callback_context then
return true, index
end
end
return false, nil
end
--- Subscribe callback on event
-- @tparam DruidEvent self @{DruidEvent}
-- @tparam function callback Callback itself
-- @tparam any|nil context Additional context as first param to callback call, usually it's self
-- @tparam any|nil callback_context Additional context as first param to callback call, usually it's self
-- @treturn boolean True if callback was subscribed
-- @usage
-- local function on_long_callback(self)
-- print("Long click!")
@@ -40,41 +71,39 @@ end
-- ...
-- local button = self.druid:new_button("button", callback)
-- button.on_long_click:subscribe(on_long_callback, self)
function DruidEvent.subscribe(self, callback, context)
function M.subscribe(self, callback, callback_context)
assert(type(self) == "table", "You should subscribe to event with : syntax")
assert(type(callback) == "function", "Callback should be function")
assert(callback, "A function must be passed to subscribe to an event")
self._callbacks = self._callbacks or {}
table.insert(self._callbacks, {
callback = callback,
context = context
})
if self:is_subscribed(callback, callback_context) then
return false
end
return callback
tinsert(self, { callback, callback_context })
return true
end
--- Unsubscribe callback on event
-- @tparam DruidEvent self @{DruidEvent}
-- @tparam function callback Callback itself
-- @tparam any|nil context Additional context as first param to callback call
-- @tparam any|nil callback_context Additional context as first param to callback call
-- @usage
-- local function on_long_callback(self)
-- print("Long click!")
-- end
-- ...
-- button.on_long_click:unsubscribe(on_long_callback, self)
function DruidEvent.unsubscribe(self, callback, context)
if not self._callbacks then
return
function M.unsubscribe(self, callback, callback_context)
assert(callback, "A function must be passed to subscribe to an event")
local _, event_index = self:is_subscribed(callback, callback_context)
if not event_index then
return false
end
for index, callback_info in ipairs(self._callbacks) do
if callback_info.callback == callback and callback_info.context == context then
table.remove(self._callbacks, index)
return
end
end
tremove(self, event_index)
return true
end
@@ -83,11 +112,18 @@ end
-- @treturn boolean True if event have handlers
-- @usage
-- local is_long_click_handler_exists = button.on_long_click:is_exist()
function DruidEvent.is_exist(self)
if not self._callbacks then
return false
function M.is_exist(self)
return #self > 0
end
return #self._callbacks > 0
--- Return true, if event not have handler
--- @tparam DruidEvent self @{DruidEvent}
--- @treturn boolean True if event not have handlers
--- @usage
--- local is_long_click_handler_not_exists = button.on_long_click:is_empty()
function M:is_empty()
return #self == 0
end
@@ -95,8 +131,10 @@ end
-- @tparam DruidEvent self @{DruidEvent}
-- @usage
-- button.on_long_click:clear()
function DruidEvent.clear(self)
self._callbacks = nil
function M.clear(self)
for index = #self, 1, -1 do
self[index] = nil
end
end
@@ -108,19 +146,60 @@ end
-- ...
-- local event = Event()
-- event:trigger("Param1", "Param2")
function DruidEvent.trigger(self, ...)
if not self._callbacks then
return false
function M.trigger(self, ...)
if #self == 0 then
return
end
for _, callback_info in ipairs(self._callbacks) do
if callback_info.context then
callback_info.callback(callback_info.context, ...)
local result = nil
local call_callback = self.call_callback
for index = 1, #self do
result = call_callback(self, self[index], ...)
end
return result
end
-- @tparam table callback Callback data {function, context}
-- @tparam any ... All event params
-- @treturn any Result of the callback
-- @local
function M:call_callback(callback, ...)
local event_callback = callback[1]
local event_callback_context = callback[2]
-- Call callback
local ok, result_or_error
if event_callback_context then
ok, result_or_error = pcall(event_callback, event_callback_context, ...)
else
callback_info.callback(...)
end
end
ok, result_or_error = pcall(event_callback, ...)
end
-- Handle errors
if not ok then
local caller_info = debug.getinfo(2)
pprint("An error occurred during event processing", {
trigger = caller_info.short_src .. ":" .. caller_info.currentline,
error = result_or_error,
})
pprint("Traceback", debug.traceback())
return nil
end
return DruidEvent
return result_or_error
end
-- Construct event metatable
EVENT_METATABLE = {
__index = M,
__call = M.trigger,
}
return setmetatable(M, {
__call = function(_, callback)
return M.create(callback)
end,
})

View File

@@ -14,7 +14,7 @@
-- @tfield node node
--- Button trigger node
-- @tfield[opt=node] node click_node
-- @tfield node|nil click_node
--- Button component from click_node
-- @tfield Button button @{Button}
@@ -50,8 +50,8 @@ end
-- @tparam Checkbox self @{Checkbox}
-- @tparam node node Gui node
-- @tparam function callback Checkbox callback
-- @tparam[opt=node] node click_node Trigger node, by default equals to node
-- @tparam[opt=false] boolean initial_state The initial state of checkbox, default - false
-- @tparam node|nil click_node Trigger node, by default equals to node. Default: node
-- @tparam boolean|nil initial_state The initial state of checkbox, default - false
function Checkbox.init(self, node, callback, click_node, initial_state)
self.druid = self:get_druid()
self.node = self:get_node(node)

View File

@@ -25,7 +25,7 @@ local CheckboxGroup = component.create("checkbox_group")
-- @tparam CheckboxGroup self @{CheckboxGroup}
-- @tparam node[] nodes Array of gui node
-- @tparam function callback Checkbox callback
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
-- @tparam node[]|nil click_nodes Array of trigger nodes, by default equals to nodes
function CheckboxGroup.init(self, nodes, callback, click_nodes)
self.druid = self:get_druid()
self.checkboxes = {}

View File

@@ -13,17 +13,17 @@
-- @tfield Scroll scroll @{Scroll}
--- The Druid Grid component
-- @tfield StaticGrid|DynamicGrid grid @{StaticGrid}, @{DynamicGrid}
--- The current visual top data index
-- @tfield number top_index
--- The current visual last data index
-- @tfield number last_index
-- @tfield StaticGrid grid @{StaticGrid}, @{DynamicGrid}
--- The current progress of scroll posititon
-- @tfield number scroll_progress
--- The current top index of visual elements
-- @tfield number top_index
--- The current last index of visual elements
-- @tfield number last_index
--- Event triggered when scroll progress is changed; event(self, progress_value)
-- @tfield DruidEvent on_scroll_progress_change @{DruidEvent}
@@ -46,16 +46,14 @@ local DataList = component.create("data_list")
--- The @{DataList} constructor
-- @tparam DataList self @{DataList}
-- @tparam Scroll scroll The @{Scroll} instance for Data List component
-- @tparam StaticGrid|DynamicGrid grid The @{StaticGrid} or @{DynamicGrid} instance for Data List component
-- @tparam StaticGrid grid The @{StaticGrid} or @{DynamicGrid} instance for Data List component
-- @tparam function create_function The create function callback(self, data, index, data_list). Function should return (node, [component])
function DataList.init(self, scroll, grid, create_function)
self.druid = self:get_druid()
self.scroll = scroll
self.grid = grid
if self.grid.style then
self.grid.style.IS_DYNAMIC_NODE_POSES = false
end
self.scroll:bind_grid(grid)
-- Current visual elements indexes
self.top_index = 1
@@ -63,26 +61,34 @@ function DataList.init(self, scroll, grid, create_function)
self.scroll_progress = 0
self._create_function = create_function
self._is_use_cache = false
self._cache = {}
self._data = {}
self._data_first_index = false
self._data_last_index = false
self._data_length = 0
self._data_visual = {}
self.scroll.on_scroll:subscribe(self._check_elements, self)
self.scroll.on_scroll:subscribe(self._refresh, self)
self.on_scroll_progress_change = Event()
self.on_element_add = Event()
self.on_element_remove = Event()
self:set_data()
end
--- Druid System on_remove function
-- @tparam DataList self @{DataList}
function DataList.on_remove(self)
self.scroll.on_scroll:unsubscribe(self._check_elements, self)
self:clear()
self.scroll.on_scroll:unsubscribe(self._refresh, self)
end
--- Set refresh function for DataList component
-- @tparam DataList self @{DataList}
-- @tparam boolean is_use_cache Use cache version of DataList. Requires make setup of components in on_element_add callback and clean in on_element_remove
-- @treturn druid.data_list Current DataList instance
function DataList.set_use_cache(self, is_use_cache)
self._is_use_cache = is_use_cache
return self
end
@@ -92,7 +98,6 @@ end
-- @treturn druid.data_list Current DataList instance
function DataList.set_data(self, data)
self._data = data or {}
self:_update_data_info()
self:_refresh()
return self
@@ -110,42 +115,35 @@ end
--- Add element to DataList. Currenly untested
-- @tparam DataList self @{DataList}
-- @tparam table data
-- @tparam number index
-- @tparam number shift_policy The constant from const.SHIFT.*
-- @local
-- @tparam number|nil index
-- @tparam number|nil shift_policy The constant from const.SHIFT.*
function DataList.add(self, data, index, shift_policy)
index = index or self._data_last_index + 1
index = index or #self._data + 1
shift_policy = shift_policy or const.SHIFT.RIGHT
helper.insert_with_shift(self._data, data, index, shift_policy)
self:_update_data_info()
self:_check_elements()
self:_refresh()
end
--- Remove element from DataList. Currenly untested
-- @tparam DataList self @{DataList}
-- @tparam number index
-- @tparam number shift_policy The constant from const.SHIFT.*
-- @local
-- @tparam number|nil index
-- @tparam number|nil shift_policy The constant from const.SHIFT.*
function DataList.remove(self, index, shift_policy)
--self:_refresh()
helper.remove_with_shift(self._data, index, shift_policy)
self:_update_data_info()
self:_refresh()
end
--- Remove element from DataList by data value. Currenly untested
-- @tparam DataList self @{DataList}
-- @tparam tabe data
-- @tparam number shift_policy The constant from const.SHIFT.*
-- @local
-- @tparam table data
-- @tparam number|nil shift_policy The constant from const.SHIFT.*
function DataList.remove_by_data(self, data, shift_policy)
local index = helper.contains(self._data, data)
if index then
helper.remove_with_shift(self._data, index, shift_policy)
self:_update_data_info()
self:_refresh()
end
end
@@ -155,32 +153,10 @@ end
-- @tparam DataList self @{DataList}
function DataList.clear(self)
self._data = {}
self:_update_data_info()
self:_refresh()
end
--- Return first index from data. It not always equals to 1
-- @tparam DataList self @{DataList}
function DataList.get_first_index(self)
return self._data_first_index
end
--- Return last index from data
-- @tparam DataList self @{DataList}
function DataList.get_last_index(self)
return self._data_last_index
end
--- Return amount of data
-- @tparam DataList self @{DataList}
function DataList.get_length(self)
return self._data_length
end
--- Return index for data value
-- @tparam DataList self @{DataList}
-- @tparam table data
@@ -227,17 +203,12 @@ end
-- @tparam DataList self @{DataList}
-- @tparam number index
function DataList.scroll_to_index(self, index)
local target = helper.clamp(index, self:get_first_index(), self:get_last_index())
self.top_index = target
self:_refresh()
if self._data_visual[target] then
self.scroll:scroll_to(gui.get_position(self._data_visual[target].node), true)
end
local pos = self.grid:get_pos(index)
self.scroll:scroll_to(pos)
end
--- Add element at passed index
--- Add element at passed index using cache or create new
-- @tparam DataList self @{DataList}
-- @tparam number index
-- @local
@@ -246,137 +217,98 @@ function DataList._add_at(self, index)
self:_remove_at(index)
end
local node, instance = self._create_function(self:get_context(), self._data[index], index, self)
self.grid:add(node, index, const.SHIFT.NO_SHIFT)
self._data_visual[index] = {
node = node,
component = instance
}
local data = self._data[index]
local node, instance
self.on_element_add:trigger(self:get_context(), index, node, instance)
-- Use cache if available and is_use_cache is set
if #self._cache > 0 and self._is_use_cache then
local cached = table.remove(self._cache)
node = cached.node
instance = cached.component
gui.set_enabled(node, true)
else
-- Create a new element if no cache or refresh function is not set
node, instance = self._create_function(self:get_context(), data, index, self)
end
self._data_visual[index] = {
data = data,
node = node,
component = instance,
}
self.grid:add(node, index, const.SHIFT.NO_SHIFT)
self.on_element_add:trigger(self:get_context(), index, node, instance, data)
end
--- Remove element from passed index
--- Remove element from passed index and add it to cache if applicable
-- @tparam DataList self @{DataList}
-- @tparam number index
-- @local
function DataList._remove_at(self, index)
self.grid:remove(index, const.SHIFT.NO_SHIFT)
local node = self._data_visual[index].node
local visual_data = self._data_visual[index]
local node = visual_data.node
local instance = visual_data.component
local data = visual_data.data
self.on_element_remove:trigger(self:get_context(), index, node, instance, data)
if self._is_use_cache then
-- Disable the node and add it to the cache instead of deleting it
gui.set_enabled(node, false)
table.insert(self._cache, visual_data) -- Cache the removed element
else
-- If no refresh function, delete the node and component as usual
gui.delete_node(node)
local instance = self._data_visual[index].component
if instance then
self.druid:remove(instance)
instance._meta.druid:remove(instance)
end
end
self._data_visual[index] = nil
self.on_element_remove:trigger(self:get_context(), index)
self._data_visual[index] = nil
end
--- Refresh all elements in DataList
-- @tparam DataList self @{DataList}
-- @local
function DataList._refresh(self)
for index, _ in pairs(self._data_visual) do
self.scroll:set_size(self.grid:get_size_for(#self._data))
local start_pos = -self.scroll.position --[[@as vector3]]
local start_index = self.grid:get_index(start_pos)
start_index = math.max(1, start_index)
local pivot = helper.get_pivot_offset(gui.get_pivot(self.scroll.view_node))
local offset_x = self.scroll.view_size.x * (0.5 - pivot.x)
local offset_y = self.scroll.view_size.y * (0.5 + pivot.y)
local end_pos = vmath.vector3(start_pos.x + offset_x, start_pos.y - offset_y, 0)
local end_index = self.grid:get_index(end_pos)
end_index = math.min(#self._data, end_index)
self.top_index = start_index
self.last_index = end_index
-- Clear from non range elements
for index, data in pairs(self._data_visual) do
if index < start_index or index > end_index then
self:_remove_at(index)
elseif self._data[index] ~= data.data then
-- TODO We want to find currently created data instances and move them to new positions
-- Now it will re-create them
self:_remove_at(index)
end
self:_check_elements()
end
--- Check elements which should be created
-- @tparam DataList self @{DataList}
-- @local
function DataList._check_elements(self)
for index, data in pairs(self._data_visual) do
if self.scroll:is_node_in_view(data.node) then
self.top_index = index
self.last_index = index
end
end
self:_check_elements_from(self.top_index, -1)
self:_check_elements_from(self.top_index + 1, 1)
for index, data in pairs(self._data_visual) do
self.top_index = math.min(self.top_index or index, index)
self.last_index = math.max(self.last_index or index, index)
end
-- Progress report
local middle_index = (self.last_index + self.top_index) / 2
local progress = (middle_index - self._data_first_index) / (self._data_last_index - self._data_first_index)
progress = helper.clamp(progress, 0, 1)
if self.last_index == self:get_last_index() then
progress = 1
end
if self.top_index == self:get_first_index() then
progress = 0
end
if self.scroll_progress ~= progress then
self.scroll_progress = progress
self.on_scroll_progress_change:trigger(self:get_context(), progress)
end
end
--- Check elements which should be created.
-- Start from index with step until element is outside of scroll view
-- @tparam DataList self @{DataList}
-- @tparam number index
-- @tparam number step
-- @local
function DataList._check_elements_from(self, index, step)
local is_outside = false
while not is_outside do
if not self._data[index] then
break
end
if not self._data_visual[index] then
-- Add new elements
for index = start_index, end_index do
if not self._data_visual[index] and self._data[index] then
self:_add_at(index)
end
if not self.scroll:is_node_in_view(self._data_visual[index].node) then
is_outside = true
-- remove nexts:
-- We add one more element, which is not in view to
-- check what it's always outside to stop spawning
local remove_index = index + step
while self._data_visual[remove_index] do
self:_remove_at(remove_index)
remove_index = remove_index + step
end
end
index = index + step
end
end
--- Update actual data params
-- @tparam DataList self @{DataList}
-- @local
function DataList._update_data_info(self)
self._data_first_index = false
self._data_last_index = false
self._data_length = 0
for index, data in pairs(self._data) do
self._data_first_index = math.min(self._data_first_index or index, index)
self._data_last_index = math.max(self._data_last_index or index, index)
self._data_length = self._data_length + 1
end
if self._data_length == 0 then
self._data_first_index = 0
self._data_last_index = 0
end
end

View File

@@ -101,7 +101,7 @@ end
-- @tparam number index The grid element index
-- @tparam node node The node to be placed
-- @tparam number|nil origin_index Index of nearby node
-- @treturn vector3 Node position
-- @treturn vector3 node position
function DynamicGrid.get_pos(self, index, node, origin_index)
local origin_node = self.nodes[origin_index]

View File

@@ -7,14 +7,17 @@
-- @within BaseComponent
-- @alias druid.hotkey
--- On change state callback(self, state)
-- @tfield DruidEvent on_change_state @{DruidEvent}
--- On hotkey released callback(self, argument)
-- @tfield DruidEvent on_hotkey_pressed @{DruidEvent}
--- On hotkey released callback(self, argument)
-- @tfield DruidEvent on_hotkey_released @{DruidEvent}
--- Visual node
-- @tfield node node
--- Button trigger node
-- @tfield[opt=node] node click_node
-- @tfield node|nil click_node
--- Button component from click_node
-- @tfield Button button @{Button}
@@ -24,7 +27,6 @@
local helper = require("druid.helper")
local component = require("druid.component")
local Event = require("druid.event")
local const = require("druid.const")
local Hotkey = component.create("hotkey")

View File

@@ -9,10 +9,10 @@
-- @within BaseComponent
-- @alias druid.input
--- On input field select callback(self, button_node)
--- On input field select callback(self, input_instance)
-- @tfield DruidEvent on_input_select @{DruidEvent}
--- On input field unselect callback(self, input_text)
--- On input field unselect callback(self, input_text, input_instance)
-- @tfield DruidEvent on_input_unselect @{DruidEvent}
--- On input field text change callback(self, input_text)
@@ -24,12 +24,42 @@
--- On input field text change to max length string callback(self, input_text)
-- @tfield DruidEvent on_input_full @{DruidEvent}
--- On trying user input with not allowed character callback(self, params, button_instance)
--- On trying user input with not allowed character callback(self, params, input_text)
-- @tfield DruidEvent on_input_wrong @{DruidEvent}
--- On cursor position change callback(self, cursor_index, start_index, end_index)
-- @tfield DruidEvent on_select_cursor_change @{DruidEvent}
--- The cursor index. The index of letter cursor after. Leftmost cursor - 0
-- @tfield number cursor_index
--- The selection start index. The index of letter cursor after. Leftmost selection - 0
-- @tfield number start_index
--- Theselection end index. The index of letter cursor before. Rightmost selection - #text
-- @tfield number end_index
--- Text component
-- @tfield Text text @{Text}
--- Current input value
-- @tfield string value
--- Previous input value
-- @tfield string previous_value
--- Current input value with marked text
-- @tfield string current_value
--- Marked text for input field. Info: https://defold.com/manuals/input-key-and-text/#marked-text
-- @tfield string marked_value
--- Text width
-- @tfield number text_width
--- Marked text width
-- @tfield number marked_text_width
--- Button component
-- @tfield Button button @{Button}
@@ -52,12 +82,21 @@
local Event = require("druid.event")
local const = require("druid.const")
local helper = require("druid.helper")
local component = require("druid.component")
local utf8_lua = require("druid.system.utf8")
local utf8 = utf8 or utf8_lua
local Input = component.create("input")
Input.ALLOWED_ACTIONS = {
[const.ACTION_TOUCH] = true,
[const.ACTION_TEXT] = true,
[const.ACTION_MARKED_TEXT] = true,
[const.ACTION_BACKSPACE] = true,
[const.ACTION_ENTER] = true,
[const.ACTION_ESC] = true,
}
--- Mask text by replacing every character with a mask character
-- @tparam string text
@@ -87,31 +126,22 @@ end
-- You can override this component styles params in druid styles table
-- or create your own style
-- @table style
-- @tfield[opt=false] boolean IS_LONGTAP_ERASE Is long tap will erase current input data
-- @tfield[opt=*] string MASK_DEFAULT_CHAR Default character mask for password input
-- @tfield[opt=false] boolean IS_UNSELECT_ON_RESELECT If true, call unselect on select selected input
-- @tfield[opt=false] boolean NO_CONSUME_INPUT_WHILE_SELECTED If true, will not consume input while input is selected. It's allow to interact with other components while input is selected (text input still captured)
-- @tfield boolean IS_LONGTAP_ERASE Is long tap will erase current input data. Default: false
-- @tfield string MASK_DEFAULT_CHAR Default character mask for password input. Default: *]
-- @tfield boolean IS_UNSELECT_ON_RESELECT If true, call unselect on select selected input. Default: false
-- @tfield function on_select (self, button_node) Callback on input field selecting
-- @tfield function on_unselect (self, button_node) Callback on input field unselecting
-- @tfield function on_input_wrong (self, button_node) Callback on wrong user input
-- @tfield table button_style Custom button style for input node
function Input.on_style_change(self, style)
self.style = {}
self.style.IS_LONGTAP_ERASE = style.IS_LONGTAP_ERASE or false
self.style.MASK_DEFAULT_CHAR = style.MASK_DEFAULT_CHAR or "*"
self.style.IS_UNSELECT_ON_RESELECT = style.IS_UNSELECT_ON_RESELECT or false
self.style.NO_CONSUME_INPUT_WHILE_SELECTED = style.NO_CONSUME_INPUT_WHILE_SELECTED or false
self.style.on_select = style.on_select or function(_, button_node) end
self.style.on_unselect = style.on_unselect or function(_, button_node) end
self.style.on_input_wrong = style.on_input_wrong or function(_, button_node) end
self.style.button_style = style.button_style or {
LONGTAP_TIME = 0.4,
AUTOHOLD_TRIGGER = 0.8,
DOUBLETAP_TIME = 0.4
}
end
@@ -121,7 +151,7 @@ end
-- @tparam node|Text text_node Text node what will be changed on user input. You can pass text component instead of text node name @{Text}
-- @tparam number|nil keyboard_type Gui keyboard type for input field
function Input.init(self, click_node, text_node, keyboard_type)
self.druid = self:get_druid(self)
self.druid = self:get_druid()
if type(text_node) == "table" then
self.text = text_node
@@ -139,6 +169,9 @@ function Input.init(self, click_node, text_node, keyboard_type)
self.text_width = 0
self.market_text_width = 0
self.total_width = 0
self.cursor_index = utf8.len(self.value)
self.start_index = self.cursor_index
self.end_index = self.cursor_index
self.max_length = nil
self.allowed_characters = nil
@@ -146,10 +179,14 @@ function Input.init(self, click_node, text_node, keyboard_type)
self.keyboard_type = keyboard_type or gui.KEYBOARD_TYPE_DEFAULT
self.button = self.druid:new_button(click_node, self.select)
self.button:set_style(self.button_style)
self.button.on_click_outside:subscribe(self.unselect)
self.button.on_long_click:subscribe(clear_and_select)
if defos then
self.button.hover.style.ON_HOVER_CURSOR = defos.CURSOR_IBEAM
self.button.hover.style.ON_MOUSE_HOVER_CURSOR = defos.CURSOR_IBEAM
end
if html5 then
self.button:set_web_user_interaction(true)
end
@@ -160,12 +197,20 @@ function Input.init(self, click_node, text_node, keyboard_type)
self.on_input_empty = Event()
self.on_input_full = Event()
self.on_input_wrong = Event()
self.on_select_cursor_change = Event()
end
function Input.on_input(self, action_id, action)
if not (action_id == nil or Input.ALLOWED_ACTIONS[action_id]) then
return false
end
if self.is_selected then
local input_text = nil
local is_marked_text_changed = false
local cursor_shift_indexes = nil
if action_id == const.ACTION_TEXT then
-- ignore return key
if action.text == "\n" or action.text == "\r" then
@@ -179,10 +224,9 @@ function Input.on_input(self, action_id, action)
-- ignore arrow keys
if not utf8.match(hex, "EF9C8[0-3]") then
if not self.allowed_characters or utf8.match(action.text, self.allowed_characters) then
input_text = self.value .. action.text
if self.max_length then
input_text = utf8.sub(input_text, 1, self.max_length)
end
local shift_offset = self.cursor_index - self.start_index
input_text = self:get_text_selected_replaced(action.text)
cursor_shift_indexes = utf8.len(action.text) - shift_offset
else
self.on_input_wrong:trigger(self:get_context(), action.text)
self.style.on_input_wrong(self, self.button.node)
@@ -196,10 +240,28 @@ function Input.on_input(self, action_id, action)
if self.max_length then
self.marked_value = utf8.sub(self.marked_value, 1, self.max_length)
end
is_marked_text_changed = true
end
if action_id == const.ACTION_BACKSPACE and (action.pressed or action.repeated) then
input_text = utf8.sub(self.value, 1, -2)
local start_index = self.start_index or utf8.len(self.value)
local end_index = self.end_index or utf8.len(self.value)
-- If start == end index, remove left of this selection letter, else delete all selection
if start_index == end_index then
local left_part = utf8.sub(self.value, 1, math.max(0, start_index - 1))
local right_part = utf8.sub(self.value, end_index + 1, utf8.len(self.value))
input_text = left_part .. right_part
cursor_shift_indexes = -1
else
local left_part = utf8.sub(self.value, 1, start_index)
local right_part = utf8.sub(self.value, end_index + 1, utf8.len(self.value))
input_text = left_part .. right_part
-- Calculate offsets from cursor pos to start index
cursor_shift_indexes = start_index - self.cursor_index
end
end
if action_id == const.ACTION_ENTER and action.released then
@@ -217,14 +279,23 @@ function Input.on_input(self, action_id, action)
return true
end
if input_text or #self.marked_value > 0 then
if input_text or is_marked_text_changed then
self:set_text(input_text)
if cursor_shift_indexes then
self:select_cursor(self.cursor_index + cursor_shift_indexes)
end
return true
end
end
local is_consume_input = not self.style.NO_CONSUME_INPUT_WHILE_SELECTED and self.is_selected
return is_consume_input
local is_mouse_action = action_id == const.ACTION_TOUCH or not action_id
if is_mouse_action then
return false
end
return self.is_selected
end
@@ -238,10 +309,38 @@ function Input.on_input_interrupt(self)
end
function Input.get_text_selected(self)
if self.start_index == self.end_index then
return self.value
end
return utf8.sub(self.value, self.start_index + 1, self.end_index)
end
--- Replace selected text with new text
-- @tparam Input self @{Input}
-- @tparam string text The text to replace selected text
-- @treturn string New input text
function Input.get_text_selected_replaced(self, text)
local left_part = utf8.sub(self.value, 1, self.start_index)
local right_part = utf8.sub(self.value, self.end_index + 1, utf8.len(self.value))
local result = left_part .. text .. right_part
if self.max_length then
result = utf8.sub(result, 1, self.max_length)
end
return result
end
--- Set text for input field
-- @tparam Input self @{Input}
-- @tparam string input_text The string to apply for input field
function Input.set_text(self, input_text)
input_text = tostring(input_text or "")
-- Case when update with marked text
if input_text then
self.value = input_text
@@ -297,8 +396,10 @@ function Input.select(self)
self.is_selected = true
gui.show_keyboard(self.keyboard_type, false)
self.on_input_select:trigger(self:get_context())
local len = utf8.len(self.value)
self:select_cursor(len, len, len)
self.on_input_select:trigger(self:get_context(), self)
self.style.on_select(self, self.button.node)
else
if self.style.IS_UNSELECT_ON_RESELECT then
@@ -313,13 +414,14 @@ end
function Input.unselect(self)
gui.reset_keyboard()
self.marked_value = ""
self.value = self.current_value
if self.is_selected then
self:reset_input_priority()
self.button:reset_input_priority()
self.is_selected = false
gui.hide_keyboard()
self.on_input_unselect:trigger(self:get_context(), self:get_text())
self.on_input_unselect:trigger(self:get_context(), self:get_text(), self)
self.style.on_unselect(self, self.button.node)
end
@@ -330,9 +432,13 @@ end
-- @tparam Input self @{Input}
-- @treturn string The current input field text
function Input.get_text(self)
if self.marked_value ~= "" then
return self.value .. self.marked_value
end
return self.value
end
--- Set maximum length for input field.
-- Pass nil to make input field unliminted (by default)
@@ -359,9 +465,97 @@ end
--- Reset current input selection and return previous value
-- @tparam Input self @{Input}
-- @treturn druid.input Current input instance
function Input.reset_changes(self)
self:set_text(self.previous_value)
self:unselect()
return self
end
--- Set cursor position in input field
-- @tparam Input self @{Input}
-- @tparam number|nil cursor_index Cursor index for cursor position, if nil - will be set to the end of the text
-- @tparam number|nil start_index Start index for cursor position, if nil - will be set to the end of the text
-- @tparam number|nil end_index End index for cursor position, if nil - will be set to the start_index
-- @treturn druid.input Current input instance
function Input.select_cursor(self, cursor_index, start_index, end_index)
local len = utf8.len(self.value)
self.cursor_index = cursor_index or len
self.start_index = start_index or self.cursor_index
self.end_index = end_index or self.start_index
self.cursor_index = helper.clamp(self.cursor_index, 0, len)
self.start_index = helper.clamp(self.start_index, 0, len)
self.end_index = helper.clamp(self.end_index, 0, len)
self.on_select_cursor_change:trigger(self:get_context(), self.cursor_index, self.start_index, self.end_index)
return self
end
--- Change cursor position by delta
-- @tparam Input self @{Input}
-- @tparam number delta side for cursor position, -1 for left, 1 for right
-- @tparam boolean is_add_to_selection (Shift key)
-- @tparam boolean is_move_to_end (Ctrl key)
function Input.move_selection(self, delta, is_add_to_selection, is_move_to_end)
local len = utf8.len(self.value)
local cursor_index = self.cursor_index
local start_index, end_index -- if nil, the selection will be 0 at cursor position
local is_right = delta > 0
local target_index = cursor_index + delta
if is_move_to_end then
target_index = is_right and len or 0
end
-- The Shift is not pressed
if not is_add_to_selection then
cursor_index = target_index
if self.start_index ~= self.end_index then
-- Reset selection without moving cursor
cursor_index = self.cursor_index
end
end
-- The Shift is pressed
if is_add_to_selection then
cursor_index = target_index
start_index = self.start_index
end_index = self.end_index
local is_cursor_extends_selection = (self.cursor_index == (is_right and end_index or start_index))
if is_cursor_extends_selection then
if is_right then
end_index = cursor_index
else
start_index = cursor_index
end
else
if is_right then
start_index = cursor_index
if is_move_to_end then
start_index = end_index
end_index = cursor_index
end
else
end_index = cursor_index
if is_move_to_end then
end_index = start_index
start_index = cursor_index
end
end
end
end
self:select_cursor(cursor_index, start_index, end_index)
end

View File

@@ -38,8 +38,8 @@ local LangText = component.create("lang_text")
--- The @{LangText} constructor
-- @tparam LangText self @{LangText}
-- @tparam string|node node The node_id or gui.get_node(node_id)
-- @tparam[opt=node_text] string locale_id Default locale id or text from node as default
-- @tparam[opt=downscale] string adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
-- @tparam string|nil locale_id Default locale id or text from node as default
-- @tparam string|nil adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
function LangText.init(self, node, locale_id, adjust_type)
self.druid = self:get_druid()
self.text = self.druid:new_text(node, locale_id, adjust_type)

View File

@@ -1,4 +1,4 @@
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
-- Copyright (c) 2024 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Layout management on node
--
@@ -13,205 +13,411 @@
--- Current layout mode
-- @tfield string mode
---On window resize callback(self, new_size)
-- @tfield DruidEvent on_size_changed @{DruidEvent}
---
local const = require("druid.const")
local helper = require("druid.helper")
local component = require("druid.component")
local Event = require("druid.event")
-- @class druid.layout.row_data
-- @tfield width number
-- @tfield height number
-- @tfield count number
local Layout = component.create("layout")
-- @class druid.layout.rows_data
-- @tfield total_width number
-- @tfield total_height number
-- @tfield nodes_width table<node, number>
-- @tfield nodes_height table<node, number>
-- @tfield rows druid.layout.row_data[]>
-- @class druid.layout: druid.base_component
local M = component.create("layout")
--- The @{Layout} constructor
-- The @{Layout} constructor
-- @tparam Layout self @{Layout}
-- @tparam node node Gui node
-- @tparam string mode The layout mode (from const.LAYOUT_MODE)
-- @tparam string layout_type The layout mode (from const.LAYOUT_MODE)
-- @tparam function|nil on_size_changed_callback The callback on window resize
function Layout.init(self, node, mode, on_size_changed_callback)
function M.init(self, node, layout_type)
self.node = self:get_node(node)
self._min_size = nil
self._max_size = nil
self._current_size = vmath.vector3(0)
self._inited = false
self._max_gui_upscale = nil
self._fit_node = nil
self._anchors = {}
self.mode = mode or const.LAYOUT_MODE.FIT
self.on_size_changed = Event(on_size_changed_callback)
self.is_dirty = true
self.entities = {}
self.margin = { x = 0, y = 0 }
self.padding = gui.get_slice9(self.node)
self.type = layout_type or "horizontal"
self.is_resize_width = false
self.is_resize_height = false
self.is_justify = false
end
function Layout.on_late_init(self)
self._inited = true
self.origin_size = self.origin_size or gui.get_size(self.node)
self.fit_size = self.fit_size or vmath.vector3(self.origin_size)
self.pivot = helper.get_pivot_offset(gui.get_pivot(self.node))
self.origin_position = gui.get_position(self.node)
self.position = vmath.vector3(self.origin_position)
gui.set_size_mode(self.node, gui.SIZE_MODE_MANUAL)
gui.set_adjust_mode(self.node, gui.ADJUST_FIT)
self:on_window_resized()
end
function Layout.on_window_resized(self)
if not self._inited then
function M:update()
if not self.is_dirty then
return
end
local x_koef, y_koef = helper.get_screen_aspect_koef()
local revert_scale = 1
if self._max_gui_upscale then
revert_scale = self._max_gui_upscale / helper.get_gui_scale()
revert_scale = math.min(revert_scale, 1)
end
gui.set_scale(self.node, vmath.vector3(revert_scale))
if self._fit_node then
self.fit_size = gui.get_size(self._fit_node)
self.fit_size.x = self.fit_size.x / x_koef
self.fit_size.y = self.fit_size.y / y_koef
end
x_koef = self.fit_size.x / self.origin_size.x * x_koef
y_koef = self.fit_size.y / self.origin_size.y * y_koef
local new_size = vmath.vector3(self.origin_size)
if self.mode == const.LAYOUT_MODE.STRETCH then
new_size.x = new_size.x * x_koef / revert_scale
new_size.y = new_size.y * y_koef / revert_scale
end
if self.mode == const.LAYOUT_MODE.STRETCH_X then
new_size.x = new_size.x * x_koef / revert_scale
end
if self.mode == const.LAYOUT_MODE.STRETCH_Y then
new_size.y = new_size.y * y_koef / revert_scale
end
-- Fit to the stretched container (node size or other defined)
if self.mode == const.LAYOUT_MODE.ZOOM_MIN then
new_size = new_size * math.min(x_koef, y_koef)
end
if self.mode == const.LAYOUT_MODE.ZOOM_MAX then
new_size = new_size * math.max(x_koef, y_koef)
end
if self._min_size then
new_size.x = math.max(new_size.x, self._min_size.x)
new_size.y = math.max(new_size.y, self._min_size.y)
end
if self._max_size then
new_size.x = math.min(new_size.x, self._max_size.x)
new_size.y = math.min(new_size.y, self._max_size.y)
end
self._current_size = new_size
gui.set_size(self.node, new_size)
self.position.x = self.origin_position.x + self.origin_position.x * (x_koef - 1)
self.position.y = self.origin_position.y + self.origin_position.y * (y_koef - 1)
gui.set_position(self.node, self.position)
self.on_size_changed:trigger(self:get_context(), new_size)
self:refresh_layout()
end
--- Set minimal size of layout node
-- @tparam Layout self @{Layout}
-- @tparam vector3 min_size
-- @treturn Layout @{Layout}
function Layout.set_min_size(self, min_size)
self._min_size = min_size
-- @tparam number|nil margin_x
-- @tparam number|nil margin_y
-- @treturn druid.layout @{Layout}
function M.set_margin(self, margin_x, margin_y)
self.margin.x = margin_x or self.margin.x
self.margin.y = margin_y or self.margin.y
self.is_dirty = true
return self
end
--- Set maximum size of layout node
-- @tparam Layout self @{Layout}
-- @tparam vector3 max_size
-- @treturn Layout @{Layout}
function Layout.set_max_size(self, max_size)
self._max_size = max_size
-- @tparam vector4 padding The vector4 with padding values, where x - left, y - top, z - right, w - bottom
-- @treturn druid.layout @{Layout}
function M.set_padding(self, padding)
self.padding = padding
self.is_dirty = true
return self
end
--- Set new origin position of layout node. You should apply this on node movement
-- @tparam Layout self @{Layout}
-- @tparam vector3 new_origin_position
-- @treturn Layout @{Layout}
function Layout.set_origin_position(self, new_origin_position)
self.origin_position = new_origin_position or self.origin_position
self:on_window_resized()
-- @treturn druid.layout @{Layout}
function M.set_dirty(self)
self.is_dirty = true
return self
end
--- Set new origin size of layout node. You should apply this on node manual size change
-- @tparam Layout self @{Layout}
-- @tparam vector3 new_origin_size
-- @treturn Layout @{Layout}
function Layout.set_origin_size(self, new_origin_size)
self.origin_size = new_origin_size or self.origin_size
self:on_window_resized()
-- @tparam boolean is_justify
-- @treturn druid.layout @{Layout}
function M.set_justify(self, is_justify)
self.is_justify = is_justify
self.is_dirty = true
return self
end
--- Set max gui upscale for FIT adjust mode (or side). It happens on bigger render gui screen
-- @tparam Layout self @{Layout}
-- @tparam number max_gui_upscale
-- @treturn Layout @{Layout}
function Layout.set_max_gui_upscale(self, max_gui_upscale)
self._max_gui_upscale = max_gui_upscale
self:on_window_resized()
end
-- @tparam string type The layout type: "horizontal", "vertical", "horizontal_wrap"
-- @treturn druid.layout @{Layout}
function M.set_type(self, type)
self.type = type
self.is_dirty = true
--- Set size for layout node to fit inside it
-- @tparam Layout self @{Layout}
-- @tparam vector3 target_size
-- @treturn Layout @{Layout}
function Layout.fit_into_size(self, target_size)
self.fit_size = target_size
self:on_window_resized()
return self
end
--- Set node for layout node to fit inside it. Pass nil to reset
-- @tparam Layout self @{Layout}
-- @tparam node|nil node
-- @treturn Layout @{Layout}
function Layout.fit_into_node(self, node)
self._fit_node = node
self:on_window_resized()
-- @tparam boolean is_hug_width
-- @tparam boolean is_hug_height
-- @treturn druid.layout @{Layout}
function M.set_hug_content(self, is_hug_width, is_hug_height)
self.is_resize_width = is_hug_width or false
self.is_resize_height = is_hug_height or false
self.is_dirty = true
return self
end
--- Set current size for layout node to fit inside it
-- @tparam Layout self @{Layout}
-- @treturn Layout @{Layout}
function Layout.fit_into_window(self)
return self:fit_into_size(vmath.vector3(
gui.get_width(),
gui.get_height(),
0))
-- @tparam string|node node_or_node_id
-- @treturn druid.layout @{Layout}
function M.add(self, node_or_node_id)
-- Acquire node from entity or by id
local node = node_or_node_id
if type(node_or_node_id) == "table" then
assert(node_or_node_id.node, "The entity should have a node")
node = node_or_node_id.node
else
-- @cast node_or_node_id string|node
node = self:get_node(node_or_node_id)
end
-- @cast node node
table.insert(self.entities, node)
gui.set_parent(node, self.node)
self.is_dirty = true
return self
end
return Layout
-- @tparam Layout self @{Layout}
-- @treturn druid.layout @{Layout}
function M.refresh_layout(self)
local layout_node = self.node
local entities = self.entities
local type = self.type -- vertical, horizontal, horizontal_wrap
local margin = self.margin -- {x: horizontal, y: vertical} in pixels, between elements
local padding = self.padding -- {x: left, y: top, z: right, w: bottom} in pixels
local is_justify = self.is_justify
local size = gui.get_size(layout_node)
local max_width = size.x - padding.x - padding.z
local max_height = size.y - padding.y - padding.w
local layout_pivot_offset = helper.get_pivot_offset(gui.get_pivot(layout_node)) -- {x: -0.5, y: -0.5} - is left bot, {x: 0.5, y: 0.5} - is right top
local rows_data = self:calculate_rows_data()
local rows = rows_data.rows
local row_index = 1
local row = rows[row_index]
-- Current x and Current y is a top left corner of the node
local current_x = -row.width * (0.5 + layout_pivot_offset.x)
local current_y = rows_data.total_height * (0.5 - layout_pivot_offset.y)
if is_justify then
if (type == "horizontal" or type == "horizontal_wrap") and row.count > 1 then
current_x = -max_width * (0.5 + layout_pivot_offset.x)
end
if type == "vertical" then
current_y = max_height * (0.5 - layout_pivot_offset.y)
end
end
for index = 1, #entities do
local node = entities[index]
local node_width = rows_data.nodes_width[node]
local node_height = rows_data.nodes_height[node]
local pivot_offset = helper.get_pivot_offset(gui.get_pivot(node))
if node_width > 0 and node_height > 0 then
-- Calculate position for current node
local position_x, position_y
if type == "horizontal" then
position_x = current_x + node_width * (0.5 + pivot_offset.x)
position_y = current_y - row.height * (0.5 - pivot_offset.y)
local node_margin = margin.x
if is_justify and row.count > 1 then
node_margin = (max_width - row.width) / (row.count - 1) + margin.x
end
current_x = current_x + node_width + node_margin
end
if type == "vertical" then
local node_margin = margin.y
if is_justify then
node_margin = (max_height - rows_data.total_height) / (#rows - 1) + margin.y
end
current_x = -row.width * (0.5 + layout_pivot_offset.x)
position_x = current_x + row.width * (0.5 + pivot_offset.x)
position_y = current_y - node_height * (0.5 - pivot_offset.y)
current_y = current_y - node_height - node_margin
row_index = row_index + 1
row = rows[row_index]
end
if type == "horizontal_wrap" then
local width = row.width
if is_justify and row.count > 0 then
width = math.max(row.width, max_width)
end
local new_row_width = width * (0.5 - layout_pivot_offset.x)
-- Compare with eps due the float loss and element flickering
if current_x + node_width - new_row_width > 0.0001 then
if row_index < #rows then
row_index = row_index + 1
row = rows[row_index]
end
current_x = -row.width * (0.5 + layout_pivot_offset.x)
current_y = current_y - row.height - margin.y
if is_justify and row.count > 1 then
current_x = -max_width * (0.5 + layout_pivot_offset.x)
end
end
position_x = current_x + node_width * (0.5 + pivot_offset.x)
position_y = current_y - row.height * (0.5 - pivot_offset.y)
local node_margin = margin.x
if is_justify and row.count > 1 then
node_margin = (max_width - row.width) / (row.count - 1) + margin.x
end
current_x = current_x + node_width + node_margin
end
do -- Padding offset
if layout_pivot_offset.x == -0.5 then
position_x = position_x + padding.x
end
if layout_pivot_offset.y == 0.5 then
position_y = position_y - padding.y
end
if layout_pivot_offset.x == 0.5 then
position_x = position_x - padding.z
end
if layout_pivot_offset.y == -0.5 then
position_y = position_y + padding.w
end
end
self:set_node_position(node, position_x, position_y)
end
end
if self.is_resize_width or self.is_resize_height then
if self.is_resize_width then
size.x = rows_data.total_width + padding.x + padding.z
end
if self.is_resize_height then
size.y = rows_data.total_height + padding.y + padding.w
end
gui.set_size(layout_node, size)
end
self.is_dirty = false
return self
end
-- @tparam Layout self @{Layout}
-- @treturn druid.layout @{Layout}
function M.clear_layout(self)
for index = #self.entities, 1, -1 do
self.entities[index] = nil
end
self.is_dirty = true
return self
end
-- @tparam node node
-- @treturn number, number
-- @local
function M.get_node_size(node)
if not gui.is_enabled(node, false) then
return 0, 0
end
local scale = gui.get_scale(node)
-- If node has text - get text size instead of node size
if gui.get_text(node) then
local text_metrics = helper.get_text_metrics_from_node(node)
return text_metrics.width * scale.x, text_metrics.height * scale.y
end
local size = gui.get_size(node)
return size.x * scale.x, size.y * scale.y
end
-- @tparam Layout self @{Layout}
-- Calculate rows data for layout. Contains total width, height and rows info (width, height, count of elements in row)
-- @treturn druid.layout.rows_data
-- @local
function M.calculate_rows_data(self)
local entities = self.entities
local margin = self.margin
local type = self.type
local padding = self.padding
local size = gui.get_size(self.node)
local max_width = size.x - padding.x - padding.z
-- Collect rows info about width, height and count of elements in row
local current_row = { width = 0, height = 0, count = 0 }
local rows_data = {
total_width = 0,
total_height = 0,
nodes_width = {},
nodes_height = {},
rows = { current_row }
}
for index = 1, #entities do
local node = entities[index]
local node_width = rows_data.nodes_width[node]
local node_height = rows_data.nodes_height[node]
-- Get node size if it's not calculated yet
if not node_width or not node_height then
node_width, node_height = M.get_node_size(node)
rows_data.nodes_width[node] = node_width
rows_data.nodes_height[node] = node_height
end
if node_width > 0 and node_height > 0 then
if type == "horizontal" then
current_row.width = current_row.width + node_width + margin.x
current_row.height = math.max(current_row.height, node_height)
current_row.count = current_row.count + 1
end
if type == "vertical" then
if current_row.count > 0 then
current_row = { width = 0, height = 0, count = 0 }
table.insert(rows_data.rows, current_row)
end
current_row.width = math.max(current_row.width, node_width + margin.x)
current_row.height = node_height
current_row.count = current_row.count + 1
end
if type == "horizontal_wrap" then
if current_row.width + node_width > max_width and current_row.count > 0 then
current_row = { width = 0, height = 0, count = 0 }
table.insert(rows_data.rows, current_row)
end
current_row.width = current_row.width + node_width + margin.x
current_row.height = math.max(current_row.height, node_height)
current_row.count = current_row.count + 1
end
end
end
-- Remove last margin of each row
-- Calculate total width and height
local rows_count = #rows_data.rows
for index = 1, rows_count do
local row = rows_data.rows[index]
if row.width > 0 then
row.width = row.width - margin.x
end
rows_data.total_width = math.max(rows_data.total_width, row.width)
rows_data.total_height = rows_data.total_height + row.height
end
rows_data.total_height = rows_data.total_height + margin.y * (rows_count - 1)
return rows_data
end
-- @tparam node node
-- @tparam number x
-- @tparam number y
-- @treturn node
-- @local
function M:set_node_position(node, x, y)
local position = gui.get_position(node)
position.x = x
position.y = y
gui.set_position(node, position)
return node
end
return M

View File

@@ -76,15 +76,29 @@ end
local function set_bar_to(self, set_to, is_silent)
local prev_value = self.last_value
local other_side = self.key == const.SIDE.X and const.SIDE.Y or const.SIDE.X
self.last_value = set_to
local total_width = set_to * self.max_size
local total_width = set_to * self.max_size[self.key]
local scale = math.min(total_width / self.slice_size, 1)
local size = math.max(total_width, self.slice_size)
local scale = 1
if self.slice_size[self.key] > 0 then
scale = math.min(total_width / self.slice_size[self.key], 1)
end
local size = math.max(total_width, self.slice_size[self.key])
do -- Scale other side
-- Decrease other side of progress bar to match the oppotize slice_size
local minimal_size = self.size[other_side] - self.slice_size[other_side]
local maximum_size = self.size[other_side]
local scale_diff = (maximum_size - minimal_size) / maximum_size
local other_scale = 1 - (scale_diff * (1 - scale))
self.scale[other_side] = other_scale
end
self.scale[self.key] = scale
gui.set_scale(self.node, self.scale)
self.size[self.key] = size
gui.set_size(self.node, self.size)
@@ -101,8 +115,8 @@ end
-- You can override this component styles params in druid styles table
-- or create your own style
-- @table style
-- @tfield[opt=5] number SPEED Progress bas fill rate. More -> faster
-- @tfield[opt=0.005] number MIN_DELTA Minimum step to fill progress bar
-- @tfield number|nil SPEED Progress bas fill rate. More -> faster. Default: 5
-- @tfield number|nil MIN_DELTA Minimum step to fill progress bar. Default: 0.005
function Progress.on_style_change(self, style)
self.style = {}
self.style.SPEED = style.SPEED or 5
@@ -114,7 +128,7 @@ end
-- @tparam Progress self @{Progress}
-- @tparam string|node node Node name or GUI Node itself.
-- @tparam string key Progress bar direction: const.SIDE.X or const.SIDE.Y
-- @tparam[opt=1] number init_value Initial value of progress bar
-- @tparam number|nil init_value Initial value of progress bar. Default: 1
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'")
@@ -125,15 +139,15 @@ function Progress.init(self, node, key, init_value)
self.node = self:get_node(node)
self.scale = gui.get_scale(self.node)
self.size = gui.get_size(self.node)
self.max_size = self.size[self.key]
self.max_size = gui.get_size(self.node)
self.slice = gui.get_slice9(self.node)
self.last_value = self._init_value
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
end
self.slice_size = vmath.vector3(
self.slice.x + self.slice.z,
self.slice.y + self.slice.w,
0
)
self.on_change = Event()
@@ -146,6 +160,12 @@ function Progress.on_layout_change(self)
end
function Progress.on_remove(self)
-- Return default size
gui.set_size(self.node, self.max_size)
end
function Progress.update(self, dt)
if self.target then
local prev_value = self.last_value
@@ -231,7 +251,7 @@ end
-- @tparam vector3 max_size The new node maximum (full) size
-- @treturn Progress @{Progress}
function Progress.set_max_size(self, max_size)
self.max_size = max_size[self.key]
self.max_size[self.key] = max_size[self.key]
self:set_to(self.last_value)
return self
end

View File

@@ -34,7 +34,7 @@ end
-- @tparam RadioGroup self @{RadioGroup}
-- @tparam node[] nodes Array of gui node
-- @tparam function callback Radio callback
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
-- @tparam node[]|nil click_nodes Array of trigger nodes, by default equals to nodes. Default - nodes
function RadioGroup.init(self, nodes, callback, click_nodes)
self.druid = self:get_druid()
self.checkboxes = {}

View File

@@ -26,7 +26,7 @@
-- @tfield vector3 end_pos
--- Length between start and end position
-- @tfield number dist
-- @tfield vector3 dist
--- Current drag state
-- @tfield boolean is_drag
@@ -68,6 +68,7 @@ function Slider.init(self, node, end_pos, callback)
self.pos = gui.get_position(self.node)
self.target_pos = vmath.vector3(self.pos)
self.end_pos = end_pos
self._is_enabled = true
self.dist = self.end_pos - self.start_pos
self.is_drag = false
@@ -85,6 +86,12 @@ function Slider.on_layout_change(self)
end
function Slider.on_remove(self)
-- Return pin to start position
gui.set_position(self.node, self.start_pos)
end
function Slider.on_window_resized(self)
local x_koef, y_koef = helper.get_screen_aspect_koef()
self._x_koef = x_koef
@@ -98,6 +105,10 @@ function Slider.on_input(self, action_id, action)
return false
end
if not self._is_enabled or not gui.is_enabled(self.node, true) then
return false
end
if gui.pick_node(self.node, action.x, action.y) then
if action.pressed then
self.pos = gui.get_position(self.node)
@@ -132,14 +143,16 @@ function Slider.on_input(self, action_id, action)
if prev_x ~= self.target_pos.x or prev_y ~= self.target_pos.y then
local prev_value = self.value
if self.dist.x > 0 then
if math.abs(self.dist.x) > 0 then
self.value = (self.target_pos.x - self.start_pos.x) / self.dist.x
end
if self.dist.y > 0 then
if math.abs(self.dist.y) > 0 then
self.value = (self.target_pos.y - self.start_pos.y) / self.dist.y
end
self.value = math.abs(self.value)
if self.steps then
local closest_dist = 1000
local closest = nil
@@ -202,7 +215,7 @@ end
-- move at this position and node drag will start.
-- This function require the Defold version 1.3.0+
-- @tparam Slider self @{Slider}
-- @tparam node input_node
-- @tparam node|string|nil input_node
-- @treturn Slider @{Slider}
function Slider.set_input_node(self, input_node)
self._input_node = self:get_node(input_node)
@@ -210,4 +223,20 @@ function Slider.set_input_node(self, input_node)
end
--- Set Slider input enabled or disabled
-- @tparam Slider self @{Slider}
-- @tparam boolean is_enabled
function Slider.set_enabled(self, is_enabled)
self._is_enabled = is_enabled
end
--- Check if Slider component is enabled
-- @tparam Slider self @{Slider}
-- @treturn boolean
function Slider.is_enabled(self)
return self._is_enabled
end
return Slider

View File

@@ -74,9 +74,9 @@ end
-- You can override this component styles params in druid styles table
-- or create your own style
-- @table style
-- @tfield[opt=0.4] number SWIPE_TIME Maximum time for swipe trigger
-- @tfield[opt=50] number SWIPE_THRESHOLD Minimum distance for swipe trigger
-- @tfield[opt=false] boolean SWIPE_TRIGGER_ON_MOVE If true, trigger on swipe moving, not only release action
-- @tfield number|nil SWIPE_TIME Maximum time for swipe trigger. Default: 0.4
-- @tfield number|nil SWIPE_THRESHOLD Minimum distance for swipe trigger. Default: 50
-- @tfield boolean|nil SWIPE_TRIGGER_ON_MOVE If true, trigger on swipe moving, not only release action. Default: false
function Swipe.on_style_change(self, style)
self.style = {}
self.style.SWIPE_TIME = style.SWIPE_TIME or 0.4
@@ -150,7 +150,7 @@ end
--- Strict swipe click area. Useful for
-- restrict events outside stencil node
-- @tparam Swipe self @{Swipe}
-- @tparam node zone Gui node
-- @tparam node|string|nil zone Gui node
function Swipe.set_click_zone(self, zone)
self.click_zone = self:get_node(zone)
end

View File

@@ -47,18 +47,19 @@ end
--- The @{Timer} constructor
-- @tparam Timer self @{Timer}
-- @tparam node node Gui text node
-- @tparam number seconds_from Start timer value in seconds
-- @tparam number|nil seconds_from Start timer value in seconds
-- @tparam number|nil seconds_to End timer value in seconds
-- @tparam function|nil callback Function on timer end
function Timer.init(self, node, seconds_from, seconds_to, callback)
self.node = self:get_node(node)
seconds_from = math.max(seconds_from, 0)
seconds_to = math.max(seconds_to or 0, 0)
self.on_tick = Event()
self.on_set_enabled = Event()
self.on_timer_end = Event(callback)
if seconds_from then
seconds_from = math.max(seconds_from, 0)
self:set_to(seconds_from)
self:set_interval(seconds_from, seconds_to)
@@ -66,6 +67,7 @@ function Timer.init(self, node, seconds_from, seconds_to, callback)
self:set_state(false)
self.on_timer_end:trigger(self:get_context(), self)
end
end
return self
end

View File

@@ -10,12 +10,15 @@
local const = require("druid.const")
local M = {}
local POSITION_X = hash("position.x")
local SCALE_X = hash("scale.x")
local SIZE_X = hash("size.x")
local function get_text_width(text_node)
if text_node then
local text_metrics = M.get_text_metrics_from_node(text_node)
local text_scale = gui.get_scale(text_node).x
local text_scale = gui.get(text_node, SCALE_X)
return text_metrics.width * text_scale
end
@@ -25,8 +28,7 @@ end
local function get_icon_width(icon_node)
if icon_node then
local icon_scale_x = gui.get_scale(icon_node).x
return gui.get_size(icon_node).x * icon_scale_x -- icon width
return gui.get(icon_node, SIZE_X) * gui.get(icon_node, SCALE_X) -- icon width
end
return 0
@@ -97,13 +99,12 @@ function M.centrate_nodes(margin, ...)
for i = 1, count do
local node = select(i, ...)
local node_width = node_widths[i]
local pos = gui.get_position(node)
pos_x = pos_x + node_width/2 -- made offset for single item
local pivot_offset = M.get_pivot_offset(gui.get_pivot(node))
pos.x = pos_x - width/2 + pivot_offset.x * node_width -- centrate node
gui.set_position(node, pos)
local new_pos_x = pos_x - width/2 + pivot_offset.x * node_width -- centrate node
gui.set(node, POSITION_X, new_pos_x)
pos_x = pos_x + node_widths[i]/2 + margin -- add second part of offset
end
@@ -369,6 +370,25 @@ function M.is_web()
end
--- Check if device is HTML5 mobile
-- @function helper.is_web_mobile
-- @treturn boolean Is web mobile
function M.is_web_mobile()
if html5 then
return html5.run("(typeof window.orientation !== 'undefined') || (navigator.userAgent.indexOf('IEMobile') !== -1);") == "true"
end
return false
end
--- Check if device is mobile and can support multitouch
-- @function helper.is_multitouch_supported
-- @treturn boolean Is multitouch supported
function M.is_multitouch_supported()
return M.is_mobile() or M.is_web_mobile()
end
--- Simple table to one-line string converter
-- @function helper.table_to_string
-- @tparam table t

View File

@@ -6,21 +6,11 @@ local settings = require("druid.system.settings")
local M = {}
local function button_hover_scale(node, target, time)
gui.animate(node, "scale", target, gui.EASING_OUTSINE, time)
end
local function button_tap_anim(node, tap_scale, start_scale)
gui.animate(node, gui.PROP_SCALE, tap_scale, gui.EASING_INSINE, 0.1, 0, function()
gui.animate(node, gui.PROP_SCALE, start_scale, gui.EASING_INSINE, 0.1)
end)
end
M["button"] = {
HOVER_SCALE = vmath.vector3(0.02, 0.02, 1),
HOVER_MOUSE_SCALE = vmath.vector3(0.01, 0.01, 1),
HOVER_TIME = 0.04,
SCALE_CHANGE = vmath.vector3(0.035, 0.035, 1),
HOVER_SCALE = vmath.vector3(0.08, 0.08, 1),
HOVER_MOUSE_SCALE = vmath.vector3(0.04, 0.04, 1),
HOVER_TIME = 0.05,
SCALE_CHANGE = vmath.vector3(0.12, 0.12, 1),
BTN_SOUND = "click",
BTN_SOUND_DISABLED = "click",
DISABLED_COLOR = vmath.vector4(0, 0, 0, 1),
@@ -33,35 +23,44 @@ M["button"] = {
local scale_to = self.start_scale + M.button.HOVER_SCALE
local target_scale = state and scale_to or self.start_scale
button_hover_scale(node, target_scale, M.button.HOVER_TIME)
gui.animate(node, "scale", target_scale, gui.EASING_OUTSINE, M.button.HOVER_TIME)
end,
on_mouse_hover = function(self, node, state)
local scale_to = self.start_scale + M.button.HOVER_MOUSE_SCALE
local target_scale = state and scale_to or self.start_scale
button_hover_scale(node, target_scale, M.button.HOVER_TIME)
gui.animate(node, "scale", target_scale, gui.EASING_OUTSINE, M.button.HOVER_TIME)
end,
on_click = function(self, node)
local scale_to = self.start_scale + M.button.SCALE_CHANGE
button_tap_anim(node, scale_to, self.start_scale)
gui.set_scale(node, scale_to)
local is_hover = self.hover:is_mouse_hovered()
local target_scale = is_hover and self.start_scale + M.button.HOVER_MOUSE_SCALE or self.start_scale
gui.animate(node, gui.PROP_SCALE, target_scale, gui.EASING_OUTBACK, 0.24)
settings.play_sound(M.button.BTN_SOUND)
end,
on_click_disabled = function(self, node)
settings.play_sound(M.button.BTN_SOUND_DISABLED)
local start_pos = self.start_pos
gui.animate(node, "position.x", start_pos.x - 3, gui.EASING_OUTSINE, 0.05, 0, function()
gui.animate(node, "position.x", start_pos.x + 3, gui.EASING_OUTSINE, 0.1, 0, function()
gui.animate(node, "position.x", start_pos.x, gui.EASING_OUTSINE, 0.05)
end)
end)
end,
on_set_enabled = function(self, node, state)
if state then
gui.set_color(node, M.button.ENABLED_COLOR)
else
gui.set_color(node, M.button.DISABLED_COLOR)
end
end
}
M["hover"] = {
ON_HOVER_CURSOR = nil,
ON_MOUSE_HOVER_CURSOR = nil,
}
M["drag"] = {
DRAG_DEADZONE = 10, -- Size in pixels of drag deadzone
@@ -84,8 +83,8 @@ M["scroll"] = {
INERT_SPEED = 30, -- koef. of inert speed
EXTRA_STRETCH_SIZE = 100, -- extra size in pixels outside of scroll (stretch effect)
POINTS_DEADZONE = 20, -- Speed to check points of interests in no_inertion mode
WHEEL_SCROLL_SPEED = 0, -- Amount of pixels to scroll by one wheel event (0 to disable)
WHEEL_SCROLL_INVERTED = false, -- Boolean to invert wheel scroll side
WHEEL_SCROLL_SPEED = 20, -- Amount of pixels to scroll by one wheel event (0 to disable)
WHEEL_SCROLL_INVERTED = true, -- Boolean to invert wheel scroll side
WHEEL_SCROLL_BY_INERTION = false, -- If true, wheel will add inertion to scroll. Direct set position otherwise.
SMALL_CONTENT_SCROLL = false, -- If true, content node with size less than view node size can be scrolled
}
@@ -119,11 +118,10 @@ M["swipe"] = {
M["input"] = {
IS_LONGTAP_ERASE = true,
BUTTON_SELECT_INCREASE = 1.06,
IS_LONGTAP_ERASE = false,
BUTTON_SELECT_INCREASE = 1.08,
MASK_DEFAULT_CHAR = "*",
IS_UNSELECT_ON_RESELECT = false,
NO_CONSUME_INPUT_WHILE_SELECTED = false,
on_select = function(self, button_node)
local target_scale = self.button.start_scale
@@ -143,12 +141,6 @@ M["input"] = {
end)
end)
end,
button = {
LONGTAP_TIME = 0.4,
AUTOHOLD_TRIGGER = 0.8,
DOUBLETAP_TIME = 0.4,
}
}

View File

@@ -1,26 +0,0 @@
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
local M = {}
M["button"] = {
LONGTAP_TIME = 0.4,
DOUBLETAP_TIME = 0.4,
HOVER_MOUSE_IMAGE = "button_yellow",
DEFAULT_IMAGE = "button_blue",
HOVER_IMAGE = "button_red",
on_hover = function(self, node, state)
local anim = state and M.button.HOVER_IMAGE or M.button.DEFAULT_IMAGE
gui.play_flipbook(node, anim)
end,
on_mouse_hover = function(self, node, state)
local anim = state and M.button.HOVER_MOUSE_IMAGE or M.button.DEFAULT_IMAGE
gui.play_flipbook(node, anim)
end
}
return M

View File

@@ -68,7 +68,6 @@
-- @see Timer
local helper = require("druid.helper")
local class = require("druid.system.middleclass")
local settings = require("druid.system.settings")
local base_component = require("druid.component")
@@ -94,7 +93,7 @@ local back_handler = require("druid.base.back_handler")
-- local dynamic_grid = require("druid.extended.dynamic_grid")
-- local checkbox_group = require("druid.extended.checkbox_group")
local DruidInstance = class("druid.druid_instance")
local DruidInstance = {}
local MSG_ADD_FOCUS = hash("acquire_input_focus")
local MSG_REMOVE_FOCUS = hash("release_input_focus")
@@ -193,10 +192,6 @@ end
local function process_input(self, action_id, action, components)
local is_input_consumed = false
if #components == 0 then
return false
end
for i = #components, 1, -1 do
local component = components[i]
local meta = component._meta
@@ -252,7 +247,7 @@ function DruidInstance.initialize(self, context, style)
end
--- Create new component.
-- Create new component.
-- @tparam DruidInstance self
-- @tparam BaseComponent component Component module
-- @tparam any ... Other component params to pass it to component:init function
@@ -293,23 +288,27 @@ end
-- Component `on_remove` function will be invoked, if exist.
-- @tparam DruidInstance self
-- @tparam BaseComponent component Component instance
-- @treturn boolean True if component was removed
function DruidInstance.remove(self, component)
if self._is_late_remove_enabled then
table.insert(self._late_remove, component)
return
return false
end
-- Recursive remove all children of component
local children = component._meta.children
for i = #children, 1, -1 do
self:remove(children[i])
local parent = children[i]:get_parent_component()
if parent then
parent:__remove_children(children[i])
end
children[i] = nil
end
local parent = component:get_parent_component()
if parent then
parent:__remove_child(component)
end
local is_removed = false
local all_components = self.components_all
for i = #all_components, 1, -1 do
if all_components[i] == component then
@@ -317,6 +316,7 @@ function DruidInstance.remove(self, component)
component:on_remove()
end
table.remove(all_components, i)
is_removed = true
end
end
@@ -330,6 +330,8 @@ function DruidInstance.remove(self, component)
end
end
end
return is_removed
end
@@ -473,10 +475,10 @@ end
-- If whitelist is not empty and component not contains in this list,
-- component will be not processed on input step
-- @tparam DruidInstance self
-- @tparam[opt=nil] table|BaseComponent whitelist_components The array of component to whitelist
-- @tparam table|BaseComponent|nil whitelist_components The array of component to whitelist
-- @treturn self @{DruidInstance}
function DruidInstance.set_whitelist(self, whitelist_components)
if whitelist_components and whitelist_components.isInstanceOf then
if whitelist_components and whitelist_components._component then
whitelist_components = { whitelist_components }
end
@@ -495,10 +497,10 @@ end
-- If blacklist is not empty and component contains in this list,
-- component will be not processed on input step
-- @tparam DruidInstance self @{DruidInstance}
-- @tparam[opt=nil] table|BaseComponent blacklist_components The array of component to blacklist
-- @tparam table|BaseComponent|nil blacklist_components The array of component to blacklist
-- @treturn self @{DruidInstance}
function DruidInstance.set_blacklist(self, blacklist_components)
if blacklist_components and blacklist_components.isInstanceOf then
if blacklist_components and blacklist_components._component then
blacklist_components = { blacklist_components }
end
@@ -556,8 +558,8 @@ end
-- @tparam DruidInstance self
-- @tparam string|node node The node_id or gui.get_node(node_id)
-- @tparam function|nil callback Button callback
-- @tparam table|nil params Button callback params
-- @tparam node|nil anim_node Button anim node (node, if not provided)
-- @tparam any|nil params Button callback params
-- @tparam node|string|nil anim_node Button anim node (node, if not provided)
-- @treturn Button @{Button} component
function DruidInstance.new_button(self, node, callback, params, anim_node)
return DruidInstance.new(self, button, node, callback, params, anim_node)
@@ -587,9 +589,10 @@ end
-- @tparam DruidInstance self
-- @tparam string|node node The node_id or gui.get_node(node_id)
-- @tparam function|nil on_hover_callback Hover callback
-- @tparam function|nil on_mouse_hover_callback Mouse hover callback
-- @treturn Hover @{Hover} component
function DruidInstance.new_hover(self, node, on_hover_callback)
return DruidInstance.new(self, hover, node, on_hover_callback)
function DruidInstance.new_hover(self, node, on_hover_callback, on_mouse_hover_callback)
return DruidInstance.new(self, hover, node, on_hover_callback, on_mouse_hover_callback)
end
@@ -705,7 +708,7 @@ end
--- Create @{Input} component
-- @tparam DruidInstance self
-- @tparam string|node click_node Button node to enabled input component
-- @tparam string|node text_node Text node what will be changed on user input
-- @tparam string|node|druid.text text_node Text node what will be changed on user input
-- @tparam number|nil keyboard_type Gui keyboard type for input field
-- @treturn Input @{Input} component
function DruidInstance.new_input(self, click_node, text_node, keyboard_type)
@@ -715,9 +718,9 @@ end
--- Create @{CheckboxGroup} component
-- @tparam DruidInstance self
-- @tparam node[] nodes Array of gui node
-- @tparam (node|string)[] nodes Array of gui node
-- @tparam function callback Checkbox callback
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
-- @tparam (node|string)[]|nil click_nodes Array of trigger nodes, by default equals to nodes
-- @treturn CheckboxGroup @{CheckboxGroup} component
function DruidInstance.new_checkbox_group(self, nodes, callback, click_nodes)
return helper.require_component_message("checkbox_group")
@@ -727,7 +730,7 @@ end
--- Create @{DataList} component
-- @tparam DruidInstance self
-- @tparam Scroll druid_scroll The Scroll instance for Data List component
-- @tparam StaticGrid|DynamicGrid druid_grid The @{StaticGrid} or @{DynamicGrid} instance for Data List component
-- @tparam StaticGrid druid_grid The @{StaticGrid} or @{DynamicGrid} instance for Data List component
-- @tparam function create_function The create function callback(self, data, index, data_list). Function should return (node, [component])
-- @treturn DataList @{DataList} component
function DruidInstance.new_data_list(self, druid_scroll, druid_grid, create_function)
@@ -737,9 +740,9 @@ end
--- Create @{RadioGroup} component
-- @tparam DruidInstance self
-- @tparam node[] nodes Array of gui node
-- @tparam (node|string)[] nodes Array of gui node
-- @tparam function callback Radio callback
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
-- @tparam (node|string)[]|nil click_nodes Array of trigger nodes, by default equals to nodes
-- @treturn RadioGroup @{RadioGroup} component
function DruidInstance.new_radio_group(self, nodes, callback, click_nodes)
return helper.require_component_message("radio_group")

View File

@@ -1,156 +0,0 @@
-- Source: https://github.com/kikito/middleclass
local middleclass = {}
local function _createIndexWrapper(aClass, f)
if f == nil then
return aClass.__instanceDict
else
return function(self, name)
local value = aClass.__instanceDict[name]
if value ~= nil then
return value
elseif type(f) == "function" then
return (f(self, name))
else
return f[name]
end
end
end
end
local function _propagateInstanceMethod(aClass, name, f)
f = name == "__index" and _createIndexWrapper(aClass, f) or f
aClass.__instanceDict[name] = f
for subclass in pairs(aClass.subclasses) do
if rawget(subclass.__declaredMethods, name) == nil then
_propagateInstanceMethod(subclass, name, f)
end
end
end
local function _declareInstanceMethod(aClass, name, f)
aClass.__declaredMethods[name] = f
if f == nil and aClass.super then
f = aClass.super.__instanceDict[name]
end
_propagateInstanceMethod(aClass, name, f)
end
local function _tostring(self) return "class " .. self.name end
local function _call(self, ...) return self:instantiate(...) end
local function _createClass(name, super)
local dict = {}
dict.__index = dict
local aClass = { name = name, super = super, static = {},
__instanceDict = dict, __declaredMethods = {},
subclasses = setmetatable({}, {__mode='k'}) }
if super then
setmetatable(aClass.static, {
__index = function(_,k)
local result = rawget(dict,k)
if result == nil then
return super.static[k]
end
return result
end
})
else
setmetatable(aClass.static, { __index = function(_,k) return rawget(dict,k) end })
end
setmetatable(aClass, { __index = aClass.static, __tostring = _tostring,
__call = _call, __newindex = _declareInstanceMethod })
return aClass
end
local function _includeMixin(aClass, mixin)
assert(type(mixin) == 'table', "mixin must be a table")
for name,method in pairs(mixin) do
if name ~= "included" and name ~= "static" then aClass[name] = method end
end
for name,method in pairs(mixin.static or {}) do
aClass.static[name] = method
end
if type(mixin.included)=="function" then mixin:included(aClass) end
return aClass
end
local DefaultMixin = {
__tostring = function(self) return "instance of " .. tostring(self.class) end,
initialize = function(self, ...) end,
isInstanceOf = function(self, aClass)
return type(aClass) == 'table'
and type(self) == 'table'
and (self.class == aClass
or type(self.class) == 'table'
and type(self.class.isSubclassOf) == 'function'
and self.class:isSubclassOf(aClass))
end,
static = {
allocate = function(self)
assert(type(self) == 'table', "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'")
return setmetatable({ class = self }, self.__instanceDict)
end,
instantiate = function(self, ...)
assert(type(self) == 'table', "Make sure that you are using 'Class:instantiate' instead of 'Class.instantiate'")
local instance = self:allocate()
instance:initialize(...)
return instance
end,
subclass = function(self, name)
assert(type(self) == 'table', "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'")
assert(type(name) == "string", "You must provide a name(string) for your class")
local subclass = _createClass(name, self)
for methodName, f in pairs(self.__instanceDict) do
_propagateInstanceMethod(subclass, methodName, f)
end
subclass.initialize = function(instance, ...) return self.initialize(instance, ...) end
self.subclasses[subclass] = true
self:subclassed(subclass)
return subclass
end,
subclassed = function(self, other) end,
isSubclassOf = function(self, other)
return type(other) == 'table' and
type(self.super) == 'table' and
( self.super == other or self.super:isSubclassOf(other) )
end,
include = function(self, ...)
assert(type(self) == 'table', "Make sure you that you are using 'Class:include' instead of 'Class.include'")
for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end
return self
end
}
}
function middleclass.class(name, super)
assert(type(name) == 'string', "A name (string) is needed for the new class")
return super and super:subclass(name) or _includeMixin(_createClass(name), DefaultMixin)
end
setmetatable(middleclass, { __call = function(_, ...) return middleclass.class(...) end })
return middleclass

View File

@@ -688,7 +688,8 @@ local function matcherGenerator(regex, plain)
local sum = 0
local bc, ec = utf8sub(str, 1, 1), utf8sub(str, 2, 2)
local skip = len(bc) + len(ec)
bc, ec = utf8unicode(bc), utf8unicode(ec)
bc = utf8unicode(bc) --[[@as string]]
ec = utf8unicode(ec) --[[@as string]]
return function(cC)
if cC == ec and sum > 0 then
sum = sum - 1

View File

@@ -3,20 +3,13 @@ local component = require("druid.component")
---@class component_name : druid.base_component
local Component = component.create("component_name")
local SCHEME = {
ROOT = "root",
BUTTON = "button",
}
-- Component constructor. Template name and nodes are optional. Pass it if you use it in your component
function Component:init(template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.root = self:get_node(SCHEME.ROOT)
self.druid = self:get_druid()
self.druid = self:get_druid(template, nodes)
self.root = self:get_node("root")
self.button = self.druid:new_button(SCHEME.BUTTON, function() end)
self.button = self.druid:new_button("button", function() end)
end

View File

@@ -3,26 +3,16 @@ local component = require("druid.component")
---@class component_name : druid.base_component
local Component = component.create("component_name")
-- Scheme of component gui nodes
local SCHEME = {
ROOT = "root",
BUTTON = "button",
}
-- Component constructor. Template name and nodes are optional. Pass it if you use it in your component
function Component:init(template, nodes)
-- If your component is gui template, pass the template name and set it
self:set_template(template)
-- If your component is cloned my gui.clone_tree, pass nodes to component and set it
self:set_nodes(nodes)
-- Use inner druid instance to create components inside this component
self.druid = self:get_druid(template, nodes)
-- self:get_node will auto process component template and nodes
self.root = self:get_node(SCHEME.ROOT)
self.root = self:get_node("root")
-- Use inner druid instance to create components inside this component
self.druid = self:get_druid()
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +0,0 @@
name: "pin_knob"
scale_along_z: 0
embedded_instances {
id: "go"
data: "components {\n"
" id: \"rich_input\"\n"
" component: \"/example/examples/custom/pin_knob/pin_knob.gui\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
""
position {
x: 0.0
y: 0.0
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 1.0
y: 1.0
z: 1.0
}
}

View File

@@ -1,677 +0,0 @@
script: "/example/examples/custom/pin_knob/pin_knob.gui_script"
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
}
textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 300.0
y: 415.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 600.0
y: 830.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
}
nodes {
position {
x: 0.0
y: 370.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 700.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Rich Input custom component"
font: "game"
id: "text_hint_horizontal"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
}
nodes {
position {
x: -100.0
y: 230.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "pin_knob1"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/druid/custom/pin_knob/pin_knob.gui"
template_node_child: false
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/empty"
id: "pin_knob1/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob1"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 2.0
y: 2.0
z: 1.0
w: 1.0
}
size {
x: 36.0
y: 36.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/slider_move"
id: "pin_knob1/pin"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob1/root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 13.5
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.2
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 17.0
y: 17.0
z: 0.0
w: 1.0
}
color {
x: 0.101960786
y: 0.101960786
z: 0.101960786
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/tick"
id: "pin_knob1/notch"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob1/pin"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: -100.0
y: 154.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 120.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "50"
font: "game"
id: "text_value1"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
}
nodes {
position {
x: 100.0
y: 230.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "pin_knob2"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/druid/custom/pin_knob/pin_knob.gui"
template_node_child: false
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/empty"
id: "pin_knob2/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob2"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 2.0
y: 2.0
z: 1.0
w: 1.0
}
size {
x: 36.0
y: 36.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/slider_move"
id: "pin_knob2/pin"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob2/root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 0.0
y: 13.5
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.2
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 17.0
y: 17.0
z: 0.0
w: 1.0
}
color {
x: 0.101960786
y: 0.101960786
z: 0.101960786
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/tick"
id: "pin_knob2/notch"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "pin_knob2/pin"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
x: 100.0
y: 154.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 120.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "50"
font: "game"
id: "text_value2"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
}
layers {
name: "image"
}
layers {
name: "text"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -1,49 +0,0 @@
local druid = require("druid.druid")
local pin_knob = require("druid.custom.pin_knob.pin_knob")
local function on_pin_change1(self, value)
self.text1:set_to(math.ceil(value))
end
local function on_pin_change2(self, value)
self.text2:set_to(math.ceil(value))
end
function init(self)
self.druid = druid.new(self)
self.text1 = self.druid:new_text("text_value1", 0)
---@type druid.pin_knob
self.pin_knob = self.druid:new(pin_knob, on_pin_change1, "pin_knob1")
self.pin_knob:set_angle(-10, -270, 270)
self.text2 = self.druid:new_text("text_value2", 0)
---@type druid.pin_knob
self.pin_knob2 = self.druid:new(pin_knob, on_pin_change2, "pin_knob2")
self.pin_knob2:set_angle(0, -90, 90)
self.pin_knob2:set_friction(0.15)
end
function final(self)
self.druid:final()
end
function update(self, dt)
self.druid:update(dt)
end
function on_message(self, message_id, message, sender)
self.druid:on_message(message_id, message, sender)
end
function on_input(self, action_id, action)
return self.druid:on_input(action_id, action)
end

File diff suppressed because it is too large Load Diff

View File

@@ -14,24 +14,15 @@ local component = require("druid.component")
---@field druid druid_instance
local ButtonComponent = component.create("button_component")
local SCHEME = {
ROOT = "root",
TEXT = "text",
ICON = "icon",
CHECKBOX = "checkbox"
}
---@param template string
---@param nodes table<hash, node>
function ButtonComponent:init(template, nodes)
self:set_template(template)
self:set_nodes(nodes)
self.druid = self:get_druid()
self.druid = self:get_druid(template, nodes)
self.root = self:get_node(SCHEME.ROOT)
self.text = self.druid:new_text(SCHEME.TEXT)
self.checkbox = self:get_node(SCHEME.CHECKBOX)
self.root = self:get_node("root")
self.text = self.druid:new_text("text")
self.checkbox = self:get_node("checkbox")
self.button = self.druid:new_button(self.root, self._on_click)

View File

@@ -1,5 +1,4 @@
local druid = require("druid.druid")
local sprite_style = require("druid.styles.sprites.style")
local function usual_callback()
@@ -52,9 +51,6 @@ end
local function setup_buttons(self)
self.druid:new_button("button_usual/button", usual_callback)
local custom_style = self.druid:new_button("button_custom_style/button", usual_callback)
custom_style:set_style(sprite_style)
local long_button = self.druid:new_button("button_long_tap/button", usual_callback)
long_button.on_hold_callback:subscribe(hold_callback)
long_button.on_long_click:subscribe(long_tap_callback)

View File

@@ -54,9 +54,10 @@ function init(self)
self.druid:new_scroll("children_scroll_3", "children_scroll_content_3")
-- Content with less size than view
self.druid:new_scroll("scroll_smaller_view", "scroll_smaller_content")
:set_extra_stretch_size(0)
:set_inert(false)
local small_scroll = self.druid:new_scroll("scroll_smaller_view", "scroll_smaller_content") --[[@as druid.scroll]]
small_scroll.style.SMALL_CONTENT_SCROLL = true
small_scroll:set_extra_stretch_size(0) -- it also update scroll size due the change of SMALL_CONTENT_SCROLL
small_scroll:set_inert(false)
-- Scroll with points of interests
self.druid:new_scroll("scroll_with_points", "scroll_with_points_content")

View File

@@ -1,4 +1,3 @@
script: ""
fonts {
name: "game"
font: "/example/assets/fonts/game.font"
@@ -7,423 +6,67 @@ textures {
name: "kenney"
texture: "/example/assets/images/kenney.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 600.0
y: 200.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_N
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 750.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 0.9411765
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Here is simple example with text"
font: "game"
id: "hint"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_N
outline {
x: 0.101960786
y: 0.101960786
z: 0.101960786
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.7
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
}
nodes {
position {
x: 0.0
y: -60.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 600.0
y: 130.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 0.9411765
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "area"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_N
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
}
nodes {
position {
x: 0.0
y: -65.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "rich_text"
parent: "area"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/druid/custom/rich_text/rich_text.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 130.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "rich_text/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_text"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
overridden_fields: 4
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 300.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.2
y: 0.2
z: 0.2
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Rich text"
font: "game"
id: "rich_text/text_prefab"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "rich_text/root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
overridden_fields: 1
overridden_fields: 4
overridden_fields: 5
overridden_fields: 14
overridden_fields: 18
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "items/checkmark"
id: "rich_text/icon_prefab"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_text/root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: true
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

File diff suppressed because it is too large Load Diff

View File

@@ -1,71 +1,76 @@
platforms:
armv7-ios:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, record, vpx, profilerext, liveupdate]
excludeSymbols: [ProfilerExt]
libs: [physics_null, record_null, profilerext_null, liveupdate_null]
excludeLibs: [liveupdate, physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, liveupdate_null, record_null]
linkFlags: []
arm64-ios:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, record, vpx, profilerext, liveupdate]
excludeSymbols: [ProfilerExt]
libs: [physics_null, record_null, profilerext_null, liveupdate_null]
excludeLibs: [liveupdate, physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, liveupdate_null, record_null]
linkFlags: []
x86_64-ios:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, record, vpx, profilerext, liveupdate]
excludeSymbols: [ProfilerExt]
libs: [physics_null, record_null, profilerext_null, liveupdate_null]
excludeLibs: [liveupdate, physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, liveupdate_null, record_null]
linkFlags: []
armv7-android:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, record, vpx, profilerext, liveupdate]
excludeLibs: [liveupdate, physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx]
excludeJars: []
excludeSymbols: [ProfilerExt]
libs: [physics_null, record_null, profilerext_null, liveupdate_null]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, liveupdate_null, record_null]
linkFlags: []
arm64-android:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, record, vpx, profilerext, liveupdate]
excludeLibs: [liveupdate, physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx]
excludeJars: []
excludeSymbols: [ProfilerExt]
libs: [physics_null, record_null, profilerext_null, liveupdate_null]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, liveupdate_null, record_null]
linkFlags: []
arm64-osx:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx, liveupdate]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, record_null, liveupdate_null]
x86_64-osx:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, record, vpx, profilerext, liveupdate]
excludeSymbols: [ProfilerExt]
libs: [physics_null, record_null, profilerext_null, liveupdate_null]
excludeLibs: [liveupdate, physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, liveupdate_null, record_null]
linkFlags: []
x86_64-linux:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, record, vpx, profilerext, liveupdate]
excludeSymbols: [ProfilerExt]
libs: [physics_null, record_null, profilerext_null, liveupdate_null]
excludeLibs: [liveupdate, physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, liveupdate_null, record_null]
linkFlags: []
x86-win32:
context:
excludeLibs: [libphysics, libLinearMath, libBulletDynamics, libBulletCollision, libBox2D, librecord, vpx, libprofilerext, libliveupdate]
excludeSymbols: [ProfilerExt]
libs: [libphysics_null.lib, librecord_null.lib, libprofilerext_null.lib, libliveupdate_null.lib]
excludeLibs: [libliveupdate, libphysics, libLinearMath, libBulletDynamics, libBulletCollision, libBox2D, libscript_box2d, librecord, vpx]
excludeSymbols: [ScriptBox2DExt]
libs: [libphysics_null.lib, libliveupdate_null.lib, librecord_null.lib]
linkFlags: []
x86_64-win32:
context:
excludeLibs: [libphysics, libLinearMath, libBulletDynamics, libBulletCollision, libBox2D, librecord, vpx, libprofilerext, libliveupdate]
excludeSymbols: [ProfilerExt]
libs: [libphysics_null.lib, librecord_null.lib, libprofilerext_null.lib, libliveupdate_null.lib]
excludeLibs: [libliveupdate, libphysics, libLinearMath, libBulletDynamics, libBulletCollision, libBox2D, libscript_box2d, librecord, vpx]
excludeSymbols: [ScriptBox2DExt]
libs: [libphysics_null.lib, libliveupdate_null.lib, librecord_null.lib]
linkFlags: []
js-web:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, record, vpx, profilerext, liveupdate]
excludeLibs: [liveupdate, physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx]
excludeJsLibs: []
excludeSymbols: [ProfilerExt]
libs: [physics_null, record_null, profilerext_null, liveupdate_null]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, liveupdate_null, record_null]
linkFlags: []
wasm-web:
context:
excludeLibs: [physics, LinearMath, BulletDynamics, BulletCollision, Box2D, record, vpx, profilerext, liveupdate]
excludeLibs: [liveupdate, physics, LinearMath, BulletDynamics, BulletCollision, Box2D, script_box2d, record, vpx]
excludeJsLibs: []
excludeSymbols: [ProfilerExt]
libs: [physics_null, record_null, profilerext_null, liveupdate_null]
excludeSymbols: [ScriptBox2DExt]
libs: [physics_null, liveupdate_null, record_null]
linkFlags: []

View File

@@ -1,5 +1,5 @@
[bootstrap]
main_collection = /example/example.collectionc
main_collection = /test/test.collectionc
[script]
shared_state = 1
@@ -15,7 +15,7 @@ high_dpi = 1
title = druid
version = 0.11.0
publisher = Insality
developer = Insality
developer = Maksim Tuprikov
dependencies#0 = https://github.com/insalitygames/deftest/archive/master.zip
dependencies#1 = https://github.com/britzl/monarch/archive/refs/tags/3.3.0.zip

BIN
media/druid_hero.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 492 KiB

BIN
media/druid_thumb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

View File

@@ -1,17 +1,17 @@
#!/bin/bash
# If true, it will check and download latest bob version. It will ignore bob_sha param
use_latest_bob=false
# Set patch (last value after dot) game version value as total git commits count (1.2.0 -> 1.2.{commits_count})
# You allow to get SHA commit from version via: git rev-list --all --reverse | sed -n {N}p
enable_incremental_version=true
# Path to bob folder. It will find and save new bob.jar files inside
bob_folder=./
# You can point bob version for project in format "filename:sha"
bob_sha="1.6.0:d9e9c49ab946c058f29a8b688c862d70f30e9c43"
bob_sha="181:fd1ad4c17bfdcd890ea7176f2672c35102384419"
# Select Defold channel. Values: stable, beta, alpha
bob_channel="stable"
# If true, it will check and download latest bob version. It will ignore bob_sha param
use_latest_bob=false
# Select Defold build server
build_server="https://build.defold.com"
# Is need to build html report
is_build_html_report=true

Some files were not shown because too many files have changed in this diff Show More