Go Back   Cockos Incorporated Forums > REAPER Forums > ReaScript, JSFX, REAPER Plug-in Extensions, Developer Forum

Reply
 
Thread Tools Display Modes
Old 12-13-2022, 12:20 PM   #281
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Quote:
Originally Posted by tack View Post
rtk should by default open windows on the primary display, based on what your OS thinks the primary display is. Is this not what you're seeing? Or if it is, how do you think it should work?
Thats what I see yes, I would like to place window on secondary or third display
or even fourth display if its possible. In the future I will eventually get a
fourth display...
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 12-13-2022, 12:48 PM   #282
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by tompad View Post
Thats what I see yes, I would like to place window on secondary or third display
or even fourth display if its possible. In the future I will eventually get a
fourth display...
For that you'll need to use the x and y rtk.Window attributes to influence the display the window will be placed on.

If this is a script other people will use, I recommend just storing the user's last choice of geometry (the x, y, w and h window attributes) via reaper.SetExtState(), and then restoring those values on next startup.
tack is offline   Reply With Quote
Old 12-16-2022, 11:09 AM   #283
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 813
Default

Quote:
Originally Posted by tack View Post
For that you'll need to use the x and y rtk.Window attributes to influence the display the window will be placed on.

If this is a script other people will use, I recommend just storing the user's last choice of geometry (the x, y, w and h window attributes) via reaper.SetExtState(), and then restoring those values on next startup.
Great - thanks!
__________________
ToDoList Obliques MusicMath Donation Some of mine and my friends music projects on Spotify
tompad is offline   Reply With Quote
Old 12-19-2022, 09:46 AM   #284
binbinhfr
Human being with feelings
 
binbinhfr's Avatar
 
Join Date: Oct 2021
Location: France
Posts: 363
Default

Hi Tack,

about window:resize(), that's ok now with the new master, it does not crash anymore.

scrolltoview still have the same problem, but I suppose that it's normal, because you did not say explicitely that you corrected it yet.

About framerate warnings :
I suppose that these warnings are normal, because when I first create the window and all the widgets, it takes time and possibly more than 1/30s ?

But I do not have the MIDI editor open at all. Just the basic arrange view with mixer on bottom.

Quote:
Are you triggering animations right away at startup then, as opposed to afterwards in response to some user interaction?
Infact when creating buttons, I update them just afterwards, with functions like this one :
Code:
function gui_update_reagig_enabled(b)
  but_enabled:attr("label", (b and "ON" or "OFF"))
  but_enabled:animate{'color', dst = (b and "green" or "red")}
end
Because I want these buttons to change label and color depending on their state.
Could it be part of the problem ?

Note that after the window creation, I do not have anymore framerate warnings.
__________________
Reaper's lunatic
Reapack repository / GitHub / SoundCloud / Donate
binbinhfr is offline   Reply With Quote
Old 12-25-2022, 09:03 AM   #285
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

Hey tack, Happy Holidays!

Circling back with the old FR to add some ability to control display of Checkbox widgets! Would be great to be able to:
  • Alter the checkbox size, color, border, etc.
  • Adjust the box models around checkbox & label separately
MonkeyBars is offline   Reply With Quote
Old 12-30-2022, 02:43 PM   #286
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default BR: Nested OptionMenu submenu won't select

Hi!

I never had any issues setting OptionMenu submenu items as selected programatically based on their IDs, but if I nest another submenu inside the submenu, selection of the ID no longer does anything.

I even tried calling :attr() directly on the option in question (like OptionMenu.menu[4].submenu[1].submenu[1]) but I don't think the attr() method is meant to be called like that and it doesn't work either.

Is this an rtk bug?
MonkeyBars is offline   Reply With Quote
Old 01-16-2023, 02:50 PM   #287
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

I have a user whose subwindow isn't displaying properly. I can't reproduce it on my system. Any input you may provide on its cause would be appreciated. Thanks tack!
MonkeyBars is offline   Reply With Quote
Old 02-21-2023, 02:52 PM   #288
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

At some point, shrinkwrapping broke for all my windows.

I am using 1.3.0 stable release, but 1.3.0-2-g765a765-dev doesn't behave any differently.

You can sync and take a look at my projects Superglue (action: Open Options Window) and Buss Driver to see the current behavior.

I tried a few different configurations and couldn't get the windows to adjust their height at all (unless I set it directly with h).

Maybe some behavior changed and there is a new trick to get shrinkwrapping working? I'm all ears. Thanks tack.
MonkeyBars is offline   Reply With Quote
Old 02-22-2023, 03:26 PM   #289
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

I'm terribly behind on this thread. Deepest apologies. It's been a challenge to find time for personal projects in the past few months.

Quote:
Originally Posted by MonkeyBars View Post
At some point, shrinkwrapping broke for all my windows.
Can you elaborate a bit more on "at some point"? At some point in your own script's development, or at some point with rtk?

