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

У меня есть кнопки, чекбоксы, слайдеры, кнобы, спинбоксы и менюшки в готовом виде.
Ну, в том или ином виде я это уже где-то в одной библиотеке видел. Но всё, что видел, не имеет под собой реализации parent-child, а без этого нормальный гуй не строится.
 
не имеет под собой реализации parent-child
если я правильно понял - речь об объектах, из которых строится новый элемент?
---------
На мой взгляд - достаточно макс. простого варианта, чтобы любой человек мог по быстрому набросать что-то из простейших элементов и привязать к своим ф-ям. Как пример - редактор для touch osc, допустим. Только из картинок делать.
Если нужен какой-либо сложный уникальный элемент - его проще будет написать с нуля.
---------
В общем, объясните если можно, этот момент не программисту, на примере. И чем это может быть полезно.
Кажется, я видел подобное в одной библиотеке для JS, написанной программистом 100%. Это более универсально, но использовать это оказалось очень неудобно. Более того - тот же человек сделал более простой вариант - такой, как я описал выше.
 
Последнее редактирование:
если я правильно понял - речь об объектах, из которых строится новый элемент?
Нет, о реализации концепции, когда у контрола GUI есть родитель. То есть грубо говоря, например есть панелька, на панельке лежат контролы. В этом случае панель является родителем контролов. Из близких к музыкальному софту примеров, где это есть, я могу назвать например Lemur (там есть контейнеры) и Ctrlr, в котором имеются группы и панели с закладками.
 
@Alex_V, ясно, я примерно о том же, просто не знаком с терминологией. И это же не является проблемой, сделать достаточно легко.
Но чем очевидная польза от этого для простых интерфейсов? То есть стоит ли это делать в ущерб простоте?
 
Сильно упрощает проектирование интерфейса, если он выходит за рамки примитивного.
На самом деле упрощает только сохранение групп элементов и их вызов при создании.
В общем то, с жтим заморачиваться стоит только при написании полноценного GUI Editor -а.
А то, о чём пишет женя - это больше учебное пособие и сокращение рутинного труда.
[DOUBLEPOST=1515857827][/DOUBLEPOST]
@Aleksandr Oleynik, по RGB там ошибочка - недавно говорил.
Спасибо!
Исправил.
 
если он выходит за рамки примитивного.
Да, наверное. Но в основном все укладывается в эти рамки, я за простоту. Почти не встречал плагинов(на них ориентируюсь) с каким-то сложным интерфейсом, а там где есть - лучше бы его там небыло;)
Кроме того, при сильной необходимости мы сможем сделать и подобие контейнеров сгруппировав элементы в отдельной ф-и, установив зависимости как угодно.
Без готового примера трудно говорить - а все что я выкладывал это уже сто лет назад было, там все плохо, я иначе сейчас буду делать. На основе того, что уже точно сам успел проверить в плане удобства.
это больше учебное пособие и сокращение рутинного труда.
Ну да, хотя при желании можно будет нарисовать что-то хорошее
 
На самом деле упрощает только сохранение групп элементов и их вызов при создании.
Как человек нарисовавший этого гуя (в основном - стандартного виндового) чертову прорву, позволю себе не согласиться. ;)
 
@Archchie, очень не простыми условиями...
Но в начале нужно понимать что вам нужно.
Я же написал, любой трек может быть одновременно и чайлдом и парентом и если вы точно скрипту не расскажете чтож вам нужно то- он вам ни чего путнего и не выдаст.
 
@Archchie, пожалуйста -
PHP:
counttracks = reaper.CountTracks(0)
if counttracks == nil then return end
for i = 1, counttracks do
  track = reaper.GetTrack(0, i-1)
  ftr = reaper.GetParentTrack(track)
  ttr = reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH")
  if ftr ~= nil and (ttr == 0 or ttr == -1 or ttr == -3) then
    htr = reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
    if htr >= 24 then
      reaper.SetMediaTrackInfo_Value( track, "I_SELECTED", 1)
    end
  end
end
Пояснять нужно или разберётесь?
 
  • Like
Реакции: Archie's
PHP:
  if ftr ~= nil and (ttr == 0 or ttr == -1 or ttr == -3) then

