ReaScripts (скрипты для Reaper) - Учимся создавать!!!

@@Michael, как получить Grid division в MIDI Editor-е, если линковка гридов в миди эдиторе и аранж окне отключена?
Всё перелопатил - не могу найти, нашёл только грид для нот.
Я конечно "через задницу" эту задачу решил, но хотелось бы прямое решение найти, помоги.
 
Привет друзья!Очень нубский вопрос!)Хотел как то образоваться в направлении написании скриптов хотя бы элементарных. Посмотрел весь курс x-raym и стрим Михаила Пилявского кое-что стал понимать, но поскольку в математике и програмировании совсем плох, сам разобраться во всем не смог. Все настолько по-разному пишут коды.Все с чего то начинают. Решил начать с шаблонов. Нашел шаблон x-raym выполнение функции для выделенных нот. И хотел прикрутить к нему действие если ноты не выделены. Иже как пару дней не могу добиться результата куда вставить второе условие что бы когда ноты были "не выделены" совершалось другое действие. Пока просто вывожу reaper.ShowConsoleMsg("note selected") Подскажите пожалуйста как это можно сделать?
Код:
function Main( take )
     
  retval, notes, ccs, sysex = reaper.MIDI_CountEvts( take )
 
  -- GET SELECTED NOTES (from 0 index)
  for k = 0, notes - 1 do
       
    local retval, sel, muted, startppq, endppq, chan, pitch, vel = reaper.MIDI_GetNote( take, k )
   
    if sel then
    reaper.ShowConsoleMsg("note selected")
      -- ACTION HERE
    
   
    end
     
     
  end

end

-------------------------------
-- INIT
-------------------------------

take = reaper.MIDIEditor_GetTake( reaper.MIDIEditor_GetActive() )

if take then
 
 
 
  Main( take ) -- Execute your main function
 

 
  reaper.UpdateArrange() -- Update the arrangement (often needed)

end -- ENDIF Take is MIDI
 
@incubator,
PHP:
function Main( take )
   
  retval, notes, ccs, sysex = reaper.MIDI_CountEvts( take )
  -- GET SELECTED NOTES (from 0 index)
  for k = 0, notes - 1 do
  local retval, sel, muted, startppq, endppq, chan, pitch, vel = reaper.MIDI_GetNote( take, k )
 
    if sel then
      reaper.ShowConsoleMsg("selected_notes".."\n")
      -- ACTION HERE
    else
      reaper.ShowConsoleMsg("not_selected_notes".."\n")
    end

  end

end

-------------------------------
-- INIT
-------------------------------

take = reaper.MIDIEditor_GetTake( reaper.MIDIEditor_GetActive() )

if take then



  Main( take ) -- Execute your main function



  reaper.UpdateArrange() -- Update the arrangement (often needed)

end -- ENDIF Take is MIDI
 
Последнее редактирование:
  • Like
Реакции: incubator
@Archchie, Спасибо вроде бы просто все было) Но единственно он, выдает количество выделенных нот и количество не выделеных.Я хотел впоследствии назначить экшны для выполнения с реакцией на выделение.Возможно ли что бы код делал при любом количестве одно сообщение "selected_notes" если хоть одна нота выделена и если не выделена одно сообщение "not_selected_notes" Я теоретически понимаю что нужна математика с reaper.MIDI_CountEvts но как это на практике сделать?Там какой то цикл получаеться который ноты считает или reaper.MIDI_CountEvts сразу дает количество? Простите за дилетантский лепет!

P.S Спасибо за материалы буду изучать
 
@incubator, в первом условии, в конце его, перед else -
ставиш break и цикл завершится как только попадётся первая выделенная нота.
А вот чтоб что-то сработало если ни одна не выделена - можно сделать ещё одно условие -
если кол-во циклов совпало с кол-вом нот, тогда делать что-то.
Если пройдя все циклы не обнаружится ни одной выделенной ноты и break не оборвет цикл, значит циклов и будет столько же, сколько нот.
И, да - MIDI_CountEvts сразу даёт кол-во нот и контролеров.

PS: В общем вот так -
PHP:
---------------------------------------------------------------------------------------------------------
local msg = function(M) reaper.ShowConsoleMsg(tostring(M).."\n") end
---------------------------------------------------------------------------------------------------------

