Forked from
tome / Tales of MajEyal
3508 commits behind the upstream repository.
Mouse.lua 8.27 KiB
-- TE4 - T-Engine 4
-- Copyright (C) 2009 - 2017 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
--- Basic mousepress handler
-- The engine calls receiveMouse when a mouse is clicked
-- @classmod engine.Mouse
module(..., package.seeall, class.make)
function _M:init()
self.areas = {}
self.areas_name = {}
self.status = {}
self.last_pos = { x = 0, y = 0 }
end
function _M:allowDownEvent(v)
self.allow_down = v
end
--- Called when a mouse is pressed
-- @param button
-- @param x coordinate of the click
-- @param y coordinate of the click
-- @param isup true if the key was released, false if pressed
-- @param force_name if not nil only the zone with this name may trigger
-- @param extra
function _M:receiveMouse(button, x, y, isup, force_name, extra)
self.last_pos = { x = x, y = y }
self.status[button] = not isup
if not self.allow_down and not isup then return end
if _M.drag then
if _M.drag.prestart then _M.drag = nil
else return self:endDrag(x, y) end
end
for i = 1, #self.areas do
local m = self.areas[i]
if (not m.mode or m.mode.button) and (x >= m.x1 and x < m.x2 and y >= m.y1 and y < m.y2) and (not force_name or force_name == m.name) then
local r = m.fct(button, x, y, nil, nil, (x-m.x1) / m.scale, (y-m.y1) / m.scale, isup and "button" or "button-down", extra)
if r ~= false then break end
end
end
end
function _M:getPos()
return self.last_pos.x, self.last_pos.y
end
function _M:receiveMouseMotion(button, x, y, xrel, yrel, force_name, extra)
self.last_pos = { x = x, y = y }
if _M.drag then
if _M.drag.on_move then return _M.drag.on_move(_M.drag, button, x, y, xrel, yrel) end
end
local cur_m = nil
for i = 1, #self.areas do
local m = self.areas[i]
if (not m.mode or m.mode.move) and (x >= m.x1 and x < m.x2 and y >= m.y1 and y < m.y2) and (not force_name or force_name == m.name) then
local r = m.fct(button, x, y, xrel, yrel, (x-m.x1) / m.scale, (y-m.y1) / m.scale, "motion", extra)
if r ~= false then
cur_m = m
break
end
end
end
if self.last_m and self.last_m.allow_out_events and self.last_m ~= cur_m then
self.last_m.fct("none", x, y, xrel, yrel, (x-self.last_m.x1) / self.last_m.scale, (y-self.last_m.y1) / self.last_m.scale, "out", extra)
end
self.last_m = cur_m
end
--- Delegate an event from an other mouse handler
-- if self.delegate_offset_x and self.delegate_offset_y are set hey will be used to change the actual coordinates
function _M:delegate(button, mx, my, xrel, yrel, bx, by, event, name, extra)
local ox, oy = (self.delegate_offset_x or 0), (self.delegate_offset_y or 0)
mx = mx - ox
my = my - oy
if event == "button" then self:receiveMouse(button, mx, my, true, name, extra)
elseif event == "button-down" then self:receiveMouse(button, mx, my, false, name, extra)
elseif event == "motion" then self:receiveMouseMotion(button, mx, my, xrel, yrel, name, extra)
end
end
--- Setups as the current game keyhandler
function _M:setCurrent()
core.mouse.set_current_handler(self)
-- if game then game.mouse = self end
_M.current = self
end
--- Returns a zone definition by its name
function _M:getZone(name)
return self.areas_name[name]
end
--- Update a named zone with new coords
-- @return true if the zone was found and updated
function _M:updateZone(name, x, y, w, h, fct, scale)
local m = self.areas_name[name]
if not m then return false end
m.scale = scale or m.scale
m.x1 = x
m.y1 = y
m.x2 = x + w * m.scale
m.y2 = y + h * m.scale
m.fct = fct or m.fct
return true
end
--- Registers a click zone that when clicked will call the object's "onClick" method
function _M:registerZone(x, y, w, h, fct, mode, name, allow_out_events, scale)
scale = scale or 1
local d = {x1=x,y1=y,x2=x+w * scale,y2=y+h * scale, fct=fct, mode=mode, name=name, allow_out_events=allow_out_events, scale=scale}
table.insert(self.areas, 1, d)
if name then self.areas_name[name] = d end
end
function _M:registerZones(t)
for i, z in ipairs(t) do
self:registerZone(z.x, z.y, z.w, z.h, z.fct, z.mode, z.name, z.out_events)
end
end
function _M:unregisterZone(fct)
if type(fct) == "function" then
for i = #self.areas, 1, -1 do
local m = self.areas[i]
if m.fct == fct then local m = table.remove(self.areas, i) if m.name then self.areas_name[m.name] = nil end break end
end
else
for i = #self.areas, 1, -1 do
local m = self.areas[i]
if m.name == fct then local m = table.remove(self.areas, i) if m.name then self.areas_name[m.name] = nil end end
end
end
end
function _M:reset()
self.areas = {}
self.areas_name = {}
end
function _M:startDrag(x, y, cursor, payload, on_done, on_move, no_prestart)
local start = function()
_M.drag.prestart = nil
if _M.drag.cursor then
local w, h = _M.drag.cursor:getSize()
_M.drag.cursor = _M.drag.cursor:glTexture()
core.display.setMouseDrag(_M.drag.cursor, w, h)
end
print("[MOUSE] enabling drag from predrag")
end
if _M.drag then
if _M.drag.prestart and math.max(math.abs(_M.drag.start_x - x), math.abs(_M.drag.start_y - y)) > 6 then
start()
end
return
end
_M.drag = {start_x=x, start_y=y, payload=payload, on_done=on_done, on_move=on_move, prestart=true, cursor=cursor}
print("[MOUSE] pre starting drag'n'drop")
if no_prestart then start() end
end
function _M:endDrag(x, y)
local drag = _M.drag
print("[MOUSE] ending drag'n'drop")
core.display.setMouseDrag(nil, 0, 0)
_M.drag = nil
_M.dragged = drag
_M.current:receiveMouse("drag-end", x, y, true, nil, {drag=drag})
if drag.on_done then drag.on_done(drag, drag.used) end
_M.dragged = nil
end
function _M:usedDrag()
(_M.drag or _M.dragged).used = true
end
--- Called when a touch event is received
-- @param fingerId id of the finger info
-- @param x coordinate of the click (normalized to 0->1)
-- @param y coordinate of the click (normalized to 0->1)
-- @param dx delta coordinate of the click (normalized to 0->1)
-- @param dy delta coordinate of the click (normalized to 0->1)
-- @param pressure
-- @param isup true if the key was released, false if pressed
function _M:receiveTouch(fingerId, x, y, dx, dy, pressure, isup)
-- print("=touch", fingerId, x, y, dx, dy, pressure, isup)
end
--- Called when a touch motion event is received
-- @param fingerId id of the finger info
-- @param x coordinate of the click (normalized to 0->1)
-- @param y coordinate of the click (normalized to 0->1)
-- @param dx delta coordinate of the click (normalized to 0->1)
-- @param dy delta coordinate of the click (normalized to 0->1)
-- @param pressure
function _M:receiveTouchMotion(fingerId, x, y, dx, dy, pressure)
-- print("=touch motion", fingerId, x, y, dx, dy, pressure)
end
--- Called when a touch gesture event is received
-- @param nb_fingers number of fingers
-- @param x coordinate of the click (normalized to 0->1)
-- @param y coordinate of the click (normalized to 0->1)
-- @param d_rot delta rotation
-- @param d_pinch delta pinch
function _M:receiveTouchGesture(nb_fingers, x, y, d_rot, d_pinch)
-- print("=touch gesture", nb_fingers, x, y, d_rot, d_pinch)
end
--- Called when a gamepad axis event is received
-- @param axis id of axis changed
-- @param value current value of the axis, from -1 to 1
function _M:receiveJoyAxis(axis, value)
-- print("=joy axis", axis, value)
end
--- Called when a gamepad ball event is received
-- @param ball id of ball changed
-- @param xrel the relative movement of the ball
-- @param yrel the relative movement of the ball
function _M:receiveJoyBall(ball, xrel, yrel)
-- print("=joy ball", axis, value)
end
--- Called when a gamepad hat event is received
-- @param hat id of the hat changed
-- @param dir current direction of the hat, one of 1,2,3,4,6,7,8,9 (representing direction)
function _M:receiveJoyHat(hat, dir)
-- print("=joy hat", hat, dir)
end