I've been playing around with widget Mouse Reclaim (http://widgets.springrts.de/springinfo/index.php#187). This widget assigns actions to mouse thumb buttons (buttons 4 and 5). I finally ended with a completely different widget which is supposed to do the following things:
- pressing and releasing button 4 issues command "repair" if the selected unit can repair, or command "fight" otherwise - pressing and releasing button 5 issues command "reclaim" if the selected unit can reclaim, or "attack" otherwise - pressing and releasing both buttons 4 & 5 issues command "resurrect" if the selected unit can resurrect, or "patrol" otherwise
The source code is as follows:
Code:
function widget:GetInfo() return { name = "Mouse thumbs", desc = "Assign actions to thumb mouse buttons, either when pressed alone or together", author = "DrHash", version = "v1", date = "Sep 15, 2010", license = "GNU GPL, v3 or later", layer = 0, enabled = true, } end
-------------------------------------- --Configuration: modify at your will-- --------------------------------------
local thumbButton1 = 4 local thumbButton2 = 5
local thumb1Command = "Repair" local thumb1AlternativeCommand = "Fight" local thumb2Command = "Reclaim" local thumb2AlternativeCommand = "Attack" local thumbComboCommand = "Resurrect" local thumbComboAlternativeCommand = "Patrol"
--------- --Flags-- ---------
local thumb1Pressed = false local thumb2Pressed = false local bothThumbsHaveBeenPressed = false
------------ --Speedups-- ------------
local SetActiveCommand = Spring.SetActiveCommand local GetActiveCommand = Spring.GetActiveCommand
------------- --Functions-- -------------
--Issue command, if possible; if not, try alternative command function issueCommand(command, alternativeCommand) SetActiveCommand(command) local _, _, _, currentActiveCommand = GetActiveCommand() if (currentActiveCommand == command) then Spring.Echo(command) else SetActiveCommand(alternativeCommand) Spring.Echo(alternativeCommand) end end
-- Just register thumb button presses function widget:MousePress(x, y, button) Spring.Echo("Press " .. button) if (button == thumbButton1) then thumb1Pressed = true bothThumbsHaveBeenPressed = thumb2Pressed Spring.Echo(thumb1Pressed, thumb2Pressed, bothThumbsHaveBeenPressed) return true end if (button == thumbButton2) then thumb2Pressed = true bothThumbsHaveBeenPressed = thumb1Pressed Spring.Echo(thumb1Pressed, thumb2Pressed, bothThumbsHaveBeenPressed) return true end return false end
-- Execute actions upon releasing thumb buttons function widget:MouseRelease(x, y, button) Spring.Echo("Release " .. button) if (button ~= thumbButton1 and button ~= thumbButton2) then -- No thumb buttons released; do nothing here Spring.Echo("Nothing to do") return false end
-- local alt,ctrl,meta,shift = Spring.GetModKeyState()
-- if thumb2 has not been released, then it has been thumb1: thumb1Pressed = false -- otherwise thumb2 has been released instead of thumb1: thumb1 continues to be pressed if it was already pressed thumb1Pressed = (thumb1Pressed and button == thumbButton2) -- same logic applies here but for the other thumb button (exchange numbers 1 and 2) thumb2Pressed = (thumb2Pressed and button == thumbButton1) Spring.Echo(thumb1Pressed, thumb2Pressed, bothThumbsHaveBeenPressed)
if (bothThumbsHaveBeenPressed) then -- Both thumb buttons have been pressed... if (not(thumb1Pressed or thumb2Pressed)) then -- ...and now both have been released: execute thumb-combo action issueCommand(thumbComboCommand, thumbComboAlternativeCommand) bothThumbsHaveBeenPressed = false Spring.Echo(thumb1Pressed, thumb2Pressed, bothThumbsHaveBeenPressed) end -- In case there is one button to release yet, do nothing until then return true end
-- Just one thumb button has been pressed and released; execute corresponding action if (button == thumbButton1) then -- Releasing thumb1 issueCommand(thumb1Command, thumb1AlternativeCommand) else -- Releasing thumb2 issueCommand(thumb2Command, thumb2AlternativeCommand) end return true end
The bottom line: the previous code doesn't work!! It seems Spring has a weird way of informing about mouse button presses and releases, or I didn't understand how functions MousePress and MouseRelease work. I'm sure the mouse buttons are working since presses and releases are properly reported by tool "xev" (under Ubuntu). I've read that within the same widget there must be a couple of functions MousePress and MouseRelease working together, and that MousePress must return true upon a mouse button press so that MouseRelease is called upon releasing that mouse button. Well, I wrote this small code in order to test this behavior:
Code:
function widget:GetInfo() return { name = "Mouse thumb test", desc = "Test press/release events of mouse thumb buttons", author = "DrHash", version = "v1", date = "Sep 15, 2010", license = "GNU GPL, v3 or later", layer = 0, enabled = true, } end
--------------------------------- --Configuration: modify at will-- ---------------------------------
local thumbButton1 = 4 local thumbButton2 = 5
------------- --Functions-- -------------
-- Register thumb button presses function widget:MousePress(x, y, button) Spring.Echo("Press " .. button) if (button == thumbButton1) then return true end if (button == thumbButton2) then return true end return false end
function widget:MouseRelease(x, y, button) Spring.Echo("Release " .. button) if (button == thumbButton1) then return true end if (button == thumbButton2) then return true end return false end
So, pressing and releasing one thumb button produces the corresponding press/release events. However, when I do the following:
press4, press5, release5, release4
the last release is not reported. If I do the following:
press4, press5, release4, release5
again, the last release is not reported. It seems that, whenever pressing several mouse buttons and then releasing them, only the first release is reported and the others act like they never existed. Am I right? Can someone tell me exactly when and what should I return from functions MousePress and MouseRelease? Does MouseRelease even have to return something?
Thanks.
Last edited by DrHash on 15 Sep 2011, 22:23, edited 2 times in total.
Mouserelease has to return true if you don't want any other events to process the action, otherwise, if you want other events to process the action you must return false.
Sometimes other events can interfere, check that no other events in any other widget returns true for the release of mousebutton 5.
Edit: it seems the release event of button 5 never gets called because the release of button 4 already returns true.
Well, assuming that the first button release deletes the second button release, I've written this other version, which seems to work:
Code:
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- -- file: gui_mouse_thumbs.lua -- brief: Assign up to 6 actions to thumb mouse buttons, either when pressed alone or together -- author: DrHash -- version: 1.0 -- -- Copyright (C) 2011. -- Licensed under the terms of the GNU GPL, v3 or later. -- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function widget:GetInfo() return { name = "Mouse thumbs", desc = "Assign up to 6 actions to thumb mouse buttons, either when pressed alone or together", author = "DrHash", version = "v1", date = "Sep 15, 2010", license = "GNU GPL, v3 or later", layer = 0, enabled = true, } end
--------------------------------- --Configuration: modify at will-- ---------------------------------
local thumbButton1 = 4 local thumbButton2 = 5 local thumbCommand1 = "Repair" local thumbAlternativeCommand1 = "Fight" local thumbCommand2 = "Reclaim" local thumbAlternativeCommand2 = "Attack" local thumbComboCommand = "Resurrect" local thumbComboAlternativeCommand = "Patrol"
--------- --Flags-- ---------
local thumbPressed1 = false local thumbPressed2 = false
------------ --Speedups-- ------------
local SetActiveCommand = Spring.SetActiveCommand local GetActiveCommand = Spring.GetActiveCommand
------------- --Functions-- -------------
--Issue command, if possible; if not, try alternative command function issueCommand(command, alternativeCommand) SetActiveCommand(command) local _, _, _, currentActiveCommand = GetActiveCommand() if (currentActiveCommand ~= command) then SetActiveCommand(alternativeCommand) end end
-- Just register thumb button presses function widget:MousePress(x, y, button) if (button == thumbButton1) then thumbPressed1 = true return true end if (button == thumbButton2) then thumbPressed2 = true return true end return false end
function widget:MouseRelease(x, y, button) if (button == thumbButton1) then thumbPressed1 = false if (thumbPressed2) then thumbPressed2 = false -- Second button release is not reported by Spring; assume it takes place issueCommand(thumbComboCommand, thumbComboAlternativeCommand) else issueCommand(thumbCommand1, thumbAlternativeCommand1) end return true elseif (button == thumbButton2) then thumbPressed2 = false if (thumbPressed1) then thumbPressed1 = false -- Second button release is not reported by Spring; assume it takes place issueCommand(thumbComboCommand, thumbComboAlternativeCommand) else issueCommand(thumbCommand2, thumbAlternativeCommand2) end return true else return false end end
Note that you must press and release the buttons in order to send the command; the widget must wait for a possible "dual" press in order to know if it must trigger a single button action or a dual button action.
A cool feature would be to be able to use thumb buttons without having to later press mouse button 1; for instance, just keep pressed one thumb button in order to extend the reclaim, repair or attack circle. When pressing both buttons at once, the reclaim/repair/attack circle would then be replaced by a resurrect circle, and upon releasing the buttons the command would be executed/enqueued. Anyone taking the challenge?
Users browsing this forum: No registered users and 1 guest
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum