Old 05-21-2019, 06:32 AM   #481
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

Quote:
Originally Posted by woodslanding View Post
Wow, this is just rockin along!!

question: I want to create a bunch of similar items that each address a different track... I can create unique names for them by concatenating a string, but then I don't know how to access them.
- Accessing array elements with variables is just a matter of using []s and concatenating a string the same way.

- You can use self inside any method that will be called with the : syntax.

Code:
for i = 0, 10 do
  local ctl = GUI.elms["ns_ctl"..i]
  ctl.onmouseup = function(self)
    setNoteSource(self.trk, self:val())
    GUI.IControl.onmouseup(self)
  end
end
Lokasenna is online now   Reply With Quote
Old 05-21-2019, 09:39 AM   #482
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

dang, that is pretty code. Lua is so cool!
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-22-2019, 09:03 PM   #483
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

Okay, continuing onward...

How would I do meters?

I'd also like to control elements from midi... is there a way to do that? I considered having dummy values in a jsfx, but I still need to figure out how to read them

I assume the gui framework has a clock somewhere to poll the mouse and keyboard, correct? Maybe it could poll midi and output levels at the same time?


Okay, right after writing this I stumbled into onupdate(). I tried this for meters:
Code:
ctl:onupdate(ctl:val(reaper.Track_GetPeakInfo(track,1)))
not doing anything yet...

another try, seems closer:
Code:
ctl.onupdate = function(self)  self:val(getMeter(track,1)) end  --getMeter calls getPeakInfo
oh my, this IS working :0
__________________
eric moon
Very Stable Genius
https://gogolab.com/

Last edited by woodslanding; 05-22-2019 at 10:13 PM.
woodslanding is offline   Reply With Quote
Old 05-23-2019, 05:58 AM   #484
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default



There's also an equivalent global hook if that helps at all:
Code:
GUI.func = myFunction
GUI.freq = 0 -- every loop
Lokasenna is online now   Reply With Quote
Old 05-23-2019, 01:43 PM   #485
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default Freeze Element?

I'm reading through the default methods of core.lua, and I found this:

Code:
-- Called on every update loop, unless the element is hidden or frozen
function GUI.Element:onupdate() end
How do you freeze an element? I did a search on freeze and frozen in core, and found nothing.... would be useful to do to save cpu, I assume.
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-23-2019, 01:51 PM   #486
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

I don't remember if I've actually tested it, but:
Code:
GUI.elms_freeze[elm.z] = true
Frozen layers should continue to draw their last visual state, but shouldn't do any processing for onupdate or input methods. ...I think.

https://github.com/jalovatt/Lokasenn.../4.02-Z-layers
Lokasenna is online now   Reply With Quote
Old 05-24-2019, 10:21 PM   #487
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

Thanks!

I realized I don't really have a use-case for this, though, because I often like to set up tracks while they are disabled... so I guess I always want the gui elements responsive. Although I will keep this in mind. It might come up again.

But in a slightly related question.... I'd like some of the gui to update precisely (like the metronome display) but other things could be comparatively more lazy. Wondering how you might go about setting up a slower update rate for certain controls, to save cpu....
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-25-2019, 06:27 AM   #488
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

- Put the lazy elements on separate layers. As long as nothing on a given layer needs to be redrawn, the entire layer will just keep blitting the same image when the GUI redraws everything.

- Add some logic to the lazy elements' onupdate, or whatever you're using to update them, so that it doesn't do the work on every loop:
Code:
local updateFrequency = 10 -- 10 script cycles
lazyElement.updateCount = 0

function lazyElement:onupdate()
  self.updateCount = (self.updateCount + 1) % updateFrequency
  if self.updateCount == 0 then
    updateStuff()
  end
end
If the lazy elements are all updating at the same time, it would be more efficient to use GUI.func:
Code:
GUI.func = updateAllTheLazyStuff
GUI.freq = 0.1 -- seconds
Lokasenna is online now   Reply With Quote
Old 05-25-2019, 10:02 AM   #489
tXShooter
Human being with feelings
 
tXShooter's Avatar
 
Join Date: Aug 2017
Posts: 301
Default

Quote:
Originally Posted by Lokasenna View Post


