Old 11-23-2019, 06:41 AM   #1
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default How to click a button in Lokasenna GUI v2

Ok, new problem, have checked the documentation and googled
with no luck. Have this code

Code:
function countDownTimer2 ()
  if (reaper.time_precise() <= endTime2) then
    reaper.defer(countDownTimer2)
  else
    reaper.ShowConsoleMsg("Continue")
    GUI.elms.Start_Cont_Button:exec() <--Click a button
  end
end
The Msg is shown, but the button is not clicked - what have I missed?
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify

Last edited by tompad; 11-24-2019 at 02:13 AM.
tompad is offline   Reply With Quote
Old 11-23-2019, 08:45 AM   #2
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,475
Default

- In future, it would be useful to clarify in the title and post that it's a question relating to my GUI.

- Working for me:
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 run 'Script: Set Lokasenna_GUI v2 library path.lua' in your Action List.", "Whoops!", 0)
    return
end
loadfile(lib_path .. "Core.lua")()

GUI.req("Classes/Class - Button.lua")()

if missing_lib then return 0 end

local function btn_click()
  GUI.Msg("Button was clicked")
end

local endTime2 = reaper.time_precise() + 2

function countDownTimer2 ()
  if (reaper.time_precise() <= endTime2) then
    reaper.defer(countDownTimer2)
  else
    GUI.Msg("Timer fired")
    GUI.elms.Start_Cont_Button:exec() --Click a button
  end
end

GUI.name = "New Window"
GUI.x, GUI.y, GUI.w, GUI.h = 0, 0, 432, 500
GUI.anchor, GUI.corner = "mouse", "C"

GUI.New("Start_Cont_Button", "Button", 1, 168, 28, 96, 20, "Go!", btn_click)

GUI.Msg("Started...")
countDownTimer2()

GUI.Init()
GUI.Main()
-->

Code:
Started...
(...two seconds later...)
Timer fired
Button was clicked
Lokasenna is online now   Reply With Quote
Old 11-24-2019, 03:05 AM   #3
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default

Quote:
Originally Posted by Lokasenna View Post
- In future, it would be useful to clarify in the title and post that it's a question relating to my GUI.
Oooh,missed it, was to exited ;-) Fixed now!

Quote:
Code:
local function btn_click()
  GUI.Msg("Button was clicked")
end

//////////

GUI.New("Start_Cont_Button", "Button", 1, 168, 28, 96, 20, "Go!", btn_click)

Hmmm, ok, I am using this

Code:
 function GUI.elms.Start_Cont_Button:onmouseup()

  GUI.Button.onmouseup(self)

-- Lots of code
end
instead of assigning btn_click to GUI.New button. Maybe thats
the problem? Or Linux? ;-)

I am using GUI-builder and the output of code is a bit different
and I had various luck with assigning function to button with that.
It was a long long time ago I tried it, could have missed something
important...
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 11-24-2019, 03:15 AM   #4
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default

I found a solution!


I tried to assign function to GUI.New-button with:

Code:
GUI.New("Start_Cont_Button", "Button", {
  z = 11,
  x = 32.0,
  y = 128.0,
  w = 100,
  h = 30,
  caption = "START!",
  font = 2,
  col_txt = "txt",
  col_fill = "elm_frame",
  func = startButton
})
and call it from countTimer2.....

...that didn't work ;-(

Instead of that I moved all own code I had in

Code:
 function GUI.elms.Start_Cont_Button:onmouseup()

  GUI.Button.onmouseup(self)

-- Own code
end
to an own function that I called from GUI.elms.Start_Cont_Buttonnmouseup().

That worked! :-)
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 11-24-2019, 08:31 AM   #5
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,475
Default

The exec method specifically calls the function assigned to func, so yes - if you overwrite mouseup directly to add our code instead of passing a function, exec won't work.
Lokasenna is online now   Reply With Quote
Old 11-24-2019, 08:50 AM   #6
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default

Quote:
Originally Posted by Lokasenna View Post
The exec method specifically calls the function assigned to func, so yes - if you overwrite mouseup directly to add our code instead of passing a function, exec won't work.
I am not sure I understand right.....

What I did was to replace
Code:
 function GUI.elms.Start_Cont_Button:onmouseup()
  GUI.Button.onmouseup(self)
-- Lots of code  
end
with

Code:
 function startButton()
 -- Lots of code
end
and added func = startButton to GUI.New ("Start_Cont_Button")-table
like this:

Code:
GUI.New("Start_Cont_Button", "Button", {
  z = 11,
  x = 32.0,
  y = 128.0,
  w = 100,
  h = 30,
  caption = "START!",
  font = 2,
  col_txt = "txt",
  col_fill = "elm_frame",
  func = startButton
})
But clicking the button did nothing. ? Shouldn't that do the thing?
Trying to understand ....but....dont.

The solution I had worked though.
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 11-24-2019, 02:03 PM   #7
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,475
Default

It should, and it works fine here.

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 run 'Script: Set Lokasenna_GUI v2 library path.lua' in your Action List.", "Whoops!", 0)
    return
end
loadfile(lib_path .. "Core.lua")()

