Extension-Druid/druid/components/scrolling_box.lua
2019-03-25 22:38:50 +01:00

242 lines
8.2 KiB
Lua

local M = {}
local druid_input = require "druid.help_modules.druid_input"
local ui_animate = require "druid.help_modules.druid_animate"
M.START = hash("START")
M.FINISH = hash("FINISH")
M.SCROLLING = hash("SCROLLING")
M.INTEREST_MOVE = hash("INTEREST_MOVE")
M.OUT_OF_ZONE_MOVE = hash("OUT_OF_ZONE_MOVE")
M.BACK_TIME = 0.2
M.ANIM_TIME = 0.4
local function callback(instance, event, type, param)
if instance.callback then
instance.callback(instance.parent.parent, event, type, param)
end
end
local function checkSwipeDirection(swipe, action)
swipe.xDistance = math.abs(swipe.endX - swipe.beginX)
swipe.yDistance = math.abs(swipe.endY - swipe.beginY)
if swipe.is_x and swipe.xDistance > swipe.yDistance then
if swipe.beginX > swipe.endX then
swipe.totalSwipeDistanceLeft = swipe.beginX - swipe.endX
if swipe.totalSwipeDistanceLeft > swipe.minSwipeDistance then
swipe.speed.x = action.dx * swipe.speed_up_coef.x * swipe.end_move_coef_x
return true
else
return false
end
else
swipe.totalSwipeDistanceRight = swipe.endX - swipe.beginX
if swipe.totalSwipeDistanceRight > swipe.minSwipeDistance then
swipe.speed.x = action.dx * swipe.speed_up_coef.x * swipe.end_move_coef_x
return true
else
return false
end
end
elseif swipe.is_y and swipe.xDistance < swipe.yDistance then
if swipe.beginY > swipe.endY then
swipe.totalSwipeDistanceUp = swipe.beginY - swipe.endY
if swipe.totalSwipeDistanceUp > swipe.minSwipeDistance then
swipe.speed.y = action.dy * swipe.speed_up_coef.y * swipe.end_move_coef_y
return true
else
return false
end
else
swipe.totalSwipeDistanceDown = swipe.endY - swipe.beginY
if swipe.totalSwipeDistanceDown > swipe.minSwipeDistance then
swipe.speed.y = action.dy * swipe.speed_up_coef.y * swipe.end_move_coef_y
return true
else
return false
end
end
end
end
function lenght(x1, y1, x2, y2)
local a, b = x1 - x2, y1 - y2
return math.sqrt(a * a + b * b)
end
local function back_move(instance)
if not instance.swipe.end_position_x and not instance.swipe.end_position_y then
if instance.points_of_interest then
local min_index, min_lenght = 0, math.huge
local len
for k, v in pairs(instance.points_of_interest) do
len = lenght(instance.pos.x, instance.pos.y, v.x, v.y)
if len < min_lenght then
min_lenght = len
min_index = k
end
end
instance.swipe.speed.x = 0
instance.swipe.speed.y = 0
gui.cancel_animation(instance.node, gui.PROP_POSITION)
instance.swipe.special_move = true
callback(instance, M.START, M.INTEREST_MOVE, instance.points_of_interest[min_index])
gui.animate(instance.node, gui.PROP_POSITION, instance.points_of_interest[min_index],
gui.EASING_LINEAR, M.ANIM_TIME, 0,
function()
instance.swipe.special_move = false
instance.pos.x = instance.points_of_interest[min_index].x
instance.pos.y = instance.points_of_interest[min_index].y
callback(instance, M.FINISH, M.SCROLLING, instance.pos)
callback(instance, M.FINISH, M.INTEREST_MOVE, instance.pos)
end
)
else
callback(instance, M.FINISH, M.SCROLLING, instance.pos)
end
end
if instance.swipe.end_position_x then
local swipe = instance.swipe
swipe.speed.x = 0
instance.pos.x = swipe.end_position_x
swipe.special_move = true
callback(instance, M.START, M.OUT_OF_ZONE_MOVE, instance.pos)
gui.animate(instance.node, ui_animate.PROP_POS_X, swipe.end_position_x, gui.EASING_INSINE, M.BACK_TIME, 0,
function()
swipe.special_move = false
callback(instance, M.FINISH, M.SCROLLING, instance.pos)
callback(instance, M.FINISH, M.OUT_OF_ZONE_MOVE, instance.pos)
end
)
swipe.end_position_x = nil
end
if instance.swipe.end_position_y then
local swipe = instance.swipe
swipe.speed.y = 0
instance.pos.y = swipe.end_position_y
swipe.special_move = true
callback(instance, M.START, M.OUT_OF_ZONE_MOVE, instance.pos)
gui.animate(instance.node, ui_animate.PROP_POS_Y, swipe.end_position_y, gui.EASING_INSINE, M.BACK_TIME, 0,
function()
swipe.special_move = false
callback(instance, M.FINISH, M.SCROLLING, instance.pos)
callback(instance, M.FINISH, M.OUT_OF_ZONE_MOVE, instance.pos)
end
)
swipe.end_position_y = nil
end
end
--- Set text to text field
-- @param action_id - input action id
-- @param action - input action
function M.on_input(instance, action_id, action)
if action_id == druid_input.A_CLICK then
if gui.pick_node(instance.scrolling_zone, action.x, action.y) then
local swipe = instance.swipe
if action.pressed then
swipe.pressed = true
swipe.beginX = action.x
swipe.beginY = action.y
druid_input.is_swipe = false
swipe.end_move_coef_x = 1
elseif not action.released and not action.pressed and not swipe.special_move then
swipe.endX = action.x
swipe.endY = action.y
local before = swipe.is_swipe
swipe.is_swipe = checkSwipeDirection(swipe, action)
if not before and swipe.is_swipe and not swipe.special_move and not swipe.waiting_for_back_move then
callback(instance, M.START, M.SCROLLING, instance.pos)
end
return swipe.is_swipe or swipe.special_move
elseif action.released then
swipe.beginX = 0
swipe.beginY = 0
swipe.endX = 0
swipe.endY = 0
swipe.pressed = false
if swipe.waiting_for_back_move then
back_move(instance)
swipe.waiting_for_back_move = false
end
return swipe.is_swipe or swipe.special_move
end
elseif action.released then
instance.swipe.pressed = false
if instance.swipe.waiting_for_back_move then
back_move(instance)
instance.swipe.waiting_for_back_move = false
end
end
end
end
--- Called when update
-- @param dt - delta time
function M.on_updated(instance, dt)
if instance.swipe.speed.x ~= 0 or instance.swipe.speed.y ~= 0 then
local swipe = instance.swipe
instance.pos.x = instance.pos.x + swipe.speed.x
instance.pos.y = instance.pos.y + swipe.speed.y
if instance.pos.x < instance.start_pos.x then
swipe.end_move_coef_x = swipe.back_slow_coef
swipe.end_position_x = instance.start_pos.x
elseif instance.pos.x > instance.maximum.x then
swipe.end_move_coef_x = swipe.back_slow_coef
swipe.end_position_x = instance.maximum.x
else
swipe.end_move_coef_x = 1
swipe.end_position_x = nil
end
if instance.pos.y < instance.start_pos.y then
swipe.end_move_coef_y = swipe.back_slow_coef
swipe.end_position_y = instance.start_pos.y
elseif instance.pos.y > instance.maximum.y then
swipe.end_move_coef_y = swipe.back_slow_coef
swipe.end_position_y = instance.maximum.y
else
swipe.end_move_coef_y = 1
swipe.end_position_y = nil
end
gui.set_position(instance.node, instance.pos)
swipe.speed.x = swipe.speed.x / swipe.speed_down_coef * swipe.end_move_coef_x
swipe.speed.y = swipe.speed.y / swipe.speed_down_coef * swipe.end_move_coef_y
if swipe.speed.x < swipe.min_speed and swipe.speed.x > - swipe.min_speed then
swipe.speed.x = 0
if not swipe.pressed then
back_move(instance)
else
swipe.waiting_for_back_move = true
end
if swipe.speed.y < swipe.min_speed and swipe.speed.y > - swipe.min_speed then
swipe.speed.y = 0
end
if swipe.speed.y == 0 and swipe.speed.x == 0 then
swipe.is_swipe = false
end
end
end
end
--- Scroll position to
-- @param pos - positon for set
-- @param is_animate - is animated set
function M.scroll_to(instance, pos, is_animate, cb, time_scrolling)
local time = is_animate and M.ANIM_TIME or 0
time = time_scrolling or time
instance.pos.x = pos.x
instance.pos.y = pos.y
gui.animate(instance.node, gui.PROP_POSITION, instance.pos, gui.EASING_INSINE, time, 0,
function()
if cb then
cb(instance.parent.parent)
end
end
)
end
return M