I would recommend creating a lua table and then simply do a tostring() of all the pattern lines.
That way, your copied data are completely detached from the pattern, and it’s faster than parsing each and every property
(joule would approve of this approach, I’m sure )
Note that the copying includes all columns, even the hidden ones.
When you need to write it back to the pattern you will need a way to parse the string. There’s some code in the xLinePattern class that might be helpful -
nevermind that the function I link to is reading from the pattern, writing would theoretically be the same process but in reverse:
https://github.com/renoise/xLib/blob/master/classes/xLinePattern.lua#L258
Thanks you!!!
Yes, I finally solved it using a global table :D.
The following code that I have built is quite interesting to me. I have been guided by your advice, from Danoise and Joule, and also from ffx. It serves to establish a range of lines inside the selected pattern track, which is obtained through a specific GUI, to save it in the table and access it at any time. In fact, the code is ready to add several clipboards. It would be very easy to add.
-------------------------------------------------------------------------------------------------
--temporaty clipboard (personal buffer)
PRE_TEMP_PATT_TRK = { 1, 1, {} } -- { p_range_1, p_range_2, lines_range_table }
--copy a block of lines to temporaty clipboard
function pre_copy_lines_to_temp_clipboard( lne_1, lne_2 )
for lne = lne_1, lne_2 do
local line = song.selected_pattern_track:line(lne)
local t_line = { ["note_columns"] = {}, ["effect_columns"] = {} }
for col = 1, 12 do
t_line["note_columns"][col] = {
["delay_value"] = 0,
["effect_amount_value"] = 0,
["effect_number_value"] = 0,
["instrument_value"] = 255,
["note_value"] = 121,
["panning_value"] = 255,
["volume_value"] = 255,
["is_empty"] = true
}
end
for eff = 1, 8 do
t_line["effect_columns"][eff] = {
["number_value"] = 0,
["amount_value"] = 0,
["is_empty"] = true
}
end
if not line.is_empty then
---
for ncol_index, ncol in ipairs( line.note_columns ) do
if ( not ncol.is_empty ) then
local t_ncol = t_line.note_columns[ncol_index]
local row_n = { "delay", "effect_amount", "effect_number", "instrument", "note", "panning", "volume" }
t_ncol.is_empty = false
for n, val in ipairs(row_n) do
t_ncol[val.."_value"] = ncol[val.."_value"]
end
end
end
---
for ecol_index, ecol in ipairs( line.effect_columns ) do
if ( not ecol.is_empty ) then
local t_ecol = t_line.effect_columns[ecol_index]
local row_e = { "number", "amount" }
t_ecol.is_empty = false
for e, val in ipairs(row_e) do
t_ecol[val.."_value"] = ecol[val.."_value"]
end
end
end
---
end
PRE_TEMP_PATT_TRK[3][lne] = t_line
end
end
--copy the block of lines from them temporaty clipboard
function pre_copy_lines_from_temp_clipboard( lne_1, lne_2, range_1 )
local num = 0
for lne = lne_1, lne_2 do
num = num + 1
local line = song.selected_pattern_track:line( range_1+num )
---
for ncol_index, ncol in ipairs(PRE_TEMP_PATT_TRK[3][lne].note_columns) do
local line_ncol = line:note_column(ncol_index)
if ncol.is_empty then
if ( not line_ncol.is_empty ) then
line_ncol:clear()
end
else
local row_n = { "delay", "effect_amount", "effect_number", "instrument", "note", "panning", "volume" }
for n, val in ipairs(row_n) do
line_ncol[val.."_value"] = ncol[val.."_value"]
end
end
end
---
for ecol_index, ecol in ipairs( PRE_TEMP_PATT_TRK[3][lne].effect_columns ) do
local line_ecol = line:effect_column(ecol_index)
if ecol.is_empty then
if ( not line_ecol.is_empty ) then
line_ecol:clear()
end
else
local row_e = { "number", "amount" }
for e, val in ipairs(row_e) do
line_ecol[val.."_value"] = ecol[val.."_value"]
end
end
end
---
end
end
--cut or copy entire block
function pre_cut_or_copy_block( bol )
if ( PRE_ON_OFF == true ) then
local sli = song.selected_line_index
local nol = song.selected_pattern.number_of_lines
local lpb = vws.PRE_SLOTS_LPB.value
local range = {}
local range_1, range_2 = {}, {}
local function check_range_1()
local blocks = nol/lpb
for div = 0, blocks-1 do
range_1[div+1] = div*lpb
range_2[div+1] = div*lpb+lpb-1
if ( sli-1 >= range_1[div+1] ) and ( sli-1 <= range_2[div+1] ) then
range[1] = range_1[div+1]
range[2] = range_2[div+1]
return
end
end
end
check_range_1()
PRE_TEMP_PATT_TRK[1] = range[1]+1
PRE_TEMP_PATT_TRK[2] = range[2]+1
--print("PRE_TEMP_PATT_TRK") rprint(PRE_TEMP_PATT_TRK)
pre_copy_lines_to_temp_clipboard(PRE_TEMP_PATT_TRK[1], PRE_TEMP_PATT_TRK[2])
--for cut
if ( bol == true ) then
if ( range[2] ~= nil ) then
for range = range[1], range[2] do
song.selected_pattern_track:line(range+1):clear()
end
else
--print("no range!")
end
vws.PRE_BT_CUT.active = false
vws.PRE_BT_COPY.active = false
end
end
end
--paste entire block
function pre_paste_block()
if ( PRE_ON_OFF == true ) then
local sli = song.selected_line_index
local nol = song.selected_pattern.number_of_lines
local lpb = vws.PRE_SLOTS_LPB.value
local range = {}
local range_1, range_2 = {}, {}
local function check_range_1()
local blocks = nol/lpb
for div = 0, blocks-1 do
range_1[div+1] = div*lpb
range_2[div+1] = div*lpb+lpb-1
if ( sli-1 >= range_1[div+1] ) and ( sli-1 <= range_2[div+1] ) then
range[1] = range_1[div+1]
range[2] = range_2[div+1]
return
end
end
end
check_range_1()
if ( range[2] ~= nil ) and ( song.selected_note_column ) then
pre_copy_lines_from_temp_clipboard(PRE_TEMP_PATT_TRK[1], PRE_TEMP_PATT_TRK[2], range[1])
end
if ( vws.PRE_BT_CUT.active == false ) then vws.PRE_BT_CUT.active = true end
if ( vws.PRE_BT_COPY.active == false ) then vws.PRE_BT_COPY.active = true end
end
end
---
function pre_cut_copy_paste()
local buttons = vb:row { spacing = -1, margin = 1, style = "plain",
vb:button {
id = "PRE_BT_CUT",
active = false,
height = 19,
width = 23,
bitmap = "ico/cut_ico.png",
notifier = function() pre_cut_or_copy_block( true ) end,
tooltip = "Cut the entire selected block.\n[CTRL + X]"
},
vb:button {
id = "PRE_BT_COPY",
active = false,
height = 19,
width = 23,
bitmap = "ico/copy_ico.png",
notifier = function() pre_cut_or_copy_block( false ) end,
tooltip = "Copy the entire selected block.\n[CTRL + C]"
},
vb:button {
id = "PRE_BT_PASTE",
active = false,
height = 19,
width = 23,
bitmap = "ico/paste_ico.png",
notifier = function() pre_paste_block() end,
tooltip = "Paste the entire copied block.\n[CTRL + V]"
}
}
return buttons
end
Some time ago I made a similar query. But I did not understand very well how to build a custom buffer. Now that I have more knowledge, I have finally been able to build it. The performance is instantaneous, since it is prepared to use a range between 2 and 32 lines, by blocks.
…
Looking at this whole matter, it would be very interesting if the API could offer the ability to match a typical Renoise object to a global one, such as a track, a track pattern or a line. Something like:
MY_GLOBAL_CLIPBOARD = renoise.type.PatternTrackObject (or something similar)
renoise.PatternTrackObject should have all the items for PatternTrack set and it should be an empty object, with no data. In this way, it could be copied with :copy_from()…
MY_GLOBAL_CLIPBOARD:copy_from(song.selected_pattern_track) something like this?