mirror of
https://github.com/Insality/druid
synced 2025-09-27 18:12:21 +02:00
Update annotations P.1
This commit is contained in:
@@ -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
|
||||
|
@@ -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
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user