Update annotations P.1

This commit is contained in:
Insality
2024-10-29 20:31:45 +02:00
parent a46f38734e
commit c85d66fdca
40 changed files with 1458 additions and 3941 deletions

View File

@@ -10,10 +10,10 @@
--- The Druid scroll component
-- @tfield Scroll scroll @{Scroll}
-- @tfield Scroll scroll Scroll
--- The Druid Grid component
-- @tfield StaticGrid grid @{StaticGrid}, @{DynamicGrid}
-- @tfield StaticGrid grid StaticGrid}, @{DynamicGrid
--- The current progress of scroll posititon
-- @tfield number scroll_progress
@@ -25,13 +25,13 @@
-- @tfield number last_index
--- Event triggered when scroll progress is changed; event(self, progress_value)
-- @tfield DruidEvent on_scroll_progress_change @{DruidEvent}
-- @tfield DruidEvent on_scroll_progress_change DruidEvent
---On DataList visual element created Event callback(self, index, node, instance)
-- @tfield DruidEvent on_element_add @{DruidEvent}
-- @tfield DruidEvent on_element_add DruidEvent
---On DataList visual element created Event callback(self, index)
-- @tfield DruidEvent on_element_remove @{DruidEvent}
-- @tfield DruidEvent on_element_remove DruidEvent
---
@@ -40,15 +40,27 @@ local helper = require("druid.helper")
local component = require("druid.component")
local Event = require("druid.event")
local DataList = component.create("data_list")
---@class druid.data_list: druid.base_component
---@field scroll druid.scroll
---@field grid druid.grid
---@field on_scroll_progress_change druid.event
---@field on_element_add druid.event
---@field on_element_remove druid.event
---@field private _create_function function
---@field private _is_use_cache boolean
---@field private _cache table
---@field private _data table
---@field private _data_visual table
---@field private top_index number
local M = component.create("data_list")
--- The @{DataList} constructor
-- @tparam DataList self @{DataList}
-- @tparam Scroll scroll The @{Scroll} instance for Data List component
-- @tparam StaticGrid grid The @{StaticGrid} or @{DynamicGrid} instance for Data List component
--- The DataList constructor
-- @tparam DataList self DataList
-- @tparam Scroll scroll The Scroll 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)
function M:init(scroll, grid, create_function)
self.scroll = scroll
self.grid = grid
if self.grid.style then
@@ -75,28 +87,28 @@ end
--- Druid System on_remove function
-- @tparam DataList self @{DataList}
function DataList.on_remove(self)
-- @tparam DataList self DataList
function M:on_remove()
self:clear()
self.scroll.on_scroll:unsubscribe(self._refresh, self)
end
--- Set refresh function for DataList component
-- @tparam DataList self @{DataList}
-- @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)
function M:set_use_cache(is_use_cache)
self._is_use_cache = is_use_cache
return self
end
--- Set new data set for DataList component
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @tparam table data The new data array
-- @treturn druid.data_list Current DataList instance
function DataList.set_data(self, data)
function M:set_data(data)
self._data = data or {}
self:_refresh()
@@ -105,19 +117,19 @@ end
--- Return current data from DataList component
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @treturn table The current data array
function DataList.get_data(self)
function M:get_data()
return self._data
end
--- Add element to DataList. Currenly untested
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @tparam table data
-- @tparam number|nil index
-- @tparam number|nil shift_policy The constant from const.SHIFT.*
function DataList.add(self, data, index, shift_policy)
function M:add(data, index, shift_policy)
index = index or #self._data + 1
shift_policy = shift_policy or const.SHIFT.RIGHT
@@ -127,20 +139,20 @@ end
--- Remove element from DataList. Currenly untested
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @tparam number|nil index
-- @tparam number|nil shift_policy The constant from const.SHIFT.*
function DataList.remove(self, index, shift_policy)
function M:remove(index, shift_policy)
helper.remove_with_shift(self._data, index, shift_policy)
self:_refresh()
end
--- Remove element from DataList by data value. Currenly untested
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @tparam table data
-- @tparam number|nil shift_policy The constant from const.SHIFT.*
function DataList.remove_by_data(self, data, shift_policy)
function M:remove_by_data(data, shift_policy)
local index = helper.contains(self._data, data)
if index then
helper.remove_with_shift(self._data, index, shift_policy)
@@ -150,17 +162,17 @@ end
--- Clear the DataList and refresh visuals
-- @tparam DataList self @{DataList}
function DataList.clear(self)
-- @tparam DataList self DataList
function M:clear()
self._data = {}
self:_refresh()
end
--- Return index for data value
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @tparam table data
function DataList.get_index(self, data)
function M:get_index(data)
for index, value in pairs(self._data) do
if value == data then
return index
@@ -172,9 +184,9 @@ end
--- Return all currenly created nodes in DataList
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @treturn node[] List of created nodes
function DataList.get_created_nodes(self)
function M:get_created_nodes()
local nodes = {}
for index, data in pairs(self._data_visual) do
@@ -186,9 +198,9 @@ end
--- Return all currenly created components in DataList
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @treturn druid.base_component[] List of created nodes
function DataList.get_created_components(self)
function M:get_created_components()
local components = {}
for index, data in pairs(self._data_visual) do
@@ -200,19 +212,19 @@ end
--- Instant scroll to element with passed index
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @tparam number index
function DataList.scroll_to_index(self, index)
function M:scroll_to_index(index)
local pos = self.grid:get_pos(index)
self.scroll:scroll_to(pos)
end
--- Add element at passed index using cache or create new
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @tparam number index
-- @local
function DataList._add_at(self, index)
function M:_add_at(index)
if self._data_visual[index] then
self:_remove_at(index)
end
@@ -243,10 +255,10 @@ end
--- Remove element from passed index and add it to cache if applicable
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @tparam number index
-- @local
function DataList._remove_at(self, index)
function M:_remove_at(index)
self.grid:remove(index, const.SHIFT.NO_SHIFT)
local visual_data = self._data_visual[index]
@@ -274,9 +286,9 @@ end
--- Refresh all elements in DataList
-- @tparam DataList self @{DataList}
-- @tparam DataList self DataList
-- @local
function DataList._refresh(self)
function M:_refresh()
self.scroll:set_size(self.grid:get_size_for(#self._data))
local start_pos = -self.scroll.position --[[@as vector3]]
@@ -313,4 +325,4 @@ function DataList._refresh(self)
end
return DataList
return M

View File

@@ -1,427 +0,0 @@
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle placing components in row
--
-- <a href="https://insality.github.io/druid/druid/index.html?example=general_grid" target="_blank"><b>Example Link</b></a>
-- @module DynamicGrid
-- @within BaseComponent
-- @alias druid.dynamic_grid
--- On item add callback(self, node, index)
-- @tfield DruidEvent on_add_item @{DruidEvent}
--- On item remove callback(self, index)
-- @tfield DruidEvent on_remove_item @{DruidEvent}
--- On item add or remove callback(self, index)
-- @tfield DruidEvent on_change_items @{DruidEvent}
--- On grid clear callback(self)
-- @tfield DruidEvent on_clear @{DruidEvent}
--- On update item positions callback(self)
-- @tfield DruidEvent on_update_positions @{DruidEvent}
--- Parent gui node
-- @tfield node parent
--- List of all grid elements. Contains from node, pos, size, pivot
-- @tfield node[] nodes
--- The first index of node in grid
-- @tfield number first_index
--- The last index of node in grid
-- @tfield number last_index
--- Item size
-- @tfield vector3 node_size
--- The size of item content
-- @tfield vector4 border
---
local const = require("druid.const")
local Event = require("druid.event")
local helper = require("druid.helper")
local component = require("druid.component")
local DynamicGrid = component.create("dynamic_grid")
local SIDE_VECTORS = {
LEFT = vmath.vector3(-1, 0, 0),
RIGHT = vmath.vector3(1, 0, 0),
TOP = vmath.vector3(0, -1, 0),
BOT = vmath.vector3(0, 1, 0),
}
local AVAILABLE_PIVOTS = {
gui.PIVOT_N,
gui.PIVOT_S,
gui.PIVOT_W,
gui.PIVOT_E,
}
--- The @{DynamicGrid} constructor
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam node parent The gui node parent, where items will be placed
function DynamicGrid.init(self, parent)
self.parent = self:get_node(parent)
local parent_pivot = gui.get_pivot(self.parent)
self.pivot = helper.get_pivot_offset(parent_pivot)
assert(helper.contains(AVAILABLE_PIVOTS, parent_pivot), const.ERRORS.GRID_DYNAMIC_ANCHOR)
self.side = ((parent_pivot == gui.PIVOT_W or parent_pivot == gui.PIVOT_E)
and const.SIDE.X or const.SIDE.Y)
self.nodes = {}
self.border = vmath.vector4(0) -- Current grid content size
self.on_add_item = Event()
self.on_remove_item = Event()
self.on_change_items = Event()
self.on_clear = Event()
self.on_update_positions = Event()
self._set_position_function = gui.set_position
end
function DynamicGrid.on_layout_change(self)
self:_update(true)
end
--- Return pos for grid node index
-- @tparam DynamicGrid self @{DynamicGrid}
-- @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
function DynamicGrid.get_pos(self, index, node, origin_index)
local origin_node = self.nodes[origin_index]
-- If anchor node is not exist, check around nodes
if not origin_node then
if self.nodes[index + 1] then
origin_index = index + 1
end
if self.nodes[index - 1] then
origin_index = index - 1
end
origin_node = self.nodes[origin_index]
end
if not origin_node then
assert(not self.first_index, "Dynamic Grid can't have gaps between nodes. Error on grid:add")
-- If not origin node, so it should be first element in the grid
local size = helper.get_scaled_size(node)
local pivot = const.PIVOTS[gui.get_pivot(node)]
return vmath.vector3(
size.x * pivot.x - size.x * self.pivot.x,
size.y * pivot.y - size.y * self.pivot.y,
0)
end
if origin_node then
-- Other nodes spawn from other side of the origin node
local is_forward = origin_index < index
local delta = is_forward and 1 or -1
return self:_get_next_node_pos(index - delta, node, self:_get_side_vector(self.side, is_forward))
end
end
--- Add new node to the grid
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam node node Gui node
-- @tparam number|nil index The node position. By default add as last node
-- @tparam number|nil shift_policy How shift nodes, if required. Default: const.SHIFT.RIGHT
-- @tparam boolean|nil is_instant If true, update node positions instantly
function DynamicGrid.add(self, node, index, shift_policy, is_instant)
shift_policy = shift_policy or const.SHIFT.RIGHT
local delta = shift_policy -- -1 or 1 or 0
-- By default add node at end
index = index or ((self.last_index or 0) + 1)
-- If node exist at index place, shifting them
local is_shift = self.nodes[index] and shift_policy ~= const.SHIFT.NO_SHIFT
if is_shift then
-- We need to iterate from index to start or end grid, depends of shift side
local start_index = shift_policy == const.SHIFT.LEFT and self.first_index or self.last_index
for i = start_index, index, -delta do
self.nodes[i + delta] = self.nodes[i]
end
end
self:_add_node(node, index, index - delta)
-- After shifting we should recalc node poses
if is_shift then
-- We need to iterate from placed node to start or end grid, depends of shift side
local target_index = shift_policy == const.SHIFT.LEFT and self.first_index or self.last_index
for i = index + delta, target_index + delta, delta do
local move_node = self.nodes[i]
move_node.pos = self:get_pos(i, move_node.node, i - delta)
end
end
-- Sync grid data
self:_update(is_instant)
self.on_add_item:trigger(self:get_context(), node, index)
self.on_change_items:trigger(self:get_context(), index)
end
--- Remove the item from the grid. Note that gui node will be not deleted
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam number index The grid node index to remove
-- @tparam number|nil shift_policy How shift nodes, if required. Default: const.SHIFT.RIGHT
-- @tparam boolean|nil is_instant If true, update node positions instantly
-- @treturn node The deleted gui node from grid
function DynamicGrid.remove(self, index, shift_policy, is_instant)
shift_policy = shift_policy or const.SHIFT.RIGHT
local delta = shift_policy -- -1 or 1 or 0
assert(self.nodes[index], "No grid item at given index " .. index)
-- Just set nil for delete node data
local removed_node = self.nodes[index].node
self.nodes[index] = nil
-- After delete node, we should shift nodes and recalc their poses, depends from is_shift_left
if shift_policy ~= const.SHIFT.NO_SHIFT then
local target_index = shift_policy == const.SHIFT.LEFT and self.first_index or self.last_index
for i = index, target_index, delta do
self.nodes[i] = self.nodes[i + delta]
if self.nodes[i] then
self.nodes[i].pos = self:get_pos(i, self.nodes[i].node, i - delta)
end
end
end
-- Sync grid data
self:_update(is_instant)
self.on_remove_item:trigger(self:get_context(), index)
self.on_change_items:trigger(self:get_context(), index)
return removed_node
end
--- Return grid content size
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam vector3 border
-- @treturn vector3 The grid content size
function DynamicGrid.get_size(self, border)
border = border or self.border
return vmath.vector3(
border.z - border.x,
border.y - border.w,
0)
end
--- Return DynamicGrid offset, where DynamicGrid content starts.
-- @tparam DynamicGrid self @{DynamicGrid} The DynamicGrid instance
-- @treturn vector3 The DynamicGrid offset
function DynamicGrid.get_offset(self)
local size = self:get_size()
local borders = self:get_borders()
local offset = vmath.vector3(
(borders.z + borders.x)/2 + size.x * self.pivot.x,
(borders.y + borders.w)/2 + size.y * self.pivot.y,
0)
return offset
end
--- Return grid content borders
-- @tparam DynamicGrid self @{DynamicGrid}
-- @treturn vector3 The grid content borders
function DynamicGrid.get_borders(self)
return self.border
end
--- Return grid index by node
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam node node The gui node in the grid
-- @treturn number The node index
function DynamicGrid.get_index_by_node(self, node)
for index, node_info in pairs(self.nodes) do
if node == node_info.node then
return index
end
end
return nil
end
--- Return array of all node positions
-- @tparam DynamicGrid self @{DynamicGrid}
-- @treturn vector3[] All grid node positions
function DynamicGrid.get_all_pos(self)
local result = {}
for i, node in pairs(self.nodes) do
table.insert(result, gui.get_position(node.node))
end
return result
end
--- Change set position function for grid nodes. It will call on
-- update poses on grid elements. Default: gui.set_position
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam function callback Function on node set position
-- @treturn druid.dynamic_grid Current grid instance
function DynamicGrid.set_position_function(self, callback)
self._set_position_function = callback or gui.set_position
return self
end
--- Clear grid nodes array. GUI nodes will be not deleted!
-- If you want to delete GUI nodes, use dynamic_grid.nodes array before grid:clear
-- @tparam DynamicGrid self @{DynamicGrid}
-- @treturn druid.dynamic_grid Current grid instance
function DynamicGrid.clear(self)
self.nodes = {}
self:_update()
self.on_clear:trigger(self:get_context())
return self
end
function DynamicGrid._add_node(self, node, index, origin_index)
self.nodes[index] = {
node = node,
pos = self:get_pos(index, node, origin_index),
size = helper.get_scaled_size(node),
pivot = const.PIVOTS[gui.get_pivot(node)]
}
-- Add new item instantly in new pos
gui.set_parent(node, self.parent)
gui.set_position(node, self.nodes[index].pos)
end
--- Update grid inner state
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam boolean|nil is_instant If true, node position update instantly, otherwise with set_position_function callback
-- @local
function DynamicGrid._update(self, is_instant)
self:_update_indexes()
self:_update_borders()
self:_update_pos(is_instant)
end
--- Update first and last indexes of grid nodes
-- @tparam DynamicGrid self @{DynamicGrid}
-- @local
function DynamicGrid._update_indexes(self)
self.first_index = nil
self.last_index = nil
for index in pairs(self.nodes) do
self.first_index = self.first_index or index
self.last_index = self.last_index or index
self.first_index = math.min(self.first_index, index)
self.last_index = math.max(self.last_index, index)
end
end
--- Update grid content borders, recalculate min and max values
-- @tparam DynamicGrid self @{DynamicGrid}
-- @local
function DynamicGrid._update_borders(self)
if not self.first_index then
self.border = vmath.vector4(0)
return
end
self.border = vmath.vector4(math.huge, -math.huge, -math.huge, math.huge)
for index, node in pairs(self.nodes) do
local pos = node.pos
local size = node.size
local pivot = node.pivot
local left = pos.x - size.x/2 - (size.x * pivot.x)
local right = pos.x + size.x/2 - (size.x * pivot.x)
local top = pos.y + size.y/2 - (size.y * pivot.y)
local bottom = pos.y - size.y/2 - (size.y * pivot.y)
self.border.x = math.min(self.border.x, left)
self.border.y = math.max(self.border.y, top)
self.border.z = math.max(self.border.z, right)
self.border.w = math.min(self.border.w, bottom)
end
end
--- Update grid nodes position
-- @tparam DynamicGrid self @{DynamicGrid}
-- @tparam boolean|nil is_instant If true, node position update instantly, otherwise with set_position_function callback
-- @local
function DynamicGrid._update_pos(self, is_instant)
for index, node in pairs(self.nodes) do
if is_instant then
gui.set_position(node.node, node.pos)
else
self._set_position_function(node.node, node.pos)
end
end
self.on_update_positions:trigger(self:get_context())
end
function DynamicGrid._get_next_node_pos(self, origin_node_index, new_node, place_side)
local node = self.nodes[origin_node_index]
local new_node_size = helper.get_scaled_size(new_node)
local new_pivot = const.PIVOTS[gui.get_pivot(new_node)]
local dist_x = (node.size.x/2 + new_node_size.x/2) * place_side.x
local dist_y = (node.size.y/2 + new_node_size.y/2) * place_side.y
local node_center_x = node.pos.x - node.size.x * node.pivot.x
local node_center_y = node.pos.y - node.size.y * node.pivot.y
return vmath.vector3(
node_center_x + dist_x + new_node_size.x * new_pivot.x,
node_center_y - dist_y + new_node_size.y * new_pivot.y,
0
)
end
--- Return side vector to correct node shifting
function DynamicGrid._get_side_vector(self, side, is_forward)
if side == const.SIDE.X then
return is_forward and SIDE_VECTORS.RIGHT or SIDE_VECTORS.LEFT
end
if side == const.SIDE.Y then
return is_forward and SIDE_VECTORS.BOT or SIDE_VECTORS.TOP
end
end
return DynamicGrid

View File

@@ -8,10 +8,10 @@
-- @alias druid.hotkey
--- On hotkey released callback(self, argument)
-- @tfield DruidEvent on_hotkey_pressed @{DruidEvent}
-- @tfield DruidEvent on_hotkey_pressed DruidEvent
--- On hotkey released callback(self, argument)
-- @tfield DruidEvent on_hotkey_released @{DruidEvent}
-- @tfield DruidEvent on_hotkey_released DruidEvent
--- Visual node
-- @tfield node node
@@ -20,7 +20,7 @@
-- @tfield node|nil click_node
--- Button component from click_node
-- @tfield Button button @{Button}
-- @tfield Button button Button
---
@@ -28,15 +28,21 @@ local helper = require("druid.helper")
local component = require("druid.component")
local Event = require("druid.event")
local Hotkey = component.create("hotkey")
---@class druid.hotkey: druid.base_component
---@field on_hotkey_pressed druid.event
---@field on_hotkey_released druid.event
---@field style table
---@field private _hotkeys table
---@field private _modificators table
local M = component.create("hotkey")
--- The @{Hotkey} constructor
-- @tparam Hotkey self @{Hotkey}
--- The Hotkey constructor
-- @tparam Hotkey self Hotkey
-- @tparam string[]|string keys The keys to be pressed for trigger callback. Should contains one key and any modificator keys
-- @tparam function callback The callback function
-- @tparam any|nil callback_argument The argument to pass into the callback function
function Hotkey.init(self, keys, callback, callback_argument)
function M:init(keys, callback, callback_argument)
self.druid = self:get_druid()
self._hotkeys = {}
@@ -56,7 +62,7 @@ end
-- or create your own style
-- @table style
-- @tfield string[] MODIFICATORS The list of action_id as hotkey modificators
function Hotkey.on_style_change(self, style)
function M:on_style_change(style)
self.style = {}
self.style.MODIFICATORS = style.MODIFICATORS or {}
@@ -67,11 +73,11 @@ end
--- Add hotkey for component callback
-- @tparam Hotkey self @{Hotkey}
-- @tparam Hotkey self Hotkey
-- @tparam string[]|hash[]|string|hash keys that have to be pressed before key pressed to activate
-- @tparam any|nil callback_argument The argument to pass into the callback function
-- @treturn Hotkey Current instance
function Hotkey.add_hotkey(self, keys, callback_argument)
function M:add_hotkey(keys, callback_argument)
keys = keys or {}
if type(keys) == "string" then
keys = { keys }
@@ -110,14 +116,14 @@ function Hotkey.add_hotkey(self, keys, callback_argument)
end
function Hotkey.on_focus_gained(self)
function M:on_focus_gained()
for k, v in pairs(self._modificators) do
self._modificators[k] = false
end
end
function Hotkey.on_input(self, action_id, action)
function M:on_input(action_id, action)
if not action_id or #self._hotkeys == 0 then
return false
end
@@ -168,13 +174,13 @@ end
--- If true, the callback will be triggered on action.repeated
-- @tparam Hotkey self @{Hotkey}
-- @tparam Hotkey self Hotkey
-- @tparam bool is_enabled_repeated The flag value
-- @treturn Hotkey
function Hotkey.set_repeat(self, is_enabled_repeated)
function M:set_repeat(is_enabled_repeated)
self._is_process_repeated = is_enabled_repeated
return self
end
return Hotkey
return M

View File

@@ -10,25 +10,25 @@
-- @alias druid.input
--- On input field select callback(self, input_instance)
-- @tfield DruidEvent on_input_select @{DruidEvent}
-- @tfield DruidEvent on_input_select DruidEvent
--- On input field unselect callback(self, input_text, input_instance)
-- @tfield DruidEvent on_input_unselect @{DruidEvent}
-- @tfield DruidEvent on_input_unselect DruidEvent
--- On input field text change callback(self, input_text)
-- @tfield DruidEvent on_input_text @{DruidEvent}
-- @tfield DruidEvent on_input_text DruidEvent
--- On input field text change to empty string callback(self, input_text)
-- @tfield DruidEvent on_input_empty @{DruidEvent}
-- @tfield DruidEvent on_input_empty DruidEvent
--- On input field text change to max length string callback(self, input_text)
-- @tfield DruidEvent on_input_full @{DruidEvent}
-- @tfield DruidEvent on_input_full DruidEvent
--- On trying user input with not allowed character callback(self, params, input_text)
-- @tfield DruidEvent on_input_wrong @{DruidEvent}
-- @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}
-- @tfield DruidEvent on_select_cursor_change DruidEvent
--- The cursor index. The index of letter cursor after. Leftmost cursor - 0
-- @tfield number cursor_index
@@ -40,7 +40,7 @@
-- @tfield number end_index
--- Text component
-- @tfield Text text @{Text}
-- @tfield Text text Text
--- Current input value
-- @tfield string value
@@ -61,7 +61,7 @@
-- @tfield number marked_text_width
--- Button component
-- @tfield Button button @{Button}
-- @tfield Button button Button
--- Is current input selected now
-- @tfield boolean is_selected
@@ -87,9 +87,19 @@ local component = require("druid.component")
local utf8_lua = require("druid.system.utf8")
local utf8 = utf8 or utf8_lua
local Input = component.create("input")
---@class druid.input: druid.base_component
---@field on_input_select druid.event
---@field on_input_unselect druid.event
---@field on_input_text druid.event
---@field on_input_empty druid.event
---@field on_input_full druid.event
---@field on_input_wrong druid.event
---@field on_select_cursor_change druid.event
---@field style table
---@field text druid.text
local M = component.create("input")
Input.ALLOWED_ACTIONS = {
M.ALLOWED_ACTIONS = {
[const.ACTION_TOUCH] = true,
[const.ACTION_TEXT] = true,
[const.ACTION_MARKED_TEXT] = true,
@@ -132,7 +142,7 @@ end
-- @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
function Input.on_style_change(self, style)
function M:on_style_change(style)
self.style = {}
self.style.IS_LONGTAP_ERASE = style.IS_LONGTAP_ERASE or false
@@ -145,12 +155,12 @@ function Input.on_style_change(self, style)
end
--- The @{Input} constructor
-- @tparam Input self @{Input}
--- The Input constructor
-- @tparam Input self Input
-- @tparam node click_node Node to enabled input component
-- @tparam node|Text text_node Text node what will be changed on user input. You can pass text component instead of text node name @{Text}
-- @tparam 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)
function M:init(click_node, text_node, keyboard_type)
self.druid = self:get_druid()
if type(text_node) == "table" then
@@ -201,8 +211,8 @@ function Input.init(self, click_node, text_node, keyboard_type)
end
function Input.on_input(self, action_id, action)
if not (action_id == nil or Input.ALLOWED_ACTIONS[action_id]) then
function M:on_input(action_id, action)
if not (action_id == nil or M.ALLOWED_ACTIONS[action_id]) then
return false
end
@@ -299,17 +309,17 @@ function Input.on_input(self, action_id, action)
end
function Input.on_focus_lost(self)
function M:on_focus_lost()
self:unselect()
end
function Input.on_input_interrupt(self)
function M:on_input_interrupt()
--self:unselect()
end
function Input.get_text_selected(self)
function M:get_text_selected()
if self.start_index == self.end_index then
return self.value
end
@@ -318,10 +328,10 @@ function Input.get_text_selected(self)
end
--- Replace selected text with new text
-- @tparam Input self @{Input}
-- @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)
function M:get_text_selected_replaced(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
@@ -336,9 +346,9 @@ end
--- Set text for input field
-- @tparam Input self @{Input}
-- @tparam Input self Input
-- @tparam string input_text The string to apply for input field
function Input.set_text(self, input_text)
function M:set_text(input_text)
input_text = tostring(input_text or "")
-- Case when update with marked text
@@ -385,8 +395,8 @@ end
--- Select input field. It will show the keyboard and trigger on_select events
-- @tparam Input self @{Input}
function Input.select(self)
-- @tparam Input self Input
function M:select()
gui.reset_keyboard()
self.marked_value = ""
if not self.is_selected then
@@ -410,8 +420,8 @@ end
--- Remove selection from input. It will hide the keyboard and trigger on_unselect events
-- @tparam Input self @{Input}
function Input.unselect(self)
-- @tparam Input self Input
function M:unselect()
gui.reset_keyboard()
self.marked_value = ""
self.value = self.current_value
@@ -429,9 +439,9 @@ end
--- Return current input field text
-- @tparam Input self @{Input}
-- @tparam Input self Input
-- @treturn string The current input field text
function Input.get_text(self)
function M:get_text()
if self.marked_value ~= "" then
return self.value .. self.marked_value
end
@@ -442,10 +452,10 @@ end
--- Set maximum length for input field.
-- Pass nil to make input field unliminted (by default)
-- @tparam Input self @{Input}
-- @tparam Input self Input
-- @tparam number max_length Maximum length for input text field
-- @treturn druid.input Current input instance
function Input.set_max_length(self, max_length)
function M:set_max_length(max_length)
self.max_length = max_length
return self
end
@@ -454,19 +464,19 @@ end
--- Set allowed charaters for input field.
-- See: https://defold.com/ref/stable/string/
-- ex: [%a%d] for alpha and numeric
-- @tparam Input self @{Input}
-- @tparam Input self Input
-- @tparam string characters Regulax exp. for validate user input
-- @treturn druid.input Current input instance
function Input.set_allowed_characters(self, characters)
function M:set_allowed_characters(characters)
self.allowed_characters = characters
return self
end
--- Reset current input selection and return previous value
-- @tparam Input self @{Input}
-- @tparam Input self Input
-- @treturn druid.input Current input instance
function Input.reset_changes(self)
function M:reset_changes()
self:set_text(self.previous_value)
self:unselect()
return self
@@ -474,12 +484,12 @@ end
--- Set cursor position in input field
-- @tparam Input self @{Input}
-- @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)
function M:select_cursor(cursor_index, start_index, end_index)
local len = utf8.len(self.value)
self.cursor_index = cursor_index or len
@@ -497,11 +507,11 @@ end
--- Change cursor position by delta
-- @tparam Input self @{Input}
-- @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)
function M:move_selection(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
@@ -559,4 +569,4 @@ function Input.move_selection(self, delta, is_add_to_selection, is_move_to_end)
end
return Input
return M

View File

@@ -18,10 +18,10 @@
-- @alias druid.lang_text
--- On change text callback
-- @tfield DruidEvent on_change @{DruidEvent}
-- @tfield DruidEvent on_change DruidEvent
--- The text component
-- @tfield Text text @{Text}
-- @tfield Text text Text
--- Text node
-- @tfield node node
@@ -32,15 +32,21 @@ local Event = require("druid.event")
local settings = require("druid.system.settings")
local component = require("druid.component")
local LangText = component.create("lang_text")
---@class druid.lang_text: druid.base_component
---@field text druid.text
---@field node node
---@field on_change druid.event
---@field private last_locale_args table
---@field private last_locale string
local M = component.create("lang_text")
--- The @{LangText} constructor
-- @tparam LangText self @{LangText}
--- The LangText constructor
-- @tparam LangText self LangText
-- @tparam string|node node The node_id or gui.get_node(node_id)
-- @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)
function M:init(node, locale_id, adjust_type)
self.druid = self:get_druid()
self.text = self.druid:new_text(node, locale_id, adjust_type)
self.node = self.text.node
@@ -55,7 +61,7 @@ function LangText.init(self, node, locale_id, adjust_type)
end
function LangText.on_language_change(self)
function M:on_language_change()
if self.last_locale then
self:translate(self.last_locale, unpack(self.last_locale_args))
end
@@ -63,10 +69,10 @@ end
--- Setup raw text to lang_text component
-- @tparam LangText self @{LangText}
-- @tparam LangText self LangText
-- @tparam string text Text for text node
-- @treturn LangText Current instance
function LangText.set_to(self, text)
function M:set_to(text)
self.last_locale = false
self.text:set_to(text)
self.on_change:trigger()
@@ -76,7 +82,7 @@ end
--- Translate the text by locale_id
-- @tparam LangText self @{LangText}
-- @tparam LangText self LangText
-- @tparam string locale_id Locale id
-- @tparam string|nil a Optional param to string.format
-- @tparam string|nil b Optional param to string.format
@@ -86,7 +92,7 @@ end
-- @tparam string|nil f Optional param to string.format
-- @tparam string|nil g Optional param to string.format
-- @treturn LangText Current instance
function LangText.translate(self, locale_id, a, b, c, d, e, f, g)
function M:translate(locale_id, a, b, c, d, e, f, g)
self.last_locale_args = { a, b, c, d, e, f, g }
self.last_locale = locale_id or self.last_locale
self.text:set_to(settings.get_text(self.last_locale, a, b, c, d, e, f, g) or "")
@@ -96,7 +102,7 @@ end
--- Format string with new text params on localized text
-- @tparam LangText self @{LangText}
-- @tparam LangText self LangText
-- @tparam string|nil a Optional param to string.format
-- @tparam string|nil b Optional param to string.format
-- @tparam string|nil c Optional param to string.format
@@ -105,11 +111,11 @@ end
-- @tparam string|nil f Optional param to string.format
-- @tparam string|nil g Optional param to string.format
-- @treturn LangText Current instance
function LangText.format(self, a, b, c, d, e, f, g)
function M:format(a, b, c, d, e, f, g)
self.last_locale_args = { a, b, c, d, e, f, g }
self.text:set_to(settings.get_text(self.last_locale, a, b, c, d, e, f, g) or "")
return self
end
return LangText
return M