Чтобы избежать подобного, можно использовать контрольную глубину папки:

PHP:
depth = 0
for i = 1, reaper.CountTracks(0) do
  track = reaper.GetTrack(0, i-1)
  ch_depth = reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH")
  depth = depth + ch_depth
  reaper.SetTrackSelected( track, reaper.GetMediaTrackInfo_Value(track, "I_WNDH") >=24
                                  and depth >= 0
                                  and ch_depth <= 0
                                  and not (depth==0 and ch_depth == 0)
                                 )
end
 
В случае с SetMediaTrackInfo_Value() это будет выглядеть как

PHP:
  reaper.SetMediaTrackInfo_Value( track, "I_SELECTED", (reaper.GetMediaTrackInfo_Value(track, "I_WNDH") >=24
                                  and depth >= 0 
                                  and reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH") <= 0
                                  and not (depth==0 and reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH") == 0))
                                  and 1 or 0
                                 )
 
  • Like
Реакции: Aleksandr Oleynik
@@Michael, для понимания и тем более обучения, как мне кажется, лучше все условия, выражения и функции разбивать на как можно более подробные части.
Компактность кода хороша безусловно, но на этапе, когда в голове уже всё уложилось в стройную систему и код читается в лёт.
 
делаю из вашего же кода
Правильно, но одной строки не хватает (и используйте при публикации кода - PHP) -
PHP:
counttracks = reaper.CountTracks(0)
if counttracks == nil then return end
for i = 1, counttracks do
  track = reaper.GetTrack(0, i-1)
  ftr = reaper.GetParentTrack(track)
  ttr = reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH")
  if ftr ~= nil and (ttr == 0 or ttr == -1 or ttr == -3) then
    htr = reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
    if htr >= 24 then
      reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 0)
    end
  end
end
reaper.TrackList_AdjustWindows(false)
 
Объясните мне пожалуйста магию, первый код не работает и ошибки не какой не выдаёт,а второй код работает ,причем они абсолютно идентичны
PHP:
counttracks = reaper.CountTracks(0)
if counttracks == nil then  return end
for i = 1, counttracks do
  track = reaper.GetTrack(0, i-1)
  ftr = reaper.GetParentTrack(track)
  ttr = reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH")
  if ftr ~= nil and (ttr == 0 or ttr == -1 or ttr == -3) then
    htr = reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
    if htr >= 24 then
      reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER ", 0)
    end
  end
end                                                                                  
reaper.TrackList_AdjustWindows(false)
PHP:
counttracks = reaper.CountTracks(0)
if counttracks == nil then return end
for i = 1, counttracks do
  track = reaper.GetTrack(0, i-1)
  ftr = reaper.GetParentTrack(track)
  ttr = reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH")
  if ftr ~= nil and (ttr == 0 or ttr == -1 or ttr == -3) then
    htr = reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
    if htr >= 24 then
      reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 0)
    end
  end
end
reaper.TrackList_AdjustWindows(false)
 
Вот тут пробел лишний:
Я на это регулярно тоже накалываюсь - по двойному щелчку мыши копирую атрибут, а он какраз с пробелом в конце копируется - вот и....
[DOUBLEPOST=1516558231][/DOUBLEPOST]@Archchie, у вас там в коде куча ошибок - исправьте их в начале.
end=ы пропущенные и ещё что-то не так
Ну вот в этой строке end нет -
if counttracks == 0 then--------------------------если треков нет,то

Ещё, defer должен запускать какую-то функцию, сильно в коде не разбирался, но видимо motion, значит писать нужно - reaper.defer (motion)

Ну и вот так, ни кто не пишет -