I'll take a look at your latest Superglue version, but just wondered if the problem started based on a change in Superglue or a change in rtk. (Will give me a better idea of where to look through historical changes to get a proper sense of what the bug in rtk might be.)
tack is offline   Reply With Quote
Old 02-22-2023, 03:44 PM   #290
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

Quote:
Originally Posted by tack View Post
Can you elaborate a bit more on "at some point"? At some point in your own script's development, or at some point with rtk?
At some point with rtk. The same Superglue and Buss Driver code that used to result in an autoshrunk Window now produces one with the same height every time and a scrollbar in the Viewport.
MonkeyBars is offline   Reply With Quote
Old 03-17-2023, 04:31 PM   #291
wnlowe
Human being with feelings
 
Join Date: Aug 2022
Posts: 2
Default

Hi! I am attempting to access the docked attribute from an rtk.Window I have configured.

Code:
win = rtk.Window{w=640, h=480, halign = 'center', title='WNL Render Settings'}
log.info(win.docked)
and I am always returning nil. My understanding would be since it has a default value, if I have not set the attribute then when I access that attribute it will return its default value of false. I have moved the log.info around. After the winpen() and in a win function like win.onmove. I am sure I am doing something wrong but I am not at all sure what it is. Thank you so much for your help!
wnlowe is offline   Reply With Quote
Old 03-17-2023, 04:40 PM   #292
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

have you tried
Code:
win:attr("docked")
MonkeyBars is offline   Reply With Quote
Old 03-17-2023, 04:42 PM   #293
wnlowe
Human being with feelings
 
Join Date: Aug 2022
Posts: 2
Default

Quote:
Originally Posted by MonkeyBars View Post
have you tried
Code:
win:attr("docked")
Yes, both that and
Code:
 win:calc('docked')
both also return nil.
wnlowe is offline   Reply With Quote
Old 03-25-2023, 10:10 AM   #294
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

Quote:
Originally Posted by MonkeyBars View Post
I never had any issues setting OptionMenu submenu items as selected programatically based on their IDs, but if I nest another submenu inside the submenu, selection of the ID no longer does anything.

I even tried calling :attr() directly on the option in question (like OptionMenu.menu[4].submenu[1].submenu[1]) but I don't think the attr() method is meant to be called like that and it doesn't work either.
Hi tack!

This bug is a real high-priority blocker imo. If you have a moment to take a look and see if you could compile a fix release addressing it, that would really help me. Development on Buss Driver is completely stonewalled due to the issue of subsubmenus essentially being useless in rtk forms since their values cannot be retrieved.
MonkeyBars is offline   Reply With Quote
Old 03-25-2023, 10:14 AM   #295
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Sorry I'm so far behind all. It continues to be a challenge to find free moments to keep these plates spinning. Thanks for calling this out as a blocker, MonkeyBars. I am out of town again this weekend but I will look into it some evening next week. Apologies for leaving you all hanging for so long!
tack is offline   Reply With Quote
Old 03-25-2023, 10:57 AM   #296
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

Quote:
Originally Posted by tack View Post
Thanks for calling this out as a blocker, MonkeyBars. I am out of town again this weekend but I will look into it some evening next week. Apologies for leaving you all hanging for so long!
No problem man! That timing sounds perfect
MonkeyBars is offline   Reply With Quote
Old 03-30-2023, 02:35 PM   #297
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by MonkeyBars View Post
No problem man! That timing sounds perfect
Aaaannnd I need to reneg again. The last three weekends out of town (and at super spreader events) has caught up with me and I've picked up a bug which is in the process of kicking my ass. (I think it's just a bad cold, but when I get colds I barely sleep so I end up just generally getting destroyed.)

I'm home this weekend though, and so I'm hoping I'll cross the apex of this thing soon and will be able to use that time productively.

I just wanted to let you know this is still high up on my to-do list.
tack is offline   Reply With Quote
Old 03-30-2023, 03:17 PM   #298
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

Quote:
Originally Posted by tack View Post
I just wanted to let you know this is still high up on my to-do list.
No problem sir, get well soon!!
MonkeyBars is offline   Reply With Quote
Old 03-31-2023, 12:16 AM   #299
binbinhfr
Human being with feelings
 
binbinhfr's Avatar
 
Join Date: Oct 2021
Location: France
Posts: 363
Default

Quote:
Originally Posted by tack View Post
I think it's just a bad cold,
Hi Tack, hope you will recover from this bad cold. "Santé !" as we say in France ! ;-)
__________________
Reaper's lunatic
Reapack repository / GitHub / SoundCloud / Donate
binbinhfr is offline   Reply With Quote
Old 04-02-2023, 12:00 PM   #300
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by wnlowe View Post
Code:
win = rtk.Window{w=640, h=480, halign = 'center', title='WNL Render Settings'}
log.info(win.docked)
This will actually log an exception on the console because the first argument to log.info() takes a format string. So it should be:

