mirror of
https://github.com/Insality/druid.git
synced 2025-09-27 18:12:19 +02:00
Merge branch 'develop' into 43-infinity-scroll
# Conflicts: # druid/base/grid.lua # druid/const.lua # druid/system/druid_instance.lua
This commit is contained in:
@@ -1,37 +1,37 @@
|
||||
--- Component to handle back key (android, backspace)
|
||||
-- @module druid.back_handler
|
||||
-- @module BackHandler
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.back_handler
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_back On back handler callback
|
||||
--- On back handler callback(self, params)
|
||||
-- @tfield druid_event on_back
|
||||
|
||||
--- Params to back callback
|
||||
-- @tfield any params
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield any params Params to click callbacks
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("back_handler", { const.ON_INPUT })
|
||||
local BackHandler = component.create("back_handler", { const.ON_INPUT })
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function back_handler:init
|
||||
-- @tparam BackHandler self
|
||||
-- @tparam callback callback On back button
|
||||
-- @tparam[opt] params Callback argument
|
||||
function M.init(self, callback, params)
|
||||
-- @tparam[opt] any params Callback argument
|
||||
function BackHandler.init(self, callback, params)
|
||||
self.params = params
|
||||
|
||||
self.on_back = Event(callback)
|
||||
end
|
||||
|
||||
|
||||
--- Input handler for component
|
||||
-- @function back_handler:on_input
|
||||
-- @tparam BackHandler self
|
||||
-- @tparam string action_id on_input action id
|
||||
-- @tparam table action on_input action
|
||||
function M.on_input(self, action_id, action)
|
||||
function BackHandler.on_input(self, action_id, action)
|
||||
if not action[const.RELEASED] then
|
||||
return false
|
||||
end
|
||||
@@ -45,4 +45,4 @@ function M.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return BackHandler
|
||||
|
@@ -1,34 +1,27 @@
|
||||
--- Component to block input on specify zone by node
|
||||
-- @module druid.blocker
|
||||
-- @module Blocker
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.blocker
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_click On release button callback
|
||||
-- @tfield druid_event on_enable_change On enable/disable callback
|
||||
---Trigger node
|
||||
-- @tfield node node
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield node node Trigger node
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("blocker", { const.ON_INPUT })
|
||||
local Blocker = component.create("blocker", { const.ON_INPUT })
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function blocker:init
|
||||
-- @tparam Blocker self
|
||||
-- @tparam node node Gui node
|
||||
function M.init(self, node)
|
||||
function Blocker.init(self, node)
|
||||
self.node = self:get_node(node)
|
||||
|
||||
self.on_click = Event()
|
||||
self.on_enable_change = Event()
|
||||
end
|
||||
|
||||
|
||||
function M.on_input(self, action_id, action)
|
||||
function Blocker.on_input(self, action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH and
|
||||
action_id ~= const.ACTION_MULTITOUCH and
|
||||
action_id ~= nil then
|
||||
@@ -48,19 +41,19 @@ end
|
||||
|
||||
|
||||
--- Set enabled blocker component state
|
||||
-- @function blocker:set_enabled
|
||||
-- @tparam Blocker self
|
||||
-- @tparam bool state Enabled state
|
||||
function M.set_enabled(self, state)
|
||||
function Blocker.set_enabled(self, state)
|
||||
gui.set_enabled(self.node, state)
|
||||
end
|
||||
|
||||
|
||||
--- Return blocked enabled state
|
||||
-- @function blocker:is_enabled
|
||||
-- @tparam Blocker self
|
||||
-- @treturn bool True, if blocker is enabled
|
||||
function M.is_enabled(self, state)
|
||||
function Blocker.is_enabled(self)
|
||||
return gui.is_enabled(self.node)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Blocker
|
||||
|
@@ -1,32 +1,57 @@
|
||||
--- Component to handle basic GUI button
|
||||
-- @module druid.button
|
||||
-- @module Button
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.button
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_click (self, params, button_instance) On release button callback
|
||||
-- @tfield druid_event on_repeated_click (self, params, button_instance, click_amount) On repeated action button callback
|
||||
-- @tfield druid_event on_long_click (self, params, button_instance, time) On long tap button callback
|
||||
-- @tfield druid_event on_double_click (self, params, button_instance, click_amount) On double tap button callback
|
||||
-- @tfield druid_event on_hold_callback (self, params, button_instance, time) On button hold before long_click callback
|
||||
-- @tfield druid_event on_click_outside (self, params, button_instance) On click outside of button
|
||||
--- On release button callback(self, params, button_instance)
|
||||
-- @tfield druid_event on_click
|
||||
|
||||
--- On repeated action button callback(self, params, button_instance, click_amount)
|
||||
-- @tfield druid_event on_repeated_click
|
||||
|
||||
---On long tap button callback(self, params, button_instance, time)
|
||||
-- @tfield druid_event on_long_click
|
||||
|
||||
---On double tap button callback(self, params, button_instance, click_amount)
|
||||
-- @tfield druid_event on_double_click
|
||||
|
||||
---On button hold before long_click callback(self, params, button_instance, time)
|
||||
-- @tfield druid_event on_hold_callback
|
||||
|
||||
---On click outside of button(self, params, button_instance)
|
||||
-- @tfield druid_event on_click_outside
|
||||
|
||||
---Trigger node
|
||||
-- @tfield node node
|
||||
|
||||
---Animation node
|
||||
-- @tfield[opt=node] node anim_node
|
||||
|
||||
---Initial scale of anim_node
|
||||
-- @tfield vector3 start_scale
|
||||
|
||||
---Initial pos of anim_node
|
||||
-- @tfield vector3 start_pos
|
||||
|
||||
---Initial pos of anim_node
|
||||
-- @tfield vector3 pos
|
||||
|
||||
---Params to click callbacks
|
||||
-- @tfield any params
|
||||
|
||||
---Druid hover logic component
|
||||
-- @tfield druid.hover hover
|
||||
|
||||
---Restriction zone
|
||||
-- @tfield[opt] node click_zone
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield node node Trigger node
|
||||
-- @tfield[opt=node] node anim_node Animation node
|
||||
-- @tfield vector3 start_scale Initial scale of anim_node
|
||||
-- @tfield vector3 start_pos Initial pos of anim_node
|
||||
-- @tfield vector3 pos Initial pos of anim_node
|
||||
-- @tfield any params Params to click callbacks
|
||||
-- @tfield druid.hover hover Druid hover logic component
|
||||
-- @tfield[opt] node click_zone Restriction zone
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("button", { const.ON_INPUT })
|
||||
local Button = component.create("button", { const.ON_INPUT })
|
||||
|
||||
|
||||
local function is_input_match(self, action_id)
|
||||
@@ -132,7 +157,7 @@ end
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in druid styles table
|
||||
-- or create your own style
|
||||
-- @table Style
|
||||
-- @table style
|
||||
-- @tfield[opt=0.4] number LONGTAP_TIME Minimum time to trigger on_hold_callback
|
||||
-- @tfield[opt=0.8] number AUTOHOLD_TRIGGER Maximum hold time to trigger button release while holding
|
||||
-- @tfield[opt=0.4] number DOUBLETAP_TIME Time between double taps
|
||||
@@ -141,7 +166,7 @@ end
|
||||
-- @tfield function on_hover (self, node, hover_state)
|
||||
-- @tfield function on_mouse_hover (self, node, hover_state)
|
||||
-- @tfield function on_set_enabled (self, node, enabled_state)
|
||||
function M.on_style_change(self, style)
|
||||
function Button.on_style_change(self, style)
|
||||
self.style = {}
|
||||
self.style.LONGTAP_TIME = style.LONGTAP_TIME or 0.4
|
||||
self.style.AUTOHOLD_TRIGGER = style.AUTOHOLD_TRIGGER or 0.8
|
||||
@@ -156,12 +181,12 @@ end
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function button:init
|
||||
-- @tparam Button self
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function callback Button callback
|
||||
-- @tparam[opt] table params Button callback params
|
||||
-- @tparam[opt] node anim_node Button anim node (node, if not provided)
|
||||
function M.init(self, node, callback, params, anim_node)
|
||||
function Button.init(self, node, callback, params, anim_node)
|
||||
self.druid = self:get_druid()
|
||||
self.node = self:get_node(node)
|
||||
|
||||
@@ -188,7 +213,7 @@ function M.init(self, node, callback, params, anim_node)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input(self, action_id, action)
|
||||
function Button.on_input(self, action_id, action)
|
||||
if not is_input_match(self, action_id) then
|
||||
return false
|
||||
end
|
||||
@@ -257,16 +282,16 @@ function M.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input_interrupt(self)
|
||||
function Button.on_input_interrupt(self)
|
||||
self.can_action = false
|
||||
end
|
||||
|
||||
|
||||
--- Set enabled button component state
|
||||
-- @function button:set_enabled
|
||||
-- @tparam Button self
|
||||
-- @tparam bool state Enabled state
|
||||
-- @treturn druid.button Current button instance
|
||||
function M.set_enabled(self, state)
|
||||
-- @treturn Button Current button instance
|
||||
function Button.set_enabled(self, state)
|
||||
self.disabled = not state
|
||||
self.hover:set_enabled(state)
|
||||
self.style.on_set_enabled(self, self.node, state)
|
||||
@@ -276,19 +301,19 @@ end
|
||||
|
||||
|
||||
--- Return button enabled state
|
||||
-- @function button:is_enabled
|
||||
-- @tparam Button self
|
||||
-- @treturn bool True, if button is enabled
|
||||
function M.is_enabled(self)
|
||||
function Button.is_enabled(self)
|
||||
return not self.disabled
|
||||
end
|
||||
|
||||
|
||||
--- Strict button click area. Useful for
|
||||
-- no click events outside stencil node
|
||||
-- @function button:set_click_zone
|
||||
-- @tparam Button self
|
||||
-- @tparam node zone Gui node
|
||||
-- @treturn druid.button Current button instance
|
||||
function M.set_click_zone(self, zone)
|
||||
-- @treturn Button Current button instance
|
||||
function Button.set_click_zone(self, zone)
|
||||
self.click_zone = self:get_node(zone)
|
||||
self.hover:set_click_zone(zone)
|
||||
|
||||
@@ -297,10 +322,10 @@ end
|
||||
|
||||
|
||||
--- Set key-code to trigger this button
|
||||
-- @function button:set_key_trigger
|
||||
-- @tparam Button self
|
||||
-- @tparam hash key The action_id of the key
|
||||
-- @treturn druid.button Current button instance
|
||||
function M.set_key_trigger(self, key)
|
||||
-- @treturn Button Current button instance
|
||||
function Button.set_key_trigger(self, key)
|
||||
self.key_trigger = hash(key)
|
||||
|
||||
return self
|
||||
@@ -308,11 +333,11 @@ end
|
||||
|
||||
|
||||
--- Get key-code to trigger this button
|
||||
-- @function button:get_key_trigger
|
||||
-- @tparam Button self
|
||||
-- @treturn hash The action_id of the key
|
||||
function M.get_key_trigger(self)
|
||||
function Button.get_key_trigger(self)
|
||||
return self.key_trigger
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Button
|
||||
|
@@ -2,32 +2,53 @@
|
||||
-- Drag have correct handling for multitouch and swap
|
||||
-- touched while dragging. Drag will be processed even
|
||||
-- the cursor is outside of node, if drag is already started
|
||||
-- @module druid.drag
|
||||
-- @module Drag
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.drag
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_touch_start (self) Event on touch start
|
||||
-- @tfield druid_event on_touch_end (self) Event on touch end
|
||||
-- @tfield druid_event on_drag_start (self) Event on drag start
|
||||
-- @tfield druid_event on_drag (self, dx, dy) Event on drag progress
|
||||
-- @tfield druid_event on_drag_end (self) Event on drag end
|
||||
--- Event on touch start callback(self)
|
||||
-- @tfield druid_event on_touch_start
|
||||
|
||||
--- Event on touch end callback(self)
|
||||
-- @tfield druid_event on_touch_end
|
||||
|
||||
--- Event on drag start callback(self)
|
||||
-- @tfield druid_event on_drag_start
|
||||
|
||||
--- on drag progress callback(self, dx, dy)
|
||||
-- @tfield druid_event on_drag Event
|
||||
|
||||
--- Event on drag end callback(self)
|
||||
-- @tfield druid_event on_drag_end
|
||||
|
||||
--- Is component now touching
|
||||
-- @tfield bool is_touch
|
||||
|
||||
--- Is component now dragging
|
||||
-- @tfield bool is_drag
|
||||
|
||||
--- Is drag component process vertical dragging. Default - true
|
||||
-- @tfield bool can_x
|
||||
|
||||
--- Is drag component process horizontal. Default - true
|
||||
-- @tfield bool can_y
|
||||
|
||||
--- Current touch x position
|
||||
-- @tfield number x
|
||||
|
||||
--- Current touch y position
|
||||
-- @tfield number y
|
||||
|
||||
--- Touch start position
|
||||
-- @tfield vector3 touch_start_pos
|
||||
|
||||
--- Components fields
|
||||
-- @table Fields
|
||||
-- @tfield bool is_touch Is component now touching
|
||||
-- @tfield bool is_drag Is component now dragging
|
||||
-- @tfield bool can_x Is drag component process vertical dragging. Default - true
|
||||
-- @tfield bool can_y Is drag component process horizontal. Default - true
|
||||
-- @tfield number x Current touch x position
|
||||
-- @tfield number y Current touch y position
|
||||
-- @tfield vector3 touch_start_pos Touch start position
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("drag", { const.ON_INPUT_HIGH })
|
||||
local Drag = component.create("drag", { const.ON_INPUT_HIGH })
|
||||
|
||||
|
||||
local function start_touch(self, touch)
|
||||
@@ -127,19 +148,19 @@ end
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in druid styles table
|
||||
-- or create your own style
|
||||
-- @table Style
|
||||
-- @table style
|
||||
-- @tfield[opt=10] number DRAG_DEADZONE Distance in pixels to start dragging
|
||||
function M.on_style_change(self, style)
|
||||
function Drag.on_style_change(self, style)
|
||||
self.style = {}
|
||||
self.style.DRAG_DEADZONE = style.DRAG_DEADZONE or 10
|
||||
end
|
||||
|
||||
|
||||
--- Drag component constructor
|
||||
-- @tparam Drag self
|
||||
-- @tparam node node GUI node to detect dragging
|
||||
-- @tparam function on_drag_callback Callback for on_drag_event(self, dx, dy)
|
||||
-- @function drag:init
|
||||
function M.init(self, node, on_drag_callback)
|
||||
function Drag.init(self, node, on_drag_callback)
|
||||
self.node = self:get_node(node)
|
||||
|
||||
self.dx = 0
|
||||
@@ -163,14 +184,14 @@ function M.init(self, node, on_drag_callback)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input_interrupt(self)
|
||||
function Drag.on_input_interrupt(self)
|
||||
if self.is_drag or self.is_touch then
|
||||
end_touch(self)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function M.on_input(self, action_id, action)
|
||||
function Drag.on_input(self, action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH and action_id ~= const.ACTION_MULTITOUCH then
|
||||
return false
|
||||
end
|
||||
@@ -241,11 +262,11 @@ end
|
||||
|
||||
--- Strict drag click area. Useful for
|
||||
-- restrict events outside stencil node
|
||||
-- @function drag:set_click_zone
|
||||
-- @tparam Drag self
|
||||
-- @tparam node zone Gui node
|
||||
function M.set_click_zone(self, zone)
|
||||
function Drag.set_click_zone(self, zone)
|
||||
self.click_zone = self:get_node(zone)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Drag
|
||||
|
@@ -1,277 +0,0 @@
|
||||
--- Component to handle placing components by row and columns.
|
||||
-- Grid can anchor your elements, get content size and other
|
||||
-- @module druid.grid
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_add_item On item add callback
|
||||
-- @tfield druid_event on_remove_item On item remove callback
|
||||
-- @tfield druid_event on_clear On grid clear callback
|
||||
-- @tfield druid_event on_update_positions On update item positions callback
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield node parent Parent gui node
|
||||
-- @tfield node[] nodes List of all grid nodes
|
||||
-- @tfield vector3 offset Item distance between each other items
|
||||
-- @tfield vector3 anchor Item anchor
|
||||
-- @tfield vector3 node_size Item size
|
||||
-- @tfield vector4 border The size of item content
|
||||
-- @tfield vector3 border_offer The border offset for correct anchor calculations
|
||||
|
||||
local const = require("druid.const")
|
||||
local Event = require("druid.event")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("grid", { const.ON_LAYOUT_CHANGE })
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function grid:init
|
||||
-- @tparam node parent The gui node parent, where items will be placed
|
||||
-- @tparam node element Element prefab. Need to get it size
|
||||
-- @tparam[opt=1] number in_row How many nodes in row can be placed
|
||||
function M.init(self, parent, element, in_row)
|
||||
self.parent = self:get_node(parent)
|
||||
self.nodes = {}
|
||||
|
||||
self.offset = vmath.vector3(0)
|
||||
self.grid_mode = const.GRID_MODE.DYNAMIC
|
||||
|
||||
local pivot = helper.get_pivot_offset(gui.get_pivot(self.parent))
|
||||
self.anchor = vmath.vector3(0.5 + pivot.x, 0.5 - pivot.y, 0)
|
||||
|
||||
self.in_row = in_row or 1
|
||||
local node = self:get_node(element)
|
||||
self.node_size = gui.get_size(node)
|
||||
self.node_pivot = const.PIVOTS[gui.get_pivot(node)]
|
||||
|
||||
self.border = vmath.vector4(0)
|
||||
self.border_offset = vmath.vector3(0)
|
||||
|
||||
self.on_add_item = Event()
|
||||
self.on_remove_item = Event()
|
||||
self.on_clear = Event()
|
||||
self.on_update_positions = Event()
|
||||
|
||||
self._set_position_function = gui.set_position
|
||||
end
|
||||
|
||||
|
||||
local function _update_border(self, pos, border)
|
||||
local size = self.node_size
|
||||
local pivot = self.node_pivot
|
||||
|
||||
local left = pos.x - size.x/2 - (size.x * pivot.x) + self.border_offset.x
|
||||
local right = pos.x + size.x/2 - (size.x * pivot.x) + self.border_offset.x
|
||||
local top = pos.y + size.y/2 - (size.y * pivot.y) + self.border_offset.y
|
||||
local bottom = pos.y - size.y/2 - (size.y * pivot.y)+ self.border_offset.y
|
||||
|
||||
border.x = math.min(border.x, left)
|
||||
border.y = math.max(border.y, top)
|
||||
border.z = math.max(border.z, right)
|
||||
border.w = math.min(border.w, bottom)
|
||||
end
|
||||
|
||||
|
||||
local function update_border_offset(self, pos)
|
||||
local border = self.border
|
||||
_update_border(self, pos, border)
|
||||
|
||||
self.border_offset = vmath.vector3(
|
||||
(border.x + (border.z - border.x) * self.anchor.x),
|
||||
(border.y + (border.w - border.y) * self.anchor.y),
|
||||
0
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
local function update_pos(self, is_instant)
|
||||
for i, node in pairs(self.nodes) do
|
||||
if is_instant then
|
||||
gui.set_position(node, self:get_pos(i))
|
||||
else
|
||||
self._set_position_function(node, self:get_pos(i))
|
||||
end
|
||||
end
|
||||
|
||||
self.on_update_positions:trigger(self:get_context())
|
||||
end
|
||||
|
||||
|
||||
local temp_pos = vmath.vector3(0)
|
||||
--- Return pos for grid node index
|
||||
-- @function grid:get_pos
|
||||
-- @tparam number index The grid element index
|
||||
-- @treturn vector3 Node position
|
||||
function M.get_pos(self, index)
|
||||
local row = math.ceil(index / self.in_row) - 1
|
||||
local col = (index - row * self.in_row) - 1
|
||||
|
||||
temp_pos.x = col * (self.node_size.x + self.offset.x) - self.border_offset.x
|
||||
temp_pos.y = -row * (self.node_size.y + self.offset.y) - self.border_offset.y
|
||||
temp_pos.z = 0
|
||||
|
||||
return temp_pos
|
||||
end
|
||||
|
||||
|
||||
--- Return index for grid pos
|
||||
-- @function grid:get_index
|
||||
-- @tparam vector3 pos The node position in the grid
|
||||
-- @treturn number The node index
|
||||
function M.get_index(self, pos)
|
||||
local col = (pos.x + self.border_offset.x) / (self.node_size.x + self.offset.x)
|
||||
local row = -(pos.y + self.border_offset.y) / (self.node_size.y + self.offset.y)
|
||||
|
||||
row = math.floor(row)
|
||||
|
||||
local index = col + (row * self.in_row)
|
||||
return math.ceil(index)
|
||||
end
|
||||
|
||||
|
||||
function M.on_layout_change(self)
|
||||
update_pos(self, true)
|
||||
end
|
||||
|
||||
|
||||
--- Set grid items offset, the distance between items
|
||||
-- @function grid:set_offset
|
||||
-- @tparam vector3 offset Offset
|
||||
function M.set_offset(self, offset)
|
||||
self.offset = offset
|
||||
update_pos(self)
|
||||
end
|
||||
|
||||
|
||||
--- Set grid anchor
|
||||
-- @function grid:set_anchor
|
||||
-- @tparam vector3 acnhor Anchor
|
||||
function M.set_anchor(self, anchor)
|
||||
self.anchor = anchor
|
||||
update_pos(self)
|
||||
end
|
||||
|
||||
|
||||
--- Add new item to the grid
|
||||
-- @function grid:add
|
||||
-- @tparam node item Gui node
|
||||
-- @tparam[opt] number index The item position. By default add as last item
|
||||
function M.add(self, item, index)
|
||||
index = index or (#self.nodes + 1)
|
||||
|
||||
if self.grid_mode == const.GRID_MODE.DYNAMIC then
|
||||
table.insert(self.nodes, index, item)
|
||||
else
|
||||
self.nodes[index] = item
|
||||
end
|
||||
|
||||
gui.set_parent(item, self.parent)
|
||||
|
||||
local pos = self:get_pos(index)
|
||||
for i, _ in pairs(self.nodes) do
|
||||
update_border_offset(self, self:get_pos(i))
|
||||
end
|
||||
|
||||
-- Add new item instantly in new pos
|
||||
gui.set_position(item, pos)
|
||||
update_pos(self)
|
||||
|
||||
self.on_add_item:trigger(self:get_context(), item, index)
|
||||
end
|
||||
|
||||
|
||||
function M:remove(index, delete_node)
|
||||
assert(self.nodes[index], "No grid item at given index " .. index)
|
||||
|
||||
local parent_node = self.nodes[index]
|
||||
if delete_node then
|
||||
gui.delete_node(parent_node)
|
||||
end
|
||||
|
||||
if self.grid_mode == const.GRID_MODE.DYNAMIC then
|
||||
table.remove(self.nodes, index)
|
||||
else
|
||||
self.nodes[index] = nil
|
||||
end
|
||||
|
||||
-- Recalculate borders
|
||||
self.border = vmath.vector4(0)
|
||||
update_border_offset(self, self:get_pos(1))
|
||||
for i, _ in pairs(self.nodes) do
|
||||
local pos = self:get_pos(i)
|
||||
update_border_offset(self, pos)
|
||||
end
|
||||
|
||||
update_pos(self)
|
||||
end
|
||||
|
||||
|
||||
--- Return grid content size
|
||||
-- @function grid:get_size
|
||||
-- @treturn vector3 The grid content size
|
||||
function M.get_size(self, border)
|
||||
border = border or self.border
|
||||
return vmath.vector3(
|
||||
border.z - border.x,
|
||||
border.y - border.w,
|
||||
0)
|
||||
end
|
||||
|
||||
|
||||
function M:get_size_for_elements_count(count)
|
||||
local border = vmath.vector4(0)
|
||||
for i = 1, count do
|
||||
local pos = self:get_pos(i)
|
||||
_update_border(self, pos, border)
|
||||
end
|
||||
|
||||
return M.get_size(self, border)
|
||||
end
|
||||
|
||||
|
||||
--- Return array of all node positions
|
||||
-- @function grid:get_all_pos
|
||||
-- @treturn vector3[] All grid node positions
|
||||
function M.get_all_pos(self)
|
||||
local result = {}
|
||||
for i, node in pairs(self.nodes) do
|
||||
table.insert(result, gui.get_position(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
|
||||
-- @function grid:set_position_function
|
||||
-- @tparam function callback Function on node set position
|
||||
function M.set_position_function(self, callback)
|
||||
self._set_position_function = callback or gui.set_position
|
||||
end
|
||||
|
||||
|
||||
--- Clear grid nodes array. GUI nodes will be not deleted!
|
||||
-- If you want to delete GUI nodes, use grid.nodes array before grid:clear
|
||||
-- @function grid:clear
|
||||
function M.clear(self)
|
||||
self.border.x = 0
|
||||
self.border.y = 0
|
||||
self.border.w = 0
|
||||
self.border.z = 0
|
||||
|
||||
self.nodes = {}
|
||||
end
|
||||
|
||||
|
||||
function M:set_grid_mode(grid_mode)
|
||||
assert(grid_mode == const.GRID_MODE.STATIC or grid_mode == const.GRID_MODE.DYNAMIC)
|
||||
|
||||
self.grid_mode = grid_mode
|
||||
end
|
||||
|
||||
|
||||
return M
|
@@ -1,24 +1,28 @@
|
||||
--- Component to handle hover node interaction
|
||||
-- @module druid.hover
|
||||
-- @module Hover
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.hover
|
||||
|
||||
--- On hover callback(self, state)
|
||||
-- @tfield druid_event on_hover
|
||||
|
||||
--- On mouse hover callback(self, state)
|
||||
-- @tfield druid_event on_mouse_hover
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_hover On hover callback (Touch pressed)
|
||||
-- @tfield druid_event on_mouse_hover On mouse hover callback (Touch over without action_id)
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("hover", { const.ON_INPUT })
|
||||
local Hover = component.create("hover", { const.ON_INPUT })
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function hover:init
|
||||
-- @tparam Hover self
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function on_hover_callback Hover callback
|
||||
function M.init(self, node, on_hover_callback)
|
||||
function Hover.init(self, node, on_hover_callback)
|
||||
self.node = self:get_node(node)
|
||||
|
||||
self._is_hovered = false
|
||||
@@ -31,7 +35,7 @@ function M.init(self, node, on_hover_callback)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input(self, action_id, action)
|
||||
function Hover.on_input(self, action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH and action_id ~= nil then
|
||||
return false
|
||||
end
|
||||
@@ -49,7 +53,7 @@ function M.on_input(self, action_id, action)
|
||||
is_pick = is_pick and gui.pick_node(self.click_zone, action.x, action.y)
|
||||
end
|
||||
|
||||
local hover_function = action_id and M.set_hover or M.set_mouse_hover
|
||||
local hover_function = action_id and self.set_hover or self.set_mouse_hover
|
||||
|
||||
if not is_pick then
|
||||
hover_function(self, false)
|
||||
@@ -64,15 +68,15 @@ function M.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input_interrupt(self)
|
||||
function Hover.on_input_interrupt(self)
|
||||
self:set_hover(false)
|
||||
end
|
||||
|
||||
|
||||
--- Set hover state
|
||||
-- @function hover:set_hover
|
||||
-- @tparam Hover self
|
||||
-- @tparam bool state The hover state
|
||||
function M.set_hover(self, state)
|
||||
function Hover.set_hover(self, state)
|
||||
if self._is_hovered ~= state then
|
||||
self._is_hovered = state
|
||||
self.on_hover:trigger(self:get_context(), state)
|
||||
@@ -80,9 +84,9 @@ function M.set_hover(self, state)
|
||||
end
|
||||
|
||||
--- Set mouse hover state
|
||||
-- @function hover:set_mouse_hover
|
||||
-- @tparam Hover self
|
||||
-- @tparam bool state The mouse hover state
|
||||
function M.set_mouse_hover(self, state)
|
||||
function Hover.set_mouse_hover(self, state)
|
||||
if self._is_mouse_hovered ~= state then
|
||||
self._is_mouse_hovered = state
|
||||
self.on_mouse_hover:trigger(self:get_context(), state)
|
||||
@@ -92,9 +96,9 @@ end
|
||||
|
||||
--- Strict hover click area. Useful for
|
||||
-- no click events outside stencil node
|
||||
-- @function hover:set_click_zone
|
||||
-- @tparam Hover self
|
||||
-- @tparam node zone Gui node
|
||||
function M.set_click_zone(self, zone)
|
||||
function Hover.set_click_zone(self, zone)
|
||||
self.click_zone = self:get_node(zone)
|
||||
end
|
||||
|
||||
@@ -102,9 +106,9 @@ end
|
||||
--- Set enable state of hover component.
|
||||
-- If hover is not enabled, it will not generate
|
||||
-- any hover events
|
||||
-- @function hover:set_enabled
|
||||
-- @tparam Hover self
|
||||
-- @tparam bool state The hover enabled state
|
||||
function M.set_enabled(self, state)
|
||||
function Hover.set_enabled(self, state)
|
||||
self._is_enabled = state
|
||||
|
||||
if not state then
|
||||
@@ -119,11 +123,11 @@ end
|
||||
|
||||
|
||||
--- Return current hover enabled state
|
||||
-- @function hover:is_enabled
|
||||
-- @tparam Hover self
|
||||
-- @treturn bool The hover enabled state
|
||||
function M.is_enabled(self)
|
||||
function Hover.is_enabled(self)
|
||||
return self._is_enabled
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Hover
|
||||
|
@@ -5,34 +5,60 @@
|
||||
-- Setup initial scroll size by changing scroll parent size. If scroll parent
|
||||
-- size will be less than scroll_input size, no scroll is available. For scroll
|
||||
-- parent size should be more than input size
|
||||
-- @module druid.scroll
|
||||
-- @module Scroll
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.scroll
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_scroll On scroll move callback
|
||||
-- @tfield druid_event on_scroll_to On scroll_to function callback
|
||||
-- @tfield druid_event on_point_scroll On scroll_to_index function callback
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield node view_node Scroll view node
|
||||
-- @tfield node content_node Scroll content node
|
||||
-- @tfield bool is_inert Flag, if scroll now moving by inertion
|
||||
-- @tfield vector3 inertion Current inert speed
|
||||
-- @tfield vector3 position Current scroll posisition
|
||||
-- @tfield vector3 target_position Current scroll target position
|
||||
-- @tfield vector4 available_pos Available position for content node: (min_x, max_y, max_x, min_y)
|
||||
-- @tfield vector3 available_size Size of available positions: (width, height, 0)
|
||||
-- @tfield druid.drag drag Drag component
|
||||
-- @tfield[opt] selected Current index of points of interests
|
||||
-- @tfield bool is_animate Flag, if scroll now animating by gui.animate
|
||||
--- On scroll move callback(self, position)
|
||||
-- @tfield druid_event on_scroll
|
||||
|
||||
--- On scroll_to function callback(self, target, is_instant)
|
||||
-- @tfield druid_event on_scroll_to
|
||||
|
||||
--- On scroll_to_index function callback(self, index, point)
|
||||
-- @tfield druid_event on_point_scroll
|
||||
|
||||
--- Scroll view node
|
||||
-- @tfield node view_node
|
||||
|
||||
--- Scroll content node
|
||||
-- @tfield node content_node
|
||||
|
||||
--- Flag, if scroll now moving by inertion
|
||||
-- @tfield bool is_inert
|
||||
|
||||
--- Current inert speed
|
||||
-- @tfield vector3 inertion
|
||||
|
||||
--- Current scroll posisition
|
||||
-- @tfield vector3 position
|
||||
|
||||
--- Current scroll target position
|
||||
-- @tfield vector3 target_position
|
||||
|
||||
--- Available position for content node: (min_x, max_y, max_x, min_y)
|
||||
-- @tfield vector4 available_pos
|
||||
|
||||
--- Size of available positions: (width, height, 0)
|
||||
-- @tfield vector3 available_size
|
||||
|
||||
--- Drag Druid component
|
||||
-- @tfield Drag drag
|
||||
|
||||
--- Current index of points of interests
|
||||
-- @tfield[opt] number selected
|
||||
|
||||
--- Flag, if scroll now animating by gui.animate
|
||||
-- @tfield bool is_animate
|
||||
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("scroll", { const.ON_UPDATE, const.ON_LAYOUT_CHANGE })
|
||||
local Scroll = component.create("scroll", { const.ON_UPDATE, const.ON_LAYOUT_CHANGE })
|
||||
|
||||
|
||||
local function inverse_lerp(min, max, current)
|
||||
@@ -61,7 +87,300 @@ local function get_size_vector(vector)
|
||||
end
|
||||
|
||||
|
||||
local function on_scroll_drag(self, dx, dy)
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in druid styles table
|
||||
-- or create your own style
|
||||
-- @table style
|
||||
-- @tfield[opt=0] number FRICT Multiplier for free inertion
|
||||
-- @tfield[opt=0] number FRICT_HOLD Multiplier for inertion, while touching
|
||||
-- @tfield[opt=3] number INERT_THRESHOLD Scroll speed to stop inertion
|
||||
-- @tfield[opt=30] number INERT_SPEED Multiplier for inertion speed
|
||||
-- @tfield[opt=20] number POINTS_DEADZONE Speed to check points of interests in no_inertion mode
|
||||
-- @tfield[opt=0.35] number BACK_SPEED Scroll back returning lerp speed
|
||||
-- @tfield[opt=0.2] number ANIM_SPEED Scroll gui.animation speed for scroll_to function
|
||||
-- @tfield[opt=0] number EXTRA_STRETCH_SIZE extra size in pixels outside of scroll (stretch effect)
|
||||
-- @tfield[opt=false] bool SMALL_CONTENT_SCROLL If true, content node with size less than view node size can be scrolled
|
||||
function Scroll.on_style_change(self, style)
|
||||
self.style = {}
|
||||
self.style.EXTRA_STRETCH_SIZE = style.EXTRA_STRETCH_SIZE or 0
|
||||
self.style.ANIM_SPEED = style.ANIM_SPEED or 0.2
|
||||
self.style.BACK_SPEED = style.BACK_SPEED or 0.35
|
||||
|
||||
self.style.FRICT = style.FRICT or 0
|
||||
self.style.FRICT_HOLD = style.FRICT_HOLD or 0
|
||||
|
||||
self.style.INERT_THRESHOLD = style.INERT_THRESHOLD or 3
|
||||
self.style.INERT_SPEED = style.INERT_SPEED or 30
|
||||
self.style.POINTS_DEADZONE = style.POINTS_DEADZONE or 20
|
||||
self.style.SMALL_CONTENT_SCROLL = style.SMALL_CONTENT_SCROLL or false
|
||||
|
||||
self._is_inert = not (self.style.FRICT == 0 or
|
||||
self.style.FRICT_HOLD == 0 or
|
||||
self.style.INERT_SPEED == 0)
|
||||
end
|
||||
|
||||
|
||||
--- Scroll constructor
|
||||
-- @tparam Scroll self
|
||||
-- @tparam node view_node GUI view scroll node
|
||||
-- @tparam node content_node GUI content scroll node
|
||||
function Scroll.init(self, view_node, content_node)
|
||||
self.druid = self:get_druid()
|
||||
|
||||
self.view_node = self:get_node(view_node)
|
||||
self.content_node = self:get_node(content_node)
|
||||
|
||||
self.position = gui.get_position(self.content_node)
|
||||
self.target_position = vmath.vector3(self.position)
|
||||
self.inertion = vmath.vector3(0)
|
||||
|
||||
self.drag = self.druid:new_drag(view_node, self._on_scroll_drag)
|
||||
self.drag.on_touch_start:subscribe(self._on_touch_start)
|
||||
self.drag.on_touch_end:subscribe(self._on_touch_end)
|
||||
|
||||
self.on_scroll = Event()
|
||||
self.on_scroll_to = Event()
|
||||
self.on_point_scroll = Event()
|
||||
|
||||
self.selected = nil
|
||||
self.is_animate = false
|
||||
|
||||
self._is_horizontal_scroll = true
|
||||
self._is_vertical_scroll = true
|
||||
self._grid_on_change = nil
|
||||
self._grid_on_change_callback = nil
|
||||
|
||||
self:_update_size()
|
||||
end
|
||||
|
||||
|
||||
function Scroll.on_layout_change(self)
|
||||
gui.set_position(self.content_node, self.position)
|
||||
end
|
||||
|
||||
|
||||
function Scroll.update(self, dt)
|
||||
if self.drag.is_drag then
|
||||
self:_update_hand_scroll(dt)
|
||||
else
|
||||
self:_update_free_scroll(dt)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Scroll.on_remove(self)
|
||||
self:bind_grid(nil)
|
||||
end
|
||||
|
||||
|
||||
--- Start scroll to target point.
|
||||
-- @tparam Scroll self
|
||||
-- @tparam vector3 point Target point
|
||||
-- @tparam[opt] bool is_instant Instant scroll flag
|
||||
-- @usage scroll:scroll_to(vmath.vector3(0, 50, 0))
|
||||
-- @usage scroll:scroll_to(vmath.vector3(0), true)
|
||||
function Scroll.scroll_to(self, point, is_instant)
|
||||
local b = self.available_pos
|
||||
local target = vmath.vector3(-point.x, -point.y, 0)
|
||||
target.x = helper.clamp(target.x, b.x, b.z)
|
||||
target.y = helper.clamp(target.y, b.y, b.w)
|
||||
|
||||
self:_cancel_animate()
|
||||
|
||||
self.is_animate = not is_instant
|
||||
|
||||
if is_instant then
|
||||
self.target_position = target
|
||||
self:_set_scroll_position(target)
|
||||
else
|
||||
gui.animate(self.content_node, gui.PROP_POSITION, target, gui.EASING_OUTSINE, self.style.ANIM_SPEED, 0, function()
|
||||
self.is_animate = false
|
||||
self.target_position = target
|
||||
self:_set_scroll_position(target)
|
||||
end)
|
||||
end
|
||||
|
||||
self.on_scroll_to:trigger(self:get_context(), target, is_instant)
|
||||
end
|
||||
|
||||
|
||||
--- Scroll to item in scroll by point index.
|
||||
-- @tparam Scroll self
|
||||
-- @tparam number index Point index
|
||||
-- @tparam[opt] bool skip_cb If true, skip the point callback
|
||||
function Scroll.scroll_to_index(self, index, skip_cb)
|
||||
if not self.points then
|
||||
return
|
||||
end
|
||||
|
||||
index = helper.clamp(index, 1, #self.points)
|
||||
|
||||
if self.selected ~= index then
|
||||
self.selected = index
|
||||
|
||||
if not skip_cb then
|
||||
self.on_point_scroll:trigger(self:get_context(), index, self.points[index])
|
||||
end
|
||||
end
|
||||
|
||||
self:scroll_to(self.points[index])
|
||||
end
|
||||
|
||||
|
||||
--- Start scroll to target scroll percent
|
||||
-- @tparam Scroll self
|
||||
-- @tparam vector3 percent target percent
|
||||
-- @tparam[opt] bool is_instant instant scroll flag
|
||||
-- @usage scroll:scroll_to_percent(vmath.vector3(0.5, 0, 0))
|
||||
function Scroll.scroll_to_percent(self, percent, is_instant)
|
||||
local border = self.available_pos
|
||||
|
||||
local pos = vmath.vector3(
|
||||
-helper.lerp(border.x, border.z, 1 - percent.x),
|
||||
-helper.lerp(border.w, border.y, 1 - percent.y),
|
||||
0
|
||||
)
|
||||
|
||||
self:scroll_to(pos, is_instant)
|
||||
end
|
||||
|
||||
|
||||
--- Return current scroll progress status.
|
||||
-- Values will be in [0..1] interval
|
||||
-- @tparam Scroll self
|
||||
-- @treturn vector3 New vector with scroll progress values
|
||||
function Scroll.get_percent(self)
|
||||
local x_perc = 1 - inverse_lerp(self.available_pos.x, self.available_pos.z, self.position.x)
|
||||
local y_perc = inverse_lerp(self.available_pos.w, self.available_pos.y, self.position.y)
|
||||
|
||||
return vmath.vector3(x_perc, y_perc, 0)
|
||||
end
|
||||
|
||||
|
||||
--- Set scroll content size.
|
||||
-- It will change content gui node size
|
||||
-- @tparam Scroll self
|
||||
-- @tparam vector3 size The new size for content node
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_size(self, size)
|
||||
gui.set_size(self.content_node, size)
|
||||
self:_update_size()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Enable or disable scroll inert.
|
||||
-- If disabled, scroll through points (if exist)
|
||||
-- If no points, just simple drag without inertion
|
||||
-- @tparam Scroll self
|
||||
-- @tparam bool state Inert scroll state
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_inert(self, state)
|
||||
self._is_inert = state
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Return if scroll have inertion.
|
||||
-- @tparam Scroll self
|
||||
-- @treturn bool If scroll have inertion
|
||||
function Scroll.is_inert(self)
|
||||
return self._is_inert
|
||||
end
|
||||
|
||||
|
||||
--- Set extra size for scroll stretching.
|
||||
-- Set 0 to disable stretching effect
|
||||
-- @tparam Scroll self
|
||||
-- @tparam[opt=0] number stretch_size Size in pixels of additional scroll area
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_extra_stretch_size(self, stretch_size)
|
||||
self.style.EXTRA_STRETCH_SIZE = stretch_size or 0
|
||||
self:_update_size()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Return vector of scroll size with width and height.
|
||||
-- @tparam Scroll self
|
||||
-- @treturn vector3 Available scroll size
|
||||
function Scroll.get_scroll_size(self)
|
||||
return self.available_size
|
||||
end
|
||||
|
||||
|
||||
--- Set points of interest.
|
||||
-- Scroll will always centered on closer points
|
||||
-- @tparam Scroll self
|
||||
-- @tparam table points Array of vector3 points
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_points(self, points)
|
||||
self.points = points
|
||||
|
||||
table.sort(self.points, function(a, b)
|
||||
return a.x > b.x or a.y < b.y
|
||||
end)
|
||||
|
||||
self:_check_threshold()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Lock or unlock horizontal scroll
|
||||
-- @tparam Scroll self
|
||||
-- @tparam bool state True, if horizontal scroll is enabled
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_horizontal_scroll(self, state)
|
||||
self._is_horizontal_scroll = state
|
||||
self.drag.can_x = self.available_size.x > 0 and state
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Lock or unlock vertical scroll
|
||||
-- @tparam Scroll self
|
||||
-- @tparam bool state True, if vertical scroll is enabled
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.set_vertical_scroll(self, state)
|
||||
self._is_vertical_scroll = state
|
||||
self.drag.can_y = self.available_size.y > 0 and state
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Bind the grid component (Static or Dynamic) to recalculate
|
||||
-- scroll size on grid changes
|
||||
-- @tparam Scroll self
|
||||
-- @tparam StaticGrid|DynamicGrid grid Druid grid component
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function Scroll.bind_grid(self, grid)
|
||||
if self._grid_on_change then
|
||||
self._grid_on_change:unsubscribe(self._grid_on_change_callback)
|
||||
|
||||
self._grid_on_change = nil
|
||||
self._grid_on_change_callback = nil
|
||||
end
|
||||
|
||||
if not grid then
|
||||
return
|
||||
end
|
||||
|
||||
self._grid_on_change = grid.on_change_items
|
||||
self._grid_on_change_callback = self._grid_on_change:subscribe(function()
|
||||
self:set_size(grid:get_size())
|
||||
end)
|
||||
self:set_size(grid:get_size())
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function Scroll._on_scroll_drag(self, dx, dy)
|
||||
local t = self.target_position
|
||||
local b = self.available_pos
|
||||
local eb = self.available_pos_extra
|
||||
@@ -102,7 +421,7 @@ local function on_scroll_drag(self, dx, dy)
|
||||
end
|
||||
|
||||
|
||||
local function check_soft_zone(self)
|
||||
function Scroll._check_soft_zone(self)
|
||||
local target = self.target_position
|
||||
local border = self.available_pos
|
||||
local speed = self.style.BACK_SPEED
|
||||
@@ -127,7 +446,7 @@ end
|
||||
|
||||
|
||||
--- Cancel animation on other animation or input touch
|
||||
local function cancel_animate(self)
|
||||
function Scroll._cancel_animate(self)
|
||||
if self.is_animate then
|
||||
self.target_position = gui.get_position(self.content_node)
|
||||
self.position.x = self.target_position.x
|
||||
@@ -138,8 +457,7 @@ local function cancel_animate(self)
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function set_scroll_position(self, position)
|
||||
function Scroll._set_scroll_position(self, position)
|
||||
local available_extra = self.available_pos_extra
|
||||
position.x = helper.clamp(position.x, available_extra.x, available_extra.z)
|
||||
position.y = helper.clamp(position.y, available_extra.w, available_extra.y)
|
||||
@@ -158,7 +476,7 @@ end
|
||||
-- if no inert, scroll to next point by scroll direction
|
||||
-- if inert, find next point by scroll director
|
||||
-- @local
|
||||
local function check_points(self)
|
||||
function Scroll._check_points(self)
|
||||
if not self.points then
|
||||
return
|
||||
end
|
||||
@@ -210,7 +528,7 @@ local function check_points(self)
|
||||
end
|
||||
|
||||
|
||||
local function check_threshold(self)
|
||||
function Scroll._check_threshold(self)
|
||||
local is_stopped = false
|
||||
|
||||
if self.inertion.x ~= 0 and math.abs(self.inertion.x) < self.style.INERT_THRESHOLD then
|
||||
@@ -223,12 +541,12 @@ local function check_threshold(self)
|
||||
end
|
||||
|
||||
if is_stopped or not self._is_inert then
|
||||
check_points(self)
|
||||
self:_check_points()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function update_free_scroll(self, dt)
|
||||
function Scroll._update_free_scroll(self, dt)
|
||||
local target = self.target_position
|
||||
|
||||
if self._is_inert and (self.inertion.x ~= 0 or self.inertion.y ~= 0) then
|
||||
@@ -236,31 +554,31 @@ local function update_free_scroll(self, dt)
|
||||
target.x = self.position.x + self.inertion.x * self.style.INERT_SPEED * dt
|
||||
target.y = self.position.y + self.inertion.y * self.style.INERT_SPEED * dt
|
||||
|
||||
check_threshold(self)
|
||||
self:_check_threshold()
|
||||
end
|
||||
|
||||
-- Inertion friction
|
||||
self.inertion = self.inertion * self.style.FRICT
|
||||
|
||||
check_soft_zone(self)
|
||||
self:_check_soft_zone()
|
||||
if self.position.x ~= target.x or self.position.y ~= target.y then
|
||||
set_scroll_position(self, target)
|
||||
self:_set_scroll_position(target)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function update_hand_scroll(self, dt)
|
||||
function Scroll._update_hand_scroll(self, dt)
|
||||
local dx = self.target_position.x - self.position.x
|
||||
local dy = self.target_position.y - self.position.y
|
||||
|
||||
self.inertion.x = (self.inertion.x + dx) * self.style.FRICT_HOLD
|
||||
self.inertion.y = (self.inertion.y + dy) * self.style.FRICT_HOLD
|
||||
|
||||
set_scroll_position(self, self.target_position)
|
||||
self:_set_scroll_position(self.target_position)
|
||||
end
|
||||
|
||||
|
||||
local function on_touch_start(self)
|
||||
function Scroll._on_touch_start(self)
|
||||
self.inertion.x = 0
|
||||
self.inertion.y = 0
|
||||
self.target_position.x = self.position.x
|
||||
@@ -268,12 +586,12 @@ local function on_touch_start(self)
|
||||
end
|
||||
|
||||
|
||||
local function on_touch_end(self)
|
||||
check_threshold(self)
|
||||
function Scroll._on_touch_end(self)
|
||||
self:_check_threshold()
|
||||
end
|
||||
|
||||
|
||||
local function update_size(self)
|
||||
function Scroll._update_size(self)
|
||||
local view_border = helper.get_border(self.view_node)
|
||||
local view_size = vmath.mul_per_elem(gui.get_size(self.view_node), gui.get_scale(self.view_node))
|
||||
|
||||
@@ -283,8 +601,8 @@ local function update_size(self)
|
||||
self.available_pos = get_border_vector(view_border - content_border)
|
||||
self.available_size = get_size_vector(self.available_pos)
|
||||
|
||||
self.drag.can_x = self.available_size.x > 0
|
||||
self.drag.can_y = self.available_size.y > 0
|
||||
self.drag.can_x = self.available_size.x > 0 and self._is_horizontal_scroll
|
||||
self.drag.can_y = self.available_size.y > 0 and self._is_vertical_scroll
|
||||
|
||||
-- Extra content size calculation
|
||||
-- We add extra size only if scroll is available
|
||||
@@ -314,237 +632,4 @@ local function update_size(self)
|
||||
end
|
||||
|
||||
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in druid styles table
|
||||
-- or create your own style
|
||||
-- @table Style
|
||||
-- @tfield[opt=0] number FRICT Multiplier for free inertion
|
||||
-- @tfield[opt=0] number FRICT_HOLD Multiplier for inertion, while touching
|
||||
-- @tfield[opt=3] number INERT_THRESHOLD Scroll speed to stop inertion
|
||||
-- @tfield[opt=30] number INERT_SPEED Multiplier for inertion speed
|
||||
-- @tfield[opt=20] number POINTS_DEADZONE Speed to check points of interests in no_inertion mode
|
||||
-- @tfield[opt=0.35] number BACK_SPEED Scroll back returning lerp speed
|
||||
-- @tfield[opt=0.2] number ANIM_SPEED Scroll gui.animation speed for scroll_to function
|
||||
-- @tfield[opt=0] number EXTRA_STRETCH_SIZE extra size in pixels outside of scroll (stretch effect)
|
||||
-- @tfield[opt=false] bool SMALL_CONTENT_SCROLL If true, content node with size less than view node size can be scrolled
|
||||
function M.on_style_change(self, style)
|
||||
self.style = {}
|
||||
self.style.EXTRA_STRETCH_SIZE = style.EXTRA_STRETCH_SIZE or 0
|
||||
self.style.ANIM_SPEED = style.ANIM_SPEED or 0.2
|
||||
self.style.BACK_SPEED = style.BACK_SPEED or 0.35
|
||||
|
||||
self.style.FRICT = style.FRICT or 0
|
||||
self.style.FRICT_HOLD = style.FRICT_HOLD or 0
|
||||
|
||||
self.style.INERT_THRESHOLD = style.INERT_THRESHOLD or 3
|
||||
self.style.INERT_SPEED = style.INERT_SPEED or 30
|
||||
self.style.POINTS_DEADZONE = style.POINTS_DEADZONE or 20
|
||||
self.style.SMALL_CONTENT_SCROLL = style.SMALL_CONTENT_SCROLL or false
|
||||
|
||||
self._is_inert = not (self.style.FRICT == 0 or
|
||||
self.style.FRICT_HOLD == 0 or
|
||||
self.style.INERT_SPEED == 0)
|
||||
end
|
||||
|
||||
|
||||
--- Scroll constructor.
|
||||
-- @function scroll:init
|
||||
-- @tparam node view_node GUI view scroll node
|
||||
-- @tparam node content_node GUI content scroll node
|
||||
function M.init(self, view_node, content_node)
|
||||
self.druid = self:get_druid()
|
||||
|
||||
self.view_node = self:get_node(view_node)
|
||||
self.content_node = self:get_node(content_node)
|
||||
|
||||
self.position = gui.get_position(self.content_node)
|
||||
self.target_position = vmath.vector3(self.position)
|
||||
self.inertion = vmath.vector3(0)
|
||||
|
||||
self.drag = self.druid:new_drag(view_node, on_scroll_drag)
|
||||
self.drag.on_touch_start:subscribe(on_touch_start)
|
||||
self.drag.on_touch_end:subscribe(on_touch_end)
|
||||
|
||||
self.on_scroll = Event()
|
||||
self.on_scroll_to = Event()
|
||||
self.on_point_scroll = Event()
|
||||
|
||||
self.selected = nil
|
||||
self.is_animate = false
|
||||
|
||||
update_size(self)
|
||||
end
|
||||
|
||||
|
||||
function M.on_layout_change(self)
|
||||
gui.set_position(self.content_node, self.position)
|
||||
end
|
||||
|
||||
|
||||
function M.update(self, dt)
|
||||
if self.drag.is_drag then
|
||||
update_hand_scroll(self, dt)
|
||||
else
|
||||
update_free_scroll(self, dt)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Start scroll to target point.
|
||||
-- @function scroll:scroll_to
|
||||
-- @tparam point vector3 Target point
|
||||
-- @tparam[opt] bool is_instant Instant scroll flag
|
||||
-- @usage scroll:scroll_to(vmath.vector3(0, 50, 0))
|
||||
-- @usage scroll:scroll_to(vmath.vector3(0), true)
|
||||
function M.scroll_to(self, point, is_instant)
|
||||
local b = self.available_pos
|
||||
local target = vmath.vector3(-point.x, -point.y, 0)
|
||||
target.x = helper.clamp(target.x, b.x, b.z)
|
||||
target.y = helper.clamp(target.y, b.y, b.w)
|
||||
|
||||
cancel_animate(self)
|
||||
|
||||
self.is_animate = not is_instant
|
||||
|
||||
if is_instant then
|
||||
self.target_position = target
|
||||
set_scroll_position(self, target)
|
||||
else
|
||||
gui.animate(self.content_node, gui.PROP_POSITION, target, gui.EASING_OUTSINE, self.style.ANIM_SPEED, 0, function()
|
||||
self.is_animate = false
|
||||
self.target_position = target
|
||||
set_scroll_position(self, target)
|
||||
end)
|
||||
end
|
||||
|
||||
self.on_scroll_to:trigger(self:get_context(), target, is_instant)
|
||||
end
|
||||
|
||||
|
||||
--- Scroll to item in scroll by point index.
|
||||
-- @function scroll:scroll_to_index
|
||||
-- @tparam number index Point index
|
||||
-- @tparam[opt] bool skip_cb If true, skip the point callback
|
||||
function M.scroll_to_index(self, index, skip_cb)
|
||||
if not self.points then
|
||||
return
|
||||
end
|
||||
|
||||
index = helper.clamp(index, 1, #self.points)
|
||||
|
||||
if self.selected ~= index then
|
||||
self.selected = index
|
||||
|
||||
if not skip_cb then
|
||||
self.on_point_scroll:trigger(self:get_context(), index, self.points[index])
|
||||
end
|
||||
end
|
||||
|
||||
self:scroll_to(self.points[index])
|
||||
end
|
||||
|
||||
|
||||
--- Start scroll to target scroll percent
|
||||
-- @function scroll:scroll_to_percent
|
||||
-- @tparam point vector3 target percent
|
||||
-- @tparam[opt] bool is_instant instant scroll flag
|
||||
-- @usage scroll:scroll_to_percent(vmath.vector3(0.5, 0, 0))
|
||||
function M.scroll_to_percent(self, percent, is_instant)
|
||||
local border = self.available_pos
|
||||
|
||||
local pos = vmath.vector3(
|
||||
-helper.lerp(border.x, border.z, 1 - percent.x),
|
||||
-helper.lerp(border.w, border.y, 1 - percent.y),
|
||||
0
|
||||
)
|
||||
|
||||
M.scroll_to(self, pos, is_instant)
|
||||
end
|
||||
|
||||
|
||||
--- Return current scroll progress status.
|
||||
-- Values will be in [0..1] interval
|
||||
-- @function scroll:get_percent
|
||||
-- @treturn vector3 New vector with scroll progress values
|
||||
function M.get_percent(self)
|
||||
local x_perc = 1 - inverse_lerp(self.available_pos.x, self.available_pos.z, self.position.x)
|
||||
local y_perc = inverse_lerp(self.available_pos.w, self.available_pos.y, self.position.y)
|
||||
|
||||
return vmath.vector3(x_perc, y_perc, 0)
|
||||
end
|
||||
|
||||
|
||||
--- Set scroll content size.
|
||||
-- It will change content gui node size
|
||||
-- @function scroll:set_size
|
||||
-- @tparam vector3 size The new size for content node
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function M.set_size(self, size)
|
||||
gui.set_size(self.content_node, size)
|
||||
update_size(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Enable or disable scroll inert.
|
||||
-- If disabled, scroll through points (if exist)
|
||||
-- If no points, just simple drag without inertion
|
||||
-- @function scroll:set_inert
|
||||
-- @tparam bool state Inert scroll state
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function M.set_inert(self, state)
|
||||
self._is_inert = state
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Return if scroll have inertion.
|
||||
-- @function scroll:is_inert
|
||||
-- @treturn bool If scroll have inertion
|
||||
function M.is_inert(self)
|
||||
return self._is_inert
|
||||
end
|
||||
|
||||
|
||||
--- Set extra size for scroll stretching.
|
||||
-- Set 0 to disable stretching effect
|
||||
-- @function scroll:set_extra_stretch_size
|
||||
-- @tparam[opt=0] number stretch_size Size in pixels of additional scroll area
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function M.set_extra_stretch_size(self, stretch_size)
|
||||
self.style.EXTRA_STRETCH_SIZE = stretch_size or 0
|
||||
update_size(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Return vector of scroll size with width and height.
|
||||
-- @function scroll:get_scroll_size
|
||||
-- @treturn vector3 Available scroll size
|
||||
function M.get_scroll_size(self)
|
||||
return self.available_size
|
||||
end
|
||||
|
||||
|
||||
--- Set points of interest.
|
||||
-- Scroll will always centered on closer points
|
||||
-- @function scroll:set_points
|
||||
-- @tparam table points Array of vector3 points
|
||||
-- @treturn druid.scroll Current scroll instance
|
||||
function M.set_points(self, points)
|
||||
self.points = points
|
||||
|
||||
table.sort(self.points, function(a, b)
|
||||
return a.x > b.x or a.y < b.y
|
||||
end)
|
||||
|
||||
check_threshold(self)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Scroll
|
||||
|
350
druid/base/static_grid.lua
Normal file
350
druid/base/static_grid.lua
Normal file
@@ -0,0 +1,350 @@
|
||||
--- Component to handle placing components by row and columns.
|
||||
-- Grid can anchor your elements, get content size and other
|
||||
-- @module StaticGrid
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.static_grid
|
||||
|
||||
--- On item add callback(self, node, index)
|
||||
-- @tfield druid_event on_add_item
|
||||
|
||||
--- On item remove callback(self, index)
|
||||
-- @tfield druid_event on_remove_item
|
||||
|
||||
--- On item add or remove callback(self, index)
|
||||
-- @tfield druid_event on_change_items
|
||||
|
||||
--- On grid clear callback(self)
|
||||
-- @tfield druid_event on_clear
|
||||
|
||||
--- On update item positions callback(self)
|
||||
-- @tfield druid_event on_update_positions
|
||||
|
||||
--- Parent gui node
|
||||
-- @tfield node parent
|
||||
|
||||
--- List of all grid nodes
|
||||
-- @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 anchor
|
||||
-- @tfield vector3 anchor
|
||||
|
||||
--- 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 StaticGrid = component.create("static_grid", { const.ON_LAYOUT_CHANGE })
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @tparam StaticGrid self
|
||||
-- @tparam node parent The gui node parent, where items will be placed
|
||||
-- @tparam node element Element prefab. Need to get it size
|
||||
-- @tparam[opt=1] number in_row How many nodes in row can be placed
|
||||
function StaticGrid.init(self, parent, element, in_row)
|
||||
self.parent = self:get_node(parent)
|
||||
self.nodes = {}
|
||||
|
||||
self.pivot = helper.get_pivot_offset(gui.get_pivot(self.parent))
|
||||
self.anchor = vmath.vector3(0.5 + self.pivot.x, 0.5 - self.pivot.y, 0)
|
||||
|
||||
self.in_row = in_row or 1
|
||||
|
||||
self._prefab = self:get_node(element)
|
||||
self.node_size = gui.get_size(self._prefab)
|
||||
self.node_pivot = const.PIVOTS[gui.get_pivot(self._prefab)]
|
||||
|
||||
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
|
||||
|
||||
|
||||
local _temp_pos = vmath.vector3(0)
|
||||
--- Return pos for grid node index
|
||||
-- @tparam StaticGrid self
|
||||
-- @tparam number index The grid element index
|
||||
-- @treturn vector3 Node position
|
||||
function StaticGrid.get_pos(self, index)
|
||||
local row = math.ceil(index / self.in_row) - 1
|
||||
local col = (index - row * self.in_row) - 1
|
||||
|
||||
_temp_pos.x = col * self.node_size.x
|
||||
_temp_pos.y = -row * self.node_size.y
|
||||
_temp_pos.z = 0
|
||||
|
||||
return _temp_pos
|
||||
end
|
||||
|
||||
|
||||
--- Return index for grid pos
|
||||
-- @tparam StaticGrid self
|
||||
-- @tparam vector3 pos The node position in the grid
|
||||
-- @treturn number The node index
|
||||
function StaticGrid.get_index(self, pos)
|
||||
local col = pos.x / self.node_size.x + 1
|
||||
local row = -pos.y / self.node_size.y
|
||||
|
||||
col = helper.round(col)
|
||||
row = helper.round(row)
|
||||
|
||||
local index = col + (row * self.in_row)
|
||||
return math.ceil(index)
|
||||
end
|
||||
|
||||
|
||||
--- Return grid index by node
|
||||
-- @tparam StaticGrid self
|
||||
-- @tparam node node The gui node in the grid
|
||||
-- @treturn number The node index
|
||||
function StaticGrid.get_index_by_node(self, node)
|
||||
for index, grid_node in pairs(self.nodes) do
|
||||
if node == grid_node then
|
||||
return index
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
function StaticGrid.on_layout_change(self)
|
||||
self:_update(true)
|
||||
end
|
||||
|
||||
|
||||
--- Set grid anchor. Default anchor is equal to anchor of grid parent node
|
||||
-- @tparam StaticGrid self
|
||||
-- @tparam vector3 anchor Anchor
|
||||
function StaticGrid.set_anchor(self, anchor)
|
||||
self.anchor = anchor
|
||||
self:_update()
|
||||
end
|
||||
|
||||
|
||||
--- Add new item to the grid
|
||||
-- @tparam StaticGrid self
|
||||
-- @tparam node item Gui node
|
||||
-- @tparam[opt] number index The item position. By default add as last item
|
||||
function StaticGrid.add(self, item, index)
|
||||
index = index or ((self.last_index or 0) + 1)
|
||||
|
||||
if self.nodes[index] then
|
||||
-- Move nodes to right
|
||||
for i = self.last_index, index, -1 do
|
||||
self.nodes[i + 1] = self.nodes[i]
|
||||
end
|
||||
end
|
||||
|
||||
self.nodes[index] = item
|
||||
|
||||
gui.set_parent(item, self.parent)
|
||||
|
||||
-- Add new item instantly in new pos. Break update function for correct positioning
|
||||
self:_update_indexes()
|
||||
self:_update_borders()
|
||||
|
||||
gui.set_position(item, self:get_pos(index) + self:_get_zero_offset())
|
||||
|
||||
self:_update_pos()
|
||||
|
||||
self.on_add_item:trigger(self:get_context(), item, 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 StaticGrid self
|
||||
-- @tparam number index The grid node index to remove
|
||||
-- @tparam bool is_shift_nodes If true, will shift nodes left after index
|
||||
-- @treturn Node The deleted gui node from grid
|
||||
function StaticGrid.remove(self, index, is_shift_nodes)
|
||||
assert(self.nodes[index], "No grid item at given index " .. index)
|
||||
|
||||
local remove_node = self.nodes[index]
|
||||
self.nodes[index] = nil
|
||||
|
||||
if is_shift_nodes then
|
||||
for i = index, self.last_index do
|
||||
self.nodes[i] = self.nodes[i + 1]
|
||||
end
|
||||
end
|
||||
|
||||
self:_update()
|
||||
|
||||
self.on_remove_item:trigger(self:get_context(), index)
|
||||
self.on_change_items:trigger(self:get_context(), index)
|
||||
|
||||
return remove_node
|
||||
end
|
||||
|
||||
|
||||
--- Return grid content size
|
||||
-- @tparam StaticGrid self
|
||||
-- @treturn vector3 The grid content size
|
||||
function StaticGrid.get_size(self)
|
||||
return vmath.vector3(
|
||||
self.border.z - self.border.x,
|
||||
self.border.y - self.border.w,
|
||||
0)
|
||||
end
|
||||
|
||||
|
||||
--- Return array of all node positions
|
||||
-- @tparam StaticGrid self
|
||||
-- @treturn vector3[] All grid node positions
|
||||
function StaticGrid.get_all_pos(self)
|
||||
local result = {}
|
||||
for i, node in pairs(self.nodes) do
|
||||
table.insert(result, gui.get_position(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 StaticGrid self
|
||||
-- @tparam function callback Function on node set position
|
||||
-- @treturn druid.static_grid Current grid instance
|
||||
function StaticGrid.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 static_grid.nodes array before grid:clear
|
||||
-- @tparam StaticGrid self
|
||||
-- @treturn druid.static_grid Current grid instance
|
||||
function StaticGrid.clear(self)
|
||||
self.border.x = 0
|
||||
self.border.y = 0
|
||||
self.border.w = 0
|
||||
self.border.z = 0
|
||||
|
||||
self.nodes = {}
|
||||
self:_update()
|
||||
|
||||
self.on_clear:trigger(self:get_context())
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Return elements offset for correct posing nodes. Correct posing at
|
||||
-- parent pivot node (0:0) with adjusting of node sizes and anchoring
|
||||
-- @tparam StaticGrid self
|
||||
-- @treturn vector3 The offset vector
|
||||
-- @local
|
||||
function StaticGrid._get_zero_offset(self)
|
||||
-- zero offset: center pos - border size * anchor
|
||||
return vmath.vector3(
|
||||
-((self.border.x + self.border.z)/2 + (self.border.z - self.border.x) * self.pivot.x),
|
||||
-((self.border.y + self.border.w)/2 + (self.border.y - self.border.w) * self.pivot.y),
|
||||
0
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
--- Update grid inner state
|
||||
-- @tparam StaticGrid self
|
||||
-- @tparam bool is_instant If true, node position update instantly, otherwise with set_position_function callback
|
||||
-- @local
|
||||
function StaticGrid._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 StaticGrid self
|
||||
-- @local
|
||||
function StaticGrid._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 StaticGrid self
|
||||
-- @local
|
||||
function StaticGrid._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)
|
||||
|
||||
local size = self.node_size
|
||||
local pivot = self.node_pivot
|
||||
for index, node in pairs(self.nodes) do
|
||||
local pos = self:get_pos(index)
|
||||
|
||||
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 StaticGrid self
|
||||
-- @tparam bool is_instant If true, node position update instantly, otherwise with set_position_function callback
|
||||
-- @local
|
||||
function StaticGrid._update_pos(self, is_instant)
|
||||
local zero_offset = self:_get_zero_offset()
|
||||
|
||||
for i, node in pairs(self.nodes) do
|
||||
local pos = self:get_pos(i)
|
||||
pos.x = pos.x + zero_offset.x
|
||||
pos.y = pos.y + zero_offset.y
|
||||
|
||||
if is_instant then
|
||||
gui.set_position(node, pos)
|
||||
else
|
||||
self._set_position_function(node, pos)
|
||||
end
|
||||
end
|
||||
|
||||
self.on_update_positions:trigger(self:get_context())
|
||||
end
|
||||
|
||||
|
||||
return StaticGrid
|
@@ -1,23 +1,26 @@
|
||||
--- Component to handle swipe gestures on node.
|
||||
-- Swipe will be triggered, if swipe was started and
|
||||
-- ended on one node
|
||||
-- @module druid.swipe
|
||||
-- @module Swipe
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.swipe
|
||||
|
||||
--- Components fields
|
||||
-- @table Fields
|
||||
-- @tparam node node Swipe node
|
||||
-- @tparam[opt] node click_zone Restriction zone
|
||||
--- Swipe node
|
||||
-- @tparam node node
|
||||
|
||||
--- Restriction zone
|
||||
-- @tparam[opt] node click_zone
|
||||
|
||||
--- Trigger on swipe event(self, swipe_side, dist, delta_time
|
||||
-- @tfield druid_event on_swipe)
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_swipe Trigger on swipe event
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("swipe", { const.ON_INPUT })
|
||||
local Swipe = component.create("swipe", { const.ON_INPUT })
|
||||
|
||||
|
||||
local function start_swipe(self, action)
|
||||
@@ -65,11 +68,11 @@ end
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in druid styles table
|
||||
-- or create your own style
|
||||
-- @table Style
|
||||
-- @table style
|
||||
-- @tfield[opt=0.4] number SWIPE_TIME Maximum time for swipe trigger
|
||||
-- @tfield[opt=50] number SWIPE_THRESHOLD Minimum distance for swipe trigger
|
||||
-- @tfield[opt=false] bool SWIPE_TRIGGER_ON_MOVE If true, trigger on swipe moving, not only release action
|
||||
function M.on_style_change(self, style)
|
||||
function Swipe.on_style_change(self, style)
|
||||
self.style = {}
|
||||
self.style.SWIPE_TIME = style.SWIPE_TIME or 0.4
|
||||
self.style.SWIPE_THRESHOLD = style.SWIPE_THRESHOLD or 50
|
||||
@@ -78,10 +81,10 @@ end
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function swipe:init
|
||||
-- @tparam Swipe self
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function on_swipe_callback Swipe callback for on_swipe_end event
|
||||
function M.init(self, node, on_swipe_callback)
|
||||
function Swipe.init(self, node, on_swipe_callback)
|
||||
self._trigger_on_move = self.style.SWIPE_TRIGGER_ON_MOVE
|
||||
self.node = self:get_node(node)
|
||||
|
||||
@@ -93,7 +96,7 @@ function M.init(self, node, on_swipe_callback)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input(self, action_id, action)
|
||||
function Swipe.on_input(self, action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH then
|
||||
return false
|
||||
end
|
||||
@@ -126,18 +129,18 @@ function M.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input_interrupt(self)
|
||||
function Swipe.on_input_interrupt(self)
|
||||
reset_swipe(self)
|
||||
end
|
||||
|
||||
|
||||
--- Strict swipe click area. Useful for
|
||||
-- restrict events outside stencil node
|
||||
-- @function swipe:set_click_zone
|
||||
-- @tparam Swipe self
|
||||
-- @tparam node zone Gui node
|
||||
function M.set_click_zone(self, zone)
|
||||
function Swipe.set_click_zone(self, zone)
|
||||
self.click_zone = self:get_node(zone)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Swipe
|
||||
|
@@ -1,30 +1,49 @@
|
||||
--- Component to handle all GUI texts.
|
||||
-- Druid text can adjust itself for text node size
|
||||
-- Text will never will be outside of his text size (even multiline)
|
||||
-- @module druid.text
|
||||
-- @module Text
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.text
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_set_text On set text callback
|
||||
-- @tfield druid_event on_update_text_scale On adjust text size callback
|
||||
-- @tfield druid_event on_set_pivot On change pivot callback
|
||||
--- On set text callback(self, text)
|
||||
-- @tfield druid_event on_set_text
|
||||
|
||||
--- On adjust text size callback(self, new_scale)
|
||||
-- @tfield druid_event on_update_text_scale
|
||||
|
||||
--- On change pivot callback(self, pivot)
|
||||
-- @tfield druid_event on_set_pivot
|
||||
|
||||
--- Text node
|
||||
-- @tfield node node
|
||||
|
||||
--- Current text position
|
||||
-- @tfield vector3 pos
|
||||
|
||||
--- Initial text node scale
|
||||
-- @tfield vector3 start_scale
|
||||
|
||||
--- Current text node scale
|
||||
-- @tfield vector3 scale
|
||||
|
||||
--- Initial text node size
|
||||
-- @tfield vector3 start_size
|
||||
|
||||
--- Current text node available are
|
||||
-- @tfield vector3 text_area
|
||||
|
||||
--- Current text size adjust settings
|
||||
-- @tfield bool is_no_adjust
|
||||
|
||||
--- Current text color
|
||||
-- @tfield vector3 color
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield node node Text node
|
||||
-- @tfield vector3 pos Current text position
|
||||
-- @tfield vector3 start_scale Initial text node scale
|
||||
-- @tfield vector3 scale Current text node scale
|
||||
-- @tfield vector3 start_size Initial text node size
|
||||
-- @tfield vector3 text_area Current text node available are
|
||||
-- @tfield bool is_no_adjust Current text size adjust settings
|
||||
-- @tfield vector3 color Current text color
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("text", { const.ON_LAYOUT_CHANGE })
|
||||
local Text = component.create("text", { const.ON_LAYOUT_CHANGE })
|
||||
|
||||
|
||||
local function update_text_size(self)
|
||||
@@ -77,11 +96,11 @@ end
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function text:init
|
||||
-- @tparam Text self
|
||||
-- @tparam node node Gui text node
|
||||
-- @tparam[opt] string value Initial text. Default value is node text from GUI scene.
|
||||
-- @tparam[opt] bool no_adjust If true, text will be not auto-adjust size
|
||||
function M.init(self, node, value, no_adjust)
|
||||
function Text.init(self, node, value, no_adjust)
|
||||
self.node = self:get_node(node)
|
||||
self.pos = gui.get_position(self.node)
|
||||
|
||||
@@ -107,15 +126,15 @@ function M.init(self, node, value, no_adjust)
|
||||
end
|
||||
|
||||
|
||||
function M.on_layout_change(self)
|
||||
function Text.on_layout_change(self)
|
||||
self:set_to(self.last_value)
|
||||
end
|
||||
|
||||
|
||||
--- Calculate text width with font with respect to trailing space
|
||||
-- @function text:get_text_width
|
||||
-- @tparam Text self
|
||||
-- @tparam[opt] string text
|
||||
function M.get_text_width(self, text)
|
||||
function Text.get_text_width(self, text)
|
||||
text = text or self.last_value
|
||||
local font = gui.get_font(self.node)
|
||||
local scale = gui.get_scale(self.node)
|
||||
@@ -134,9 +153,9 @@ end
|
||||
|
||||
|
||||
--- Set text to text field
|
||||
-- @function text:set_to
|
||||
-- @tparam Text self
|
||||
-- @tparam string set_to Text for node
|
||||
function M.set_to(self, set_to)
|
||||
function Text.set_to(self, set_to)
|
||||
self.last_value = set_to
|
||||
gui.set_text(self.node, set_to)
|
||||
|
||||
@@ -149,27 +168,27 @@ end
|
||||
|
||||
|
||||
--- Set color
|
||||
-- @function text:set_color
|
||||
-- @tparam Text self
|
||||
-- @tparam vector4 color Color for node
|
||||
function M.set_color(self, color)
|
||||
function Text.set_color(self, color)
|
||||
self.color = color
|
||||
gui.set_color(self.node, color)
|
||||
end
|
||||
|
||||
|
||||
--- Set alpha
|
||||
-- @function text:set_alpha
|
||||
-- @tparam Text self
|
||||
-- @tparam number alpha Alpha for node
|
||||
function M.set_alpha(self, alpha)
|
||||
function Text.set_alpha(self, alpha)
|
||||
self.color.w = alpha
|
||||
gui.set_color(self.node, self.color)
|
||||
end
|
||||
|
||||
|
||||
--- Set scale
|
||||
-- @function text:set_scale
|
||||
-- @tparam Text self
|
||||
-- @tparam vector3 scale Scale for node
|
||||
function M.set_scale(self, scale)
|
||||
function Text.set_scale(self, scale)
|
||||
self.last_scale = scale
|
||||
gui.set_scale(self.node, scale)
|
||||
end
|
||||
@@ -177,9 +196,9 @@ end
|
||||
|
||||
--- Set text pivot. Text will re-anchor inside
|
||||
-- his text area
|
||||
-- @function text:set_pivot
|
||||
-- @tparam Text self
|
||||
-- @tparam gui.pivot pivot Gui pivot constant
|
||||
function M.set_pivot(self, pivot)
|
||||
function Text.set_pivot(self, pivot)
|
||||
local prev_pivot = gui.get_pivot(self.node)
|
||||
local prev_offset = const.PIVOTS[prev_pivot]
|
||||
|
||||
@@ -200,11 +219,11 @@ end
|
||||
|
||||
|
||||
--- Return true, if text with line break
|
||||
-- @function text:is_multiline
|
||||
-- @tparam Text self
|
||||
-- @treturn bool Is text node with line break
|
||||
function M.is_multiline(self)
|
||||
function Text.is_multiline(self)
|
||||
return gui.get_line_break(self.node)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Text
|
||||
|
@@ -1,20 +1,20 @@
|
||||
--- Basic class for all Druid components.
|
||||
-- To create you component, use `component.create`
|
||||
-- @module component
|
||||
-- @module BaseComponent
|
||||
-- @alias druid.base_component
|
||||
|
||||
local const = require("druid.const")
|
||||
local class = require("druid.system.middleclass")
|
||||
|
||||
-- @classmod Component
|
||||
local Component = class("druid.component")
|
||||
local BaseComponent = class("druid.component")
|
||||
|
||||
|
||||
--- Set current component style table.
|
||||
-- Invoke `on_style_change` on component, if exist. Component should handle
|
||||
-- Invoke `on_style_change` on component, if exist. BaseComponent should handle
|
||||
-- their style changing and store all style params
|
||||
-- @function component:set_style
|
||||
-- @tparam table style Druid style module
|
||||
function Component.set_style(self, druid_style)
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam table druid_style Druid style module
|
||||
function BaseComponent.set_style(self, druid_style)
|
||||
self._meta.style = druid_style or const.EMPTY_TABLE
|
||||
local component_style = self._meta.style[self._component.name] or const.EMPTY_TABLE
|
||||
|
||||
@@ -24,72 +24,40 @@ function Component.set_style(self, druid_style)
|
||||
end
|
||||
|
||||
|
||||
--- Get current component template name
|
||||
-- @function component:get_template
|
||||
-- @treturn string Component template name
|
||||
function Component.get_template(self)
|
||||
return self._meta.template
|
||||
end
|
||||
|
||||
|
||||
--- Set current component template name
|
||||
-- @function component:set_template
|
||||
-- @tparam string template Component template name
|
||||
function Component.set_template(self, template)
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam string template BaseComponent template name
|
||||
function BaseComponent.set_template(self, template)
|
||||
self._meta.template = template
|
||||
end
|
||||
|
||||
|
||||
--- Get current component nodes
|
||||
-- @function component:get_nodes
|
||||
-- @treturn table Component nodes table
|
||||
function Component.get_nodes(self)
|
||||
return self._meta.nodes
|
||||
end
|
||||
|
||||
|
||||
--- Set current component nodes
|
||||
-- @function component:set_nodes
|
||||
-- @tparam table nodes Component nodes table
|
||||
function Component.set_nodes(self, nodes)
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam table nodes BaseComponent nodes table
|
||||
function BaseComponent.set_nodes(self, nodes)
|
||||
self._meta.nodes = nodes
|
||||
end
|
||||
|
||||
|
||||
--- Get current component context
|
||||
-- @function component:get_context
|
||||
-- @treturn table Component context
|
||||
function Component.get_context(self, context)
|
||||
-- @tparam BaseComponent self
|
||||
-- @treturn table BaseComponent context
|
||||
function BaseComponent.get_context(self)
|
||||
return self._meta.context
|
||||
end
|
||||
|
||||
|
||||
--- Set current component context
|
||||
-- @function component:set_context
|
||||
-- @tparam table context Druid context. Usually it is self of script
|
||||
function Component.set_context(self, context)
|
||||
self._meta.context = context
|
||||
end
|
||||
|
||||
|
||||
--- Get current component interests
|
||||
-- @function component:get_interests
|
||||
-- @treturn table List of component interests
|
||||
function Component.get_interests(self)
|
||||
return self._component.interest
|
||||
end
|
||||
|
||||
|
||||
--- Increase input priority in current input stack
|
||||
-- @function component:increase_input_priority
|
||||
function Component.increase_input_priority(self)
|
||||
-- @tparam BaseComponent self
|
||||
function BaseComponent.increase_input_priority(self)
|
||||
self._meta.increased_input_priority = true
|
||||
end
|
||||
|
||||
|
||||
--- Reset input priority in current input stack
|
||||
-- @function component:reset_input_priority
|
||||
function Component.reset_input_priority(self)
|
||||
-- @tparam BaseComponent self
|
||||
function BaseComponent.reset_input_priority(self)
|
||||
self._meta.increased_input_priority = false
|
||||
end
|
||||
|
||||
@@ -98,12 +66,12 @@ end
|
||||
-- If component has nodes, node_or_name should be string
|
||||
-- It auto pick node by template name or from nodes by clone_tree
|
||||
-- if they was setup via component:set_nodes, component:set_template
|
||||
-- @function component:get_node
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam string|node node_or_name Node name or node itself
|
||||
-- @treturn node Gui node
|
||||
function Component.get_node(self, node_or_name)
|
||||
local template_name = self:get_template() or const.EMPTY_STRING
|
||||
local nodes = self:get_nodes()
|
||||
function BaseComponent.get_node(self, node_or_name)
|
||||
local template_name = self:__get_template() or const.EMPTY_STRING
|
||||
local nodes = self:__get_nodes()
|
||||
|
||||
if template_name ~= const.EMPTY_STRING then
|
||||
template_name = template_name .. "/"
|
||||
@@ -126,60 +94,89 @@ end
|
||||
|
||||
--- Return druid with context of calling component.
|
||||
-- Use it to create component inside of other components.
|
||||
-- @function component:get_druid
|
||||
-- @tparam BaseComponent self
|
||||
-- @treturn Druid Druid instance with component context
|
||||
function Component.get_druid(self)
|
||||
function BaseComponent.get_druid(self)
|
||||
local context = { _context = self }
|
||||
return setmetatable(context, { __index = self._meta.druid })
|
||||
end
|
||||
|
||||
|
||||
--- Return true, if current component is child of another component
|
||||
-- @function component:is_child_of
|
||||
-- @treturn bool True, if current component is child of another
|
||||
function Component.is_child_of(self, component)
|
||||
return self:get_context() == component
|
||||
end
|
||||
|
||||
|
||||
--- Return component name
|
||||
-- @function component:get_name
|
||||
-- @tparam BaseComponent self
|
||||
-- @treturn string The component name
|
||||
function Component.get_name(self)
|
||||
function BaseComponent.get_name(self)
|
||||
return self._component.name
|
||||
end
|
||||
|
||||
|
||||
--- Set component input state. By default it enabled
|
||||
-- You can disable any input of component by this function
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam bool state The component input state
|
||||
-- @treturn BaseComponent BaseComponent itself
|
||||
function BaseComponent.set_input_enabled(self, state)
|
||||
self._meta.input_enabled = state
|
||||
|
||||
for index = 1, #self._meta.children do
|
||||
self._meta.children[index]:set_input_enabled(state)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Return the parent for current component
|
||||
-- @tparam BaseComponent self
|
||||
-- @treturn druid.base_component|nil The druid component instance or nil
|
||||
function BaseComponent.get_parent_component(self)
|
||||
local context = self:get_context()
|
||||
|
||||
if context.isInstanceOf and context:isInstanceOf(BaseComponent) then
|
||||
return context
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Setup component context and his style table
|
||||
-- @function component:setup_component
|
||||
-- @tparam druid_instance table The parent druid instance
|
||||
-- @tparam context table Druid context. Usually it is self of script
|
||||
-- @tparam style table Druid style module
|
||||
-- @treturn Component Component itself
|
||||
function Component.setup_component(self, druid_instance, context, style)
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam table druid_instance The parent druid instance
|
||||
-- @tparam table context Druid context. Usually it is self of script
|
||||
-- @tparam table style Druid style module
|
||||
-- @treturn component BaseComponent itself
|
||||
function BaseComponent.setup_component(self, druid_instance, context, style)
|
||||
self._meta = {
|
||||
template = nil,
|
||||
context = nil,
|
||||
nodes = nil,
|
||||
style = nil,
|
||||
druid = druid_instance,
|
||||
increased_input_priority = false
|
||||
increased_input_priority = false,
|
||||
input_enabled = true,
|
||||
children = {}
|
||||
}
|
||||
|
||||
self:set_context(context)
|
||||
self:__set_context(context)
|
||||
self:set_style(style)
|
||||
|
||||
local parent = self:get_parent_component()
|
||||
if parent then
|
||||
parent:__add_children(self)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Basic constructor of component. It will call automaticaly
|
||||
-- by `Component.static.create`
|
||||
-- @function component:initialize
|
||||
-- @tparam string name Component name
|
||||
-- by `BaseComponent.static.create`
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam string name BaseComponent name
|
||||
-- @tparam[opt={}] table interest List of component's interest
|
||||
-- @local
|
||||
function Component.initialize(self, name, interest)
|
||||
function BaseComponent.initialize(self, name, interest)
|
||||
interest = interest or {}
|
||||
|
||||
self._component = {
|
||||
@@ -189,21 +186,84 @@ function Component.initialize(self, name, interest)
|
||||
end
|
||||
|
||||
|
||||
function BaseComponent.__tostring(self)
|
||||
return self._component.name
|
||||
end
|
||||
|
||||
|
||||
--- Set current component context
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam table context Druid context. Usually it is self of script
|
||||
-- @local
|
||||
function BaseComponent.__set_context(self, context)
|
||||
self._meta.context = context
|
||||
end
|
||||
|
||||
|
||||
--- Get current component interests
|
||||
-- @tparam BaseComponent self
|
||||
-- @treturn table List of component interests
|
||||
-- @local
|
||||
function BaseComponent.__get_interests(self)
|
||||
return self._component.interest
|
||||
end
|
||||
|
||||
|
||||
--- Get current component template name
|
||||
-- @tparam BaseComponent self
|
||||
-- @treturn string BaseComponent template name
|
||||
-- @local
|
||||
function BaseComponent.__get_template(self)
|
||||
return self._meta.template
|
||||
end
|
||||
|
||||
|
||||
--- Get current component nodes
|
||||
-- @tparam BaseComponent self
|
||||
-- @treturn table BaseComponent nodes table
|
||||
-- @local
|
||||
function BaseComponent.__get_nodes(self)
|
||||
return self._meta.nodes
|
||||
end
|
||||
|
||||
|
||||
--- Add child to component children list
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam component children The druid component instance
|
||||
-- @local
|
||||
function BaseComponent.__add_children(self, children)
|
||||
table.insert(self._meta.children, children)
|
||||
end
|
||||
|
||||
|
||||
--- Remove child from component children list
|
||||
-- @tparam BaseComponent self
|
||||
-- @tparam component children The druid component instance
|
||||
-- @local
|
||||
function BaseComponent.__remove_children(self, children)
|
||||
for i = #self._meta.children, 1, -1 do
|
||||
if self._meta.children[i] == children then
|
||||
table.remove(self._meta.children, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Create new component. It will inheritance from basic
|
||||
-- druid component.
|
||||
-- @function Component.create
|
||||
-- @tparam string name Component name
|
||||
-- @tparam string name BaseComponent name
|
||||
-- @tparam[opt={}] table interest List of component's interest
|
||||
function Component.static.create(name, interest)
|
||||
-- @local
|
||||
function BaseComponent.static.create(name, interest)
|
||||
-- Yea, inheritance here
|
||||
local new_class = class(name, Component)
|
||||
local new_class = class(name, BaseComponent)
|
||||
|
||||
new_class.initialize = function(self)
|
||||
Component.initialize(self, name, interest)
|
||||
BaseComponent.initialize(self, name, interest)
|
||||
end
|
||||
|
||||
return new_class
|
||||
end
|
||||
|
||||
|
||||
return Component
|
||||
return BaseComponent
|
||||
|
@@ -1,6 +1,7 @@
|
||||
--- Druid constants
|
||||
-- @local
|
||||
-- @module const
|
||||
-- @module DruidConst
|
||||
-- @alias druid_const
|
||||
|
||||
local M = {}
|
||||
|
||||
@@ -102,9 +103,8 @@ M.SWIPE = {
|
||||
}
|
||||
|
||||
|
||||
M.GRID_MODE = {
|
||||
STATIC = "static",
|
||||
DYNAMIC = "dynamic",
|
||||
M.ERRORS = {
|
||||
GRID_DYNAMIC_ANCHOR = "The pivot of dynamic grid node should be West, East, South or North"
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,16 +1,16 @@
|
||||
--- Lua event small library
|
||||
-- @module druid_event
|
||||
-- @module DruidEvent
|
||||
-- @alias druid_event
|
||||
|
||||
local class = require("druid.system.middleclass")
|
||||
|
||||
-- @class DruidEvent
|
||||
local M = class("druid.event")
|
||||
local DruidEvent = class("druid.event")
|
||||
|
||||
|
||||
--- Event constructur
|
||||
-- @function Event
|
||||
-- @tparam DruidEvent self
|
||||
-- @tparam function initial_callback Subscribe the callback on new event, if callback exist
|
||||
function M.initialize(self, initial_callback)
|
||||
function DruidEvent.initialize(self, initial_callback)
|
||||
self._callbacks = {}
|
||||
|
||||
if initial_callback then
|
||||
@@ -20,20 +20,22 @@ end
|
||||
|
||||
|
||||
--- Subscribe callback on event
|
||||
-- @function event:subscribe
|
||||
-- @tparam DruidEvent self
|
||||
-- @tparam function callback Callback itself
|
||||
function M.subscribe(self, callback)
|
||||
function DruidEvent.subscribe(self, callback)
|
||||
assert(type(self) == "table", "You should subscribe to event with : syntax")
|
||||
assert(type(callback) == "function", "Callback should be function")
|
||||
|
||||
table.insert(self._callbacks, callback)
|
||||
|
||||
return callback
|
||||
end
|
||||
|
||||
|
||||
--- Unsubscribe callback on event
|
||||
-- @function event:unsubscribe
|
||||
-- @tparam DruidEvent self
|
||||
-- @tparam function callback Callback itself
|
||||
function M.unsubscribe(self, callback)
|
||||
function DruidEvent.unsubscribe(self, callback)
|
||||
for i = 1, #self._callbacks do
|
||||
if self._callbacks[i] == callback then
|
||||
table.remove(self._callbacks, i)
|
||||
@@ -44,28 +46,28 @@ end
|
||||
|
||||
|
||||
--- Return true, if event have at lease one handler
|
||||
-- @function event:is_exist
|
||||
-- @tparam DruidEvent self
|
||||
-- @treturn bool True if event have handlers
|
||||
function M.is_exist(self)
|
||||
function DruidEvent.is_exist(self)
|
||||
return #self._callbacks > 0
|
||||
end
|
||||
|
||||
|
||||
--- Clear the all event handlers
|
||||
-- @function event:clear
|
||||
function M.clear(self)
|
||||
-- @tparam DruidEvent self
|
||||
function DruidEvent.clear(self)
|
||||
self._callbacks = {}
|
||||
end
|
||||
|
||||
|
||||
--- Trigger the event and call all subscribed callbacks
|
||||
-- @function event:trigger
|
||||
-- @param ... All event params
|
||||
function M.trigger(self, ...)
|
||||
-- @tparam DruidEvent self
|
||||
-- @tparam any ... All event params
|
||||
function DruidEvent.trigger(self, ...)
|
||||
for i = 1, #self._callbacks do
|
||||
self._callbacks[i](...)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return DruidEvent
|
||||
|
@@ -1,34 +1,39 @@
|
||||
--- Druid checkbox component
|
||||
-- @module druid.checkbox
|
||||
-- @module Checkbox
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.checkbox
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_change_state On change state callback
|
||||
--- On change state callback(self, state)
|
||||
-- @tfield druid_event on_change_state
|
||||
|
||||
--- Visual node
|
||||
-- @tfield node node
|
||||
|
||||
--- Button trigger node
|
||||
-- @tfield[opt=node] node click_node
|
||||
|
||||
--- Button component from click_node
|
||||
-- @tfield Button button
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield node node Visual node
|
||||
-- @tfield[opt=node] node click_node Button trigger node
|
||||
-- @tfield druid.button button Button component from click_node
|
||||
|
||||
local const = require("druid.const")
|
||||
local Event = require("druid.event")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("checkbox", { const.ON_LAYOUT_CHANGE })
|
||||
local Checkbox = component.create("checkbox", { const.ON_LAYOUT_CHANGE })
|
||||
|
||||
|
||||
local function on_click(self)
|
||||
M.set_state(self, not self.state)
|
||||
self:set_state(not self.state)
|
||||
end
|
||||
|
||||
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in druid styles table
|
||||
-- or create your own style
|
||||
-- @table Style
|
||||
-- @table style
|
||||
-- @tfield function on_change_state (self, node, state)
|
||||
function M.on_style_change(self, style)
|
||||
function Checkbox.on_style_change(self, style)
|
||||
self.style = {}
|
||||
|
||||
self.style.on_change_state = style.on_change_state or function(_, node, state)
|
||||
@@ -38,32 +43,32 @@ end
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function checkbox:init
|
||||
-- @tparam Checkbox self
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function callback Checkbox callback
|
||||
-- @tparam[opt=node] node click node Trigger node, by default equals to node
|
||||
function M.init(self, node, callback, click_node)
|
||||
-- @tparam[opt=node] node click_node Trigger node, by default equals to node
|
||||
function Checkbox.init(self, node, callback, click_node)
|
||||
self.druid = self:get_druid()
|
||||
self.node = self:get_node(node)
|
||||
self.click_node = self:get_node(click_node)
|
||||
|
||||
self.button = self.druid:new_button(self.click_node or self.node, on_click)
|
||||
M.set_state(self, false, true)
|
||||
self:set_state(false, true)
|
||||
|
||||
self.on_change_state = Event(callback)
|
||||
end
|
||||
|
||||
|
||||
function M.on_layout_change(self)
|
||||
function Checkbox.on_layout_change(self)
|
||||
self:set_state(self.state, true)
|
||||
end
|
||||
|
||||
|
||||
--- Set checkbox state
|
||||
-- @function checkbox:set_state
|
||||
-- @tparam Checkbox self
|
||||
-- @tparam bool state Checkbox state
|
||||
-- @tparam bool is_silent Don't trigger on_change_state if true
|
||||
function M.set_state(self, state, is_silent)
|
||||
function Checkbox.set_state(self, state, is_silent)
|
||||
self.state = state
|
||||
self.style.on_change_state(self, self.node, state)
|
||||
|
||||
@@ -74,11 +79,11 @@ end
|
||||
|
||||
|
||||
--- Return checkbox state
|
||||
-- @function checkbox:get_state
|
||||
-- @tparam Checkbox self
|
||||
-- @treturn bool Checkbox state
|
||||
function M.get_state(self)
|
||||
function Checkbox.get_state(self)
|
||||
return self.state
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Checkbox
|
@@ -1,26 +1,27 @@
|
||||
--- Checkbox group module
|
||||
-- @module druid.checkbox_group
|
||||
-- @module CheckboxGroup
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.checkbox_group
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_checkbox_click On any checkbox click
|
||||
--- On any checkbox click callback(self, index)
|
||||
-- @tfield druid_event on_checkbox_click
|
||||
|
||||
--- Array of checkbox components
|
||||
-- @tfield table checkboxes
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield table checkboxes Array of checkbox components
|
||||
|
||||
local Event = require("druid.event")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("checkbox_group")
|
||||
local CheckboxGroup = component.create("checkbox_group")
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function checkbox_group:init
|
||||
-- @tparam node[] node Array of gui node
|
||||
-- @tparam CheckboxGroup self
|
||||
-- @tparam node[] nodes Array of gui node
|
||||
-- @tparam function callback Checkbox callback
|
||||
-- @tparam[opt=node] node[] click node Array of trigger nodes, by default equals to nodes
|
||||
function M.init(self, nodes, callback, click_nodes)
|
||||
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
|
||||
function CheckboxGroup.init(self, nodes, callback, click_nodes)
|
||||
self.druid = self:get_druid()
|
||||
self.checkboxes = {}
|
||||
|
||||
@@ -38,9 +39,9 @@ end
|
||||
|
||||
|
||||
--- Set checkbox group state
|
||||
-- @function checkbox_group:set_state
|
||||
-- @tparam CheckboxGroup self
|
||||
-- @tparam bool[] indexes Array of checkbox state
|
||||
function M.set_state(self, indexes)
|
||||
function CheckboxGroup.set_state(self, indexes)
|
||||
for i = 1, #indexes do
|
||||
if self.checkboxes[i] then
|
||||
self.checkboxes[i]:set_state(indexes[i], true)
|
||||
@@ -50,9 +51,9 @@ end
|
||||
|
||||
|
||||
--- Return checkbox group state
|
||||
-- @function checkbox_group:get_state
|
||||
-- @tparam CheckboxGroup self
|
||||
-- @treturn bool[] Array if checkboxes state
|
||||
function M.get_state(self)
|
||||
function CheckboxGroup.get_state(self)
|
||||
local result = {}
|
||||
|
||||
for i = 1, #self.checkboxes do
|
||||
@@ -63,4 +64,4 @@ function M.get_state(self)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return CheckboxGroup
|
@@ -1,64 +1,67 @@
|
||||
--- Druid component template
|
||||
-- @module druid.component
|
||||
-- @local
|
||||
local const = require("druid.const")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("my_component_name", { const.ON_UPDATE })
|
||||
local Component = component.create("my_component_name", { const.ON_UPDATE })
|
||||
|
||||
|
||||
-- Component constructor
|
||||
function M.init(self, ...)
|
||||
function Component:init(...)
|
||||
end
|
||||
|
||||
|
||||
-- Call only if exist interest: const.ON_UPDATE
|
||||
function M.update(self, dt)
|
||||
function Component:update(dt)
|
||||
end
|
||||
|
||||
|
||||
-- Call only if exist interest: const.ON_INPUT or const.ON_INPUT_HIGH
|
||||
function M.on_input(self, action_id, action)
|
||||
function Component:on_input(action_id, action)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- Call on component creation and on component:set_style() function
|
||||
function M.on_style_change(self, style)
|
||||
function Component:on_style_change(style)
|
||||
end
|
||||
|
||||
|
||||
-- Call only if exist interest: const.ON_MESSAGE
|
||||
function M.on_message(self, message_id, message, sender)
|
||||
function Component:on_message(message_id, message, sender)
|
||||
end
|
||||
|
||||
|
||||
-- Call only if component with ON_LANGUAGE_CHANGE interest
|
||||
function M.on_language_change(self)
|
||||
function Component:on_language_change()
|
||||
end
|
||||
|
||||
|
||||
-- Call only if component with ON_LAYOUT_CHANGE interest
|
||||
function M.on_layout_change(self)
|
||||
function Component:on_layout_change()
|
||||
end
|
||||
|
||||
|
||||
-- Call, if input was capturing before this component
|
||||
-- Example: scroll is start scrolling, so you need unhover button
|
||||
function M.on_input_interrupt(self)
|
||||
function Component:on_input_interrupt()
|
||||
end
|
||||
|
||||
|
||||
-- Call, if game lost focus. Need ON_FOCUS_LOST intereset
|
||||
function M.on_focus_lost(self)
|
||||
function Component:on_focus_lost()
|
||||
end
|
||||
|
||||
|
||||
-- Call, if game gained focus. Need ON_FOCUS_GAINED intereset
|
||||
function M.on_focus_gained(self)
|
||||
function Component:on_focus_gained()
|
||||
end
|
||||
|
||||
|
||||
-- Call on component remove or on druid:final
|
||||
function M.on_remove(self)
|
||||
function Component:on_remove()
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Component
|
415
druid/extended/dynamic_grid.lua
Normal file
415
druid/extended/dynamic_grid.lua
Normal file
@@ -0,0 +1,415 @@
|
||||
--- Component to handle placing components in row
|
||||
-- @module DynamicGrid
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.dynamic_grid
|
||||
|
||||
--- On item add callback(self, node, index)
|
||||
-- @tfield druid_event on_add_item
|
||||
|
||||
--- On item remove callback(self, index)
|
||||
-- @tfield druid_event on_remove_item
|
||||
|
||||
--- On item add or remove callback(self, index)
|
||||
-- @tfield druid_event on_change_items
|
||||
|
||||
--- On grid clear callback(self)
|
||||
-- @tfield druid_event on_clear
|
||||
|
||||
--- On update item positions callback(self)
|
||||
-- @tfield druid_event on_update_positions
|
||||
|
||||
--- Parent gui node
|
||||
-- @tfield node parent
|
||||
|
||||
--- List of all grid nodes
|
||||
-- @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", { const.ON_LAYOUT_CHANGE })
|
||||
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @tparam DynamicGrid self
|
||||
-- @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
|
||||
-- @tparam number index The grid element index
|
||||
-- @tparam node node The node to be placed
|
||||
-- @tparam[opt] number 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 = self:_get_node_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
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam[opt] number index The node position. By default add as last node
|
||||
-- @tparam[opt=false] bool is_shift_left If true, shift all nodes to the left, otherwise shift nodes to the right
|
||||
function DynamicGrid.add(self, node, index, is_shift_left)
|
||||
local delta = is_shift_left and -1 or 1
|
||||
|
||||
-- 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]
|
||||
if is_shift then
|
||||
-- We need to iterate from index to start or end grid, depends of shift side
|
||||
local start_index = is_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 = is_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()
|
||||
|
||||
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
|
||||
-- @tparam number index The grid node index to remove
|
||||
-- @tparam[opt=false] bool is_shift_left If true, shift all nodes to the left, otherwise shift nodes to the right
|
||||
-- @treturn Node The deleted gui node from grid
|
||||
function DynamicGrid.remove(self, index, is_shift_left)
|
||||
local delta = is_shift_left and -1 or 1
|
||||
|
||||
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
|
||||
local target_index = is_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
|
||||
|
||||
-- Sync grid data
|
||||
self:_update()
|
||||
|
||||
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
|
||||
-- @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 grid index by node
|
||||
-- @tparam DynamicGrid self
|
||||
-- @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
|
||||
-- @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))
|
||||
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
|
||||
-- @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
|
||||
-- @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 = self:_get_node_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 + self:_get_zero_offset())
|
||||
end
|
||||
|
||||
|
||||
--- Update grid inner state
|
||||
-- @tparam DynamicGrid self
|
||||
-- @tparam bool 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
|
||||
-- @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
|
||||
-- @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
|
||||
-- @tparam bool is_instant If true, node position update instantly, otherwise with set_position_function callback
|
||||
-- @local
|
||||
function DynamicGrid._update_pos(self, is_instant)
|
||||
local offset = self:_get_zero_offset()
|
||||
|
||||
for index, node in pairs(self.nodes) do
|
||||
if is_instant then
|
||||
gui.set_position(node.node, node.pos + offset)
|
||||
else
|
||||
self._set_position_function(node.node, node.pos + offset)
|
||||
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 = self:_get_node_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
|
||||
|
||||
|
||||
function DynamicGrid._get_node_size(self, node)
|
||||
return vmath.mul_per_elem(gui.get_size(node), gui.get_scale(node))
|
||||
end
|
||||
|
||||
|
||||
--- Return elements offset for correct posing nodes. Correct posing at
|
||||
-- parent pivot node (0:0) with adjusting of node sizes and anchoring
|
||||
-- @tparam DynamicGrid self
|
||||
-- @treturn vector3 The offset vector
|
||||
-- @local
|
||||
function DynamicGrid._get_zero_offset(self)
|
||||
-- zero offset: center pos - border size * anchor
|
||||
return vmath.vector3(
|
||||
-((self.border.x + self.border.z)/2 + (self.border.z - self.border.x) * self.pivot.x),
|
||||
-((self.border.y + self.border.w)/2 + (self.border.y - self.border.w) * self.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
|
@@ -12,7 +12,6 @@ function M:init(data_list, scroll, grid, create_function)
|
||||
self.druid = self:get_druid()
|
||||
self.scroll = scroll
|
||||
self.grid = grid
|
||||
self.grid:set_grid_mode(const.GRID_MODE.STATIC)
|
||||
|
||||
self.data = data_list
|
||||
self.top_index = 1
|
@@ -1,33 +1,56 @@
|
||||
--- Druid input text component.
|
||||
-- Carry on user text input
|
||||
-- @author Part of code from Britzl gooey input component
|
||||
-- @module druid.input
|
||||
-- @module Input
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.input
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_input_select (self, button_node) On input field select callback
|
||||
-- @tfield druid_event on_input_unselect (self, button_node) On input field unselect callback
|
||||
-- @tfield druid_event on_input_text (self, input_text) On input field text change callback
|
||||
-- @tfield druid_event on_input_empty (self, input_text) On input field text change to empty string callback
|
||||
-- @tfield druid_event on_input_full (self, input_text) On input field text change to max length string callback
|
||||
-- @tfield druid_event on_input_wrong (self, params, button_instance) On trying user input with not allowed character callback
|
||||
--- On input field select callback(self, button_node)
|
||||
-- @tfield druid_event on_input_select
|
||||
|
||||
--- On input field unselect callback(self, button_node)
|
||||
-- @tfield druid_event on_input_unselect
|
||||
|
||||
--- On input field text change callback(self, input_text)
|
||||
-- @tfield druid_event on_input_text
|
||||
|
||||
--- On input field text change to empty string callback(self, input_text)
|
||||
-- @tfield druid_event on_input_empty
|
||||
|
||||
--- On input field text change to max length string callback(self, input_text)
|
||||
-- @tfield druid_event on_input_full
|
||||
|
||||
--- On trying user input with not allowed character callback(self, params, button_instance)
|
||||
-- @tfield druid_event on_input_wrong
|
||||
|
||||
--- Text component
|
||||
-- @tfield druid.text text
|
||||
|
||||
--- Button component
|
||||
-- @tfield druid.button button
|
||||
|
||||
--- Is current input selected now
|
||||
-- @tfield bool is_selected
|
||||
|
||||
--- Is current input is empty now
|
||||
-- @tfield bool is_empty
|
||||
|
||||
--- Max length for input text
|
||||
-- @tfield[opt] number max_length
|
||||
|
||||
--- Pattern matching for user input
|
||||
-- @tfield[opt] string allowerd_characters
|
||||
|
||||
--- Gui keyboard type for input field
|
||||
-- @tfield number keyboard_type
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield druid.text text Text component
|
||||
-- @tfield druid.button button Button component
|
||||
-- @tfield bool is_selected Is current input selected now
|
||||
-- @tfield bool is_empty Is current input is empty now
|
||||
-- @tfield[opt] number max_length Max length for input text
|
||||
-- @tfield[opt] string allowerd_characters Pattern matching for user input
|
||||
-- @tfield number keyboard_type Gui keyboard type for input field
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local component = require("druid.component")
|
||||
local utf8 = require("druid.system.utf8")
|
||||
|
||||
local M = component.create("input", { const.ON_INPUT, const.ON_FOCUS_LOST })
|
||||
local Input = component.create("input", { const.ON_INPUT, const.ON_FOCUS_LOST })
|
||||
|
||||
|
||||
--- Mask text by replacing every character with a mask character
|
||||
@@ -48,11 +71,11 @@ end
|
||||
local function select(self)
|
||||
gui.reset_keyboard()
|
||||
self.marked_value = ""
|
||||
if not self.selected then
|
||||
if not self.is_selected then
|
||||
self:increase_input_priority()
|
||||
self.button:increase_input_priority()
|
||||
self.previous_value = self.value
|
||||
self.selected = true
|
||||
self.is_selected = true
|
||||
|
||||
gui.show_keyboard(self.keyboard_type, false)
|
||||
self.on_input_select:trigger(self:get_context())
|
||||
@@ -65,10 +88,10 @@ end
|
||||
local function unselect(self)
|
||||
gui.reset_keyboard()
|
||||
self.marked_value = ""
|
||||
if self.selected then
|
||||
if self.is_selected then
|
||||
self:reset_input_priority()
|
||||
self.button:reset_input_priority()
|
||||
self.selected = false
|
||||
self.is_selected = false
|
||||
|
||||
gui.hide_keyboard()
|
||||
self.on_input_unselect:trigger(self:get_context())
|
||||
@@ -90,14 +113,14 @@ end
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in druid styles table
|
||||
-- or create your own style
|
||||
-- @table Style
|
||||
-- @table style
|
||||
-- @tfield[opt=false] bool IS_LONGTAP_ERASE Is long tap will erase current input data
|
||||
-- @tfield[opt=*] string MASK_DEFAULT_CHAR Default character mask for password input
|
||||
-- @tfield function on_select (self, button_node) Callback on input field selecting
|
||||
-- @tfield function on_unselect (self, button_node) Callback on input field unselecting
|
||||
-- @tfield function on_input_wrong (self, button_node) Callback on wrong user input
|
||||
-- @tfield table button_style Custom button style for input node
|
||||
function M.on_style_change(self, style)
|
||||
function Input.on_style_change(self, style)
|
||||
self.style = {}
|
||||
|
||||
self.style.IS_LONGTAP_ERASE = style.IS_LONGTAP_ERASE or false
|
||||
@@ -115,11 +138,14 @@ function M.on_style_change(self, style)
|
||||
end
|
||||
|
||||
|
||||
function M.init(self, click_node, text_node, keyboard_type)
|
||||
-- @tparam node click_node Button node to enabled input component
|
||||
-- @tparam node text_node Text node what will be changed on user input
|
||||
-- @tparam[opt] number keyboard_type Gui keyboard type for input field
|
||||
function Input.init(self, click_node, text_node, keyboard_type)
|
||||
self.druid = self:get_druid(self)
|
||||
self.text = self.druid:new_text(text_node)
|
||||
|
||||
self.selected = false
|
||||
self.is_selected = false
|
||||
self.value = self.text.last_value
|
||||
self.previous_value = self.text.last_value
|
||||
self.current_value = self.text.last_value
|
||||
@@ -149,8 +175,8 @@ function M.init(self, click_node, text_node, keyboard_type)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input(self, action_id, action)
|
||||
if self.selected then
|
||||
function Input.on_input(self, action_id, action)
|
||||
if self.is_selected then
|
||||
local input_text = nil
|
||||
if action_id == const.ACTION_TEXT then
|
||||
-- ignore return key
|
||||
@@ -209,24 +235,24 @@ function M.on_input(self, action_id, action)
|
||||
end
|
||||
end
|
||||
|
||||
return self.selected
|
||||
return self.is_selected
|
||||
end
|
||||
|
||||
|
||||
function M.on_focus_lost(self)
|
||||
function Input.on_focus_lost(self)
|
||||
unselect(self)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input_interrupt(self)
|
||||
function Input.on_input_interrupt(self)
|
||||
-- unselect(self)
|
||||
end
|
||||
|
||||
|
||||
--- Set text for input field
|
||||
-- @function input:set_text
|
||||
-- @tparam Input self
|
||||
-- @tparam string input_text The string to apply for input field
|
||||
function M.set_text(self, input_text)
|
||||
function Input.set_text(self, input_text)
|
||||
-- Case when update with marked text
|
||||
if input_text then
|
||||
self.value = input_text
|
||||
@@ -271,19 +297,19 @@ end
|
||||
|
||||
|
||||
--- Return current input field text
|
||||
-- @function input:get_text
|
||||
-- @tparam Input self
|
||||
-- @treturn string The current input field text
|
||||
function M.get_text(self)
|
||||
function Input.get_text(self)
|
||||
return self.value .. self.marked_value
|
||||
end
|
||||
|
||||
|
||||
--- Set maximum length for input field.
|
||||
-- Pass nil to make input field unliminted (by default)
|
||||
-- @function input:set_max_length
|
||||
-- @tparam Input self
|
||||
-- @tparam number max_length Maximum length for input text field
|
||||
-- @treturn druid.input Current input instance
|
||||
function M.set_max_length(self, max_length)
|
||||
function Input.set_max_length(self, max_length)
|
||||
self.max_length = max_length
|
||||
return self
|
||||
end
|
||||
@@ -292,21 +318,21 @@ end
|
||||
--- Set allowed charaters for input field.
|
||||
-- See: https://defold.com/ref/stable/string/
|
||||
-- ex: [%a%d] for alpha and numeric
|
||||
-- @function input:set_allowerd_characters
|
||||
-- @tparam Input self
|
||||
-- @tparam string characters Regulax exp. for validate user input
|
||||
-- @treturn druid.input Current input instance
|
||||
function M.set_allowed_characters(self, characters)
|
||||
function Input.set_allowed_characters(self, characters)
|
||||
self.allowed_characters = characters
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Reset current input selection and return previous value
|
||||
-- @function input:reset_changes
|
||||
function M.reset_changes(self)
|
||||
-- @tparam Input self
|
||||
function Input.reset_changes(self)
|
||||
self:set_text(self.previous_value)
|
||||
unselect(self)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Input
|
@@ -1,29 +1,30 @@
|
||||
--- Component to handle all GUI texts
|
||||
-- Good working with localization system
|
||||
-- @module druid.lang_text
|
||||
-- @module LangText
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.lang_text
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_change On change text callback
|
||||
--- On change text callback
|
||||
-- @tfield druid_event on_change
|
||||
|
||||
--- The text component
|
||||
-- @tfield Text text
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield druid.text text The text component
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local settings = require("druid.system.settings")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("lang_text", { const.ON_LANGUAGE_CHANGE })
|
||||
local LangText = component.create("lang_text", { const.ON_LANGUAGE_CHANGE })
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function lang_text:init
|
||||
-- @tparam LangText self
|
||||
-- @tparam node node The text node
|
||||
-- @tparam string locale_id Default locale id
|
||||
-- @tparam bool no_adjust If true, will not correct text size
|
||||
function M.init(self, node, locale_id, no_adjust)
|
||||
function LangText.init(self, node, locale_id, no_adjust)
|
||||
self.druid = self:get_druid()
|
||||
self.text = self.druid:new_text(node, locale_id, no_adjust)
|
||||
self.last_locale_args = {}
|
||||
@@ -36,17 +37,17 @@ function M.init(self, node, locale_id, no_adjust)
|
||||
end
|
||||
|
||||
|
||||
function M.on_language_change(self)
|
||||
function LangText.on_language_change(self)
|
||||
if self.last_locale then
|
||||
M.translate(self, self.last_locale, unpack(self.last_locale_args))
|
||||
self:translate(self.last_locale, unpack(self.last_locale_args))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Setup raw text to lang_text component
|
||||
-- @function lang_text:set_to
|
||||
-- @tparam LangText self
|
||||
-- @tparam string text Text for text node
|
||||
function M.set_to(self, text)
|
||||
function LangText.set_to(self, text)
|
||||
self.last_locale = false
|
||||
self.text:set_to(text)
|
||||
self.on_change:trigger()
|
||||
@@ -54,13 +55,13 @@ end
|
||||
|
||||
|
||||
--- Translate the text by locale_id
|
||||
-- @function lang_text:translate
|
||||
-- @tparam LangText self
|
||||
-- @tparam string locale_id Locale id
|
||||
function M.translate(self, locale_id, ...)
|
||||
function LangText.translate(self, locale_id, ...)
|
||||
self.last_locale_args = {...}
|
||||
self.last_locale = locale_id or self.last_locale
|
||||
self.text:set_to(settings.get_text(self.last_locale, ...))
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return LangText
|
@@ -1,26 +1,37 @@
|
||||
--- Basic progress bar component.
|
||||
-- For correct progress bar init it should be in max size from gui
|
||||
-- @module druid.progress
|
||||
-- @module Progress
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.progress
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_change On progress bar change callback
|
||||
--- On progress bar change callback(self, new_value)
|
||||
-- @tfield druid_event on_change
|
||||
|
||||
--- Progress bar fill node
|
||||
-- @tfield node node
|
||||
|
||||
--- The progress bar direction
|
||||
-- @tfield string key
|
||||
|
||||
--- Current progress bar scale
|
||||
-- @tfield vector3 scale
|
||||
|
||||
--- Current progress bar size
|
||||
-- @tfield vector3 size
|
||||
|
||||
--- Maximum size of progress bar
|
||||
-- @tfield number max_size
|
||||
|
||||
--- Progress bar slice9 settings
|
||||
-- @tfield vector4 slice
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield node node Progress bar fill node
|
||||
-- @tfield string key The progress bar direction
|
||||
-- @tfield vector3 scale Current progress bar scale
|
||||
-- @tfield vector3 size Current progress bar size
|
||||
-- @tfield number max_size Maximum size of progress bar
|
||||
-- @tfield vector4 slice Progress bar slice9 settings
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("progress", { const.ON_UPDATE, const.ON_LAYOUT_CHANGE })
|
||||
local Progress = component.create("progress", { const.ON_UPDATE, const.ON_LAYOUT_CHANGE })
|
||||
|
||||
|
||||
local function check_steps(self, from, to, exactly)
|
||||
@@ -68,10 +79,10 @@ end
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in druid styles table
|
||||
-- or create your own style
|
||||
-- @table Style
|
||||
-- @table style
|
||||
-- @tfield[opt=5] number SPEED Progress bas fill rate. More -> faster
|
||||
-- @tfield[opt=0.005] number MIN_DELTA Minimum step to fill progress bar
|
||||
function M.on_style_change(self, style)
|
||||
function Progress.on_style_change(self, style)
|
||||
self.style = {}
|
||||
self.style.SPEED = style.SPEED or 5
|
||||
self.style.MIN_DELTA = style.MIN_DELTA or 0.005
|
||||
@@ -79,11 +90,11 @@ end
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function progress:init
|
||||
-- @tparam Progress self
|
||||
-- @tparam string|node node Progress bar fill node or node name
|
||||
-- @tparam string key Progress bar direction: const.SIDE.X or const.SIDE.Y
|
||||
-- @tparam[opt=1] number init_value Initial value of progress bar
|
||||
function M.init(self, node, key, init_value)
|
||||
function Progress.init(self, node, key, init_value)
|
||||
assert(key == const.SIDE.X or const.SIDE.Y, "Progress bar key should be 'x' or 'y'")
|
||||
|
||||
self.prop = hash("scale."..key)
|
||||
@@ -106,12 +117,12 @@ function M.init(self, node, key, init_value)
|
||||
end
|
||||
|
||||
|
||||
function M.on_layout_change(self)
|
||||
function Progress.on_layout_change(self)
|
||||
self:set_to(self.last_value)
|
||||
end
|
||||
|
||||
|
||||
function M.update(self, dt)
|
||||
function Progress.update(self, dt)
|
||||
if self.target then
|
||||
local prev_value = self.last_value
|
||||
local step = math.abs(self.last_value - self.target) * (self.style.SPEED*dt)
|
||||
@@ -132,50 +143,50 @@ end
|
||||
|
||||
|
||||
--- Fill a progress bar and stop progress animation
|
||||
-- @function progress:fill
|
||||
function M.fill(self)
|
||||
-- @tparam Progress self
|
||||
function Progress.fill(self)
|
||||
set_bar_to(self, 1, true)
|
||||
end
|
||||
|
||||
|
||||
--- Empty a progress bar
|
||||
-- @function progress:empty
|
||||
function M.empty(self)
|
||||
-- @tparam Progress self
|
||||
function Progress.empty(self)
|
||||
set_bar_to(self, 0, true)
|
||||
end
|
||||
|
||||
|
||||
--- Instant fill progress bar to value
|
||||
-- @function progress:set_to
|
||||
-- @tparam Progress self
|
||||
-- @tparam number to Progress bar value, from 0 to 1
|
||||
function M.set_to(self, to)
|
||||
function Progress.set_to(self, to)
|
||||
set_bar_to(self, to)
|
||||
end
|
||||
|
||||
|
||||
--- Return current progress bar value
|
||||
-- @function progress:get
|
||||
function M.get(self)
|
||||
-- @tparam Progress self
|
||||
function Progress.get(self)
|
||||
return self.last_value
|
||||
end
|
||||
|
||||
|
||||
--- Set points on progress bar to fire the callback
|
||||
-- @function progress:set_steps
|
||||
-- @tparam Progress self
|
||||
-- @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 M.set_steps(self, steps, callback)
|
||||
function Progress.set_steps(self, steps, callback)
|
||||
self.steps = steps
|
||||
self.step_callback = callback
|
||||
end
|
||||
|
||||
|
||||
--- Start animation of a progress bar
|
||||
-- @function progress:to
|
||||
-- @tparam Progress self
|
||||
-- @tparam number to value between 0..1
|
||||
-- @tparam[opt] function callback Callback on animation ends
|
||||
function M.to(self, to, callback)
|
||||
function Progress.to(self, to, callback)
|
||||
to = helper.clamp(to, 0, 1)
|
||||
-- cause of float error
|
||||
local value = helper.round(to, 5)
|
||||
@@ -190,4 +201,4 @@ function M.to(self, to, callback)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Progress
|
@@ -1,18 +1,19 @@
|
||||
--- Radio group module
|
||||
-- @module druid.radio_group
|
||||
-- @module RadioGroup
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.radio_group
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_radio_click On any checkbox click
|
||||
--- On any checkbox click
|
||||
-- @tfield druid_event on_radio_click
|
||||
|
||||
--- Array of checkbox components
|
||||
-- @tfield Checkbox[] checkboxes
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield table checkboxes Array of checkbox components
|
||||
|
||||
local Event = require("druid.event")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("radio_group")
|
||||
local RadioGroup = component.create("radio_group")
|
||||
|
||||
|
||||
local function on_checkbox_click(self, index)
|
||||
@@ -25,11 +26,11 @@ end
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function radio_group:init
|
||||
-- @tparam node[] node Array of gui node
|
||||
-- @tparam RadioGroup self
|
||||
-- @tparam node[] nodes Array of gui node
|
||||
-- @tparam function callback Radio callback
|
||||
-- @tparam[opt=node] node[] click node Array of trigger nodes, by default equals to nodes
|
||||
function M.init(self, nodes, callback, click_nodes)
|
||||
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
|
||||
function RadioGroup.init(self, nodes, callback, click_nodes)
|
||||
self.druid = self:get_druid()
|
||||
self.checkboxes = {}
|
||||
|
||||
@@ -47,17 +48,17 @@ end
|
||||
|
||||
|
||||
--- Set radio group state
|
||||
-- @function radio_group:set_state
|
||||
-- @tparam RadioGroup self
|
||||
-- @tparam number index Index in radio group
|
||||
function M.set_state(self, index)
|
||||
function RadioGroup.set_state(self, index)
|
||||
on_checkbox_click(self, index)
|
||||
end
|
||||
|
||||
|
||||
--- Return radio group state
|
||||
-- @function radio_group:get_state
|
||||
-- @tparam RadioGroup self
|
||||
-- @treturn number Index in radio group
|
||||
function M.get_state(self)
|
||||
function RadioGroup.get_state(self)
|
||||
local result = -1
|
||||
|
||||
for i = 1, #self.checkboxes do
|
||||
@@ -71,4 +72,4 @@ function M.get_state(self)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return RadioGroup
|
@@ -1,20 +1,35 @@
|
||||
--- Druid slider component
|
||||
-- @module druid.slider
|
||||
-- @module Slider
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.slider
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_change_value On change value callback
|
||||
--- On change value callback(self, value)
|
||||
-- @tfield druid_event on_change_value
|
||||
|
||||
--- Slider pin node
|
||||
-- @tfield node node
|
||||
|
||||
--- Start pin node position
|
||||
-- @tfield vector3 start_pos
|
||||
|
||||
--- Current pin node position
|
||||
-- @tfield vector3 pos
|
||||
|
||||
--- Targer pin node position
|
||||
-- @tfield vector3 target_pos
|
||||
|
||||
--- End pin node position
|
||||
-- @tfield vector3 end_pos
|
||||
|
||||
--- Length between start and end position
|
||||
-- @tfield number dist
|
||||
|
||||
--- Current drag state
|
||||
-- @tfield bool is_drag
|
||||
|
||||
--- Current slider value
|
||||
-- @tfield number value
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield node node Slider pin node
|
||||
-- @tfield vector3 start_pos Start pin node position
|
||||
-- @tfield vector3 pos Current pin node position
|
||||
-- @tfield vector3 target_pos Targer pin node position
|
||||
-- @tfield vector3 end_pos End pin node position
|
||||
-- @tfield number dist Length between start and end position
|
||||
-- @tfield bool is_drag Current drag state
|
||||
-- @tfield number value Current slider value
|
||||
|
||||
|
||||
local Event = require("druid.event")
|
||||
@@ -22,7 +37,7 @@ local helper = require("druid.helper")
|
||||
local const = require("druid.const")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("slider", { const.ON_INPUT_HIGH, const.ON_LAYOUT_CHANGE })
|
||||
local Slider = component.create("slider", { const.ON_INPUT_HIGH, const.ON_LAYOUT_CHANGE })
|
||||
|
||||
|
||||
local function on_change_value(self)
|
||||
@@ -37,11 +52,11 @@ end
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function slider:init
|
||||
-- @tparam Slider self
|
||||
-- @tparam node node Gui pin node
|
||||
-- @tparam vector3 end_pos The end position of slider
|
||||
-- @tparam[opt] function callback On slider change callback
|
||||
function M.init(self, node, end_pos, callback)
|
||||
function Slider.init(self, node, end_pos, callback)
|
||||
self.node = self:get_node(node)
|
||||
|
||||
self.start_pos = gui.get_position(self.node)
|
||||
@@ -59,12 +74,12 @@ function M.init(self, node, end_pos, callback)
|
||||
end
|
||||
|
||||
|
||||
function M.on_layout_change(self)
|
||||
function Slider.on_layout_change(self)
|
||||
self:set(self.value, true)
|
||||
end
|
||||
|
||||
|
||||
function M.on_input(self, action_id, action)
|
||||
function Slider.on_input(self, action_id, action)
|
||||
if action_id ~= const.ACTION_TOUCH then
|
||||
return false
|
||||
end
|
||||
@@ -130,10 +145,10 @@ end
|
||||
|
||||
|
||||
--- Set value for slider
|
||||
-- @function slider:set
|
||||
-- @tparam Slider self
|
||||
-- @tparam number value Value from 0 to 1
|
||||
-- @tparam[opt] bool is_silent Don't trigger event if true
|
||||
function M.set(self, value, is_silent)
|
||||
function Slider.set(self, value, is_silent)
|
||||
value = helper.clamp(value, 0, 1)
|
||||
set_position(self, value)
|
||||
self.value = value
|
||||
@@ -145,12 +160,12 @@ end
|
||||
|
||||
--- Set slider steps. Pin node will
|
||||
-- apply closest step position
|
||||
-- @function slider:set_steps
|
||||
-- @tparam Slider self
|
||||
-- @tparam number[] steps Array of steps
|
||||
-- @usage slider:set_steps({0, 0.2, 0.6, 1})
|
||||
function M.set_steps(self, steps)
|
||||
function Slider.set_steps(self, steps)
|
||||
self.steps = steps
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Slider
|
@@ -1,20 +1,31 @@
|
||||
--- Component to handle GUI timers.
|
||||
-- Timer updating by game delta time. If game is not focused -
|
||||
-- timer will be not updated.
|
||||
-- @module druid.timer
|
||||
-- @module Timer
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.timer
|
||||
|
||||
--- Component events
|
||||
-- @table Events
|
||||
-- @tfield druid_event on_tick On timer tick callback. Fire every second
|
||||
-- @tfield druid_event on_set_enabled On timer change enabled state callback
|
||||
-- @tfield druid_event on_timer_end On timer end callback
|
||||
--- On timer tick. Fire every second callback(self, value)
|
||||
-- @tfield druid_event on_tick
|
||||
|
||||
--- On timer change enabled state callback(self, is_enabled)
|
||||
-- @tfield druid_event on_set_enabled
|
||||
|
||||
--- On timer end callback
|
||||
-- @tfield druid_event on_timer_end(self, Timer)
|
||||
|
||||
--- Trigger node
|
||||
-- @tfield node node
|
||||
|
||||
--- Initial timer value
|
||||
-- @tfield number from
|
||||
|
||||
--- Target timer value
|
||||
-- @tfield number target
|
||||
|
||||
--- Current timer value
|
||||
-- @tfield number value
|
||||
|
||||
--- Component fields
|
||||
-- @table Fields
|
||||
-- @tfield node node Trigger node
|
||||
-- @tfield number from Initial timer value
|
||||
-- @tfield number target Target timer value
|
||||
-- @tfield number value Current timer value
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
@@ -22,16 +33,16 @@ local formats = require("druid.helper.formats")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local M = component.create("timer", { const.ON_UPDATE })
|
||||
local Timer = component.create("timer", { const.ON_UPDATE })
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @function timer:init
|
||||
-- @tparam Timer self
|
||||
-- @tparam node node Gui text node
|
||||
-- @tparam number seconds_from Start timer value in seconds
|
||||
-- @tparam[opt=0] number seconds_to End timer value in seconds
|
||||
-- @tparam[opt] function callback Function on timer end
|
||||
function M.init(self, node, seconds_from, seconds_to, callback)
|
||||
function Timer.init(self, node, seconds_from, seconds_to, callback)
|
||||
self.node = self:get_node(node)
|
||||
seconds_from = math.max(seconds_from, 0)
|
||||
seconds_to = math.max(seconds_to or 0, 0)
|
||||
@@ -52,7 +63,7 @@ function M.init(self, node, seconds_from, seconds_to, callback)
|
||||
end
|
||||
|
||||
|
||||
function M.update(self, dt)
|
||||
function Timer.update(self, dt)
|
||||
if not self.is_on then
|
||||
return
|
||||
end
|
||||
@@ -63,7 +74,7 @@ function M.update(self, dt)
|
||||
if self.temp > dist then
|
||||
self.temp = self.temp - dist
|
||||
self.value = helper.step(self.value, self.target, 1)
|
||||
M.set_to(self, self.value)
|
||||
self:set_to(self.value)
|
||||
|
||||
self.on_tick:trigger(self:get_context(), self.value)
|
||||
|
||||
@@ -75,18 +86,18 @@ function M.update(self, dt)
|
||||
end
|
||||
|
||||
--- Set text to text field
|
||||
-- @function timer:set_to
|
||||
-- @tparam Timer self
|
||||
-- @tparam number set_to Value in seconds
|
||||
function M.set_to(self, set_to)
|
||||
function Timer.set_to(self, set_to)
|
||||
self.last_value = set_to
|
||||
gui.set_text(self.node, formats.second_string_min(set_to))
|
||||
end
|
||||
|
||||
|
||||
--- Called when update
|
||||
-- @function timer:set_state
|
||||
-- @tparam Timer self
|
||||
-- @tparam bool is_on Timer enable state
|
||||
function M.set_state(self, is_on)
|
||||
function Timer.set_state(self, is_on)
|
||||
self.is_on = is_on
|
||||
|
||||
self.on_set_enabled:trigger(self:get_context(), is_on)
|
||||
@@ -94,17 +105,17 @@ end
|
||||
|
||||
|
||||
--- Set time interval
|
||||
-- @function timer:set_interval
|
||||
-- @tparam Timer self
|
||||
-- @tparam number from Start time in seconds
|
||||
-- @tparam number to Target time in seconds
|
||||
function M.set_interval(self, from, to)
|
||||
function Timer.set_interval(self, from, to)
|
||||
self.from = from
|
||||
self.value = from
|
||||
self.temp = 0
|
||||
self.target = to
|
||||
M.set_state(self, true)
|
||||
M.set_to(self, from)
|
||||
self:set_state(true)
|
||||
self:set_to(from)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
return Timer
|
@@ -131,6 +131,16 @@ function M.lerp(a, b, t)
|
||||
end
|
||||
|
||||
|
||||
function M.contains(t, value)
|
||||
for i = 1, #t do
|
||||
if t[i] == value then
|
||||
return i
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
--- Check if node is enabled in gui hierarchy.
|
||||
-- Return false, if node or any his parent is disabled
|
||||
-- @function helper.is_enabled
|
||||
@@ -188,4 +198,28 @@ function M.get_border(node)
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
--- Show deprecated message. Once time per message
|
||||
-- @function helper.deprecated
|
||||
-- @tparam string message The deprecated message
|
||||
local _deprecated_messages = {}
|
||||
function M.deprecated(message)
|
||||
if _deprecated_messages[message] then
|
||||
return
|
||||
end
|
||||
|
||||
print("[Druid]: " .. message)
|
||||
_deprecated_messages[message] = true
|
||||
end
|
||||
|
||||
|
||||
-- Show message to require extended component
|
||||
function M.extended_component(component_name)
|
||||
print(string.format("[Druid]: The component %s is extended component. You have to register it via druid.register to use it", component_name))
|
||||
print("[Druid]: Use next code:")
|
||||
print(string.format('local %s = require("druid.extended.%s")', component_name, component_name))
|
||||
print(string.format('druid.register("%s", %s)', component_name, component_name))
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
|
@@ -1,51 +1,62 @@
|
||||
--- Druid main class. Create instance of this
|
||||
-- to start creating components
|
||||
-- @module druid_instance
|
||||
-- @see druid.button
|
||||
-- @see druid.blocker
|
||||
-- @see druid.back_handler
|
||||
-- @see druid.input
|
||||
-- @see druid.text
|
||||
-- @see druid.lang_text
|
||||
-- @see druid.timer
|
||||
-- @see druid.progress
|
||||
-- @see druid.grid
|
||||
-- @see druid.scroll
|
||||
-- @see druid.slider
|
||||
-- @see druid.checkbox
|
||||
-- @see druid.checkbox_group
|
||||
-- @see druid.radio_group
|
||||
-- @see druid.swipe
|
||||
-- @see druid.drag
|
||||
-- @see druid.infinity_list
|
||||
--- Instance of Druid. Make one instance per gui_script with next code:
|
||||
--
|
||||
-- local druid = require("druid.druid")
|
||||
-- function init(self)
|
||||
-- self.druid = druid.new(self)
|
||||
-- local button = self.druid:new_button(...)
|
||||
-- end
|
||||
--
|
||||
-- Learn Druid instance function here
|
||||
-- @module DruidInstance
|
||||
-- @alias druid_instance
|
||||
-- @see Button
|
||||
-- @see Blocker
|
||||
-- @see BackHandler
|
||||
-- @see Input
|
||||
-- @see Text
|
||||
-- @see LangText
|
||||
-- @see Timer
|
||||
-- @see Progress
|
||||
-- @see StaticGrid
|
||||
-- @see DynamicGrid
|
||||
-- @see Scroll
|
||||
-- @see Slider
|
||||
-- @see Checkbox
|
||||
-- @see CheckboxGroup
|
||||
-- @see RadioGroup
|
||||
-- @see Swipe
|
||||
-- @see Drag
|
||||
-- @see Hover
|
||||
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local druid_input = require("druid.helper.druid_input")
|
||||
local settings = require("druid.system.settings")
|
||||
local class = require("druid.system.middleclass")
|
||||
|
||||
local button = require("druid.base.button")
|
||||
local blocker = require("druid.base.blocker")
|
||||
local back_handler = require("druid.base.back_handler")
|
||||
local hover = require("druid.base.hover")
|
||||
local text = require("druid.base.text")
|
||||
local lang_text = require("druid.base.lang_text")
|
||||
local timer = require("druid.base.timer")
|
||||
local progress = require("druid.base.progress")
|
||||
local grid = require("druid.base.grid")
|
||||
local scroll = require("druid.base.scroll")
|
||||
local slider = require("druid.base.slider")
|
||||
local checkbox = require("druid.base.checkbox")
|
||||
local checkbox_group = require("druid.base.checkbox_group")
|
||||
local radio_group = require("druid.base.radio_group")
|
||||
local input = require("druid.base.input")
|
||||
local swipe = require("druid.base.swipe")
|
||||
local blocker = require("druid.base.blocker")
|
||||
local button = require("druid.base.button")
|
||||
local drag = require("druid.base.drag")
|
||||
local infinity_list = require("druid.base.infinity_list")
|
||||
-- local infinity_scroll = require("druid.base.infinity_scroll")
|
||||
local hover = require("druid.base.hover")
|
||||
local scroll = require("druid.base.scroll")
|
||||
local static_grid = require("druid.base.static_grid")
|
||||
local swipe = require("druid.base.swipe")
|
||||
local text = require("druid.base.text")
|
||||
|
||||
-- @classmod Druid
|
||||
local Druid = class("druid.druid_instance")
|
||||
local checkbox = require("druid.extended.checkbox")
|
||||
local checkbox_group = require("druid.extended.checkbox_group")
|
||||
local dynamic_grid = require("druid.extended.dynamic_grid")
|
||||
local input = require("druid.extended.input")
|
||||
local lang_text = require("druid.extended.lang_text")
|
||||
local progress = require("druid.extended.progress")
|
||||
local radio_group = require("druid.extended.radio_group")
|
||||
local slider = require("druid.extended.slider")
|
||||
local timer = require("druid.extended.timer")
|
||||
local infinity_list = require("druid.extended.infinity_list")
|
||||
|
||||
|
||||
local DruidInstance = class("druid.druid_instance")
|
||||
|
||||
|
||||
local function input_init(self)
|
||||
@@ -79,7 +90,7 @@ local function create(self, instance_class)
|
||||
|
||||
table.insert(self.components[const.ALL], instance)
|
||||
|
||||
local register_to = instance:get_interests()
|
||||
local register_to = instance:__get_interests()
|
||||
for i = 1, #register_to do
|
||||
local interest = register_to[i]
|
||||
table.insert(self.components[interest], instance)
|
||||
@@ -101,7 +112,8 @@ local function process_input(action_id, action, components, is_input_consumed)
|
||||
for i = #components, 1, -1 do
|
||||
local component = components[i]
|
||||
-- Process increased input priority first
|
||||
if component._meta.increased_input_priority then
|
||||
local meta = component._meta
|
||||
if meta.input_enabled and meta.increased_input_priority then
|
||||
if not is_input_consumed then
|
||||
is_input_consumed = component:on_input(action_id, action)
|
||||
else
|
||||
@@ -114,7 +126,9 @@ local function process_input(action_id, action, components, is_input_consumed)
|
||||
|
||||
for i = #components, 1, -1 do
|
||||
local component = components[i]
|
||||
if not component._meta.increased_input_priority then
|
||||
-- Process usual input priority next
|
||||
local meta = component._meta
|
||||
if meta.input_enabled and not meta.increased_input_priority then
|
||||
if not is_input_consumed then
|
||||
is_input_consumed = component:on_input(action_id, action)
|
||||
else
|
||||
@@ -130,10 +144,10 @@ end
|
||||
|
||||
|
||||
--- Druid class constructor
|
||||
-- @function druid:initialize
|
||||
-- @tparam context table Druid context. Usually it is self of script
|
||||
-- @tparam style table Druid style module
|
||||
function Druid.initialize(self, context, style)
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam table context Druid context. Usually it is self of script
|
||||
-- @tparam table style Druid style module
|
||||
function DruidInstance.initialize(self, context, style)
|
||||
self._context = context
|
||||
self._style = style or settings.default_style
|
||||
self._deleted = false
|
||||
@@ -149,10 +163,10 @@ end
|
||||
|
||||
|
||||
--- Create new druid component
|
||||
-- @function druid:create
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam Component component Component module
|
||||
-- @tparam args ... Other component params to pass it to component:init function
|
||||
function Druid.create(self, component, ...)
|
||||
function DruidInstance.create(self, component, ...)
|
||||
local instance = create(self, component)
|
||||
|
||||
if instance.init then
|
||||
@@ -165,8 +179,8 @@ end
|
||||
|
||||
--- Call on final function on gui_script. It will call on_remove
|
||||
-- on all druid components
|
||||
-- @function druid:final
|
||||
function Druid.final(self)
|
||||
-- @tparam DruidInstance self
|
||||
function DruidInstance.final(self)
|
||||
local components = self.components[const.ALL]
|
||||
|
||||
for i = #components, 1, -1 do
|
||||
@@ -183,24 +197,26 @@ end
|
||||
|
||||
--- Remove component from druid instance.
|
||||
-- Component `on_remove` function will be invoked, if exist.
|
||||
-- @function druid:remove
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam Component component Component instance
|
||||
function Druid.remove(self, component)
|
||||
function DruidInstance.remove(self, component)
|
||||
if self._is_input_processing then
|
||||
table.insert(self._late_remove, component)
|
||||
return
|
||||
end
|
||||
|
||||
local all_components = self.components[const.ALL]
|
||||
|
||||
-- Recursive remove all children of component
|
||||
for i = #all_components, 1, -1 do
|
||||
local inst = all_components[i]
|
||||
if inst:is_child_of(component) then
|
||||
self:remove(inst)
|
||||
local children = component._meta.children
|
||||
for i = #children, 1, -1 do
|
||||
self:remove(children[i])
|
||||
local parent = children[i]:get_parent_component()
|
||||
if parent then
|
||||
parent:__remove_children(children[i])
|
||||
end
|
||||
end
|
||||
component._meta.children = {}
|
||||
|
||||
local all_components = self.components[const.ALL]
|
||||
for i = #all_components, 1, -1 do
|
||||
if all_components[i] == component then
|
||||
if component.on_remove then
|
||||
@@ -210,7 +226,7 @@ function Druid.remove(self, component)
|
||||
end
|
||||
end
|
||||
|
||||
local interests = component:get_interests()
|
||||
local interests = component:__get_interests()
|
||||
for i = 1, #interests do
|
||||
local interest = interests[i]
|
||||
local components = self.components[interest]
|
||||
@@ -224,9 +240,9 @@ end
|
||||
|
||||
|
||||
--- Druid update function
|
||||
-- @function druid:update
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam number dt Delta time
|
||||
function Druid.update(self, dt)
|
||||
function DruidInstance.update(self, dt)
|
||||
local components = self.components[const.ON_UPDATE]
|
||||
for i = 1, #components do
|
||||
components[i]:update(dt)
|
||||
@@ -235,10 +251,10 @@ end
|
||||
|
||||
|
||||
--- Druid on_input function
|
||||
-- @function druid:on_input
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam hash action_id Action_id from on_input
|
||||
-- @tparam table action Action from on_input
|
||||
function Druid.on_input(self, action_id, action)
|
||||
function DruidInstance.on_input(self, action_id, action)
|
||||
self._is_input_processing = true
|
||||
|
||||
local is_input_consumed = false
|
||||
@@ -263,11 +279,11 @@ end
|
||||
|
||||
|
||||
--- Druid on_message function
|
||||
-- @function druid:on_message
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam hash message_id Message_id from on_message
|
||||
-- @tparam table message Message from on_message
|
||||
-- @tparam hash sender Sender from on_message
|
||||
function Druid.on_message(self, message_id, message, sender)
|
||||
function DruidInstance.on_message(self, message_id, message, sender)
|
||||
local specific_ui_message = const.SPECIFIC_UI_MESSAGES[message_id]
|
||||
|
||||
if specific_ui_message then
|
||||
@@ -289,8 +305,8 @@ end
|
||||
|
||||
--- Druid on focus lost interest function.
|
||||
-- This one called by on_window_callback by global window listener
|
||||
-- @function druid:on_focus_lost
|
||||
function Druid.on_focus_lost(self)
|
||||
-- @tparam DruidInstance self
|
||||
function DruidInstance.on_focus_lost(self)
|
||||
local components = self.components[const.ON_FOCUS_LOST]
|
||||
for i = 1, #components do
|
||||
components[i]:on_focus_lost()
|
||||
@@ -300,8 +316,8 @@ end
|
||||
|
||||
--- Druid on focus gained interest function.
|
||||
-- This one called by on_window_callback by global window listener
|
||||
-- @function druid:on_focus_gained
|
||||
function Druid.on_focus_gained(self)
|
||||
-- @tparam DruidInstance self
|
||||
function DruidInstance.on_focus_gained(self)
|
||||
local components = self.components[const.ON_FOCUS_GAINED]
|
||||
for i = 1, #components do
|
||||
components[i]:on_focus_gained()
|
||||
@@ -311,8 +327,8 @@ end
|
||||
|
||||
--- Druid on layout change function.
|
||||
-- Called on update gui layout
|
||||
-- @function druid:on_layout_change
|
||||
function Druid.on_layout_change(self)
|
||||
-- @tparam DruidInstance self
|
||||
function DruidInstance.on_layout_change(self)
|
||||
local components = self.components[const.ON_LAYOUT_CHANGE]
|
||||
for i = 1, #components do
|
||||
components[i]:on_layout_change()
|
||||
@@ -324,7 +340,7 @@ end
|
||||
-- This one called by global gruid.on_language_change, but can be
|
||||
-- call manualy to update all translations
|
||||
-- @function druid.on_language_change
|
||||
function Druid.on_language_change(self)
|
||||
function DruidInstance.on_language_change(self)
|
||||
local components = self.components[const.ON_LANGUAGE_CHANGE]
|
||||
for i = 1, #components do
|
||||
components[i]:on_language_change()
|
||||
@@ -333,149 +349,182 @@ end
|
||||
|
||||
|
||||
--- Create button basic component
|
||||
-- @function druid:new_button
|
||||
-- @tparam args ... button init args
|
||||
-- @treturn Component button component
|
||||
function Druid.new_button(self, ...)
|
||||
return Druid.create(self, button, ...)
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function callback Button callback
|
||||
-- @tparam[opt] table params Button callback params
|
||||
-- @tparam[opt] node anim_node Button anim node (node, if not provided)
|
||||
-- @treturn Button button component
|
||||
function DruidInstance.new_button(self, node, callback, params, anim_node)
|
||||
return DruidInstance.create(self, button, node, callback, params, anim_node)
|
||||
end
|
||||
|
||||
|
||||
--- Create blocker basic component
|
||||
-- @function druid:new_blocker
|
||||
-- @tparam args ... blocker init args
|
||||
-- @treturn Component blocker component
|
||||
function Druid.new_blocker(self, ...)
|
||||
return Druid.create(self, blocker, ...)
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node Gui node
|
||||
-- @treturn Blocker blocker component
|
||||
function DruidInstance.new_blocker(self, node)
|
||||
return DruidInstance.create(self, blocker, node)
|
||||
end
|
||||
|
||||
|
||||
--- Create back_handler basic component
|
||||
-- @function druid:new_back_handler
|
||||
-- @tparam args ... back_handler init args
|
||||
-- @treturn Component back_handler component
|
||||
function Druid.new_back_handler(self, ...)
|
||||
return Druid.create(self, back_handler, ...)
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam callback callback On back button
|
||||
-- @tparam[opt] any params Callback argument
|
||||
-- @treturn BackHandler back_handler component
|
||||
function DruidInstance.new_back_handler(self, callback, params)
|
||||
return DruidInstance.create(self, back_handler, callback, params)
|
||||
end
|
||||
|
||||
|
||||
--- Create hover basic component
|
||||
-- @function druid:new_hover
|
||||
-- @tparam args ... hover init args
|
||||
-- @treturn Component hover component
|
||||
function Druid.new_hover(self, ...)
|
||||
return Druid.create(self, hover, ...)
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function on_hover_callback Hover callback
|
||||
-- @treturn Hover hover component
|
||||
function DruidInstance.new_hover(self, node, on_hover_callback)
|
||||
return DruidInstance.create(self, hover, node, on_hover_callback)
|
||||
end
|
||||
|
||||
|
||||
--- Create text basic component
|
||||
-- @function druid:new_text
|
||||
-- @tparam args ... text init args
|
||||
-- @treturn Component text component
|
||||
function Druid.new_text(self, ...)
|
||||
return Druid.create(self, text, ...)
|
||||
end
|
||||
|
||||
|
||||
--- Create lang_text basic component
|
||||
-- @function druid:new_lang_text
|
||||
-- @tparam args ... lang_text init args
|
||||
-- @treturn Component lang_text component
|
||||
function Druid.new_lang_text(self, ...)
|
||||
return Druid.create(self, lang_text, ...)
|
||||
end
|
||||
|
||||
|
||||
--- Create timer basic component
|
||||
-- @function druid:new_timer
|
||||
-- @tparam args ... timer init args
|
||||
-- @treturn Component timer component
|
||||
function Druid.new_timer(self, ...)
|
||||
return Druid.create(self, timer, ...)
|
||||
end
|
||||
|
||||
|
||||
--- Create progress basic component
|
||||
-- @function druid:new_progress
|
||||
-- @tparam args ... progress init args
|
||||
-- @treturn Component progress component
|
||||
function Druid.new_progress(self, ...)
|
||||
return Druid.create(self, progress, ...)
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node Gui text node
|
||||
-- @tparam[opt] string value Initial text. Default value is node text from GUI scene.
|
||||
-- @tparam[opt] bool no_adjust If true, text will be not auto-adjust size
|
||||
-- @treturn Tet text component
|
||||
function DruidInstance.new_text(self, node, value, no_adjust)
|
||||
return DruidInstance.create(self, text, node, value, no_adjust)
|
||||
end
|
||||
|
||||
|
||||
--- Create grid basic component
|
||||
-- @function druid:new_grid
|
||||
-- @tparam args ... grid init args
|
||||
-- @treturn Component grid component
|
||||
function Druid.new_grid(self, ...)
|
||||
return Druid.create(self, grid, ...)
|
||||
-- Deprecated
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node parent The gui node parent, where items will be placed
|
||||
-- @tparam node element Element prefab. Need to get it size
|
||||
-- @tparam[opt=1] number in_row How many nodes in row can be placed
|
||||
-- @treturn StaticGrid grid component
|
||||
function DruidInstance.new_grid(self, parent, element, in_row)
|
||||
helper.deprecated("The druid:new_grid is deprecated. Please use druid:new_static_grid instead")
|
||||
return DruidInstance.create(self, static_grid, parent, element, in_row)
|
||||
end
|
||||
|
||||
|
||||
--- Create static grid basic component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node parent The gui node parent, where items will be placed
|
||||
-- @tparam node element Element prefab. Need to get it size
|
||||
-- @tparam[opt=1] number in_row How many nodes in row can be placed
|
||||
-- @treturn StaticGrid grid component
|
||||
function DruidInstance.new_static_grid(self, parent, element, in_row)
|
||||
return DruidInstance.create(self, static_grid, parent, element, in_row)
|
||||
end
|
||||
|
||||
|
||||
--- Create scroll basic component
|
||||
-- @function druid:new_scroll
|
||||
-- @tparam args ... scroll init args
|
||||
-- @treturn Component scroll component
|
||||
function Druid.new_scroll(self, ...)
|
||||
return Druid.create(self, scroll, ...)
|
||||
end
|
||||
|
||||
|
||||
--- Create slider basic component
|
||||
-- @function druid:new_slider
|
||||
-- @tparam args ... slider init args
|
||||
-- @treturn Component slider component
|
||||
function Druid.new_slider(self, ...)
|
||||
return Druid.create(self, slider, ...)
|
||||
end
|
||||
|
||||
|
||||
--- Create checkbox basic component
|
||||
-- @function druid:new_checkbox
|
||||
-- @tparam args ... checkbox init args
|
||||
-- @treturn Component checkbox component
|
||||
function Druid.new_checkbox(self, ...)
|
||||
return Druid.create(self, checkbox, ...)
|
||||
end
|
||||
|
||||
|
||||
--- Create input basic component
|
||||
-- @function druid:new_input
|
||||
-- @tparam args ... input init args
|
||||
-- @treturn Component input component
|
||||
function Druid.new_input(self, ...)
|
||||
return Druid.create(self, input, ...)
|
||||
end
|
||||
|
||||
|
||||
--- Create checkbox_group basic component
|
||||
-- @function druid:new_checkbox_group
|
||||
-- @tparam args ... checkbox_group init args
|
||||
-- @treturn Component checkbox_group component
|
||||
function Druid.new_checkbox_group(self, ...)
|
||||
return Druid.create(self, checkbox_group, ...)
|
||||
end
|
||||
|
||||
|
||||
--- Create radio_group basic component
|
||||
-- @function druid:new_radio_group
|
||||
-- @tparam args ... radio_group init args
|
||||
-- @treturn Component radio_group component
|
||||
function Druid.new_radio_group(self, ...)
|
||||
return Druid.create(self, radio_group, ...)
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node view_node GUI view scroll node
|
||||
-- @tparam node content_node GUI content scroll node
|
||||
-- @treturn Scroll scroll component
|
||||
function DruidInstance.new_scroll(self, view_node, content_node)
|
||||
return DruidInstance.create(self, scroll, view_node, content_node)
|
||||
end
|
||||
|
||||
|
||||
--- Create swipe basic component
|
||||
-- @function druid:new_swipe
|
||||
-- @tparam args ... swipe init args
|
||||
-- @treturn Component swipe component
|
||||
function Druid.new_swipe(self, ...)
|
||||
return Druid.create(self, swipe, ...)
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function on_swipe_callback Swipe callback for on_swipe_end event
|
||||
-- @treturn Swipe swipe component
|
||||
function DruidInstance.new_swipe(self, node, on_swipe_callback)
|
||||
return DruidInstance.create(self, swipe, node, on_swipe_callback)
|
||||
end
|
||||
|
||||
|
||||
--- Create drag basic component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node GUI node to detect dragging
|
||||
-- @tparam function on_drag_callback Callback for on_drag_event(self, dx, dy)
|
||||
-- @treturn Drag drag component
|
||||
function DruidInstance.new_drag(self, node, on_drag_callback)
|
||||
return DruidInstance.create(self, drag, node, on_drag_callback)
|
||||
end
|
||||
|
||||
|
||||
--- Create dynamic grid component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node parent The gui node parent, where items will be placed
|
||||
-- @treturn DynamicGrid grid component
|
||||
function DruidInstance.new_dynamic_grid(self, parent)
|
||||
-- return helper.extended_component("dynamic_grid")
|
||||
return DruidInstance.create(self, dynamic_grid, parent)
|
||||
end
|
||||
|
||||
|
||||
--- Create lang_text component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node The text node
|
||||
-- @tparam string locale_id Default locale id
|
||||
-- @tparam bool no_adjust If true, will not correct text size
|
||||
-- @treturn LangText lang_text component
|
||||
function DruidInstance.new_lang_text(self, node, locale_id, no_adjust)
|
||||
-- return helper.extended_component("lang_text")
|
||||
return DruidInstance.create(self, lang_text, node, locale_id, no_adjust)
|
||||
end
|
||||
|
||||
|
||||
--- Create slider component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node Gui pin node
|
||||
-- @tparam vector3 end_pos The end position of slider
|
||||
-- @tparam[opt] function callback On slider change callback
|
||||
-- @treturn Slider slider component
|
||||
function DruidInstance.new_slider(self, node, end_pos, callback)
|
||||
-- return helper.extended_component("slider")
|
||||
return DruidInstance.create(self, slider, node, end_pos, callback)
|
||||
end
|
||||
|
||||
|
||||
--- Create checkbox component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node Gui node
|
||||
-- @tparam function callback Checkbox callback
|
||||
-- @tparam[opt=node] node click_node Trigger node, by default equals to node
|
||||
-- @treturn Checkbox checkbox component
|
||||
function DruidInstance.new_checkbox(self, node, callback, click_node)
|
||||
-- return helper.extended_component("checkbox")
|
||||
return DruidInstance.create(self, checkbox, node, callback, click_node)
|
||||
end
|
||||
|
||||
|
||||
--- Create input component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node click_node Button node to enabled input component
|
||||
-- @tparam node text_node Text node what will be changed on user input
|
||||
-- @tparam[opt] number keyboard_type Gui keyboard type for input field
|
||||
-- @treturn Input input component
|
||||
function DruidInstance.new_input(self, click_node, text_node, keyboard_type)
|
||||
-- return helper.extended_component("input")
|
||||
return DruidInstance.create(self, input, click_node, text_node, keyboard_type)
|
||||
end
|
||||
|
||||
|
||||
--- Create checkbox_group component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node[] nodes Array of gui node
|
||||
-- @tparam function callback Checkbox callback
|
||||
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
|
||||
-- @treturn CheckboxGroup checkbox_group component
|
||||
function DruidInstance.new_checkbox_group(self, nodes, callback, click_nodes)
|
||||
-- return helper.extended_component("checkbox_group")
|
||||
return DruidInstance.create(self, checkbox_group, nodes, callback, click_nodes)
|
||||
end
|
||||
|
||||
|
||||
<<<<<<< HEAD
|
||||
--- Create drag basic component
|
||||
-- @function druid:new_drag
|
||||
-- @tparam args ... drag init args
|
||||
@@ -495,3 +544,43 @@ end
|
||||
|
||||
|
||||
return Druid
|
||||
=======
|
||||
--- Create radio_group component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node[] nodes Array of gui node
|
||||
-- @tparam function callback Radio callback
|
||||
-- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes
|
||||
-- @treturn RadioGroup radio_group component
|
||||
function DruidInstance.new_radio_group(self, nodes, callback, click_nodes)
|
||||
-- return helper.extended_component("radio_group")
|
||||
return DruidInstance.create(self, radio_group, nodes, callback, click_nodes)
|
||||
end
|
||||
|
||||
|
||||
--- Create timer component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam node node Gui text node
|
||||
-- @tparam number seconds_from Start timer value in seconds
|
||||
-- @tparam[opt=0] number seconds_to End timer value in seconds
|
||||
-- @tparam[opt] function callback Function on timer end
|
||||
-- @treturn Timer timer component
|
||||
function DruidInstance.new_timer(self, node, seconds_from, seconds_to, callback)
|
||||
-- return helper.extended_component("timer")
|
||||
return DruidInstance.create(self, timer, node, seconds_from, seconds_to, callback)
|
||||
end
|
||||
|
||||
|
||||
--- Create progress component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node Progress bar fill node or node name
|
||||
-- @tparam string key Progress bar direction: const.SIDE.X or const.SIDE.Y
|
||||
-- @tparam[opt=1] number init_value Initial value of progress bar
|
||||
-- @treturn Progress progress component
|
||||
function DruidInstance.new_progress(self, node, key, init_value)
|
||||
-- return helper.extended_component("progress")
|
||||
return DruidInstance.create(self, progress, node, key, init_value)
|
||||
end
|
||||
|
||||
|
||||
return DruidInstance
|
||||
>>>>>>> develop
|
||||
|
Reference in New Issue
Block a user