PHP:
function close()                                                                                                     
  for i = 0, counttracks -1 do-----------------------------------создаём цикл опроса по каждому треку (кроме Мастера) 
    local track = reaper.GetTrack(0,i)------------------------------получаем  Трек                                 
    reaper.SetMediaTrackInfo_Value( track, 'I_SELECTED', 0 )-----------снимаем выделение со всех треков         
    if reaper.GetMediaTrackInfo_Value(track,"I_FOLDERDEPTH")==1 then-----если трек папка то                   
      reaper.SetMediaTrackInfo_Value( track, 'I_SELECTED', 1 )-----------------выделить трек                   
      r(sws('_SWS_COLLAPSE'),0)------------------------------------SWS: Set selected folder(s) collapsed
    end                                                                                                       
  end     
  r(sws('_SWS_SELCHILDREN'),0)---------------------------SWS: Select only children of selected folders
  r(sws('_SWSTL_HIDEMCP'),0)-----------------------------SWS: Hide selected track(s) from MCP     
  for i = 0, counttracks -1 do ----------------------------создаём цикл опроса по каждому треку (кроме Мастера)
    track = reaper.GetTrack(0,i)--------------------------получаем Трек                                                                       
    reaper.SetMediaTrackInfo_Value( track,'I_SELECTED',0)--снимаем выделение с опрошенного трека                       
  end                                                                                                                           
  reaper.Undo_EndBlock('close folder (TCP,MCP)',-1)
 
  function motion()
    counttracks = reaper.CountTracks(0)
    if counttracks == nil then return end
    for i = 1, counttracks do
      track = reaper.GetTrack(0, i-1)
      ftr = reaper.GetParentTrack(track)
      ttr = reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH")
      if ftr ~= nil and (ttr == 0 or ttr == -1 or ttr == -3) then
        htr = reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
        if htr >= 24 then
          reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 1)
        else
          reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 0)
        end
      end
    end
    reaper.TrackList_AdjustWindows(false)
    reaper.defer()
  end 
  motion()
end

Не знаю, может и работать не будет....
Пишут вот так -

PHP:
function motion()
  counttracks = reaper.CountTracks(0)
  if counttracks == nil then return end
  for i = 1, counttracks do
    track = reaper.GetTrack(0, i-1)
    ftr = reaper.GetParentTrack(track)
    ttr = reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH")
    if ftr ~= nil and (ttr == 0 or ttr == -1 or ttr == -3) then
      htr = reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
      if htr >= 24 then
        reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 1)
      else
        reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 0)
      end
    end
  end
  reaper.TrackList_AdjustWindows(false)
  reaper.defer(motion)
end 

function close()                                                                                                     
  for i = 0, counttracks -1 do-----------------------------------создаём цикл опроса по каждому треку (кроме Мастера) 
    local track = reaper.GetTrack(0,i)------------------------------получаем  Трек                                 
    reaper.SetMediaTrackInfo_Value( track, 'I_SELECTED', 0 )-----------снимаем выделение со всех треков         
    if reaper.GetMediaTrackInfo_Value(track,"I_FOLDERDEPTH")==1 then-----если трек папка то                   
      reaper.SetMediaTrackInfo_Value( track, 'I_SELECTED', 1 )-----------------выделить трек                   
      r(sws('_SWS_COLLAPSE'),0)------------------------------------SWS: Set selected folder(s) collapsed
    end                                                                                                       
  end     
  r(sws('_SWS_SELCHILDREN'),0)---------------------------SWS: Select only children of selected folders
  r(sws('_SWSTL_HIDEMCP'),0)-----------------------------SWS: Hide selected track(s) from MCP     
  for i = 0, counttracks -1 do ----------------------------создаём цикл опроса по каждому треку (кроме Мастера)
    track = reaper.GetTrack(0,i)--------------------------получаем Трек                                                                       
    reaper.SetMediaTrackInfo_Value( track,'I_SELECTED',0)--снимаем выделение с опрошенного трека                       
  end                                                                                                                           
  reaper.Undo_EndBlock('close folder (TCP,MCP)',-1)
 
  motion()
end

Но повторюсь, я в коде не разбирался, просто грубые ошибки описал.
atexit() также как правило пишется для запуска при выходи из скрипта (после завершения дефера) какой-то функции, типпа такого -
PHP:
function exit ()
трамтатамтатам
end

reaper.atexit (exit)
 
Последнее редактирование:
потому что он в следующий строке
Тогда лучше писать так -
PHP:
if counttracks == 0 then   --если треков нет,то
  reaper.Undo_EndBlock('',-1)
  return