Code:
win = rtk.Window{w=640, h=480, halign='center', title='WNL Render Settings'}
log.info("%s", win.docked)
And for me this does log "false" to the console.
tack is offline   Reply With Quote
Old 04-02-2023, 12:20 PM   #301
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by MonkeyBars View Post
I never had any issues setting OptionMenu submenu items as selected programatically based on their IDs, but if I nest another submenu inside the submenu, selection of the ID no longer does anything.
I should have saved us some time and preemptively asked you for an example.

I assembled my own example of a submenu inside a submenu but couldn't reproduce any weirdness around the item ids. When selecting an item interactively, the "selected" attribute corresponds with the selected item's id. And setting the item programmatically based on the id works too, both when initializing the selected attribute on the constructor, and afterward via the attr() API.

Can you tailor this example to reproduce the bug? Or maybe I've misunderstood what you mean by "selection of the ID"?

Code:
    local window = rtk.Window{padding=10}
    local hbox = window:add(rtk.HBox{spacing=10})
    local menu = hbox:add(rtk.OptionMenu{selected='sub-1'})
    menu:attr('menu', {
        {'Top item', id='top'},
        {'Submenu', submenu={
            {'Sub Item 1', id='sub-1'},
            {'Sub Item 2', id='sub-2'},
            {'Nested Submenu', submenu={
                {'Nested Item 1', id='nested-1'},
                {'Nested Item 2', id='nested-2'},
            }}
        }},
        rtk.NativeMenu.SEPARATOR,
        {'Bottom Item', id='bottom'},
    })
    menu.onchange = function(self, item, lastitem)
        log.info('selected item id: %s (should be the same as %s)', item.id, menu.selected)
    end
    hbox:add(rtk.Button{'Set Programmatically', onclick=function()
        menu:attr('selected', 'nested-2')
    end})
    window:open()
tack is offline   Reply With Quote
Old 04-02-2023, 06:21 PM   #302
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

Quote:
Originally Posted by tack View Post
I assembled my own example of a submenu inside a submenu but couldn't reproduce any weirdness around the item ids. When selecting an item interactively, the "selected" attribute corresponds with the selected item's id.
I am using "selected_id" but "selected" doesn't work for me either. My first test is just to get the selected ID, and later I'll need to set it as well. First things first

Quote:
Can you tailor this example to reproduce the bug?
Thanks for the test code. I added rtk and log=rtk.log but the onchange isn't kicking anything at all out to my console when I select various dropdown options. Am I using the wrong version of rtk or something? I've got v1.3.0

I DM'd you the dev code I'm using for Buss Driver

Last edited by MonkeyBars; 04-02-2023 at 06:27 PM.
MonkeyBars is offline   Reply With Quote
Old 04-02-2023, 06:32 PM   #303
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by MonkeyBars View Post
Thanks for the test code. I added rtk and log=rtk.log but the onchange isn't kicking anything at all out to my console when I select various dropdown options. Am I using the wrong version of rtk or something? I've got v1.3.0
Ah, it's just that the default log level is ERROR so log.info() gets filtered out. My usual top-of-file boilerplate for my various test files sets it to DEBUG.

Here's a complete copy/paste example using the ReaPack install, tested with v1.3.0.

Code:
package.path = reaper.GetResourcePath() .. '/Scripts/rtk/1/?.lua'
local rtk = require('rtk')
local log = rtk.log
log.level = log.DEBUG

local function main()
    local window = rtk.Window{padding=10}
    local hbox = window:add(rtk.HBox{spacing=10})
    local menu = hbox:add(rtk.OptionMenu{selected='sub-1'})
    menu:attr('menu', {
        {'Top item', id='top'},
        {'Submenu', submenu={
            {'Sub Item 1', id='sub-1'},
            {'Sub Item 2', id='sub-2'},
            {'Nested Submenu', submenu={
                {'Nested Item 1', id='nested-1'},
                {'Nested Item 2', id='nested-2'},
            }}
        }},
        rtk.NativeMenu.SEPARATOR,
        {'Bottom Item', id='bottom'},
    })
    menu.onchange = function(self, item, lastitem)
        log.info('selected item id: %s (should be the same as %s)', item.id, menu.selected)
    end
    hbox:add(rtk.Button{'Set Programmatically', onclick=function()
        menu:attr('selected', 'nested-2')
    end})
    window:open()
end

rtk.call(main)
tack is offline   Reply With Quote
Old 04-02-2023, 06:54 PM   #304
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

Quote:
Originally Posted by tack View Post
Ah, it's just that the default log level is ERROR so log.info() gets filtered out. My usual top-of-file boilerplate for my various test files sets it to DEBUG.
Ah ok thanks. Your test code definitely works. I'll try to identify where my code differs.

Edit: I figured out my issue – it's not rtk after all! Thank you so much for having a look.

