Old 02-20-2019, 09:54 AM   #401
bFooz
Human being with feelings
 
bFooz's Avatar
 
Join Date: Jul 2010
Location: Slovakia
Posts: 1,052
Default

Quote:
Originally Posted by Lokasenna View Post
Nice ideas, thanks.

Why no shadows, out of curiosity? I've always found them really useful.
They are distracting and a user (me) subconsciously think what is their function, what is clickable, what is not, do they represent something? To much visual information.

These days you don't have shadows like this anywhere, they are not necessary for good UI navigation anymore since people get used to computer screens. I have seen a good shadow implementation in Davinci Resolve, where they use wider shadows to indicate which panel goes over which in terms of layering.
__________________
Donations | Mixing & Mastering Services
bFooz is offline   Reply With Quote
Old 02-20-2019, 10:54 AM   #402
mespotine
Human being with feelings
 
mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig, Germany
Posts: 1,558
Default

@lokasenna

Are you interested in cooperating for the rewrite? I'm also planning a Gui-Engine for my Ultraschall-API with event-management-system, separation of GUI and code, multiple gui-windows openable from one script and such, currently building the technical basis for that into my API.

Maybe we could do one Gui to rule them all. Especially, as you are so deep into the whole gfx-thing already, this would be awesome...
__________________
Ultraschall-API - a Lua-functions-library4Reaper: https://forum.cockos.com/showthread....98#post2067798
Reaper Internals - Developerdocs4Reaper: https://forum.cockos.com/showthread.php?t=207635
mespotine is offline   Reply With Quote
Old 02-20-2019, 11:07 AM   #403
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Quote:
Originally Posted by mespotine View Post
@lokasenna

Are you interested in cooperating for the rewrite? I'm also planning a Gui-Engine for my Ultraschall-API with event-management-system, separation of GUI and code, multiple gui-windows openable from one script and such, currently building the technical basis for that into my API.

Maybe we could do one Gui to rule them all. Especially, as you are so deep into the whole gfx-thing already, this would be awesome...
Definitely worth talking about, absolutely.
Lokasenna is offline   Reply With Quote
Old 02-20-2019, 11:24 AM   #404
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Quote:
Originally Posted by bFooz View Post
They are distracting and a user (me) subconsciously think what is their function, what is clickable, what is not, do they represent something? To much visual information.

These days you don't have shadows like this anywhere, they are not necessary for good UI navigation anymore since people get used to computer screens. I have seen a good shadow implementation in Davinci Resolve, where they use wider shadows to indicate which panel goes over which in terms of layering.
I actually find the modern "everything is flat" style frustrating specifically because you *can't* tell which things are clickable, where one area ends, etc. There are times when I have multiple apps and windows open and I have to stop for a second to figure out which one an element belongs to.

One thing I'm hoping to add is a global user config so you can adjust the theming to your taste, in which case "shadow size" will definitely be an option.

Last edited by Lokasenna; 02-20-2019 at 11:43 AM.
Lokasenna is offline   Reply With Quote
Old 02-20-2019, 11:33 AM   #405
_Stevie_
Human being with feelings
 
_Stevie_'s Avatar
 
Join Date: Oct 2017
Posts: 2,788
Default

Quote:
Originally Posted by Lokasenna View Post
I actually find the modern "everything is flat" style frustrating specifically because you *can't* tell which things are clickable, where one area ends, etc. There are times when I have multiple apps and windows open and I have to stop for a second to figure out which one an element belongs to.
I absolutely agree with that.

And a collab between you and mespo sounds amazing
__________________
My Reascripts forum thread | My Reascripts on GitHub | Stephan Römer - film composer
If you wish to donate for my scripts: please consider an organization like: animal shelter, doctors without borders, UNICEF, etc...
_Stevie_ is offline   Reply With Quote
Old 02-21-2019, 06:20 AM   #406
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 372
Default

Collab! That would make a great thing even greater! (Is this possible?);-)

I would also love to see an import-func(save/load) to GUI Builder!

Theming of GUI?
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 02-21-2019, 11:12 AM   #407
xpander
Human being with feelings
 
xpander's Avatar
 
Join Date: Jun 2007
Location: Terra incognita
Posts: 4,845
Default

Quote:
Originally Posted by Lokasenna View Post
I actually find the modern "everything is flat" style frustrating specifically because you *can't* tell which things are clickable, where one area ends, etc.
Same here sometimes. For me it makes it usually quicker to see immediately if something is actually a clickable/adjustable control or e.g. just a shown value or a parameter name.

