Изменение кей-команд "на лету" (Changeble Hot Keys).

Тема в разделе "Cockos Reaper", создана пользователем diggidon, 21 мар 2016.

  1. diggidon

    diggidon Super Moderator Команда форума

    Регистрация:
    26 май 2008
    Сообщения:
    6.577
    Симпатии:
    6.713
    Род занятий:
    Жму кнопки, кручу ручки...
    Адрес:
    Днепр UA
    Господа Рипероманы, встречайте новую, 100% уникальную фичу - Сhangeble Hot Keys. Ни один другой DAW гарантированно так не умеет.

    Концепт был следующий:
    1. Зарезервировать несколько клавиш на клавиатуре (в нашем случае это F1-F12), назначение которых менялось бы в зависимости от задачи, над которой вы сейчас работаете.
    Первый пресет - Go to marker 1-12, второй пресет - Select track 1-12, третий пресет - работа со стреч маркерами, четвёртый... пятый... девяносто девятый...
    2. Менять назначение этих клавиш (вызывать пресеты) что называется "на лету" - по нажатию другой клавиши, или соответствующей кнопки на тулбаре.
    3. Сделать так, чтобы было видно, какой именно пресет сейчас используется. Принцип зависимой "кнопки-лампочки" - при включении одного пресета соответствующая кнопка загорается, остальные кнопки гаснут.

    В качестве примера рассмотрим два пресета. Один - Go to marker 1-12, второй - Select track 1-12.
    Changeble Hot Key 1.gif
    В мультике всё видно - выбираем пресет кнопкой на тулбаре, жмём F1-F12.
    Обратите внимание, как ведут себя кнопки тулбара. Если нажимать не мышкой, а привязанными к этим кнопкам клавишами, они будут вести себя точно так же.

    1.Есть два Lua скрипта (которые в дальнейшем следует использовать как шаблон для создания своих собственных пресетов).
    ! Go to marker 1-12 (Changeble Key Preset).lua
    ! Select track 1-12 (Changeble Key Preset).lua

    2.Помещаем их в папку \AppData\Roaming\REAPER\Scripts, импортируем в Рипер (Action List → ReaScript → Load...)
    3. При запуске любого из этих скриптов в папке Scripts создадутся ещё 12 скриптов
    ChanKey01.lua ... ChanKey12.lua, их тоже импортируеми в Рипер, и назначаем их на клавиши F1-F12.
    4. Делаем собственные пресеты.
    Для этого нужно сделать копию одного из двух шаблонных скриптов (! Go to marker 1-12 (Changeble Key Preset).lua или ! Select track 1-12 (Changeble Key Preset).lua), копию отредактировать, переименовать как удобно, импортировать в Рипер.
    Standart Action.jpg SWS Custom Scripts.jpg
    Если вы планируете использовать в пресете стандартные экшны Рипера, используйте в качестве шаблона
    ! Go to marker 1-12 (Changeble Key Preset).lua
    Во всех остальных случаях (кастомы, SWS extension, скрипты) используйте в качестве шаблона
    ! Select track 1-12 (Changeble Key Preset).lua
    Где посмотреть/скопировать Command ID нужного экшна/кастома/скрипта:
    Command ID.jpg

    5. Привязываем вновь созданные и импортированные скрипты-пресеты к кнопкам на тулбаре. При желании, назначаем на каждый скрипт-пресет кнопку на клавиатуре или миди-контроллере.
    Собсно, всё.
    Проверено, работает, летает...)))
    Огромное, просто ОГРОМЕННОЕ СПАСИБИЩЕ Саше Олейнику @Aleksandr Oleynik за реализацию этого проекта! Ну, и мне немножко (за то, что повыносил ему мозг своими техзаданиями :)).

    P.S. Безусловно мы понимаем, что процедура создания своих собственных пресетов, мягко говоря, абсолютно не юзер френдли, особенно для не очень подготовленного пользователя (впрочем, сам процесс работы с уже готовыми пресетами - это просто огонь).
    Поэтому в идеале очень хотелось бы прикрутить ко всему этому делу какой-нибудь понятный юзер интерфейсик - именно для создания своих собственных пресетов. Типа, жмём Create User Preset → выплывает 12 кнопок → жмём на каждую кнопку, выбираем нужный экшн → Save As... → погнали.
    И если к этому делу подключатся наши гуру-скриптописатели (например, @@Michael, @EUGEN27771), мы будем очень рады.
     

    Вложения:

    arkaine, podushkin, stepperian и 17 другим нравится это.
  2. Aleksandr Oleynik

    Aleksandr Oleynik Well-Known Member

    Регистрация:
    16 янв 2007
    Сообщения:
    18.219
    Симпатии:
    10.305
    Пол:
    Мужской
    Адрес:
    Киев
    Сама возможность данной фичи уже обсуждалась ранее -
    http://rmmedia.ru/threads/118091/page-11#post-1950968
    И достаточно бурно пообсуждалась.
    Но по скольку, так сказать "Реального Заказчика" не появилось ( с реальной необходимостью довести всё до работающих скриптов) - то тормознулость тогда. Пару запросов на подобную фичу возникали от разных Форумчан и после этого.
    Но вот тут Пан Дигидон загорелся не на шутку - ну и - вышло то, что вышло.
    Если Фича будет восстребованна, я подумаю как её сделать более Юзабилити.
    Ну и понятно, что без помощи @@@Michael, @@EUGEN27771 не справлюсь!
     
    Последнее редактирование: 22 мар 2016
    Andruha, Хитчер, Aliko и 5 другим нравится это.
  3. EUGEN27771

    EUGEN27771 Well-Known Member

    Регистрация:
    23 апр 2010
    Сообщения:
    2.283
    Симпатии:
    1.962
    Пол:
    Мужской
    еще тот "гуру", я скорее сдуру-скриптописатель(это я про себя только).
    А что надо, если конкретнее?
     
    Хитчер и Aliko нравится это.
  4. Aleksandr Oleynik

    Aleksandr Oleynik Well-Known Member

    Регистрация:
    16 янв 2007
    Сообщения:
    18.219
    Симпатии:
    10.305
    Пол:
    Мужской
    Адрес:
    Киев
    С чего ты скриптописатель, не важно - но то, что умеешь ты, мне пока и не снилось :)

    Нужно придумать механизм автоматической перезаписи команд при создании нового Скрипта-Пресета для новой группы хоткеев.
    Сейчас ID каждого из Экшинов (Кастом Экшинов) нужно ручками вписывать (переписывать) в новый Скрипт-Пресет.
    А было бы круто сделать некое GUI, в котором было бы -
    1. 12 кнопок, нажимая на которые возникал бы Action List - выбираешь Экшин, делаешь Copy selected action command ID - и ID попадает в таблицу скрипта (может и как-то иначе, но так, чтоб любому "дундуку было ясно что делать".
    PS: И ещё нужно бы на них шот каты из скрипта иметь возможность назначать :(
    2. И большая кнопка - "Создать и зарегистрировать новый Скрипт-Пресет для Группы Хоткеев" (ну или по проще назвать :) ) - нажал на неё, скрипт предложил ввести Имя Скрипта и все данные из таблиц c ID в нужные места записал. ну и сообщил, что какие-то из 12 ячеек остались пустыми (и учёл это в скрипте).
    PS: И тут тоже засада - нужно и эти скрипты вешать на кнопки в Тулюаре и/или на хоткеи назначать иметь возможность :(
    --- добавлено 22 мар 2016, дата сообщения: 22 мар 2016 ---
    PS: В общем, чтоб функционал получился - "для солдатов и матросов" - нужно долго продумывать и много писать.
    А сейчас -
    делаешь дубликат скрипта, подменяешь в его начале ID-шники на новые по каждой из 12-и команд, сохраняешь, добавляешь на Тулбар и пользуешься.
    Кому реально нужно - на мой взгляд разберуться.
    Вот Женя же разобрался, не умея писать скрипты ВООБЩЕ.
     
  5. diggidon

    diggidon Super Moderator Команда форума

    Регистрация:
    26 май 2008
    Сообщения:
    6.577
    Симпатии:
    6.713
    Род занятий:
    Жму кнопки, кручу ручки...
    Адрес:
    Днепр UA
    Ну если совсем для "пионера", то как-то так:
    Это как оно должно нмв выглядеть. Технические детали Саша описал.

    Хотя мне, скажу честно, и так офигенно, потому что мнем это было ОЧЕНЬ нужно. Один раз скрипт-пресет сделал - и забыл, а пользуешься им потом постоянно, и с большим комфортом...
    Но неподготовленный юзер запросто может обломаться именно на этапе создания своего скрипта-пресета, поэтому какую-нибудь понятную рамочку-табличку прикрутить хотелось бы.
     
    AntonCorea и Aleksandr Oleynik нравится это.
  6. Aleksandr Oleynik

    Aleksandr Oleynik Well-Known Member

    Регистрация:
    16 янв 2007
    Сообщения:
    18.219
    Симпатии:
    10.305
    Пол:
    Мужской
    Адрес:
    Киев
    Женя, чтоб совсем для "не в теме" - прийдётся Очень много делать и не факт, что возможно, например Action ID подтянуть в скрипт при выборе Action в Action List.
     
  7. EUGEN27771

    EUGEN27771 Well-Known Member

    Регистрация:
    23 апр 2010
    Сообщения:
    2.283
    Симпатии:
    1.962
    Пол:
    Мужской
    Может быть сделаю, если будет время, пока другие интересные темы есть, только экшн придется руками вставлять в диалог.
    В принципе, сделать и Вы можете, могу дать кнопки, а там дальше цеплять можно что угодно.
    В общем, вот простые кнопки,
    PHP:
    --------------------------------------------------------------------------------
    ---   
    Simple Element Class   ---------------------------------------------------
    --------------------------------------------------------------------------------
    local Element = {}
    function 
    Element:new(x,y,w,hr,g,b,albl,fnt,fnt_sznorm_val)
        
    local elm = {}
        
    elm.def_xywh = {x,y,w,h,fnt_sz} -- its default coord,used for Zoom etc
        elm
    .xelm.yelm.welm.xywh
        elm
    .relm.gelm.belm.rgba
        elm
    .lblelm.fntelm.fnt_sz  lblfntfnt_sz
        elm
    .norm_val norm_val
        
    ------
        
    setmetatable(elmself)
        
    self.__index self
        
    return elm
    end
    --------------------------------------------------------------
    --- Function for 
    Child Classes(args Child,Parent Class) ----
    --------------------------------------------------------------
    function 
    extended(ChildParent)
         
    setmetatable(Child,{__index Parent})
    end
    --------------------------------------------------------------
    ---   
    Element Class Methods(Main Methods)   ------------------
    --------------------------------------------------------------
    function 
    Element:update_xywh()
      if 
    not Z_w or not Z_h then return end -- return if zoom not defined
      
    if Z_w>0.5 and Z_w<3 then
       self
    .xself.math.ceil(self.def_xywh[1]* Z_w) , math.ceil(self.def_xywh[3]* Z_w) --upd x,w
      end
      
    if Z_h>0.5 and Z_h<3 then
       self
    .yself.math.ceil(self.def_xywh[2]* Z_h) , math.ceil(self.def_xywh[4]* Z_h) --upd y,h
      end
      
    if Z_w>0.5 or Z_h>0.5  then --fix it!--
         
    self.fnt_sz math.max(9,self.def_xywh[5]* (Z_w+Z_h)/2)
         
    self.fnt_sz math.min(22,self.fnt_sz)
      
    end    
    end
    --------
    function 
    Element:pointIN(p_xp_y)
      return 
    p_x >= self.and p_x <= self.self.and p_y >= self.and p_y <= self.self.h
    end
    --------
    function 
    Element:mouseIN()
      return 
    gfx.mouse_cap&1==and self:pointIN(gfx.mouse_x,gfx.mouse_y)
    end
    --------
    function 
    Element:mouseDown()
      return 
    gfx.mouse_cap&1==and self:pointIN(mouse_ox,mouse_oy)
    end
    --------
    function 
    Element:mouseClick()
      return 
    gfx.mouse_cap&1==and last_mouse_cap&1==and
      
    self:pointIN(gfx.mouse_x,gfx.mouse_y) and self:pointIN(mouse_ox,mouse_oy)      
    end
    --------
    function 
    Element:draw_frame()
      
    local x,y,w,h  self.x,self.y,self.w,self.h
      gfx
    .rect(xywh0)--frame1
      gfx
    .roundrect(xyw-1h-13true)--frame2      
    end
    --------------------------------------------------------------------------------
    ---   
    Create Element Child Classes(Button,Slider,Knob)   -----------------------
    --------------------------------------------------------------------------------
    local Button ={}; local Knob ={}; local Slider ={};
      
    extended(ButtonElement)
      
    extended(Knob,   Element)
      
    extended(SliderElement)
    ---
    Create Slider Child Classes(V_Slider,H_Slider)----
    local H_Slider ={}; local V_Slider ={};
      
    extended(H_SliderSlider)
      
    extended(V_SliderSlider)

    --------------------------------------------------------------------------------
    --------------------------------------------------------------------------------
    ---   
    Button Class Methods   ---------------------------------------------------
    --------------------------------------------------------------------------------
    function 
    Button:draw_lbl()
        
    local x,y,w,h  self.x,self.y,self.w,self.h
        local fnt
    ,fnt_sz self.fntself.fnt_sz
        
    --Draw btn lbl(text)--
          
    gfx.set(0.7101)--set label color
          gfx
    .setfont(1fntfnt_sz);--set label fnt
            local lbl_w
    lbl_h gfx.measurestr(self.lbl)
            
    gfx.x+(w-lbl_w)/2gfx.y+(h-lbl_h)/2
            gfx
    .drawstr(self.lbl)
    end
    ---------------------
    function 
    Button:draw()
        
    self:update_xywh()--Update xywh(if wind changed)
        
    local x,y,w,h  self.x,self.y,self.w,self.h
        local r
    ,g,b,a  self.r,self.g,self.b,self.a
        
    ---Get L_mouse state--
              --
    in element--
              if 
    self:mouseIN() then a=a+0.1 end
              
    --in elm L_down--
              if 
    self:mouseDown() then a=a+0.2 end
              
    --in elm L_up(released and was previously pressed)--
              if 
    self:mouseClick() then --[[self.onClick()]] end
        
    --Draw btn(body,frame)--
        
    gfx.set(r,g,b,a)--set btn color
        gfx
    .rect(x,y,w,h,true)--body
        self
    :draw_frame()
        ------------------------
        
    self:draw_lbl()
    end
    -------------------------------------------------
    ----
    Objects--------------------------------------
    -------------------------------------------------
    local btn1 Button:new(20,  20,50,50,  0.7,0.3,0.3,0.5"B1","Arial",20 )
    local btn2 Button:new(80,  20,50,50,  0.7,0.3,0.3,0.5"B2","Arial",20 )
    local btn3 Button:new(14020,50,50,  0.7,0.3,0.3,0.5"B3","Arial",20 )
    local btn4 Button:new(20,  80,50,50,  0.3,0.7,0.3,0.5"B4","Arial",20 )
    local btn5 Button:new(80,  80,50,50,  0.3,0.7,0.3,0.5"B5","Arial",20 )
    local btn6 Button:new(14080,50,50,  0.3,0.7,0.3,0.5"B6","Arial",20 )
    local Button_TB = {btn1,btn2,btn3,btn4,btn5,btn6}

    ------------------------------------------------
    ------------------------------------------------
    function 
    DRAW()
    for 
    key,btn in pairs(Button_TB) do btn:draw() end
    end

    --------------------------------------------------------------------------------
    --
    Init--------------------------------------------------------------------------
    --------------------------------------------------------------------------------
    function 
    Init()
    --
    Some gfx Wnd Default Values--------------
    local R,G,20,20,20        --0..255 form
    Wnd_bgd 
    G*256 B*65536 --red+green*256+blue*65536
    Wnd_Title
    ,Wnd_W,Wnd_H,Wnd_Dock,Wnd_X,Wnd_Y "TEST"210,1500,100,320
    --Init window------------------------------
    gfx.clear Wnd_bgd      
    gfx
    .initWnd_TitleWnd_W,Wnd_HWnd_DockWnd_X,Wnd_Y )
    --
    Mouse--
    last_mouse_cap 0
    last_x
    last_y 00
    end
    -------------------------
    --
    Mainloop---------------
    function 
    mainloop()
    Z_w,Z_h gfx.w/Wnd_Wgfx.h/Wnd_H
    if gfx.mouse_cap&1==and last_mouse_cap&1==0 then
        mouse_ox
    mouse_oy gfx.mouse_xgfx.mouse_y
    end
    Ctrl  
    gfx.mouse_cap&4==4
    Shift 
    gfx.mouse_cap&8==8
    ----------------------
    --
    DRAW,MAIN function--
       
    DRAW()--Main()
    ----------------------
    ----------------------
    last_mouse_cap gfx.mouse_cap
    last_x
    last_y gfx.mouse_xgfx.mouse_y
    char 
    gfx.getchar()
    if 
    char~=-1 then reaper.defer(mainloopend --defer
    -----------
    gfx.update()
    -----------
    end
    ---------------------------------------
    ---------------------------------------
    Init()
    mainloop()
    Добавить,удалить,поменять можно здесь
    Снимок.PNG
    Как добавить действия Вы знаете
     
    Последнее редактирование: 22 мар 2016
    RJ Baker, Beckoff, Aleksandr Oleynik и ещё 1-му нравится это.
  8. Aleksandr Oleynik

    Aleksandr Oleynik Well-Known Member

    Регистрация:
    16 янв 2007
    Сообщения:
    18.219
    Симпатии:
    10.305
    Пол:
    Мужской
    Адрес:
    Киев
    Это очень здорово! Ждём! :)

    Как ID брать, выбирая Action из списка экшинов? Или просто - скопировал ID - вставил в диалоговое окно User Input?
    В общем ты так и написал -
     
  9. EUGEN27771

    EUGEN27771 Well-Known Member

    Регистрация:
    23 апр 2010
    Сообщения:
    2.283
    Симпатии:
    1.962
    Пол:
    Мужской
    Наверное, только так.. других вариантов я не знаю.
     
  10. diggidon

    diggidon Super Moderator Команда форума

    Регистрация:
    26 май 2008
    Сообщения:
    6.577
    Симпатии:
    6.713
    Род занятий:
    Жму кнопки, кручу ручки...
    Адрес:
    Днепр UA
    Не забывайте, что там ещё одна "засада" - разные шаблонные скрипты под стандартные экшны и под кастомы/цикл/SWS/скрипты. Как с этим быть?
    Я, повторюсь, довольно быстро разобрался, в том числе и как сделать микс-скрипт (часть штатных, часть кастомов/цикл/SWS/скриптов).
    Но мы же думаем о функционале для не очень продвинутых юзеров... Чтобы не отпугнуло... Фича-то реально обалденная получилась, у меня вчера реально крышу снесло от вновь открывшихся возможностей - 10 штук пресетов себе уже запилил, и то ли ещё будет))
     
    AntonCorea нравится это.
  11. Aleksandr Oleynik

    Aleksandr Oleynik Well-Known Member

    Регистрация:
    16 янв 2007
    Сообщения:
    18.219
    Симпатии:
    10.305
    Пол:
    Мужской
    Адрес:
    Киев
    А ведь где-то же хранится этот список наименований Action и их ID!
    --- добавлено 22 мар 2016, дата сообщения: 22 мар 2016 ---
    Это какраз не сложно! Патерн, который будет отдуплять чисто цифровой ID от цифро-буквенного и соответственно использовать разные шаблоны команд.
     
    diggidon нравится это.
  12. diggidon

    diggidon Super Moderator Команда форума

    Регистрация:
    26 май 2008
    Сообщения:
    6.577
    Симпатии:
    6.713
    Род занятий:
    Жму кнопки, кручу ручки...
    Адрес:
    Днепр UA
    Ну не совсем так, что-то там я наваял... :rolleyes:
    http://rmmedia.ru/threads/107757/#post-1890890
    Впрочем, да, это действительно не скриптописание, а так, баловство... Написать скрипт - это не портировать кастом в eel.
     
    AntonCorea и Aleksandr Oleynik нравится это.
  13. Aleksandr Oleynik

    Aleksandr Oleynik Well-Known Member

    Регистрация:
    16 янв 2007
    Сообщения:
    18.219
    Симпатии:
    10.305
    Пол:
    Мужской
    Адрес:
    Киев
    Не скромничай, в любом случае ты совсем не годишься на роль шитконтрола для юзабилити, ты и между строк читать умеешь! :)
     
    diggidon нравится это.
  14. leshachooze

    leshachooze Member

    Регистрация:
    15 фев 2013
    Сообщения:
    32
    Симпатии:
    33
    Пол:
    Мужской
    Нет слов, кроме восхищения

    Идеально для тех, кто использует VST-кнопки, можно наконец реализовать добавление эффекта на дорожку или на айтем в одной кнопке.

    Аплодирую!
     
    Furqat нравится это.
  15. lil-burn

    lil-burn Well-Known Member

    Регистрация:
    15 авг 2012
    Сообщения:
    903
    Симпатии:
    626
    Пол:
    Мужской
    Адрес:
    Екатеринбург
    @EUGEN27771 поднатаскал меня немного по gfx, так что на днях попробую реализовать нечто похожее на это
     
    stepperian, diggidon и Aleksandr Oleynik нравится это.
  16. RJ Baker

    RJ Baker Well-Known Member

    Регистрация:
    15 июл 2006
    Сообщения:
    942
    Симпатии:
    411
    Пол:
    Мужской
    Род занятий:
    Музыка, аранжировка
    Адрес:
    Мариуполь
    А можно ли расписать подробнее как прикрепить к получившимся кнопкам действия (стандартные экшены и скриптовые или это неважно?)
     
  17. EUGEN27771

    EUGEN27771 Well-Known Member

    Регистрация:
    23 апр 2010
    Сообщения:
    2.283
    Симпатии:
    1.962
    Пол:
    Мужской
    Сами кнопки получились - это уже хорошо. Это очень старый скрипт, но он наиболее простой - в этом и фокус, оказывается.
    Раскомментировать эту строку if self:mouseClick() then --[[self.onClick()]] end - убрать двойные кв. скобки, я спецом закомментил, хотя нужно было иначе сделать.
    Должно быть так - if self:mouseClick() and self.onClick then self.onClick() end
    Теперь, каждой кнопке можно дать свое действие - в общем случае - любая функция, а в Вашем конкретном - по такому принципу:
    --- Исправлено ---
    -- Methods -----
    command = 1007 -- Это только пример, можете писать напрямую вместо command!!!
    btn1.onClick = function() reaper.Main_OnCommand(command, 0) end
    btn2.onClick = ...
    btn3.onClick = ...
    ...etc

    Где command - это command ID - смотреть в списке экшнов.
     
    Последнее редактирование: 8 янв 2017
    RJ Baker нравится это.
  18. RJ Baker

    RJ Baker Well-Known Member

    Регистрация:
    15 июл 2006
    Сообщения:
    942
    Симпатии:
    411
    Пол:
    Мужской
    Род занятий:
    Музыка, аранжировка
    Адрес:
    Мариуполь
    @EUGEN27771, спасибо за ответ, но, извините не все понял, написал в личку. Сделал много кнопочек осталось их научится назначать..
     
  19. EUGEN27771

    EUGEN27771 Well-Known Member

    Регистрация:
    23 апр 2010
    Сообщения:
    2.283
    Симпатии:
    1.962
    Пол:
    Мужской
    @RJ Baker, поправил, моя вина(писал по памяти, ошибся).
    Верхнюю строку( if self:mouseClick() ... ) тоже исправьте, чтобы на "пустые" кнопки не было ошибок.
     
    RJ Baker нравится это.
  20. RJ Baker

    RJ Baker Well-Known Member

    Регистрация:
    15 июл 2006
    Сообщения:
    942
    Симпатии:
    411
    Пол:
    Мужской
    Род занятий:
    Музыка, аранжировка
    Адрес:
    Мариуполь
    @EUGEN27771, да, теперь работает, большое спасибо! ура!
    Но.. только со стандартными экшенами, а там где ID скриптов-кастомных экшенов я по аналогии с выложенным выше скриптом Select track 1-12 (Changeble Key Preset).lua пытался что то сделать, но выдает ощибки, подскажите как правильно описать command ID в данном случае?
    Нужно ли вводить какую то переменную типа
    local btn2 = "_SWS_SEL1" или как то еще?
     
  21. lil-burn

    lil-burn Well-Known Member

    Регистрация:
    15 авг 2012
    Сообщения:
    903
    Симпатии:
    626
    Пол:
    Мужской
    Адрес:
    Екатеринбург
    @RJ Baker, типа такого Main_OnCommand(NamedCommandLookup("_S&M_CYCLACTION_136"), 0)
     
    RJ Baker нравится это.
  22. RJ Baker

    RJ Baker Well-Known Member

    Регистрация:
    15 июл 2006
    Сообщения:
    942
    Симпатии:
    411
    Пол:
    Мужской
    Род занятий:
    Музыка, аранжировка
    Адрес:
    Мариуполь
    Спасибо, вам ребята @EUGEN27771, @lil-burn, за подсказки: я хоть и освоил как то для себя WALTER, но тут совсем другой уровень, а я не программист совсем. НЕ понимаю - все ж должно работать уже, 1-я кнопка отзывается как надо, а вторая все равно выдает "attempt to call a nil value (global 'NamedCommandLookup'" - ну простите туповат я наверное, обещаю, как разберусь с этим скриптом, больше доставать вопросами не стану!
    Чессслово!))
    Код:
    --------------------------------------------------------------------------------
    ---   Simple Element Class   ---------------------------------------------------
    --------------------------------------------------------------------------------
    local Element = {}
    function Element:new(x,y,w,h, r,g,b,a, lbl,fnt,fnt_sz, norm_val)
        local elm = {}
        elm.def_xywh = {x,y,w,h,fnt_sz} -- its default coord,used for Zoom etc
        elm.x, elm.y, elm.w, elm.h = x, y, w, h
        elm.r, elm.g, elm.b, elm.a = r, g, b, a
        elm.lbl, elm.fnt, elm.fnt_sz  = lbl, fnt, fnt_sz
        elm.norm_val = norm_val
        ------
        setmetatable(elm, self)
        self.__index = self
        return elm
    end
    --------------------------------------------------------------
    --- Function for Child Classes(args = Child,Parent Class) ----
    --------------------------------------------------------------
    function extended(Child, Parent)
         setmetatable(Child,{__index = Parent})
    end
    --------------------------------------------------------------
    ---   Element Class Methods(Main Methods)   ------------------
    --------------------------------------------------------------
    function Element:update_xywh()
      if not Z_w or not Z_h then return end -- return if zoom not defined
      if Z_w>0.5 and Z_w<3 then
       self.x, self.w = math.ceil(self.def_xywh[1]* Z_w) , math.ceil(self.def_xywh[3]* Z_w) --upd x,w
      end
      if Z_h>0.5 and Z_h<3 then
       self.y, self.h = math.ceil(self.def_xywh[2]* Z_h) , math.ceil(self.def_xywh[4]* Z_h) --upd y,h
      end
      if Z_w>0.5 or Z_h>0.5  then --fix it!--
         self.fnt_sz = math.max(9,self.def_xywh[5]* (Z_w+Z_h)/2)
         self.fnt_sz = math.min(22,self.fnt_sz)
      end  
    end
    --------
    function Element:pointIN(p_x, p_y)
      return p_x >= self.x and p_x <= self.x + self.w and p_y >= self.y and p_y <= self.y + self.h
    end
    --------
    function Element:mouseIN()
      return gfx.mouse_cap&1==0 and self:pointIN(gfx.mouse_x,gfx.mouse_y)
    end
    --------
    function Element:mouseDown()
      return gfx.mouse_cap&1==1 and self:pointIN(mouse_ox,mouse_oy)
    end
    --------
    function Element:mouseClick()
      return gfx.mouse_cap&1==0 and last_mouse_cap&1==1 and
      self:pointIN(gfx.mouse_x,gfx.mouse_y) and self:pointIN(mouse_ox,mouse_oy)    
    end
    --------
    function Element:draw_frame()
      local x,y,w,h  = self.x,self.y,self.w,self.h
      gfx.rect(x, y, w, h, 0)--frame1
      gfx.roundrect(x, y, w-1, h-1, 3, true)--frame2    
    end
    --------------------------------------------------------------------------------
    ---   Create Element Child Classes(Button,Slider,Knob)   -----------------------
    --------------------------------------------------------------------------------
    local Button ={}; local Knob ={}; local Slider ={};
      extended(Button, Element)
      extended(Knob,   Element)
      extended(Slider, Element)
    ---Create Slider Child Classes(V_Slider,H_Slider)----
    local H_Slider ={}; local V_Slider ={};
      extended(H_Slider, Slider)
      extended(V_Slider, Slider)
    
    --------------------------------------------------------------------------------
    --------------------------------------------------------------------------------
    ---   Button Class Methods   ---------------------------------------------------
    --------------------------------------------------------------------------------
    function Button:draw_lbl()
        local x,y,w,h  = self.x,self.y,self.w,self.h
        local fnt,fnt_sz = self.fnt, self.fnt_sz
        --Draw btn lbl(text)--
          gfx.set(0.7, 1, 0, 1)--set label color
          gfx.setfont(1, fnt, fnt_sz);--set label fnt
            local lbl_w, lbl_h = gfx.measurestr(self.lbl)
            gfx.x = x+(w-lbl_w)/2; gfx.y = y+(h-lbl_h)/2
            gfx.drawstr(self.lbl)
    end
    ---------------------
    function Button:draw()
        self:update_xywh()--Update xywh(if wind changed)
        local x,y,w,h  = self.x,self.y,self.w,self.h
        local r,g,b,a  = self.r,self.g,self.b,self.a
        ---Get L_mouse state--
              --in element--
              if self:mouseIN() then a=a+0.1 end
              --in elm L_down--
              if self:mouseDown() then a=a+0.2 end
              --in elm L_up(released and was previously pressed)--
              if self:mouseClick() and self.onClick then self.onClick() end
        --Draw btn(body,frame)--
        gfx.set(r,g,b,a)--set btn color
        gfx.rect(x,y,w,h,true)--body
        self:draw_frame()
        ------------------------
        self:draw_lbl()
    end
    -------------------------------------------------
    ----Objects--------------------------------------
    -------------------------------------------------
    local btn1 = Button:new(20,  20,50,50,  0.7,0.3,0.3,0.5, "B1","Arial",20 )
    local btn2 = Button:new(80,  20,50,50,  0.7,0.3,0.3,0.5, "B2","Arial",20 )
    local btn3 = Button:new(140, 20,50,50,  0.7,0.3,0.3,0.5, "B3","Arial",20 )
    local btn4 = Button:new(200,  20,50,50,  0.7,0.3,0.3,0.5, "B4","Arial",20 )
    local btn5 = Button:new(260,  20,50,50,  0.7,0.3,0.3,0.5, "B5","Arial",20 )
    local btn6 = Button:new(320, 20,50,50,  0.7,0.3,0.3,0.5, "B6","Arial",20 )
    local btn7 = Button:new(20,  80,50,50,  0.3,0.7,0.3,0.5, "B7","Arial",20 )
    local btn8 = Button:new(80,  80,50,50,  0.3,0.7,0.3,0.5, "B8","Arial",20 )
    local btn9 = Button:new(140, 80,50,50,  0.3,0.7,0.3,0.5, "B9","Arial",20 )
    local btn10 = Button:new(200,  80,50,50,  0.7,0.3,0.3,0.5, "B10","Arial",20 )
    local btn11 = Button:new(260,  80,50,50,  0.7,0.3,0.3,0.5, "B11","Arial",20 )
    local btn12 = Button:new(320,  80,50,50,  0.7,0.3,0.3,0.5, "B12","Arial",20 )
    local btn13 = Button:new(20, 140,50,50,  0.7,0.3,0.3,0.5, "B13","Arial",20 )
    local btn14 = Button:new(80,  140,50,50,  0.7,0.3,0.3,0.5, "B14","Arial",20 )
    local btn15 = Button:new(140,  140,50,50,  0.7,0.3,0.3,0.5, "B15","Arial",20 )
    local btn16 = Button:new(200, 140,50,50,  0.7,0.3,0.3,0.5, "B16","Arial",20 )
    local btn17 = Button:new(260,  140,50,50,  0.3,0.7,0.3,0.5, "B17","Arial",20 )
    local btn18 = Button:new(320,  140,50,50,  0.3,0.7,0.3,0.5, "B18","Arial",20 )
    
    local Button_TB = {btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btn10,btn11,btn12,btn13,btn14,btn15,btn16,btn17,btn18}
    
    btn1.onClick = function() reaper.Main_OnCommand(40007, 0) end
    btn2.onClick = function() reaper.Main_OnCommand(NamedCommandLookup("_RS73b2fd94028f6345e90b72b4d8a636681c04f5f0"), 0) end
    
    ------------------------------------------------
    ------------------------------------------------
    function DRAW()
    for key,btn in pairs(Button_TB) do btn:draw() end
    end
    
    --------------------------------------------------------------------------------
    --Init--------------------------------------------------------------------------
    --------------------------------------------------------------------------------
    function Init()
    --Some gfx Wnd Default Values--------------
    local R,G,B = 10,10,25 --0..255 form
    Wnd_bgd = R  + G*256 + B*65536 --red +green*256+blue*65536
    Wnd_Title,Wnd_W,Wnd_H,Wnd_Dock,Wnd_X,Wnd_Y = "18 buttons", 390,210,0,100,320
    --Init window------------------------------
    gfx.clear = Wnd_bgd    
    gfx.init( Wnd_Title, Wnd_W,Wnd_H, Wnd_Dock, Wnd_X,Wnd_Y )
    --Mouse--
    last_mouse_cap = 0
    last_x, last_y = 0, 0
    end
    -------------------------
    --Mainloop---------------
    function mainloop()
    Z_w,Z_h = gfx.w/Wnd_W, gfx.h/Wnd_H
    if gfx.mouse_cap&1==1 and last_mouse_cap&1==0 then
        mouse_ox, mouse_oy = gfx.mouse_x, gfx.mouse_y
    end
    Ctrl  = gfx.mouse_cap&4==4
    Shift = gfx.mouse_cap&8==8
    ----------------------
    --DRAW,MAIN function--
       DRAW()--Main()
    ----------------------
    ----------------------
    last_mouse_cap = gfx.mouse_cap
    last_x, last_y = gfx.mouse_x, gfx.mouse_y
    char = gfx.getchar()
    if char~=-1 then reaper.defer(mainloop) end --defer
    -----------
    gfx.update()
    -----------
    end
    ---------------------------------------
    ---------------------------------------
    Init()
    mainloop()
    И еще может объясните - почему кнопки 7-9 и 17-18 не меняют цвет они же ничем вроде бы не отличаются...
    Мне понравилась сама идея - обойти ограничение Рипера в 16 тулбаров... ну и т.д. А так я ни на что не претендую, чисто для себя решение хочу допилить.
     
  23. Buyan

    Buyan Member

    Регистрация:
    19 апр 2016
    Сообщения:
    80
    Симпатии:
    13
    Пол:
    Мужской
    Род занятий:
    Хобби: Гитара, Флейта, Звукорежиссура.
    Адрес:
    Белая Церковь
    Не вникал глубоко в суть предоставленных скриптов и механизма решения данной задачи, так как не успел пока ознакомится с ReaScripts и API Риппера.
    Но осмелюсь дать весьма скромный совет по поводу упрощения для "юзера" процесса настройки собственных пресетов.
    Вместо громоздкости и сложностей в реализации интерфейса, можно пойти другим проверенным в сходных задачах путем - читать конфигурации пресетов из INI-файла. Который пользователю создать будет проще, нежели вписывать ID непосредственно в код скрипта.

    Например:
    Код:
    [Имя Пресета 1]
    Key_1=ID
    Key_2=ID
    Key_n=ID
    [Имя Пресета 2]
    ...
    
     
  24. lil-burn

    lil-burn Well-Known Member

    Регистрация:
    15 авг 2012
    Сообщения:
    903
    Симпатии:
    626
    Пол:
    Мужской
    Адрес:
    Екатеринбург
    @RJ Baker, перед NamedCommandLookup тоже надо писать reaper
    reaper.Main_OnCommand(reaper.NamedCommandLookup("_RS73b2fd94028f6345e90b72b4d8a636681c04f5f0"), 0)
     
    RJ Baker нравится это.
  25. RJ Baker

    RJ Baker Well-Known Member

    Регистрация:
    15 июл 2006
    Сообщения:
    942
    Симпатии:
    411
    Пол:
    Мужской
    Род занятий:
    Музыка, аранжировка
    Адрес:
    Мариуполь
    @lil-burn, Браво! Спасибищще огромное, как груз с плеч - все заработало как надо теперь!
     
  26. vitalker

    vitalker Well-Known Member

    Регистрация:
    8 окт 2013
    Сообщения:
    3.674
    Симпатии:
    1.396
    Адрес:
    Гродно
    Странно, что все забыли про такую штуку. Как думаете, если Джастину показать, то он запилит её в основной функционал?
     
  27. vitalker

    vitalker Well-Known Member

    Регистрация:
    8 окт 2013
    Сообщения:
    3.674
    Симпатии:
    1.396
    Адрес:
    Гродно
    Даже никто не глянул.
     
  28. Alex_028

    Alex_028 Well-Known Member

    Регистрация:
    10 май 2015
    Сообщения:
    776
    Симпатии:
    328
    Пол:
    Мужской
    Род занятий:
    Программирование, VST DSP, Reaper accessibility
    Адрес:
    Киев, Донецк UA
    @vitalker, я поддерживаю!
    Уже давно на кокосовом форуме поднимался вопрос про создание контекстнозависимых хоткеев или в зависимости от выбраной задачи, но за эту тему как-то тоже забыли.
     
  29. diggidon

    diggidon Super Moderator Команда форума

    Регистрация:
    26 май 2008
    Сообщения:
    6.577
    Симпатии:
    6.713
    Род занятий:
    Жму кнопки, кручу ручки...
    Адрес:
    Днепр UA
    А я вовсю юзаю, не дожидаясь Джастина.
    У меня уже штук 10 разных сетов, из которых 3 в активном ежедневном использовании
    З.Ы. Каждый раз вспоминаю @Aleksandr Oleynik "незлым тихим словом"))) © Т. Г. Шевченко.
     
  30. vitalker

    vitalker Well-Known Member

    Регистрация:
    8 окт 2013
    Сообщения:
    3.674
    Симпатии:
    1.396
    Адрес:
    Гродно
    Вот у него хотел спросить: может на оф.форум запилить темку об этом?
     
  31. Alex_028

    Alex_028 Well-Known Member

    Регистрация:
    10 май 2015
    Сообщения:
    776
    Симпатии:
    328
    Пол:
    Мужской
    Род занятий:
    Программирование, VST DSP, Reaper accessibility
    Адрес:
    Киев, Донецк UA
    @diggidon, я тоже делал по заветам Александра, но у меня портянки экшенов и на них горячек нехватает. Руки пока недошли собрать в пару скриптов.
    Все равно контекстнозависимые хоткеи очень бы облегчили жизнь.
     
  32. diggidon

    diggidon Super Moderator Команда форума

    Регистрация:
    26 май 2008
    Сообщения:
    6.577
    Симпатии:
    6.713
    Род занятий:
    Жму кнопки, кручу ручки...
    Адрес:
    Днепр UA
    @Alex_028, ничто не мешает сделать 16, 22, или хоть 30-до-неба экшнов, и назначить их на удобные вам горячки (в смысле совсем не обязательно делать именно 12, и назначать их на F1-F12).

    Там вообще всё просто, как три копейки, на разобраться уйдёт минуты полторы.
     
  33. Erundolog

    Erundolog Member

    Регистрация:
    4 ноя 2016
    Сообщения:
    171
    Симпатии:
    21
    Пол:
    Мужской
    Адрес:
    Армавир
    Не так уж и просто. Уже второй день читаю, начал устанавливать. Туплю. Гением себя не считаю но среднестатистическому боту как я сложно вникнуть. Мануал конечно оставляет желать лучшего. Импортируйте активируйте. Создаст. Потом опять создайте брр.


    Кажется разобрался.
    Подскажите почему 2 ваших скрипта повешенные на кнопки при нажатии (активации) подсвечиваются. А я еще новые создал мои при нажатии активируются но не подсвечиваются. Что я упустил ?


    Разобрался. Оказывается не подсвечивается если Ваш скрипт засовываешь в свой экшен в котором первое действие это загрузка скринсета а затем запуск Вашего скрипта.
     
    Последнее редактирование: 12 май 2018
  34. vitalker

    vitalker Well-Known Member

    Регистрация:
    8 окт 2013
    Сообщения:
    3.674
    Симпатии:
    1.396
    Адрес:
    Гродно
    @Aleksandr Oleynik , разрешите выложить это на оф.форуме?
     
  35. Aleksandr Oleynik

    Aleksandr Oleynik Well-Known Member

    Регистрация:
    16 янв 2007
    Сообщения:
    18.219
    Симпатии:
    10.305
    Пол:
    Мужской
    Адрес:
    Киев
    Без проблем.
     

Поделиться этой страницей