Merge branch 'develop' into feature/D16-checkbox

This commit is contained in:
Maxim Tuprikov
2019-09-28 17:14:12 +03:00
committed by GitHub
21 changed files with 799 additions and 162 deletions

View File

@@ -1,27 +0,0 @@
local data = require("druid.data")
local M = {}
M.interest = {
data.ON_INPUT
}
function M.init(self, callback, params)
self.event = data.A_ANDR_BACK
self.callback = callback
self.params = params
end
--- input handler
-- @param action_id - input action id
-- @param action - input action
function M.on_input(self, action_id, action)
if action[data.RELEASED] then
self.callback(self.parent.parent, self.params)
end
return true
end
return M

View File

@@ -0,0 +1,34 @@
--- Component to handle back key
-- @module base.back_handler
local const = require("druid.const")
local M = {}
M.interest = {
const.ON_INPUT
}
--- Component init function
-- @tparam table self component instance
-- @tparam callback callback on back button
-- @tparam[opt] params callback argument
function M.init(self, callback, params)
self.event = const.ACTION_BACK
self.callback = callback
self.params = params
end
--- Input handler for component
-- @tparam string action_id on_input action id
-- @tparam table action on_input action
function M.on_input(self, action_id, action)
if action[const.RELEASED] then
self.callback(self.parent.parent, self.params)
end
return true
end
return M

33
druid/base/blocker.lua Normal file
View File

@@ -0,0 +1,33 @@
--- Component to block input on specify zone (node)
-- @module base.blocker
local const = require("druid.const")
local helper = require("druid.helper")
local M = {}
M.interest = {
const.ON_SWIPE
}
function M.init(self, node)
self.node = helper.get_node(node)
self.event = const.ACTION_TOUCH
end
function M.on_input(self, action_id, action)
if not helper.is_enabled(self.node) then
return false
end
if gui.pick_node(self.node, action.x, action.y) then
return true
end
return false
end
return M

View File