GUI.req("Classes/Class - Button.lua")()

-- If any of the requested libraries weren't found, abort the script.
if missing_lib then return 0 end

local function btn_click()
  GUI.Msg("Button was clicked")
end

local endTime2 = reaper.time_precise() + 2

function countDownTimer2 ()
  if (reaper.time_precise() <= endTime2) then
    reaper.defer(countDownTimer2)
  else
    GUI.Msg("Timer fired")
    GUI.elms.Start_Cont_Button:exec() --Click a button
  end
end

GUI.name = "New Window"
GUI.x, GUI.y, GUI.w, GUI.h = 0, 0, 432, 500
GUI.anchor, GUI.corner = "mouse", "C"

-- GUI.New("Start_Cont_Button", 	"Button", 		1, 168, 28, 96, 20, "Go!", btn_click)

GUI.New("Start_Cont_Button", "Button", {
  z = 11,
  x = 32.0,
  y = 128.0,
  w = 100,
  h = 30,
  caption = "START!",
  font = 2,
  col_txt = "txt",
  col_fill = "elm_frame",
  func = btn_click,
})

GUI.Msg("Started...")
countDownTimer2()

GUI.Init()
GUI.Main()
I feel like there must be something else going on with your code. If you can post the whole thing I'm happy to have a look.
Lokasenna is online now   Reply With Quote
Old 11-25-2019, 07:07 AM   #8
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default

Quote:
Originally Posted by Lokasenna View Post

I feel like there must be something else going on with your code. If you can post the whole thing I'm happy to have a look.
My code is in Practice Coach 1.0.2 in Reapack, you are welcome to look at it. :-)

You need to replace my button-code though....
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 11-25-2019, 07:13 AM   #9
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default

I tested YOUR code - and, suprice! it worked. :-)

And after looking thru it with my sharp glasses I found something.
One tiny little comma after btn_click - AHAAA I thought, but noooo,
after removing comma the code worked although.
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 11-25-2019, 07:45 AM   #10
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,475
Default

Ah, I see the issue.

Lua doesn't hoist variables, even global ones, so you can't assign func = startButton before you've declared startButton. In some cases where it's necessary, you can just declare local myThing without a value early on and assign a function to it somewhere later; anything else declared after myThing will be able to see it and access it.

In this case, the script fails silently because the Button class adds a do-nothing function to keep itself from crashing.

1. Take all of your function declarations (startButton, resetWindow, etc) and move them above where all of the elements are declared.
2. For buttons where your onmouseup is just calling a function, delete the onmouseup code and pass the function to the button directly with func = startButton.

Should work now. If it doesn't, I've got it working here and can PM you the code.
Lokasenna is online now   Reply With Quote
Old 11-25-2019, 08:27 AM   #11
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default

Quote:
Originally Posted by Lokasenna View Post
Ah, I see the issue.

Lua doesn't hoist variables, even global ones, so you can't assign func = startButton before you've declared startButton. In some cases where it's necessary, you can just declare local myThing without a value early on and assign a function to it somewhere later; anything else declared after myThing will be able to see it and access it.

In this case, the script fails silently because the Button class adds a do-nothing function to keep itself from crashing.

1. Take all of your function declarations (startButton, resetWindow, etc) and move them above where all of the elements are declared.
2. For buttons where your onmouseup is just calling a function, delete the onmouseup code and pass the function to the button directly with func = startButton.

Should work now. If it doesn't, I've got it working here and can PM you the code.
Ahaaa. ok, so it is better to have the GUI-code after my own functions?
But before Main? Or even after Main?? I am a bit confused because I
think I in the earlier days of coding reascripts had to put GUI-code
first.....could be a misunderstanding from me though....
Just run a test with GUI-code after Main() and it run like it should.
That way I could get "away" the GUI-code from the main code.

Just a thought - is it possible to have my GUI-code in a separate lua-file
and call it from the main lua file??

If its possible to have separate files (it should) are there any tools to
compile these files to a single file when the project shall release? When
releasing its simpler to have one file but when working with the code it
would be nice to separate the code...
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 11-25-2019, 10:27 AM   #12
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,475
Default

Short answer: Yes.

- Have a look at Lua's loadfile function.
- I wrote a compiler specifically for this purpose; it uses a few specific comments to replace your loading code with the contents of the file. https://forum.cockos.com/showthread.php?t=185264

You may find yourself running into issues of variable scope, just FYI. If so, try not assigning any of the callbacks like func = ... in the GUI file; rather, add them separately in the main file after loading the GUI elements.

I can provide more detail later.
Lokasenna is online now   Reply With Quote
Old 11-25-2019, 10:36 AM   #13
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,475
Default

That said, I find it easier to just leave the files separate and have ReaPack install them all. Put your main script where it should go (/Various), any extra files in a subfolder with the same name as the script just to make it clear, and then edit the script's ReaPack header to install that folder as well as the script.

https://github.com/cfillion/reapack-...-Documentation
Lokasenna is online now   Reply With Quote
Old 11-25-2019, 11:33 PM   #14
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default

After some good sleep and breakfast a Q went up.
I now understand that adding a func to a button
in GUI-code needs to be after the called function.
But how about if the function calls a GUI??
Shouldn't the GUI-code then be before the function
calling it?