View File

@@ -1,45 +1,41 @@
-- Copyright (c) 2024 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Layout management on node
--
-- <a href="https://insality.github.io/druid/druid/index.html?example=general_layout" target="_blank"><b>Example Link</b></a>
-- @module Layout
-- @within BaseComponent
-- @alias druid.layout
--- Layout node
-- @tfield node node
--- Current layout mode
-- @tfield string mode
---
local helper = require("druid.helper")
local component = require("druid.component")
-- @class druid.layout.row_data
-- @tfield width number
-- @tfield height number
-- @tfield count number
---@alias druid.layout.mode
---| "horizontal" Elements are placed horizontally
---| "vertical" Elements are placed vertically
---| "horizontal_wrap" Elements are placed horizontally, but if the row width is greater than the parent width, the next row is created
-- @class druid.layout.rows_data
-- @tfield total_width number
-- @tfield total_height number
-- @tfield nodes_width table<node, number>
-- @tfield nodes_height table<node, number>
-- @tfield rows druid.layout.row_data[]>
---@class druid.layout.row_data
---@field width number
---@field height number
---@field count number
-- @class druid.layout: druid.base_component
---@class druid.layout.rows_data
---@field total_width number
---@field total_height number
---@field nodes_width table<node, number>
---@field nodes_height table<node, number>
---@field rows druid.layout.row_data[]>
---@class druid.layout: druid.base_component
---@field node node
---@field is_dirty boolean
---@field entities node[]
---@field margin {x: number, y: number}
---@field padding vector4
---@field type string
---@field is_resize_width boolean
---@field is_resize_height boolean
---@field is_justify boolean
local M = component.create("layout")
-- The @{Layout} constructor
-- @tparam Layout self @{Layout}
-- @tparam node node Gui node
-- @tparam string layout_type The layout mode (from const.LAYOUT_MODE)
-- @tparam function|nil on_size_changed_callback The callback on window resize
function M.init(self, node, layout_type)
self.node = self:get_node(node)
---Layout component constructor
---@local
---@param node_or_node_id node|string
---@param layout_type druid.layout.mode
function M:init(node_or_node_id, layout_type)
self.node = self:get_node(node_or_node_id)
self.is_dirty = true
self.entities = {}
@@ -51,6 +47,8 @@ function M.init(self, node, layout_type)
self.is_justify = false
end
---@local
function M:update()
if not self.is_dirty then
return
@@ -60,11 +58,10 @@ function M:update()
end
-- @tparam Layout self @{Layout}
-- @tparam number|nil margin_x
-- @tparam number|nil margin_y
-- @treturn druid.layout @{Layout}
function M.set_margin(self, margin_x, margin_y)
---@param margin_x number|nil
---@param margin_y number|nil
---@return druid.layout
function M:set_margin(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
@@ -73,10 +70,9 @@ function M.set_margin(self, margin_x, margin_y)
end
-- @tparam Layout self @{Layout}
-- @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)
---@param padding vector4 The vector4 with padding values, where x - left, y - top, z - right, w - bottom
---@return druid.layout
function M:set_padding(padding)
self.padding = padding
self.is_dirty = true
@@ -84,19 +80,17 @@ function M.set_padding(self, padding)
end
-- @tparam Layout self @{Layout}
-- @treturn druid.layout @{Layout}
function M.set_dirty(self)
---@return druid.layout
function M:set_dirty()
self.is_dirty = true
return self
end
-- @tparam Layout self @{Layout}
-- @tparam boolean is_justify
-- @treturn druid.layout @{Layout}
function M.set_justify(self, is_justify)
---@param is_justify boolean
---@return druid.layout
function M:set_justify(is_justify)
self.is_justify = is_justify
self.is_dirty = true
@@ -104,10 +98,9 @@ function M.set_justify(self, is_justify)
end
-- @tparam Layout self @{Layout}
-- @tparam string type The layout type: "horizontal", "vertical", "horizontal_wrap"
-- @treturn druid.layout @{Layout}
function M.set_type(self, type)
---@param type string The layout type: "horizontal", "vertical", "horizontal_wrap"
---@return druid.layout
function M:set_type(type)
self.type = type
self.is_dirty = true
@@ -115,11 +108,10 @@ function M.set_type(self, type)
end
-- @tparam Layout self @{Layout}
-- @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)
---@param is_hug_width boolean
---@param is_hug_height boolean
---@return druid.layout
function M:set_hug_content(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
@@ -128,21 +120,20 @@ function M.set_hug_content(self, is_hug_width, is_hug_height)
end
-- @tparam Layout self @{Layout}
-- @tparam string|node node_or_node_id
-- @treturn druid.layout @{Layout}
function M.add(self, node_or_node_id)
---@param node_or_node_id node|string node_or_node_id
---@return druid.layout
function M:add(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
---@cast node_or_node_id string|node
node = self:get_node(node_or_node_id)
end
-- @cast node node
---@cast node node
table.insert(self.entities, node)
gui.set_parent(node, self.node)
@@ -152,9 +143,8 @@ function M.add(self, node_or_node_id)
end
-- @tparam Layout self @{Layout}
-- @treturn druid.layout @{Layout}
function M.refresh_layout(self)
---@return druid.layout
function M:refresh_layout()
local layout_node = self.node
local entities = self.entities
@@ -289,9 +279,8 @@ function M.refresh_layout(self)
end
-- @tparam Layout self @{Layout}
-- @treturn druid.layout @{Layout}
function M.clear_layout(self)
---@return druid.layout
function M:clear_layout()
for index = #self.entities, 1, -1 do
self.entities[index] = nil
end
@@ -302,10 +291,9 @@ function M.clear_layout(self)
end
-- @tparam node node
-- @treturn number, number
-- @local
function M.get_node_size(node)
---@param node node
---@return number, number
function M:get_node_size(node)
if not gui.is_enabled(node, false) then
return 0, 0
end
@@ -323,11 +311,10 @@ function M.get_node_size(node)
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)
---Calculate rows data for layout. Contains total width, height and rows info (width, height, count of elements in row)
---@local
---@return druid.layout.rows_data
function M:calculate_rows_data()
local entities = self.entities
local margin = self.margin
local type = self.type
@@ -353,7 +340,7 @@ function M.calculate_rows_data(self)
-- 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)
node_width, node_height = self:get_node_size(node)
rows_data.nodes_width[node] = node_width
rows_data.nodes_height[node] = node_height
end
@@ -407,11 +394,10 @@ function M.calculate_rows_data(self)
end
-- @tparam node node
-- @tparam number x
-- @tparam number y
-- @treturn node
-- @local
---@param node node
---@param x number
---@param y number
---@return node
function M:set_node_position(node, x, y)
local position = gui.get_position(node)
position.x = x