function Main (take)
  retval, notes, ccs, sysex = reaper.MIDI_CountEvts( take )
  -- GET SELECTED NOTES (from 0 index)
  for k = 0, notes - 1 do
    local retval, sel, muted, startppq, endppq, chan, pitch, vel = reaper.MIDI_GetNote( take, k )

    if sel then
      msg((k+1).."   selected_notes".."\n")
      -- IF SELECTED - ACTION HERE
      break
    else
      if (notes - 1) == k then
        msg((k+1).."   not_selected_notes".."\n")
        -- IF NOT SELECTED - ACTION HERE
      end
    end
  end
end

-- INIT
take = reaper.MIDIEditor_GetTake( reaper.MIDIEditor_GetActive() )

if take then
  Main (take) -- Execute your main function
  reaper.UpdateArrange() -- Update the arrangement (often needed)
end
 
Последнее редактирование:
  • Like
Реакции: Archie's и incubator
@Aleksandr Oleynik, А как получить количество сработанных циклов?
А вот выше код написал.
Если ни одна из нот не выделена, то кол-во циклов в любом случаи будет равно кол-ву нот, а значит для того чтобы инициировать какое-то действе по этому условию (что ни одна нота не выделена), нужно сделать очередное условие if кол-во нот == кол-ву циклов
ну а цикл ведь у нас переменная k
 
  • Like
Реакции: Archie's и incubator
@Aleksandr Oleynik, Спасибо все разжевали даже, я сейчас подпишу комментарии для лучшего понимания.

Кстати заметил что например скрипты kawa с удаленными пробелами все в одну строку как бы. Добавляет ли это проиводительности в реальности?
Код:
---------------------------------------------------------------------------------------------------------
local msg = function(M) reaper.ShowConsoleMsg(tostring(M).."\n") end --Переменная для последующего сокращения функции
---------------------------------------------------------------------------------------------------------

function Main (take) -- Начало описания главной функции
  retval, notes, ccs, sysex = reaper.MIDI_CountEvts( take )  --Поддсчет количества нот

  for k = 0, notes - 1 do --Задаем переменные для к и notes
    local retval, sel, muted, startppq, endppq, chan, pitch, vel = reaper.MIDI_GetNote( take, k ) --Берем выделеные ноты

    if sel then   --Если есть выделеные ноты (проходит все ноты если есть выделеные выдает одно сообщение и прерываеться
      msg((k+1).."   selected_notes".."\n") --Выводим сообщение ноты выделены
      -- IF SELECTED - ACTION HERE
      break   --прерываемся
    else    --или же
        if (notes - 1) == k then -- смотрим выше если notes(количество нот равно нулю)
        msg((k+1).."   not_selected_notes".."\n") ---То выводим сообщение что ничего не выделено
        -- IF NOT SELECTED - ACTION HERE
      end
    end
  end
end

-- INIT
take = reaper.MIDIEditor_GetTake( reaper.MIDIEditor_GetActive() ) --Проверяет активен ли миди редактор

if take then  --Если есть значение выполняем основную функцию
  Main (take) -- Выполнение функции
  reaper.UpdateArrange() -- Update the arrangement (often needed) --Обновление аражировки для отображения действий
end



И возможно ли было это сделать проще? Получить значение из фунции reaper.MIDI_GetNote и использовать как то его через true и false?
 
Последнее редактирование:
PHP:
----------------------------------------------------------------
local msg = function(param)reaper.ShowConsoleMsg(param.."\n")end
----------------------------------------------------------------

  take = reaper.MIDIEditor_GetTake(reaper.MIDIEditor_GetActive())                     --Получить миди редактор активного тейка
  if take == nil then return end                                                     --если миди редактор закрыт то дальше не продолжать
  retval,count_notes,ccs,sysex = reaper.MIDI_CountEvts(take)                            --Получить количество нот 
  for i = 1,count_notes do                                                                --Создаем цикл опроса по каждой ноте
  local retval, sel, muted, startppq, endppq, chan, pitch, vel = reaper.MIDI_GetNote(take,i-1)--Получаем ноту и её состояние
    if sel then msg(i.."notes_selection") break                                           --Если нота выделенна то (msg)("notes_selection")и сломать цикл опроса
    elseif count_notes == i then msg(i.."not_selected_notes")                   --Если количество нот == количеству цикла опроса то (msg)("not_selected_notes")
    end
  end
 
Последнее редактирование:
  • Like
Реакции: incubator
Кстати заметил что например скрипты kawa с удаленными пробелами все в одну строку как бы. Добавляет ли это проиводительности в реальности?
Нет. Способ записи кода ни как не влияет на производительнось. Код либо работает - либо нет.
Я для написания скриптов использую редактор Atom с модулем для LUA -
он автоматом по шоткату мне форматирует и табулирует верно код.
Когда код скрипта разрастается, используют (ну кроме коментов) для лучшего потом понимания своего же скрипта, несколько приёмов.
Я наверняка все и не знаю, но -
- делают правильное форматирование и табуляцию, чтоб каждое условие, каждая функция читались сразу;
- разбивают всё на простые функции - это порой увеличивает код, но очень способствет его пониманию;
- разбивают скрипт на неколько модулей, по сути на отдельные скрипты.
[DOUBLEPOST=1517680907][/DOUBLEPOST]
И возможно ли было это сделать проще? Получить значение из фунции reaper.MIDI_GetNote и использовать как то его через true и false?
Почти всегда можно сделать лучше и проще, но на это ни какой жизни не хватит, по этому - первое найденное работающее решение и есть самым верным :)
 