@@ -1,4 +1,11 @@
local data = require("druid.data")
--- Component to handle basic GUI button
-- @module base.button
-- TODO: Add button mode:
-- Long tap
-- Repeated tap
local const = require("druid.const")
local ui_animate = require("druid.helper.druid_animate")
local settings = require("druid.settings")
local helper = require("druid.helper")
@@ -6,18 +13,18 @@ local b_settings = settings.button
local M = {}
M.interest = {
data.ON_INPUT
const.ON_INPUT
}
M.DEFAULT_DEACTIVATE_COLOR = vmath.vector4(0, 0, 0, 0)
M.DEFAULT_DEACTIVATE_SCALE = vmath.vector3(0.8, 0.9, 1)
M.DEFAULT_ACTIVATE_SCALE = vmath.vector3(1, 1, 1)
M.DEFAUL_ACTIVATION_TIME = 0.2
M.DEFAULT_ACTIVATION_TIME = 0.2
function M.init(self, node, callback, params, anim_node, event)
self.node = helper.get_node(node)
self.event = data.A_TOUCH
self.event = const.ACTION_TOUCH
self.anim_node = anim_node and helper.get_node(anim_node) or self.node
self.scale_from = gui.get_scale(self.anim_node)
self.scale_to = self.scale_from + b_settings.SCALE_CHANGE
@@ -30,14 +37,23 @@ function M.init(self, node, callback, params, anim_node, event)
self.hover_anim = b_settings.IS_HOVER
self.sound = b_settings.BTN_SOUND
self.sound_disable = b_settings.BTN_SOUND_DISABLED
self.ext_zone = nil
self.click_zone = nil
-- TODO: to separate component "block_input"?
-- If callback is nil, so the buttons is stub and without anim
-- Used for zones, what should dont pass the input to other UI elements
if not callback then
self.stub = true
self.hover_anim = false
self.callback = function() end
end
end
local function set_hover(self, state)
if self.hover_anim and self._is_hovered ~= state then
local target_scale = state and self.scale_hover_to or self.scale_from
ui_animate.scale(self, self.node, target_scale, b_settings.HOVER_TIME)
ui_animate.scale(self, self.anim_node, target_scale, b_settings.HOVER_TIME)
self._is_hovered = state
end
end
@@ -47,15 +63,17 @@ local function on_button_release(self)
if not self.disabled then
if not self.stub and self.can_action then
self.can_action = false
self.tap_anim(self)
settings.play_sound(self.sound)
if self.tap_anim then
self.tap_anim(self)
end
self.callback(self.parent.parent, self.params, self)
settings.play_sound(self.sound)
else
set_hover(self, false)
end
return true
else
self.sound_disable()
settings.play_sound(self.sound_disable)
return false
end
end
@@ -70,30 +88,32 @@ function M.on_input(self, action_id, action)
end
local is_pick = gui.pick_node(self.node, action.x, action.y)
if self.ext_zone then
is_pick = is_pick and gui.pick_node(self.ext_zone, action.x, action.y)
if self.click_zone then
is_pick = is_pick and gui.pick_node(self.click_zone, action.x, action.y)
end
if is_pick then
if action.pressed then
-- Can interact if start touch on the button
self.can_action = true
return true
end
if action.released then
set_hover(self, false)
return on_button_release(self)
else
set_hover(self, true)
end
return not self.disabled
else
if not is_pick then
-- Can't interact, if touch outside of button
self.can_action = false
set_hover(self, false)
return false
end
if action.pressed then
-- Can interact if start touch on the button
self.can_action = true
self.repeated_counter = 0
return true
end
if action.released then
set_hover(self, false)
return on_button_release(self)
else
set_hover(self, true)
end
return not self.disabled
end
@@ -123,21 +143,21 @@ end
function M.deactivate(self, is_animate, callback)
self.disabled = true
if is_animate then
local counter = 0
local clbk = function()
counter = counter + 1
if counter == 3 and callback then
-- callback call three times in gui.animation
local clbk = helper.after(3, function()
if callback then
callback(self.parent.parent)
end
end
end)
ui_animate.color(self, self.node, M.DEFAULT_DEACTIVATE_COLOR,
clbk, M.DEFAUL_ACTIVATION_TIME, 0, gui.EASING_OUTBOUNCE)
clbk, M.DEFAULT_ACTIVATION_TIME, 0, gui.EASING_OUTBOUNCE)
ui_animate.scale_y_from_to(self, self.node, M.DEFAULT_ACTIVATE_SCALE.x,
M.DEFAULT_DEACTIVATE_SCALE.x, clbk, M.DEFAUL_ACTIVATION_TIME, gui.EASING_OUTBOUNCE)
M.DEFAULT_DEACTIVATE_SCALE.x, clbk, M.DEFAULT_ACTIVATION_TIME, gui.EASING_OUTBOUNCE)
ui_animate.scale_x_from_to(self, self.node, M.DEFAULT_ACTIVATE_SCALE.y,
M.DEFAULT_DEACTIVATE_SCALE.y, clbk, M.DEFAUL_ACTIVATION_TIME, gui.EASING_OUTBOUNCE)
M.DEFAULT_DEACTIVATE_SCALE.y, clbk, M.DEFAULT_ACTIVATION_TIME, gui.EASING_OUTBOUNCE)
else
gui.set_color(self.node, M.DEFAULT_DEACTIVATE_COLOR)
gui.set_scale(self.node, M.DEFAULT_DEACTIVATE_SCALE)
@@ -150,24 +170,22 @@ end
function M.activate(self, is_animate, callback)
if is_animate then
local counter = 0
local clbk = function()
counter = counter + 1
if counter == 3 then
-- callback call three times in gui.animation
local clbk = helper.after(3, function()
self.disabled = false
if callback then
callback(self.parent.parent)
end
end
end
end)
ui_animate.color(self, self.node, ui_animate.TINT_SHOW,
clbk, M.DEFAUL_ACTIVATION_TIME, 0, gui.EASING_OUTBOUNCE)
clbk, M.DEFAULT_ACTIVATION_TIME, 0, gui.EASING_OUTBOUNCE)
ui_animate.scale_y_from_to(self, self.node, M.DEFAULT_DEACTIVATE_SCALE.x,
M.DEFAULT_ACTIVATE_SCALE.x, clbk, M.DEFAUL_ACTIVATION_TIME, gui.EASING_OUTBOUNCE)
M.DEFAULT_ACTIVATE_SCALE.x, clbk, M.DEFAULT_ACTIVATION_TIME, gui.EASING_OUTBOUNCE)
ui_animate.scale_x_from_to(self, self.node, M.DEFAULT_DEACTIVATE_SCALE.y,
M.DEFAULT_ACTIVATE_SCALE.y, clbk, M.DEFAUL_ACTIVATION_TIME, gui.EASING_OUTBOUNCE)
M.DEFAULT_ACTIVATE_SCALE.y, clbk, M.DEFAULT_ACTIVATION_TIME, gui.EASING_OUTBOUNCE)
else
gui.set_color(self.node, ui_animate.TINT_SHOW)
gui.set_scale(self.node, M.DEFAULT_ACTIVATE_SCALE)
@@ -178,11 +196,19 @@ function M.activate(self, is_animate, callback)
end
end
--- Set additional node, what need to be clicked on button click
-- Used, if need setup, what button can be clicked only in special zone
function M.set_ext_zone(self, zone)
self.ext_zone = helper.get_node(zone)
function M.disable_animation(self)
self.hover_anim = false
self.tap_anim = nil
self.back_anim = nil
end
return M
--- Set additional node, what need to be clicked on button click
-- Used, if need setup, what button can be clicked only in special zone
function M.set_click_zone(self, zone)
self.click_zone = helper.get_node(zone)
end
return M