View File

@@ -20,7 +20,7 @@
-- @alias druid.progress
--- On progress bar change callback(self, new_value)
-- @tfield DruidEvent on_change @{DruidEvent}
-- @tfield DruidEvent on_change DruidEvent
--- Progress bar fill node
-- @tfield node node
@@ -49,7 +49,13 @@ local const = require("druid.const")
local helper = require("druid.helper")
local component = require("druid.component")
local Progress = component.create("progress")
---@class druid.progress: druid.base_component
---@field node node
---@field on_change druid.event
---@field style table
---@field key string
---@field prop hash
local M = component.create("progress")
local function check_steps(self, from, to, exactly)
@@ -117,19 +123,19 @@ end
-- @table style
-- @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)
function M:on_style_change(style)
self.style = {}
self.style.SPEED = style.SPEED or 5
self.style.MIN_DELTA = style.MIN_DELTA or 0.005
end
--- The @{Progress} constructor
-- @tparam Progress self @{Progress}
--- The Progress constructor
-- @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 number|nil init_value Initial value of progress bar. Default: 1
function Progress.init(self, node, key, init_value)
function M:init(node, key, init_value)
assert(key == const.SIDE.X or const.SIDE.Y, "Progress bar key should be 'x' or 'y'")
self.key = key
@@ -155,18 +161,18 @@ function Progress.init(self, node, key, init_value)
end
function Progress.on_layout_change(self)
function M:on_layout_change()
self:set_to(self.last_value)
end
function Progress.on_remove(self)
function M:on_remove()
-- Return default size
gui.set_size(self.node, self.max_size)
end
function Progress.update(self, dt)
function M:update(dt)
if self.target then
local prev_value = self.last_value
local step = math.abs(self.last_value - self.target) * (self.style.SPEED*dt)
@@ -187,51 +193,51 @@ end
--- Fill a progress bar and stop progress animation
-- @tparam Progress self @{Progress}
function Progress.fill(self)
-- @tparam Progress self Progress
function M:fill()
set_bar_to(self, 1, true)
end
--- Empty a progress bar
-- @tparam Progress self @{Progress}
function Progress.empty(self)
-- @tparam Progress self Progress
function M:empty()
set_bar_to(self, 0, true)
end
--- Instant fill progress bar to value
-- @tparam Progress self @{Progress}
-- @tparam Progress self Progress
-- @tparam number to Progress bar value, from 0 to 1
function Progress.set_to(self, to)
function M:set_to(to)
to = helper.clamp(to, 0, 1)
set_bar_to(self, to)
end
--- Return current progress bar value
-- @tparam Progress self @{Progress}
function Progress.get(self)
-- @tparam Progress self Progress
function M:get()
return self.last_value
end
--- Set points on progress bar to fire the callback
-- @tparam Progress self @{Progress}
-- @tparam Progress self Progress
-- @tparam number[] steps Array of progress bar values
-- @tparam function callback Callback on intersect step value
-- @usage progress:set_steps({0, 0.3, 0.6, 1}, function(self, step) end)
function Progress.set_steps(self, steps, callback)
function M:set_steps(steps, callback)
self.steps = steps
self.step_callback = callback
end
--- Start animation of a progress bar
-- @tparam Progress self @{Progress}
-- @tparam Progress self Progress
-- @tparam number to value between 0..1
-- @tparam function|nil callback Callback on animation ends
function Progress.to(self, to, callback)
function M:to(to, callback)
to = helper.clamp(to, 0, 1)
-- cause of float error
local value = helper.round(to, 5)
@@ -247,14 +253,14 @@ end
--- Set progress bar max node size
-- @tparam Progress self @{Progress}
-- @tparam Progress self Progress
-- @tparam vector3 max_size The new node maximum (full) size
-- @treturn Progress @{Progress}
function Progress.set_max_size(self, max_size)
-- @treturn Progress Progress
function M:set_max_size(max_size)
self.max_size[self.key] = max_size[self.key]
self:set_to(self.last_value)
return self
end
return Progress
return M