Последнее редактирование:
  • Like
Реакции: Archie's и incubator
@Archchie, Спасибо! У вас компактно и понятно)))

@Aleksandr Oleynik, Поздравте меня я написал свой первый скрип с нуля!!! Я очень люблю умные кнопки которые действуют на все в зависимости от фокуса.Я сделал умный Delete который работает в зависимости от фокуса и "Time selection".Код элементарный, но я думаю даже может пригодится кому то))
Код:
 isSet = reaper.GetSet_LoopTimeRange( 0, 0, 0, 0, 0 ) --  Даем переменную "Time selection"
focus = reaper.GetCursorContext() --  Даем переменную значения где сейчас фокус?


if focus == 0 then
reaper.Main_OnCommand(40697, 0)  --если фокус на треках то даем команду стереть трек

elseif isSet == 0 and focus == 1 then
reaper.Main_OnCommand(40697, 0)   -- если нет "Time selection" и фокус на "Items" стираем выделеные "Items"

elseif isSet == 0 and focus == 2 then
reaper.Main_OnCommand(40697, 0) -- если нет "Time selection" и фокус на "Envelope" стираем выделенную точку

elseif isSet > 0  and focus == 1 then
reaper.Main_OnCommand(reaper.NamedCommandLookup('_XENAKIOS_TSADEL'),0 ) --Если есть "Time selection" и фокус на "Items" стираем у выделенныйх "Items" только то что в "Time selection"

elseif isSet > 0  and focus == 2 then
reaper.Main_OnCommand(40089, 0)  --Если есть "Time selection" и фокус на "Envelopes стираем группу точек в "Time selection""

end

Посмотрите пожалуйста укажите на ошибки!)
 
  • Like
Реакции: Kokarev Maxim
Поздравляю! :)
В нашем полку прибыло?

Вот на примере этого скрипта покажу как форматирует код Atom (поставили в него модуль LUA, и по нажатию шотката Shift+Control+I получаем верно отформатированный код) -
2018-02-04_085632.png
И сразу видно, где начинается и где заканчивается выражение (начинается в строке 8 с if и заканчивается end-ом в строке 18).

Функции с Get дают переменную, но в коментах наверное логичней писать - берём переменную.

Теперь, что касается оптимизации кода -
Экшин 40697 уже контекстно зависим от фокуса и ему не нужны доп условия зависящие от фокуса, он их и так понимает, а значит можно сильно упростить код -
PHP:
isSet = reaper.GetSet_LoopTimeRange( 0, 0, 0, 0, 0 ) --  Берём переменную "Time selection"
focus = reaper.GetCursorContext() --  Берём переменную значения где сейчас фокус?

if isSet == 0 then
  reaper.Main_OnCommand(40697, 0)
else
  if focus == 1 then
    reaper.Main_OnCommand(reaper.NamedCommandLookup('_XENAKIOS_TSADEL'), 0)
  elseif focus == 2 then
    reaper.Main_OnCommand(40089, 0)
  end
end

Ну и наверное стоит развить данный скрипт в область работы с тем-же миди эдитором.
Мы ведь можем отслеживать открыт или нет миди эдитор и точно так-же удалять по каким-то условиям ноты, контролеры....
Ну вот пока только для нот -
PHP:
isSet = reaper.GetSet_LoopTimeRange( 0, 0, 0, 0, 0 ) --  Берём переменную "Time selection"
focus = reaper.GetCursorContext() --  Берём переменную значения где сейчас фокус?
midieditor = reaper.MIDIEditor_GetActive()