View File

@@ -1,11 +1,11 @@
--- Component to handle placing components by row and columns.
-- Grid can anchor your elements, get content size and other
-- @module base.grid
local helper = require("druid.helper")
local M = {}
--- Sort and placing nodes
-- Plans: placing by max width, placing with max in_row
-- Allow different node sizes, allow animation with node insert
function M.init(self, parent, element, in_row)
self.parent = helper.get_node(parent)
@@ -111,4 +111,4 @@ function M.clear(self)
end
return M
return M

View File

@@ -1,4 +1,7 @@
local data = require("druid.data")
--- Component to handle progress bars
-- @module base.progress
local const = require("druid.const")
local helper = require("druid.helper")
local settings = require("druid.settings")
local p_settings = settings.progress
@@ -6,7 +9,7 @@ local p_settings = settings.progress
local M = {}
M.interest = {
data.ON_UPDATE,
const.ON_UPDATE,
}
local PROP_Y = "y"
@@ -147,4 +150,4 @@ function M.update(self, dt)
end
return M
return M

View File

@@ -1,5 +1,8 @@
--- Component to handle scroll content
-- @module base.scroll
local helper = require("druid.helper")
local data = require("druid.data")
local const = require("druid.const")
local settings = require("druid.settings").scroll
local M = {}
@@ -8,8 +11,8 @@ local SIDE_X = "x"
local SIDE_Y = "y"
M.interest = {
data.ON_UPDATE,
data.ON_SWIPE,
const.ON_UPDATE,
const.ON_SWIPE,
}
-- Global on all scrolls
@@ -99,10 +102,7 @@ end
local function get_zone_center(self)
local pos = vmath.vector3(self.pos)
pos.x = pos.x + self.center_offset.x
pos.y = pos.y + self.center_offset.y
return pos
return self.pos + self.center_offset
end
@@ -257,7 +257,7 @@ end
function M.on_input(self, action_id, action)
if action_id ~= data.A_TOUCH then
if action_id ~= const.ACTION_TOUCH then
return false
end
local inp = self.input
@@ -289,18 +289,21 @@ function M.on_input(self, action_id, action)
M.current_scroll = self
end
end
if M.current_scroll == self then
add_delta(self, action.dx, action.dy)
result = true
end
end
end
if inp.touch and not action.pressed then
if M.current_scroll == self then
add_delta(self, action.dx, action.dy)
result = true
end
end
if action.released then
inp.touch = false
inp.side = false
if M.current_scroll == self then
M.current_scroll = nil
inp.touch = false
inp.side = false
result = true
end
check_threshold(self)
@@ -310,8 +313,12 @@ function M.on_input(self, action_id, action)
end
--- Start scroll to point (x, y, z)
function M.scroll_to(self, point)
--- Start scroll to target point
-- @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.border
local target = vmath.vector3(point)
target.x = helper.clamp(point.x - self.center_offset.x, b.x, b.z)
@@ -319,12 +326,18 @@ function M.scroll_to(self, point)
cancel_animate(self)
self.animate = true
gui.animate(self.node, gui.PROP_POSITION, target, gui.EASING_OUTSINE, settings.ANIM_SPEED, 0, function()
self.animate = false
self.animate = not is_instant
if is_instant then
self.target = target
set_pos(self, target)
end)
else
gui.animate(self.node, gui.PROP_POSITION, target, gui.EASING_OUTSINE, settings.ANIM_SPEED, 0, function()
self.animate = false
self.target = target
set_pos(self, target)
end)
end
end
@@ -384,4 +397,4 @@ function M.set_border(self, border)
end
return M
return M

