--Leeland Kirwan (FatRatKnight)
--I feel this can be handled with better elegance. ... Hey, it works.
--[[
Helps in handling the mouse when TASing a game that uses it. Actually, will
also work while unpaused, if you like doing things that way.
Click anywhere on the game screen. As long as you're holding a mouse button
down, the script will let the new position of your mouse decide what the input
to lsnes will be. Will not actually determine the actual clicks of the
simulated mouse, that's up to your L or R hotkeys.
While a mouse button is held, will also display nifty feedback on what it will
do. Just try it out and see for yourself. Safe to run even if you haven't told
lsnes your movie uses a mouse or two.
]]--
local function Limits(v,l,h) return math.min(h,math.max(l,v)) end
-- Returns v, or l if it's below that, or h if above.
-- No attempt at defining behavior when h < l; Returns h, though.
-- x x y y Mouse Input: Xmouse1, Xmouse2, Ymouse1, Ymouse2
local MI= {0,0,0,0} -- Not elegantly handled when catching user mouse.
local function ClearMI() for i= 1,4 do MI[i]= 0 end end
--*****************************************************************************
function on_input(IsSubframe)
--*****************************************************************************
--Applies input. Makes sure not to try mouse input with no mouse.
--Not currently compliant running over a script that uses on_input.
for port= 1, 2 do -- Whole reason why MI is a table.
if input.port_type(port) == "mouse" then
input.set2(port,0,0,MI[port ])
input.set2(port,0,1,MI[port+2])
end
end
ClearMI()
end
local Mx , My= 0 , 0
local click= false
--*****************************************************************************
local function Str4(num)
--*****************************************************************************
--Just produces a + or - preceeding a three-digit decimal value.
local s= "+"
if num < 0 then s= "-"; num= -num end
return string.format(s .. "%3d", num)
end
local color= 0x00FF00
--*****************************************************************************
local function ShowMouse(port)
--*****************************************************************************
-- For use with on_paint. Needs to know which port to report.
-- Paints coordinates in some top corner, and a visual line for user sanity.
-- Warns if the port isn't a mouse.
local ResX,ResY= gui.resolution()
local X= (ResX-72)*(port-1) -- Paint position
local Dx,Dy= MI[port],MI[port+2] -- Current input to send to lsnes
gui.line(Mx,My,Mx-Dx,My-Dy,color)
gui.crosshair(Mx ,My ,10,gui.rainbow(1,2,color))
gui.crosshair(Mx-Dx,My-Dy,10,gui.rainbow(1,2,color))
color= gui.rainbow(1,12,color)
-- Whoops! Extra color change if both mouse buttons are held. ... Don't care.
gui.text(X,0,string.format("%s:%s",Str4(Dx),Str4(Dy)),0xFFFFFF,0x80000000)
if input.port_type(port) ~= "mouse" then -- Warning.
gui.text(X,16,"No mouse!",0xFF8000,0x80000000)
end
end
OldPaint= on_paint or function() end -- Do not break old display script!
--*****************************************************************************
function on_paint(non_synth)
--*****************************************************************************
OldPaint(non_synth) -- Run old display (or null function)
if clickL then ShowMouse(1) end
if clickR then ShowMouse(2) end
end
local Keys= {} -- Fill with functions to read user input.
--These next two functions track where the mouse is going.
--If the user's mouse has a button held down, will also
--adjust the Mouse Input table accordingly.
--I feel like I've done a sloppy job here. It works, though.
-------------------------------------------------------------------------------
function Keys.mouse_x(key,T) -- Mouse move X.
-------------------------------------------------------------------------------
if clickL then MI[1]= Limits(MI[1] + T.last_rawval - Mx,-127,127) end
if clickR then MI[2]= Limits(MI[2] + T.last_rawval - Mx,-127,127) end
Mx= T.last_rawval
end
-------------------------------------------------------------------------------
function Keys.mouse_y(key,T) -- Mouse move Y.
-------------------------------------------------------------------------------
if clickL then
MI[3]= Limits(MI[3] + T.last_rawval - My,-127,127)
gui.repaint()
end
if clickR then
MI[4]= Limits(MI[4] + T.last_rawval - My,-127,127)
gui.repaint()
end
My= T.last_rawval
end
-------------------------------------------------------------------------------
function Keys.mouse_left(key,T) -- Left mouse button
-------------------------------------------------------------------------------
clickL= (T.last_rawval == 1) -- I want true or false, not 0 or 1.
gui.repaint()
end
-------------------------------------------------------------------------------
function Keys.mouse_right(key,T) -- Right mouse button
-------------------------------------------------------------------------------
clickR= (T.last_rawval == 1) -- Do I need to explain again?
gui.repaint()
end
-------------------------------------------------------------------------------
function Keys.space(key,T) ClearMI(); gui.repaint() end -- Clears mouse input
-------------------------------------------------------------------------------
--Whoops, clears it in both press and release. ... Eh, whatever.
--*****************************************************************************
function on_keyhook(key,T)
--*****************************************************************************
-- Just call the individual key function. Don't ask, just do.
Keys[key](key,T)
end
for k, v in pairs(Keys) do input.keyhook(k,true) end