There's also an equivalent global hook if that helps at all:
Code:
GUI.func = myFunction
GUI.freq = 0 -- every loop
Is it possible to change the frequency on functions? Like, run a function once every 100 loops to check for a file?
__________________
"But be ye doers of the word, and not hearers only, deceiving your own selves."
tXShooter is offline   Reply With Quote
Old 05-25-2019, 10:10 AM   #490
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

GUI.freq is in seconds, so you can give it 0.2 or something. For an exact number of loops you would have to manage a counter yourself:
Code:
local updateCounter = 0
local updateFrequency = 100
GUI.func = function()
  if (updateCounter == 0) then
    updateTheThings()
  end

  -- Increments the counter, but wraps it to 0 when it hits 100
  updateCounter = (updateCounter + 1) % updateFrequency
end
GUI.freq = 0
Lokasenna is online now   Reply With Quote
Old 05-25-2019, 04:50 PM   #491
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

Alrighty folks, I think I've procrastinated on this about as much as I can.

Version 3 of the GUI is now ready to accept contributions from Viewers Like You: https://github.com/jalovatt/scythe

Notable changes thus far:
- The project has been renamed "Scythe" because lol Reaper puns.
- The GUI has been ripped apart and restructured into a bunch of smaller modules.
- The {type = "Button", x = 48, caption = "Hi!"} syntax for creating elements is now the ONLY way to create elements because it makes life way, way easier.
- Elements, layers, and windows (well, only one window for the moment) are handled in a much more object-oriented way. If you've ever worked with HTML objects in Javascript, it should look familiar - see the example scripts in the repo.
- There are now a bunch of public modules, separate from the GUI, providing things like extra table functions, text processing, etc.

I have a very long list of features to include in 3.0, and even more that would be nice to have, so I'm open to as much assistance as you can give me. Have a look and see if anything catches your eye.

Thanks.
Lokasenna is online now   Reply With Quote
Old 05-25-2019, 11:14 PM   #492
Nogla
Human being with feelings
 
Join Date: Apr 2018
Location: Kaliningrad
Posts: 18
Default

Is it possible to use your library as a GUI frontend for Control Surface plugin (C++ DLL)?
Nogla is offline   Reply With Quote
Old 05-26-2019, 07:18 AM   #493
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

Not directly - ReaScripts don't have any access to .dlls. If the library is specific to Reaper it could be written to expose some functions for a script to use.
Lokasenna is online now   Reply With Quote
Old 05-30-2019, 07:21 PM   #494
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

I am checking out the V3. One quick question:

Is there a way to get better code completion in vs code? Especially functions in classes that are not in the file, but added via require or other methods.

I've avoided splitting my code into multiple files for just that reason, and I'm wondering if you've found a workaround, now that the core has been split up....

I do have a working image widget class. When it's a little more polished, I'll send it to you. I think some of it might be useful.
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-30-2019, 07:48 PM   #495
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

Reading function names from other files is something the language server/extension for VS Code has to do, and I have yet to find one for Lua that does it.

When v3 is ready to go I'd definitely like to add a set of autocomplete snippets to the existing pack here: https://forum.cockos.com/showthread.php?t=208769 , but until then you're out of luck. Keeping modules small does help with remember what functions they expose though.
Lokasenna is online now   Reply With Quote
Old 05-30-2019, 09:10 PM   #496
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

I was afraid of that.

until then, I'm afraid Lua is only 1.75 tons of fun.
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-31-2019, 08:07 AM   #497
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

Quote:
Originally Posted by Lokasenna View Post
- Put the lazy elements on separate layers. As long as nothing on a given layer needs to be redrawn, the entire layer will just keep blitting the same image when the GUI redraws everything.

The thing is if I am needlessly checking values from Reaper on every update, that's going to use a lot of cpu, quite independent of the task of drawing anything. I'll have maybe 300 elements in the gui, and they all need to stay in sync with Reaper, even if it's not that frequently.... I just don't want to peg the cpu by asking for all that data at once. So I've got to figure that out.

Quote:
If the lazy elements are all updating at the same time, it would be more efficient to use GUI.func:
Code:
GUI.func = updateAllTheLazyStuff
GUI.freq = 0.1 -- seconds
Basically every one of my components is going to need to poll reaper for changes, so I'd like to have a default implementation in the component. But I'm confused about where I'd put these, so that I'd have a good default behaviour (such as 'check 5x a second, offset by a random amount') and still be able to override it in individual components, such as my metronome display, which should update on every cycle.