93
druid/base/slider.lua Normal file
View File

@@ -0,0 +1,93 @@
--- Druid slider component
-- @module base.slider
local helper = require("druid.helper")
local const = require("druid.const")
local M = {}
M.interest = {
const.ON_SWIPE
}
local function on_change_value(self)
if self.callback then
self.callback(self.parent.parent, self.value)
end
end
function M.init(self, node, end_pos, callback)
self.node = helper.get_node(node)
self.start_pos = gui.get_position(self.node)
self.pos = gui.get_position(self.node)
self.target_pos = self.pos
self.end_pos = end_pos
self.dist = self.end_pos - self.start_pos
self.is_drag = false
self.value = 0
self.callback = callback
assert(self.dist.x == 0 or self.dist.y == 0, "Slider for now can be only vertical or horizontal")
end
function M.on_input(self, action_id, action)
if action_id ~= const.ACTION_TOUCH then
return false
end
if gui.pick_node(self.node, action.x, action.y) then
if action.pressed then
self.pos = gui.get_position(self.node)
self.is_drag = true
end
end
if self.is_drag and not action.pressed then
-- move
self.pos.x = self.pos.x + action.dx
self.pos.y = self.pos.y + action.dy
local prev_x = self.target_pos.x
local prev_y = self.target_pos.y
self.target_pos.x = helper.clamp(self.pos.x, self.start_pos.x, self.end_pos.x)
self.target_pos.y = helper.clamp(self.pos.y, self.start_pos.y, self.end_pos.y)
gui.set_position(self.node, self.target_pos)
if prev_x ~= self.target_pos.x or prev_y ~= self.target_pos.y then
if self.dist.x > 0 then
self.value = (self.target_pos.x - self.start_pos.x) / self.dist.x
end
if self.dist.y > 0 then
self.value = (self.target_pos.y - self.start_pos.y) / self.dist.y
end
on_change_value(self)
end
end
if action.released then
self.is_drag = false
end
return self.is_drag
end
function M.set(self, value)
value = helper.clamp(value, 0, 1)
gui.set_position(self.node, self.start_pos + self.dist * value)
self.value = value
on_change_value(self)
end
return M

View File

@@ -1,10 +1,14 @@
local data = require("druid.data")
--- Component to handle all GUI texts
-- Good working with localization system
-- @module base.text
local const = require("druid.const")
local settings = require("druid.settings")
local helper = require("druid.helper")
local M = {}
M.interest = {
data.ON_CHANGE_LANGUAGE,
const.ON_CHANGE_LANGUAGE,
}
@@ -81,4 +85,4 @@ function M.set_scale(self, scale)
end
return M
return M

View File

@@ -1,14 +1,18 @@
local data = require("druid.data")
--- Component to handle GUI timers
-- @module base.timer
local const = require("druid.const")
local formats = require("druid.helper.formats")
local helper = require("druid.helper")
local M = {}
M.interest = {
data.ON_UPDATE
const.ON_UPDATE
}
local empty = function() end
function M.init(self, node, seconds_from, seconds_to, callback)
self.node = helper.get_node(node)
seconds_from = math.max(seconds_from, 0)