if midieditor then
  if isSet == 0 then
    reaper.MIDIEditor_OnCommand(midieditor, 40002)
  else
    reaper.MIDIEditor_OnCommand(midieditor, 40214)
    reaper.MIDIEditor_OnCommand(midieditor, 40746)
    reaper.MIDIEditor_OnCommand(midieditor, 40002)
  end
else
  if isSet == 0 then
    reaper.Main_OnCommand(40697, 0)
  else
    if focus == 1 then
      reaper.Main_OnCommand(reaper.NamedCommandLookup('_XENAKIOS_TSADEL'), 0)
    elseif focus == 2 then
      reaper.Main_OnCommand(40089, 0)
    end
  end
end

Тот же код можно записать несколько иначе, используя другой путь выполнения условий -
PHP:
isSet = reaper.GetSet_LoopTimeRange( 0, 0, 0, 0, 0 ) --  Берём переменную "Time selection"
focus = reaper.GetCursorContext() --  Берём переменную значения где сейчас фокус?
midieditor = reaper.MIDIEditor_GetActive()

if isSet == 0 then
  if midieditor then
    reaper.MIDIEditor_OnCommand(midieditor, 40002)
  else
    reaper.Main_OnCommand(40697, 0)
  end
else
  if midieditor then
    reaper.MIDIEditor_OnCommand(midieditor, 40214)
    reaper.MIDIEditor_OnCommand(midieditor, 40746)
    reaper.MIDIEditor_OnCommand(midieditor, 40002)
  else
    if focus == 1 then
      reaper.Main_OnCommand(reaper.NamedCommandLookup('_XENAKIOS_TSADEL'), 0)
    elseif focus == 2 then
      reaper.Main_OnCommand(40089, 0)
    end
  end
end
Какой вариант лучше - зависит от того, какое условие является более главным.
В данном случаи - и тайм селекшин и открытый миди эдитор - равнозначны, но если вы дальше начнёте развивать код, и например захотите что-то удалять на энвелопах айтемов, а не треков - тайм селекшин станет более главным и тогда второй вариант кода будет удобнее! Хотя с энвелопами айтемов пример не удачный, так как с ними то как раз всё и так работать будет - с этим кодом.
Кстати, мне скрипт нравится, я бы им обычную функцию делита заменил, помониторив ещё другие возможные варианты, когда делит нужен и контекстная его работа удобнее.
Но нужно внимательнее посмотреть штатные экшины -
есть ведь 40307, 40312 для айтемов
 
Последнее редактирование:
  • Like
Реакции: Kokarev Maxim и incubator
Такой вопрос! Как реализовать? Получаем выделенный трек и если выделенных треков нет то
PHP:
    local sel_track = reaper.GetSelectedTrack(0,0)
    if  sel_track == nil then
       return
    end
и вот(в место return) если выделенных треков нет-то, что бы всплывало вот такое вот окно
Снимо1к.PNG
 
Последнее редактирование:
Поздравляю! :)
В нашем полку прибыло?
Да очень увлекательное это занятие, Рипер рано или поздно склонит тебя писать скрипты)
Вот на примере этого скрипта покажу как форматирует код Atom (поставили в него модуль LUA, и по нажатию шотката Shift+Control+I получаем верно отформатированный код) -
И сразу видно, где начинается и где заканчивается выражение (начинается в строке 8 с if и заканчивается end-ом в строке 18).
Красивенько!И удобно! Надо будет себе поставить что бы глаза не разбегались)
Функции с Get дают переменную, но в коментах наверное логичней писать - берём переменную.
Ошибся, прошу прощения но я только начинаю многие вещи пока наугад.
Теперь, что касается оптимизации кода -
Экшин 40697 уже контекстно зависим от фокуса и ему не нужны доп условия зависящие от фокуса, он их и так понимает, а значит можно сильно упростить код -
PHP:
isSet = reaper.GetSet_LoopTimeRange( 0, 0, 0, 0, 0 ) --  Берём переменную "Time selection"
focus = reaper.GetCursorContext() --  Берём переменную значения где сейчас фокус?

if isSet == 0 then
  reaper.Main_OnCommand(40697, 0)