thinking out loud here.... so I can have individual components set their GUI.func to 'getReaperVal(x)' and then have the image component class call GUI.func itself. And it could call it every "GUI.freq + (random %)"?

Well, no, because GUI.func is triggered at the discretion of the core function, right? So I need to implement similar functionality in my component that includes an offset?
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-31-2019, 09:26 AM   #498
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

GUI.func is just a top-level thing. Components don't have any built-in frequency settings for onupdate, but you could keep them from all updating at the same time with something like:
Code:
-- When creating them, assign a random number from 0 to 99
myElement.updateIndex = Math.floor(Math.random() * 100)

function myElement:onupdate()
  if elementUpdateCounter == self.updateIndex then
    -- update stuff
  end
end

-- Increment a global counter
GUI.func = function()
  elementUpdateCounter = (elementUpdateCounter + 1) % 100
end
You might also look into Lua's "coroutines" - they're functions that you can effectively pause and come back to, which makes them great for saying "here's a giant pile of work, do a bit of it and then wait for the next script update to do a bit more". If your elements were named consistently but with increasing numbers, you could have a coroutine looping over all of them but only doing ten at a time, etc.
Lokasenna is online now   Reply With Quote
Old 05-31-2019, 12:16 PM   #499
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

yeah, okay that looks good.

I'm having a problem with self being nil the first time onupdate gets called.... but I see you have 'self' right there... hmmm.

Code:
function GUI.IControl:onupdate()
    self.updateCount = (self.updateCount + 1) % self.updateRate --line 142
    if self.updateCount == 0 then
Class - IControl.lua:142: attempt to index a nil value (local 'self')
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-31-2019, 02:03 PM   #500
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

Is the function being called with a . instead of a : ? The : is what adds a hidden self parameter.
Lokasenna is online now   Reply With Quote
Old 05-31-2019, 03:08 PM   #501
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

right, exactly, thank you!

still trying to keep that all straight, but I did just reread that part of the Lua docs, for all the good it did!
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-31-2019, 08:29 PM   #502
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

I have a partially transparent component, and I'd like to have a display-only indicator component visible through it.

I thought putting the display on z=2 and the transparent component on z=1 would work, but it seems like the z=2 component doesn't get displayed at all. Is there a way around this?
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-31-2019, 08:56 PM   #503
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

It should be. Is the transparent element drawing any sort of a background (if you copied from something like Label, it might be).
Lokasenna is online now   Reply With Quote
Old 05-31-2019, 09:23 PM   #504
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

Doh!!!!

Okay, another question: as I recall, there is no way to get a window without a title bar, correct?

I'd love to go full screen, and use every pixel. Obviously I'd have to include my own close button
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 05-31-2019, 09:39 PM   #505
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

Not really.

The JS extension adds a few neat window functions, and I think you can hack a "frameless" window by copying the screen content behind the window and then blitting it on top of the whole window and frame, but the .gif I saw was a bit jerky and it won't work on Linux at the moment.
Lokasenna is online now   Reply With Quote
Old 06-21-2019, 12:49 AM   #506
MusoBob
Human being with feelings
 
MusoBob's Avatar
 
Join Date: Sep 2014
Posts: 845
Default

I'm trying to replace a Radio with a Menubox.
I don't know if I have to change the "optarray" to something else as it gets

Error: Class - Menubox.lua:141: bad argument #1 to 'floor' (number expected, got nil)


when I select a Radio it updates the buttons.

Code:
    --GUI.New("scale_choice",     "Radio",          4, 20, 100, 140, 330, "Select Scale", "Major,Minor,Harmonic Major,Harmonic Minor", "v", 4)
    
    GUI.New("scale_choice",   "Menubox",     4, 120, 100, 64, 20, "Select Scale", "Major,Minor,Harmonic Major,Harmonic Minor")
    
    scale = GUI.elms.scale_choice.optarray[ GUI.Val("scale_choice") ]

function GUI.elms.scale_choice:onmouseup()
    -- Run the original method
    GUI.Radio.onmouseup(self)

    -- And then your function
    update_chord_buttons() 
