diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..7453334
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,13 @@
+# These are supported funding model platforms
+
+github: insality # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: insality # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/README.md b/README.md
index 196ba21..68a95e6 100644
--- a/README.md
+++ b/README.md
@@ -25,13 +25,13 @@ Or point to the ZIP file of a [specific release](https://github.com/Insality/dru
**Druid** requires the following input bindings:
- Mouse trigger - `Button 1` -> `touch` _For basic input components_
-- Mouse trigger - `Wheel up` -> `scroll_up` _For scroll component_
-- Mouse trigger - `Wheel down` -> `scroll_down` _For scroll component_
+- Mouse trigger - `Wheel up` -> `mouse_wheel_up` _For scroll component_
+- Mouse trigger - `Wheel down` -> `mouse_wheel_down` _For scroll component_
- Key trigger - `Backspace` -> `key_backspace` _For back_handler component, input component_
- Key trigger - `Back` -> `key_back` _For back_handler component, Android back button, input component_
- Key trigger - `Enter` -> `key_enter` _For input component, optional_
- Key trigger - `Esc` -> `key_esc` _For input component, optional_
-- Touch triggers - `Touch multi` -> `multitouch` _For scroll component_
+- Touch triggers - `Touch multi` -> `touch_multi` _For scroll component_


@@ -50,9 +50,9 @@ input_key_esc = key_esc
input_key_back = key_back
input_key_enter = key_enter
input_key_backspace = key_backspace
-input_multitouch = multitouch
-input_scroll_up = scroll_up
-input_scroll_down = scroll_down
+input_multitouch = touch_multi
+input_scroll_up = mouse_wheel_up
+input_scroll_down = mouse_wheel_down
```
@@ -123,7 +123,7 @@ Here is full **Druid** components list:
| Name | Description | API page | Example Link | Is Basic component[^1] | Preview |
|------|-------------|----------|------------|-------------|---------|
| **[Button](docs_md/01-components.md#button)** | Basic input component. Handles all types of interactions: click, long click, hold click, double click, etc | [Button API](https://insality.github.io/druid/modules/Button.html) | [Button Example](https://insality.github.io/druid/druid/?example=general_buttons) | ✅ |
|
-| **[Text](docs_md/01-components.md#text)** | Wrap on GUI text node, handle different text size adjusting, providing additional text API | [Text API](https://insality.github.io/druid/modules/Button.html) | [Text Example](https://insality.github.io/druid/druid/?example=texts_general) | ✅ |
|
+| **[Text](docs_md/01-components.md#text)** | Wrap on GUI text node, handle different text size adjusting, providing additional text API | [Text API](https://insality.github.io/druid/modules/Text.html) | [Text Example](https://insality.github.io/druid/druid/?example=texts_general) | ✅ |
|
| **[Scroll](docs_md/01-components.md#scroll)** | Scroll component | [Scroll API](https://insality.github.io/druid/modules/Scroll.html) | [Scroll Example](https://insality.github.io/druid/druid/?example=general_scroll) | ✅ |
|
| **[Blocker](docs_md/01-components.md#blocker)** | Block user input in node zone area | [Blocker API](https://insality.github.io/druid/modules/Blocker.html) | ❌ | ✅ | |
| **[Back Handler](docs_md/01-components.md#back-handler)** | Handle back button (Android back button, backspace key) | [Back Handler API](https://insality.github.io/druid/modules/BackHandler.html) | ❌ | ✅ | |
diff --git a/druid/base/button.lua b/druid/base/button.lua
index aa66aba..950227e 100755
--- a/druid/base/button.lua
+++ b/druid/base/button.lua
@@ -61,7 +61,7 @@ local Button = component.create("button")
local function is_input_match(self, action_id)
- if action_id == const.ACTION_TOUCH then
+ if action_id == const.ACTION_TOUCH or action_id == const.ACTION_MULTITOUCH then
return true
end
diff --git a/druid/base/hover.lua b/druid/base/hover.lua
index 00323b4..680f7ef 100644
--- a/druid/base/hover.lua
+++ b/druid/base/hover.lua
@@ -5,10 +5,10 @@
-- @within BaseComponent
-- @alias druid.hover
---- On hover callback(self, state)
+--- On hover callback(self, state, hover_instance)
-- @tfield DruidEvent on_hover @{DruidEvent}
---- On mouse hover callback(self, state)
+--- On mouse hover callback(self, state, hover_instance)
-- @tfield DruidEvent on_mouse_hover @{DruidEvent}
---
@@ -81,6 +81,8 @@ function Hover.on_input(self, action_id, action)
else
hover_function(self, true)
end
+
+ return false
end
@@ -95,7 +97,7 @@ end
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.on_hover:trigger(self:get_context(), state, self)
end
end
@@ -114,7 +116,7 @@ end
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.on_mouse_hover:trigger(self:get_context(), state, self)
end
end
diff --git a/druid/base/text.lua b/druid/base/text.lua
index 098ae93..c266513 100755
--- a/druid/base/text.lua
+++ b/druid/base/text.lua
@@ -10,7 +10,7 @@
--- On set text callback(self, text)
-- @tfield DruidEvent on_set_text @{DruidEvent}
---- On adjust text size callback(self, new_scale)
+--- On adjust text size callback(self, new_scale, text_metrics)
-- @tfield DruidEvent on_update_text_scale @{DruidEvent}
--- On change pivot callback(self, pivot)
@@ -100,7 +100,7 @@ local function update_text_area_size(self)
update_text_size(self)
- self.on_update_text_scale:trigger(self:get_context(), new_scale)
+ self.on_update_text_scale:trigger(self:get_context(), new_scale, metrics)
end
diff --git a/druid/const.lua b/druid/const.lua
index 5276299..7aa1d5c 100755
--- a/druid/const.lua
+++ b/druid/const.lua
@@ -14,11 +14,11 @@ M.ACTION_MARKED_TEXT = hash(sys.get_config("druid.input_marked_text", "marked_te
M.ACTION_ESC = hash(sys.get_config("druid.input_key_esc", "key_esc"))
M.ACTION_BACK = hash(sys.get_config("druid.input_key_back", "key_back"))
M.ACTION_ENTER = hash(sys.get_config("druid.input_key_enter", "key_enter"))
-M.ACTION_MULTITOUCH = hash(sys.get_config("druid.input_multitouch", "multitouch"))
+M.ACTION_MULTITOUCH = hash(sys.get_config("druid.input_multitouch", "touch_multi"))
M.ACTION_BACKSPACE = hash(sys.get_config("druid.input_key_backspace", "key_backspace"))
-M.ACTION_SCROLL_UP = hash(sys.get_config("druid.input_scroll_up", "scroll_up"))
-M.ACTION_SCROLL_DOWN = hash(sys.get_config("druid.input_scroll_down", "scroll_down"))
+M.ACTION_SCROLL_UP = hash(sys.get_config("druid.input_scroll_up", "mouse_wheel_up"))
+M.ACTION_SCROLL_DOWN = hash(sys.get_config("druid.input_scroll_down", "mouse_wheel_down"))
M.IS_STENCIL_CHECK = not (sys.get_config("druid.no_stencil_check") == "1")
diff --git a/druid/extended/input.lua b/druid/extended/input.lua
index 36da224..e4d09eb 100755
--- a/druid/extended/input.lua
+++ b/druid/extended/input.lua
@@ -87,6 +87,7 @@ end
-- @tfield[opt=false] bool 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] bool IS_UNSELECT_ON_RESELECT If true, call unselect on select selected input
+-- @tfield[opt=false] bool 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 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
@@ -97,6 +98,7 @@ function Input.on_style_change(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
@@ -214,7 +216,8 @@ function Input.on_input(self, action_id, action)
end
end
- return self.is_selected
+ local is_consume_input = not self.style.NO_CONSUME_INPUT_WHILE_SELECTED and self.is_selected
+ return is_consume_input
end
diff --git a/druid/extended/progress.lua b/druid/extended/progress.lua
index 1e6fd4d..ed08326 100644
--- a/druid/extended/progress.lua
+++ b/druid/extended/progress.lua
@@ -121,12 +121,8 @@ function Progress.init(self, node, key, init_value)
end
self.on_change = Event()
-end
-
--- @tparam Progress self @{Progress}
-function Progress.on_late_init(self)
- self:set_to(self._init_value)
+ self:set_to(self.last_value)
end
diff --git a/druid/helper.lua b/druid/helper.lua
index 760b0fd..223886a 100644
--- a/druid/helper.lua
+++ b/druid/helper.lua
@@ -208,10 +208,10 @@ end
--- Get cumulative parent's node scale
-- @function helper.get_scene_scale
-- @tparam node node Gui node
--- @tparam bool include_node_scale
--- @treturn bool Is enabled in hierarchy
-function M.get_scene_scale(node, include_node_scale)
- local scale = include_node_scale and gui.get_scale(node) or vmath.vector3(1)
+-- @tparam bool include_passed_node_scale True if add current node scale to result
+-- @treturn vector3 The scene node scale
+function M.get_scene_scale(node, include_passed_node_scale)
+ local scale = include_passed_node_scale and gui.get_scale(node) or vmath.vector3(1)
local parent = gui.get_parent(node)
while parent do
scale = vmath.mul_per_elem(scale, gui.get_scale(parent))
@@ -319,6 +319,26 @@ function M.get_border(node, offset)
end
+--- Get text metric from gui node. Replacement of previous gui.get_text_metrics_from_node function
+-- @tparam Node text_node
+-- @treturn table {width, height, max_ascent, max_descent}
+function M.get_text_metrics_from_node(text_node)
+ local font_resource = gui.get_font_resource(gui.get_font(text_node))
+ local options = {
+ tracking = gui.get_tracking(text_node),
+ line_break = gui.get_line_break(text_node),
+ }
+
+ -- Gather other options only if it used in node
+ if options.line_break then
+ options.width = gui.get_size(text_node).x
+ options.leading = gui.get_leading(text_node)
+ end
+
+ return resource.get_text_metrics(font_resource, gui.get_text(text_node), options)
+end
+
+
--- Show deprecated message. Once time per message
-- @function helper.deprecated
-- @tparam string message The deprecated message
diff --git a/druid/styles/default/style.lua b/druid/styles/default/style.lua
index 0991ba4..6908005 100644
--- a/druid/styles/default/style.lua
+++ b/druid/styles/default/style.lua
@@ -114,6 +114,7 @@ M["input"] = {
BUTTON_SELECT_INCREASE = 1.06,
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
diff --git a/druid/system/druid_instance.lua b/druid/system/druid_instance.lua
index 7b838e0..a4004d4 100755
--- a/druid/system/druid_instance.lua
+++ b/druid/system/druid_instance.lua
@@ -194,6 +194,18 @@ local function process_input(self, action_id, action, components)
end
+local function schedule_late_init(self)
+ if self._late_init_timer_id then
+ return
+ end
+
+ self._late_init_timer_id = timer.delay(0, false, function()
+ self._late_init_timer_id = nil
+ self:late_init()
+ end)
+end
+
+
--- Druid class constructor
-- @tparam DruidInstance self
-- @tparam table context Druid context. Usually it is self of script
@@ -216,10 +228,6 @@ function DruidInstance.initialize(self, context, style)
for i = 1, #base_component.ALL_INTERESTS do
self.components_interest[base_component.ALL_INTERESTS[i]] = {}
end
-
- timer.delay(0, false, function()
- self:late_init()
- end)
end
@@ -245,6 +253,9 @@ function DruidInstance.new(self, component, ...)
if instance.init then
instance:init(...)
end
+ if instance.on_late_init or (not self.input_inited and instance.on_input) then
+ schedule_late_init(self)
+ end
return instance
end
@@ -316,7 +327,7 @@ function DruidInstance.remove(self, component)
end
---- Druid late update function call after init and before udpate step
+--- Druid late update function call after init and before update step
-- @tparam DruidInstance self
function DruidInstance.late_init(self)
local late_init_components = self.components_interest[base_component.ON_LATE_INIT]
@@ -570,7 +581,7 @@ end
-- @tparam node node Gui text node
-- @tparam[opt] string value Initial text. Default value is node text from GUI scene.
-- @tparam[opt] bool no_adjust If true, text will be not auto-adjust size
--- @treturn Tet text component
+-- @treturn Text text component
function DruidInstance.new_text(self, node, value, no_adjust)
return DruidInstance.new(self, text, node, value, no_adjust)
end
diff --git a/example/example.collection b/example/example.collection
index 097a84f..7c151e9 100644
--- a/example/example.collection
+++ b/example/example.collection
@@ -16,6 +16,8 @@ embedded_instances {
" z: 0.0\n"
" w: 1.0\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
""
position {
@@ -51,6 +53,8 @@ embedded_instances {
" z: 0.0\n"
" w: 1.0\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
""
position {
@@ -139,6 +143,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -202,6 +208,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -265,6 +273,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -328,6 +338,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -391,6 +403,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -454,6 +468,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -517,6 +533,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -580,6 +598,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -643,6 +663,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -706,6 +728,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -769,6 +793,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -832,6 +858,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -895,6 +923,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -958,6 +988,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1021,6 +1053,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1084,6 +1118,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1147,6 +1183,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1210,6 +1248,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1273,6 +1313,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1336,6 +1378,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1399,6 +1443,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1462,6 +1508,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1525,6 +1573,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1588,6 +1638,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1651,6 +1703,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1714,6 +1768,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1777,6 +1833,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1840,6 +1898,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1903,6 +1963,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -1966,6 +2028,8 @@ embedded_instances {
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
+ " property_decls {\n"
+ " }\n"
"}\n"
"embedded_components {\n"
" id: \"collectionfactory\"\n"
@@ -2003,3 +2067,198 @@ embedded_instances {
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"
+ " 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/system/late_init_check/late_init_check.collection\\\"\\n"
+ "load_dynamically: 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"
+ " 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/general/hover/hover.collection\\\"\\n"
+ "load_dynamically: 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"
+ " 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/texts/lang_text/lang_text.collection\\\"\\n"
+ "load_dynamically: 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/example.gui_script b/example/example.gui_script
index f583d3c..0e68862 100644
--- a/example/example.gui_script
+++ b/example/example.gui_script
@@ -132,6 +132,7 @@ local function init_lobby(self)
self.lobby_scroll = self.druid:new_scroll("lobby_view", "lobby_content")
self.lobby_grid = self.druid:new_dynamic_grid("lobby_content")
self.lobby_scroll:bind_grid(self.lobby_grid)
+ self.lobby_scroll.style.WHEEL_SCROLL_SPEED = 20
self.lobby_grid:add(get_title(self, "General examples"))
self.lobby_grid:add(get_button(self, "Overview", "general_overview", "/general/overview/overview.gui_script"))
@@ -144,6 +145,7 @@ local function init_lobby(self)
self.lobby_grid:add(get_button(self, "Checkboxes", "general_checkboxes", "/general/checkboxes/checkboxes.gui_script"))
self.lobby_grid:add(get_button(self, "Input text", "general_input", "/general/input/input.gui_script"))
self.lobby_grid:add(get_button(self, "Layout", "general_layout", "/general/layout/layout.gui_script"))
+ self.lobby_grid:add(get_button(self, "Hover", "general_hover", "/general/hover/hover.gui_script"))
self.lobby_grid:add(get_button(self, "Swipe", "general_swipe", "/general/swipe/swipe.gui_script"))
self.lobby_grid:add(get_button(self, "Drag", "general_drag", "/general/drag/drag.gui_script"))
self.lobby_grid:add(get_button(self, "Hotkey", "general_hotkey", "/general/hotkey/hotkey.gui_script"))
@@ -151,7 +153,7 @@ local function init_lobby(self)
self.lobby_grid:add(get_title(self, "Texts"))
self.lobby_grid:add(get_button(self, "Texts", "texts_general", "/texts/texts_general/texts_general.gui_script"))
self.lobby_grid:add(get_button(self, "Adjust types", "texts_adjust", "/texts/texts_adjust/texts_adjust.gui_script"))
- self.lobby_grid:add(get_button_disabled(self, "Lang Text", "texts_lang_text"))
+ self.lobby_grid:add(get_button(self, "Lang Text", "texts_lang_text", "/texts/texts_adjust/texts_lang_text.gui_script"))
self.lobby_grid:add(get_title(self, "Scrolls"))
self.lobby_grid:add(get_button_disabled(self, "Nested scrolls", "scroll_scene"))
@@ -188,6 +190,7 @@ local function init_lobby(self)
self.lobby_grid:add(get_button(self, "Message input", "system_message_input", "/system/message_input/message_input.gui_script"))
self.lobby_grid:add(get_button_disabled(self, "Input priority"))
self.lobby_grid:add(get_button(self, "Inner templates", "system_inner_templates", "/system/inner_templates/inner_templates.gui_script"))
+ self.lobby_grid:add(get_button(self, "Late init check", "system_late_init_check", "/system/late_init_check/late_init_check.gui_script"))
end
diff --git a/example/examples/general/hover/hover.collection b/example/examples/general/hover/hover.collection
new file mode 100644
index 0000000..e7a70b0
--- /dev/null
+++ b/example/examples/general/hover/hover.collection
@@ -0,0 +1,39 @@
+name: "hover"
+scale_along_z: 0
+embedded_instances {
+ id: "go"
+ data: "components {\n"
+ " id: \"hover\"\n"
+ " component: \"/example/examples/general/hover/hover.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
+ }
+}
diff --git a/example/examples/general/hover/hover.gui b/example/examples/general/hover/hover.gui
new file mode 100644
index 0000000..fa7239a
--- /dev/null
+++ b/example/examples/general/hover/hover.gui
@@ -0,0 +1,249 @@
+script: "/example/examples/general/hover/hover.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
+ 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: "hover_node"
+ parent: "root"
+ layer: ""
+ inherit_alpha: true
+ alpha: 1.0
+ template: "/example/templates/button.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: 200.0
+ y: 80.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/button_blue"
+ id: "hover_node/button"
+ xanchor: XANCHOR_NONE
+ yanchor: YANCHOR_NONE
+ pivot: PIVOT_CENTER
+ adjust_mode: ADJUST_MODE_FIT
+ parent: "hover_node"
+ layer: "image"
+ inherit_alpha: true
+ slice9 {
+ x: 15.0
+ y: 15.0
+ z: 15.0
+ w: 15.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: true
+}
+nodes {
+ position {
+ x: 0.0
+ y: 7.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: 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_TEXT
+ blend_mode: BLEND_MODE_ALPHA
+ text: "Hover me!"
+ font: "game"
+ id: "hover_node/text"
+ xanchor: XANCHOR_NONE
+ yanchor: YANCHOR_NONE
+ pivot: PIVOT_CENTER
+ outline {
+ x: 1.0
+ y: 1.0
+ z: 1.0
+ w: 1.0
+ }
+ shadow {
+ x: 0.101960786
+ y: 0.2
+ z: 0.6
+ w: 1.0
+ }
+ adjust_mode: ADJUST_MODE_FIT
+ line_break: false
+ parent: "hover_node/button"
+ layer: "text"
+ inherit_alpha: true
+ alpha: 1.0
+ outline_alpha: 0.0
+ shadow_alpha: 0.78
+ overridden_fields: 8
+ template_node_child: true
+ text_leading: 1.0
+ text_tracking: 0.0
+ custom_type: 0
+ enabled: true
+ visible: true
+}
+layers {
+ name: "image"
+}
+layers {
+ name: "text"
+}
+material: "/builtins/materials/gui.material"
+adjust_reference: ADJUST_REFERENCE_PARENT
+max_nodes: 512
diff --git a/example/examples/general/hover/hover.gui_script b/example/examples/general/hover/hover.gui_script
new file mode 100644
index 0000000..6b18a7e
--- /dev/null
+++ b/example/examples/general/hover/hover.gui_script
@@ -0,0 +1,41 @@
+local druid = require("druid.druid")
+
+
+function init(self)
+ self.druid = druid.new(self)
+
+ local hover = self.druid:new_hover("hover_node/button")
+
+ -- Usual hover respect to touch action on mobiles. On desktop we will use mouse hover
+ hover.on_mouse_hover:subscribe(function(_, is_hover, hover_instance)
+ print("is hover", is_hover)
+ local node = hover_instance.node
+ gui.animate(node, gui.PROP_SCALE, is_hover and vmath.vector3(1.2) or vmath.vector3(1), gui.EASING_OUTSINE, 0.2)
+ end)
+
+ local button = self.druid:new_button("hover_node/button", function()
+ print("Button clicked")
+ end)
+ -- Remove all animations from button, including button hover animations
+ button:set_style()
+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/system/late_init_check/late_init_check.collection b/example/examples/system/late_init_check/late_init_check.collection
new file mode 100644
index 0000000..9700af5
--- /dev/null
+++ b/example/examples/system/late_init_check/late_init_check.collection
@@ -0,0 +1,39 @@
+name: "late_init_check"
+scale_along_z: 0
+embedded_instances {
+ id: "go"
+ data: "components {\n"
+ " id: \"late_init_check\"\n"
+ " component: \"/example/examples/system/late_init_check/late_init_check.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
+ }
+}
diff --git a/example/examples/system/late_init_check/late_init_check.gui b/example/examples/system/late_init_check/late_init_check.gui
new file mode 100644
index 0000000..9869261
--- /dev/null
+++ b/example/examples/system/late_init_check/late_init_check.gui
@@ -0,0 +1,374 @@
+script: "/example/examples/system/late_init_check/late_init_check.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
+ 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: 500.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: "Late init system check\n"
+ "\n"
+ "Should capture input only after create first input component"
+ font: "game"
+ id: "text_hint"
+ 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: true
+ 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
+ custom_type: 0
+ enabled: true
+ visible: true
+}
+nodes {
+ position {
+ x: 0.0
+ y: -46.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: "prefab_button"
+ parent: "root"
+ layer: ""
+ inherit_alpha: true
+ alpha: 1.0
+ template: "/example/templates/button.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: 200.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: "kenney/button_blue"
+ id: "prefab_button/button"
+ xanchor: XANCHOR_NONE
+ yanchor: YANCHOR_NONE
+ pivot: PIVOT_CENTER
+ adjust_mode: ADJUST_MODE_FIT
+ parent: "prefab_button"
+ layer: "image"
+ inherit_alpha: true
+ slice9 {
+ x: 15.0
+ y: 15.0
+ z: 15.0
+ w: 15.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: true
+}
+nodes {
+ position {
+ x: 0.0
+ y: 7.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: 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_TEXT
+ blend_mode: BLEND_MODE_ALPHA
+ text: "Tap me!"
+ font: "game"
+ id: "prefab_button/text"
+ xanchor: XANCHOR_NONE
+ yanchor: YANCHOR_NONE
+ pivot: PIVOT_CENTER
+ outline {
+ x: 1.0
+ y: 1.0
+ z: 1.0
+ w: 1.0
+ }
+ shadow {
+ x: 0.101960786
+ y: 0.2
+ z: 0.6
+ w: 1.0
+ }
+ adjust_mode: ADJUST_MODE_FIT
+ line_break: false
+ parent: "prefab_button/button"
+ layer: "text"
+ inherit_alpha: true
+ alpha: 1.0
+ outline_alpha: 0.0
+ shadow_alpha: 0.78
+ 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: 400.0
+ y: 300.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: "grid"
+ 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
+}
+layers {
+ name: "image"
+}
+layers {
+ name: "text"
+}
+material: "/builtins/materials/gui.material"
+adjust_reference: ADJUST_REFERENCE_PARENT
+max_nodes: 512
diff --git a/example/examples/system/late_init_check/late_init_check.gui_script b/example/examples/system/late_init_check/late_init_check.gui_script
new file mode 100644
index 0000000..2820029
--- /dev/null
+++ b/example/examples/system/late_init_check/late_init_check.gui_script
@@ -0,0 +1,46 @@
+local druid = require("druid.druid")
+
+
+local function create_button(self, index)
+ local cloned = gui.clone_tree(self.prefab)
+ local root = cloned["prefab_button/button"]
+ self.grid:add(root)
+ gui.set_enabled(root, true)
+
+ local button = self.druid:new_button(root, function()
+ print("Created button with timer delay:", index)
+ end)
+ -- Override to check calls, don't do it in production ;)
+ button.on_late_init = function()
+ print("Late init button check", index)
+ end
+
+ print("Button created, is input inited now?", self.druid.input_inited)
+end
+
+
+function init(self)
+ self.druid = druid.new(self)
+
+ self.prefab = gui.get_node("prefab_button/button")
+ gui.set_enabled(self.prefab, false)
+
+ self.grid = self.druid:new_static_grid("grid", self.prefab, 1)
+
+ create_button(self, 0)
+ for index = 1, 4 do
+ timer.delay(index, false, function()
+ create_button(self, index)
+ end)
+ end
+end
+
+
+function final(self)
+ self.druid:final()
+end
+
+
+function on_input(self, action_id, action)
+ return self.druid:on_input(action_id, action)
+end
diff --git a/example/examples/texts/lang_text/lang_text.collection b/example/examples/texts/lang_text/lang_text.collection
new file mode 100644
index 0000000..aec1738
--- /dev/null
+++ b/example/examples/texts/lang_text/lang_text.collection
@@ -0,0 +1,39 @@
+name: "lang_text"
+scale_along_z: 0
+embedded_instances {
+ id: "go"
+ data: "components {\n"
+ " id: \"lang_text\"\n"
+ " component: \"/example/examples/texts/lang_text/lang_text.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
+ }
+}
diff --git a/example/examples/texts/lang_text/lang_text.gui b/example/examples/texts/lang_text/lang_text.gui
new file mode 100644
index 0000000..5c4429c
--- /dev/null
+++ b/example/examples/texts/lang_text/lang_text.gui
@@ -0,0 +1,514 @@
+script: "/example/examples/texts/lang_text/lang_text.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
+ custom_type: 0
+ enabled: true
+ visible: true
+}
+nodes {
+ position {
+ x: 6.0
+ y: 241.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: "button_change_lang"
+ parent: "root"
+ layer: ""
+ inherit_alpha: true
+ alpha: 1.0
+ template: "/example/templates/button.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: 200.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: "kenney/button_blue"
+ id: "button_change_lang/button"
+ xanchor: XANCHOR_NONE
+ yanchor: YANCHOR_NONE
+ pivot: PIVOT_CENTER
+ adjust_mode: ADJUST_MODE_FIT
+ parent: "button_change_lang"
+ layer: "image"
+ inherit_alpha: true
+ slice9 {
+ x: 15.0
+ y: 15.0
+ z: 15.0
+ w: 15.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: true
+}
+nodes {
+ position {
+ x: 0.0
+ y: 7.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: 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_TEXT
+ blend_mode: BLEND_MODE_ALPHA
+ text: "Change lang"
+ font: "game"
+ id: "button_change_lang/text"
+ xanchor: XANCHOR_NONE
+ yanchor: YANCHOR_NONE
+ pivot: PIVOT_CENTER
+ outline {
+ x: 1.0
+ y: 1.0
+ z: 1.0
+ w: 1.0
+ }
+ shadow {
+ x: 0.101960786
+ y: 0.2
+ z: 0.6
+ w: 1.0
+ }
+ adjust_mode: ADJUST_MODE_FIT
+ line_break: false
+ parent: "button_change_lang/button"
+ layer: "text"
+ inherit_alpha: true
+ alpha: 1.0
+ outline_alpha: 0.0
+ shadow_alpha: 0.78
+ overridden_fields: 2
+ 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: 147.0
+ z: 0.0
+ w: 1.0
+ }
+ rotation {
+ x: 0.0
+ y: 0.0
+ z: 0.0
+ w: 1.0
+ }
+ scale {
+ x: 0.6
+ y: 0.6
+ z: 1.0
+ w: 1.0
+ }
+ size {
+ x: 500.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: "Current lang: en"
+ font: "game"
+ id: "text_current_lang"
+ 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
+ custom_type: 0
+ enabled: true
+ visible: true
+}
+nodes {
+ position {
+ x: 0.0
+ y: -20.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_TEXT
+ blend_mode: BLEND_MODE_ALPHA
+ text: "Example 1"
+ font: "game"
+ id: "text_example_1"
+ 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
+ custom_type: 0
+ enabled: true
+ visible: true
+}
+nodes {
+ position {
+ x: 0.0
+ y: -150.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_TEXT
+ blend_mode: BLEND_MODE_ALPHA
+ text: "Example 2"
+ font: "game"
+ id: "text_example_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: 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: 1.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: -270.0
+ z: 0.0
+ w: 1.0
+ }
+ rotation {
+ x: 0.0
+ y: 0.0
+ z: 0.0
+ w: 1.0
+ }
+ scale {
+ x: 0.6
+ y: 0.6
+ 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: "Example 3"
+ font: "game"
+ id: "text_example_3"
+ 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: true
+ 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
+ custom_type: 0
+ enabled: true
+ visible: true
+}
+layers {
+ name: "image"
+}
+layers {
+ name: "text"
+}
+material: "/builtins/materials/gui.material"
+adjust_reference: ADJUST_REFERENCE_PARENT
+max_nodes: 512
diff --git a/example/examples/texts/lang_text/lang_text.gui_script b/example/examples/texts/lang_text/lang_text.gui_script
new file mode 100644
index 0000000..f62a95f
--- /dev/null
+++ b/example/examples/texts/lang_text/lang_text.gui_script
@@ -0,0 +1,50 @@
+local druid = require("druid.druid")
+local druid_const = require("druid.const")
+local lang = require("example.lang")
+
+
+local function refresh_lang_text(self)
+ self.text_current:format(lang.get_locale("ui_lang"))
+end
+
+
+function init(self)
+ self.druid = druid.new(self)
+
+ self.text_current = self.druid:new_lang_text("text_current_lang", "ui_current_lang")
+ self.text_example_1 = self.druid:new_lang_text("text_example_1", "ui_example_1")
+ self.text_example_2 = self.druid:new_lang_text("text_example_2", "ui_example_2")
+ self.text_example_3 = self.druid:new_lang_text("text_example_3", "ui_example_3")
+ self.text_example_3:format(10, 20, 30)
+
+ refresh_lang_text(self)
+
+ self.current_lang = lang.get_locale()
+ self.druid:new_button("button_change_lang/button", lang.toggle_locale)
+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)
+ -- If we have localized text in text formatting, we should update it manually
+ -- If we have non localized text, the lang_text:format or :translate will update text manually again
+ if message_id == hash(druid_const.ON_LANGUAGE_CHANGE) then
+ refresh_lang_text(self)
+ end
+
+ 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/lang.lua b/example/lang.lua
index 1cc60ce..a790951 100644
--- a/example/lang.lua
+++ b/example/lang.lua
@@ -3,6 +3,8 @@ local druid = require("druid.druid")
local M = {}
local en = {
+ ui_lang = "En",
+ ui_current_lang = "Current lang: %s",
main_page = "Main page",
texts_page = "Text page",
button_page = "Button page",
@@ -21,9 +23,14 @@ local en = {
ui_section_input = "Input",
ui_text_example = "Translated",
ui_text_change_lang = "Change lang",
+ ui_example_1 = "Some text example",
+ ui_example_2 = "Lang text with different length to be adjusted",
+ ui_example_3 = "Text with 3 params: %s, %s and %s",
}
local ru = {
+ ui_lang = "Ру",
+ ui_current_lang = "Текущий язык: %s",
main_page = "Основное",
texts_page = "Текст",
button_page = "Кнопки",
@@ -42,6 +49,9 @@ local ru = {
ui_section_input = "Ввод текста",
ui_text_example = "Переведен",
ui_text_change_lang = "Сменить язык",
+ ui_example_1 = "Пример текста",
+ ui_example_2 = "Короткий текст",
+ ui_example_3 = "Текст с 3 параметрами: %s, %s и %s",
}
@@ -64,4 +74,5 @@ function M.toggle_locale()
druid.on_language_change()
end
+
return M
diff --git a/game.project b/game.project
index d5aaf3a..3e4b2d6 100644
--- a/game.project
+++ b/game.project
@@ -36,9 +36,9 @@ input_key_esc = key_esc
input_key_back = key_back
input_key_enter = key_enter
input_key_backspace = key_backspace
-input_multitouch = multitouch
-input_scroll_up = scroll_up
-input_scroll_down = scroll_down
+input_multitouch = touch_multi
+input_scroll_up = mouse_wheel_up
+input_scroll_down = mouse_wheel_down
[html5]
engine_arguments = --verify-graphics-calls=false
diff --git a/input/game.input_binding b/input/game.input_binding
index a6d0b3a..e42b4b5 100644
--- a/input/game.input_binding
+++ b/input/game.input_binding
@@ -32,11 +32,11 @@ key_trigger {
}
mouse_trigger {
input: MOUSE_WHEEL_UP
- action: "scroll_up"
+ action: "mouse_wheel_up"
}
mouse_trigger {
input: MOUSE_WHEEL_DOWN
- action: "scroll_down"
+ action: "mouse_wheel_down"
}
mouse_trigger {
input: MOUSE_BUTTON_1
@@ -44,7 +44,7 @@ mouse_trigger {
}
touch_trigger {
input: TOUCH_MULTI
- action: "multitouch"
+ action: "touch_multi"
}
text_trigger {
input: TEXT
diff --git a/media/input_binding_1.png b/media/input_binding_1.png
index aa0856a..ca902e9 100644
Binary files a/media/input_binding_1.png and b/media/input_binding_1.png differ
diff --git a/settings_deployer b/settings_deployer
index 36568b5..f54021b 100644
--- a/settings_deployer
+++ b/settings_deployer
@@ -1,4 +1,4 @@
#!/bin/bash
use_latest_bob=false
enable_incremental_version=true
-bob_sha="3.0:0e77ba11ac957ee01878bbde2e6ac0c9fae6dc01"
+bob_sha="4.0:f4a699eb412a2445e894568f2d7466aba61b4c41"