else
  if focus == 1 then
    reaper.Main_OnCommand(reaper.NamedCommandLookup('_XENAKIOS_TSADEL'), 0)
  elseif focus == 2 then
    reaper.Main_OnCommand(40089, 0)
  end
end
Да точно это я не учел,- так намного компактней и красивей!) Первый скрипт слегка комом)
Ну и наверное стоит развить данный скрипт в область работы с тем-же миди эдитором.
Мы ведь можем отслеживать открыт или нет миди эдитор и точно так-же удалять по каким-то условиям ноты, контролеры....
Ну вот пока только для нот -
PHP:
isSet = reaper.GetSet_LoopTimeRange( 0, 0, 0, 0, 0 ) --  Берём переменную "Time selection"
focus = reaper.GetCursorContext() --  Берём переменную значения где сейчас фокус?
midieditor = reaper.MIDIEditor_GetActive()

if midieditor then
  if isSet == 0 then
    reaper.MIDIEditor_OnCommand(midieditor, 40002)
  else
    reaper.MIDIEditor_OnCommand(midieditor, 40214)
    reaper.MIDIEditor_OnCommand(midieditor, 40746)
    reaper.MIDIEditor_OnCommand(midieditor, 40002)
  end
else
  if isSet == 0 then
    reaper.Main_OnCommand(40697, 0)
  else
    if focus == 1 then
      reaper.Main_OnCommand(reaper.NamedCommandLookup('_XENAKIOS_TSADEL'), 0)
    elseif focus == 2 then
      reaper.Main_OnCommand(40089, 0)
    end
  end
end

Тот же код можно записать несколько иначе, используя другой путь выполнения условий -
PHP:
isSet = reaper.GetSet_LoopTimeRange( 0, 0, 0, 0, 0 ) --  Берём переменную "Time selection"
focus = reaper.GetCursorContext() --  Берём переменную значения где сейчас фокус?
midieditor = reaper.MIDIEditor_GetActive()

if isSet == 0 then
  if midieditor then
    reaper.MIDIEditor_OnCommand(midieditor, 40002)
  else
    reaper.Main_OnCommand(40697, 0)
  end
else
  if midieditor then
    reaper.MIDIEditor_OnCommand(midieditor, 40214)
    reaper.MIDIEditor_OnCommand(midieditor, 40746)
    reaper.MIDIEditor_OnCommand(midieditor, 40002)
  else
    if focus == 1 then
      reaper.Main_OnCommand(reaper.NamedCommandLookup('_XENAKIOS_TSADEL'), 0)
    elseif focus == 2 then
      reaper.Main_OnCommand(40089, 0)
    end
  end
end
Отличная идея! Вы уже две модификации сделали и продумали наперед Миди редактор. Я его как то упустил что в "Time Selection" нужно будет тоже ноты стирать.
А может все таки лучше разделить Delete для Основного окна и для Миди редактора?Это же вроде возможно? Потому что я нопример использую миди редактор в Доке и одновременно работаю в аранжировке и вместо кусочка клипов удаляються нотки))
Если разделить на отдельные скрипты.Тогда вопрос можно ли получить фокус из Мидиредактора, на нотах он или на контроллерах?
Какой вариант лучше - зависит от того, какое условие является более главным.
В данном случаи - и тайм селекшин и открытый миди эдитор - равнозначны, но если вы дальше начнёте развивать код, и например захотите что-то удалять на энвелопах айтемов, а не треков - тайм селекшин станет более главным и тогда второй вариант кода будет удобнее! Хотя с энвелопами айтемов пример не удачный, так как с ними то как раз всё и так работать будет - с этим кодом.
Кстати, мне скрипт нравится, я бы им обычную функцию делита заменил, помониторив ещё другие возможные варианты, когда делит нужен и контекстная его работа удобнее.
Но нужно внимательнее посмотреть штатные экшины -
есть ведь 40307, 40312 для айтемов

Ну 40307 там делает cut то есть забирает стираемое в буфер а в процессе работы могут возникнуть запутки с этим)
Я потестирую тогда и попробую отдельный Delete для Миди редактора сделать)) Спасибо за участие! Очень интерестно так обучаться)
 
Можно, и отформатировать в ручную можно пробелами -
PHP:
local sel_track = reaper.GetSelectedTrack(0,0)
if  sel_track == nil then
  mesg = [=[        No Selected
             Track]=]
  reaper.MB(mesg , "", 0)
end
 
  • Like
