|
|
|
05-12-2019, 08:00 AM
|
#481
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
I am not quite sure what you are trying to do, but these lines may be problematic:
In these, only the tiny 1-pixel corner of merge_bm is composited and stretched onto trackview, so the (track_window, cursor.x , cursor.y, W, H, merge_bm, 0, 0, 1, 1) should probably be (track_window, cursor.x , cursor.y, 5000, 5000, merge_bm, 0, 0, 5000, 5000):
Code:
local merge_bm = reaper.JS_LICE_CreateBitmap(true, 5000, 5000)
reaper.JS_Composite(track_window, cursor.x , cursor.y, W, H, merge_bm, 0, 0, 1, 1)
end
In these lines, the FillRect is drawn far outside the boundaries of the bitmap, which is only 1 pixel wide, so nothing will happen:
Code:
local item_bm[i]= reaper.JS_LICE_CreateBitmap(true, 1, 1)
reaper.JS_LICE_FillRect(item_bm[i], item.x , item.y, item.w, item.h, 0x66557788, 1, "COPY" ) -- MAKE ITEM RECTANGLE
|
|
|
05-12-2019, 08:16 AM
|
#482
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Instead of calling JS_Composite for every item in AS for example:
If there are 16 items JS_Composite will be called 16 times in loop, so if there are more items it will call it X times.
What I want is to minimize that and cpu usage and flickering (more items it has the flickering get more noticeable since it is looping it x times):
Build all items rectangles into one single image and then compose ONLY that one:
this is what I do atm:
Code:
for i = 1, x do
item_bm = reaper.JS_LICE_CreateBitmap() -- create bitmap for item
reaper.JS_Composite(item_bm) -- draw what bitmap
end
what I want is:
Code:
final_image = reaper.JS_LICE_CreateBitmap() -- bitmap where all the rectangles of all items will be
for i = 1, x do
item_bm = reaper.JS_LICE_CreateBitmap() -- create bitmap for item
reaper.JS_LICE_FillRect(item_bg) --fill that bitmap with rectangle
reaper.JS_LICE_Blit(final_bm, item_bm) -- copy item bitmap to final image
end
reaper.JS_Composite(final_bg) -- draw the final bitmap with all rectangles of all items, CALL IT ONLY ONCE
Since I'm still pretty bad with blitting, code above copies item_bm to final_mb?
this is the code I'm using now
Code:
local i_y, i_h, i_b = A[tostring(atrack)].t + t_h, A[tostring(atrack)].h + t_h, A[tostring(atrack)].b + t_h
if not items_bm[i] then items_bm[i] = {} end
for j = 1, #active_as.tracks[i].items do
local item = active_as.tracks[i].items[j]
if items_bm[i][j] == nil then items_bm[i][j] = reaper.JS_LICE_CreateBitmap(true, 1, 1); reaper.JS_LICE_Clear(items_bm[i][j], 0x66557788) end
local new_item_start, new_item_lenght = as_item_position(item, active_as.sel_start, active_as.sel_end, mouse_time_pos)
reaper.JS_Composite(track_window, math.floor(new_item_start * zoom_lvl) - Arr_pixel, (i_y - y_view_start), math.floor(new_item_lenght * zoom_lvl), i_b - i_y, items_bm[i][j], 0, 0, 1, 1)
end
The code is available on my git,WIP folder draw_item_shadow() function so you can see what it does, just make selection over items
Last edited by Sexan; 05-12-2019 at 08:23 AM.
|
|
|
05-12-2019, 08:31 AM
|
#483
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by Sexan
Instead of calling JS_Composite for every item in AS for example:
If there are 16 items JS_Composite will be called 16 times in loop, so if there are more items it will call it X times.
|
This is indeed possible, and easy. Simply draw new FillRects on the large bitmap, instead of creating new bitmaps:
Code:
bitmap = reaper.JS_LICE_CreateBitmap(true, 5000, 5000) -- bitmap where all the rectangles of all items will be
reaper.JS_Composite(trackview, 0, 0, 5000, 5000, bitmap, 0, 0, 5000, 5000) -- CALL IT ONLY ONCE
-- Whenever the mouse cursor position changes:
reaper.JS_LICE_Clear(bitmap, 0) -- CLEAR PREVIOUS FILLRECTS
for i = 1, totalNumberOfAreas do
reaper.JS_LICE_FillRect(bitmap, area[i].x, area[i].y, area[i].w, area[i].h, someColor, 1, "COPY")
-- DRAW SHADOWS AND OTHER LINES
end
I'm not sure that there will be less flicker (on WindowsOS), unfortunately. Fewer blitting function calls, but more pixels blitted in total.
|
|
|
05-12-2019, 08:47 AM
|
#484
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Thank you very much, as for capturing part of the screen (capture item real images from reapers screen) I need to use GDI and bitmap_dc?
|
|
|
05-12-2019, 09:13 AM
|
#485
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Yes: GDI_Blit is the link between the screen and LICE *sys*bitmaps.
(Under the hood, the Composite functions also use GDI blitting to copy the bitmaps onto the screen.)
If you would like to display "ghosts" of the contents of the AS while the user is mouse-dragging, you can use GDI blit to save each of the AS areas as a LICE bitmap, and then LICE_ScaledBlit to copy them onto the large bitmap discussed above (scaled to the height of the target track or envelope lane), or Composite each individually to the trackview.
|
|
|
05-12-2019, 09:32 AM
|
#486
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Can you give me please short code example.... I'm getting white color only ...sorry this gdi/blitting/lice stuff is too much for my brain
|
|
|
05-12-2019, 11:42 AM
|
#487
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 10,088
|
Quote:
Originally Posted by sexan
sorry this gdi/blitting/lice stuff is too much for my brain
|
You are way ahead of any other scripter on this topic ^^
|
|
|
05-12-2019, 02:34 PM
|
#488
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by Sexan
Can you give me please short code example.... I'm getting white color only ...sorry this gdi/blitting/lice stuff is too much for my brain
|
Here are examples for both options that I mentioned above.
While writing the examples, I realized that REAPER's windows (on WindowsOS, at least) don't have alpha information, which causes weirdness when trying blit them to and from LICE bitmaps that do use alpha. However, if you *first* blit a transparent bitmap onto the window, then suddenly that area does gain alpha info.
I will update the extension with new functions to change the alpha values of LICE bitmaps.
In the meantime, this example uses GDI_Blit to first copy a transparent rectangle onto the Area Select area, before copying it to the mouse position. (In you Area51 code, the AS areas will in any case already have transparent overlays.)
Code:
main = reaper.GetMainHwnd()
trackview = reaper.JS_Window_FindChildByID(main, 1000)
tvDC = reaper.JS_GDI_GetWindowDC(trackview)
-- JUST A QUICK HACK TO GET ALL TRACK Y COORDINATES, TO DEMONSTRATE SCALED BLIT
sOK, topVisiblePixel, pageSize, min, max, trackPos = reaper.JS_Window_GetScrollInfo(trackview, "VERT")
tvOK, tvLeft, tvTop, tvRight, tvBottom = reaper.JS_Window_GetRect(trackview)
bottomPixel = -topVisiblePixel
tT = {} -- TABLE OF TRACK INFO
if reaper.GetMasterTrackVisibility()&1 == 1 then
track = reaper.GetMasterTrack(0)
tT[track] = {top = bottomPixel}
bottomPixel = bottomPixel + reaper.GetMediaTrackInfo_Value(track, "I_WNDH") + 5
tT[track].bottom = bottomPixel
end
for t = 0, reaper.CountTracks(0)-1 do
track = reaper.GetTrack(0, t)
tT[track] = {top = bottomPixel}
bottomPixel = bottomPixel + reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
tT[track].bottom = bottomPixel
end
-- UNLINK PREVIOUS BITMAPS
OK, list = reaper.JS_Composite_ListBitmaps(trackview)
for a in list:gmatch("[^,]+") do
reaper.JS_Composite_Unlink(trackview, reaper.JS_Window_HandleFromAddress(a))
end
-- LET'S ASSUME THERE IS ONE AREA SELECT ON TRACK 0, WITH WIDTH 200 PIXELS. DRAW THIS RECTANGLE ON SCREEN
-- !!! REAPER'S WINDOWS DON'T HAVE ALPHA INFO PER DEFAULT. THIS BLIT WILL PROVIDE THEM WITH ALPHA INFO !!!
bm1 = reaper.JS_LICE_CreateBitmap(true, 1, 1)
bm1DC = reaper.JS_LICE_GetDC(bm1)
reaper.JS_LICE_Clear(bm1, 0x40400000)
sourceTrack = reaper.GetTrack(0, 0)
sourceHeight = tT[sourceTrack].bottom-tT[sourceTrack].top
ASWidth = 200
reaper.JS_GDI_StretchBlit(tvDC, 0, tT[sourceTrack].top, ASWidth, sourceHeight, bm1DC, 0, 0, 1, 1, "ALPHA")
-- NOW FOR DEMONSTRATING COPYING GHOSTS TO MOUSE POSITION
-- COPY AREA SELECT CONTENTS TO A LICE BITMAP
ghost1 = reaper.JS_LICE_CreateBitmap(true, ASWidth, sourceHeight)
reaper.JS_LICE_Clear(ghost1, 0)
ghost1DC = reaper.JS_LICE_GetDC(ghost1)
reaper.JS_GDI_Blit(ghost1DC, 0, 0, tvDC, 0, tT[sourceTrack].top, ASWidth, sourceHeight)
--pix = string.format("%x", reaper.JS_LICE_GetPixel(ghost1, 20, 20)&0xffffffff)
-- OPTION 1: COMPOSITE EACH AREA SELECT SUB-AREA SEPARATELY
--[[
function loop()
if reaper.JS_Mouse_GetState(1) ~= 1 then -- QUIT WHEN LEFT-CLICK
x, y = reaper.GetMousePosition()
if x ~= prevX or y ~= prevY then
prevX, prevY = x, y
track = reaper.GetTrackFromPoint(x, y)
if track then
x, y = x-tvLeft, y-tvRight -- CONVERT TO RELATIVE CLIENT COORDINATES
reaper.JS_Composite(trackview, x, tT[track].top, ASWidth, tT[track].bottom-tT[track].top, ghost1, 0, 0, ASWidth, sourceHeight) -- STRETCH TO FIT TARGET TRACK
reaper.JS_Window_InvalidateRect(trackview, 0, 0, 1, 1, true) -- INVALIDATE COORDINATES DON'T MATTER FOR COMPOSITE: COMPOSITE WILL UPDATE ENTIRE WINDOW
end
end
reaper.defer(loop)
end
end
]]
-- OPTION 2: USE SINGLE LARGE CANVAS
--
canvas = reaper.JS_LICE_CreateBitmap(true, 5000, 5000) -- LARGE ENOUGH TO COVER ENTIRE TRACKVIEW
cOK = reaper.JS_Composite(trackview, 0, 0, 5000, 5000, canvas, 0, 0, 5000, 5000) -- I DON'T THINK IT MATTERS IF THE COMPOSITE SIZES ARE LARGER THAN THE ACTUAL WINDOWS
function loop()
if reaper.JS_Mouse_GetState(1) ~= 1 then -- QUIT WHEN LEFT-CLICK
x, y = reaper.GetMousePosition()
if x ~= prevX or y ~= prevY then
prevX, prevY = x, y
track = reaper.GetTrackFromPoint(x, y)
if track then
x, y = x-tvLeft, y-tvRight -- CONVERT TO RELATIVE CLIENT COORDINATES
reaper.JS_LICE_Clear(canvas, 0) -- CLEAR PREVIOUS CONTENT TO TRANSPARENT
reaper.JS_LICE_ScaledBlit(canvas, x, tT[track].top, ASWidth, tT[track].bottom-tT[track].top, ghost1, 0, 0, ASWidth, sourceHeight, 1, "COPY") -- STRETCH TO FIT TARGET TRACK
reaper.JS_Window_InvalidateRect(trackview, 0, 0, 1, 1, true) -- INVALIDATE COORDINATES DON'T MATTER FOR COMPOSITE: COMPOSITE WILL UPDATE ENTIRE WINDOW
end
end
reaper.defer(loop)
end
end
function atexit()
if ghost1 then reaper.JS_LICE_DestroyBitmap(ghost1) end -- DESTROYING BITMAP WILL AUTOMATICAAL UNLINK TOO
if bm1 then reaper.JS_LICE_DestroyBitmap(bm1) end
if canvas then reaper.JS_LICE_DestroyBitmap(canvas) end
if tvDC then reaper.JS_GDI_ReleaseDC(trackview, tvDC) end
reaper.JS_Window_InvalidateRect(trackview, 0, 0, 5000, 5000, true)
end
reaper.atexit(atexit)
-- WAIT FOR MOUSE CLICK BEFORE STARTING
while reaper.JS_Mouse_GetState(1) ~= 1 do end
while reaper.JS_Mouse_GetState(1) == 1 do end
loop()
Last edited by juliansader; 05-12-2019 at 03:04 PM.
|
|
|
05-12-2019, 03:35 PM
|
#489
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Sorry need to ask....
Code:
tT[track] = {top = bottomPixel}
so this is actually working no matter tT is reported as 0 (in IDE)?
I converted them to string since I thought its not getting user data as a key
again thank you veeeeeeeery much for your help
Last edited by Sexan; 05-12-2019 at 03:46 PM.
|
|
|
05-12-2019, 03:53 PM
|
#490
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by Sexan
so this is actually working no matter there is no value and tT is reported as 0 (in IDE)?
|
Yes - Lua tables can use any type of variable as a key.
Hmmm... I'm not sure how the IDE calculates the size. It seems to ignore some types of keys. (The IDE also only displays string up to the first \0, and truncates long floating point numbers.)
|
|
|
05-12-2019, 04:00 PM
|
#491
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Yeah I know it can use anything for key but that table calculation got me... oh well, need to fix some stuff now
|
|
|
05-13-2019, 03:30 AM
|
#492
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Julian is this the best we can get from the image (its not exact copy of whats on the screen, its washed out, little hard to see)?
Its transparency is depended on AS transparency? Want stronger peak color/contrast, I know I can only manipulate with whole image
Code:
local function get_item_blit(tbl, as_tr, as_start, as_end)
if not tbl then return end
local zoom_lvl, Arr_start_time, Arr_end_time, Arr_pixel, x_view_start, y_view_start, x_view_end, y_view_end, state, scroll = project_info()
local items_bm = {}
local item_bar = 15
for i = 1, #tbl do
items_bm[i] = {}
local item_t, item_h, item_b = A[as_tr].t, A[as_tr].h, A[as_tr].b
local item_start, item_lenght = item_blit(tbl[i], as_start, as_end)
items_bm[i].item_bm = reaper.JS_LICE_CreateBitmap(true, math.floor(item_lenght * zoom_lvl), item_h)
items_bm[i].dc = reaper.JS_LICE_GetDC(items_bm[i].item_bm)
reaper.JS_LICE_Clear(items_bm[i].item_bm, 0)
reaper.JS_GDI_Blit(items_bm[i].dc, 0, 0, track_window_dc, math.floor(item_start * zoom_lvl) - Arr_pixel, ((item_t+item_bar) - y_view_start), math.floor(item_lenght * zoom_lvl), item_h-19) -- (-19 TO COMPENSATE ITEM BAR REMOVING)
end
return items_bm
end
Last edited by Sexan; 05-13-2019 at 03:38 AM.
|
|
|
05-13-2019, 03:46 AM
|
#493
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
I will soon add some functions to the extension to manipulate alpha and other colors.
In the meantime, you can increase a bitmap's alpha by blitting onto it another bitmap with "ADD" option. ADD adds the values of each channel (A, R, G, B) separately for each pixel:
Code:
-- AS_bitmap is the target Area Select bitmap
alpha_bitmap = reaper.JS_LICE_CreateBitmap(true, 1, 1)
reaper.JS_LICE_Clear(alpha_bitmap, 0xFF000000) -- This value will added to ASbm
reaper.JS_LICE_ScaledBlit(AS_bitmap, 0, 0, w, h, alpha_bitmap, 0, 0, 1, 1, 1, "ADD")
I only discovered this trick today, after experimenting with the blitting modes. My previous examples would have been better if I used this.
"MUL" mode can be used to lower the brightness of each channel separately.
I'm not quite sure yet what "HSVADJ" and "MASK" do on a bitwise level.
Last edited by juliansader; 05-13-2019 at 04:02 AM.
|
|
|
05-13-2019, 04:22 AM
|
#494
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
I will wait for your update so I do not add unnecessary code which I will probably forget later (the script is not yet in "usable" state so it wont mind this little graphics drawbacks atm.
Anyway this is pretty cool
You are the great blitting magician!!
|
|
|
05-14-2019, 08:23 PM
|
#495
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
- I imagine a number of the window functions shouldn't be expected to work on Linux, right? AttachTopmostPin isn't doing anything here, at any rate.
Edit: It's not working on Windows 8 for me either. I'm getting valid HWND from Window_Find, calling AttachTopmostPin... nothing happens. Just for fun I tried setting Window_Find to exact, and it still didn't work, but it also sent Reaper's main window to the very back.
- I'm getting errors when I try to use reaper.JS_Window_SetZOrder(hwnd, "TOPMOST"). If I don't provide the third parameter it gets mad, but if I provide the third parameter it crashes with 'reaper.JS_Window_SetZOrder' argument 3: expected void*.
Last edited by Lokasenna; 05-14-2019 at 08:50 PM.
|
|
|
05-15-2019, 01:29 AM
|
#496
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Julian is there any way to "flush" VK keys got with JS_VKeys_GetState()? Sometimes they got stuck and script gets their state as pressed even they are not so while is script is running you need to press every stucked one to reset its state. It mostly happens when script crashes but also some other times which I cannot reliably reproduce. I'm making setup script which will intercept only keys that are selected, but sometimes they are falsely triggered
https://github.com/GoranKovac/ReaScr...a_51_Setup.lua
The script
This is what I have when the the script crashes.
On script restart it thinks all of this keys are pressed
Last edited by Sexan; 05-15-2019 at 01:44 AM.
|
|
|
05-15-2019, 04:38 AM
|
#497
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by Sexan
Julian is there any way to "flush" VK keys got with JS_VKeys_GetState()? Sometimes they got stuck and script gets their state as pressed even they are not so while is script is running you need to press every stucked one to reset its state.
|
This is exactly why I needed to add the cutoffTime parameter. For example, you can use GetState/Down(-0.5) at the beginning of the script to get only those keys that were pressed immediately before the script started, and GetState/Down(prevTime) to get keys that were pressed since the previous defer cycle.
|
|
|
05-15-2019, 05:31 AM
|
#498
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
I'm not sure about second part, I need to count defer cycles via time_precise and then use that as time? Could you give example code?
|
|
|
05-16-2019, 04:28 PM
|
#499
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 10,088
|
@juliansader
Can you remember me,
We can have GFW window without titlebar with this script right ?
How do you remove title bar ?
THX !
|
|
|
05-18-2019, 03:59 AM
|
#500
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by Sexan
I will wait for your update so I do not add unnecessary code which I will probably forget later (the script is not yet in "usable" state so it wont mind this little graphics drawbacks atm.
|
I have uploaded v0.987 with some new functions and options for color processing LICE bitmaps:
* LICE_Blit options "BLUR", "ALPHAMUL" and "CHANCOPY_XTOY"
* LICE_ProcessRect
* LICE_AlterRect/BitmapHSV
You can use LICE_ProcessRect with SET_A to set the alpha of the ghosts, and AlterHSV to change the hues.
NOTE: I realized that Windows' GDI_Blit function doesn't do alpha multiplication of the source pixels on the fly while blitting, unlike the Linux and OSX functions. If it is important to get exactly the same color rendering on Windows as on Linux/OSX, the source bitmap must be pre-multiplied with alpha.
Quote:
Originally Posted by X-Raym
@juliansader
We can have GFW window without titlebar with this script right ?
How do you remove title bar ?
|
This is something that I've wanted to do for a long time, but unfortunately, I couldn't figure it out. On Windows, it is possible to remove the frames of REAPER's script GUIs, but it leaves ugly artefacts.
Quote:
Originally Posted by Lokasenna
- I imagine a number of the window functions shouldn't be expected to work on Linux, right?
|
Hopefully only a few. Thanks for testing and please let me know if you find any other Linux problems! I have updated the API help docs.
Quote:
Originally Posted by Lokasenna
AttachTopmostPin isn't doing anything here, at any rate.
Edit: It's not working on Windows 8 for me either.
|
This is unexpected. I wonder if anyone else has tried it on Windows 8? (It works on Windows 7 x64 and OSX High Sierra x64.)
The HWND must be a top-level, framed window. For example:
Code:
gfx.init("qwerty", 200, 200, 0, 200, 200)
w = reaper.JS_Window_Find("qwerty", true)
reaper.JS_Window_AttachTopmostPin(w)
Quote:
Originally Posted by Lokasenna
- I'm getting errors when I try to use reaper.JS_Window_SetZOrder(hwnd, "TOPMOST"). If I don't provide the third parameter it gets mad, but if I provide the third parameter it crashes with 'reaper.JS_Window_SetZOrder' argument 3: expected void*
|
In TOPMOST mode, the extension ignores the third parameter, but REAPER still requires it, so you can simply use the same HWND as in the first parameter. (I tried to convince REAPER to make the third parameter optional, but apparently REAPER doesn't like optional void* parameters.)
|
|
|
05-18-2019, 04:09 AM
|
#501
|
Human being with feelings
Join Date: Feb 2019
Location: Southern Vermont
Posts: 869
|
I know how stingy everyone is with their time in regards to answering the pedantic questions of the lowly, but:
Is there any itemized documentation regarding your functions and updates to? I looked on your github and even made three google searches* and couldn't find much.
Currently, it seems like the bulk info regarding usage of your extensions come from X-Raym's phenomenal website-utility, https://www.extremraym.com/cloud/reascript-doc/.
*I'll send you an invoice, for my time...
|
|
|
05-18-2019, 04:30 AM
|
#502
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Awesome thank you! If its not too much trouble can you please help me with that VK_Key cutoff (2 posts above you)? Not sure how the code should look like
|
|
|
05-18-2019, 04:55 AM
|
#503
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by Dafarkias
I know how stingy everyone is with their time in regards to answering the pedantic questions of the lowly, but:
Is there any itemized documentation regarding your functions and updates to? I looked on your github and even made three google searches* and couldn't find much.
Currently, it seems like the bulk info regarding usage of your extensions come from X-Raym's phenomenal website-utility,
|
The idea behind this extension is to make all the useful and powerful functions that are available to C++ extensions available to ReaScripts too. The online documentation for the corresponding C++ functions is therefore the best place to learn how to use these functions. For example, Window messages and Drawing with GDI.
Cockos's own LICE and swell C++ functions are not so extensively documented, and you will unfortunately have to browse through the "ReaScript, JSFX, REAPER Plug-in Extensions, Developer" subforum as well as the "WDL users" subforum.
For functions that do not have direct C++ equivalents, such as JS_Composite, the best (and only) source of information is this and other discussion threads.
You can also get a better idea of what's going on under the hood by checking the source code on github.
The information on X-Raym's website can also be accessed through REAPER itself, by running the action "ReaScript: Open reaScript documentation". (X-Raym's website is much better formatted, of course.)
|
|
|
05-18-2019, 05:10 AM
|
#504
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by Sexan
Awesome thank you! If its not too much trouble can you please help me with that VK_Key cutoff (2 posts above you)? Not sure how the code should look like
|
How do you intend the keyboard control for Area(51) to work, ideally?
My own js_Mouse editing script are somewhat unusual, since they only use keystrokes to terminate, and in two ways: 1) if any key is pressed, the scripts terminates; 2) if the shortcut key is held down for more than 0.5 second, it becomes similar to a "left drag", and the scripts terminates when the keys are released. I use the following code:
Some preparatory stuff:
Code:
-- The script will intercept keystrokes, to allow control of script via keyboard,
-- and to prevent inadvertently running other actions such as closing MIDI editor by pressing ESC
local VKLow, VKHi = 8, 0xFE --0xA5 -- Range of virtual key codes to check for key presses
local VKState0 = string.rep("\0", VKHi-VKLow+1) -- For quick comparison to zero state
local dragTime = 0.5 -- How long must the shortcut key be held down before left-drag is activated?
local dragTimeStarted = false
At the start of the script:
Code:
-- GET MOUSE AND KEYBOARD STARTING STATE:
-- as soon as possible. Hopefully, if script is started with mouse click, mouse button will still be down.
-- VKeys_Intercept is also urgent, because must prevent multiple WM_KEYDOWN message from being sent, which may trigger script termination.
interceptKeysOK = (reaper.JS_VKeys_Intercept(-1, 1) > 0)
if not interceptKeysOK then reaper.MB("Could not intercept keyboard input.", "ERROR", 0) return false end
mouseState = reaper.JS_Mouse_GetState(0xFF)
mouseOrigX, mouseOrigY = reaper.GetMousePosition()
startTime = reaper.time_precise()
prevMouseTime = startTime + 0.5 -- In case mousewheel sends multiple messages, don't react to messages sent too closely spaced, so wait till little beyond startTime.
keyState = reaper.JS_VKeys_GetState(-2):sub(VKLow, VKHi) -- Ignore keys that were pressed more than 2 second ago.
and then at the start of each defer cycle:
Code:
-- Must the script terminate?
-- There are several ways to terminate the script: Any keystroke or mouse button will terminate the script;
-- except unmodified middle button and unmodified mousewheel, which toggles or scrolls through options, respectively.
-- Also, the script will terminate if the shortcut key is held down and only released *after* dragTime.
-- This gives the user flexibility to control the script via keyboard or mouse, as desired.
local prevCycleTime = thisCycleTime or startTime
thisCycleTime = reaper.time_precise()
dragTimeStarted = dragTimeStarted or (thisCycleTime > startTime + dragTime)
-- KEYBOARD: Script can be terminated by pressing key twice to start/stop, or by holding key and releasing after dragTime
local prevKeyState = keyState
keyState = reaper.JS_VKeys_GetState(startTime-2):sub(VKLow, VKHi)
if dragTimeStarted and keyState ~= prevKeyState and keyState == VKState0 then -- Only lift after every key has been lifted, to avoid immediately trigger action again. NOTE: modifier keys don't always send repeat KEYDOWN if held together with another key.
return false
end
local keyDown = reaper.JS_VKeys_GetDown(prevCycleTime):sub(VKLow, VKHi)
if keyDown ~= prevKeyState and keyDown ~= VKState0 then
local p = 0
::checkNextKeyDown:: do
p = keyDown:find("\1", p+1)
if p then
if prevKeyState:byte(p) == 0 then
return false
else
goto checkNextKeyDown
end
end
end
end
|
|
|
05-18-2019, 05:34 AM
|
#505
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
well the plan is :
1. Users setup their modifiers and keys via setup script (split,delete,move,resize,stretch envelopes etc)
2 Script makes table of all the key/keys group
2. While AS is active/drawn it will intercepts all the keys in that table
3. If key/key group is pressed (Ctrl+a, Ctrl+Shift + v, Ctrl + xy, or any combination made in setup script) and it will trigger corresponding function (split,delete whatever)
4. If there is no AS on the screen then it will release all intercepts
Basically it will intercept keys while there is AS on screen
|
|
|
05-18-2019, 07:13 AM
|
#506
|
Human being with feelings
Join Date: Oct 2017
Location: Black Forest
Posts: 5,130
|
@Julian, is there any way to detect a touchscreen press with JS_MouseGetState()? I haven't found the right flag for it.
|
|
|
05-18-2019, 01:40 PM
|
#507
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,707
|
Since JS-extension has measuring of texts-functions now, how do I use them?
I would want to attempt a version of GetUserInputs, that automatically adjusts to the text given as captions and default-input-boxes, but need to know, how long the caption-strings are actually in pixels.
|
|
|
05-18-2019, 01:41 PM
|
#508
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,707
|
Quote:
Originally Posted by lb0
WOW!! What a HUGE list! Thank you for your hard work on this - this will be invaluable!
|
Thanks
|
|
|
05-18-2019, 03:14 PM
|
#509
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
Quote:
Originally Posted by juliansader
Hopefully only a few. Thanks for testing and please let me know if you find any other Linux problems! I have updated the API help docs.
|
I would actually be surprised if they all work, as window decorations are handled very differently in Linux and the various window managers a user might be running. Reaper doesn't even have a right-click menu on the titlebar for a script window, for example.
Quote:
This is unexpected. I wonder if anyone else has tried it on Windows 8? (It works on Windows 7 x64 and OSX High Sierra x64.)
The HWND must be a top-level, framed window. For example:
Code:
gfx.init("qwerty", 200, 200, 0, 200, 200)
w = reaper.JS_Window_Find("qwerty", true)
reaper.JS_Window_AttachTopmostPin(w)
|
That's pretty much what I have. Normal script window, same variable for the window title and the Find string. It does find a valid HWND, it just doesn't add a pin.
Quote:
In TOPMOST mode, the extension ignores the third parameter, but REAPER still requires it, so you can simply use the same HWND as in the first parameter. (I tried to convince REAPER to make the third parameter optional, but apparently REAPER doesn't like optional void* parameters.)
|
Fair enough. This would definitely be worth specifying in the docs, if you haven't already, since any functions with optional parameters will need something type-appropriate passed in as a placeholder.
|
|
|
05-20-2019, 06:00 AM
|
#510
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by _Stevie_
@Julian, is there any way to detect a touchscreen press with JS_MouseGetState()? I haven't found the right flag for it.
|
I don't know. If the touchscreen sends standard mouse messages, Mouse_GetState or VKeys might be able to detect it, but AFAIK touchscreens send other kinds of messages such as WM_TOUCH.
I don't have a touchscreen to test myself, but perhaps someone else can? If the touchscreen sends any kind of WM_ message to a REAPER window, it should be possible to detect it with the WindowMessage functions.
|
|
|
05-20-2019, 06:06 AM
|
#511
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Quote:
Originally Posted by juliansader
I don't know. If the touchscreen sends standard mouse messages, Mouse_GetState or VKeys might be able to detect it, but AFAIK touchscreens send other kinds of messages such as WM_TOUCH.
I don't have a touchscreen to test myself, but perhaps someone else can? If the touchscreen sends any kind of WM_ message to a REAPER window, it should be possible to detect it with the WindowMessage functions.
|
It works here out of the box, I have XPS 13 with touch screen and it JUST works,no additional configuration
Nothing changed in the code, It receives responds from JS_MOUSE_STATE
Last edited by Sexan; 05-20-2019 at 06:12 AM.
|
|
|
05-20-2019, 07:10 AM
|
#512
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by mespotine
Since JS-extension has measuring of texts-functions now, how do I use them?
I would want to attempt a version of GetUserInputs, that automatically adjusts to the text given as captions and default-input-boxes, but need to know, how long the caption-strings are actually in pixels.
|
Unfortunately I'm not sure if any of the extension function are relevant for measuring text for GetUserInputs.
It would be great if you could somehow tweak the width of the GetUserInputs dialog box! How do you intend to do it?
BTW, as far as I can tell, on WindowsOS, GetUserInputs uses dialog box resource #436, with a logical font "MS Shell Dlg" and font size 8. However, the pixel width differ between Windows and Linux.
|
|
|
05-20-2019, 08:13 AM
|
#513
|
Human being with feelings
Join Date: Oct 2017
Location: Black Forest
Posts: 5,130
|
Hey Julian and Sexan,
yes, touch screen works in Reaper.
But I would like to try if Reaper can catch the WM_TOUCH message
and then send a click to a window WITHOUT stealing the focus of the currently
activated window.
@Julian, tried the Peek function. Apparently WM_TOUCH is not deteced. What a pity.
EDIT: is there a way to listen for ALL window messages, without checking for a specific one?
Last edited by _Stevie_; 05-20-2019 at 08:50 AM.
|
|
|
05-20-2019, 08:57 AM
|
#514
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,707
|
Quote:
Originally Posted by _Stevie_
Hey Julian and Sexan,
yes, touch screen works in Reaper.
But I would like to try if Reaper can catch the WM_TOUCH message
and then send a click to a window WITHOUT stealing the focus of the currently
activated window.
@Julian, tried the Peek function. Apparently WM_TOUCH is not deteced. What a pity.
EDIT: is there a way to listen for ALL window messages, without checking for a specific one?
|
If manage to do that completely, could you write a small tutorial on that one into the Reaper-Internals-thread? We might have use for touch-stuff in our Ultraschall-extension
|
|
|
05-20-2019, 09:02 AM
|
#515
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,707
|
Quote:
Originally Posted by juliansader
Unfortunately I'm not sure if any of the extension function are relevant for measuring text for GetUserInputs.
It would be great if you could somehow tweak the width of the GetUserInputs dialog box! How do you intend to do it?
BTW, as far as I can tell, on WindowsOS, GetUserInputs uses dialog box resource #436, with a logical font "MS Shell Dlg" and font size 8. However, the pixel width differ between Windows and Linux.
|
My current approach is to work with a background-script, that I start before opening the GetUserInput-dialog, which reads all the attributes from the window and childhwnds.
This works already for catching the text the user input into the inputboxes to circumvent the csv-retval-problem.
I would just use that script as well to automatically adjust the length of the dialog-boxes and their correct position, including window-size.
With the length of the text, I could autosize it, otherwise, I would need to let the user decide on that one.
I also think about adding the feature, that when a caption ends with a \n, I would move the inputbox to the next line, giving the caption full width of the window.
So the width would not be split into two fields(caption and inputbox) but rather full width for both.
Edit: is there a way to get the currently used font in a hwnd?
|
|
|
05-20-2019, 10:55 AM
|
#516
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,203
|
Quote:
Originally Posted by tparker24
Although I don't know much about Perl or C, I muddled through somehow and was able to cobble together the python interface file needed for python users. I'm calling it JS_ReaScriptAPI.py
You need to place it in your Plugins (not UserPlugins) directory. For example, in my portable install it goes in: D:\REAPER\Plugins
Then, in your python script, you need to have an import like: from JS_ReaScriptAPI import *
Here's my little python test script:
Code:
from JS_ReaScriptAPI import *
v = JS_ReaScriptAPI_Version(0)
RPR_ShowConsoleMsg(v)
This is unofficial, and there are no guarantees, but it works fine in my little test script.
Attached is the txt file (916 lines), which you need to rename to: JS_ReaScriptAPI.py
Attachment 35525
Hope this helps, but let me know if I've encroached on the author!
- Tom
|
Since above one probably got a bit outdated meanwhile, here's one generated fron v0.987:
https://stash.reaper.fm/v/36404/js_ReaScriptAPI.py
(Btw. the Python function wrappers file can be created rather easily using the Pearl scripts SWS is also using.)
Last edited by nofish; 05-20-2019 at 11:19 AM.
|
|
|
05-20-2019, 12:38 PM
|
#517
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Edit... my bad
Last edited by Sexan; 05-20-2019 at 12:47 PM.
|
|
|
05-20-2019, 12:52 PM
|
#518
|
Human being with feelings
Join Date: Oct 2017
Location: Black Forest
Posts: 5,130
|
Quote:
Originally Posted by mespotine
If manage to do that completely, could you write a small tutorial on that one into the Reaper-Internals-thread? We might have use for touch-stuff in our Ultraschall-extension
|
I will! At the moment I don't have high hopes for that, though.
|
|
|
05-20-2019, 01:11 PM
|
#519
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
how do you revert bitmap to its original state/color?
I'm trying JS_LICE_AlterBitmapHSV
|
Besides the obvious solution of just saving the original bitmap and switching between them, you can use any invertible transformation. AFAIK, in the case of HSV, saturation and value aren't reversible, since they can bump against max and min values. Hue, on the other hand, is a continuous ring that will wrap around when it reaches the maximum, so if you use AlterHSV with any +hue, just use -hue to revert the change.
Another option is to use ProcessRect in XOR mode, since XOR is invertible. Just XOR with any number (0x00FFFFFF will nicely invert the colors without changing alpha) and then XOR again to revert.
|
|
|
05-20-2019, 01:27 PM
|
#520
|
Human being with feelings
Join Date: Jun 2009
Location: Croatia
Posts: 4,793
|
Quote:
Originally Posted by juliansader
Besides the obvious solution of just saving the original bitmap and switching between them, you can use any invertible transformation. AFAIK, in the case of HSV, saturation and value aren't reversible, since they can bump against max and min values. Hue, on the other hand, is a continuous ring that will wrap around when it reaches the maximum, so if you use AlterHSV with any +hue, just use -hue to revert the change.
Another option is to use ProcessRect in XOR mode, since XOR is invertible. Just XOR with any number (0x00FFFFFF will nicely invert the colors without changing alpha) and then XOR again to revert.
|
Yeah thats what I did, but used wrong numbers...sorry, thats why I've edited the post
|
|
|
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 08:10 AM.
|