end  --Undo и stop
В некоторых языках лишний пробел в конце строки - и код работать не будет.
В такой редактор как Atom, например, можно поставить модуль синтаксиса LUA и по шоткату приводить код в правильный вид, со всеми верными отступами, форматами и параграфами.
 
Я на это регулярно тоже накалываюсь - по двойному щелчку мыши копирую атрибут, а он какраз с пробелом в конце копируется - вот и....
В принципе, от проблем такого рода можно попытаться избавиться, заведя пачку глобальных констант типа такого:
Код:
  I_FOLDERDEPTH = "I_FOLDERDEPTH"
  I_WNDH = "I_WNDH"
и потом в коде использовать их, а не строковые выражения. После имени переменной количество пробелов значения не имеет. От опечаток в имени переменных это, правда, не спасет. Был бы язык без неявных переменных, и эту проблемку можно было бы решить. Но в Lua - вряд ли.
 
В некоторых языках лишний пробел в конце строки - и код работать не будет.
Вот за придумывание языков, в которых работоспособность похожим образом зависит от количества пробелов, надо расстреливать из рогатки.
 
Скажите пожалуйста как сделать что бы в экшен листе появился статус (ON OFF)
он включается выключается но статуса нет—неудобно
PHP:
function motion() 
  counttracks = reaper.CountTracks(0)
  if counttracks == nil then return end
  for i = 1, counttracks do
    track = reaper.GetTrack(0, i-1)
    ftr = reaper.GetParentTrack(track)
    ttr = reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH")
    if ftr ~= nil and (ttr == 0 or ttr == -1 or ttr == -3) then
      htr = reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
      if htr >= 24 then
        reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 1)
        else
        reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 0)
      end
    end
  end
  reaper.TrackList_AdjustWindows(false)
  reaper.defer(motion)
end 
motion()
 
Скажите пожалуйста как сделать что бы в экшен листе появился статус (ON OFF)
Для каких целей? Что не удобно?
Если нужно видеть работает скрипт или нет, есть давно сделаный Михаилом функционал - "включающий-выключающий" кнопку на тулбаре.
PHP:
function motion()
  counttracks = reaper.CountTracks(0)
  if counttracks == nil then return end
  for i = 1, counttracks do
    track = reaper.GetTrack(0, i-1)
    ftr = reaper.GetParentTrack(track)
    ttr = reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH")
    if ftr ~= nil and (ttr == 0 or ttr == -1 or ttr == -3) then
      htr = reaper.GetMediaTrackInfo_Value(track, "I_WNDH")
      if htr >= 24 then
        reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 1)
        else
        reaper.SetMediaTrackInfo_Value( track, "B_SHOWINMIXER", 0)
      end
    end
  end
  reaper.TrackList_AdjustWindows(false)
  reaper.defer(motion)
end

-- Set ToolBar Button ON
function SetButtonON()
  is_new_value, filename, sec, cmd, mode, resolution, val = reaper.get_action_context()
  state = reaper.GetToggleCommandStateEx( sec, cmd )
  reaper.SetToggleCommandState( sec, cmd, 1 ) -- Set ON
  reaper.RefreshToolbar2( sec, cmd )
end
--
-- Set ToolBar Button OFF
function SetButtonOFF()
  is_new_value, filename, sec, cmd, mode, resolution, val = reaper.get_action_context()
  state = reaper.GetToggleCommandStateEx( sec, cmd )
  reaper.SetToggleCommandState( sec, cmd, 0 ) -- Set OFF
  reaper.RefreshToolbar2( sec, cmd )
end
----------------------------------------------------------------------------------------------------

SetButtonON() -- функция запуска срипта с "поджигом" кнопки тулбара

motion() -- основная функция дефера

reaper.atexit(SetButtonOFF) -- выход из скрипта с запуском функции выхода с тушением кнопки тулбара
Если нужно "знать" включен скрипт или нет для работы какого-то другого скрипта, то тут тоже масса возможностей, например использовать SWS/S&M: Dummy toggle - это пустышки Экшины, у которых только статус и меняется
 
  • Like
Реакции: Archie's

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