Meanwhile if you do have a cycle or two to spare, it would be amazing if you took a look at Buss Driver and/or Superglue from my repo as the main window and options window respectively no longer shrinkwrap height to content. I don't know exactly which rtk version the bug started during...

Last edited by MonkeyBars; 04-02-2023 at 07:16 PM.
MonkeyBars is offline   Reply With Quote
Old 04-03-2023, 09:43 AM   #305
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by MonkeyBars View Post
Edit: I figured out my issue – it's not rtk after all! Thank you so much for having a look.
Great! Glad you got that sorted.

Quote:
Originally Posted by MonkeyBars View Post
Meanwhile if you do have a cycle or two to spare, it would be amazing if you took a look at Buss Driver and/or Superglue from my repo as the main window and options window respectively no longer shrinkwrap height to content. I don't know exactly which rtk version the bug started during...
I'll see what I can find. I had a very quick test with the code you PMed me and it looks ok:



Remind me what platform you primarily use again? May be one of those things that bugs out on Mac retina systems. I can test it out more thoroughly this evening.
tack is offline   Reply With Quote
Old 04-03-2023, 10:33 AM   #306
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

Quote:
Originally Posted by tack View Post
I'll see what I can find. I had a very quick test with the code you PMed me and it looks ok:



Remind me what platform you primarily use again? May be one of those things that bugs out on Mac retina systems. I can test it out more thoroughly this evening.
I'm on a Mac with non-Apple external monitors, so I don't know if it counts as retina.

Looks like your window is quite wide there, so I recommend perhaps increasing your Reaper UI scaling to 1.33 and adding another 75 tracks or whatever to your project so you can really test the height expansion for BD.

Meanwhile please try the script "Script: MB_Superglue - Options - Global - Open script options window.lua" and see how that looks. May be a more stable test of shrinkwrap.
MonkeyBars is offline   Reply With Quote
Old 04-20-2023, 08:37 AM   #307
MonkeyBars
Human being with feelings
 
MonkeyBars's Avatar
 
Join Date: Feb 2016
Location: Hollyweird
Posts: 2,637
Default

By the way, I finally figured out the main issues I was having with rtk's OptionMenu behavior - again, thanks for the test file. I think I was confusing rtk with the "selected" attr by using type number for id's, and even labels. I guess rtk was trying to parse whether to use index or id and choosing wrong or something. It seems to work much better with strings for both these option attributes.

Perhaps a note ought to be added to the rtk docs about this.

Last edited by MonkeyBars; 04-20-2023 at 03:30 PM.
MonkeyBars is offline   Reply With Quote
Old 05-28-2023, 12:00 AM   #308
erikmartinez
Human being with feelings
 
erikmartinez's Avatar
 
Join Date: Feb 2023
Location: Kazakhstan
Posts: 204
Default

Hi bro! I'm using your RTK library for my tool, and I've been trying to figure out two things for quite some time:
Is it possible to make the sliders return to their original position, either by double-clicking them or by assigning a button for that purpose?
How can I restart a script from within the script itself? I encountered a problem when trying to restart within the main script. It opens a window inside a window, as if duplicating it. I've tried various approaches, but unfortunately, none of them have worked so far.
I really like your library, not only because it looks great but also because it's fast! I'm currently working on my first script tool for handling MIDI using your library. I haven't started working on others yet, but in my opinion, they generally have a small input delay.
I also couldn't figure out how to scale everything inside the window, specifically by increasing its size. If these questions seem silly, I apologize!
erikmartinez is offline   Reply With Quote
Old 05-28-2023, 06:46 PM   #309
lexaproductions
Human being with feelings
 
Join Date: Jan 2013
Posts: 1,128
Default

Hi Tack,
Total newbie here. This is very comprehensive! Was trying to find how to position the labels next to a checkbox. By default it goes on the right, but I'm trying to put it on the left.

I'm really starting with your framework. Thanks for the time. Will donate for sure.
lexaproductions is offline   Reply With Quote
Old 05-29-2023, 04:36 PM   #310
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by erikmartinez View Post
Is it possible to make the sliders return to their original position, either by double-clicking them or by assigning a button for that purpose?
You can set sliders programmatically by calling attr() and setting the 'value' attribute. If you want a separate reset button:

Code:
local b = somebox:add(rtk.Button{'Reset'})
b.onclick = function()
   slider:attr('value', 0)
end
(That assumes somebox and slider were defined somewhere else.)

In theory you can also set a double-click handler on the slider itself, resetting it when the slider is double-clicked.

In practice, there's a small bug in rtk preventing this working as it should, because the slider's position begins an animation when you click the first time, if it's still animating when the second click comes in the doubleclick, the animation ends up clobbering the programmatically set value. This is a bug which I'll fix, but in the meantime you can easily work around it yourself by cancelling the existing animation on the 'value' attribute before setting the value.

