Old 09-03-2018, 08:24 AM   #121
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,238
Default

- I get tompad_ToDoList.lua:610: attempt to concatenate a nil value when I run it, probably because I don't have the text file it's looking for. You might want have a default items table hardcoded that it can use if table.load returns an error.

- You've currently got it set to place the window centered on the mouse cursor, with X and Y relative to that position. Try:

Code:
GUI.name = "ToDoList" .. " " .. versionNr
GUI.x, GUI.y, GUI.w, GUI.h = 0, 300, 536, 272
GUI.anchor, GUI.corner = "screen", "C"
Lokasenna is online now   Reply With Quote
Old 09-03-2018, 09:39 AM   #122
brainwreck
Human being with feelings
 
Join Date: Jul 2006
Posts: 20,840
Default

Lokasenna, I have only read small portions of your tutoral. At some point, I want to go through it proper. Just wanted to say, you're a fucking saint for posting this tutorial.
__________________
It's time to take a stand against the synthesizer.
brainwreck is offline   Reply With Quote
Old 09-03-2018, 09:59 AM   #123
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,238
Default

Cheers. I'm actually working on rewriting it, expanding it, and updating it to use the ReaPack version of the GUI.
Lokasenna is online now   Reply With Quote
Old 09-03-2018, 11:23 AM   #124
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 371
Default

Quote:
Originally Posted by Lokasenna View Post
- I get tompad_ToDoList.lua:610: attempt to concatenate a nil value when I run it,
probably because I don't have the text file it's looking for. You might want have a
default items table hardcoded that it can use if table.load returns an error.
B...bu..b...but I have defult items!

Strange, I have it in

Code:
function set_initial_state()
  ------------------------------------
  -------- Load Listbox contents ----------
  ------------------------------------


  if items == nil then
    items = {
      {["id"] = "{109E9200-597D-6B3E-38D6-DB21CA82A1F3}", ["prio"] = "a", ["title"] = "Donate to Lokasenna", ["frame"] = "Dont forget to donate to Lokasenna" },
      {["id"] = "{36E55F9F-9183-7B9E-2D16-BF5EAA091820}", ["prio"] = "b", ["title"] = "Donate to XRayM", ["frame"] = "Dont forget to donate to XRayM" },
      {["id"] = "{B15A4D85-FBC9-11AE-C181-AED8E7C90501}", ["prio"] = "c", ["title"] = "Donate to cfillion", ["frame"] = "Dont forget to donate to cfillion" }
    }
    saveToFile()
  end
  fillListBoxwithTasks ()
  GUI.Val("lst_tasks", {1})
  GUI.Val("frm_details", items[GUI.Val("lst_tasks")].frame)
  selectedItem = items[GUI.Val("lst_tasks")].id
  sortItems()
end
And before that in the beginning of script I got:

Code:
local items = table.load(project_path .. "/" .. "todolist.txt" )
I just checked with my windows computer - deleted todolist.txt and
started ToDoList - no errors, and creating the file todolist.txt,
BUT! here is a strange thing! On linux it saves the todolist.txt
in the same folder as Project.rpp, BUT on windows it saves the same
file in projects audio folder!!

Hmmmm maybe I have different configurations for Reaper on the two
different computers but should that make any difference?

My save code look like this:

Code:
function saveToFile ()
  table.save(items, project_path .. "/" .. "todolist.txt")
end
And I am using "save_load_table_to_file.lua"


Quote:
- You've currently got it set to place the window centered on the mouse cursor, with X and Y relative to that position. Try:

Code:
GUI.name = "ToDoList" .. " " .. versionNr
GUI.x, GUI.y, GUI.w, GUI.h = 0, 0, 536, 272
GUI.anchor, GUI.corner = "screen", "C"
This works fine both in Win and linux! :-)
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 09-03-2018, 12:10 PM   #125
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,238
Default

Ah, I had an existing file from a previous version that must not have been cooperating - deleting the file worked.
Lokasenna is online now   Reply With Quote
Old 09-03-2018, 01:44 PM   #126
tompad
Human being with feelings
 
Join Date: Jan 2010
Location: Fjugesta, Sweden
Posts: 371
Default

Quote:
Originally Posted by Lokasenna View Post
Ah, I had an existing file from a previous version that must not have been cooperating - deleting the file worked.
Puh....:-) Yes I made the structure of the items table different,
needed some GUIDs in it.
__________________
ToDoList Obliques MusicMath Donation Mark4celeste Frid i ditt hjärta Eve & the Fisherman on Spotify
tompad is offline   Reply With Quote
Old 09-03-2018, 10:45 PM   #127
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

[QUOTE=Lokasenna;2030302]You have to specifically request a redraw for the element's z layer:

