|
|
|
01-15-2017, 05:29 AM
|
#1
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
LUA : Detection of key press or hold help
Does anyone have any idea ohow to make this, detect if buttun is hold down or just pressed(clicked)? I've tried with different approaches but no luck (time between key presses, counting etc). Is it even possible to do it in Reaper because gfx.getchar() constantly detects is as 0-something (its never stable number)
|
|
|
01-15-2017, 07:30 AM
|
#2
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
If you just call gfx.getchar() it returns any value it wants from the keyboard state. Figure out the key-code of the key you want and pass that to gfx.getchar like so:
Code:
local name, x, y, w, h = "text demo", 200, 200, 200, 200
local D = 100
local char
local function Main()
char = gfx.getchar(D)
if char == 27 or char == -1 then
return 0
else
reaper.defer(Main)
end
gfx.x, gfx.y = 50, 50
gfx.drawstr("char = "..char)
gfx.update()
end
gfx.init(name, x, y, 0, w, h)
Main()
|
|
|
01-15-2017, 08:07 AM
|
#3
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
oh cool thank you! Can you please just help me figure out the logic how to get is the button just pressed or hold down? I know I need reaper.time_precise for it like if the button is pressed more than 1 second it is "hold" anything below is "clicked". I know its easy but I have mental block
|
|
|
01-15-2017, 08:41 AM
|
#4
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
here is my take on it (maybe there is a better way?)
Code:
local name, x, y, w, h = "text demo", 200, 200, 200, 200
last_char = 0
last_time = reaper.time_precise()
function Main()
local currentTime = reaper.time_precise()
char = gfx.getchar(100)
if char ~= last_char then
last_time = currentTime
last_char = char
end
if char == 1 then
press_time = (currentTime - last_time)*10
end
if press_time ~= nil then
if press_time < 1 then
gfx.x, gfx.y = 70, 80
gfx.drawstr("CLICKED")
else
gfx.x, gfx.y = 70, 80
gfx.drawstr("HOLD")
end
end
gfx.x, gfx.y = 50, 50
gfx.drawstr("char = "..char)
gfx.update()
reaper.defer(Main)
end
gfx.init(name, x, y, 0, w, h)
Main()
still problems on first press/click
|
|
|
01-15-2017, 08:43 AM
|
#5
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
You just need an extra variable to track if the key was pressed the previous time you checked; you could use two, one to track if it was pressed and another to keep a time stamp, but it's easier to just use the time stamp as your check. That is, you set the time stamp to nil if the key isn't down, and then use " if time_stamp ~= nil to tell you if it was down last time.
Code:
local name, x, y, w, h = "text demo", 200, 200, 250, 100
local D = 100
local char, char_D, down_time
local function Main()
char = gfx.getchar()
if char == 27 or char == -1 then
return 0
else
reaper.defer(Main)
end
char_D = gfx.getchar(D)
-- Is the key pressed and it wasn't pressed already?
if char_D ~= 0 and not down_time then
-- If yes, note the time
down_time = reaper.time_precise()
elseif char_D == 0 and down_time then
-- Otherwise, make sure our time stamp is cleared
down_time = nil
end
gfx.x, gfx.y = 50, 25
gfx.drawstr("D pressed: "..(tostring(char_D == 1)))
-- Is the key pressed?
if down_time then
-- How long has it been pressed?
local len = reaper.time_precise() - down_time
-- We don't need that many decimal places; let's round it
-- (multiplying and dividing by 10 = 1 decimal, by 100 = 2 decimals, etc)
len = math.floor(len * 100) / 100
gfx.x, gfx.y = 50, 50
gfx.drawstr(len)
if len > 1 then
gfx.x, gfx.y = 50, 75
gfx.drawstr("held")
end
end
gfx.update()
end
gfx.init(name, w, h, 0, x, y)
Main()
|
|
|
01-15-2017, 09:53 AM
|
#6
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Ok now the last piece of the puzzle. How can I make some logical check (it has to be some sort of "wait") to get ONLY click or ONLY hold (right now its always a click followed by hold)
How can I make a "wait" so ;
when button is pressed if "hold" does not show up in 1 second it is considered a click.
so
Code:
If button is pressed
get first state (which is click)
wait 1 second
get second state
if there is second state
MAIN STATE == SECOND STATE (hold)
if there is no second state
MAIN STATE == FIRST STATE (click)
I hope this makes sense. I want to make a script with two behaviors on click and on hold
|
|
|
01-15-2017, 12:42 PM
|
#7
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
Basically you just treat it like mouse clicks, waiting for the button to come back up before you do anything.
Code:
--[[
A demonstration of how to check for specific keypresses,
and/or when a key is being held down
]]--
local name, x, y, w, h = "Keypress demo", 200, 200, 250, 100
-- ASCII code for the letter D
local D = 100
-- Declare our variables beforehand so that they aren't flushed when the script loops
local char, char_D, down_time, held
local function Main()
-- See if the user pressed Escape (27) or closed the window (-1) to quit
char = gfx.getchar()
if char == 27 or char == -1 then
return 0
else
reaper.defer(Main)
end
-- If we want to know a specific key's state, we need to specifically ask for that key
char_D = gfx.getchar(D)
-- Is the key pressed and it wasn't pressed already?
if char_D ~= 0 and not down_time then
-- If yes, note the time
down_time = reaper.time_precise()
-- Was the key down before and now it isn't?
elseif char_D == 0 and down_time then
-- Don't treat it as a click if it was being held
if not held then
-- Put your "on click" function here
gfx.x, gfx.y = 50, 75
gfx.drawstr("clicked!")
end
-- If you *do* want to send a click event when the button is let up
-- from being held, put your function here instead.
held = false
down_time = nil
end
gfx.x, gfx.y = 50, 25
gfx.drawstr("'D' pressed: "..(tostring(char_D == 1)))
-- Is the key pressed?
if down_time then
-- How long has it been pressed?
local len = reaper.time_precise() - down_time
-- We don't need that many decimal places; let's round it
-- (multiplying and dividing by 10 = 1 decimal, by 100 = 2 decimals, etc)
len = math.floor(len * 100) / 100
gfx.x, gfx.y = 50, 50
gfx.drawstr(len)
if len > 1 then
gfx.x, gfx.y = 50, 75
gfx.drawstr("held")
held = true
end
end
gfx.update()
end
gfx.init(name, w, h, 0, x, y)
Main()
|
|
|
01-15-2017, 02:36 PM
|
#8
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Thank you very much! You are an awesome person!
|
|
|
01-16-2017, 02:14 AM
|
#9
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Ok this is the idea "PieMenu" , but I think currently its not possible without a help of devs because of the script does not pass keys some time.
What I thought is to trigger the reaper.defer while we are on hold state (button is held down) but the problem is that when starting the script it does not get the keys few seconds so it cannot get the states. Script gets keys much faster if its clicked in or key is pressed twice, but without it needs 1-2 sec to get the keys so this sticky keys demonstration script above does not work as I've expected.
But the general idea was :
https://stash.reaper.fm/29503/piemenuconcept.lua
just a "concept"
Menu opens on "hacked" hold (you need to hold the key down until counter starts) and actions are activated when shortcut button is released,but clicking part does not work ATM
The further idea was pie to open on hold and what ever action was selected to be quick activated on "click". So for example split item was selected in menu then whenever "clicking" script shortcut again it will trigger split again unless other action was selected in the menu. But that is an easier part , also it would be context sensitive
Its cool as hell! hope something will be done regarding script gettign keys faster
Last edited by Sexan; 01-16-2017 at 03:22 AM.
|
|
|
01-16-2017, 02:33 AM
|
#10
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
regarding script getting pressed key here it is how it looks like when called
here I've just trick it to start defer and when it gets state to end it and move the defer to hold state
Code:
start = 1
local mx, my = reaper.GetMousePosition()
local name, w, h = "Keypress demo", 250, 100
local D = 121
local char, char_D, down_time, held
local function Main()
if start ~= nil then -------------------------------DEFER START
reaper.defer(Main)
end
char_D = gfx.getchar(D)
if char_D ~= 0 and not down_time then
down_time = reaper.time_precise()
end
gfx.x, gfx.y = 50, 25
gfx.drawstr("'Y' pressed: "..(tostring(char_D == 1)))
-- Is the key pressed?
if down_time then
start = nil -------------------------------TERMINATE START
reaper.defer(Main) -------------------------------SWITCH DEFER
--reaper.defer(Main)
-- How long has it been pressed?
local len = reaper.time_precise() - down_time
-- We don't need that many decimal places; let's round it
-- (multiplying and dividing by 10 = 1 decimal, by 100 = 2 decimals, etc)
len = math.floor(len * 100) / 100
gfx.x, gfx.y = 50, 50
gfx.drawstr(len)
if len > 0.15 then
gfx.x, gfx.y = 50, 75
gfx.drawstr("held")
held = true
end
end
-- Was the key down before and now it isn't?
if char_D == 0 and down_time then
-- Don't treat it as a click if it was being held
--reaper.defer(Main)
if not held then
-- Put your "on click" function here
gfx.x, gfx.y = 50, 75
gfx.drawstr("clicked!")
end
-- If you *do* want to send a click event when the button is let up
-- from being held, put your function here instead.
held = false
down_time = nil
end
gfx.update()
end
gfx.init(name, w, h, 0, mx-100, my-100)
Main()
as you can see it needs some time to detect anything
But again it is much faster if shortcut is pressed twice
Last edited by Sexan; 01-16-2017 at 03:19 AM.
|
|
|
01-16-2017, 04:44 AM
|
#11
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Omg I want this sooooo much!!! 200 commands on single shortcut
Devs if you have a tiny space in your big hearts for me regarding this key passing delay...
|
|
|
01-16-2017, 06:16 AM
|
#12
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
I thought about doing something similar ages ago but completely forgot about it. Would be nice.
|
|
|
01-16-2017, 06:21 AM
|
#13
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
I will again need your expertise for creating circle and buttons from it if you have time , will donate for all your help!
|
|
|
01-16-2017, 06:25 AM
|
#14
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
Sure thing.
|
|
|
01-16-2017, 06:27 AM
|
#15
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Something like this , main circle and part of circle above for expanding menu
or something else if you have an better idea,dont know whats the best for space saving and more actions
here is the current version if you need :
https://stash.reaper.fm/29510/PieWIP.lua
|
|
|
01-16-2017, 06:34 AM
|
#16
|
Administrator
Join Date: Mar 2007
Location: NY
Posts: 15,750
|
Quote:
Originally Posted by Sexan
Devs if you have a tiny space in your big hearts for me regarding this key passing delay...
|
Sorry, what's the issue exactly?
|
|
|
01-16-2017, 06:35 AM
|
#17
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
He's seeing a delay, maybe a third of a second, between when he calls gfx.init and when it first responds to his gfx.getchar code. Since the code relies on holding down a key to maintain the window, he ends up having to cheat his reaper.defer calls for a few loops until getchar comes in.
|
|
|
01-16-2017, 06:38 AM
|
#18
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Hi Schwa! The issue is when script starts the pressed key wont get passed while hold down few moments.
I have this script on shortcut Y
And when the script starts the script also looks if Y is pressed. That way the script won't defer .
Right now I've "Hacked" that part to script to be defered whole time until script recognize the button has passed
Post #10 you can see that when script starts after few moments it starts to recognize that key is still pressed
the button is pressed down the whole time
But this script is with "hacked" part in, you can download the code in post #10 to see whats happening
I want to script to defer immediately when started (while the key is still pressed down)
If I remove the "wait" part that should not be there, then the script would start and immediately exit because the key wont pass to script
Last edited by Sexan; 01-16-2017 at 06:47 AM.
|
|
|
01-16-2017, 06:50 AM
|
#19
|
Administrator
Join Date: Mar 2007
Location: NY
Posts: 15,750
|
If you are launching the script on 'Y', that key stroke is processed and removed from the queue -- in general, a script or any program would not want to process a keystroke that occurred before the script launched. The delay is the wait until the system starts sending the repeat keystroke, same as the delay if you are typing text and just hold down a key.
What you want is a new function to detect the keyboard state, rather than processing keyboard input.
|
|
|
01-16-2017, 06:52 AM
|
#20
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Can you give an example of the function?
I've tried everything that crossed my mind and nothing work (and btw as you can see I'm hardcore noob)
Thank you
|
|
|
01-16-2017, 06:54 AM
|
#21
|
Administrator
Join Date: Mar 2007
Location: NY
Posts: 15,750
|
It doesn't exist, reascript has no way to detect the keyboard state separately from the keystroke queue.
|
|
|
01-16-2017, 06:56 AM
|
#22
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Oh, bummer. Anyway thank you for your time!
|
|
|
01-16-2017, 07:34 AM
|
#23
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Well life goes on! I think this will be much easier to do with modified radio boxes and easier to manage if you did not start already with gui.
Last edited by Sexan; 01-16-2017 at 07:40 AM.
|
|
|
01-16-2017, 12:30 PM
|
#24
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
What can I say? It's something to do.
|
|
|
01-16-2017, 12:43 PM
|
#25
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Awesome!!!! On what is based (buttons,checkbox,radiobox?)
I've made two versions,one based on buttons other one on modified radioboxes
|
|
|
01-16-2017, 03:00 PM
|
#26
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
This one's completely from scratch, just to get the design and behavior figured out.
https://github.com/ReaTeam/ReaScript...enu%20demo.lua
I also came up with a way around that awkward keyboard behavior we were discussing this morning:
- While it's in "startup" mode, like you had, it also keeps looking at the keyboard queue to see if there's a key held down.
- Once it sees one, it starts specifically watching that key to keep the window open.
- If it *doesn't* find a key at startup, a timer will automatically close the window. This avoids a problem where, if you just clicked the action key, it would open the window and then stay open until you clicked the button again because startup mode was never turned off.
There's no on-click code yet though. I'd like to have it do this for the submenus, maybe with a different color so you know what level you're in:
|
|
|
01-16-2017, 03:02 PM
|
#27
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Cool! Will check it now! btw smart work around!!
|
|
|
01-16-2017, 10:25 PM
|
#28
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
Updated the link above with a sexier version.
The only stumbling block I've found now is that, if you have the script auto-quit when the user clicks a button, the script immediately gets run again because they're holding still holding down their action key. So, for now at least it has to be "click a button and then let go of the key".
It occurs to me that you could use right-click to enter a "setup" mode, where it would let you click through the menus and assign each button a caption and action ID, saving to ExtStates and all that.
|
|
|
01-17-2017, 01:11 AM
|
#29
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Cool! I would be cool (because I really really like it that way its much faster for me at least) actions to activate on button release (I am talking about sub menus).
Quote:
Originally Posted by Lokasenna
It occurs to me that you could use right-click to enter a "setup" mode, where it would let you click through the menus and assign each button a caption and action ID, saving to ExtStates and all that.
|
That would be awesome for easier management
Last edited by Sexan; 01-17-2017 at 03:47 AM.
|
|
|
01-17-2017, 03:26 AM
|
#30
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
Managed to modify it to my needs ,added few lines at defer exit to catch which menu is clicked and which action is under mouse,works great:
Code:
elseif last_mouse_down then
mnu_clicked = (mouse_mnu - cur_depth + 1) % #mnu_arr
if cur_depth == 0 then
cur_depth = mouse_mnu + 1
----------------------------
cur_menu = mnu_arr[cur_depth] --<----- THIS
----------------------------
--elseif mnu_clicked > 0 then
-- *** Put your "option was clicked" function here ***
-- cur_depth = 0
else
cur_depth = 0
--------------
cur_menu = nil --<----- THIS
--------------
end
last_mouse_down = false
end
Code:
if key_down ~= 0 or (startup and diff < 0.6) then
reaper.defer(Main)
else
if cur_menu then
local cur_mouse_over = (mouse_mnu - cur_depth + 1) % #mnu_arr
if cur_mouse_over ~= 0 then
action = string.match(cur_menu[cur_mouse_over], '%d+')
reaper.Main_OnCommand(action,0)
end
end
return 0
end
Last edited by Sexan; 01-17-2017 at 04:41 AM.
|
|
|
01-17-2017, 03:54 AM
|
#31
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
btw there is a small bug with ONLY one mouse zone, there is a pixel sized area that does not recognize the zone:
other zones are ok
btw I think it is better to not have empty spaces,reason for that is faster workflow. If you set most common used actions to that empty spaces then when you activate main menu you only have to move your mouse little to left-right or up-down:
Last edited by Sexan; 01-17-2017 at 05:15 AM.
|
|
|
01-17-2017, 09:03 AM
|
#32
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,596
|
added action on main buttons (I'm just playing around with ideas):
if you did not enter sub menu and main buttons have action they are triggered :
Code:
-- look if main buttons have actions on them
-- and extract action ID if it exists
action_M = string.match(mnu_arr[mouse_mnu+1][0], '%d+')
-- Draw all of the options
draw_mnu()
Code:
function activate_on_release()
-- in submenu
if cur_menu then
cur_mouse_over = (mouse_mnu - cur_depth + 1) % #mnu_arr --<----- current mouse over
if cur_mouse_over ~= 0 then
action = string.match(cur_menu[cur_mouse_over], '%d+')
reaper.Main_OnCommand(action,0)
end
-- in main menu
else
if action_M then
reaper.Main_OnCommand(action_M,0)
end
end
end
EDIT: One more PIXEL bug
if you lower mouse position by 1 pixel down it activates far right zone (opposite of the left side bug, the same pixel position makes far left side unselectable)
Last edited by Sexan; 01-17-2017 at 09:54 AM.
|
|
|
01-17-2017, 10:24 AM
|
#33
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
The pixel bugs were because of my polar --> cartesian function; it was using y / sin to get the radius, which gives weird values in a few situations. I'll have it updated in a bit once I add the setup mode.
|
|
|
01-19-2017, 09:32 AM
|
#34
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 02:19 PM.
|