Here's a complete example that resets the slider to 0 when it's double clicked. Of course, you can set the "reset value" to whatever you like, just change the call to attr() accordingly.

Code:
package.path = reaper.GetResourcePath() .. '/Scripts/rtk/1/?.lua'
local rtk = require('rtk')

local function main()
    local win = rtk.Window{padding=20, minw=400}
    local slider = win:add(rtk.Slider())
    slider.ondoubleclick = function()
        slider:cancel_animation('value')
        slider:attr('value', 0)
    end
    win:open()
end

rtk.call(main)
Quote:
Originally Posted by erikmartinez View Post
How can I restart a script from within the script itself? I encountered a problem when trying to restart within the main script. It opens a window inside a window, as if duplicating it. I've tried various approaches, but unfortunately, none of them have worked so far.
At first I thought this wasn't really an rtk-specific question but more of a general ReaScript question of how to restart scripts, but the "window inside a window" thing is throwing me. Can you elaborate a bit more what you mean?

Quote:
Originally Posted by erikmartinez View Post
I also couldn't figure out how to scale everything inside the window, specifically by increasing its size.
Scaling the window contents can be done by setting rtk.scale.user to something other than its default of 1.0.

Quote:
Originally Posted by erikmartinez View Post
If these questions seem silly, I apologize!
Not at all! If the search function in the documentation isn't helping, by all means ask away.
tack is offline   Reply With Quote
Old 05-29-2023, 04:40 PM   #311
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by lexaproductions View Post
Was trying to find how to position the labels next to a checkbox. By default it goes on the right, but I'm trying to put it on the left.
rtk.CheckBox is a subclass of rtk.Button, so all the attributes from rtk.Button apply there as well.

In particular the one you want is iconpos, because with rtk.CheckBox, the checkbox itself is actually the icon. So if you set iconpos to 'right' then the label will appear to the left of the checkbox.

Code:
somebox:add(rtk.CheckBox{'This is on the left side now', iconpos='right'})
Hope that helps!
tack is offline   Reply With Quote
Old 05-30-2023, 11:15 PM   #312
erikmartinez
Human being with feelings
 
erikmartinez's Avatar
 
Join Date: Feb 2023
Location: Kazakhstan
Posts: 204
Default

Quote:
Originally Posted by tack View Post
You can set sliders programmatically by calling attr() and setting the 'value' attribute. If you want a separate reset button:

Code:
local b = somebox:add(rtk.Button{'Reset'})
b.onclick = function()
   slider:attr('value', 0)
end
(That assumes somebox and slider were defined somewhere else.)

In theory you can also set a double-click handler on the slider itself, resetting it when the slider is double-clicked.

In practice, there's a small bug in rtk preventing this working as it should, because the slider's position begins an animation when you click the first time, if it's still animating when the second click comes in the doubleclick, the animation ends up clobbering the programmatically set value. This is a bug which I'll fix, but in the meantime you can easily work around it yourself by cancelling the existing animation on the 'value' attribute before setting the value.

Here's a complete example that resets the slider to 0 when it's double clicked. Of course, you can set the "reset value" to whatever you like, just change the call to attr() accordingly.

Code:
package.path = reaper.GetResourcePath() .. '/Scripts/rtk/1/?.lua'
local rtk = require('rtk')

local function main()
    local win = rtk.Window{padding=20, minw=400}
    local slider = win:add(rtk.Slider())
    slider.ondoubleclick = function()
        slider:cancel_animation('value')
        slider:attr('value', 0)
    end
    win:open()
end

rtk.call(main)

At first I thought this wasn't really an rtk-specific question but more of a general ReaScript question of how to restart scripts, but the "window inside a window" thing is throwing me. Can you elaborate a bit more what you mean?


Scaling the window contents can be done by setting rtk.scale.user to something other than its default of 1.0.


Not at all! If the search function in the documentation isn't helping, by all means ask away.
Wow! You really solved my problems, it's great! I am still regularly surprised by the flexibility of your work. About rescaling:
While trying to make a restart function, I found out that dofile () runs scripts in the context of the current one. And if you start, conditionally, another version in this way, it turns out as if there are two or more windows in one, in general, I implemented another chip in this way, but still, by resetting the slider value, you can make the reset function more concise. And the documentation, in my opinion, is quite clear, it's just that I've only been learning to write scripts for the fifteenth day
erikmartinez is offline   Reply With Quote
Old 06-02-2023, 11:08 AM   #313
erikmartinez
Human being with feelings
 
erikmartinez's Avatar
 
Join Date: Feb 2023
Location: Kazakhstan
Posts: 204
Default

I tried to scale the window as follows, but the problem is that when you try to change the scale from the corner of the window, it, along with the overall scale, also changes the width and height of the window.

I'd like to have a fixed proportional height and width, but I don't really understand how to implement it. I'll attach screenshots for clarity.