Реакции: Archie's
Подскажите пожалуйста, не могу ни как сообразить,
как поставить точки автоматизации в тех местах где находится автоматизация в данный момент.
Как получить эту высоту?
Снимок.PNG
PHP:
        local start_time, end_time = reaper.GetSet_LoopTimeRange(0, 0, 0, 0, 0)
        if start_time == end_time then return end
        ---
        local count_track = reaper.CountTracks(0)
        for i = 1, count_track do
          local track = reaper.GetTrack(0, i - 1 )
          local count_env = reaper.CountTrackEnvelopes(track)
          for i = 1, count_env do
            local env = reaper.GetTrackEnvelope(track, i - 1 )


            reaper.InsertEnvelopePoint( env, start_time, 0, 0, 0, 0, 0 )--?????????????????
            reaper.InsertEnvelopePoint( env, end_time, 0, 0, 0, 0, 0 )--?????????????????


          end
        end


        reaper.UpdateArrange()
 
Последнее редактирование:
@Archchie, удивительно, но я точно тем-же занимался вчера.
Получить из уравнения треугольника.
Ну или, если есть возможность ручками выделить кривую и переместить в эту точку плэй курсор - есть экшин такой, поставить поинт на кривую
 
если есть возможность ручками выделить кривую и переместить в эту точку плэй курсор - есть экшин такой, поставить поинт на кривую
Про экшен знаю,но ручками выделить кривую не как-так как это для всех кривых.
Что бы выделить кривую, тоже не могу найти в API
 
@@Michael, спасибище!!!
А я тут целый математический кружок развёл у себя в скрипте, чтоб её вычислить :)...
PS: Но что приятно - вычисленная мной совсем иначе Value с точностью до 12-го знака совпала с значение value вычисляемого из функции Envelope_Evaluate.......

Как же не хватает подробного описания API функций Рипера..., куча функций совершенно с не адекватными названиями и самой функции и переменных. Да ещё и переменные одни и те же в разных функциях называются почему то по разному...
[DOUBLEPOST=1518341060][/DOUBLEPOST]
Что бы выделить кривую, тоже не могу найти в API
Потому как нет в API этого, или опять в не очевидной форме.
@@Michael, может и это есть, а мы не находим?
 
Последнее редактирование:
  • Like
Реакции: incubator и Archie's
@gazzz, Envelope_Evaluate() работает при любой кривой, мой метод вычисления через функции прямоугольного треуголиника работает ЕСТЕСТВЕННО только для линейных кривых, это очевидно....
[DOUBLEPOST=1518351043][/DOUBLEPOST]А вот смотрите какой глюк я споймал -
2018-02-11_132835.png
Чуть мозги себе не сломал - как такое возможно, чтоб было на айтеме две разных кривых громкости, при том, что в перечне она естественно одна.
 
А вот смотрите какой глюк я споймал -
Посмотреть вложение 142479
Чуть мозги себе не сломал - как такое возможно, чтоб было на айтеме две разных кривых громкости, при том, что в перечне она естественно одна.
Envelope_SortPoints() после всех манипуляций с точками.
 
Последнее редактирование:
  • Like
Реакции: Aleksandr Oleynik
@@Michael, ещё один вопрос всплыл - как различить какая кривая Volume выделена, Трековая или Тэйковая?
Имя у ни одно и то-же, а вот время позиций точек разное и нужно точно знать - какая.
По выделенному айтему - не проходит, так как как ни странно, а можно выделить кривую айтема не выделяя сам айтем.

PS: Сам спросил, сам ответил - Envelope_GetParentTake
 
Друзья пытался модифицировать сегодня скрипт x-raym который двигает выбранный трек ниже или выше (на самом деле он его заново создает и стирает) Так вот когда пытаешься ставить его как фунцию в условия он теряет фокус с треков после одного срабатывания и ничем его не вернуть не sws командой не API командой. Я хотел что бы он в зависимости от фокуса двигал или треки или контент. Подскажите пожалуйста как можно поставить его в условия грамотно? Или вернуть фокус?
Код:
focus = reaper.GetCursorContext() --  Берём переменную значения где сейчас фокус?


function movetrackdown()



function Is_Valid_Track(track)
  valid_track = reaper.ValidatePtr(track, "MediaTrack*")
  return valid_track
end

function ReverseTable(t)
  local reversedTable = {}
  local itemCount = #t
  for k, v in ipairs(t) do
      reversedTable[itemCount + 1 - k] = v
  end
  return reversedTable