"Probably NOT Thomas because as you saw when putting
the GUI-code after the Main() it worked"


...but yet?

And another thing - am I getting this correct?
If I use separate files, the loadfile should go
after the function called by the button, right?

Yes I know I could test it and see, but discussing it
here makes me think and use my vocabulary in english
better. I dont have anyone to discuss this even in
my native language....OH THOMAS THAT SOUNDED SAD! ;-)
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 11-26-2019, 07:36 AM   #15
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,475
Default

When referring to the elements we get to "cheat" a little bit.

Code:
loadfile(lib_path .. "Core.lua")()
GUI.req("Classes/Class - Button.lua")()

local function doStuff()
  GUI.elms.myButton:exec()
end

GUI.New("myButton", "Button", ...)
This works because the first line creates a global variable, GUI, which the function can see. The existence of anything inside GUI, such as a table called elms with a child table called myButton, doesn't matter until we actually call that function.

Same with GUI.Val - as soon as you load the GUI at the top, that function is created, so you can call it anywhere in your code and as long as the element you're looking for exists when you call it, you're good.

As far as when to load things, it's a good practice to do all of your loading at the very top just so it's always clear what other files are being used. As I said above, you can assign the buttons' functions and any method overrides in the main script, so the file with the GUI elements really just needs to be a bunch of GUI.News.
Lokasenna is online now   Reply With Quote
Old 11-29-2019, 08:07 AM   #16
reapero
Human being with feelings
 
Join Date: Aug 2011
Posts: 250
Default

DELETED - taken to the Lokasenna GUI thread

Last edited by reapero; 11-29-2019 at 08:23 AM.
reapero is offline   Reply With Quote
Old 12-01-2019, 02:46 AM   #17
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default

Quote:
Originally Posted by Lokasenna View Post
As far as when to load things, it's a good practice to do all of your loading at the very top just so it's always clear what other files are being used. As I said above, you can assign the buttons' functions and any method overrides in the main script, so the file with the GUI elements really just needs to be a bunch of GUI.News.
Let see if I got this right - If I export a GUI-file in GUI-Builder, I can load
that file with loadfile in the beginning of the main script file and if I want one
of the.... let say a button in GUI-file have a function hooked to it I just
override with GUI.New("myButton", "Button", func = nameOfFunc)?

So the w,h,x,y,etc of button is taken from GUI-file and nameOfFunc is added to that button?

If thats right - its freaking wonderful! :-)

...I have something else I want to ask you, been thinking around a bit.
Is it advisebly to put a call to a function with reaper.CountTracks() and
reaper.ReorderSelected() and some more in Main loop?
I have something that I might wanna run in the background, but if its
not ok I could do a regular script called by user.
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 12-01-2019, 08:59 AM   #18
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,475
Default

Quote:
Originally Posted by tompad View Post
Let see if I got this right - If I export a GUI-file in GUI-Builder, I can load
that file with loadfile in the beginning of the main script file and if I want one
of the.... let say a button in GUI-file have a function hooked to it I just
override with GUI.New("myButton", "Button", func = nameOfFunc)?

So the w,h,x,y,etc of button is taken from GUI-file and nameOfFunc is added to that button?
Almost.

- You'll probably want to load Lokasenna_GUI itself in the main script so you can use helpers like GUI.Msg.

- You'll probably want to move the GUI.Init and GUI.Main statements from the end of the UI file into your main script as well so that it can be charge of when the GUI starts up.

- If you just don't assign a func to the button in your GUI file, any time after the main script has loaded it you can set it with GUI.elms.my_button.func = some_function_in_this_script

Here's a quick example that should get the idea across: https://dl.dropboxusercontent.com/s/...gui%20test.zip

There are different ways to do it, such as setting up the GUI script as a function that you pass the click handler into when you call it, but that's really just a tidiness/organization thing.

Quote:
Is it advisebly to put a call to a function with reaper.CountTracks() and reaper.ReorderSelected() and some more in Main loop? I have something that I might wanna run in the background, but if its not ok I could do a regular script called by user.
You certainly can, as long as you aren't abusing the user's CPU. If there's a particular condition you can check for, like "has the number of tracks changed?", then that's easy enough to run on every loop. You can also use reaper.time_precise() or just a simple loop counter to reduce how often your checking + doing stuff happens.
Lokasenna is online now   Reply With Quote
Old 12-04-2019, 11:44 PM   #19
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 407
Default

Quote:
Originally Posted by Lokasenna View Post

- If you just don't assign a func to the button in your GUI file, any time after the main script has loaded it you can set it with GUI.elms.my_button.func = some_function_in_this_script

Here's a quick example that should get the idea across: https://dl.dropboxusercontent.com/s/...gui%20test.zip

.......

You certainly can, as long as you aren't abusing the user's CPU. If there's a particular condition you can check for, like "has the number of tracks changed?", then that's easy enough to run on every loop. You can also use reaper.time_precise() or just a simple loop counter to reduce how often your checking + doing stuff happens.
Awesome! Thanks for the example external GUI test!
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 03:04 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.