Inline helper.is_enabled, remove unused code, documentation fixes, remove formats and druid_input files, add more tests

This commit is contained in:
Insality 2023-07-15 11:53:07 +03:00
parent c01ee189b4
commit 38c117b9d8
20 changed files with 275 additions and 134 deletions

View File

@ -2,7 +2,7 @@ std = "max"
files['.luacheckrc'].global = false files['.luacheckrc'].global = false
unused_args = false unused_args = false
max_code_line_length = 90 max_code_line_length = 120
max_comment_line_length = false max_comment_line_length = false
globals = { globals = {

View File

@ -71,6 +71,7 @@ function on_message(self, message_id, message, sender)
end end
-- "on_input" is used in almost all Druid components -- "on_input" is used in almost all Druid components
-- The return value from `druid:on_input` is required!
function on_input(self, action_id, action) function on_input(self, action_id, action)
return self.druid:on_input(action_id, action) return self.druid:on_input(action_id, action)
end end
@ -190,6 +191,7 @@ 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**. 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 ## Documentation

View File

@ -459,6 +459,14 @@ This version is the most basic one. Honestly, just wanna to publish current vers
Another addition is the ability to enable the "HTML mode" for the Button component. In this mode, the button's action occurs in the context of `user action`, allowing operations like "copy and paste text" "show the keyboard" and more. However, in this mode, the button only responds to regular clicks due to the technical implementation of it (so no double clicks or long taps). Another addition is the ability to enable the "HTML mode" for the Button component. In this mode, the button's action occurs in the context of `user action`, allowing operations like "copy and paste text" "show the keyboard" and more. However, in this mode, the button only responds to regular clicks due to the technical implementation of it (so no double clicks or long taps).
The huge work was done on documentation. Now it's more clear and have more examples. All documentation now moved to the API section. The separate `componentd.md` file will be deleted soon as all documentation will be moved to the API section.
The API section now filled with overview and usage examples. I've started with the basic modules, in future I will add more examples for all modules.
Also, I've added the Unit Tests. It's not cover all **Druid** code, but it's a good start! 🎉
I have the feedback form for you, please fill it if you have a free minute. It will help me to improve **Druid** in future. %LINK HERE%
**Changelog 0.11.0** **Changelog 0.11.0**
@ -473,9 +481,10 @@ Another addition is the ability to enable the "HTML mode" for the Button compone
- Now if you will open the example from direct URL, it will be updated to the current URL. So now it's much easier to share the example link with each other. - Now if you will open the example from direct URL, it will be updated to the current URL. So now it's much easier to share the example link with each other.
- **#183**: Documentation about GUI in World Space - **#183**: Documentation about GUI in World Space
- Also not only the GUI in World Space, but overall How to GUI in Defold article. - Also not only the GUI in World Space, but overall How to GUI in Defold article.
- **#199**: Having to click twice to unselect one input field and select another - **#234**: [BREAKING][Blocker] Now `blocker:set_enabled` and `blocker:is_enabled` affects only inner state of component. To consume input, the blocker component should be enabled and the node itself should be enabled.
- **#115**: Add debug mode for druid/druid_instance/components - **#235**: [Drag] Fix Drag coordinates on streched screen
- **#129**: Remove sound function, move inside styles - **#236**: [Hover] Fix nil return in `hover:on_input`
- **#226**: Data List remove function issue - **#237**: [Layout] Add `layout:set_max_gui_upscale` function
- **#238**: [System] Add Helper documentation
If you like **Druid**, please, consider to support me!

8
docs_md/game_examples.md Normal file
View File

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

View File

@ -189,7 +189,7 @@ local druid__button = {}
---@return hash The action_id of the input key ---@return hash The action_id of the input key
function druid__button.get_key_trigger(self) end function druid__button.get_key_trigger(self) end
--- @{Button} constructor --- The @{Button} constructor
---@param self druid.button @{Button} ---@param self druid.button @{Button}
---@param node string|Node Node name or GUI Node itself ---@param node string|Node Node name or GUI Node itself
---@param callback function On click button callback ---@param callback function On click button callback

View File

@ -20,7 +20,7 @@
-- @within BaseComponent -- @within BaseComponent
-- @alias druid.back_handler -- @alias druid.back_handler
--- @{DruidEvent} Event on back handler action. --- The @{DruidEvent} Event on back handler action.
-- --
-- Trigger on input action ACTION_BACK or ACTION_BACKSPACE -- Trigger on input action ACTION_BACK or ACTION_BACKSPACE
-- @usage -- @usage
@ -43,7 +43,7 @@ local component = require("druid.component")
local BackHandler = component.create("back_handler") local BackHandler = component.create("back_handler")
--- @{BackHandler} constructor --- The @{BackHandler} constructor
-- @tparam BackHandler self @{BackHandler} -- @tparam BackHandler self @{BackHandler}
-- @tparam callback callback On back button -- @tparam callback callback On back button
-- @tparam[opt] any custom_args Button events custom arguments -- @tparam[opt] any custom_args Button events custom arguments

View File

@ -35,7 +35,7 @@
-- @alias druid.button -- @alias druid.button
--- @{DruidEvent}: Event on successful release action over button. --- The @{DruidEvent}: Event on successful release action over button.
-- @usage -- @usage
-- -- Custom args passed in Button constructor -- -- Custom args passed in Button constructor
-- button.on_click:subscribe(function(self, custom_args, button_instance) -- button.on_click:subscribe(function(self, custom_args, button_instance)
@ -44,7 +44,7 @@
-- @tfield DruidEvent on_click @{DruidEvent} -- @tfield DruidEvent on_click @{DruidEvent}
--- @{DruidEvent}: Event on repeated action over button. --- The @{DruidEvent}: Event on repeated action over button.
-- --
-- This callback will be triggered if user hold the button. The repeat rate pick from `input.repeat_interval` in game.project -- This callback will be triggered if user hold the button. The repeat rate pick from `input.repeat_interval` in game.project
-- @usage -- @usage
@ -55,7 +55,7 @@
-- @tfield DruidEvent on_repeated_click @{DruidEvent} -- @tfield DruidEvent on_repeated_click @{DruidEvent}
--- @{DruidEvent}: Event on long tap action over button. --- The @{DruidEvent}: Event on long tap action over button.
-- --
-- This callback will be triggered if user pressed the button and hold the some amount of time. -- This callback will be triggered if user pressed the button and hold the some amount of time.
-- The amount of time picked from button style param: LONGTAP_TIME -- The amount of time picked from button style param: LONGTAP_TIME
@ -67,7 +67,7 @@
-- @tfield DruidEvent on_long_click @{DruidEvent} -- @tfield DruidEvent on_long_click @{DruidEvent}
--- @{DruidEvent}: Event on double tap action over button. --- The @{DruidEvent}: Event on double tap action over button.
-- --
-- If secondary click was too fast after previous one, the double -- If secondary click was too fast after previous one, the double
-- click will be called instead usual click (if on_double_click subscriber exists) -- click will be called instead usual click (if on_double_click subscriber exists)
@ -79,7 +79,7 @@
-- @tfield DruidEvent on_double_click @{DruidEvent} -- @tfield DruidEvent on_double_click @{DruidEvent}
--- @{DruidEvent}: Event calls every frame before on_long_click event. --- The @{DruidEvent}: Event calls every frame before on_long_click event.
-- --
-- If long_click subscriber exists, the on_hold_callback will be called before long_click trigger. -- If long_click subscriber exists, the on_hold_callback will be called before long_click trigger.
-- --
@ -92,7 +92,7 @@
-- @tfield DruidEvent on_hold_callback @{DruidEvent} -- @tfield DruidEvent on_hold_callback @{DruidEvent}
--- @{DruidEvent}: Event calls if click event was outside of button. --- The @{DruidEvent}: Event calls if click event was outside of button.
-- --
-- This event will be triggered for each button what was not clicked on user click action -- This event will be triggered for each button what was not clicked on user click action
-- --
@ -105,7 +105,7 @@
-- @tfield DruidEvent on_click_outside @{DruidEvent} -- @tfield DruidEvent on_click_outside @{DruidEvent}
--- @{DruidEvent}: Event triggered if button was pressed by user. --- The @{DruidEvent}: Event triggered if button was pressed by user.
-- @usage -- @usage
-- -- Custom args passed in Button constructor -- -- Custom args passed in Button constructor
-- button.on_pressed:subscribe(function(self, custom_args, button_instance) -- button.on_pressed:subscribe(function(self, custom_args, button_instance)
@ -128,7 +128,7 @@
---Custom args for any Button event. Setup in Button constructor ---Custom args for any Button event. Setup in Button constructor
-- @tfield any params -- @tfield any params
--- @{Hover}: Button Hover component --- The @{Hover}: Button Hover component
-- @tfield Hover hover @{Hover} -- @tfield Hover hover @{Hover}
--- Additional button click area, defined by another GUI Node --- Additional button click area, defined by another GUI Node
@ -276,7 +276,7 @@ function Button.on_style_change(self, style)
end end
--- @{Button} constructor --- The @{Button} constructor
-- @tparam Button self @{Button} -- @tparam Button self @{Button}
-- @tparam string|Node node Node name or GUI Node itself -- @tparam string|Node node Node name or GUI Node itself
-- @tparam function callback On click button callback -- @tparam function callback On click button callback
@ -329,7 +329,7 @@ function Button.on_input(self, action_id, action)
return false return false
end end
if not helper.is_enabled(self.node) then if not gui.is_enabled(self.node, true) then
return false return false
end end
@ -414,7 +414,7 @@ end
function Button.on_message_input(self, node_id, message) function Button.on_message_input(self, node_id, message)
if node_id ~= self.node_id or self.disabled or not helper.is_enabled(self.node) then if node_id ~= self.node_id or self.disabled or not gui.is_enabled(self.node) then
return false return false
end end

View File

@ -73,7 +73,11 @@ end
local function end_touch(self) local function end_touch(self)
if self.is_drag then if self.is_drag then
self.on_drag_end:trigger(self:get_context(), self.x - self.touch_start_pos.x, self.y - self.touch_start_pos.y) self.on_drag_end:trigger(
self:get_context(),
self.x - self.touch_start_pos.x,
self.y - self.touch_start_pos.y
)
end end
self.is_drag = false self.is_drag = false
@ -229,7 +233,7 @@ function Drag.on_input(self, action_id, action)
return false return false
end end
if not helper.is_enabled(self.node) or self._is_disabled then if not gui.is_enabled(self.node, true) or self._is_disabled then
return false return false
end end

View File

@ -58,7 +58,7 @@ function Hover.on_input(self, action_id, action)
return false return false
end end
if not helper.is_enabled(self.node) or not self._is_enabled then if not gui.is_enabled(self.node, true) or not self._is_enabled then
self:set_hover(false) self:set_hover(false)
self:set_mouse_hover(false) self:set_mouse_hover(false)
return false return false

View File

@ -1,16 +1,17 @@
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license -- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle component's position by row and columns. --- Component to handle component's position by row and columns.
-- ## Overview ## -- <b># Overview #</b>
-- --
-- The Static Grid component allows for positioning components in rows and columns. -- The Static Grid component allows for positioning components in rows and columns.
-- It provides a static grid layout with constant node sizes, allowing for pre-calculated -- It provides a static grid layout with constant node sizes, allowing for pre-calculated
-- node positions and the option to include gaps between nodes. -- node positions and the option to include gaps between nodes.
-- --
-- ## Notes ## -- <b># Notes #</b>
-- --
-- • In a static grid, the node size remains constant, enabling the calculation of node -- • In a static grid, the node size remains constant, enabling the calculation of node
-- positions before placement. Nodes can be placed with gaps between them. -- positions before placement. If you want add gaps between nodes, increase the root prefab size,
-- including the padding and margin.
-- --
-- • The static grid can automatically shift elements when nodes are added or removed. -- • The static grid can automatically shift elements when nodes are added or removed.
-- --
@ -110,7 +111,7 @@ function StaticGrid.on_style_change(self, style)
end end
--- @{StaticGrid} constructor --- The @{StaticGrid} constructor
-- @tparam StaticGrid self @{StaticGrid} -- @tparam StaticGrid self @{StaticGrid}
-- @tparam string|Node parent The GUI Node container, where grid's items will be placed -- @tparam string|Node parent The GUI Node container, where grid's items will be placed
-- @tparam node element Element prefab. Need to get it size -- @tparam node element Element prefab. Need to get it size

View File

@ -116,7 +116,7 @@ function Swipe.on_input(self, action_id, action)
return false return false
end end
if not helper.is_enabled(self.node) then if not gui.is_enabled(self.node, true) then
return false return false
end end

View File

@ -31,13 +31,19 @@
--- ---
local Event = require("druid.event") local Event = require("druid.event")
local formats = require("druid.helper.formats")
local helper = require("druid.helper") local helper = require("druid.helper")
local component = require("druid.component") local component = require("druid.component")
local Timer = component.create("timer") local Timer = component.create("timer")
local function second_string_min(sec)
local mins = math.floor(sec / 60)
local seconds = math.floor(sec - mins * 60)
return string.format("%.2d:%.2d", mins, seconds)
end
--- Component init function --- Component init function
-- @tparam Timer self @{Timer} -- @tparam Timer self @{Timer}
-- @tparam node node Gui text node -- @tparam node node Gui text node
@ -98,7 +104,7 @@ end
-- @tparam number set_to Value in seconds -- @tparam number set_to Value in seconds
function Timer.set_to(self, set_to) function Timer.set_to(self, set_to)
self.last_value = set_to self.last_value = set_to
gui.set_text(self.node, formats.second_string_min(set_to)) gui.set_text(self.node, second_string_min(set_to))
end end

View File

@ -10,7 +10,6 @@
local const = require("druid.const") local const = require("druid.const")
local M = {} local M = {}
M._some = { pepepe = true }
local function get_text_width(text_node) local function get_text_width(text_node)
@ -261,17 +260,6 @@ function M.get_scaled_size(node)
end end
--- Check if node is enabled in GUI hierarchy.
--
-- Return false, if node or any his parent is disabled
-- @function helper.is_enabled
-- @tparam node node GUI node
-- @treturn bool Is enabled in hierarchy
function M.is_enabled(node)
return gui.is_enabled(node, true)
end
--- Get cumulative parent's node scale --- Get cumulative parent's node scale
-- @function helper.get_scene_scale -- @function helper.get_scene_scale
-- @tparam node node Gui node -- @tparam node node Gui node
@ -394,7 +382,7 @@ end
--- Get text metric from GUI node. --- Get text metric from GUI node.
-- @function helper.get_text_metrics_from_node -- @function helper.get_text_metrics_from_node
-- @tparam Node text_node -- @tparam Node text_node
-- @treturn pepepe -- @treturn GUITextMetrics
-- @usage -- @usage
-- type GUITextMetrics = { -- type GUITextMetrics = {
-- width: number, -- width: number,
@ -498,12 +486,14 @@ function M.deprecated(message)
end end
--- Show message to require extended component --- Show message to require component
-- @local -- @local
function M.extended_component(component_name) function M.require_component_message(component_name, component_type)
print(string.format("[Druid]: The component %s is extended component. You have to register it via druid.register to use it", component_name)) component_type = component_type or "extended"
print(string.format("[Druid]: The component %s is %s component. You have to register it via druid.register to use it", component_name, component_type))
print("[Druid]: Use next code:") print("[Druid]: Use next code:")
print(string.format('local %s = require("druid.extended.%s")', component_name, component_name)) print(string.format('local %s = require("druid.%s.%s")', component_name, component_type, component_name))
print(string.format('druid.register("%s", %s)', component_name, component_name)) print(string.format('druid.register("%s", %s)', component_name, component_name))
end end

View File

@ -1,24 +0,0 @@
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid inner module to acquire/release input
-- @module helper.input
-- @local
local M = {}
local ADD_FOCUS = hash("acquire_input_focus")
local REMOVE_FOCUS = hash("release_input_focus")
local PATH_OBJ = "."
function M.focus()
msg.post(PATH_OBJ, ADD_FOCUS)
end
function M.remove()
msg.post(PATH_OBJ, REMOVE_FOCUS)
end
return M

View File

@ -1,47 +0,0 @@
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Druid module with utils on string formats
-- @local
-- @module helper.formats
local const = require("druid.const")
local M = {}
--- Return number with zero number prefix
-- @function formats.add_prefix_zeros
-- @tparam number num Number for conversion
-- @tparam number count Count of numerals
-- @return string with need count of zero (1,3) -> 001
function M.add_prefix_zeros(num, count)
local result = tostring(num)
for i = string.len(result), count - 1 do
result = const.ZERO .. result
end
return result
end
--- Convert seconds to string minutes:seconds
-- @function formats.second_string_min
-- @tparam number sec Seconds
-- @return string minutes:seconds
function M.second_string_min(sec)
local mins = math.floor(sec / 60)
local seconds = math.floor(sec - mins * 60)
return string.format("%.2d:%.2d", mins, seconds)
end
--- Interpolate string with named Parameters in Table
-- @function formats.second_string_min
-- @tparam string s Target string
-- @tparam table tab Table with parameters
-- @return string with replaced parameters
function M.interpolate_string(s, tab)
return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end))
end
return M

View File

@ -71,7 +71,6 @@ local helper = require("druid.helper")
local class = require("druid.system.middleclass") local class = require("druid.system.middleclass")
local settings = require("druid.system.settings") local settings = require("druid.system.settings")
local base_component = require("druid.component") local base_component = require("druid.component")
local druid_input = require("druid.helper.druid_input")
local drag = require("druid.base.drag") local drag = require("druid.base.drag")
local text = require("druid.base.text") local text = require("druid.base.text")
@ -97,6 +96,9 @@ local back_handler = require("druid.base.back_handler")
local DruidInstance = class("druid.druid_instance") local DruidInstance = class("druid.druid_instance")
local PATH_OBJ = "."
local MSG_ADD_FOCUS = hash("acquire_input_focus")
local MSG_REMOVE_FOCUS = hash("release_input_focus")
local IS_NO_AUTO_INPUT = sys.get_config_int("druid.no_auto_input", 0) == 1 local IS_NO_AUTO_INPUT = sys.get_config_int("druid.no_auto_input", 0) == 1
local function set_input_state(self, is_input_inited) local function set_input_state(self, is_input_inited)
@ -106,9 +108,9 @@ local function set_input_state(self, is_input_inited)
self.input_inited = is_input_inited self.input_inited = is_input_inited
if is_input_inited then if is_input_inited then
druid_input.focus() msg.post(PATH_OBJ, MSG_ADD_FOCUS)
else else
druid_input.remove() msg.post(PATH_OBJ, MSG_REMOVE_FOCUS)
end end
end end
@ -659,7 +661,7 @@ end
-- @tparam function on_swipe_callback Swipe callback for on_swipe_end event -- @tparam function on_swipe_callback Swipe callback for on_swipe_end event
-- @treturn Swipe @{Swipe} component -- @treturn Swipe @{Swipe} component
function DruidInstance.new_swipe(self, node, on_swipe_callback) function DruidInstance.new_swipe(self, node, on_swipe_callback)
return helper.extended_component("swipe") return helper.require_component_message("swipe")
end end
@ -668,7 +670,7 @@ end
-- @tparam node parent The gui node parent, where items will be placed -- @tparam node parent The gui node parent, where items will be placed
-- @treturn DynamicGrid @{DynamicGrid} component -- @treturn DynamicGrid @{DynamicGrid} component
function DruidInstance.new_dynamic_grid(self, parent) function DruidInstance.new_dynamic_grid(self, parent)
return helper.extended_component("dynamic_grid") return helper.require_component_message("dynamic_grid")
end end
@ -679,7 +681,7 @@ end
-- @tparam bool no_adjust If true, will not correct text size -- @tparam bool no_adjust If true, will not correct text size
-- @treturn LangText @{LangText} component -- @treturn LangText @{LangText} component
function DruidInstance.new_lang_text(self, node, locale_id, no_adjust) function DruidInstance.new_lang_text(self, node, locale_id, no_adjust)
return helper.extended_component("lang_text") return helper.require_component_message("lang_text")
end end
@ -690,7 +692,7 @@ end
-- @tparam[opt] function callback On slider change callback -- @tparam[opt] function callback On slider change callback
-- @treturn Slider @{Slider} component -- @treturn Slider @{Slider} component
function DruidInstance.new_slider(self, node, end_pos, callback) function DruidInstance.new_slider(self, node, end_pos, callback)
return helper.extended_component("slider") return helper.require_component_message("slider")
end end
@ -702,7 +704,7 @@ end
-- @tparam[opt=false] boolean initial_state The initial state of checkbox, default - false -- @tparam[opt=false] boolean initial_state The initial state of checkbox, default - false
-- @treturn Checkbox @{Checkbox} component -- @treturn Checkbox @{Checkbox} component
function DruidInstance.new_checkbox(self, node, callback, click_node, initial_state) function DruidInstance.new_checkbox(self, node, callback, click_node, initial_state)
return helper.extended_component("checkbox") return helper.require_component_message("checkbox")
end end
@ -713,7 +715,7 @@ end
-- @tparam[opt] number keyboard_type Gui keyboard type for input field -- @tparam[opt] number keyboard_type Gui keyboard type for input field
-- @treturn Input @{Input} component -- @treturn Input @{Input} component
function DruidInstance.new_input(self, click_node, text_node, keyboard_type) function DruidInstance.new_input(self, click_node, text_node, keyboard_type)
return helper.extended_component("input") return helper.require_component_message("input")
end end
@ -724,7 +726,7 @@ end
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes -- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
-- @treturn CheckboxGroup @{CheckboxGroup} component -- @treturn CheckboxGroup @{CheckboxGroup} component
function DruidInstance.new_checkbox_group(self, nodes, callback, click_nodes) function DruidInstance.new_checkbox_group(self, nodes, callback, click_nodes)
return helper.extended_component("checkbox_group") return helper.require_component_message("checkbox_group")
end end
@ -735,7 +737,7 @@ end
-- @tparam function create_function The create function callback(self, data, index, data_list). Function should return (node, [component]) -- @tparam function create_function The create function callback(self, data, index, data_list). Function should return (node, [component])
-- @treturn DataList @{DataList} component -- @treturn DataList @{DataList} component
function DruidInstance.new_data_list(self, druid_scroll, druid_grid, create_function) function DruidInstance.new_data_list(self, druid_scroll, druid_grid, create_function)
return helper.extended_component("data_list") return helper.require_component_message("data_list")
end end
@ -746,7 +748,7 @@ end
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes -- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
-- @treturn RadioGroup @{RadioGroup} component -- @treturn RadioGroup @{RadioGroup} component
function DruidInstance.new_radio_group(self, nodes, callback, click_nodes) function DruidInstance.new_radio_group(self, nodes, callback, click_nodes)
return helper.extended_component("radio_group") return helper.require_component_message("radio_group")
end end
@ -758,7 +760,7 @@ end
-- @tparam[opt] function callback Function on timer end -- @tparam[opt] function callback Function on timer end
-- @treturn Timer @{Timer} component -- @treturn Timer @{Timer} component
function DruidInstance.new_timer(self, node, seconds_from, seconds_to, callback) function DruidInstance.new_timer(self, node, seconds_from, seconds_to, callback)
return helper.extended_component("timer") return helper.require_component_message("timer")
end end
@ -769,7 +771,7 @@ end
-- @tparam[opt=1] number init_value Initial value of progress bar -- @tparam[opt=1] number init_value Initial value of progress bar
-- @treturn Progress @{Progress} component -- @treturn Progress @{Progress} component
function DruidInstance.new_progress(self, node, key, init_value) function DruidInstance.new_progress(self, node, key, init_value)
return helper.extended_component("progress") return helper.require_component_message("progress")
end end
@ -779,7 +781,7 @@ end
-- @tparam string mode The layout mode -- @tparam string mode The layout mode
-- @treturn Layout @{Layout} component -- @treturn Layout @{Layout} component
function DruidInstance.new_layout(self, node, mode) function DruidInstance.new_layout(self, node, mode)
return helper.extended_component("layout") return helper.require_component_message("layout")
end end
@ -790,7 +792,18 @@ end
-- @tparam[opt] value params Button callback params -- @tparam[opt] value params Button callback params
-- @treturn Hotkey @{Hotkey} component -- @treturn Hotkey @{Hotkey} component
function DruidInstance.new_hotkey(self, keys_array, callback, params) function DruidInstance.new_hotkey(self, keys_array, callback, params)
return helper.extended_component("hotkey") return helper.require_component_message("hotkey")
end
--- Create @{RichText} component.
-- As a template please check rich_text.gui layout.
-- @tparam DruidInstance self
-- @tparam[opt] string template Template name if used
-- @tparam[opt] table<hash, node> nodes Nodes table from gui.clone_tree
-- @treturn Hotkey @{RichText} component
function DruidInstance.new_hotkey(self, template, nodes)
return helper.require_component_message("rich_text", "custom")
end end

View File

@ -5,6 +5,9 @@ local tests = {
require("test.tests.test_button"), require("test.tests.test_button"),
require("test.tests.test_hover"), require("test.tests.test_hover"),
require("test.tests.test_drag"), require("test.tests.test_drag"),
require("test.tests.test_back_handler"),
require("test.tests.test_blocker"),
--require("test.tests.test_static_grid"),
} }

View File

@ -0,0 +1,40 @@
local mock_gui = require "deftest.mock.gui"
local mock_time = require("deftest.mock.time")
local mock_input = require("test.helper.mock_input")
local test_helper = require("test.helper.test_helper")
local druid_system = require("druid.druid")
return function()
local druid = nil
local context = test_helper.get_context()
describe("Back Handler component", function()
before(function()
mock_gui.mock()
mock_time.mock()
mock_time.set(60)
druid = druid_system.new(context)
end)
after(function()
mock_gui.unmock()
mock_time.unmock()
druid:final(context)
druid = nil
end)
it("Should react on back action id with custom args", function()
local on_back_handler, on_back_handler_mock = test_helper.get_function()
druid:new_back_handler(on_back_handler, { args = "custom" })
druid:on_input(mock_input.key_pressed("key_back"))
druid:on_input(mock_input.key_released("key_back"))
assert(on_back_handler_mock.calls == 1)
assert(on_back_handler_mock.params[1] == context)
assert(on_back_handler_mock.params[2].args == "custom")
druid:on_input(mock_input.key_pressed("key_a"))
druid:on_input(mock_input.key_released("key_a"))
assert(on_back_handler_mock.calls == 1)
end)
end)
end

View File

@ -0,0 +1,93 @@
local mock_gui = require "deftest.mock.gui"
local mock_time = require("deftest.mock.time")
local mock_input = require("test.helper.mock_input")
local test_helper = require("test.helper.test_helper")
local druid_system = require("druid.druid")
return function()
local druid = nil
local context = test_helper.get_context()
describe("Blocker component", function()
before(function()
mock_gui.mock()
mock_time.mock()
mock_time.set(60)
druid = druid_system.new(context)
end)
after(function()
mock_gui.unmock()
mock_time.unmock()
druid:final(context)
druid = nil
end)
it("Should consume input", function()
local button_node = mock_gui.add_box("button", 0, 0, 100, 50)
local blocker_node = mock_gui.add_box("blocker", 20, 20, 20, 20)
local on_click, on_click_mock = test_helper.get_function()
druid:new_button(button_node, on_click)
druid:new_blocker(blocker_node)
druid:on_input(mock_input.click_pressed(10, 10))
druid:on_input(mock_input.click_released(10, 10))
assert(on_click_mock.calls == 1)
-- Click should been consumed by blocker component
druid:on_input(mock_input.click_pressed(20, 20))
druid:on_input(mock_input.click_released(20, 20))
assert(on_click_mock.calls == 1)
-- If move from button to blocker, should consume too
druid:on_input(mock_input.click_pressed(10, 10))
druid:on_input(mock_input.click_released(20, 20))
assert(on_click_mock.calls == 1)
-- And from blocker to button too
druid:on_input(mock_input.click_pressed(20, 20))
druid:on_input(mock_input.click_released(10, 10))
assert(on_click_mock.calls == 1)
end)
it("Should be disabled via node or set_enabled", function()
local button_node = mock_gui.add_box("button", 0, 0, 100, 50)
local blocker_node = mock_gui.add_box("blocker", 20, 20, 20, 20)
local on_click, on_click_mock = test_helper.get_function()
druid:new_button(button_node, on_click)
local blocker = druid:new_blocker(blocker_node)
-- Click should been consumed by blocker component
druid:on_input(mock_input.click_pressed(20, 20))
druid:on_input(mock_input.click_released(20, 20))
assert(on_click_mock.calls == 0)
-- Disable blocker component
blocker:set_enabled(false)
druid:on_input(mock_input.click_pressed(20, 20))
druid:on_input(mock_input.click_released(20, 20))
assert(gui.is_enabled(blocker_node) == true)
assert(blocker:is_enabled() == false)
assert(on_click_mock.calls == 1)
-- Disable blocker node component
blocker:set_enabled(true)
gui.set_enabled(blocker_node, false)
druid:on_input(mock_input.click_pressed(20, 20))
druid:on_input(mock_input.click_released(20, 20))
assert(gui.is_enabled(blocker_node) == false)
assert(blocker:is_enabled() == true)
assert(on_click_mock.calls == 2)
-- Return state
gui.set_enabled(blocker_node, true)
druid:on_input(mock_input.click_pressed(20, 20))
druid:on_input(mock_input.click_released(20, 20))
assert(gui.is_enabled(blocker_node) == true)
assert(blocker:is_enabled() == true)
assert(on_click_mock.calls == 2)
end)
end)
end

View File

@ -0,0 +1,43 @@
local mock_gui = require "deftest.mock.gui"
local mock_time = require("deftest.mock.time")
local mock_input = require("test.helper.mock_input")
local test_helper = require("test.helper.test_helper")
local druid_system = require("druid.druid")
return function()
local druid = nil
local context = test_helper.get_context()
describe("Static Grid component", function()
local parent = nil
---@type druid.static_grid
local grid = nil
local prefab = nil
before(function()
mock_gui.mock()
mock_time.mock()
mock_time.set(60)
druid = druid_system.new(context)
parent = mock_gui.add_box("parent", 0, 0, 50, 50)
prefab = mock_gui.add_box("prefab", 50, 50, 25, 25)
grid = druid:new_static_grid(parent, prefab, 3)
end)
after(function()
mock_gui.unmock()
mock_time.unmock()
druid:final(context)
druid = nil
end)
it("Should add nodes", function()
local nodes = {}
for index = 1, 4 do
local cloned = gui.clone(prefab)
grid:add(cloned)
table.insert(nodes, cloned)
end
end)
end)
end