end

function SaveSelectedTracks(table)
  for i = 0, reaper.CountSelectedTracks(0)-1 do
    table[i+1] = reaper.GetSelectedTrack(0, i)
  end
end



function Main()

  new_tracks = {}

  sel_tracks = ReverseTable( sel_tracks )

  for i, track in ipairs( sel_tracks ) do

    reaper.SetOnlyTrackSelected( track )
 
    reaper.Main_OnCommand(reaper.NamedCommandLookup("_S&M_COPYSNDRCV1"),0) -- copy track with routing
 
    reaper.Main_OnCommand(reaper.NamedCommandLookup("_XENAKIOS_SELNEXTTRACK"),0) -- Select Next Track
    local track_copy = reaper.GetSelectedTrack(0, 0)
 
    if track_copy == track then
       table.insert( new_tracks, track )
      break
    end
    reaper.Main_OnCommand(40914, 0) -- set as last touch
    reaper.Main_OnCommand(reaper.NamedCommandLookup("_S&M_PASTSNDRCV1"),0) -- paste track with routing
 
    local track_copy = reaper.GetSelectedTrack(0, 0)
 
    -- ADD SENDS ENVELOPE
    for category = -1, 1 do
      local sends_count = reaper.GetTrackNumSends( track, category )
      for sendidx = 0, sends_count -1 do
        for envelopeType = 0, 2 do
          local env = reaper.BR_GetMediaTrackSendInfo_Envelope( track, category, sendidx, envelopeType )
          local retval, xml = reaper.GetEnvelopeStateChunk( env, "", false )
          local env_copy = reaper.BR_GetMediaTrackSendInfo_Envelope( track_copy, category, sendidx, envelopeType )
          reaper.SetEnvelopeStateChunk( env_copy, xml, false )
        end
      end
    end
 
    reaper.DeleteTrack( track ) -- Delete Source Track
 
    table.insert( new_tracks, track_copy )
 
  end

  return new_tracks

end

-- INIT
local reaper = reaper

count_selected_track = reaper.CountSelectedTracks( 0 )

if count_selected_track > 0  then





  -- Avoid complex selection with Child and their Parents
  reaper.Main_OnCommand(reaper.NamedCommandLookup("_SWS_UNSELPARENTS"),0) -- Unselect parent track

  -- Save Tracks
  sel_tracks = {}
  SaveSelectedTracks( sel_tracks )

  Main()

  -- Select New Tracks
  if new_tracks then
    for i, track in ipairs( new_tracks ) do
      reaper.SetTrackSelected( track, true )
    end
  end

  -- Select Source Tracks if they still exist
  for i, track in ipairs( sel_tracks ) do
    if Is_Valid_Track( track ) then
      reaper.SetTrackSelected( track, true )
    end
  end
  reaper.TrackList_AdjustWindows(0)


  reaper.Undo_EndBlock("Move selected tracks down on visible track list", -1)



reaper.SetCursorContext(0, fx_env)
end

end



if focus == 0 then movetrackdown()
elseif focus == 1 or 2 or -1 then  reaper.Main_OnCommand(40118, 0) end
 
@incubator,

PHP:
    -----------------------------------------------------------------------------
    local function No_Undo()end; local function no_undo()reaper.defer(No_Undo)end
    -----------------------------------------------------------------------------

    local focus = reaper.GetCursorContext2(true)--  Берём переменную значения где сейчас фокус?
    local r     = reaper.Main_OnCommand
    local sws   = reaper.NamedCommandLookup
    --=====================================

    kolichestvo_sel_tr = reaper.CountSelectedTracks( 0 )     --получаем кол-ва выделенных треков (кроме Мастера)
    if kolichestvo_sel_tr == 0 then                        --если выделенных треков нет то
       reaper.MB('No Select Track','Track',0)               --окно с предупреждением
      no_undo() return                                      --  (no undo); остановить скрипт
    end
    --=================================================

    function next_track()
      for i = kolichestvo_sel_tr-1,0,-1  do                 --создаём цикл опроса по каждому выделенному треку (кроме Мастера)        
        local track = reaper.GetSelectedTrack(0,i+1)          --Получаем выделенный трек из проекта кроме первого
        if  track then                                         --если трек то
          reaper.SetMediaTrackInfo_Value(track,'I_SELECTED',0)  --снять выделение
        end
      end
      reaper.SelectAllMediaItems(0, 0)  --Снять выделения со всех айтамов
      r(40914,0)                        --Track: Set first selected track as last touched track
      r(sws("_S&M_CUTSNDRCV1"),0)      --Cut selected tracks (with routing)
      r(sws("_S&M_PASTSNDRCV1"),0)     --paste track with routing

    end
    ---==============================================================================

    reaper.PreventUIRefresh(1); reaper.Undo_BeginBlock()

    if focus == 0 then
      next_track()
    elseif focus == 1 then
    --?????????????? (item)
    elseif focus == 2 then--
    --???????????????? (envelop)
    end

    reaper.Undo_EndBlock("Move the selected track down one track",1); reaper.PreventUIRefresh(-1)
