|
|
|
06-04-2016, 02:02 PM
|
#1
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
Lokasenna's GUI library for Lua v2
V3 update, February 2020 - v3 is now available on ReaPack! I'll make a separate thread for it when time allows, but in the meantime you can have a look at https://jalovatt.github.io/scythe
GUIs. We all need them, and they're a bit of a pain to make in ReaScript. Why not let someone else do the hard work so you can get back to actually making your script do something cool?
Installation:
ReaPack
- Install the Lokasenna's GUI library v2 for Lua package
- In Reaper's action list, run Set Lokasenna_GUI v2 library path.lua
Any scripts requiring this library should now be able to find it.
Manual
- Download the files here (including any subfolders), making sure to keep the same folder structure wherever you put them on your hard drive
- Find and run the install script, Set Lokasenna_GUI v2 library path.lua
Developers
A second package, Lokasenna's GUI library v2 for Lua (developer tools), provides example scripts, templates, and documentation.
Development:
All of my work is done at Lokasenna_GUI on Github. Everything there is to be considered unstable, and probably not suitable for release, but any new feature updates or class additions will show up there. Contributions, bug reports, etc are all welcome.
Enjoy!
Reasons why you should use this sexy beast include:
- It comes with a GUI builder! (Experimental, see the Developer Tools package)
- Very little coding required on your part. A simple GUI might need only a dozen lines of code compared to the hundreds (or thousands, for some of my scripts) you'd have to write if you did it yourself.
- Global font and color settings, so you can change the overall look to suit your fancy.
- Layer visibility management, so you can have multiple sets of controls or dialog boxes come and go as needed.
- Graphics use blitting whenever possible, keeping the CPU usage low without any worry on your part.
- Hooks to run your own functions as part of the GUI's updating loop. You could relabel the options around a knob if you wanted, or have a slider and knob match the selected track's volume/pan... etc.
- Built-in crash reporting, providing more detailed error messages than Reaper does by itself.
- Can be told to exit from your own code, and to run a function when it does. For instance, "save all the current settings, run this action, and quit".
- Numerous helper functions in addition to the GUI code, simplifying a number of things that might be annoying to code on your own every time.
- Modular design, allowing you to use as much, or as little, of my own code as you want. You can also write your own classes if you'd prefer.
Changelog:
July 8/18: The "Lokasenna GUI v2.x.x" watermark now reads its version from ReaPack so I don't have to remember to update it.
June 27/18: First stable release, available on ReaPack. It will only be updated directly with bug fixes - any feature updates and new classes will live on the project repository until I feel like they're safe to move over.
June 6/18: Added support for creating elements with keyed tables rather than a series of function arguments, and an example script demonstrating it.
June 2/18: New class - Window. A number of under-the-hood improvements and new Core functions. Better crash reporting, and handling of Reaper's "restricted permissions" mode.
May 10/18: Fixed some weirdness with how Knob and Slider return their values. This update changes the parameters for both classes and will break any scripts that use them. My apologies.
April 29/18: Added Menubar class.
April 25/18: Added a basic crash reporter, moved the project to my own repository on Github.
April 22/18: Went through all of the classes/scripts and did some major tidying, as well as breaking most of the longer functions into smaller chunks.
April 8/18: Added Listbox and TextEditor classes. There were also a number of bug fixes and efficiency improvements back in... February? I forget.
September 26/17: Bug fix - the Knob class was ignoring min/max values when drawing values around the knob.
August 19/17: Bug fixes related to macOS using decimal values for the mousewheel, and scrolling the mousewheel on a Menubox with no options in it.
July 31/17: A few bug fixes.
June 9/17: First proper release. Classes are modular, tons of new features, code is much more efficient.
June 13/16: Rewrote the library to be copy/paste-able rather than distributing the file separately.
Last edited by Lokasenna; 02-09-2020 at 03:25 PM.
|
|
|
06-04-2016, 06:13 PM
|
#2
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 9,900
|
Thanks for your hard work on this, I'm sure it could be useful to a lot of scripters !!
Cheers !
|
|
|
06-04-2016, 10:19 PM
|
#3
|
Human being with feelings
Join Date: Jun 2010
Location: Texas
Posts: 357
|
This is amazing, Lokasenna.
|
|
|
06-08-2016, 08:30 AM
|
#4
|
Human being with feelings
Join Date: Feb 2015
Posts: 755
|
This looks awesome!
|
|
|
06-08-2016, 12:56 PM
|
#5
|
Human being with feelings
Join Date: Feb 2009
Location: Dunedin, New Zealand
Posts: 205
|
Bravo! Amazing work and excellent reference scripts!
|
|
|
06-10-2016, 04:40 AM
|
#6
|
Human being with feelings
Join Date: Sep 2012
Location: Oz
Posts: 196
|
Great stuff! Thanks!!
|
|
|
02-20-2021, 09:43 PM
|
#7
|
Human being with feelings
Join Date: Jan 2021
Posts: 22
|
Issue in regard to getting GUI.Val, after setting it via a command
Hi Everyone, new to reaper, the forums, and programming in general and would be very grateful for any assistance.
After setting a listbox value via a command, I don't seem to be able to query the correct value.
I would like to add that I don't seem to have issues querying the value if I select the list item with my mouse cursor.
This is probably something really simple that I'm missing but I can't see it.
Thanks all
Code:
local lib_path = reaper.GetExtState("Lokasenna_GUI", "lib_path_v2")
if not lib_path or lib_path == "" then
reaper.MB("Couldn't load the Lokasenna_GUI library. Please install 'Lokasenna's GUI library v2 for Lua', available on ReaPack, then run the 'Set Lokasenna_GUI v2 library path.lua' script in your Action List.", "Whoops!", 0)
return
end
loadfile(lib_path .. "Core.lua")()
GUI.req("Classes/Class - Listbox.lua")()
GUI.req("Classes/Class - Button.lua")()
function example_function()
GUI.Val("Listbox", 1) --Sets the index to 1
reaper.ShowConsoleMsg("Current index: " .. GUI.Val("Listbox")) --Lists 1 as the current index
GUI.Val("Listbox", 4) --Sets the index to 4
GUI.elms.Listbox.retval = {5}
reaper.ShowConsoleMsg("Current index: " .. GUI.Val("Listbox")) --why does it list 1???? I would expect to get 4 in return
GUI.Val("Listbox", 3) --Sets the index to 3
reaper.ShowConsoleMsg("Current index: " .. GUI.Val("Listbox")) --still lists 1?
end
GUI.New("Listbox", "Listbox", {
z = 11,
x = 80,
y = 32,
w = 192,
h = 96,
list = {"item 1", "item 2", "item 4", "item 5", "item 6"},
multi = false, -- For my purposes, I nee
caption = "Scenes"
})
GUI.New("Button", "Button", {
z = 12,
x = 80,
y = 160,
w = 70,
h = 20,
caption = "Push Me",
func = example_function --Here is where I trigger the function on the button click
})
GUI.Init()
GUI.Main()
|
|
|
02-21-2021, 12:47 AM
|
#8
|
Human being with feelings
Join Date: Sep 2014
Posts: 2,643
|
See what this does:
Code:
local lib_path = reaper.GetExtState("Lokasenna_GUI", "lib_path_v2")
if not lib_path or lib_path == "" then
reaper.MB("Couldn't load the Lokasenna_GUI library. Please install 'Lokasenna's GUI library v2 for Lua', available on ReaPack, then run the 'Set Lokasenna_GUI v2 library path.lua' script in your Action List.", "Whoops!", 0)
return
end
loadfile(lib_path .. "Core.lua")()
GUI.req("Classes/Class - Listbox.lua")()
GUI.req("Classes/Class - Button.lua")()
function example_function()
GUI.Val("Listbox", 1) --Sets the index to 1
reaper.ShowConsoleMsg("Current index: " .. listbox_val .."\n") --Lists 1 as the current index
GUI.Val("Listbox", 4) --Sets the index to 4
GUI.elms.Listbox.retval = {5}
reaper.ShowConsoleMsg("Current index: " .. listbox_val .."\n") --why does it list 1???? I would expect to get 4 in return
GUI.Val("Listbox", 3) --Sets the index to 3
reaper.ShowConsoleMsg("Current index: " .. listbox_val .."\n") --still lists 1?
end
GUI.New("Listbox", "Listbox", {
z = 11,
x = 80,
y = 32,
w = 192,
h = 96,
list = {"item 1", "item 2", "item 4", "item 5", "item 6"},
multi = false, -- For my purposes, I nee
caption = "Scenes"
})
GUI.New("Button", "Button", {
z = 12,
x = 80,
y = 160,
w = 70,
h = 20,
caption = "Push Me",
func = example_function --Here is where I trigger the function on the button click
})
function GUI.elms.Listbox:onmouseup()
GUI.Listbox.onmouseup(self)
listbox_val = GUI.Val("Listbox")
reaper.ShowConsoleMsg("Current index: " .. GUI.Val("Listbox") .."\n")
end
GUI.Init()
GUI.Main()
|
|
|
02-21-2021, 02:15 AM
|
#9
|
Human being with feelings
Join Date: Sep 2014
Posts: 2,643
|
I had a look at it, this should set it:
Code:
GUI.Val("Listbox", 2) --Sets the index to 2. Accepts a table of boolean values for items to be selected or not selected.
GUI.elms.Listbox:init()
reaper.ShowConsoleMsg("Current index: " .. GUI.Val("Listbox") .."\n") --Lists 2 as the current index
EDIT: and this will set 1 4 6 selected
Code:
GUI.Val("Listbox", {true,false,true,false,true}) --Sets the index to 1 4 6. Accepts a table of boolean values for items to be selected or not selected.
or
Code:
preset1={true,false,true,false,true}
GUI.Val("Listbox", preset1) --Sets the index to 1 4 6. Accepts a table of boolean values for items to be selected or not selected.
https://github.com/jalovatt/Lokasenn...i/2.00-Listbox
Example Lokasenna GUI included > Script: Example - Menubar, Listbox, and TextEditor.lua
\REAPER\Scripts\ReaTeam Scripts\Development\Lokasenna_GUI v2\Developer Tools\Examples and Templates
Last edited by MusoBob; 02-21-2021 at 04:50 AM.
|
|
|
02-22-2021, 01:04 PM
|
#10
|
Human being with feelings
Join Date: Jan 2021
Posts: 22
|
Thanks for your help MusoBob.
When I'm running this I'm still getting 1 returned to me?
Perhaps I'm running it the wrong place? or I am on the wrong version of Lokasenna?
Code:
local lib_path = reaper.GetExtState("Lokasenna_GUI", "lib_path_v2")
if not lib_path or lib_path == "" then
reaper.MB("Couldn't load the Lokasenna_GUI library. Please install 'Lokasenna's GUI library v2 for Lua', available on ReaPack, then run the 'Set Lokasenna_GUI v2 library path.lua' script in your Action List.", "Whoops!", 0)
return
end
loadfile(lib_path .. "Core.lua")()
GUI.req("Classes/Class - Listbox.lua")()
GUI.req("Classes/Class - Button.lua")()
function example_function()
GUI.Val("Listbox", 2) --Sets the index to 2.
GUI.elms.Listbox:init()
reaper.ShowConsoleMsg("Current index: " .. GUI.Val("Listbox") .."\n") --Still listing 1 for me?
end
GUI.New("Listbox", "Listbox", {
z = 11,
x = 80,
y = 32,
w = 192,
h = 96,
list = {"item 1", "item 2", "item 4", "item 5", "item 6"},
multi = false,
caption = "Scenes"
})
GUI.New("Button", "Button", {
z = 12,
x = 80,
y = 160,
w = 70,
h = 20,
caption = "Push Me",
func = example_function --Here is where I trigger the function on the button click
})
GUI.Init()
GUI.Main()
|
|
|
02-22-2021, 02:18 PM
|
#11
|
Human being with feelings
Join Date: Sep 2014
Posts: 2,643
|
I will have another look at it, but if you are setting the value you should already know that ?
Code:
function example_function()
set_val = 2 --Sets the index to 2
GUI.Val("Listbox", set_val) .
GUI.elms.Listbox:init()
reaper.ShowConsoleMsg("Current index: " .. set_val .."\n")
end
|
|
|
02-23-2021, 12:16 PM
|
#12
|
Human being with feelings
Join Date: Mar 2013
Posts: 5,857
|
I had a quick look at the core code of the Listbox class and it seems that the Listbox also expects a table when using multi = false (for returning the correct value **). So try this:
Code:
function example_function()
GUI.Val("Listbox", {[4] = true}) -- set index 4 to true
reaper.ShowConsoleMsg("Current index: " .. GUI.Val("Listbox") .."\n")
end
Or as MusoBob showed with the example above in post #831: another way would be to use the value directly from the variable ( set_val in the example) for further usage.
** EDIT: Not quite sure yet (I need to take a closer look at the core code again), but getting '1' as return value when using multi = false and a number (instead of a table) for setting the index might perhaps be a bug.
Last edited by solger; 02-23-2021 at 01:12 PM.
|
|
|
04-12-2021, 08:54 AM
|
#13
|
Human being with feelings
Join Date: Jul 2009
Posts: 1,071
|
Hi all,
Couple of questions
Is there a best practice for creating a row of buttons ?
I would like to have a different function on each button which I have but at the moment I have to create each one individually like so .. and the code gets long and I'm looking at creating quite a few of them.
Code:
local layer = GUI.createLayer({name = "Layer1"})
layer:addElements( GUI.createElements(
{
name = "1",
type = "Button",
x = 8,
y = 10,
w = 60,
h = 30,
caption = "b1",
func = func1,
},
{
name = "2",
type = "Button",
x = 8,
y = 90,
w = 60,
h = 30,
caption = "b2",
func = func2,
},
etc. etc.
Also second question,
Is there a way to change the color of the last clicked button ? So I know that is the current function ?
Thanks v much
|
|
|
04-12-2021, 11:32 AM
|
#14
|
Human being with feelings
Join Date: Mar 2007
Location: Denver, CO
Posts: 633
|
There are a lot of ways to do that. I created a grid layout method for a bunch of identically sized elements:
Code:
function GetLayoutXandY(i,x,y,w,h,rows)
----MSG("layout: x = "..x)
local xadj = math.floor((i - 1)/rows)
local yadj = (i-1) % rows
local xpos = x + (xadj * w)
local ypos = y + (yadj * h)
return xpos,ypos
end
then I have a method like this:
Code:
mybuttons = {
x = 0, y = 0, w = 96, h = 36
}
for i,s in ipairs(mybuttons) do
local xpos, ypos = GetLayoutXandY(i,mybuttons.x,mybuttons.y, mybuttons.w,mybuttons.h, 1)
local button = GUI.createElement({
name = 'button'..i,
x = xpos,
y = ypos,
--etc.
})
myLayer:addElements(button)
end
Hope this helps.
|
|
|
04-12-2021, 02:45 PM
|
#15
|
Human being with feelings
Join Date: Jul 2009
Posts: 1,071
|
@woodslanding
Yeah that looks like the sort of thing I might need I was sure there had to be a way of drawing stuff automatically, I am using scythe v3 and can't seem to get your code working though. How would this integrate into the basic framework ?
Cheers for your help.
|
|
|
04-13-2021, 07:16 AM
|
#16
|
Human being with feelings
Join Date: Mar 2007
Location: Denver, CO
Posts: 633
|
that's kind of pseudo-code, yeah. I'm sure it won't work as is... it's just to give you the idea.
Read up on lua tables, and study the methods he uses to create the various widgets himself, you'll see how the constructors are just tables. Once you learn to create and alter tables various ways, it will all fall into place.
|
|
|
10-18-2021, 08:37 AM
|
#17
|
Human being with feelings
Join Date: Jan 2021
Posts: 22
|
Help with element deletion
Hi Everyone, I'm trying to have a button that removes itself after a certain amount of time. It seems to remove its self property when it is clicked, but when triggered by the timer function it doesn't seem to update the UI. I believe I somehow need to trigger a UI redraw but am not sure of how ( I also might be looking in the wrong place). Any help would be greatly appreciated.
Code:
Code:
function remove_popup()
GUI.elms.popup:delete()
end
GUI.New("popup", "Button", {
z = 1,
x = 5.0,
y = 260.0,
w = 330,
h = 40,
caption = msg,
font = 3,
col_txt = "white",
col_fill = "blue",
func = remove_popup
})
time_start = reaper.time_precise()
reaper.ShowConsoleMsg("Starting a timer for 2 seconds...")
local function Main()
local elapsed = reaper.time_precise() - time_start
if elapsed >= 3 then
remove_popup()
reaper.ShowConsoleMsg("2 seconds have elapsed")
return
else
reaper.defer(Main)
end
end
Main()
|
|
|
10-18-2021, 10:31 AM
|
#18
|
Human being with feelings
Join Date: Mar 2013
Posts: 5,857
|
Adding this line should do the trick:
Code:
function remove_popup()
GUI.elms.popup:delete()
GUI.redraw_z[0] = true
end
Using redraw_z[0] (with value 'zero') redraws everything. It's also possible to redraw only specific z layers. More info here: https://github.com/jalovatt/Lokasenn.../4.02-Z-layers
EDIT:
Since the button in your example is on z layer 1 (z = 1), redrawing only z layer 1 should also work:
Code:
function remove_popup()
GUI.elms.popup:delete()
GUI.redraw_z[1] = true
end
Last edited by solger; 10-18-2021 at 10:38 AM.
|
|
|
10-18-2021, 05:22 PM
|
#19
|
Human being with feelings
Join Date: Jan 2021
Posts: 22
|
That's the ticket, thanks so much Solger. Very helpful as always.
Quote:
Originally Posted by solger
Adding this line should do the trick:
Code:
function remove_popup()
GUI.elms.popup:delete()
GUI.redraw_z[0] = true
end
Using redraw_z[0] (with value 'zero') redraws everything. It's also possible to redraw only specific z layers. More info here: https://github.com/jalovatt/Lokasenn.../4.02-Z-layers
EDIT:
Since the button in your example is on z layer 1 (z = 1), redrawing only z layer 1 should also work:
Code:
function remove_popup()
GUI.elms.popup:delete()
GUI.redraw_z[1] = true
end
|
|
|
|
11-28-2021, 11:59 AM
|
#20
|
Human being with feelings
Join Date: Jan 2011
Location: Ottawa, Canada
Posts: 293
|
Easy Q: How do I close the main window?
Hey Folks, just getting started with this cool GUI script and Lua scripting in general.
I've written my script and hooked it into a couple sliders and buttons. But for some reason I'm stuck on what I figured would be the easiest things:
1. I would like the Ok button to Close the GUI main window (as changes have already been applied)
2. I would like the main window "X" button to call a 'restore()' function and close the window
I have my various functions working. I can modify the Midi, and restore it. But I can't figure out how to interact with the main window.
I've tried setting 'GUI.quit = true' and it doesn't appear to do anything to the window.
I've been looking at the wiki and I see guidance on how to start the Gui, but not how to shut it down: https://github.com/jalovatt/Lokasenn...a-basic-script
Any help here would be much appreciated...
|
|
|
11-28-2021, 12:21 PM
|
#21
|
Human being with feelings
Join Date: Mar 2013
Posts: 5,857
|
Quote:
Originally Posted by DrFrankencopter
1. I would like the Ok button to Close the GUI main window (as changes have already been applied)
...
I've tried setting 'GUI.quit = true' and it doesn't appear to do anything to the window.
|
Calling 'gfx.quit' afterwards should do the trick:
Code:
GUI.quit = true
gfx.quit()
Quote:
Originally Posted by DrFrankencopter
2. I would like the main window "X" button to call a 'restore()' function and close the window
|
Try using the reaper.atexit function ( https://www.extremraym.com/cloud/rea...oc/#lua_atexit):
Code:
reaper.atexit(function ()
-- call your code or function(s) here
end)
|
|
|
Thread Tools |
|
Display Modes |
Hybrid 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 11:17 PM.
|