Code:
GUI.elms.frm_track.color = "red"
GUI.elms.frm_track:redraw()
Reading the code again, it looks like frm_track is hidden if no track is selected. So that's why I'm not seeing a color change

So I went through and changed z order so the frame is UNDER the slider, and commented out the lines that made it invisible, and I can see the frame at all times. I thought it was getting its color changed, but it was disappearing.

Now I can see that the background to the window is also the background to the slider. So to affect an actual decent looking change of color, I will need to change the backgrounds of all widgets within my frame. I guess I'll look into that.

But..... even though I can now see the frame at all times, the code above to change the color is still not working.

Thought this would be pretty straighforward, but I guess I'm learning. Here's where the script is at.

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

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




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


GUI.name = "Example - Color Test"
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",  3,  0, 0, 300, 128, false, true, "blue", 0)
GUI.New("sldr_pan", "Slider",  2,  88, 64, 128, "First selected track's Pan:", -100, 100, 100, nil, "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

  update_pan()
  
end
function GUI.elms.sldr_pan:ondrag()
  GUI.Slider.ondrag(self)
  update_pan()
end
function GUI.elms.sldr_pan:onwheel()
  GUI.Slider.onwheel(self)
  update_pan()
end
function GUI.elms.sldr_pan:ondoubleclick()
  GUI.Slider.ondoubleclick(self)
  update_pan()
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()
  
  -- Check the track state and toggle our warning label as needed
  tr = reaper.GetSelectedTrack( 0, 0 )
  
  if tr then
    
    -- Save a bit of CPU by only doing this if we need to
    if GUI.elms.lbl_track.z == 1 then
      
      -- These both accomplish the same thing...
      
      -- lbl_track is moved to a different layer, which we've permanently
      -- hidden above. Use this if you have several elements on a single 
      -- layer and only want to hide one of them. e.g. adjusting which
      -- options are available depending on other things the user does.
      GUI.elms.lbl_track.z = 5
      
      -- frm_track's entire layer is hidden. This is what the Tabs element
      -- uses.
      --GUI.elms_hide[GUI.elms.frm_track.z] = true
      
      
      -- Layers can also be frozen; they'll be drawn, but won't receive
      -- any user input. Use this for i.e. having a slider display an
      -- RMS value, since the user can't do anything with it.
      
      -- Completely unnecessary here, because frm_track is on top and will
      -- "steal" any user input.
      
      --GUI.elms_freeze[GUI.elms.sldr_pan.z] = false
      
      
      -- Force a redraw of every layer
      GUI.redraw_z[0] = true
      
    end
    
    -- See if the track's Pan value has been changed and update the slider
    local pan = reaper.GetMediaTrackInfo_Value( tr, "D_PAN" )
    if math.abs( pan - (GUI.Val("sldr_pan") / 100) ) > 0.00 then
      
      -- Converting the returned value (-1 to 1) to Slider steps (0 to 200)
      pan = (math.floor(100*pan) - GUI.elms.sldr_pan.min )

      GUI.Val("sldr_pan", pan )
      
    end  
        
        local trackColor = reaper.GetTrackColor(tr)
        GUI.elms.frm_track.color = "red" --reaper.ColorFromNative( trackColor )
        GUI.elms.frm_track:redraw()
        
  
  -- If we don't have a track, hide the track elements
    -- and pop up a warning
  else
  
    if GUI.elms.lbl_track.z == 5 then
      
      GUI.elms.lbl_track.z = 1
      GUI.elms_hide[GUI.elms.frm_track.z] = false
      GUI.elms_freeze[GUI.elms.sldr_pan.z] = true
    
      GUI.redraw_z[0] = true
      
    end
  
  end
  
  
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 09-04-2018, 12:13 AM   #128
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

Reading me some manual....

found this:

Code:
GUI.elms.frm_track.color = "red" --reaper.ColorFromNative( trackColor )
        GUI.elms.frm_track:redraw()
        GUI.Msg(GUI.elms.frm_track:Msg())
which gives:

frm_track.bg = wnd_bg
frm_track.buff = 1019
frm_track.col_txt = txt
frm_track.color = red

...

but it is clearly still very blue-looking... so is the "color" in the constructor not the same as "color" in the properties? Or is the redraw not working for some reason?

Edit: tried the same method on the slider, no change....
Edit: tried setting the slider .bg, and saw my first color change outside the constructor.
so I tried this:
GUI.elms.sldr_pan.bg = colorFromNative(trackColor)
and it crashed the script. So I guess this is not what you meant by 'dump it in'....

Edit: tried this:
Code:
local trackColor = reaper.GetTrackColor(tr)
      local r,g,b = colorFromNative(trackColor)
      GUI.elms.sldr_pan.bg = {r,g,b}
and that doesn't seem to be dumping it in either. Guess I need to go read some more about Lua, as I'm clearly confused.
__________________
eric moon
Very Stable Genius
https://gogolab.com/

Last edited by woodslanding; 09-04-2018 at 12:29 AM.
woodslanding is offline   Reply With Quote
Old 09-04-2018, 06:45 AM   #129
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,238
Default

If you're seeing blue when it should be red, that's the OS issue. Get R, G, B using ColorFromNative and then swap R and B before passing them to the color table.
Lokasenna is online now   Reply With Quote
Old 09-04-2018, 07:00 AM   #130
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,238
Default

Ah, I see the issue.

Most elements draw some/all of themselves to a buffer and then copy from there to the screen to be more efficient. Changing any properties that would be "baked in" to the buffered copy should just need a call to GUI.elms.frm_track:init() to have the buffered copy redrawn.

Code:
            local trackColor = reaper.GetTrackColor(tr)
            GUI.elms.frm_track.color = "red" --reaper.ColorFromNative( trackColor )
            GUI.elms.frm_track:init()
            GUI.elms.frm_track:redraw()
Maybe poor naming on my part - redraw gets a new copy from the element's buffer, and init redraws the buffer itself. It's somewhat inconsistent from class to class, since things like text are generally done on each update rather than stored in the buffer.
Lokasenna is online now   Reply With Quote
Old 09-04-2018, 09:00 AM   #131
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 391
Default

okay, that makes a lot of sense.... so for my image slider I would put my code to pull an image off disk in 'init', and the code to blit some chunk of it in 'redraw', as I won't expect to be changing the image itself dynamically in normal use.

I would put a background color in my redraw code, though, because I use dynamic color a lot to make sure I am editing parameters for the correct track....

I'll try this out when I'm back at my desk. But I will also reread my lua primer, it's been a year, and I seem to have forgotten a lot
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 09-04-2018, 09:54 AM   #132
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,238
Default

Almost.

- Element gets a buffer and draws to it in init.

- The GUI maintains a buffer for each full z layer.

- On each loop, the GUI looks to see which z layers need to be redrawn. This is set, for a given layer, by the redraw methods of any element on it.

- For each element in the layers to be redrawn, it calls element:draw() so they can draw/blit a new copy of themselves to the layer buffer.

- After any drawing is finished, all of the visible layers are blitted together to the window.

Roughly, any drawing that might be a CPU hog, or only needs to be done once, or sporadically when settings change, should be done in init. Any drawing that will change often, or that doesn't have much of a performance cost (text, say) can go in draw.
Lokasenna is online now   Reply With Quote
Old 07-28-2019, 08:24 PM   #133
lexaproductions
Human being with feelings
 
Join Date: Jan 2013
Posts: 427
Default

Hey Lokasenna,
Do you know how to make a multi-line string, centered on all lines?
__________________
MP 12 Core 3.46GHZ 48GB OSX10.11.6, MBP 15" 2012 OSX10.12, RME Fireface UFX, MCU,
Reaper 5, SD2, Omnisphere, Wave Altiverb, PSP, VB3, Izotope, Scuffham, Soundtoys 5, Slate All Plugins.
lexaproductions is offline   Reply With Quote
Old 07-29-2019, 06:40 AM   #134
Lokasenna
Human being with feelings
 
Lokasenna's Avatar
 
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,238
Default

The short answer is that you have to print each line separately and manage the line height yourself.

Code:
local strs = {
  "Line 1 is this long",
  "Line 2 is a bit longer",
  "Line 3 is even longer than that",
}

gfx.init("Multiline", 320, 200, 0, 200, 200)

local function Main()
  local char = gfx.getchar()
  if char == -1 or char == 27 then return end

  --[[
    Add values together to combine, i.e. 5 = center horz. and vert.
    flags&1: center horizontally
    flags&2: right justify
    flags&4: center vertically
    flags&8: bottom justify
    flags&256: ignore right/bottom, otherwise text is clipped to (gfx.x, gfx.y, right, bottom)
  ]]--
  local align = 1

  --[[
    For centering, it will place the text at the midpoint of left + right or
    top + bottom.
  ]]--
  local left = 0
  local right = 320
  local top = 48
  local bottom = 200

  local fontSize = 12

  gfx.setfont(1, 'Arial', fontSize, '')

  for i, line in ipairs(strs) do

    gfx.x, gfx.y = left, top + (i - 1) * fontSize
    gfx.drawstr(line, align, right, bottom)

  end

  gfx.update()
  reaper.defer(Main)
end

Main()
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:12 PM.


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