local window = rtk.Window{
y = 125,
expand=true,
opacity = 0.96,
borderless = true,
title = 'mdtool',

fillh=true,
fillw=true,
maxw=245,
maxh=680,
resizable =true

}

function windownresize()
local newWidth, newHeight = window.w, window.h
local baseWidth, baseHeight = 245, 680
local scale = math.min(newWidth / baseWidth, newHeight / baseHeight)
local scaledWidth = baseWidth * scale
local scaledHeight = baseHeight * scale

window.w = scaledWidth
window.h = scaledHeight
rtk.scale.value = scale
rtk.scale.user = scale

end
Attached Images
File Type: jpeg photo1685776311.jpeg (32.9 KB, 58 views)
File Type: jpeg photo1685776325.jpeg (21.3 KB, 60 views)
File Type: jpeg photo1685776342.jpeg (36.9 KB, 67 views)

Last edited by erikmartinez; 06-03-2023 at 12:20 AM.
erikmartinez is offline   Reply With Quote
Old 06-04-2023, 12:53 PM   #314
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by erikmartinez View Post
I'd like to have a fixed proportional height and width, but I don't really understand how to implement it.
You can adjust rtk.scale.user in response to a resize, but hooking resize to constrain dimensions before the resize occurs isn't currently possible. And any time you try to resize the window programmatically in response to a notification of resize after the it already occurred, it's going to be extremely janky.

It would in theory be possible to support this with borderless windows (i.e. rtk.Window{borderless=true}), because in this case rtk implements the resize logic directly. rtk doesn't provide this hook today, but I could add an event handler to support this.

But for non-borderless (i.e. normal bordered) windows, ReaScripts are really just passive observers -- the OS handles resize, and ReaScripts get notified about the size after-the-fact. In this case, you may be able to get ahead of this with JS_WindowMessage_Intercept(), but I am not sure how because AFAICT you'd need to intercept WM_SIZING which isn't one of the supported event types. You could ask on the JSAPI thread if that's possible.

Meanwhile I know I can definitely support this for borderless windows, because that's fully in control of rtk, but would require a change to rtk to surface this hook. Let me know if you're interested.


Quote:
Originally Posted by erikmartinez View Post
local window = rtk.Window{
y = 125,
expand=true,
opacity = 0.96,
borderless = true,
title = 'mdtool',

fillh=true,
fillw=true,
maxw=245,
maxh=680,
resizable =true
}
FWIW, expand won't do anything (it's not a valid attribute on rtk.Window) and fillw/fillh, while technically defined in rtk.Widget, don't have any meaning for rtk.Window. (What would you expect them to do?) They don't hurt anything, but you could remove them.

Quote:
Originally Posted by erikmartinez View Post
window.w = scaledWidth
window.h = scaledHeight
This doesn't do what you think it does. If you want to set attributes, use attr(). For example, window:attr('w', somevalue). Read the section on widget attributes for more context.

But then you don't want to do that either in onresize() because as I said above, this ends up resizing the window after it was already sized, so in practice the window is going to bounce around in annoying ways.

Quote:
Originally Posted by erikmartinez View Post
rtk.scale.value = scale
rtk.scale.user = scale
Don't set rtk.scale.value. Per the documentation this is a read-only calculated value used for manual drawing purposes.

But you can set rtk.scale.user inside onresize(), that should work properly.
tack is offline   Reply With Quote
Old 06-13-2023, 07:06 AM   #315
erikmartinez
Human being with feelings
 
erikmartinez's Avatar
 
Join Date: Feb 2023
Location: Kazakhstan
Posts: 204
Default

Thanks for the feedback! Are you planning to add vertical or circular sliders in the near future?
erikmartinez is offline   Reply With Quote
Old 08-03-2023, 06:42 AM   #316
AZpercussion
Human being with feelings
 
Join Date: Oct 2019
Location: Moscow / Tbilisi
Posts: 914
Default

Hi, Tack! Thanks for the great library!
It's really well documented, but I can't figured out a couple things:

1. How can I addres to widget's attribute if the widget included into a screen via app:add_screen?

2. Does a preferable place for loops exist? As example I need to check amount of selected tracks and draw it into text widget.
Should I use a separate looped function or it's possible to include this function in widget's methods directly?
AZpercussion is offline   Reply With Quote
Old 08-03-2023, 05:23 PM   #317
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Hey AZpercussion,

Quote:
Originally Posted by AZpercussion View Post
1. How can I addres to widget's attribute if the widget included into a screen via app:add_screen?
The table you pass Application:add_screen() contains a screen name, which you can then access by that name via the screens attribute.

See https://reapertoolkit.dev/class/rtk....cation.screens for an example.

That's how you can get access to the widget you passed to add_screen(). If you want to access child widgets within that, you can either manually assign those children to variables you track and access yourself, or you can use widget refs (see the example below as well where that's used).