View File

@@ -8,7 +8,7 @@
-- @alias druid.slider
--- On change value callback(self, value)
-- @tfield DruidEvent on_change_value @{DruidEvent}
-- @tfield DruidEvent on_change_value DruidEvent
--- Slider pin node
-- @tfield node node
@@ -42,7 +42,19 @@ local helper = require("druid.helper")
local const = require("druid.const")
local component = require("druid.component")
local Slider = component.create("slider", const.PRIORITY_INPUT_HIGH)
---@class druid.slider: druid.base_component
---@field node node
---@field on_change_value druid.event
---@field style table
---@field private start_pos vector3
---@field private pos vector3
---@field private target_pos vector3
---@field private end_pos vector3
---@field private dist vector3
---@field private is_drag boolean
---@field private value number
---@field private steps number[]
local M = component.create("slider", const.PRIORITY_INPUT_HIGH)
local function on_change_value(self)
@@ -56,12 +68,12 @@ local function set_position(self, value)
end
--- The @{Slider} constructor
-- @tparam Slider self @{Slider}
--- The Slider constructor
-- @tparam Slider self Slider
-- @tparam node node Gui pin node
-- @tparam vector3 end_pos The end position of slider
-- @tparam function|nil callback On slider change callback
function Slider.init(self, node, end_pos, callback)
function M:init(node, end_pos, callback)
self.node = self:get_node(node)
self.start_pos = gui.get_position(self.node)
@@ -81,18 +93,18 @@ function Slider.init(self, node, end_pos, callback)
end
function Slider.on_layout_change(self)
function M:on_layout_change()
self:set(self.value)
end
function Slider.on_remove(self)
function M:on_remove()
-- Return pin to start position
gui.set_position(self.node, self.start_pos)
end
function Slider.on_window_resized(self)
function M:on_window_resized()
local x_koef, y_koef = helper.get_screen_aspect_koef()
self._x_koef = x_koef
self._y_koef = y_koef
@@ -100,7 +112,7 @@ function Slider.on_window_resized(self)
end
function Slider.on_input(self, action_id, action)
function M:on_input(action_id, action)
if action_id ~= const.ACTION_TOUCH then
return false
end
@@ -185,10 +197,10 @@ end
--- Set value for slider
-- @tparam Slider self @{Slider}
-- @tparam Slider self Slider
-- @tparam number value Value from 0 to 1
-- @tparam boolean|nil is_silent Don't trigger event if true
function Slider.set(self, value, is_silent)
function M:set(value, is_silent)
value = helper.clamp(value, 0, 1)
set_position(self, value)
self.value = value
@@ -200,11 +212,11 @@ end
--- Set slider steps. Pin node will
-- apply closest step position
-- @tparam Slider self @{Slider}
-- @tparam Slider self Slider
-- @tparam number[] steps Array of steps
-- @usage slider:set_steps({0, 0.2, 0.6, 1})
-- @treturn Slider @{Slider}
function Slider.set_steps(self, steps)
-- @treturn Slider Slider
function M:set_steps(steps)
self.steps = steps
return self
end
@@ -214,29 +226,29 @@ end
-- 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+
-- @tparam Slider self @{Slider}
-- @tparam Slider self Slider
-- @tparam node|string|nil input_node
-- @treturn Slider @{Slider}
function Slider.set_input_node(self, input_node)
-- @treturn Slider Slider
function M:set_input_node(input_node)
self._input_node = self:get_node(input_node)
return self
end
--- Set Slider input enabled or disabled
-- @tparam Slider self @{Slider}
-- @tparam Slider self Slider
-- @tparam boolean is_enabled
function Slider.set_enabled(self, is_enabled)
function M:set_enabled(is_enabled)
self._is_enabled = is_enabled
end
--- Check if Slider component is enabled
-- @tparam Slider self @{Slider}
-- @tparam Slider self Slider
-- @treturn boolean
function Slider.is_enabled(self)
function M:is_enabled()
return self._is_enabled
end
return Slider
return M

