diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml
index 65cd61a..0a039c3 100644
--- a/.github/workflows/ci-workflow.yml
+++ b/.github/workflows/ci-workflow.yml
@@ -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)
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 8e0296c..690997a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,8 @@ Thumbs.db
builtins
dist
deployer_version_settings.txt
+
.deployer_cache
+bob*.jar
+manifest.private.der
+manifest.public.der
\ No newline at end of file
diff --git a/.luacheckrc b/.luacheckrc
deleted file mode 100644
index f9c6bc5..0000000
--- a/.luacheckrc
+++ /dev/null
@@ -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",
-}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..44850ee
--- /dev/null
+++ b/.vscode/settings.json
@@ -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"
+ ]
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 329ab66..760392e 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
[](https://insality.github.io/druid/)
-[](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](https://www.buymeacoffee.com/insality)
+[](https://github.com/Insality/druid/tags)
+[](https://github.com/Insality/druid/actions)
+[](https://codecov.io/gh/Insality/druid)
-[](https://github.com/Insality/druid/releases)
-[](https://github.com/Insality/druid/actions)
-[](https://codecov.io/gh/Insality/druid)
+[](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](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) | |
| **[Timer](https://insality.github.io/druid/modules/Timer.html)** | Logic over GUI Text. Handle basic timer functions. | ❌ | |
| **[Hotkey](https://insality.github.io/druid/modules/Hotkey.html)** | Allow to set callbacks for keyboard hotkeys with key modificators. | [Hotkey Example](https://insality.github.io/druid/druid/?example=general_hotkey) | |
-| **[Layout](https://insality.github.io/druid/modules/Layout.html)** | Logic over GUI Node. Handle node size depends on layout mode and screen aspect ratio. Contains helpers to build more complex UI layout. | [Layout Example](https://insality.github.io/druid/druid/?example=general_layout) | |
+| **[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) | |
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:
@@ -214,4 +220,4 @@ For a complete history of the development of **Druid**, please check the [change
Your donation helps me stay engaged in creating valuable projects for **Defold**. If you appreciate what I'm doing, please consider supporting me!
-[](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](https://www.buymeacoffee.com/insality)
+[](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](https://www.buymeacoffee.com/insality)
\ No newline at end of file
diff --git a/config.ld b/config.ld
index 1a295b1..a487ec9 100644
--- a/config.ld
+++ b/config.ld
@@ -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",
diff --git a/deployer_build_stats.csv b/deployer_build_stats.csv
index 8643758..9960c84 100644
--- a/deployer_build_stats.csv
+++ b/deployer_build_stats.csv
@@ -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
diff --git a/docs/modules/BackHandler.html b/docs/modules/BackHandler.html
index 50d2bc5..df93b56 100644
--- a/docs/modules/BackHandler.html
+++ b/docs/modules/BackHandler.html
@@ -147,9 +147,8 @@ local back_handler = self.druid:new_back_handler(callback, [params])
params
- any
+ any or nil
- (optional )
diff --git a/docs/modules/BaseComponent.html b/docs/modules/BaseComponent.html
index 1c81617..4d4d649 100644
--- a/docs/modules/BaseComponent.html
+++ b/docs/modules/BaseComponent.html
@@ -106,7 +106,7 @@ return AwesomeComponent
Context used as first arg in all Druid events
- get_druid(self)
+ get_druid(self, template, nodes)
Get Druid instance for inner component creation.
@@ -226,7 +226,7 @@ return AwesomeComponent
- get_druid(self)
+ get_druid(self, template, nodes)
Get Druid instance for inner component creation.
@@ -238,6 +238,14 @@ return AwesomeComponent
BaseComponent
BaseComponent
+ template
+ string or nil
+ The template name
+
+ nodes
+ table or nil
+ The nodes table
+
Returns:
diff --git a/docs/modules/Button.html b/docs/modules/Button.html
index 2a0def6..a451bac 100644
--- a/docs/modules/Button.html
+++ b/docs/modules/Button.html
@@ -97,7 +97,7 @@
print("Also the button component is passed in callback params")
end
-local custom_args = "any variable to pass inside callback"
+local custom_args = "Any variable to pass inside callback"
local button = self.druid:new_button("button_name", on_button_click, custom_args)
@@ -153,7 +153,7 @@ local button = self.druid:new_button("button_name", on_button_click, c
click_zone
- Additional button click area, defined by another GUI Node
+ Additional button click area, defined by another GUI node
hover
@@ -360,7 +360,7 @@ local button = self.druid:new_button("button_name", on_button_click, c
Button
zone
- node or nil
+ node , string or nil
Gui node
@@ -433,7 +433,7 @@ button:set_enabled(true )
Button
key
- hash
+ hash or string
The action_id of the input key
@@ -508,19 +508,16 @@ button:set_enabled(true )
Fields:
LONGTAP_TIME
- number
- Minimum time to trigger on_hold_callback
- (default 0.4)
+ number or nil
+ Minimum time to trigger on_hold_callback. Default: 0.4
AUTOHOLD_TRIGGER
- number
- Maximum hold time to trigger button release while holding
- (default 0.8)
+ number or nil
+ Maximum hold time to trigger button release while holding. Default: 0.8
DOUBLETAP_TIME
- number
- Time between double taps
- (default 0.4)
+ number or nil
+ Time between double taps. Default: 0.4
on_click
function
@@ -565,9 +562,8 @@ button:set_enabled(true )
anim_node
- node
-
- (default node)
+ node or nil
+ Default node
@@ -581,14 +577,13 @@ button:set_enabled(true )
click_zone
- Additional button click area, defined by another GUI Node
+ Additional button click area, defined by another GUI node
click_zone
- node
+ node or nil
- (optional )
diff --git a/docs/modules/Checkbox.html b/docs/modules/Checkbox.html
index 8ac33c6..57e1d53 100644
--- a/docs/modules/Checkbox.html
+++ b/docs/modules/Checkbox.html
@@ -87,7 +87,7 @@
Return checkbox state
- init(self, node, callback[, click_node=node[, initial_state=false]])
+ init(self, node, callback, click_node, initial_state)
The Checkbox constructor
@@ -158,7 +158,7 @@
- init(self, node, callback[, click_node=node[, initial_state=false]])
+ init(self, node, callback, click_node, initial_state)
The Checkbox constructor
@@ -179,14 +179,12 @@
Checkbox callback
click_node
- node
- Trigger node, by default equals to node
- (default node)
+ node or nil
+ Trigger node, by default equals to node. Default: node
initial_state
- boolean
+ boolean or nil
The initial state of checkbox, default - false
- (default false)
@@ -289,9 +287,8 @@
click_node
- node
+ node or nil
- (default node)
diff --git a/docs/modules/CheckboxGroup.html b/docs/modules/CheckboxGroup.html
index 8551324..3a3914b 100644
--- a/docs/modules/CheckboxGroup.html
+++ b/docs/modules/CheckboxGroup.html
@@ -86,7 +86,7 @@
Return checkbox group state
- init(self, nodes, callback[, click_nodes=node])
+ init(self, nodes, callback, click_nodes)
The CheckboxGroup constructor
@@ -142,7 +142,7 @@
- init(self, nodes, callback[, click_nodes=node])
+ init(self, nodes, callback, click_nodes)
The CheckboxGroup constructor
@@ -163,9 +163,8 @@
Checkbox callback
click_nodes
- node[]
+ node[] or nil
Array of trigger nodes, by default equals to nodes
- (default node)
diff --git a/docs/modules/DataList.html b/docs/modules/DataList.html
index 8003f36..68df37a 100644
--- a/docs/modules/DataList.html
+++ b/docs/modules/DataList.html
@@ -83,6 +83,10 @@
+
+ add(self, data, index, shift_policy)
+ Add element to DataList.
+
clear(self)
Clear the DataList and refresh visuals
@@ -100,22 +104,10 @@
Return current data from DataList component
- get_first_index(self)
- Return first index from data.
-
-
get_index(self, data)
Return index for data value
- get_last_index(self)
- Return last index from data
-
-
- get_length(self)
- Return amount of data
-
-
init(self, scroll, grid, create_function)
The DataList constructor
@@ -124,6 +116,14 @@
Druid System on_remove function
+ remove(self, index, shift_policy)
+ Remove element from DataList.
+
+
+ remove_by_data(self, data, shift_policy)
+ Remove element from DataList by data value.
+
+
scroll_to_index(self, index)
Instant scroll to element with passed index
@@ -131,6 +131,10 @@
set_data(self, data)
Set new data set for DataList component
+
+ set_use_cache(self, is_use_cache)
+ Set refresh function for DataList component
+
@@ -140,7 +144,7 @@
last_index
- The current visual last data index
+ The current last index of visual elements
on_element_add
@@ -164,7 +168,7 @@
top_index
- The current visual top data index
+ The current top index of visual elements
@@ -175,6 +179,39 @@
+
+
+ add(self, data, index, shift_policy)
+
+
+ Add element to DataList. Currenly untested
+
+
+ Parameters:
+
+ self
+ DataList
+ DataList
+
+ data
+ table
+
+
+ index
+ number or nil
+
+
+ shift_policy
+ number or nil
+ The constant from const.SHIFT.*
+
+
+
+
+
+
+
+
clear(self)
@@ -276,27 +313,6 @@
-
-
-
- get_first_index(self)
-
-
- Return first index from data. It not always equals to 1
-
-
- Parameters:
-
-
-
-
-
-
@@ -322,48 +338,6 @@
-
-
-
- get_last_index(self)
-
-
- Return last index from data
-
-
- Parameters:
-
-
-
-
-
-
-
-
-
- get_length(self)
-
-
- Return amount of data
-
-
- Parameters:
-
-
-
-
-
-
@@ -418,6 +392,64 @@
+
+
+
+ remove(self, index, shift_policy)
+
+
+ Remove element from DataList. Currenly untested
+
+
+ Parameters:
+
+ self
+ DataList
+ DataList
+
+ index
+ number or nil
+
+
+ shift_policy
+ number or nil
+ The constant from const.SHIFT.*
+
+
+
+
+
+
+
+
+
+
+ remove_by_data(self, data, shift_policy)
+
+
+ Remove element from DataList by data value. Currenly untested
+
+
+ Parameters:
+
+ self
+ DataList
+ DataList
+
+ data
+ table
+
+
+ shift_policy
+ number or nil
+ The constant from const.SHIFT.*
+
+
+
+
+
+
+
@@ -474,6 +506,37 @@
+
+
+
+ set_use_cache(self, is_use_cache)
+
+
+ Set refresh function for DataList component
+
+
+ Parameters:
+
+ self
+ DataList
+ DataList
+
+ 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
+
+
+
+ Returns:
+
+
+ druid.data_list
+ Current DataList instance
+
+
+
+
+
@@ -504,7 +567,7 @@
last_index
- The current visual last data index
+ The current last index of visual elements
@@ -624,7 +687,7 @@
top_index
- The current visual top data index
+ The current top index of visual elements
+ node
+ Drag node
+
+
on_drag
- on drag progress callback(self, dx, dy, total_x, total_y)
+ on drag progress callback(self, dx, dy, total_x, total_y, touch)
on_drag_end
- Event on drag end callback(self, total_x, total_y)
+ Event on drag end callback(self, total_x, total_y, touch)
on_drag_start
- Event on drag start callback(self)
+ Event on drag start callback(self, touch)
on_touch_end
@@ -149,6 +153,14 @@
Event on touch start callback(self)
+ screen_x
+ Current touch x screen position
+
+
+ screen_y
+ Current touch y screen position
+
+
touch_start_pos
Touch start position
@@ -184,7 +196,7 @@
Drag
node
- node
+ node
GUI node to detect dragging
on_drag_callback
@@ -241,7 +253,7 @@
Drag
node
- node
+ node , string or nil
Gui node
@@ -293,14 +305,12 @@
Fields:
DRAG_DEADZONE
- number
- Distance in pixels to start dragging
- (default 10)
+ number or nil
+ Distance in pixels to start dragging. Default: 10
NO_USE_SCREEN_KOEF
- boolean
- If screen aspect ratio affects on drag values
- (default false)
+ boolean or nil
+ If screen aspect ratio affects on drag values. Default: false
@@ -392,13 +402,33 @@
+
+
+
+ node
+
+
+ Drag node
+
+
+
+
+
+
+
+
on_drag
- on drag progress callback(self, dx, dy, total_x, total_y)
+ on drag progress callback(self, dx, dy, total_x, total_y, touch)
+
+
+
+
+ is_empty(self)
+
+
+ Return true, if event not have handler
+
+
+ Parameters:
+
+
+ Returns:
+
+
+ boolean
+ True if event not have handlers
+
+
+
+
+ Usage:
+ local is_long_click_handler_not_exists = button.on_long_click:is_empty()
@@ -201,10 +240,45 @@
local is_long_click_handler_exists = button.on_long_click:is_exist()
+
+
+
+ is_subscribed(self, callback, callback_context)
+
+
+ Check is event subscribed.
+
+
+ Parameters:
+
+ self
+ DruidEvent
+ DruidEvent
+
+ callback
+ function
+ Callback itself
+
+ callback_context
+ any or nil
+ Additional context as first param to callback call
+
+
+
+ Returns:
+
+
+ boolean,
+ number|nil @Is event subscribed, return index of callback in event as second param
+
+
+
+
+
- subscribe(self, callback, context)
+ subscribe(self, callback, callback_context)
Subscribe callback on event
@@ -220,12 +294,18 @@
function
Callback itself
- context
+ callback_context
any or nil
Additional context as first param to callback call, usually it's self
+ Returns:
+
+
+ boolean
+ True if callback was subscribed
+
@@ -274,7 +354,7 @@ event:trigger("Param1" , "Param2
- unsubscribe(self, callback, context)
+ unsubscribe(self, callback, callback_context)
Unsubscribe callback on event
@@ -290,7 +370,7 @@ event:trigger("Param1" , "Param2
function
Callback itself
- context
+ callback_context
any or nil
Additional context as first param to callback call
diff --git a/docs/modules/DruidInstance.html b/docs/modules/DruidInstance.html
index 2e0ae35..5007e3c 100644
--- a/docs/modules/DruidInstance.html
+++ b/docs/modules/DruidInstance.html
@@ -142,10 +142,6 @@ end
Call this in gui_script final function.
- new(self, component, ...)
- Create new component.
-
-
new_back_handler(self, callback, params)
Create BackHandler component
@@ -162,7 +158,7 @@ end
Create Checkbox component
- new_checkbox_group(self, nodes, callback[, click_nodes=node])
+ new_checkbox_group(self, nodes, callback, click_nodes)
Create CheckboxGroup component
@@ -182,7 +178,7 @@ end
Create Hotkey component
- new_hover(self, node, on_hover_callback)
+ new_hover(self, node, on_hover_callback, on_mouse_hover_callback)
Create Hover component
@@ -202,7 +198,7 @@ end
Create Progress component
- new_radio_group(self, nodes, callback[, click_nodes=node])
+ new_radio_group(self, nodes, callback, click_nodes)
Create RadioGroup component
@@ -246,11 +242,11 @@ end
Remove created component from Druid instance.
- set_blacklist(self[, blacklist_components=nil])
+ set_blacklist(self, blacklist_components)
Set blacklist components for input processing.
- set_whitelist(self[, whitelist_components=nil])
+ set_whitelist(self, whitelist_components)
Set whitelist components for input processing.
@@ -286,41 +282,6 @@ end
-
-
-
- new(self, component, ...)
-
-
- Create new component.
-
-
- Parameters:
-
- self
- DruidInstance
-
-
- component
- BaseComponent
- Component module
-
- ...
- any
- Other component params to pass it to component:init function
-
-
-
- Returns:
-
-
- BaseComponent
- Component instance
-
-
-
-
-
@@ -411,11 +372,11 @@ end
Button callback
params
- table or nil
+ any or nil
Button callback params
anim_node
- node or nil
+ node , string or nil
Button anim node (node, if not provided)
@@ -476,7 +437,7 @@ end
- new_checkbox_group(self, nodes, callback[, click_nodes=node])
+ new_checkbox_group(self, nodes, callback, click_nodes)
Create CheckboxGroup component
@@ -489,7 +450,7 @@ end
nodes
- node[]
+ (node or string)[]
Array of gui node
callback
@@ -497,9 +458,8 @@ end
Checkbox callback
click_nodes
- node[]
+ (node , string)[] or nil
Array of trigger nodes, by default equals to nodes
- (default node)
@@ -660,7 +620,7 @@ end
- new_hover(self, node, on_hover_callback)
+ new_hover(self, node, on_hover_callback, on_mouse_hover_callback)
Create Hover component
@@ -680,6 +640,10 @@ end
function or nil
Hover callback
+ on_mouse_hover_callback
+ function or nil
+ Mouse hover callback
+
Returns:
@@ -712,7 +676,7 @@ end
Button node to enabled input component
text_node
- string or node
+ string , node or druid.text
Text node what will be changed on user input
keyboard_type
@@ -847,7 +811,7 @@ end
- new_radio_group(self, nodes, callback[, click_nodes=node])
+ new_radio_group(self, nodes, callback, click_nodes)
Create RadioGroup component
@@ -860,7 +824,7 @@ end
nodes
- node[]
+ (node or string)[]
Array of gui node
callback
@@ -868,9 +832,8 @@ end
Radio callback
click_nodes
- node[]
+ (node , string)[] or nil
Array of trigger nodes, by default equals to nodes
- (default node)
@@ -1211,7 +1174,7 @@ end
Message from on_message
sender
- hash
+ url
Sender from on_message
@@ -1242,6 +1205,12 @@ end
+ Returns:
+
+
+ boolean
+ True if component was removed
+
@@ -1249,7 +1218,7 @@ end
- set_blacklist(self[, blacklist_components=nil])
+ set_blacklist(self, blacklist_components)
Set blacklist components for input processing.
@@ -1264,9 +1233,8 @@ end
DruidInstance
blacklist_components
- table or BaseComponent
+ table , BaseComponent or nil
The array of component to blacklist
- (default nil)
@@ -1283,7 +1251,7 @@ end
- set_whitelist(self[, whitelist_components=nil])
+ set_whitelist(self, whitelist_components)
Set whitelist components for input processing.
@@ -1298,9 +1266,8 @@ end
whitelist_components
- table or BaseComponent
+ table , BaseComponent or nil
The array of component to whitelist
- (default nil)
diff --git a/docs/modules/DynamicGrid.html b/docs/modules/DynamicGrid.html
index 2f6677f..52d8458 100644
--- a/docs/modules/DynamicGrid.html
+++ b/docs/modules/DynamicGrid.html
@@ -420,7 +420,7 @@
vector3
- Node position
+ node position
diff --git a/docs/modules/Helper.html b/docs/modules/Helper.html
index 2ede020..f465d57 100644
--- a/docs/modules/Helper.html
+++ b/docs/modules/Helper.html
@@ -151,10 +151,18 @@ helper.centrate_nodes(0, node_1, node_2)
Check if device is native mobile (Android or iOS)
+ helper.is_multitouch_supported()
+ Check if device is mobile and can support multitouch
+
+
helper.is_web()
Check if device is HTML5
+ helper.is_web_mobile()
+ Check if device is HTML5 mobile
+
+
helper.lerp(a, b, t)
Lerp between two values
@@ -658,6 +666,26 @@ helper.centrate_nodes(0, node_1, node_2)
+
+
+
+ helper.is_multitouch_supported()
+
+
+ Check if device is mobile and can support multitouch
+
+
+
+ Returns:
+
+
+ boolean
+ Is multitouch supported
+
+
+
+
+
@@ -678,6 +706,26 @@ helper.centrate_nodes(0, node_1, node_2)
+
+
+
+ helper.is_web_mobile()
+
+
+ Check if device is HTML5 mobile
+
+
+
+ Returns:
+
+
+ boolean
+ Is web mobile
+
+
+
+
+
diff --git a/docs/modules/Hotkey.html b/docs/modules/Hotkey.html
index 3cd5a00..68e4015 100644
--- a/docs/modules/Hotkey.html
+++ b/docs/modules/Hotkey.html
@@ -90,6 +90,10 @@
init(self, keys, callback, callback_argument)
The Hotkey constructor
+
+ set_repeat(self, is_enabled_repeated)
+ If true, the callback will be triggered on action.repeated
+
@@ -192,6 +200,37 @@
+
+
+
+ set_repeat(self, is_enabled_repeated)
+
+
+ If true, the callback will be triggered on action.repeated
+
+
+ Parameters:
+
+ self
+ Hotkey
+ Hotkey
+
+ is_enabled_repeated
+ bool
+ The flag value
+
+
+
+ Returns:
+
+
+ Hotkey
+
+
+
+
+
+
@@ -254,9 +293,8 @@
click_node
- node
+ node or nil
- (default node)
@@ -286,15 +324,35 @@
-
- on_change_state
+
+ on_hotkey_pressed
- On change state callback(self, state)
+ On hotkey released callback(self, argument)
- on_change_state
+ on_hotkey_pressed
+ DruidEvent
+ DruidEvent
+
+
+
+
+
+
+
+
+
+
+ on_hotkey_released
+
+
+ On hotkey released callback(self, argument)
+
+
+
+
+
+ get_text_selected_replaced(self, text)
+
+
+ Replace selected text with new text
+
+
+ Parameters:
+
+ self
+ Input
+ Input
+
+ text
+ string
+ The text to replace selected text
+
+
+
+ Returns:
+
+
+ string
+ New input text
+
+
+
+
+
@@ -250,6 +333,39 @@
+
+
+
+ move_selection(self, delta, is_add_to_selection, is_move_to_end)
+
+
+ Change cursor position by delta
+
+
+ Parameters:
+
+ self
+ Input
+ Input
+
+ delta
+ number
+ side for cursor position, -1 for left, 1 for right
+
+ is_add_to_selection
+ boolean
+ (Shift key)
+
+ is_move_to_end
+ boolean
+ (Ctrl key)
+
+
+
+
+
+
+
@@ -267,6 +383,12 @@
+ Returns:
+
+
+ druid.input
+ Current input instance
+
@@ -292,6 +414,45 @@
+
+
+
+ select_cursor(self, cursor_index, start_index, end_index)
+
+
+ Set cursor position in input field
+
+
+ Parameters:
+
+ self
+ Input
+ Input
+
+ cursor_index
+ number or nil
+ Cursor index for cursor position, if nil - will be set to the end of the text
+
+ start_index
+ number or nil
+ Start index for cursor position, if nil - will be set to the end of the text
+
+ end_index
+ number or nil
+ End index for cursor position, if nil - will be set to the start_index
+
+
+
+ Returns:
+
+
+ druid.input
+ Current input instance
+
+
+
+
+
@@ -422,23 +583,15 @@
IS_LONGTAP_ERASE
boolean
- Is long tap will erase current input data
- (default false)
+ Is long tap will erase current input data. Default: false
MASK_DEFAULT_CHAR
string
- Default character mask for password input
- (default *)
+ Default character mask for password input. Default: *]
IS_UNSELECT_ON_RESELECT
boolean
- If true, call unselect on select selected input
- (default false)
-
- 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)
- (default false)
+ If true, call unselect on select selected input. Default: false
on_select
function
@@ -477,9 +630,8 @@
@@ -507,6 +659,66 @@
+
+
+
+ current_value
+
+
+ Current input value with marked text
+
+
+
+ current_value
+ string
+
+
+
+
+
+
+
+
+
+
+
+ cursor_index
+
+
+ The cursor index. The index of letter cursor after. Leftmost cursor - 0
+
+
+
+ cursor_index
+ number
+
+
+
+
+
+
+
+
+
+
+
+ end_index
+
+
+ Theselection end index. The index of letter cursor before. Rightmost selection - #text
+
+
+
+ end_index
+ number
+
+
+
+
+
+
+
+
@@ -567,6 +779,46 @@
+
+
+
+ marked_text_width
+
+
+ Marked text width
+
+
+
+ marked_text_width
+ number
+
+
+
+
+
+
+
+
+
+
+
+ marked_value
+
+
+ Marked text for input field. Info: https://defold.com/manuals/input-key-and-text/#marked-text
+
+
+
+
+
+
+
+
@@ -578,9 +830,8 @@
max_length
- number
+ number or nil
- (optional )
@@ -634,7 +885,7 @@
on_input_select
- On input field select callback(self, button_node)
+ On input field select callback(self, input_instance)
@@ -674,7 +925,7 @@
on_input_unselect
- On input field unselect callback(self, input_text)
+ On input field unselect callback(self, input_text, input_instance)
@@ -694,7 +945,7 @@
on_input_wrong
- 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)
+
+
+ on_select_cursor_change
+
+
+ On cursor position change callback(self, cursor_index, start_index, end_index)
+
+
+
+ on_select_cursor_change
+ DruidEvent
+ DruidEvent
+
+
+
+
+
+
+
+
+
+
+ previous_value
+
+
+ Previous input value
+
+
+
+ previous_value
+ string
+
+
+
+
+
+
+
+
+
+
+
+ start_index
+
+
+ The selection start index. The index of letter cursor after. Leftmost selection - 0
+
+
+
+ start_index
+ number
+
+
+
+
+
+
+
+
@@ -728,6 +1039,46 @@
+
+
+
+ text_width
+
+
+ Text width
+
+
+
+ text_width
+ number
+
+
+
+
+
+
+
+
+
+
+
+ value
+
+
+ Current input value
+
+
+
+
+
+
+
+
diff --git a/docs/modules/LangText.html b/docs/modules/LangText.html
index 2099832..0d02aba 100644
--- a/docs/modules/LangText.html
+++ b/docs/modules/LangText.html
@@ -93,7 +93,7 @@
Format string with new text params on localized text
- init(self, node[, locale_id=node_text[, adjust_type=downscale]])
+ init(self, node, locale_id, adjust_type)
The LangText constructor
@@ -185,7 +185,7 @@
- init(self, node[, locale_id=node_text[, adjust_type=downscale]])
+ init(self, node, locale_id, adjust_type)
The LangText constructor
@@ -202,14 +202,12 @@
The node_id or gui.get_node(node_id)
locale_id
- string
+ string or nil
Default locale id or text from node as default
- (default node_text)
adjust_type
- string
+ string or nil
Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
- (default downscale)
diff --git a/docs/modules/Layout.html b/docs/modules/Layout.html
index edad2b6..c8f4140 100644
--- a/docs/modules/Layout.html
+++ b/docs/modules/Layout.html
@@ -32,7 +32,6 @@
Contents
@@ -79,45 +78,6 @@
Example Link
-
-
-
- fit_into_node(self, node)
- Set node for layout node to fit inside it.
-
-
- fit_into_size(self, target_size)
- Set size for layout node to fit inside it
-
-
- fit_into_window(self)
- Set current size for layout node to fit inside it
-
-
- init(self, node, mode, on_size_changed_callback)
- The Layout constructor
-
-
- set_max_gui_upscale(self, max_gui_upscale)
- Set max gui upscale for FIT adjust mode (or side).
-
-
- set_max_size(self, max_size)
- Set maximum size of layout node
-
-
- set_min_size(self, min_size)
- Set minimal size of layout node
-
-
- set_origin_position(self, new_origin_position)
- Set new origin position of layout node.
-
-
- set_origin_size(self, new_origin_size)
- Set new origin size of layout node.
-
-
@@ -128,297 +88,12 @@
node
Layout node
-
- on_size_changed
- On window resize callback(self, new_size)
-
-
-
-
-
-
- fit_into_node(self, node)
-
-
- Set node for layout node to fit inside it. Pass nil to reset
-
-
- Parameters:
-
- self
- Layout
- Layout
-
- node
- node or nil
-
-
-
-
- Returns:
-
-
- Layout
- Layout
-
-
-
-
-
-
-
-
- fit_into_size(self, target_size)
-
-
- Set size for layout node to fit inside it
-
-
- Parameters:
-
- self
- Layout
- Layout
-
- target_size
- vector3
-
-
-
-
- Returns:
-
-
- Layout
- Layout
-
-
-
-
-
-
-
-
- fit_into_window(self)
-
-
- Set current size for layout node to fit inside it
-
-
- Parameters:
-
-
- Returns:
-
-
- Layout
- Layout
-
-
-
-
-
-
-
-
- init(self, node, mode, on_size_changed_callback)
-
-
- The Layout constructor
-
-
- Parameters:
-
- self
- Layout
- Layout
-
- node
- node
- Gui node
-
- mode
- string
- The layout mode (from const.LAYOUT_MODE)
-
- on_size_changed_callback
- function or nil
- The callback on window resize
-
-
-
-
-
-
-
-
-
-
- set_max_gui_upscale(self, max_gui_upscale)
-
-
- Set max gui upscale for FIT adjust mode (or side). It happens on bigger render gui screen
-
-
- Parameters:
-
- self
- Layout
- Layout
-
- max_gui_upscale
- number
-
-
-
-
- Returns:
-
-
- Layout
- Layout
-
-
-
-
-
-
-
-
- set_max_size(self, max_size)
-
-
- Set maximum size of layout node
-
-
- Parameters:
-
- self
- Layout
- Layout
-
- max_size
- vector3
-
-
-
-
- Returns:
-
-
- Layout
- Layout
-
-
-
-
-
-
-
-
- set_min_size(self, min_size)
-
-
- Set minimal size of layout node
-
-
- Parameters:
-
- self
- Layout
- Layout
-
- min_size
- vector3
-
-
-
-
- Returns:
-
-
- Layout
- Layout
-
-
-
-
-
-
-
-
- set_origin_position(self, new_origin_position)
-
-
- Set new origin position of layout node. You should apply this on node movement
-
-
- Parameters:
-
- self
- Layout
- Layout
-
- new_origin_position
- vector3
-
-
-
-
- Returns:
-
-
- Layout
- Layout
-
-
-
-
-
-
-
-
- set_origin_size(self, new_origin_size)
-
-
- Set new origin size of layout node. You should apply this on node manual size change
-
-
- Parameters:
-
- self
- Layout
- Layout
-
- new_origin_size
- vector3
-
-
-
-
- Returns:
-
-
- Layout
- Layout
-
-
-
-
-
-
-
@@ -461,26 +136,6 @@
-
-
-
- on_size_changed
-
-
- On window resize callback(self, new_size)
-
-
-
-
-
-
-
-
diff --git a/docs/modules/PinKnob.html b/docs/modules/PinKnob.html
index 6e58444..d97d64e 100644
--- a/docs/modules/PinKnob.html
+++ b/docs/modules/PinKnob.html
@@ -91,7 +91,7 @@
Set current and min/max angles for component
- set_friction(self[, value=1])
+ set_friction(self, value)
Set current and min/max angles for component
@@ -192,7 +192,7 @@
- set_friction(self[, value=1])
+ set_friction(self, value)
Set current and min/max angles for component
@@ -205,9 +205,8 @@
PinKnob
value
- number
- The spin speed multiplier
- (default 1)
+ number or nil
+ The spin speed multiplier. Default: 1
diff --git a/docs/modules/Progress.html b/docs/modules/Progress.html
index b72ba4f..cec8988 100644
--- a/docs/modules/Progress.html
+++ b/docs/modules/Progress.html
@@ -103,7 +103,7 @@
Return current progress bar value
- init(self, node, key[, init_value=1])
+ init(self, node, key, init_value)
The Progress constructor
@@ -234,7 +234,7 @@
- init(self, node, key[, init_value=1])
+ init(self, node, key, init_value)
The Progress constructor
@@ -255,9 +255,8 @@
Progress bar direction: const.SIDE.X or const.SIDE.Y
init_value
- number
- Initial value of progress bar
- (default 1)
+ number or nil
+ Initial value of progress bar. Default: 1
@@ -401,14 +400,12 @@
Fields:
SPEED
- number
- Progress bas fill rate. More -> faster
- (default 5)
+ number or nil
+ Progress bas fill rate. More -> faster. Default: 5
MIN_DELTA
- number
- Minimum step to fill progress bar
- (default 0.005)
+ number or nil
+ Minimum step to fill progress bar. Default: 0.005
diff --git a/docs/modules/RadioGroup.html b/docs/modules/RadioGroup.html
index 95b3e24..7445394 100644
--- a/docs/modules/RadioGroup.html
+++ b/docs/modules/RadioGroup.html
@@ -86,7 +86,7 @@
Return radio group state
- init(self, nodes, callback[, click_nodes=node])
+ init(self, nodes, callback, click_nodes)
The RadioGroup constructor
@@ -142,7 +142,7 @@
- init(self, nodes, callback[, click_nodes=node])
+ init(self, nodes, callback, click_nodes)
The RadioGroup constructor
@@ -163,9 +163,8 @@
Radio callback
click_nodes
- node[]
- Array of trigger nodes, by default equals to nodes
- (default node)
+ node[] or nil
+ Array of trigger nodes, by default equals to nodes. Default - nodes
diff --git a/docs/modules/RichInput.html b/docs/modules/RichInput.html
index c8d62dc..0c70936 100644
--- a/docs/modules/RichInput.html
+++ b/docs/modules/RichInput.html
@@ -84,20 +84,32 @@
@@ -135,7 +147,7 @@
get_text(self)
- GSet input field text
+ Set input field text
Parameters:
@@ -146,12 +158,6 @@
- Returns:
-
-
- string
- Current input text
-
@@ -185,6 +191,27 @@
+
+
+
+ select(self)
+
+
+ Select input field
+
+
+ Parameters:
+
+
+
+
+
+
@@ -218,6 +245,37 @@
+
+
+
+ set_font(self, font)
+
+
+ Set input field font
+
+
+ Parameters:
+
+ self
+ RichInput
+ RichInput
+
+ font
+ hash
+ The font hash
+
+
+
+ Returns:
+
+
+ druid.input
+ Current input instance
+
+
+
+
+
@@ -234,16 +292,41 @@
RichInput
placeholder_text
- string or nil
+ string
The placeholder text
+
+
+
+
+
+
+
+ set_text(self, text)
+
+
+ Set input field text
+
+
+ Parameters:
+
+
Returns:
- RichInput
- Current instance
+ druid.input
+ Current input instance
diff --git a/docs/modules/RichText.html b/docs/modules/RichText.html
index 372c37e..ec185a8 100644
--- a/docs/modules/RichText.html
+++ b/docs/modules/RichText.html
@@ -81,19 +81,7 @@
# Overview #
This custom component is inspired by defold-richtext by britzl.
It uses a similar syntax for tags but currently supports fewer tags.
-
All parameters for the Rich Text component are adjusted in the GUI scene.
-
This component uses GUI component template. (/druid/custom/rich_text/rich_text.gui).
-
You able to customize it or make your own with the next node scructure:
-
root
-
- text_prefab
-
- icon_prefab
-
# Rich Text Setup #
-
• Root node size: Set the maximum width and height of the text.
-
• Root anchor: Define the alignment of the Rich Text inside the root node size area.
-
• Text prefab: Configure all default text parameters for the text node.
-
• Text prefab anchor: Set the anchor for each text node (adjust this only if animating text).
-
• Icon prefab: Configure all default node parameters for the icon node.
-
• Icon prefab anchor: Set the anchor for each icon node (adjust this only if animating the icon).
+
Create Rich Text on your GUI Text Node. All properties of the text node will be used as default for the text.
# Notes #
• Nested tags are supported
Example Link
@@ -119,7 +107,6 @@ self.rich_text:set_text("Hello, Druid Rich Text!")
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 = {
+
+ characters(self, word)
+ Split a word into it's characters
+
clear()
Clear all created words.
@@ -159,11 +150,15 @@ type druid.rich_text.metrics = {
Get current line metrics
+ get_text(self)
+ Get current text
+
+
get_words()
Get all current words.
- init(self, template, nodes)
+ init(self, text_node, value)
The RichText constructor
@@ -171,7 +166,7 @@ type druid.rich_text.metrics = {
Set text for Rich Text
- tagged(tag)
+ tagged(self, tag)
Get all words, which has a passed tag.
@@ -188,6 +183,18 @@ type druid.rich_text.metrics = {
druid
The component druid instance
+
+ icon_prefab
+ The icon prefab node
+
+
+ root
+ The root node of the Rich Text
+
+
+ text_prefab
+ The text prefab node
+
@@ -197,6 +204,37 @@ type druid.rich_text.metrics = {
+
+
+ characters(self, word)
+
+
+ Split a word into it's characters
+
+
+ Parameters:
+
+ self
+ RichText
+ RichText
+
+ word
+ druid.rich_text.word
+
+
+
+
+ Returns:
+
+
+ druid.rich_text.word[]
+ characters
+
+
+
+
+
+
clear()
@@ -230,6 +268,33 @@ type druid.rich_text.metrics = {
+
+
+
+ get_text(self)
+
+
+ Get current text
+
+
+ Parameters:
+
+
+ Returns:
+
+
+ string
+ text
+
+
+
+
+
@@ -253,7 +318,7 @@ type druid.rich_text.metrics = {
- init(self, template, nodes)
+ init(self, text_node, value)
The RichText constructor
@@ -265,13 +330,13 @@ type druid.rich_text.metrics = {
RichText
RichText
- template
- string
- The Rich Text template name
+ text_node
+ node or string
+ The text node to make Rich Text
- nodes
- table
- The node table, if prefab was copied by gui.clone_tree()
+ value
+ string or nil
+ The initial text value. Default will be gui.get_text(text_node)
@@ -295,7 +360,7 @@ type druid.rich_text.metrics = {
RichText
text
- string
+ string or nil
The text to set
@@ -361,7 +426,7 @@ Words <nobr>inside tag</nobr> won't break
- tagged(tag)
+ tagged(self, tag)
Get all words, which has a passed tag.
@@ -369,6 +434,10 @@ Words <nobr>inside tag</nobr> won't breakParameters:
+
+ set_view_size(self, size)
+ Set new scroll view size in case the node size was changed.
+
+
+ update_view_size(self)
+ Refresh scroll view size
+
+
+ _is_inert
+ Flag, if scroll now moving by inertion
+
available_pos
Available position for content node: (min_x, max_y, max_x, min_y)
@@ -229,6 +241,10 @@
view_node
Scroll view node
+
+ view_size
+ Scroll view size
+
@@ -525,7 +541,7 @@
node
- node
+ node or string
Gui node
@@ -683,7 +699,7 @@
The new size for content node
offset
- vector3
+ vector3 or nil
Offset value to set, where content is starts
@@ -729,6 +745,58 @@
+
+
+
+ set_view_size(self, size)
+
+
+ Set new scroll view size in case the node size was changed.
+
+
+ Parameters:
+
+ self
+ Scroll
+ Scroll
+
+ size
+ vector3
+ The new size for view node
+
+
+
+ Returns:
+
+
+ druid.scroll
+ Current scroll instance
+
+
+
+
+
+
+
+
+ update_view_size(self)
+
+
+ Refresh scroll view size
+
+
+ Parameters:
+
+
+
+
+
+
@@ -747,64 +815,52 @@
Fields:
FRICT
- number
- Multiplier for free inertion
- (default 0)
+ number or nil
+ Multiplier for free inertion. Default: 0
FRICT_HOLD
- number
- Multiplier for inertion, while touching
- (default 0)
+ number or nil
+ Multiplier for inertion, while touching. Default: 0
INERT_THRESHOLD
- number
- Scroll speed to stop inertion
- (default 3)
+ number or nil
+ Scroll speed to stop inertion. Default: 3
INERT_SPEED
- number
- Multiplier for inertion speed
- (default 30)
+ number or nil
+ Multiplier for inertion speed. Default: 30
POINTS_DEADZONE
- number
- Speed to check points of interests in no_inertion mode
- (default 20)
+ number or nil
+ Speed to check points of interests in no_inertion mode. Default: 20
BACK_SPEED
- number
- Scroll back returning lerp speed
- (default 0.35)
+ number or nil
+ Scroll back returning lerp speed. Default: 35
ANIM_SPEED
- number
- Scroll gui.animation speed for scroll_to function
- (default 0.2)
+ number or nil
+ Scroll gui.animation speed for scroll_to function. Default: 2
EXTRA_STRETCH_SIZE
- number
- extra size in pixels outside of scroll (stretch effect)
- (default 0)
+ number or nil
+ extra size in pixels outside of scroll (stretch effect). Default: 0
SMALL_CONTENT_SCROLL
- boolean
- If true, content node with size less than view node size can be scrolled
- (default false)
+ boolean or nil
+ If true, content node with size less than view node size can be scrolled. Default: false
WHEEL_SCROLL_SPEED
- boolean
- The scroll speed via mouse wheel scroll or touchpad. Set to 0 to disable wheel scrolling
- (default 0)
+ boolean or nil
+ The scroll speed via mouse wheel scroll or touchpad. Set to 0 to disable wheel scrolling. Default: 0
WHEEL_SCROLL_INVERTED
- boolean
- If true, invert direction for touchpad and mouse wheel scroll
- (default false)
+ boolean or nil
+ If true, invert direction for touchpad and mouse wheel scroll. Default: false
WHEEL_SCROLL_BY_INERTION
- boolean
- If true, wheel will add inertion to scroll. Direct set position otherwise.
- (default false)
+ boolean or nil
+ If true, wheel will add inertion to scroll. Direct set position otherwise.. Default: false
@@ -817,6 +873,26 @@
+
+
+ _is_inert
+
+
+ Flag, if scroll now moving by inertion
+
+
+
+ _is_inert
+ boolean
+
+
+
+
+
+
+
+
+
available_pos
@@ -1027,9 +1103,8 @@
selected
- number
+ number or nil
- (optional )
@@ -1077,6 +1152,26 @@
+
+
+
+ view_size
+
+
+ Scroll view size
+
+
+
+ view_size
+ vector3
+
+
+
+
+
+
+
+
diff --git a/docs/modules/Slider.html b/docs/modules/Slider.html
index 3fdf8fe..94fc9f0 100644
--- a/docs/modules/Slider.html
+++ b/docs/modules/Slider.html
@@ -86,10 +86,18 @@
The Slider constructor
+ is_enabled(self)
+ Check if Slider component is enabled
+
+
set(self, value, is_silent)
Set value for slider
+ set_enabled(self, is_enabled)
+ Set Slider input enabled or disabled
+
+
set_input_node(self, input_node)
Set input zone for slider.
@@ -177,6 +185,33 @@
+
+
+
+ is_enabled(self)
+
+
+ Check if Slider component is enabled
+
+
+ Parameters:
+
+
+ Returns:
+
+
+ boolean
+
+
+
+
+
+
@@ -206,6 +241,31 @@
+
+
+
+ set_enabled(self, is_enabled)
+
+
+ Set Slider input enabled or disabled
+
+
+ Parameters:
+
+ self
+ Slider
+ Slider
+
+ is_enabled
+ boolean
+
+
+
+
+
+
+
+
@@ -225,7 +285,7 @@
Slider
input_node
- node
+ node , string or nil
@@ -291,7 +351,7 @@
diff --git a/docs/modules/StaticGrid.html b/docs/modules/StaticGrid.html
index e5591d3..076f3bb 100644
--- a/docs/modules/StaticGrid.html
+++ b/docs/modules/StaticGrid.html
@@ -138,7 +138,7 @@
Return grid content size
- init(self, parent, element[, in_row=1])
+ init(self, parent, element, in_row)
The StaticGrid constructor
@@ -154,9 +154,21 @@
Set new in_row elements for grid
+ set_item_size(self[, width[, height]])
+ Set new node size for grid
+
+
+ set_items(self, nodes[, is_instant=false])
+ Set new items to the grid.
+
+
set_position_function(self, callback)
Change set position function for grid nodes.
+
+ sort_nodes(self, comparator)
+ Sort grid nodes by custom comparator function
+
@@ -496,7 +508,7 @@
- init(self, parent, element[, in_row=1])
+ init(self, parent, element, in_row)
The StaticGrid constructor
@@ -517,9 +529,8 @@
Element prefab. Need to get it size
in_row
- number
- How many nodes in row can be placed
- (default 1)
+ number or nil
+ How many nodes in row can be placed. By default 1
@@ -622,6 +633,73 @@
+
+
+
+ set_item_size(self[, width[, height]])
+
+
+ Set new node size for grid
+
+
+ Parameters:
+
+ self
+ StaticGrid
+ StaticGrid
+
+ width
+ number
+ The new node width
+ (optional )
+
+ height
+ number
+ The new node height
+ (optional )
+
+
+
+ Returns:
+
+
+ druid.static_grid
+ Current grid instance
+
+
+
+
+
+
+
+
+ set_items(self, nodes[, is_instant=false])
+
+
+ Set new items to the grid. All previous items will be removed
+
+
+ Parameters:
+
+ self
+ StaticGrid
+ StaticGrid
+
+ nodes
+ node[]
+ The new grid nodes
+
+ is_instant
+ boolean
+ If true, update node positions instantly
+ (default false)
+
+
+
+
+
+
+
@@ -654,6 +732,37 @@
+
+
+
+ sort_nodes(self, comparator)
+
+
+ Sort grid nodes by custom comparator function
+
+
+ Parameters:
+
+ self
+ StaticGrid
+ StaticGrid
+
+ comparator
+ function
+ The comparator function. (a, b) -> boolean
+
+
+
+ Returns:
+
+
+ druid.static_grid
+ Current grid instance
+
+
+
+
+
@@ -672,14 +781,12 @@
Fields:
IS_DYNAMIC_NODE_POSES
- boolean
- If true, always center grid content as grid pivot sets
- (default false)
+ boolean or nil
+ If true, always center grid content as grid pivot sets. Default: false
IS_ALIGN_LAST_ROW
- boolean
- If true, always align last row of the grid as grid pivot sets
- (default false)
+ boolean or nil
+ If true, always align last row of the grid as grid pivot sets. Default: false
diff --git a/docs/modules/Swipe.html b/docs/modules/Swipe.html
index 3b68b0d..da20bb1 100644
--- a/docs/modules/Swipe.html
+++ b/docs/modules/Swipe.html
@@ -169,7 +169,7 @@
Swipe
zone
- node
+ node , string or nil
Gui node
@@ -196,19 +196,16 @@
Fields:
SWIPE_TIME
- number
- Maximum time for swipe trigger
- (default 0.4)
+ number or nil
+ Maximum time for swipe trigger. Default: 0.4
SWIPE_THRESHOLD
- number
- Minimum distance for swipe trigger
- (default 50)
+ number or nil
+ Minimum distance for swipe trigger. Default: 50
SWIPE_TRIGGER_ON_MOVE
- boolean
- If true, trigger on swipe moving, not only release action
- (default false)
+ boolean or nil
+ If true, trigger on swipe moving, not only release action. Default: false
diff --git a/docs/modules/Text.html b/docs/modules/Text.html
index 179c6cb..4f7d196 100644
--- a/docs/modules/Text.html
+++ b/docs/modules/Text.html
@@ -105,11 +105,15 @@
Return current text adjust type
+ get_text_index_by_width(self, width)
+ Get chars count by width
+
+
get_text_size(self, text)
Calculate text width with font with respect to trailing space
- init(self, node, value[, adjust_type=downscale])
+ init(self, node, value, adjust_type)
The Text constructor
@@ -247,6 +251,37 @@
+
+
+
+ get_text_index_by_width(self, width)
+
+
+ Get chars count by width
+
+
+ Parameters:
+
+ self
+ Text
+ Text
+
+ width
+ number
+
+
+
+
+ Returns:
+
+
+ number
+ Chars count
+
+
+
+
+
@@ -263,8 +298,8 @@
Text
text
- string or nil
-
+ string
+ |nil
@@ -284,7 +319,7 @@
- init(self, node, value[, adjust_type=downscale])
+ init(self, node, value, adjust_type)
The Text constructor
@@ -302,12 +337,11 @@
value
string or nil
- Initial text. Default value is node text from GUI scene.
+ Initial text. Default value is node text from GUI scene. Default: nil
adjust_type
- string
- Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference
- (default downscale)
+ string or nil
+ Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference. Default: DOWNSCALE
@@ -544,7 +578,7 @@
Text
adjust_type
- number or nil
+ string or nil
See const.TEXT_ADJUST. If pass nil - use current adjust type
minimal_scale
@@ -612,14 +646,20 @@
Fields:
TRIM_POSTFIX
- string
- The postfix for TRIM adjust type
- (default ...)
+ string or nil
+ The postfix for TRIM adjust type. Default: ...
DEFAULT_ADJUST
- string
- The default adjust type for any text component
- (default DOWNSCALE)
+ string or nil
+ The default adjust type for any text component. Default: DOWNSCALE
+
+ ADJUST_STEPS
+ string or nil
+ Amount of iterations for text adjust by height. Default: 20
+
+ ADJUST_SCALE_DELTA
+ string or nil
+ Scale step on each height adjust step. Default: 0.02
diff --git a/docs/modules/Timer.html b/docs/modules/Timer.html
index 7c3eb82..9dca7a5 100644
--- a/docs/modules/Timer.html
+++ b/docs/modules/Timer.html
@@ -158,7 +158,7 @@
Gui text node
seconds_from
- number
+ number or nil
Start timer value in seconds
seconds_to
diff --git a/docs/modules/druid.extended.layout.html b/docs/modules/druid.extended.layout.html
new file mode 100644
index 0000000..4f01fd5
--- /dev/null
+++ b/docs/modules/druid.extended.layout.html
@@ -0,0 +1,95 @@
+
+
+
+
+ Defold Druid UI Framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Druid
+
+
+
+
+
+
Modules
+
+
+
+
+
+
+
Module druid.extended.layout
+
Druid layout module
+
# Overview #
+
Layout component works like Dynamic Grid before - for aligning elements in a row or column.
+
Works like a Figma layout.
+
# Notes
+
+
+
+
+
+
+
+
+
+
+
+
+
generated by LDoc TESTING
+
Last updated 2015-01-01 12:00:00
+
+
+
+
diff --git a/docs/modules/druid.system.utf8.html b/docs/modules/druid.system.utf8.html
new file mode 100644
index 0000000..0582106
--- /dev/null
+++ b/docs/modules/druid.system.utf8.html
@@ -0,0 +1,93 @@
+
+
+
+
+ Defold Druid UI Framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Druid
+
+
+
+
+
+
Modules
+
+
+
+
+
+
+
Module druid.system.utf8
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
generated by LDoc TESTING
+
Last updated 2015-01-01 12:00:00
+
+
+
+
diff --git a/docs_md/02-creating_custom_components.md b/docs_md/02-creating_custom_components.md
index b7aaf99..cf9c32c 100644
--- a/docs_md/02-creating_custom_components.md
+++ b/docs_md/02-creating_custom_components.md
@@ -14,21 +14,14 @@ A basic custom component template looks like this (you can copy it from `/druid/
```lua
local component = require("druid.component")
----@class component_name : druid.base_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
@@ -43,18 +36,12 @@ A full custom component template looks like this (you can copy it from `/druid/t
```lua
local component = require("druid.component")
----@class component_name : druid.base_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
diff --git a/docs_md/advanced-setup.md b/docs_md/advanced-setup.md
index ac13ec9..5e047a7 100644
--- a/docs_md/advanced-setup.md
+++ b/docs_md/advanced-setup.md
@@ -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)

@@ -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
```
diff --git a/docs_md/changelog.md b/docs_md/changelog.md
index cffcf26..f04f284 100644
--- a/docs_md/changelog.md
+++ b/docs_md/changelog.md
@@ -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!
[](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](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
diff --git a/docs_md/game_examples.md b/docs_md/game_examples.md
deleted file mode 100644
index 9735b3d..0000000
--- a/docs_md/game_examples.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Game Examples
-
-## Family Island
-
-## Sea Battle: Universe
-
-## Monkey Mart
-
diff --git a/druid/annotations.lua b/druid/annotations.lua
index efd981f..4c9e4c7 100644
--- a/druid/annotations.lua
+++ b/druid/annotations.lua
@@ -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,9 +1427,15 @@ 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
+---@param text string |nil
---@return number Width
---@return number Height
function druid__text.get_text_size(self, text) end
@@ -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
+---@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
\ No newline at end of file
diff --git a/druid/base/button.lua b/druid/base/button.lua
index 5bd10c4..9b09c48 100755
--- a/druid/base/button.lua
+++ b/druid/base/button.lua
@@ -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
- on_button_long_click(self)
+ 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")
diff --git a/druid/base/drag.lua b/druid/base/drag.lua
index c2a5072..fd79105 100644
--- a/druid/base/drag.lua
+++ b/druid/base/drag.lua
@@ -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
diff --git a/druid/base/hover.lua b/druid/base/hover.lua
index f2a2517..f178cf2 100644
--- a/druid/base/hover.lua
+++ b/druid/base/hover.lua
@@ -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
- self._is_hovered = state
- self.on_hover:trigger(self:get_context(), state, self)
+ 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
- self._is_mouse_hovered = state
- self.on_mouse_hover:trigger(self:get_context(), state, self)
+ 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
diff --git a/druid/base/scroll.lua b/druid/base/scroll.lua
index 7328429..962411a 100755
--- a/druid/base/scroll.lua
+++ b/druid/base/scroll.lua
@@ -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
diff --git a/druid/base/static_grid.lua b/druid/base/static_grid.lua
index ee2903e..e66813c 100644
--- a/druid/base/static_grid.lua
+++ b/druid/base/static_grid.lua
@@ -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
diff --git a/druid/base/text.lua b/druid/base/text.lua
index a34ffe7..39188f4 100755
--- a/druid/base/text.lua
+++ b/druid/base/text.lua
@@ -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
- scale_modifier = math.min(scale_modifier, self.start_scale.x)
+ 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
- local scale_modifier_by_height = math.sqrt(max_height / metrics.height)
- scale_modifier = math.min(self.start_scale.y, scale_modifier_by_height)
+ -- 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
- if metrics.width * scale_modifier > max_width then
- scale_modifier = math.min(max_width / metrics.width, self.start_scale.x)
+ -- #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)
+
+ 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
diff --git a/druid/component.lua b/druid/component.lua
index ca6f89e..1bd76c9 100644
--- a/druid/component.lua
+++ b/druid/component.lua
@@ -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)
- end
+ 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
diff --git a/druid/const.lua b/druid/const.lua
index c9adc29..70667de 100755
--- a/druid/const.lua
+++ b/druid/const.lua
@@ -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"
diff --git a/druid/custom/pin_knob/pin_knob.gui b/druid/custom/pin_knob/pin_knob.gui
deleted file mode 100644
index 6397460..0000000
--- a/druid/custom/pin_knob/pin_knob.gui
+++ /dev/null
@@ -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
diff --git a/druid/custom/pin_knob/pin_knob.lua b/druid/custom/pin_knob/pin_knob.lua
deleted file mode 100644
index 418f6be..0000000
--- a/druid/custom/pin_knob/pin_knob.lua
+++ /dev/null
@@ -1,123 +0,0 @@
--- Copyright (c) 2022 Maksim Tuprikov . 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
diff --git a/druid/custom/rich_input/rich_input.lua b/druid/custom/rich_input/rich_input.lua
index 68d3560..bffe3fa 100644
--- a/druid/custom/rich_input/rich_input.lua
+++ b/druid/custom/rich_input/rich_input.lua
@@ -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
diff --git a/druid/custom/rich_text/module/rt.lua b/druid/custom/rich_text/module/rt.lua
index 8a350ec..8baa48c 100755
--- a/druid/custom/rich_text/module/rt.lua
+++ b/druid/custom/rich_text/module/rt.lua
@@ -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)
diff --git a/druid/custom/rich_text/module/rt_parse.lua b/druid/custom/rich_text/module/rt_parse.lua
index 66c6a1d..53d42a6 100755
--- a/druid/custom/rich_text/module/rt_parse.lua
+++ b/druid/custom/rich_text/module/rt_parse.lua
@@ -117,6 +117,10 @@ function M.parse(text, default_settings, style)
assert(default_settings)
text = text:gsub("&zwsp;", "\226\128\139 ")
+
+ -- Replace all \n with to make it easier to split the text
+ text = text:gsub("\n", " ")
+
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 == "/"
diff --git a/druid/custom/rich_text/module/rt_tags.lua b/druid/custom/rich_text/module/rt_tags.lua
index 0805822..058131e 100644
--- a/druid/custom/rich_text/module/rt_tags.lua
+++ b/druid/custom/rich_text/module/rt_tags.lua
@@ -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)
diff --git a/druid/custom/rich_text/rich_text.gui b/druid/custom/rich_text/rich_text.gui
deleted file mode 100644
index e37f9ea..0000000
--- a/druid/custom/rich_text/rich_text.gui
+++ /dev/null
@@ -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
diff --git a/druid/custom/rich_text/rich_text.lua b/druid/custom/rich_text/rich_text.lua
index 6f0b0cd..81ac7ac 100644
--- a/druid/custom/rich_text/rich_text.lua
+++ b/druid/custom/rich_text/rich_text.lua
@@ -6,31 +6,7 @@
-- This custom component is inspired by defold-richtext by britzl.
-- It uses a similar syntax for tags but currently supports fewer tags.
--
--- All parameters for the Rich Text component are adjusted in the GUI scene.
---
--- This component uses GUI component template. (/druid/custom/rich_text/rich_text.gui).
---
--- You able to customize it or make your own with the next node scructure:
---
--- root
---
--- - text_prefab
---
--- - icon_prefab
---
--- # Rich Text Setup #
---
--- • Root node size: Set the maximum width and height of the text.
---
--- • Root anchor: Define the alignment of the Rich Text inside the root node size area.
---
--- • Text prefab: Configure all default text parameters for the text node.
---
--- • Text prefab anchor: Set the anchor for each text node (adjust this only if animating text).
---
--- • Icon prefab: Configure all default node parameters for the icon node.
---
--- • Icon prefab anchor: Set the anchor for each icon node (adjust this only if animating the icon).
+-- Create Rich Text on your GUI Text Node. All properties of the text node will be used as default for the text.
--
-- # Notes #
--
@@ -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
--
--
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
diff --git a/druid/druid.lua b/druid/druid.lua
index ad5e766..1d247f2 100644
--- a/druid/druid.lua
+++ b/druid/druid.lua
@@ -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
diff --git a/druid/editor_scripts/component.lua_template b/druid/editor_scripts/component.lua_template
index d50db11..f33bae3 100644
--- a/druid/editor_scripts/component.lua_template
+++ b/druid/editor_scripts/component.lua_template
@@ -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
-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
diff --git a/druid/editor_scripts/create_druid_component.py b/druid/editor_scripts/create_druid_component.py
index 054bfa3..24d1203 100644
--- a/druid/editor_scripts/create_druid_component.py
+++ b/druid/editor_scripts/create_druid_component.py
@@ -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)
diff --git a/druid/editor_scripts/druid.editor_script b/druid/editor_scripts/druid.editor_script
index 6534c1d..7903c00 100644
--- a/druid/editor_scripts/druid.editor_script
+++ b/druid/editor_scripts/druid.editor_script
@@ -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"},
diff --git a/druid/editor_scripts/run_python_script_on_gui.sh b/druid/editor_scripts/run_python_script_on_gui.sh
index f76c34d..5b0e2b9 100644
--- a/druid/editor_scripts/run_python_script_on_gui.sh
+++ b/druid/editor_scripts/run_python_script_on_gui.sh
@@ -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
diff --git a/druid/event.lua b/druid/event.lua
index 208620c..ef79c86 100644
--- a/druid/event.lua
+++ b/druid/event.lua
@@ -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
- end
- return #self._callbacks > 0
+function M.is_exist(self)
+ return #self > 0
+end
+
+
+--- 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, ...)
- else
- callback_info.callback(...)
- end
+ local result = nil
+
+ local call_callback = self.call_callback
+ for index = 1, #self do
+ result = call_callback(self, self[index], ...)
end
+
+ return result
end
-return DruidEvent
+-- @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
+ 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 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,
+})
diff --git a/druid/extended/checkbox.lua b/druid/extended/checkbox.lua
index 2c629e8..dd13921 100755
--- a/druid/extended/checkbox.lua
+++ b/druid/extended/checkbox.lua
@@ -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)
diff --git a/druid/extended/checkbox_group.lua b/druid/extended/checkbox_group.lua
index 2dd66ba..d59adc3 100644
--- a/druid/extended/checkbox_group.lua
+++ b/druid/extended/checkbox_group.lua
@@ -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 = {}
diff --git a/druid/extended/data_list.lua b/druid/extended/data_list.lua
index f3e5be1..81bf959 100644
--- a/druid/extended/data_list.lua
+++ b/druid/extended/data_list.lua
@@ -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
- gui.delete_node(node)
+ local visual_data = self._data_visual[index]
+ local node = visual_data.node
+ local instance = visual_data.component
+ local data = visual_data.data
- local instance = self._data_visual[index].component
- if instance then
- self.druid:remove(instance)
+ 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)
+ if instance then
+ 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:_remove_at(index)
- end
- self:_check_elements()
-end
+ 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)
---- Check elements which should be created
--- @tparam DataList self @{DataList}
--- @local
-function DataList._check_elements(self)
+ 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 self.scroll:is_node_in_view(data.node) then
- self.top_index = index
- self.last_index = index
+ 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
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
diff --git a/druid/extended/dynamic_grid.lua b/druid/extended/dynamic_grid.lua
index 8a91af8..c4f0c76 100644
--- a/druid/extended/dynamic_grid.lua
+++ b/druid/extended/dynamic_grid.lua
@@ -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]
diff --git a/druid/extended/hotkey.lua b/druid/extended/hotkey.lua
index 1e867a8..41507bd 100644
--- a/druid/extended/hotkey.lua
+++ b/druid/extended/hotkey.lua
@@ -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")
diff --git a/druid/extended/input.lua b/druid/extended/input.lua
index 89c5fa0..db608e1 100755
--- a/druid/extended/input.lua
+++ b/druid/extended/input.lua
@@ -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,29 +197,36 @@ 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
return true
end
- local hex = string.gsub(action.text,"(.)", function (c)
+ local hex = string.gsub(action.text, "(.)", function(c)
return string.format("%02X%s",string.byte(c), "")
end)
-- 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
@@ -234,7 +305,33 @@ end
function Input.on_input_interrupt(self)
- -- self:unselect()
+ --self:unselect()
+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
@@ -242,6 +339,8 @@ end
-- @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,7 +432,11 @@ end
-- @tparam Input self @{Input}
-- @treturn string The current input field text
function Input.get_text(self)
- return self.value .. self.marked_value
+ if self.marked_value ~= "" then
+ return self.value .. self.marked_value
+ end
+
+ return self.value
end
@@ -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
diff --git a/druid/extended/lang_text.lua b/druid/extended/lang_text.lua
index 6e2a699..6d38f83 100755
--- a/druid/extended/lang_text.lua
+++ b/druid/extended/lang_text.lua
@@ -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)
diff --git a/druid/extended/layout.lua b/druid/extended/layout.lua
index ff24fef..2380d58 100644
--- a/druid/extended/layout.lua
+++ b/druid/extended/layout.lua
@@ -1,4 +1,4 @@
--- Copyright (c) 2021 Maksim Tuprikov . This code is licensed under MIT license
+-- Copyright (c) 2024 Maksim Tuprikov . 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
+-- @tfield nodes_height table
+-- @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
diff --git a/druid/extended/progress.lua b/druid/extended/progress.lua
index b5fb749..163b017 100644
--- a/druid/extended/progress.lua
+++ b/druid/extended/progress.lua
@@ -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
diff --git a/druid/extended/radio_group.lua b/druid/extended/radio_group.lua
index 8321c3f..51dbe6b 100644
--- a/druid/extended/radio_group.lua
+++ b/druid/extended/radio_group.lua
@@ -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 = {}
diff --git a/druid/extended/slider.lua b/druid/extended/slider.lua
index 05e9453..7af97d3 100644
--- a/druid/extended/slider.lua
+++ b/druid/extended/slider.lua
@@ -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
diff --git a/druid/extended/swipe.lua b/druid/extended/swipe.lua
index 264805b..110d9f4 100644
--- a/druid/extended/swipe.lua
+++ b/druid/extended/swipe.lua
@@ -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
diff --git a/druid/extended/timer.lua b/druid/extended/timer.lua
index beb2af5..235f4be 100644
--- a/druid/extended/timer.lua
+++ b/druid/extended/timer.lua
@@ -47,24 +47,26 @@ 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)
- self:set_to(seconds_from)
- self:set_interval(seconds_from, seconds_to)
+ if seconds_from then
+ seconds_from = math.max(seconds_from, 0)
+ self:set_to(seconds_from)
+ self:set_interval(seconds_from, seconds_to)
- if seconds_to - seconds_from == 0 then
- self:set_state(false)
- self.on_timer_end:trigger(self:get_context(), self)
+ if seconds_to - seconds_from == 0 then
+ self:set_state(false)
+ self.on_timer_end:trigger(self:get_context(), self)
+ end
end
return self
diff --git a/druid/helper.lua b/druid/helper.lua
index 1838174..827e9cf 100644
--- a/druid/helper.lua
+++ b/druid/helper.lua
@@ -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
diff --git a/druid/styles/default/style.lua b/druid/styles/default/style.lua
index 29921a6..ca9121c 100644
--- a/druid/styles/default/style.lua
+++ b/druid/styles/default/style.lua
@@ -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,
- }
}
diff --git a/druid/styles/sprites/style.lua b/druid/styles/sprites/style.lua
deleted file mode 100644
index 260ff2d..0000000
--- a/druid/styles/sprites/style.lua
+++ /dev/null
@@ -1,26 +0,0 @@
--- Copyright (c) 2021 Maksim Tuprikov . 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
diff --git a/druid/system/druid_instance.lua b/druid/system/druid_instance.lua
index 02f875d..ece7d01 100755
--- a/druid/system/druid_instance.lua
+++ b/druid/system/druid_instance.lua
@@ -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")
diff --git a/druid/system/middleclass.lua b/druid/system/middleclass.lua
deleted file mode 100644
index e0ef598..0000000
--- a/druid/system/middleclass.lua
+++ /dev/null
@@ -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
diff --git a/druid/system/utf8.lua b/druid/system/utf8.lua
index 7f13914..6c99fcf 100644
--- a/druid/system/utf8.lua
+++ b/druid/system/utf8.lua
@@ -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
diff --git a/druid/templates/component.template.lua b/druid/templates/component.template.lua
index cbc43ad..d67bf32 100644
--- a/druid/templates/component.template.lua
+++ b/druid/templates/component.template.lua
@@ -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
diff --git a/druid/templates/component_full.template.lua b/druid/templates/component_full.template.lua
index 70232d1..1978cf2 100644
--- a/druid/templates/component_full.template.lua
+++ b/druid/templates/component_full.template.lua
@@ -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
diff --git a/example/example.collection b/example/example.collection
index 0d91d8e..4651339 100644
--- a/example/example.collection
+++ b/example/example.collection
@@ -5,74 +5,16 @@ embedded_instances {
data: "components {\n"
" id: \"main\"\n"
" component: \"/example/example.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"
- " property_decls {\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
- }
}
embedded_instances {
id: "system"
data: "components {\n"
" id: \"init\"\n"
" component: \"/example/init.script\"\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"
- " property_decls {\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
- }
}
embedded_instances {
id: "sound"
@@ -80,59 +22,15 @@ embedded_instances {
" id: \"click\"\n"
" type: \"sound\"\n"
" data: \"sound: \\\"/example/assets/sounds/click.ogg\\\"\\n"
- "looping: 0\\n"
- "group: \\\"master\\\"\\n"
- "gain: 1.0\\n"
- "pan: 0.0\\n"
- "speed: 1.0\\n"
- "loopcount: 0\\n"
"\"\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
- }
}
embedded_instances {
id: "general_overview"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_overview\"\n"
@@ -143,62 +41,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/overview/overview.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_buttons"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_buttons\"\n"
@@ -209,62 +66,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/buttons/buttons.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "texts_general"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"texts_general\"\n"
@@ -275,62 +91,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/texts/texts_general/texts_general.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_sliders"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_sliders\"\n"
@@ -341,62 +116,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/sliders/sliders.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_grid"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_grid\"\n"
@@ -407,62 +141,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/grid/grid.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_input"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_input\"\n"
@@ -473,62 +166,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/input/input.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_scroll"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_scroll\"\n"
@@ -539,62 +191,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/scroll/scroll.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_data_list"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_data_list\"\n"
@@ -605,62 +216,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/data_list/data_list.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "data_list_static_grid"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"data_list_static_grid\"\n"
@@ -671,62 +241,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/data_list/static_grid/static_grid.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "data_list_dynamic_grid"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"data_list_dynamic_grid\"\n"
@@ -737,62 +266,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/data_list/dynamic_grid/dynamic_grid.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "data_list_navigate"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"data_list_navigate\"\n"
@@ -803,62 +291,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/data_list/navigate/navigate.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "data_list_add_remove_nodes"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"data_list_add_remove_nodes\"\n"
@@ -869,62 +316,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/data_list/add_remove_nodes/add_remove_nodes.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "grid_static_grid"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"grid_static_grid\"\n"
@@ -935,62 +341,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/grid/static_grid/static_grid.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "grid_animations"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"grid_animations\"\n"
@@ -1001,62 +366,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/grid/grid_animations/grid_animations.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "grid_static_grid_dynamic_pos"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"grid_static_grid_dynamic_pos\"\n"
@@ -1067,62 +391,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/grid/static_grid_dynamic_pos/static_grid_dynamic_pos.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "system_whitelist_blacklist"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"system_whitelist_blacklist\"\n"
@@ -1133,62 +416,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/system/whitelist_blacklist/whitelist_blacklist.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "texts_adjust"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"texts_adjust\"\n"
@@ -1199,62 +441,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/texts/texts_adjust/texts_adjust.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "system_message_input"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"system_message_input\"\n"
@@ -1265,62 +466,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/system/message_input/message_input.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "custom_rich_input"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"custom_rich_input\"\n"
@@ -1331,128 +491,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/custom/rich_input/rich_input.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
-}
-embedded_instances {
- id: "custom_pin_knob"
- data: "components {\n"
- " id: \"screen_factory\"\n"
- " component: \"/monarch/screen_factory.script\"\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"
- " properties {\n"
- " id: \"screen_id\"\n"
- " value: \"custom_pin_knob\"\n"
- " type: PROPERTY_TYPE_HASH\n"
- " }\n"
- " properties {\n"
- " id: \"popup\"\n"
- " value: \"true\"\n"
- " type: PROPERTY_TYPE_BOOLEAN\n"
- " }\n"
- " property_decls {\n"
- " }\n"
- "}\n"
- "embedded_components {\n"
- " id: \"collectionfactory\"\n"
- " type: \"collectionfactory\"\n"
- " data: \"prototype: \\\"/example/examples/custom/pin_knob/pin_knob.collection\\\"\\n"
- "load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
- "\"\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
- }
}
embedded_instances {
id: "system_inner_templates"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"system_inner_templates\"\n"
@@ -1463,62 +516,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/system/inner_templates/inner_templates.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_swipe"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_swipe\"\n"
@@ -1529,62 +541,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/swipe/swipe.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_drag"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_drag\"\n"
@@ -1595,62 +566,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/drag/drag.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_checkboxes"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_checkboxes\"\n"
@@ -1661,62 +591,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/checkboxes/checkboxes.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "data_list_reinit_data"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"data_list_reinit_data\"\n"
@@ -1727,62 +616,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/data_list/reinit_data/reinit_data.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_layout"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_layout\"\n"
@@ -1793,62 +641,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/layout/layout.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_hotkey"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_hotkey\"\n"
@@ -1859,62 +666,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/hotkey/hotkey.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "data_list_with_component"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"data_list_with_component\"\n"
@@ -1925,62 +691,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/data_list/with_component/with_component.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "layout_fit"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"layout_fit\"\n"
@@ -1991,62 +716,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/layout/layout_fit/layout_fit.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_progress_bar"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_progress_bar\"\n"
@@ -2057,62 +741,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/progress_bar/progress_bar.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "system_late_init_check"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"system_late_init_check\"\n"
@@ -2123,62 +766,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/system/late_init_check/late_init_check.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "general_hover"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"general_hover\"\n"
@@ -2189,62 +791,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/general/hover/hover.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "texts_lang_text"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"texts_lang_text\"\n"
@@ -2255,62 +816,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/texts/lang_text/lang_text.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "custom_rich_text"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"custom_rich_text\"\n"
@@ -2321,62 +841,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/custom/rich_text/rich_text.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "data_list_manage_data"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"data_list_manage_data\"\n"
@@ -2387,62 +866,21 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/data_list/manage_data/manage_data.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
embedded_instances {
id: "rich_text_texts"
data: "components {\n"
" id: \"screen_factory\"\n"
" component: \"/monarch/screen_factory.script\"\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"
" properties {\n"
" id: \"screen_id\"\n"
" value: \"rich_text_texts\"\n"
@@ -2453,43 +891,13 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
- " property_decls {\n"
- " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
" type: \"collectionfactory\"\n"
" data: \"prototype: \\\"/example/examples/rich_text/rich_text_texts/rich_text_texts.collection\\\"\\n"
"load_dynamically: true\\n"
- "dynamic_prototype: false\\n"
"\"\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
- }
}
diff --git a/example/examples/custom/pin_knob/pin_knob.collection b/example/examples/custom/pin_knob/pin_knob.collection
deleted file mode 100644
index 2698ebf..0000000
--- a/example/examples/custom/pin_knob/pin_knob.collection
+++ /dev/null
@@ -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
- }
-}
diff --git a/example/examples/custom/pin_knob/pin_knob.gui b/example/examples/custom/pin_knob/pin_knob.gui
deleted file mode 100644
index d20d64f..0000000
--- a/example/examples/custom/pin_knob/pin_knob.gui
+++ /dev/null
@@ -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
diff --git a/example/examples/custom/pin_knob/pin_knob.gui_script b/example/examples/custom/pin_knob/pin_knob.gui_script
deleted file mode 100644
index cd81204..0000000
--- a/example/examples/custom/pin_knob/pin_knob.gui_script
+++ /dev/null
@@ -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
diff --git a/example/examples/custom/rich_text/rich_text.gui b/example/examples/custom/rich_text/rich_text.gui
index f2dd603..0762a48 100644
--- a/example/examples/custom/rich_text/rich_text.gui
+++ b/example/examples/custom/rich_text/rich_text.gui
@@ -7,5388 +7,82 @@ 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
- custom_type: 0
- enabled: true
- visible: true
}
nodes {
position {
- x: 0.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: "scroll_view"
- 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: 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: 600.0
y: 1800.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: "scroll_content"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
parent: "scroll_view"
- 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: 500.0
y: 100.0
- z: 0.0
- w: 1.0
}
color {
x: 0.9490196
y: 0.9490196
z: 0.9490196
- w: 1.0
}
type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
text: "This is the example page of Rich Text component"
font: "game"
id: "hint1"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
pivot: PIVOT_N
outline {
x: 0.2
- y: 0.0
z: 0.2
- w: 1.0
}
shadow {
x: 0.2
y: 0.2
z: 0.2
- w: 1.0
}
- adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "scroll_content"
- layer: ""
inherit_alpha: true
- alpha: 1.0
outline_alpha: 0.75
shadow_alpha: 0.25
- 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: -160.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: 150.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case1"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_1"
- parent: "case1"
- 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: 400.0
- y: 150.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_1/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_1"
- 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: -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: 150.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: "rich_text_1/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: true
- parent: "rich_text_1/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.75
- shadow_alpha: 0.0
- overridden_fields: 4
- overridden_fields: 18
- overridden_fields: 31
- 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_1/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_1/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
-}
-nodes {
- position {
- x: 0.0
- y: -252.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: 500.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.9490196
- y: 0.9490196
- z: 0.9490196
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text should match with usual text node"
- font: "game"
- id: "hint2"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- outline {
- x: 0.2
- y: 0.0
- z: 0.2
- w: 1.0
- }
- shadow {
- x: 0.2
- y: 0.2
- z: 0.2
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "scroll_content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.75
- shadow_alpha: 0.25
- 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: -400.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: 120.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case2"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_2"
- parent: "case2"
- 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: 400.0
- y: 112.5
- 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_2/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_2"
- 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: 1
- overridden_fields: 4
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: -200.0
- y: -10.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: 550.0
- y: 50.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Here is example to compare Rich Text posing with usual GUI Text Node."
- font: "game"
- id: "rich_text_2/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_2/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_2/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_2/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
- overridden_fields: 3
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- 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: 0.75
- y: 0.75
- z: 1.0
- w: 1.0
- }
- size {
- x: 533.0
- y: 150.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.9019608
- y: 0.7019608
- z: 0.9019608
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Here is example to compare Rich Text posing with usual GUI Text Node."
- font: "game"
- id: "text_case_2"
- 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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "case2"
- layer: ""
- inherit_alpha: true
- alpha: 0.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: -475.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: 500.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.9490196
- y: 0.9490196
- z: 0.9490196
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text split text to several text nodes"
- font: "game"
- id: "hint3"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- outline {
- x: 0.2
- y: 0.0
- z: 0.2
- w: 1.0
- }
- shadow {
- x: 0.2
- y: 0.2
- z: 0.2
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "scroll_content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.75
- shadow_alpha: 0.25
- 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: -620.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: 120.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case3"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_3"
- parent: "case3"
- 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: 400.0
- y: 112.5
- 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_3/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_3"
- 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: 1
- overridden_fields: 4
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: -200.0
- y: -10.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: 400.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_3/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_3/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_3/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_3/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
- overridden_fields: 3
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: 0.0
- y: -685.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: 500.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.9490196
- y: 0.9490196
- z: 0.9490196
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text supports images"
- font: "game"
- id: "hint4"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- outline {
- x: 0.2
- y: 0.0
- z: 0.2
- w: 1.0
- }
- shadow {
- x: 0.2
- y: 0.2
- z: 0.2
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "scroll_content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.75
- shadow_alpha: 0.25
- 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: -800.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: 60.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case4_1"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_4_1"
- parent: "case4_1"
- 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: 400.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_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "rich_text_4_1/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_4_1"
- 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: 1
- overridden_fields: 4
- template_node_child: true
- 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: 0.75
- y: 0.75
- z: 1.0
- w: 1.0
- }
- size {
- x: 400.0
- y: 50.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_4_1/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_4_1/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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_4_1/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_4_1/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
-}
-nodes {
- position {
- x: 0.0
- y: -870.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: 60.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case4_2"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_4_2"
- parent: "case4_2"
- 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: 400.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_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "rich_text_4_2/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_4_2"
- 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: 1
- overridden_fields: 4
- template_node_child: true
- 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: 0.75
- y: 0.75
- z: 1.0
- w: 1.0
- }
- size {
- x: 400.0
- y: 50.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_4_2/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_4_2/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.5
- y: 0.5
- 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_4_2/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_4_2/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
- overridden_fields: 3
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: 0.0
- y: -940.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: 60.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case4_3"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_4_3"
- parent: "case4_3"
- 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: 400.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_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "rich_text_4_3/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_4_3"
- 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: 1
- overridden_fields: 4
- template_node_child: true
- 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: 0.75
- y: 0.75
- z: 1.0
- w: 1.0
- }
- size {
- x: 400.0
- y: 50.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_4_3/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_4_3/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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_4_3/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_4_3/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
-}
-nodes {
- position {
- x: 0.0
- y: -986.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: 700.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.9490196
- y: 0.9490196
- z: 0.9490196
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text support all pivots (area from root node size)"
- font: "game"
- id: "hint5"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- outline {
- x: 0.2
- y: 0.0
- z: 0.2
- w: 1.0
- }
- shadow {
- x: 0.2
- y: 0.2
- z: 0.2
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "scroll_content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.75
- shadow_alpha: 0.25
- template_node_child: false
- text_leading: 1.0
- text_tracking: 0.0
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: -180.0
- y: -1132.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: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5_NW"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_5_NW"
- parent: "case5_NW"
- 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: -75.0
- y: 50.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: 150.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: "rich_text_5_NW/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_NW
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_NW"
- 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: 1
- overridden_fields: 4
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: 0.0
- y: -50.0
- z: 0.0
- w: 1.0
- }
- rotation {
- x: 0.0
- y: 0.0
- z: 0.0
- w: 1.0
- }
- scale {
- x: 0.5
- y: 0.5
- z: 1.0
- w: 1.0
- }
- size {
- x: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_5_NW/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_5_NW/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_5_NW/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_NW/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
- overridden_fields: 3
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: 0.0
- y: -1132.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: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5_N"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_5_N"
- parent: "case5_N"
- 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: 50.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: 150.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: "rich_text_5_N/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_N"
- 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: 1
- overridden_fields: 4
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: -73.0
- y: -50.0
- z: 0.0
- w: 1.0
- }
- rotation {
- x: 0.0
- y: 0.0
- z: 0.0
- w: 1.0
- }
- scale {
- x: 0.5
- y: 0.5
- z: 1.0
- w: 1.0
- }
- size {
- x: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_5_N/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_5_N/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_5_N/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_N/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
- overridden_fields: 3
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: 180.0
- y: -1132.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: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5_NE"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_5_NE"
- parent: "case5_NE"
- 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: 75.0
- y: 50.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: 150.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: "rich_text_5_NE/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_NE
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_NE"
- 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: 1
- overridden_fields: 4
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: -150.0
- y: -50.0
- z: 0.0
- w: 1.0
- }
- rotation {
- x: 0.0
- y: 0.0
- z: 0.0
- w: 1.0
- }
- scale {
- x: 0.5
- y: 0.5
- z: 1.0
- w: 1.0
- }
- size {
- x: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_5_NE/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_5_NE/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_5_NE/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_NE/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
- overridden_fields: 3
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: -180.0
- y: -1252.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: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5_W"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_5_W"
- parent: "case5_W"
- 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: -75.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: 150.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: "rich_text_5_W/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_W
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_W"
- 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: 1
- overridden_fields: 4
- overridden_fields: 14
- 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: 0.5
- y: 0.5
- z: 1.0
- w: 1.0
- }
- size {
- x: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_5_W/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_5_W/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_5_W/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_W/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
- overridden_fields: 3
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: 0.0
- y: -1252.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: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5_C"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_5_C"
- parent: "case5_C"
- 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: 150.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: "rich_text_5_C/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_C"
- 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: 1
- overridden_fields: 4
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: -73.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.5
- y: 0.5
- z: 1.0
- w: 1.0
- }
- size {
- x: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_5_C/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_5_C/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_5_C/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_C/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
- overridden_fields: 3
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: 180.0
- y: -1252.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: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5_E"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_5_E"
- parent: "case5_E"
- 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: 75.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: 150.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: "rich_text_5_E/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_E
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_E"
- 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: 1
- overridden_fields: 4
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: -150.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.5
- y: 0.5
- z: 1.0
- w: 1.0
- }
- size {
- x: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_5_E/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_5_E/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_5_E/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_E/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
- overridden_fields: 3
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: -180.0
- y: -1372.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: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5_SW"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_5_SW"
- parent: "case5_SW"
- 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: -75.0
- y: -50.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: 150.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: "rich_text_5_SW/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_SW
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_SW"
- 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: 1
- overridden_fields: 4
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: 0.0
- y: 50.0
- z: 0.0
- w: 1.0
- }
- rotation {
- x: 0.0
- y: 0.0
- z: 0.0
- w: 1.0
- }
- scale {
- x: 0.5
- y: 0.5
- z: 1.0
- w: 1.0
- }
- size {
- x: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_5_SW/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_5_SW/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_5_SW/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_S
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_SW/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
- overridden_fields: 3
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: 0.0
- y: -1372.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: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5_S"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_5_S"
- parent: "case5_S"
- 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: -50.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: 150.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: "rich_text_5_S/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_S
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_S"
- 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: 1
- overridden_fields: 4
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: -75.0
- y: 50.0
- z: 0.0
- w: 1.0
- }
- rotation {
- x: 0.0
- y: 0.0
- z: 0.0
- w: 1.0
- }
- scale {
- x: 0.5
- y: 0.5
- z: 1.0
- w: 1.0
- }
- size {
- x: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_5_S/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_5_S/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_5_S/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_S
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_S/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
- overridden_fields: 3
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: 180.0
- y: -1372.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: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5_SE"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_5_SE"
- parent: "case5_SE"
- 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: 75.0
- y: -50.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: 150.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: "rich_text_5_SE/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_SE
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_SE"
- 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: 1
- overridden_fields: 4
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: -150.0
- y: 50.0
- z: 0.0
- w: 1.0
- }
- rotation {
- x: 0.0
- y: 0.0
- z: 0.0
- w: 1.0
- }
- scale {
- x: 0.5
- y: 0.5
- z: 1.0
- w: 1.0
- }
- size {
- x: 150.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 1.0
- y: 0.9019608
- z: 0.6
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "Rich Text"
- font: "game"
- id: "rich_text_5_SE/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.5019608
- y: 0.7019608
- z: 0.7019608
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "rich_text_5_SE/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 5
- overridden_fields: 8
- overridden_fields: 16
- overridden_fields: 18
- overridden_fields: 32
- 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: 0.75
- y: 0.75
- 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_5_SE/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_S
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_5_SE/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
- overridden_fields: 3
- overridden_fields: 14
- template_node_child: true
- size_mode: SIZE_MODE_AUTO
- custom_type: 0
- enabled: true
- visible: true
-}
-nodes {
- position {
- x: -500.0
- y: -200.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: ""
- id: "highlight"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: -1455.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: 700.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.9490196
- y: 0.9490196
- z: 0.9490196
- w: 1.0
- }
- type: TYPE_TEXT
- blend_mode: BLEND_MODE_ALPHA
- text: "You can get the tagged word to make logic around"
- font: "game"
- id: "hint"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- outline {
- x: 0.2
- y: 0.0
- z: 0.2
- w: 1.0
- }
- shadow {
- x: 0.2
- y: 0.2
- z: 0.2
- w: 1.0
- }
- adjust_mode: ADJUST_MODE_FIT
- line_break: true
- parent: "scroll_content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.75
- shadow_alpha: 0.25
- 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: -1622.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: 150.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.101960786
- y: 0.3019608
- z: 0.3019608
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case6"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "scroll_content"
- 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: 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_TEMPLATE
- id: "rich_text_6"
- parent: "case6"
- 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: 400.0
- y: 150.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_6/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_6"
- 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: 400.0
- y: 150.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: "rich_text_6/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_6/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.75
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 4
- overridden_fields: 14
- overridden_fields: 18
- overridden_fields: 31
- 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_6/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "rich_text_6/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
}
layers {
name: "image"
@@ -5398,4 +92,3 @@ layers {
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
-max_nodes: 512
diff --git a/example/examples/data_list/with_component/button_component/button_component.lua b/example/examples/data_list/with_component/button_component/button_component.lua
index 39c6c23..2609c8e 100644
--- a/example/examples/data_list/with_component/button_component/button_component.lua
+++ b/example/examples/data_list/with_component/button_component/button_component.lua
@@ -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
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)
diff --git a/example/examples/general/buttons/buttons.gui_script b/example/examples/general/buttons/buttons.gui_script
index 04b3f1c..144c237 100644
--- a/example/examples/general/buttons/buttons.gui_script
+++ b/example/examples/general/buttons/buttons.gui_script
@@ -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)
diff --git a/example/examples/general/scroll/scroll.gui_script b/example/examples/general/scroll/scroll.gui_script
index 3ad39b9..f9a5468 100644
--- a/example/examples/general/scroll/scroll.gui_script
+++ b/example/examples/general/scroll/scroll.gui_script
@@ -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")
diff --git a/example/examples/rich_text/rich_text_texts/prefab_example_rich_text.gui b/example/examples/rich_text/rich_text_texts/prefab_example_rich_text.gui
index 2c49da9..aa377e3 100644
--- a/example/examples/rich_text/rich_text_texts/prefab_example_rich_text.gui
+++ b/example/examples/rich_text/rich_text_texts/prefab_example_rich_text.gui
@@ -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
diff --git a/example/examples/rich_text/rich_text_texts/rich_text_texts.gui b/example/examples/rich_text/rich_text_texts/rich_text_texts.gui
index 757aa39..6354116 100644
--- a/example/examples/rich_text/rich_text_texts/rich_text_texts.gui
+++ b/example/examples/rich_text/rich_text_texts/rich_text_texts.gui
@@ -15,2838 +15,37 @@ 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
- custom_type: 0
- enabled: true
- visible: true
}
nodes {
position {
- x: 0.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: 1200.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: "content"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
pivot: PIVOT_N
adjust_mode: ADJUST_MODE_STRETCH
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: 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: 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: "case1"
- parent: "content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/example/examples/rich_text/rich_text_texts/prefab_example_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: 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: "case1/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case1"
- 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_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: "case1/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: "case1/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.7
- shadow_alpha: 0.0
- 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: -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: "case1/area"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case1/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_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: "case1/rich_text"
- parent: "case1/area"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/druid/custom/rich_text/rich_text.gui"
- template_node_child: true
- 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: "case1/rich_text/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case1/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
- 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: "case1/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: "case1/rich_text/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- 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: "case1/rich_text/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case1/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
-}
-nodes {
- position {
- x: 0.0
- y: -200.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: "case2"
- parent: "content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/example/examples/rich_text/rich_text_texts/prefab_example_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: 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: "case2/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case2"
- 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_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: "Text color setup"
- font: "game"
- id: "case2/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: "case2/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.7
- shadow_alpha: 0.0
- overridden_fields: 8
- 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: -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: "case2/area"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case2/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_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: "case2/rich_text"
- parent: "case2/area"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/druid/custom/rich_text/rich_text.gui"
- template_node_child: true
- 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: "case2/rich_text/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case2/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
- 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: "case2/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: "case2/rich_text/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- 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: "case2/rich_text/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case2/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
-}
-nodes {
- position {
- x: 0.0
- y: -400.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: "case3"
- parent: "content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/example/examples/rich_text/rich_text_texts/prefab_example_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: 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: "case3/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case3"
- 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_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: "Text font setup"
- font: "game"
- id: "case3/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: "case3/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.7
- shadow_alpha: 0.0
- overridden_fields: 8
- 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: -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: "case3/area"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case3/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_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: "case3/rich_text"
- parent: "case3/area"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/druid/custom/rich_text/rich_text.gui"
- template_node_child: true
- 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: "case3/rich_text/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case3/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
- 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: "case3/rich_text/text_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_SW
- 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: "case3/rich_text/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 14
- 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: "case3/rich_text/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case3/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
-}
-nodes {
- position {
- x: 0.0
- y: -600.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: "case4"
- parent: "content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/example/examples/rich_text/rich_text_texts/prefab_example_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: 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: "case4/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case4"
- 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_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: "Example with and "
- font: "game"
- id: "case4/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: "case4/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.7
- shadow_alpha: 0.0
- overridden_fields: 8
- 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: -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: "case4/area"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case4/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_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: "case4/rich_text"
- parent: "case4/area"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/druid/custom/rich_text/rich_text.gui"
- template_node_child: true
- 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: "case4/rich_text/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case4/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: "case4/rich_text/text_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_SW
- 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: "case4/rich_text/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 8
- overridden_fields: 14
- 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: "case4/rich_text/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case4/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
-}
-nodes {
- position {
- x: 0.0
- y: -800.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: "case5"
- parent: "content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/example/examples/rich_text/rich_text_texts/prefab_example_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: 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: "case5/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case5"
- 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_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: "Rich Text can adjust text by height:"
- font: "game"
- id: "case5/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: "case5/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.7
- shadow_alpha: 0.0
- overridden_fields: 8
- 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: -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: "case5/area"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case5/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_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: "case5/rich_text"
- parent: "case5/area"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/druid/custom/rich_text/rich_text.gui"
- template_node_child: true
- 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: 400.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.8
- y: 1.0
- z: 1.0
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case5/rich_text/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case5/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
- overridden_fields: 5
- overridden_fields: 46
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- 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: 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: "case5/rich_text/text_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_SW
- 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: "case5/rich_text/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 8
- overridden_fields: 14
- 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: "case5/rich_text/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case5/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
-}
-nodes {
- position {
- x: 0.0
- y: -1000.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: "case6"
- parent: "content"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/example/examples/rich_text/rich_text_texts/prefab_example_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: 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: "case6/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case6"
- 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_MANUAL
- custom_type: 0
- enabled: true
- visible: false
-}
-nodes {
- position {
- x: 0.0
- y: 9.0
- z: 0.0
- w: 1.0
- }
- rotation {
- x: 0.0
- y: 0.0
- z: 0.0
- w: 1.0
- }
- scale {
- x: 0.7
- y: 0.7
- z: 1.0
- w: 1.0
- }
- size {
- x: 800.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: "Disabled Line Break in text_prefab, adjust by width"
- font: "game"
- id: "case6/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: "case6/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.7
- shadow_alpha: 0.0
- overridden_fields: 1
- overridden_fields: 3
- overridden_fields: 4
- overridden_fields: 8
- 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: -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: "case6/area"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_N
- adjust_mode: ADJUST_MODE_FIT
- parent: "case6/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_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: "case6/rich_text"
- parent: "case6/area"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- template: "/druid/custom/rich_text/rich_text.gui"
- template_node_child: true
- 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: 400.0
- y: 100.0
- z: 0.0
- w: 1.0
- }
- color {
- x: 0.8
- y: 1.0
- z: 1.0
- w: 1.0
- }
- type: TYPE_BOX
- blend_mode: BLEND_MODE_ALPHA
- texture: ""
- id: "case6/rich_text/root"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case6/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
- overridden_fields: 5
- overridden_fields: 46
- template_node_child: true
- size_mode: SIZE_MODE_MANUAL
- 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: 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: "case6/rich_text/text_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_SW
- 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: "case6/rich_text/root"
- layer: ""
- inherit_alpha: true
- alpha: 1.0
- outline_alpha: 0.0
- shadow_alpha: 0.0
- overridden_fields: 8
- 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: "case6/rich_text/icon_prefab"
- xanchor: XANCHOR_NONE
- yanchor: YANCHOR_NONE
- pivot: PIVOT_CENTER
- adjust_mode: ADJUST_MODE_FIT
- parent: "case6/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
-}
layers {
name: "image"
}
@@ -2855,4 +54,3 @@ layers {
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
-max_nodes: 512
diff --git a/example/game.appmanifest b/example/game.appmanifest
index 251e444..9fd8707 100644
--- a/example/game.appmanifest
+++ b/example/game.appmanifest
@@ -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: []
diff --git a/game.project b/game.project
index ef1cc91..3df4888 100644
--- a/game.project
+++ b/game.project
@@ -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
diff --git a/media/druid_hero.png b/media/druid_hero.png
new file mode 100644
index 0000000..2f55dfd
Binary files /dev/null and b/media/druid_hero.png differ
diff --git a/media/druid_logo.png b/media/druid_logo.png
index 6b5174b..4f3c65c 100644
Binary files a/media/druid_logo.png and b/media/druid_logo.png differ
diff --git a/media/druid_thumb.png b/media/druid_thumb.png
new file mode 100644
index 0000000..4601d35
Binary files /dev/null and b/media/druid_thumb.png differ
diff --git a/settings_deployer b/settings_deployer
index 92e4328..07634c7 100644
--- a/settings_deployer
+++ b/settings_deployer
@@ -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
+is_build_html_report=true
\ No newline at end of file
diff --git a/unit_test.txt b/test/test.ini
similarity index 100%
rename from unit_test.txt
rename to test/test.ini
diff --git a/test/tests/test_button.lua b/test/tests/test_button.lua
index 154803f..057135b 100644
--- a/test/tests/test_button.lua
+++ b/test/tests/test_button.lua
@@ -63,7 +63,7 @@ return function()
assert(on_long_click_mock.calls == 0)
druid:on_input(mock_input.click_pressed(10, 10))
- mock_time.elapse(0.5)
+ mock_time.elapse(1)
druid:on_input(mock_input.click_released(20, 10))
assert(on_click_mock.calls == 1)
@@ -144,14 +144,15 @@ return function()
instance.on_hold_callback:subscribe(on_hold_callback)
druid:on_input(mock_input.click_pressed(10, 10))
- mock_time.elapse(0.5) -- time between hold treshold and autorelease hold time
- druid:on_input(mock_input.click_repeated(10, 10))
+ mock_time.elapse(1) -- time between hold treshold and autorelease hold time
+ druid:on_input(mock_input.input_empty(10, 10))
+ pprint(on_long_click_mock)
assert(on_click_mock.calls == 0)
- assert(on_hold_callback_mock.calls == 1)
- assert(on_hold_callback_mock.params[1] == context)
- assert(on_hold_callback_mock.params[2] == button_params)
- assert(on_hold_callback_mock.params[3] == instance)
+ assert(on_long_click_mock.calls == 1)
+ assert(on_long_click_mock.params[1] == context)
+ assert(on_long_click_mock.params[2] == button_params)
+ assert(on_long_click_mock.params[3] == instance)
druid:on_input(mock_input.click_released(10, 10))
@@ -257,8 +258,8 @@ return function()
instance:set_enabled(false)
local is_clicked_pressed = druid:on_input(mock_input.click_pressed(10, 10))
local is_clicked_released = druid:on_input(mock_input.click_released(10, 10))
- assert(is_clicked_pressed == false)
- assert(is_clicked_released == false)
+ assert(is_clicked_pressed == true)
+ assert(is_clicked_released == true)
assert(on_click_mock.calls == 0)
assert(instance:is_enabled() == false)
diff --git a/utils/annotations_manual.lua b/utils/annotations_manual.lua
index d87b665..ab4169d 100644
--- a/utils/annotations_manual.lua
+++ b/utils/annotations_manual.lua
@@ -1,10 +1,14 @@
-- 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
@@ -21,7 +25,7 @@
---@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
@@ -31,6 +35,9 @@
---@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
@@ -42,6 +49,7 @@
---@field parent node
---@field size number
---@field fonts table
+---@field scale vector3
---@field color vector4
---@field shadow vector4
---@field outline vector4
@@ -49,11 +57,46 @@
---@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
\ No newline at end of file