Quote:
Originally Posted by AZpercussion View Post
2. Does a preferable place for loops exist? As example I need to check amount of selected tracks and draw it into text widget.
Sounds like you're looking for something to run continuously "in the background" (so to speak) so that you can update the GUI based on some REAPER state?

The best way to do this is to hook the rtk.Window.onupdate event handler. See https://reapertoolkit.dev/class/rtk....indow.onupdate.

Here's an example that continuously updates the UI to show the current number of tracks in the project.

Code:
-- Assumes you've already imported rtk

local function main()
    local win = rtk.Window{
        padding=20,
        rtk.HBox{
            spacing=5,
            rtk.Text{'Number of tracks:'},
            rtk.Text{ref='ntracks'}
        }
    }
    win.onupdate = function()
        win.refs.ntracks:attr('text', reaper.GetNumTracks())
    end
    win:open()
end

rtk.call(main)
Hope that helps!
tack is offline   Reply With Quote
Old 08-19-2023, 11:51 AM   #318
erikmartinez
Human being with feelings
 
erikmartinez's Avatar
 
Join Date: Feb 2023
Location: Kazakhstan
Posts: 204
Default

Hwy, Tack!went back to your library and some questions came up.
1. How to create a real-time active volume indicator after getting the volume of a track?
The only thing that came to mind was to get the volume of the track and change the position of the horizontal slider
2. How can I make the reaper shortcuts go through the window RТК?
3. How did you make drag widgets? moving widgets under the pressed LMB among stacks of other widgets (conditionally).
4. And an open question about vertical sliders, either buttons that track the vertical slide with the mouse, or knobs. Do you plan to update the library with these new widgets?

thanks for your great work!
erikmartinez is offline   Reply With Quote
Old 08-19-2023, 04:44 PM   #319
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 1,619
Default

Quote:
Originally Posted by erikmartinez View Post
1. How to create a real-time active volume indicator after getting the volume of a track?
The only thing that came to mind was to get the volume of the track and change the position of the horizontal slider
I don't think rtk.Slider is an ideal approach for meters; sliders are really meant for interactivity. And of course as you know there's no vertical slider yet.

There a few possible ways to deal with this, for example:
  1. Create an rtk.VBox with a number of cells and set a non-transparent background on the cells necessary to render a meter-looking box based on the current level. One could even use the rtk.VBox spacing attribute to add spacing between the cells to give a kind of LCD look to the meter.
  2. Create an rtk.Spacer and draw manually in the spacer, as shown in the example for the rtk.Spacer docs
  3. Create a custom meter widget that implements one of the above strategies

Personally I'd go with a custom widget that draws the meter directly. This gives the most flexibility to customize appearance and behavior. I'd subclass rtk.Spacer (one of my regrets is not calling that rtk.Canvas, because that's basically what it's best used for -- I will probably rename it in the future).

Here's an example implementation of a vertical multi-channel volume meter widget, with a helper method to set the current meter level based on particular track (VolumeMeter:set_from_track()). The window will show the volume level of the currently selected track.