View File

@@ -16,7 +16,7 @@
-- @tparam node|nil click_zone
--- Trigger on swipe event(self, swipe_side, dist, delta_time)
-- @tfield DruidEvent on_swipe) @{DruidEvent}
-- @tfield DruidEvent on_swipe) DruidEvent
---
@@ -25,7 +25,17 @@ local const = require("druid.const")
local helper = require("druid.helper")
local component = require("druid.component")
local Swipe = component.create("swipe")
---@class druid.swipe: druid.base_component
---@field node node
---@field on_swipe druid.event
---@field style table
---@field click_zone node
---@field private _trigger_on_move boolean
---@field private _swipe_start_time number
---@field private _start_pos vector3
---@field private _is_enabled boolean
---@field private _is_mobile boolean
local M = component.create("swipe")
local function start_swipe(self, action)
@@ -36,7 +46,7 @@ end
local function reset_swipe(self, action)
self._swipe_start_time = false
self._swipe_start_time = 0
end
@@ -77,7 +87,7 @@ end
-- @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)
function M:on_style_change(style)
self.style = {}
self.style.SWIPE_TIME = style.SWIPE_TIME or 0.4
self.style.SWIPE_THRESHOLD = style.SWIPE_THRESHOLD or 50
@@ -85,15 +95,19 @@ function Swipe.on_style_change(self, style)
end
--- The @{Swipe} constructor
-- @tparam Swipe self @{Swipe}
--- The Swipe constructor
-- @tparam Swipe self Swipe
-- @tparam node node Gui node
-- @tparam function on_swipe_callback Swipe callback for on_swipe_end event
function Swipe.init(self, node, on_swipe_callback)
self._trigger_on_move = self.style.SWIPE_TRIGGER_ON_MOVE
self.node = self:get_node(node)
self._swipe_start_time = false
---Swipe constructor
---@param node_or_node_id node|string
---@param on_swipe_callback function
function M:init(node_or_node_id, on_swipe_callback)
self._trigger_on_move = self.style.SWIPE_TRIGGER_ON_MOVE
self.node = self:get_node(node_or_node_id)
self._swipe_start_time = 0
self._start_pos = vmath.vector3(0)
self.click_zone = nil
@@ -101,7 +115,7 @@ function Swipe.init(self, node, on_swipe_callback)
end
function Swipe.on_late_init(self)
function M:on_late_init()
if not self.click_zone and const.IS_STENCIL_CHECK then
local stencil_node = helper.get_closest_stencil_node(self.node)
if stencil_node then
@@ -111,7 +125,7 @@ function Swipe.on_late_init(self)
end
function Swipe.on_input(self, action_id, action)
function M:on_input(action_id, action)
if action_id ~= const.ACTION_TOUCH then
return false
end
@@ -126,7 +140,7 @@ function Swipe.on_input(self, action_id, action)
return false
end
if self._swipe_start_time and (self._trigger_on_move or action.released) then
if self._swipe_start_time ~= 0 and (self._trigger_on_move or action.released) then
check_swipe(self, action)
end
@@ -142,18 +156,18 @@ function Swipe.on_input(self, action_id, action)
end
function Swipe.on_input_interrupt(self)
function M:on_input_interrupt()
reset_swipe(self)
end
--- Strict swipe click area. Useful for
-- restrict events outside stencil node
-- @tparam Swipe self @{Swipe}
-- @tparam Swipe self Swipe
-- @tparam node|string|nil zone Gui node
function Swipe.set_click_zone(self, zone)
function M:set_click_zone(zone)
self.click_zone = self:get_node(zone)
end
return Swipe
return M