Quote:
One thing I'm hoping to add is a global user config so you can adjust the theming to your taste, in which case "shadow size" will definitely be an option.
That would be nice.
xpander is offline   Reply With Quote
Old 02-21-2019, 11:40 AM   #408
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Quote:
Originally Posted by tompad View Post
Collab! That would make a great thing even greater! (Is this possible?);-)
I'm hoping for collaborators, absolutely. I'm working on modularizing the existing codebase so it's easier to rewrite separate parts without breaking everything; once that's done, I'll put it on a repo and try to figure out a collaboration process.

Quote:
I would also love to see an import-func(save/load) to GUI Builder!
Yes please.

Quote:
Theming of GUI?
Users being able to set their own global fonts and colors will definitely happen, similar to how Radial Menu does it.
Lokasenna is offline   Reply With Quote
Old 03-03-2019, 03:58 PM   #409
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 741
Default

Quote:
Originally Posted by mespotine View Post
multiple gui-windows openable from one script and such
Is this possible without resorting to spawning multiple scripts under-the-hood by triggering actions? It's not too clear how to do this otherwise as gfx.init() assumes a global context.

I've wished for this for Reaticulate which needs to be able to open a separate window for the bank editor, but for now I'm just invoking a separate action which runs a separate instance. It'd be nice to consolidate this into one script "process" context as the UI library is starting to get pretty weighty.
tack is offline   Reply With Quote
Old 03-03-2019, 04:52 PM   #410
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Quote:
Originally Posted by tack View Post
Is this possible without resorting to spawning multiple scripts under-the-hood by triggering actions? It's not too clear how to do this otherwise as gfx.init() assumes a global context.
mespotine's Ultraschall API has a bunch of functions for opening and running multiple windows. I haven't had a chance to play with them yet, but I'm planning for the next version of my GUI to work with it.

Quote:
It'd be nice to consolidate this into one script "process" context as the UI library is starting to get pretty weighty.
Step 1: Don't have all the code in one file, especially the different widgets that a given script might not need.
Step 2: Don't load files unless the script needs them.

The current version of my GUI does this for the widgets, but I've already refactored the next release to do it for pretty much everything.

Optional Step 3: Just use my GUI instead. :P If you're interested, I'm happy to help with porting everything. Even just using the engine of mine with your own custom classes might save you a lot of work, I think.
Lokasenna is offline   Reply With Quote
Old 03-03-2019, 05:46 PM   #411
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 741
Default

Quote:
Originally Posted by Lokasenna View Post
mespotine's Ultraschall API has a bunch of functions for opening and running multiple windows.
Ah cool, thanks for the tip. I'll check it out.