end

    scale_numbers = GUI.Val("scale_choice")
    scale_names = { [1] = "Major", [2] = "Minor", [3] = "Harmonic_Major", [4] = "Harmonic_Minor"}
    selected_scale = scale_names[scale_numbers]
I'm always trying to find this you should put it in you signature
https://github.com/jalovatt/Lokasenna_GUI/wiki




.
__________________
ReaTrakStudio Chord Track for Reaper forum
www.reatrak.com
MusoBob is offline   Reply With Quote
Old 06-21-2019, 06:07 AM   #507
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

Quote:
Originally Posted by MusoBob View Post
Code:
function GUI.elms.scale_choice:onmouseup()
    -- Run the original method
    GUI.Radio.onmouseup(self)

    -- And then your function
    update_chord_buttons() 
end
My first guess would be that it's having trouble because you're still calling GUI.Radio.onmouseup(self) instead of Menubox.

Failing that, I'd have to look at the script myself. Is it not printing out a full stack trace for you?

Quote:
I'm always trying to find this you should put it in you signature https://github.com/jalovatt/Lokasenna_GUI/wiki
Unfortunately there's a limit on signature length and I'm already up against it. There is a link to the repo in the OP of this thread through (under "Development").
Lokasenna is online now   Reply With Quote
Old 06-21-2019, 01:05 PM   #508
MusoBob
Human being with feelings
 
MusoBob's Avatar
 
Join Date: Sep 2014
Posts: 845
Default

Perfect thanks !
__________________
ReaTrakStudio Chord Track for Reaper forum
www.reatrak.com
MusoBob is offline   Reply With Quote
Old 06-30-2019, 07:30 PM   #509
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default argument in control method override

I'm trying to create a matrix of buttons, and I'm trying to get each one to call a master method (called 'select') with its own index as an argument:

Code:
for i = 1,buttonCount

    --create button, etc

    ctl.onmouseup = function(self) select(i) GUI.IButton.onmouseup(self) end
and it doesn't seem to work. I feel like I don't quite understand what happens when you create this kind of function... does the value of 'i' not get stored with the function?
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 06-30-2019, 08:20 PM   #510
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

Quote:
Originally Posted by woodslanding View Post
I'm trying to create a matrix of buttons, and I'm trying to get each one to call a master method (called 'select') with its own index as an argument:

Code:
for i = 1,buttonCount

    --create button, etc

    ctl.onmouseup = function(self) select(i) GUI.IButton.onmouseup(self) end
and it doesn't seem to work. I feel like I don't quite understand what happens when you create this kind of function... does the value of 'i' not get stored with the function?
I would actually expect it to store i there, since you're creating the function within i's scope. Try adding a GUI.Msg(i) in the function as well to see if it's being called and if it has i.

Regardless, there is a better way to do what you want - Buttons already have a hook for running a user function, and it specifically does take extra parameters.

Code:
ctl.func = select -- note: no ()s here
ctl.params = {i}
Everything in params is unpacked and passed as arguments to func.
Lokasenna is online now   Reply With Quote
Old 06-30-2019, 08:47 PM   #511
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

oh cool. I couldn't figure out how to give func arguments....
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 07-07-2019, 03:43 AM   #512
zookthespook
Human being with feelings
 
Join Date: Mar 2015
Posts: 518
Default

As My coding skills have barely reached the "hello world " level , i hope to see this script going the plogue Bidule or CTRLR way where logic\code could be connected through visual elements too !!
regardless huge fan of your work , your radial menu

cheers
zook
zookthespook is offline   Reply With Quote
Old 07-07-2019, 08:36 AM   #513
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,029
Default

Quote:
Originally Posted by zookthespook View Post
As My coding skills have barely reached the "hello world " level , i hope to see this script going the plogue Bidule or CTRLR way where logic\code could be connected through visual elements too !!
regardless huge fan of your work , your radial menu

cheers
zook
It's a nice idea, and it is on my list of things to look into when I have a chance. I've also thought about replicating Cubase's Project Logical Editor which would end up being fairly similar under the hood.

In the meantime, the current version of the library does have a visual editor for setting up a script GUI - after exporting it, you would just have to write the code to make the buttons and sliders actually do something in Reaper.
Lokasenna is online now   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 09:42 AM.


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