View File

@@ -1,40 +1,18 @@
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
--- Component to handle GUI timers.
-- Timer updating by game delta time. If game is not focused -
-- timer will be not updated.
-- @module Timer
-- @within BaseComponent
-- @alias druid.timer
--- On timer tick. Fire every second callback(self, value)
-- @tfield DruidEvent on_tick @{DruidEvent}
--- On timer change enabled state callback(self, is_enabled)
-- @tfield DruidEvent on_set_enabled @{DruidEvent}
--- On timer end callback
-- @tfield DruidEvent on_timer_end(self, Timer) @{DruidEvent}
--- Trigger node
-- @tfield node node
--- Initial timer value
-- @tfield number from
--- Target timer value
-- @tfield number target
--- Current timer value
-- @tfield number value
---
local Event = require("druid.event")
local helper = require("druid.helper")
local component = require("druid.component")
local Timer = component.create("timer")
---@class druid.timer: druid.base_component
---@field on_tick druid.event
---@field on_set_enabled druid.event
---@field on_timer_end druid.event
---@field style table
---@field node node
---@field from number
---@field target number
---@field value number
---@field is_on boolean|nil
local M = component.create("timer")
local function second_string_min(sec)
@@ -44,13 +22,12 @@ local function second_string_min(sec)
end
--- The @{Timer} constructor
-- @tparam Timer self @{Timer}
-- @tparam node node Gui text node
-- @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)
---The Timer constructor
---@param node node Gui text node
---@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 M:init(node, seconds_from, seconds_to, callback)
self.node = self:get_node(node)
seconds_to = math.max(seconds_to or 0, 0)
@@ -73,7 +50,7 @@ function Timer.init(self, node, seconds_from, seconds_to, callback)
end
function Timer.update(self, dt)
function M:update(dt)
if not self.is_on then
return
end
@@ -96,42 +73,47 @@ function Timer.update(self, dt)
end
function Timer.on_layout_change(self)
function M:on_layout_change()
self:set_to(self.last_value)
end
--- Set text to text field
-- @tparam Timer self @{Timer}
-- @tparam number set_to Value in seconds
function Timer.set_to(self, set_to)
---@param self druid.timer
---@param set_to number Value in seconds
---@return druid.timer self
function M:set_to(set_to)
self.last_value = set_to
gui.set_text(self.node, second_string_min(set_to))
return self
end
--- Called when update
-- @tparam Timer self @{Timer}
-- @tparam boolean|nil is_on Timer enable state
function Timer.set_state(self, is_on)
---@param self druid.timer
---@param is_on boolean|nil Timer enable state
---@return druid.timer self
function M:set_state(is_on)
self.is_on = is_on
self.on_set_enabled:trigger(self:get_context(), is_on)
return self
end
--- Set time interval
-- @tparam Timer self @{Timer}
-- @tparam number from Start time in seconds
-- @tparam number to Target time in seconds
function Timer.set_interval(self, from, to)
---@param self druid.timer
---@param from number Start time in seconds
---@param to number Target time in seconds
---@return druid.timer self
function M:set_interval(from, to)
self.from = from
self.value = from
self.temp = 0
self.target = to
self:set_state(true)
self:set_to(from)
return self
end
return Timer
return M