The widget is pretty basic but shows the concept. It subclasses rtk.Spacer (which is just a tiny bit easier than directly subclassing rtk.Widget because rtk.Spacer's default draw method is a bit more complete, allowing VolumeMeter to just implement _handle_draw()). It has a few attributes to control basic appearance, but the main attribute is the "levels" attribute which is a table that contains the 0.0-1.0 floating point value of each channel's level.

Drawing ticks and labels, gradients, >0dB, peak value label, etc. (the usual meter-y things) is left as an exercise for the reader.

Code:
VolumeMeter = rtk.class('VolumeMeter', rtk.Spacer)
VolumeMeter.register{
    -- Current level of each channel for the meter where 0=-inf and 1=+0dB
    levels = rtk.Attribute{default={0, 0}},
    -- Number of pixels of spacing between channels in the meter
    spacing = rtk.Attribute{default=3},
    -- Minimum visible dB
    mindb = rtk.Attribute{default=-64},
    -- Color of the meter
    color = rtk.Attribute{type='color', default='cornflowerblue'},
    -- Opacity of the gutter (drawn in color)
    gutter = rtk.Attribute{default=0.08},

    -- Override base class height so we default to the full height of parent container
    h = 1.0,
}

function VolumeMeter:initialize(attrs, ...)
    rtk.Spacer.initialize(self, attrs, VolumeMeter.attributes.defaults, ...)
end

function VolumeMeter:_handle_draw(offx, offy, alpha, event)
    local calc = self.calc
    local x = offx + calc.x
    -- Bottom of widget
    local y = offy + calc.y
    -- Total dB covered by meter
    local range = math.abs(calc.mindb)
    -- Width of each channel meter, accounting for spacing
    local chw = (calc.w - (calc.spacing * (#calc.levels - 1))) / #calc.levels
    -- Draw the gutter
    self:setcolor(calc.color)
    gfx.a = calc.gutter
    gfx.rect(x, y, calc.w, calc.h)
    gfx.a = 1

    for _, level in ipairs(calc.levels) do
        -- Current level in dB
        local db = 20 * math.log(level, 10)
        -- Height of the channel in pixels based on the current level
        local chh = (rtk.clamp(db, calc.mindb, 0) + range) / range * calc.h
        -- Draw the level
        gfx.rect(x, y + calc.h - chh, chw, chh)
        -- Advance x position for next channel
        x = x + chw + calc.spacing
    end
end

function VolumeMeter:set_from_track(track, maxch)
    if not reaper.ValidatePtr2(0, track, 'MediaTrack*') then
        self:attr('levels', {0})
        return
    end
    local levels = {}
    -- Number of channels for this track clamped by maxch if provided
    local nch = rtk.clamp(reaper.GetMediaTrackInfo_Value(track, 'I_NCHAN'), 0, maxch)
    for i = 0, nch - 1 do
        levels[#levels+1] = reaper.Track_GetPeakInfo(track, i)
    end
    self:attr('levels', levels)
end


local function main()
    local win = rtk.Window{
        h=600, padding=20, halign='center',
        VolumeMeter{ref='meter', w=30},
    }
    win.onupdate = function()
        win.refs.meter:set_from_track(reaper.GetSelectedTrack2(0, 0, true))
    end
    win:open()
end

rtk.call(main)
(If you do add labels yourself, I strongly recommend using rtk.Font to draw the text rather than using gfx.drawstr().)

I really need to add a section to the docs on how to create custom widgets. It's not as scary as it sounds, and gives a bunch of flexibility when you want something visually that rtk can't do natively.


Quote:
Originally Posted by erikmartinez View Post
2. How can I make the reaper shortcuts go through the window RТК?
You mean when an rtk window is focused, to have uncaught keystrokes pass through to REAPER's main window?

This is more of a general ReaScript question than an rtk one. I did actually look into this a couple years ago for Reaticulate and it's truly nontrivial.

At least it was at the time. Google brought me to https://forum.cockos.com/showthread.php?t=273404 which suggests recent API changes in REAPER may now make this possible.

I can't vouch for FeedTheCat's sample code but it looks like a very good place to start.

Quote:
Originally Posted by erikmartinez View Post
3. How did you make drag widgets? moving widgets under the pressed LMB
among stacks of other widgets (conditionally).
In a nutshell, by using a box (rtk.HBox or rtk.VBox) and reordering the cells in the box based on what's dragged where.

I don't have a ready-made standalone example for you. I could make one, though not tonight. Instead, I'll point you to the implementation from Reaticulate where articulation maps assigned to a track can be reordered by click-dragging on a drag handle image.

Start here: https://github.com/jtackaberry/reati...ckcfg.lua#L394 and note that:
  • bankbox represents a single bank on the track and is a draggable widget inside the reorderable box (the outer VBox that contains all bankboxes called screen.banklist)
  • bankbox.ondropfocus (line 394) returns true to ensure it's a valid drop target for other bankboxes
  • bankbox.ondropmousemove (line 397) calls screen.move_bankbox() to reorder the banklist dynamically as another bankbox is being moved over top that one
  • Line 409 creates the drag handle image to provide a visual cue to the user of draggability
  • Line 419 adds an ondragstart handler to the drag handle image which changes the visual appearance of the now-dragging bankbox to indicate something is happening
  • Line 425 adds an ondragend handler to restore the bankbox's appearance now that the drag operation has completed
  • Line 71 is a cheeky but effective hack that creates an invisible drop target right below the banklist VBox so if user drags a bankbox right at the bottom of the screen (rather than over another bankbox) it will still move the dragging bankbox to the end.
  • Line 351 is screen.move_bankbox() which handles reordering the banklist VBox based on the source and target widget positions.

Quote:
Originally Posted by erikmartinez View Post
4. And an open question about vertical sliders, either buttons that track the vertical slide with the mouse, or knobs. Do you plan to update the library with these new widgets?
I definitely plan to, I just don't know exactly when.
tack is offline   Reply With Quote
Old 08-23-2023, 08:40 AM   #320
erikmartinez
Human being with feelings
 
erikmartinez's Avatar
 
Join Date: Feb 2023
Location: Kazakhstan
Posts: 204
Default

Hey Tack! I managed to create somewhat similar vertical sliders, but my code looks pretty awful, but... the most important thing is that it works. I enjoy learning to program with your library!

Here's what one of the possible arpeggiator layouts looks like (the buttons temporarily replace widgets that I'll try to create similarly):



Now I have a question: is it possible, while creating a new instance of the box, to 'narrow down' all the newly created boxes as they get closer to the window's edge? In other words, the more of these widgets I create, the thinner they should become to fit into one screen.

I feel like I still don't know enough about the various ways to implement different graphical ideas with your library, but if you see a way to make it 'prettier' while looking at the GIF, I would be very glad!
erikmartinez 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 07:02 AM.


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