PHP:
focus = reaper.GetCursorContext2(true) --  Берём переменную значения где сейчас фокус?


function movetrackdown()



function Is_Valid_Track(track)
  valid_track = reaper.ValidatePtr(track, "MediaTrack*")
  return valid_track
end

function ReverseTable(t)
  local reversedTable = {}
  local itemCount = #t
  for k, v in ipairs(t) do
      reversedTable[itemCount + 1 - k] = v
  end
  return reversedTable
end

function SaveSelectedTracks(table)
  for i = 0, reaper.CountSelectedTracks(0)-1 do
    table[i+1] = reaper.GetSelectedTrack(0, i)
  end
end



function Main()

  new_tracks = {}

  sel_tracks = ReverseTable( sel_tracks )

  for i, track in ipairs( sel_tracks ) do

    reaper.SetOnlyTrackSelected( track )

    reaper.Main_OnCommand(reaper.NamedCommandLookup("_S&M_COPYSNDRCV1"),0) -- copy track with routing

    reaper.Main_OnCommand(reaper.NamedCommandLookup("_XENAKIOS_SELNEXTTRACK"),0) -- Select Next Track
    local track_copy = reaper.GetSelectedTrack(0, 0)

    if track_copy == track then
       table.insert( new_tracks, track )
      break
    end
    reaper.Main_OnCommand(40914, 0) -- set as last touch
    reaper.Main_OnCommand(reaper.NamedCommandLookup("_S&M_PASTSNDRCV1"),0) -- paste track with routing

    local track_copy = reaper.GetSelectedTrack(0, 0)

    -- ADD SENDS ENVELOPE
    for category = -1, 1 do
      local sends_count = reaper.GetTrackNumSends( track, category )
      for sendidx = 0, sends_count -1 do
        for envelopeType = 0, 2 do
          local env = reaper.BR_GetMediaTrackSendInfo_Envelope( track, category, sendidx, envelopeType )
          local retval, xml = reaper.GetEnvelopeStateChunk( env, "", false )
          local env_copy = reaper.BR_GetMediaTrackSendInfo_Envelope( track_copy, category, sendidx, envelopeType )
          reaper.SetEnvelopeStateChunk( env_copy, xml, false )
        end
      end
    end

    reaper.DeleteTrack( track ) -- Delete Source Track

    table.insert( new_tracks, track_copy )

  end

  return new_tracks

end

-- INIT
local reaper = reaper

count_selected_track = reaper.CountSelectedTracks( 0 )

if count_selected_track > 0  then





  -- Avoid complex selection with Child and their Parents
  reaper.Main_OnCommand(reaper.NamedCommandLookup("_SWS_UNSELPARENTS"),0) -- Unselect parent track

  -- Save Tracks
  sel_tracks = {}
  SaveSelectedTracks( sel_tracks )

  Main()

  -- Select New Tracks
  if new_tracks then
    for i, track in ipairs( new_tracks ) do
      reaper.SetTrackSelected( track, true )
    end
  end

  -- Select Source Tracks if they still exist
  for i, track in ipairs( sel_tracks ) do
    if Is_Valid_Track( track ) then
      reaper.SetTrackSelected( track, true )
    end
  end
  reaper.TrackList_AdjustWindows(0)


  reaper.Undo_EndBlock("Move selected tracks down on visible track list", -1)



reaper.SetCursorContext(0, fx_env)
end

end



if focus == 0 then movetrackdown()
elseif focus == 1 or 2 or -1 then  reaper.Main_OnCommand(40118, 0) end
 
Последнее редактирование:
  • Like
Реакции: incubator
@Archchie, Спасибо большое! А второй код вы как то исправили? Я не могу найти отличий, но он работает)Как так?
 

Сейчас просматривают