Quote:
Originally Posted by Lokasenna View Post
Step 1: Don't have all the code in one file, especially the different widgets that a given script might not need.
Step 2: Don't load files unless the script needs them.
Most of the stuff in that file is actually core functionality. The widgets themselves are pretty minimal in comparison. Load times are pretty insignificant (os.clock() doesn't have enough resolution to measure it) so I'm not motivated to split it up into separate files yet except to make development easier (and I'm getting to that point).

I was more concerned about memory overhead given the duplication across instances. But I suppose relative to everything else going on in a DAW it's minimal.

Quote:
Originally Posted by Lokasenna View Post
Optional Step 3: Just use my GUI instead. :P If you're interested, I'm happy to help with porting everything. Even just using the engine of mine with your own custom classes might save you a lot of work, I think.
I did consider it actually, but ultimately decided I was just much too invested in what I call rtk (the "Reaper toolkit" which is heavily inspired by gtk+ in its basic design). Your first release happened after I'd already spent about a year working on Reaticulate (and during that period worked on rtk to support it).

The main issue I have with your current version is the fixed grid system. Fluid layouts are important to me, for example being able to achieve something like this:

https://www.youtube.com/watch?v=mEg0wptXt1E

That's actually where most of the code is, in the container/box system and the scrollable viewport, plus some other scaffolding to support things like inter-widget drag-and-drop. That foundation is relatively mature right now and I don't want to abandon it -- even though your library clearly does have a significantly more featureful set of widgets to choose from.

Possibly you're looking at a dynamic layout system in your rewrite? If so I might take another look at that time. Meanwhile, I need to focus on getting the next major release of Reaticulate out the door.
tack is offline   Reply With Quote
Old 03-03-2019, 06:21 PM   #412
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Fair enough.

My GUI doesn't have a fixed grid system, it's just that none of the widgets have code to resize/reposition themselves. There are global and widget-level hooks for the window being resized, so you would just have to add one function to loop through all of the widgets and recalculate from their original x/y/w/h versus the current window dimensions.

Well, and then fix the widgets that have some dimensions hardcoded or calculated when you first create them... Dynamic positioning is easy-peasy though.

I would like to make dynamic sizing easier in the new version though - one item on my to-do list is to borrow the "flow" logic White Tie has in the Default 5 theme so the widgets can push each other around and wrap as needed.

Last edited by Lokasenna; 03-03-2019 at 06:29 PM.
Lokasenna is offline   Reply With Quote
Old 03-03-2019, 06:47 PM   #413
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 741
Default

Quote:
Originally Posted by Lokasenna View Post
Well, and then fix the widgets that have some dimensions hardcoded or calculated when you first create them... Dynamic positioning is easy-peasy though.
There's devils in them there details.

The box system I implemented (which is inspired by gtk+'s hbox/vbox) was surprisingly challenging. Boxes which are sized only as much as needed to fit their children (shrink-wrapped); boxes that can be expanded to fit their parent containers; cells within boxes that can have different ratios in their consumption of available space; propagating that available space to child widgets or not, and if not then justifying the children within the cells; supporting all that in scrollable viewports. And then I further stacked the deck against myself by wanting to support dynamically-determined but fixed-position widgets (think position:fixed in CSS), which you can see in that red "Fixed position widget" in the video.

I ended up spending a surprising amount of time getting that right (or at least what I think is right). Surprising because I too figured it couldn't be all that hard.

Quote:
Originally Posted by Lokasenna View Post
I would like to make dynamic sizing easier in the new version though - one item on my to-do list is to borrow the "flow" logic White Tie has in the Default 5 theme so the widgets can push each other around and wrap as needed.
That's a very cool idea. I can definitely see use-cases for that.
tack is offline   Reply With Quote
Old 03-03-2019, 06:53 PM   #414
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Quote:
Originally Posted by tack View Post
There's devils in them there details.

The box system I implemented (which is inspired by gtk+'s hbox/vbox) was surprisingly challenging. Boxes which are sized only as much as needed to fit their children (shrink-wrapped); boxes that can be expanded to fit their parent containers; cells within boxes that can have different ratios in their consumption of available space; propagating that available space to child widgets or not, and if not then justifying the children within the cells; supporting all that in scrollable viewports. And then I further stacked the deck against myself by wanting to support dynamically-determined but fixed-position widgets (think position:fixed in CSS), which you can see in that red "Fixed position widget" in the video.
Nice. I'm adding a note to my idea list to look at your code for a potential "do all the resizing things" module.
Lokasenna is offline   Reply With Quote
Old 03-03-2019, 06:57 PM   #415
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 741
Default

Quote:
Originally Posted by Lokasenna View Post
Nice. I'm adding a note to my idea list to look at your code for a potential "do all the resizing things" module.
Cool. If there's anything in there you're able to lift, that's icing on the cake. Let me know if you find bugs.

Container, Box (subclasses Container), VBox and HBox (which subclass Box) are the ones to look at.
tack is offline   Reply With Quote
Old 03-03-2019, 07:00 PM   #416
tack
Human being with feelings
 
tack's Avatar
 
Join Date: Jan 2014
Location: Ontario, Canada
Posts: 741
Default

The important thing is that the architecture needs to support the notion of reflowing. It's not just when the window resizes: any time something changes its size within the scene graph, it needs to trigger a reflow.
tack is offline   Reply With Quote
Old 03-03-2019, 11:16 PM   #417
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 372
Default

Quote:
Originally Posted by tack View Post
Ooooooh myyyyyy Gooooooooooood!

This is awesome, Tack!
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 03-28-2019, 10:49 PM   #418
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default can't get value from gui.Val

I'm trying to test a method by modifying one of the example scripts (as little as possible) It just adds a send or two, and changes a parameter in a jsfx.

But however I try to get the value of the slider, It always crashes the script, and the trace doesn't show the value of it.

Is there a simpler way to get the value of a slider than to override mouse methods anyway? I couldn't find one. The button object has a built-in method, but none of the others seem to.... I'm used to adding a listener, but I don't see any equivalent here.

I also tried calling my method with self.Val as an argument from within the double-click method, instead of trying to get it from within my method and that allowed me to get the slider's value printed to the console before the crash.... it said 'nil'.

Here's the trace:
Code:
Test_Attempt_2.lua:59: in upvalue 'setNotesource'
	Test_Attempt_2.lua:179: in method 'ondoubleclick'
	Core.lua:843: in field 'Update'
	Core.lua:434: in field 'Main_Update_Elms'
	Core.lua:301: in function <...am Scripts\Development\Lokasenna_GUI v2\Library\Core.lua:297>
		[C]: in function 'xpcall'
	Core.lua:297: in function <...am Scripts\Development\Lokasenna_GUI v2\Library\Core.lua:296>

Lokasenna_GUI:	v2.16.3
Reaper:       	5.972/x64
Platform:     	Win64
And here's the code:

Code:
-- NoIndex: true

--[[
	Lokasenna_GUI

- Using the Main loop to monitor and interact with things in Reaper
	- Using z layers and related functions to move elements around
	- Changing elements' methods for your own purposes

]]--

-- The Core library must be loaded prior to anything else

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")()

dofile(reaper.GetResourcePath().."/UserPlugins/ultraschall_api.lua")

GUI.req("Classes/Class - Label.lua")()
GUI.req("Classes/Class - Slider.lua")()
GUI.req("Classes/Class - Frame.lua")()

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




------------------------------------
-------- Data + functions ----------
------------------------------------


-- Pre-declaring this so every function has access to it
local tr


local function update_pan()
	
	--reaper.SetMediaTrackInfo_Value( tr, "D_PAN", GUI.Val("sldr_pan")/100 )
	
end

local function addMidiReceive(tracknumber,srcChan)
    --set to midi input (1024)
    added = ultraschall.AddTrackAUXSendReceives(tracknumber,srcChan,
                                        0,0,0,0,0,0,1,1,-1,1024,-1,false)
    if added then return added 
    else ultraschall.print2("problem setting midi receive from track "
        ..tostring(srcChan).." to track "..tostring(tracknumber))
    end
end

local function setNotesource()
    nsIndex = gui.Val("sldr_pan")
    reaper.ShowConsoleMsg("nsrc = "..tostring(nsIndex))  
    tracknumber = 16
    PIANO = 1
    ROLI = 2
    DUAL = 3
    NONE = 4

    OUTPUT_A_TRACKNUM = 1
    OUTPUT_B_TRACKNUM = 2
    OUTPUT_C_TRACKNUM = 3
    OUTPUT_D_TRACKNUM = 4
    PIANO_TRACKNUM = 5
    ROLI_TRACKNUM = 6

    MIDICHSTRIP_SLOT_NUM = 2
    NS_SELECT_PARAM = 11

    --Get track
    track = reaper.GetTrack(0,tracknumber) 
    if track == nil then ultraschall.print2("invalid track number")
    end
    --ultraschall.print2("track = "..tostring(tracknumber))
    --Get list of sends
    count_Receives = ultraschall.CountTrackAUXSendReceives(tracknumber)
    --check through for those that are midi enabled
    for i = 0, count_Receives do
        _,_,_,_,_,_,_,_,_,_,hasMIDI,_ = ultraschall.GetTrackAUXSendReceives(tracknumber, i)
        if hasMIDI == 1024 then   --setting for all midi enabled
            --remove these sends
            removed = ultraschall.DeleteTrackAUXSendReceives(tracknumber, i, false)
        end
    end
    --add new send(s) to track 1-kx8,2-roli,1&2 dual, none for FX (this is also our check for isFX)
    if nsIndex == PIANO then 
        addMidiReceive(tracknumber,PIANO_TRACKNUM)
    elseif nsIndex == ROLI then  
        addMidiReceive(tracknumber,ROLI_TRACKNUM)
    elseif nsIndex == DUAL then  
        addMidiReceive(tracknumber,ROLI_TRACKNUM)
        addMidiReceive(tracknumber,PIANO_TRACKNUM) 
    else  --do nothing it's an effect... or should we do something?
    end
    --set midiChStrip value for input type
    --reaper.ShowConsoleMsg()
    reaper.TrackFX_SetParam(track,MIDICHSTRIP_SLOT_NUM,NS_SELECT_PARAM,nsIndex)   
    ultraschall.ShowLastErrorMessage()
end




------------------------------------
-------- Window settings -----------
------------------------------------


GUI.name = "Example - Main, Z, and Methods"
GUI.x, GUI.y, GUI.w, GUI.h = 0, 0, 300, 128
GUI.anchor, GUI.corner = "mouse", "C"




------------------------------------
-------- GUI Elements --------------
------------------------------------


--[[	

	Frame		z, 	x, 	y, 	w, 	h[, shadow, fill, color, round]
	Label		z, 	x, 	y,		caption[, shadow, font, color, bg]
	Slider		z, 	x, 	y, 	w, 	caption, min, max, defaults[, inc, dir]
	
]]--

--GUI.New("lbl_track", "Label",	1,	96, 8, "No track selected!", true, 2, "red")
--GUI.New("frm_track", "Frame",	2,	0, 0, 300, 128, false, true, "faded", 0)
GUI.New("sldr_pan", "Slider",	3,	88, 64, 128, "First selected track's NS:", 1, 4, 1, 1, "h")


-- Layer 5 will never be shown or updated
-- (See the Main function below)
GUI.elms_hide[5] = true




------------------------------------
-------- Method overrides ----------
------------------------------------


-- Class methods can be overwritten, either at the class level or
-- for individual elements.

-- You can also easily append your own code to the stock methods:
function GUI.elms.sldr_pan:onmousedown()
	
	-- Run the slider's normal method
	GUI.Slider.onmousedown(self)

	-- Note that we have to call the method as a function here; we
	-- can't use the : syntax because sldr_pan's 'self' needs to be
	-- passed on as a value. If we used a :, it would pass GUI.Slider
    
	
	
end
function GUI.elms.sldr_pan:ondrag()
	GUI.Slider.ondrag(self)
	
end
function GUI.elms.sldr_pan:onwheel()
	GUI.Slider.onwheel(self)
	
end
function GUI.elms.sldr_pan:ondoubleclick()
    GUI.Slider.ondoubleclick(self)
    setNotesource()
    --setNotesource(self.Val)
	
end




------------------------------------
-------- Main loop -----------------
------------------------------------


-- This will be run on every update loop of the GUI script; anything you would put
-- inside a reaper.defer() loop should go here. (The function name doesn't matter)
local function Main()
	
	
	
end


GUI.Init()

-- Tell the GUI library to run Main on each update loop
-- Individual elements are updated first, then GUI.func is run, then the GUI is redrawn
GUI.func = Main

-- How often (in seconds) to run GUI.func. 0 = every loop.
GUI.freq = 0

GUI.Main()
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 03-29-2019, 06:09 AM   #419
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Line 59 - you've got GUI in lowercase.

It's possible to add listeners by overriding each of the element's input methods. You do have to be aware of what arguments the GUI is passing in each of them and make sure you provide them to the original method yourself (see the wheel example below).

Code:
function my_slider:onmouseup()
  GUI.Slider.onclick(self)
  -- run your own code here
end

function my_slider:ondrag()
  GUI.Slider.ondrag(self)
  -- run your own code here
end

function my_slider:onwheel(inc)
  GUI.Slider.onwheel(self, inc)
  -- run your own code here
end
I'm hoping to make it easier for v3.
Lokasenna is offline   Reply With Quote
Old 03-29-2019, 07:55 AM   #420
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
Line 59 - you've got GUI in lowercase.
DOH!!!!
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 03-29-2019, 08:58 AM   #421
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

Okay, moving right along now....

I can't figure out why my radio button object is sending a value of '1', regardless of which option is selected...

I also can't figure out why the slider defaults to 19 instead of 16, and why it's slider graphic is backwards....

Thanks as always!

Code:
-- The Core library must be loaded prior to anything else

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")()

dofile(reaper.GetResourcePath().."/UserPlugins/ultraschall_api.lua")


GUI.req("Classes/Class - Slider.lua")()
GUI.req("Classes/Class - Options.lua")()    

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

local function addMidiReceive(srcChan,tracknumber)
    --set to midi input (1024)
    added = ultraschall.AddTrackAUXSendReceives(srcChan,tracknumber,
                                        0,0,0,0,0,0,1,1,-1,1024,-1,false)
    if added then return added 
    else ultraschall.print2("problem setting midi receive from track "
        ..tostring(srcChan).." to track "..tostring(tracknumber))
    end
end

local function removeMIDISend(midiSourceTrack,destTrack)
    sendCount = ultraschall.CountTrackAUXSendReceives(midiSourceTrack)
    for sendNum = 0, sendCount do
        dest,_,_,_,_,_,_,_,_,_,_,_ = ultraschall.GetTrackAUXSendReceives(destTrack, sendNum)
        if dest == destTrack then 
            removed = ultraschall.DeleteTrackAUXSendReceives(midiSourceTrack, sendNum, false)
        end
    end
end


local function setNotesource()

    nsIndex = GUI.Val("nsNum") 
    tracknumber = 16 -- GUI.Val("sldr_track")
    --reaper.ShowConsoleMsg("track = "..tostring(tracknumber))
    reaper.ShowConsoleMsg("nsIndex = "..tostring(nsIndex).."\n")
    PIANO = 1
    ROLI = 2
    DUAL = 3
    NONE = 4

    OUTPUT_A_TRACKNUM = 1
    OUTPUT_B_TRACKNUM = 2
    OUTPUT_C_TRACKNUM = 3
    OUTPUT_D_TRACKNUM = 4
    PIANO_TRACKNUM = 5
    ROLI_TRACKNUM = 6

    MIDICHSTRIP_SLOT_NUM = 1
    NS_SELECT_PARAM = 11

    --Get track
    track = reaper.GetTrack(0,tracknumber) 
    if track == nil then ultraschall.print2("invalid track number")
    end
    --Get list of sends
    removeMIDISend(PIANO_TRACKNUM,tracknumber)
    removeMIDISend(ROLI_TRACKNUM,tracknumber)
--[[
    count_Receives = ultraschall.CountTrackAUXSendReceives(tracknumber)
    --check through for those that are midi enabled
    for i = 0, count_Receives do
        _,_,_,_,_,_,_,_,_,_,hasMIDI,_ = ultraschall.GetTrackAUXSendReceives(tracknumber, i)
        reaper.ShowConsoleMsg("receive ="..tostring(i).."hasMIDI = "..tostring(hasMIDI))
        if hasMIDI == 1024 then   --setting for all midi enabled
            --remove these sends
            removed = ultraschall.DeleteTrackAUXSendReceives(tracknumber, i, false)
        end
    end]]--
    --add new send(s) to track 1-kx8,2-roli,1&2 dual, none for FX (this is also our check for isFX)
    if nsIndex == PIANO then 
        addMidiReceive(tracknumber,PIANO_TRACKNUM)
    elseif nsIndex == ROLI then  
        addMidiReceive(tracknumber,ROLI_TRACKNUM)
    elseif nsIndex == DUAL then  
        addMidiReceive(tracknumber,ROLI_TRACKNUM)
        addMidiReceive(tracknumber,PIANO_TRACKNUM) 
    else  --do nothing it's an effect... or should we do something?
    end
    --set midiChStrip value for input type
    reaper.TrackFX_SetParam(track,MIDICHSTRIP_SLOT_NUM,NS_SELECT_PARAM,nsIndex)   
    ultraschall.ShowLastErrorMessage()
end

GUI.name = "NS TEST"
GUI.x, GUI.y, GUI.w, GUI.h = 0, 0, 400, 200
GUI.anchor, GUI.corner = "mouse", "C"

GUI.New("nsNum",	"Radio",	    1, 192,	32,  80, 108, "", "KX8,DUAL,ROLI,NONE", "v", 4)
GUI.New("sldr_track", "Slider",	1, 32,  96, 128, "Track", 16,19, 16, 1, "h")

local elms = {}

GUI.CreateElms(elms)

function GUI.elms.nsNum:onmouseup()

    setNotesource()
    --ultraschall.print2(tostring(gui.Val("chk_opts")))
    GUI.Slider.onmouseup(self)

end



GUI.Init()


GUI.Main()
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 03-29-2019, 09:28 AM   #422
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

The defaults parameter is in steps, starting fro 0, not the actual values used for min and max. You're telling it to default to step 16 when the slider only has steps 0, 1, 2, and 3.

Bad design on my part. It is in the docs though: https://github.com/jalovatt/Lokasenn...ki/2.00-Slider
Lokasenna is offline   Reply With Quote
Old 03-29-2019, 10:33 AM   #423
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

Okay, I see how that works..... How about the radio button issue?

EDIT: Figured that out. Was referencing the wrong control in my mouseup method....
__________________
eric moon
Very Stable Genius
https://gogolab.com/

Last edited by woodslanding; 03-29-2019 at 10:54 AM.
woodslanding is offline   Reply With Quote
Old 03-29-2019, 10:56 AM   #424
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Oops, skipped right over that one.

You're overwriting the Radio element's onmouseup method but then calling the Slider class' original method inside, so the Radio isn't going to update properly.
Lokasenna is offline   Reply With Quote
Old 03-29-2019, 11:00 AM   #425
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

I also noticed this:
Code:
local elms = {}

GUI.CreateElms(elms)
If you're using GUI.New you don't need to worry about this - CreateElms is an alternative syntax so you can create a bunch of elements from a table of parameters in one go: https://github.com/jalovatt/Lokasenn...d%20tables.lua

For what it's worth, v3 will be using the "table of parameters" approach for everything because it makes life way easier.
Lokasenna is offline   Reply With Quote
Old 03-29-2019, 12:32 PM   #426
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

The Problem I'm having now is that I'm using the mouse up method to trigger my method, but I'm getting the previous value not the one that changed when I pressed the mouse... Not sure what I should do.
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 03-29-2019, 12:50 PM   #427
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Call GUI.Radio.onmouseup(self) before your code, so the value is updated before you check it.
Lokasenna is offline   Reply With Quote
Old 03-29-2019, 03:39 PM   #428
kartalex
Human being with feelings
 
Join Date: Dec 2015
Posts: 35
Default

Hi, Lokasenna! Hi, guys!

I have some other questions! Please help me)

1) I want to resize and refresh GUI. I found this:

Code:
local __,x,y,w,h = gfx.dock(-1,0,0,0,0)
    
    gfx.quit()
    gfx.init(GUI.name, GUI.w, GUI.h, 0, x, y)
	  GUI.redraw_z[0] = true
It works.. but it makes script window focused, even if it wasn't focused before. I want to use it to display some information about selected item, it should update and resize to fit displayed info every time I click on any item (I did it in GUI.func), but don't want to make the window focused.

How to avoid focusing GUI while refreshing it?
Maybe there's a way to refresh (resize) GUI window without recreating it?

2) How to pass keystrokes from script GUI to Reaper itself? I want some codes work with script, and all others - pass to main window. I found out that in GUI.func I can make someting like this:

Code:
local char = gfx.getchar()
if char == 32 then reaper.Main_OnCommandEx(40044, 0,0) end       -- space -> transport play
But how to pass other keys to main window just like main window keyboard focused?

Last edited by kartalex; 03-29-2019 at 03:47 PM.
kartalex is offline   Reply With Quote
Old 03-29-2019, 04:01 PM   #429
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

1. There's no native way to do that - windows get focus when you create them. The JS extension has a bunch of extra window functions, so I think you can do it with that.

And no, we don't currently have a way to resize the window. Again, the JS extension might.

2. That's the only way to do it natively - specifying every key and the command to use. It's worth remembering that not everyone will use the same key mappings as you though.
Lokasenna is offline   Reply With Quote
Old 04-01-2019, 07:14 AM   #430
CSDProductions
Human being with feelings
 
Join Date: Mar 2019
Posts: 7
Default

Hey all,

Firstly - Lokasenna thanks for the creation of this. Very helpful!

I'm just getting into the world of Reascript, making a very basic window to aid some live playback.

I'm trying to use the return from GetPlayState() to determine the background colour of the window.
So...

Question 1 - Is it possible to change the colour of the main window?

Question 2 - If not, I'm really struggling to get a frame to change colour based on the return state. See the code below.

if reaper.GetPlayState() == 1 then
reaper.ShowConsoleMsg("PLAYING")
GUI.elms.stop_bg.color = "red"
end

Am I barking up the wrong tree? I know we're entering the if statement as the Console is displaying the message I'd expect. The other option is to have two frames and change their Z layer value but again, this also doesn't seem to work which makes me think I'm doing something fundamental wrong.

Thanks in advance!
CSDProductions is offline   Reply With Quote
Old 04-01-2019, 08:20 AM   #431
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Not at my Reaper machine right now but:

1. The window background is set by gfx.clear. Changing that should do it... you might need to close and reopen the window though.

Code:
gfx.clear = reaper.ColorToNative(R 0-255, G 0-255, B 0-255)
2. Any time you change something about an element's appearance, you also need to use GUI.redraw_z[elm.z] = true so it knows it needs a redraw. Many of the elements, like Frame in this case, will also need a call to their init method to redraw their internal buffers.

Code:
if reaper.GetPlayState() == 1 then
  reaper.ShowConsoleMsg("PLAYING")
  local elm = GUI.elms.stop_bg
  elm.color = "red" 
  elm:init()
  GUI.redraw_z[elm.z]
end
Lokasenna is offline   Reply With Quote
Old 04-01-2019, 11:19 AM   #432
CSDProductions
Human being with feelings
 
Join Date: Mar 2019
Posts: 7
Default

Worked! Thanks Lokasenna.
CSDProductions is offline   Reply With Quote
Old 04-04-2019, 08:35 AM   #433
CSDProductions
Human being with feelings
 
Join Date: Mar 2019
Posts: 7
Default

Me again! Anyone know if there's a way to centre align text in a label or frame?? Thanks!
CSDProductions is offline   Reply With Quote
Old 04-04-2019, 09:35 AM   #434
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

I could have sworn I added that to the Label class right after Cockos updated gfx.drawstr to support alignment, but apparently not. Putting that on my to-do list.

In the meantime, you can center the label yourself any time after the window has been opened with GUI.center
Code:
-- center in another element
GUI.elms.myLabel.x = GUI.center(GUI.elms.myLabel, GUI.elms.otherElement)

-- arbitrary coordinates (xywh all need to be given even if you don't care about y - just put 0 or make up a number)
GUI.elms.myLabel.x, GUI.elms.myLabel.y = GUI.center(GUI.elms.myLabel, {x = 32, y = 48, w = 96, h = 16})

-- the window
GUI.elms.myLabel.x = GUI.center(GUI.elms.myLabel)

-- and don't forget:
GUI.elms.myLabel:redraw()
For the Frame... there isn't a good way. You can use its .pad property to adjust where the text ends up - it pads both sides, then wraps the text to fit the remaining space.
Lokasenna is offline   Reply With Quote
Old 04-07-2019, 04:58 PM   #435
kartalex
Human being with feelings
 
Join Date: Dec 2015
Posts: 35
Default

Hi, Lokasenna! Hi, guys)

How to make my script (where Lokasenna's GUI is used) run in background, for when I hit Close button and reopen - it didn't restart, but kept working?

I have this in my script:
Code:
function Defer_Loop()
  local char = gfx.getchar()
  if char == 27 then MAIN_exit() end  
  if char == 32 then reaper.Main_OnCommandEx(40044, 0,0) end       -- space -> transport play  
  if char ~= -1 then reaper.defer(Defer_Loop) else MAIN_exit() end -- stop on close 
end

function MAIN_exit()
  reaper.atexit()
  gfx.quit()
end 

--------- some code here  

GUI.Init()
GUI.func=Defer_Loop()
GUI.Main()
But this doesn't keep it working in background ((
kartalex is offline   Reply With Quote
Old 04-07-2019, 08:31 PM   #436
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

- You need to run your "keep it going in the background" loop separate from the GUI; when the window is closed, the GUI quits, so whatever you gave it for GUI.func will no longer be run.

- If your defer loop is what you're using for the background script, it won't work. gfx.getchar will always be -1 if there's no window open.

- FYI, running the script again won't reopen the window, it will kill the script and start it over again. If your GUI is just setting a bunch of parameters for the background script to use, this might be okay - you would just need to have it store the parameters in an ExtState or something and then read them when a new instance starts up.

- I don't think you actually can close the window and reopen it within the same script instance, actually, since the GUI does a bunch of stuff when you open the window and might crash if you tried to do it again.

I'm curious what you're trying to accomplish with this. Feel free to PM me if you need any help.
Lokasenna is offline   Reply With Quote
Old 04-09-2019, 10:23 AM   #437
TonE
Human being with feelings
 
Join Date: Feb 2009
Location: Reaper HAS send control via midi !!!
Posts: 1,847
Default

How can we add background images to jsfx, e.g. to filther?
TonE is offline   Reply With Quote
Old 04-09-2019, 11:08 AM   #438
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,251
Default

Not with my library - it only works with Lua scripts.

JSFX can load .png files - have a look at the Sonic Anomaly ones and see how they're doing it.
Lokasenna is offline   Reply With Quote
Old 04-09-2019, 11:58 AM   #439
TonE
Human being with feelings
 
Join Date: Feb 2009
Location: Reaper HAS send control via midi !!!
Posts: 1,847
Default

Thanks for the hint. Example SLAX.jsfx.

Writing at top.
PHP Code:
providesslax_gfx/* 
After sliders, adding a few .png like this, also defining as resource:

PHP Code:
filename:0,slax_gfx/bg.png
filename
:1,slax_gfx/bigpot.png
filename
:2,slax_gfx/prepot.png
filename
:3,slax_gfx/needles.png
filename
:4,slax_gfx/opt.png
filename
:5,slax_gfx/optbut.png

resource
:0,1,2,3,4,
Defining background size.
PHP Code:
@gfx 400 360 
Then grepping for gfx_r, gfx_g, gfx_b, gfx_a and gfx_blit for interesting ideas.

Resaving filther.jsfx as myfilther.jsfx and you can have your backgrounded filther or any jsfx, without an updated filther.jsfx overwriting your modifications. I can try some backgrounds plus 'Atari ST 8x16 System Font' on myfilther. Bri1 has created some great filther images already. This is how it can look then: https://github.com/JoepVanlier/JSFX/issues/5

Last edited by TonE; 04-09-2019 at 01:20 PM.
TonE is offline   Reply With Quote
Old 04-15-2019, 01:57 AM   #440
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default How is V3 coming along?

I'm getting very close to having all my backend stuff working properly, and back to considering gui.

How is V3 coming? Would it be ready for beta testing anytime soon? Or am I better off diving into trying to write components for v2?
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding 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 10:36 PM.


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