mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
814 lines
24 KiB
Lua
814 lines
24 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
local shortcuts = {
|
|
[KEY_TAB] = function()
|
|
if IsValid( MKeyboard.entity ) then
|
|
RunConsoleCommand( "musical_keyboard_leave", MKeyboard.entity:EntIndex() )
|
|
end
|
|
end,
|
|
|
|
[KEY_SPACE] = function()
|
|
MKeyboard:ToggleMenu()
|
|
end,
|
|
|
|
[KEY_LEFT] = function()
|
|
MKeyboard:SwitchInstrument( -1 )
|
|
end,
|
|
|
|
[KEY_RIGHT] = function()
|
|
MKeyboard:SwitchInstrument( 1 )
|
|
end,
|
|
|
|
[KEY_UP] = function()
|
|
MKeyboard:SetTranspose( MKeyboard.settings.transpose + 1 )
|
|
end,
|
|
|
|
[KEY_DOWN] = function()
|
|
MKeyboard:SetTranspose( MKeyboard.settings.transpose - 1 )
|
|
end
|
|
}
|
|
|
|
local dontBlockBinds = {
|
|
["+attack"] = true,
|
|
["+attack2"] = true,
|
|
["+duck"] = true
|
|
}
|
|
|
|
local transmitQueue = {}
|
|
local queueTimer, queueStart
|
|
|
|
MKeyboard.layoutName = ""
|
|
MKeyboard.isMenuOpen = false
|
|
MKeyboard.lastNoteWasAutomated = false
|
|
|
|
function MKeyboard:Init( ent )
|
|
self.entity = ent
|
|
self.blockInputTimer = RealTime() + 0.3
|
|
|
|
self:LoadSettings()
|
|
self:OpenInterface()
|
|
|
|
self:SetInstrument()
|
|
self:SetTranspose()
|
|
self:SetLayoutByIndex()
|
|
|
|
self.piano.OnNoteOn = function( note, velocity, instrument, automated )
|
|
instrument = instrument or self.settings.instrument
|
|
|
|
local data = self.instruments[instrument] or self.instruments[1]
|
|
if note < data.noteMin or note > data.noteMax then return end
|
|
|
|
self.entity:EmitNote( note, velocity, instrument, automated )
|
|
self.lastNoteWasAutomated = automated
|
|
|
|
-- Remember when we started putting notes
|
|
-- on the queue, and when we should send them
|
|
local t = SysTime()
|
|
|
|
if not queueTimer then
|
|
queueTimer = t + 0.4
|
|
queueStart = t
|
|
end
|
|
|
|
-- Add notes to the queue unless the limit was reached
|
|
local noteCount = #transmitQueue
|
|
if noteCount < self.NET_MAX_NOTES then
|
|
transmitQueue[noteCount + 1] = {
|
|
note, velocity, instrument, t - queueStart
|
|
}
|
|
end
|
|
end
|
|
|
|
hook.Add( "Think", "MKeyboard.ProcessLocalKeyboard", function()
|
|
if not IsValid( self.entity ) then
|
|
self:Shutdown()
|
|
|
|
return
|
|
end
|
|
|
|
local t = SysTime()
|
|
|
|
-- If the queued notes are ready to be sent...
|
|
if queueTimer and t > queueTimer then
|
|
net.Start( "mkeyboard.notes", false )
|
|
net.WriteEntity( self.entity )
|
|
net.WriteBool( self.lastNoteWasAutomated )
|
|
net.WriteUInt( #transmitQueue, 5 )
|
|
|
|
for _, params in ipairs( transmitQueue ) do
|
|
net.WriteUInt( params[1], 7 ) -- note
|
|
net.WriteUInt( params[2], 7 ) -- velocity
|
|
net.WriteUInt( params[3], 6 ) -- instrument
|
|
net.WriteFloat( params[4] ) -- time offset
|
|
end
|
|
|
|
net.SendToServer()
|
|
|
|
table.Empty( transmitQueue )
|
|
queueTimer = nil
|
|
end
|
|
end )
|
|
|
|
hook.Add( "PlayerButtonDown", "MKeyboard.DetectButtonPress", function( ply, button )
|
|
if ply == LocalPlayer() and IsFirstTimePredicted() then
|
|
self:OnButtonPress( button )
|
|
end
|
|
end )
|
|
|
|
hook.Add( "PlayerButtonUp", "MKeyboard.DetectButtonRelease", function( ply, button )
|
|
if ply == LocalPlayer() and IsFirstTimePredicted() then
|
|
self:OnButtonRelease( button )
|
|
end
|
|
end )
|
|
|
|
hook.Add( "PlayerBindPress", "MKeyboard.BlockBinds", function( _, bind )
|
|
if not dontBlockBinds[bind] then return true end
|
|
end )
|
|
|
|
-- Custom Chat compatibility
|
|
hook.Add( "CustomChatBlockInput", "MKeyboard.PreventOpeningChat", function()
|
|
return true
|
|
end )
|
|
|
|
if not self.isMIDIAvailable then return end
|
|
|
|
timer.Create( "MKeyboard.CheckMIDI", 1, 0, function()
|
|
self:CheckMIDI()
|
|
end )
|
|
end
|
|
|
|
function MKeyboard:Shutdown()
|
|
self.entity = nil
|
|
|
|
transmitQueue = {}
|
|
queueTimer = nil
|
|
|
|
self:CloseInterface()
|
|
|
|
timer.Remove( "MKeyboard.CheckMIDI" )
|
|
|
|
if self.isMIDIAvailable then
|
|
self:CloseMIDI()
|
|
end
|
|
|
|
hook.Remove( "Think", "MKeyboard.ProcessLocalKeyboard" )
|
|
hook.Remove( "PlayerButtonDown", "MKeyboard.DetectButtonPress" )
|
|
hook.Remove( "PlayerButtonUp", "MKeyboard.DetectButtonRelease" )
|
|
hook.Remove( "PlayerBindPress", "MKeyboard.BlockBinds" )
|
|
hook.Remove( "CustomChatBlockInput", "MKeyboard.PreventOpeningChat" )
|
|
end
|
|
|
|
local settings = MKeyboard.settings
|
|
local colors = MKeyboard.colors
|
|
|
|
function MKeyboard:OnButtonPress( button )
|
|
if RealTime() > self.blockInputTimer then
|
|
self.lastNoteWasAutomated = false
|
|
self.piano:PressButton( button, settings.velocity, settings.instrument, colors.manual )
|
|
end
|
|
end
|
|
|
|
function MKeyboard:OnButtonRelease( button )
|
|
if shortcuts[button] then
|
|
shortcuts[button]()
|
|
|
|
return
|
|
end
|
|
|
|
self.piano:ReleaseButton( button )
|
|
end
|
|
|
|
function MKeyboard:SetInstrument( index )
|
|
index = index or settings.instrument
|
|
|
|
local instrument = self.instruments[index]
|
|
|
|
if instrument then
|
|
self.piano:SetNoteRange( instrument.noteMin, instrument.noteMax )
|
|
settings.instrument = index
|
|
end
|
|
end
|
|
|
|
function MKeyboard:SetTranspose( transpose )
|
|
transpose = transpose or settings.transpose
|
|
|
|
self.piano:ReleaseAllNotes()
|
|
self.piano.transpose = transpose
|
|
settings.transpose = transpose
|
|
end
|
|
|
|
function MKeyboard:SetLayoutByIndex( index )
|
|
index = index or settings.layout
|
|
|
|
if self.layouts[index] then
|
|
settings.layout = index
|
|
|
|
local layout = self.layouts[index]
|
|
|
|
self.piano:SetLayout( layout.keys )
|
|
self.layoutName = language.GetPhrase( layout.label )
|
|
self:UpdateSheetsList()
|
|
end
|
|
end
|
|
|
|
function MKeyboard:SwitchInstrument( to )
|
|
local newInstrument = settings.instrument + to
|
|
|
|
if newInstrument < 1 then
|
|
newInstrument = #self.instruments
|
|
|
|
elseif newInstrument > #self.instruments then
|
|
newInstrument = 1
|
|
end
|
|
|
|
self:SetInstrument( newInstrument )
|
|
|
|
local line = self.instrumentList:GetLine( newInstrument )
|
|
|
|
self.instrumentList:ClearSelection()
|
|
self.instrumentList:SelectItem( line )
|
|
self.instrumentList.VBar:AnimateTo( line:GetY() - self.instrumentList:GetTall() * 0.5, 0.25, 0, -1 )
|
|
|
|
self:SaveSettings()
|
|
end
|
|
|
|
function MKeyboard:CloseInterface()
|
|
self.isMenuOpen = false
|
|
|
|
if IsValid( self.frame ) then
|
|
self.frame:Close()
|
|
end
|
|
|
|
if IsValid( self.frameDevices ) then
|
|
self.frameDevices:Close()
|
|
end
|
|
|
|
if IsValid( self.frameChannels ) then
|
|
self.frameChannels:Close()
|
|
end
|
|
end
|
|
|
|
function MKeyboard:ToggleMenu()
|
|
self.isMenuOpen = not self.isMenuOpen
|
|
|
|
-- I might have found a bug here. Basically, cant get the panel position
|
|
-- after calling LerpPositions without playing the animation first
|
|
-- local x = self.frame:GetX()
|
|
|
|
local x = ( ScrW() - ScrW() * 0.7 ) * 0.5
|
|
local tall = self.frame:GetTall()
|
|
|
|
if self.isMenuOpen then
|
|
self.frame:SetPos( x, ScrH() - tall )
|
|
self.frame:MakePopup()
|
|
else
|
|
self.frame:SetPos( x, ScrH() - tall * 0.49 )
|
|
self.frame:SetMouseInputEnabled( false )
|
|
self.frame:SetKeyboardInputEnabled( false )
|
|
end
|
|
end
|
|
|
|
local function CreatePanel( title, parent, dock, wide, help )
|
|
local panel = vgui.Create( "DPanel", parent )
|
|
panel:DockPadding( 8, 8, 8, 8 )
|
|
panel:DockMargin( 4, 0, 4, 0 )
|
|
panel:Dock( dock )
|
|
panel:SetBackgroundColor( colors.panel )
|
|
|
|
if wide then
|
|
panel:SetWide( wide )
|
|
end
|
|
|
|
local panelHeader = vgui.Create( "DPanel", panel )
|
|
panelHeader:Dock( TOP )
|
|
panelHeader:SetPaintBackground( false )
|
|
|
|
local labelTitle = vgui.Create( "DLabel", panelHeader )
|
|
labelTitle:SetFont( "MKeyboard_Key" )
|
|
labelTitle:SetText( language.GetPhrase( title ) )
|
|
labelTitle:SizeToContents()
|
|
labelTitle:Dock( LEFT )
|
|
labelTitle:SetTextColor( colors.white )
|
|
|
|
if help then
|
|
local labelHelp = vgui.Create( "DLabel", panelHeader )
|
|
labelHelp:SetFont( "MKeyboard_Key" )
|
|
labelHelp:SetText( language.GetPhrase( help ) )
|
|
labelHelp:SizeToContents()
|
|
labelHelp:Dock( RIGHT )
|
|
labelHelp:SetTextColor( colors.white )
|
|
end
|
|
|
|
return panel
|
|
end
|
|
|
|
local SetColor = surface.SetDrawColor
|
|
local DrawRect = surface.DrawRect
|
|
local DrawText = draw.SimpleText
|
|
|
|
local Ceil = math.ceil
|
|
|
|
local function DrawSheet( index, x, y )
|
|
local data = MKeyboard.sheets[index]
|
|
if not data then return end
|
|
|
|
local borderSize = Ceil( ScrW() * 0.002 )
|
|
local titleBarSize = ScrH() * 0.028
|
|
|
|
surface.SetFont( "MKeyboard_Sheet" )
|
|
|
|
local sheetW, sheetH = surface.GetTextSize( data.sequence )
|
|
local w, h = math.max( ScrW() * 0.3, sheetW + borderSize * 2 ), sheetH + titleBarSize * 0.5
|
|
local oldClipping = DisableClipping( true )
|
|
|
|
x = x - w * 0.5
|
|
y = y - h
|
|
|
|
SetColor( 0, 0, 0, 254 )
|
|
DrawRect( x, y, w, h )
|
|
|
|
draw.DrawText( data.sequence, "MKeyboard_Sheet", x + w * 0.5, y + titleBarSize, nil, TEXT_ALIGN_CENTER )
|
|
DrawText( data.title, "MKeyboard_Title", x + w * 0.5, y + borderSize, colors.white, TEXT_ALIGN_CENTER )
|
|
|
|
DisableClipping( oldClipping )
|
|
end
|
|
|
|
function MKeyboard:OpenInterface()
|
|
if not self.selectedMIDIPort then
|
|
self:ShowDevicesDialog()
|
|
end
|
|
|
|
local wide = ScrW() * 0.7
|
|
local tall = ScrH() * 0.5
|
|
|
|
self.frame = vgui.Create( "DFrame" )
|
|
self.frame:SetPos( ( ScrW() - wide ) * 0.5, ScrH() - tall * 0.5 )
|
|
self.frame:SetSize( wide, tall )
|
|
self.frame:SetTitle( "" )
|
|
self.frame:SetDeleteOnClose( true )
|
|
self.frame:SetDraggable( false )
|
|
self.frame:SetSizable( false )
|
|
self.frame:ShowCloseButton( false )
|
|
self.frame:LerpPositions( 1, true )
|
|
|
|
-- Passthrough button events while this panel is focused
|
|
self.frame.OnKeyCodePressed = function( _, key )
|
|
self:OnButtonPress( key )
|
|
end
|
|
|
|
self.frame.OnKeyCodeReleased = function( _, key )
|
|
self:OnButtonRelease( key )
|
|
end
|
|
|
|
local helpMessage = {
|
|
[false] = language.GetPhrase( "musicalk.help.open" ),
|
|
[true] = language.GetPhrase( "musicalk.help.close" )
|
|
}
|
|
|
|
self.frame.Paint = function( _, w, h )
|
|
draw.RoundedBoxEx( 8, 0, h * 0.4, w, h * 0.6, colors.frame, true, true, false, false )
|
|
|
|
if self.midiPortName then
|
|
DrawText( self.midiPortName, "MKeyboard_Title", w - ( w * 0.01 ), h * 0.43,
|
|
colors.white, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP )
|
|
|
|
DrawText( helpMessage[self.isMenuOpen], "MKeyboard_Title", w * 0.01, h * 0.43,
|
|
colors.white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP )
|
|
else
|
|
DrawText( helpMessage[self.isMenuOpen], "MKeyboard_Title", w * 0.5, h * 0.43,
|
|
colors.white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP )
|
|
end
|
|
|
|
if settings.sheet > 0 then
|
|
DrawSheet( settings.sheet, w * 0.5, 0 )
|
|
end
|
|
|
|
local pianoW = self.piano.w
|
|
local pianoH = h * 0.3
|
|
|
|
local x = ( w * 0.5 ) - ( pianoW * 0.5 )
|
|
local y = 6
|
|
|
|
draw.RoundedBox( 4, x - 6, y - 6, pianoW + 12, pianoH + 12, colors.panel )
|
|
|
|
-- Draw layout, instrument name & transpose
|
|
local transpose = settings.transpose
|
|
local offset = 0
|
|
|
|
DrawText( self.layoutName, "MKeyboard_Key", x, y, colors.white )
|
|
|
|
if transpose ~= 0 then
|
|
offset = DrawText(
|
|
transpose > 0 and "+" .. transpose or transpose,
|
|
"MKeyboard_Key",
|
|
x + pianoW, y, colors.manual,
|
|
TEXT_ALIGN_RIGHT
|
|
)
|
|
|
|
offset = offset + 6
|
|
end
|
|
|
|
local data = self.instruments[settings.instrument]
|
|
local _, th = DrawText( data.name, "MKeyboard_Key", x + pianoW - offset, y, colors.white, TEXT_ALIGN_RIGHT )
|
|
|
|
th = th + 4
|
|
|
|
self.piano:Draw( x, y + th, pianoH - th )
|
|
end
|
|
|
|
local mainPanel = vgui.Create( "DPanel", self.frame )
|
|
mainPanel:SetPos( wide * 0.01, tall * 0.52 )
|
|
mainPanel:SetSize( wide * 0.98, tall * 0.45 )
|
|
mainPanel:DockPadding( 0, 0, 0, 0 )
|
|
mainPanel:SetPaintBackground( false )
|
|
|
|
---------- Settings panel ----------
|
|
|
|
local panelSettings = CreatePanel( "musicalk.settings", mainPanel, LEFT, wide * 0.3 )
|
|
|
|
local settingsScroll = vgui.Create( "DScrollPanel", panelSettings )
|
|
settingsScroll:Dock( FILL )
|
|
settingsScroll:DockMargin( 0, 8, 0, 0 )
|
|
|
|
local function AddRow( text, propertyClass )
|
|
local parent = vgui.Create( "DPanel", settingsScroll )
|
|
parent:SetWide( wide * 0.3 )
|
|
parent:SetTall( 28 )
|
|
parent:DockPadding( 4, 4, 4, 4 )
|
|
parent:DockMargin( 0, 0, 0, 2 )
|
|
parent:Dock( TOP )
|
|
parent:SetBackgroundColor( colors.white )
|
|
|
|
local label = vgui.Create( "DLabel", parent )
|
|
label:SetText( language.GetPhrase( text ) )
|
|
label:SetTextColor( colors.black )
|
|
label:SetWide( parent:GetWide() )
|
|
label:Dock( FILL )
|
|
|
|
if not propertyClass then
|
|
label:SetTextColor( colors.white )
|
|
label:SetContentAlignment( 5 )
|
|
|
|
parent:SetBackgroundColor( colors.black )
|
|
parent:SetTall( 28 )
|
|
|
|
return
|
|
end
|
|
|
|
local property = vgui.Create( propertyClass, parent )
|
|
|
|
if propertyClass == "DNumSlider" then
|
|
property.TextArea:SetWide( 30 )
|
|
|
|
function property:PerformLayout()
|
|
self.Label:SetWide( 0 )
|
|
end
|
|
end
|
|
|
|
property:Dock( RIGHT )
|
|
property:SetWide( 150 )
|
|
|
|
return property
|
|
end
|
|
|
|
AddRow( "musicalk.vkeys" )
|
|
|
|
-- Layouts list
|
|
local rowLayouts = AddRow( "musicalk.layout", "DComboBox" )
|
|
|
|
for i, v in ipairs( self.layouts ) do
|
|
rowLayouts:AddChoice( language.GetPhrase( v.label ), nil, i == settings.layout )
|
|
end
|
|
|
|
rowLayouts.OnSelect = function( _, index )
|
|
settings.sheet = 0
|
|
self:SetLayoutByIndex( index )
|
|
self:SaveSettings()
|
|
end
|
|
|
|
-- Should draw labels?
|
|
local rowDrawLabels = AddRow( "musicalk.vkeys.labels", "DImageButton" )
|
|
rowDrawLabels:SetImage( settings.drawKeyLabels and "icon16/accept.png" or "icon16/cancel.png" )
|
|
rowDrawLabels:SetStretchToFit( false )
|
|
rowDrawLabels:SetPaintBackground( true )
|
|
|
|
rowDrawLabels.DoClick = function()
|
|
settings.drawKeyLabels = not settings.drawKeyLabels
|
|
self:SaveSettings()
|
|
|
|
rowDrawLabels:SetIcon( settings.drawKeyLabels and "icon16/accept.png" or "icon16/cancel.png" )
|
|
end
|
|
|
|
-- Velocity
|
|
local rowVelocity = AddRow( "musicalk.vkeys.velocity", "DNumSlider" )
|
|
rowVelocity:SetMin( 0 )
|
|
rowVelocity:SetMax( 127 )
|
|
rowVelocity:SetDecimals( 0 )
|
|
rowVelocity:SetValue( settings.velocity )
|
|
rowVelocity.Label:SetTextColor( colors.black )
|
|
|
|
rowVelocity.OnValueChanged = function( _, value )
|
|
settings.velocity = Ceil( value )
|
|
end
|
|
|
|
-- Transpose
|
|
local rowTranspose = AddRow( "musicalk.vkeys.transpose", "DNumSlider" )
|
|
rowTranspose:SetMin( -24 )
|
|
rowTranspose:SetMax( 42 )
|
|
rowTranspose:SetDecimals( 0 )
|
|
rowTranspose:SetValue( settings.transpose )
|
|
rowTranspose.Label:SetTextColor( colors.black )
|
|
rowTranspose.Label:SetWide( 30 )
|
|
rowTranspose.Slider:SetWide( 300 )
|
|
|
|
self.rowTranspose = rowTranspose
|
|
|
|
rowTranspose.OnValueChanged = function( _, value )
|
|
if value < 0 then
|
|
value = Ceil( value )
|
|
else
|
|
value = math.floor( value )
|
|
end
|
|
|
|
self:SetTranspose( value )
|
|
self:SaveSettings()
|
|
end
|
|
|
|
AddRow( "MIDI" )
|
|
|
|
-- MIDI devices
|
|
local rowDevices = AddRow( "musicalk.midi.device", "DButton" )
|
|
rowDevices:SetText( language.GetPhrase( "musicalk.midi.device.choose" ) )
|
|
|
|
if self.isMIDIAvailable then
|
|
if table.Count( midi.GetPorts() ) == 0 then
|
|
rowDevices:SetText( language.GetPhrase( "musicalk.midi.nodevices" ) )
|
|
rowDevices:SetEnabled( false )
|
|
end
|
|
|
|
rowDevices.DoClick = function()
|
|
self:ShowDevicesDialog()
|
|
end
|
|
|
|
local rowChannels = AddRow( "musicalk.midi.channels", "DButton" )
|
|
rowChannels:SetText( language.GetPhrase( "musicalk.midi.channels.setup" ) )
|
|
|
|
rowChannels.DoClick = function()
|
|
self:ShowChannelsDialog()
|
|
end
|
|
|
|
local rowMIDITranspose = AddRow( "musicalk.vkeys.transpose", "DNumSlider" )
|
|
rowMIDITranspose:SetMin( -48 )
|
|
rowMIDITranspose:SetMax( 48 )
|
|
rowMIDITranspose:SetDecimals( 0 )
|
|
rowMIDITranspose:SetValue( settings.midiTranspose )
|
|
rowMIDITranspose.Label:SetTextColor( colors.black )
|
|
rowMIDITranspose.Label:SetWide( 30 )
|
|
rowMIDITranspose.Slider:SetWide( 300 )
|
|
|
|
rowMIDITranspose.OnValueChanged = function( _, value )
|
|
if value < 0 then
|
|
settings.midiTranspose = Ceil( value )
|
|
else
|
|
settings.midiTranspose = math.floor( value )
|
|
end
|
|
|
|
self:SaveSettings()
|
|
self.piano:ReleaseAllNotes()
|
|
end
|
|
else
|
|
rowDevices:SetText( language.GetPhrase( "musicalk.midi.nomodule" ) )
|
|
rowDevices:SetEnabled( false )
|
|
|
|
local rowInstallHelp = AddRow( "musicalk.midi.guide", "DButton" )
|
|
rowInstallHelp:SetText( language.GetPhrase( "musicalk.midi.guide" ) )
|
|
|
|
rowInstallHelp.DoClick = function()
|
|
gui.OpenURL( self.URL_MIDI_GUIDE )
|
|
self:ToggleMenu()
|
|
end
|
|
end
|
|
|
|
---------- Instruments panel ----------
|
|
|
|
local panelInstruments = CreatePanel( "musicalk.instruments", mainPanel, FILL, nil, "musicalk.instruments.help" )
|
|
|
|
self.instrumentList = vgui.Create( "DListView", panelInstruments )
|
|
self.instrumentList:Dock( FILL )
|
|
self.instrumentList:DockMargin( 0, 8, 0, 0 )
|
|
self.instrumentList:AddColumn( language.GetPhrase( "musicalk.instruments" ) )
|
|
self.instrumentList:SetMultiSelect( false )
|
|
self.instrumentList:SetHideHeaders( true )
|
|
self.instrumentList:SetSortable( false )
|
|
|
|
for i, v in ipairs( self.instruments ) do
|
|
self.instrumentList:AddLine( i .. " - " .. v.name )
|
|
end
|
|
|
|
self.instrumentList:SelectItem( self.instrumentList:GetLine( settings.instrument ) )
|
|
|
|
self.instrumentList.OnRowSelected = function( _, index )
|
|
self:SetInstrument( index )
|
|
self:SaveSettings()
|
|
end
|
|
|
|
---------- Layouts Panel ----------
|
|
|
|
local panelSheets = CreatePanel( "musicalk.sheets", mainPanel, RIGHT, wide * 0.3 )
|
|
|
|
self.sheetList = vgui.Create( "DListView", panelSheets )
|
|
self.sheetList:Dock( FILL )
|
|
self.sheetList:DockMargin( 0, 8, 0, 0 )
|
|
self.sheetList:AddColumn( language.GetPhrase( "musicalk.sheets" ) )
|
|
self.sheetList:SetMultiSelect( false )
|
|
self.sheetList:SetHideHeaders( true )
|
|
self.sheetList:SetSortable( false )
|
|
|
|
self:UpdateSheetsList()
|
|
|
|
self.sheetList.OnRowSelected = function( _, _, line )
|
|
settings.sheet = line._sheetIndex
|
|
self:SaveSettings()
|
|
end
|
|
end
|
|
|
|
function MKeyboard:UpdateSheetsList()
|
|
local layoutId = self.layouts[settings.layout].id
|
|
|
|
self.sheetList:Clear()
|
|
|
|
local selectedItem = self.sheetList:AddLine( language.GetPhrase( "musicalk.sheets.hidden" ) )
|
|
selectedItem._sheetIndex = 0
|
|
|
|
for i, v in ipairs( self.sheets ) do
|
|
if v.layout == layoutId then
|
|
local line = self.sheetList:AddLine( v.title )
|
|
line._sheetIndex = i
|
|
|
|
if i == settings.sheet then
|
|
selectedItem = line
|
|
end
|
|
end
|
|
end
|
|
|
|
self.sheetList:SelectItem( selectedItem )
|
|
end
|
|
|
|
function MKeyboard:ShowDevicesDialog()
|
|
if IsValid( self.frameDevices ) then
|
|
self.frameDevices:Close()
|
|
end
|
|
|
|
if not self.isMIDIAvailable then return end
|
|
|
|
local midiPorts = midi.GetPorts()
|
|
if table.Count( midiPorts ) == 0 then return end
|
|
|
|
if midi.IsOpened() then
|
|
self:CloseMIDI()
|
|
end
|
|
|
|
self.selectedMIDIPort = nil
|
|
|
|
self.frameDevices = vgui.Create( "DFrame" )
|
|
self.frameDevices:SetSize( 300, 130 )
|
|
self.frameDevices:SetTitle( language.GetPhrase( "musicalk.midi.device.choose" ) )
|
|
self.frameDevices:SetVisible( true )
|
|
self.frameDevices:SetDraggable( true )
|
|
self.frameDevices:ShowCloseButton( true )
|
|
self.frameDevices:SetDeleteOnClose( true )
|
|
self.frameDevices:Center()
|
|
self.frameDevices:MakePopup()
|
|
|
|
local startTime = SysTime()
|
|
local oldPaint = self.frameDevices.Paint
|
|
|
|
self.frameDevices.Paint = function( s, w, h )
|
|
Derma_DrawBackgroundBlur( s, startTime )
|
|
oldPaint( s, w, h )
|
|
end
|
|
|
|
local labelHelp = vgui.Create( "DLabel", self.frameDevices )
|
|
labelHelp:SetPos( 10, 40 )
|
|
labelHelp:SetSize( 280, 40 )
|
|
|
|
labelHelp:SetText( string.format(
|
|
language.GetPhrase( "musicalk.midi.found" ),
|
|
tostring( table.Count( midiPorts ) )
|
|
) )
|
|
|
|
local comboDevices = vgui.Create( "DComboBox", self.frameDevices )
|
|
comboDevices:SetPos( 10, 90 )
|
|
comboDevices:SetSize( 280, 20 )
|
|
comboDevices:SetValue( language.GetPhrase( "musicalk.midi.select" ) )
|
|
|
|
for k, v in pairs( midiPorts ) do
|
|
comboDevices:AddChoice( "[" .. k .. "] " .. v )
|
|
end
|
|
|
|
comboDevices.OnSelect = function( _, index )
|
|
self.selectedMIDIPort = index - 1
|
|
self.frameDevices:Close()
|
|
end
|
|
end
|
|
|
|
function MKeyboard:ShowChannelsDialog()
|
|
if IsValid( self.frameChannels ) then
|
|
self.frameChannels:Close()
|
|
|
|
return
|
|
end
|
|
|
|
local tall = math.min( 610, ScrH() * 0.6 )
|
|
|
|
self.frameChannels = vgui.Create( "DFrame" )
|
|
self.frameChannels:SetSize( 400, tall )
|
|
self.frameChannels:SetTitle( language.GetPhrase( "musicalk.channels" ) )
|
|
self.frameChannels:SetVisible( true )
|
|
self.frameChannels:SetSizable( true )
|
|
self.frameChannels:SetDraggable( true )
|
|
self.frameChannels:ShowCloseButton( true )
|
|
self.frameChannels:SetDeleteOnClose( true )
|
|
self.frameChannels:SetPos( ScrW() - self.frameChannels:GetWide(), 0 )
|
|
self.frameChannels:MakePopup()
|
|
|
|
-- Passthrough button events while this panel is focused
|
|
self.frameChannels.OnKeyCodePressed = function( _, key )
|
|
self:OnButtonPress( key )
|
|
end
|
|
|
|
self.frameChannels.OnKeyCodeReleased = function( _, key )
|
|
self:OnButtonRelease( key )
|
|
end
|
|
|
|
local scrollChannels = vgui.Create( "DScrollPanel", self.frameChannels )
|
|
scrollChannels:Dock( FILL )
|
|
|
|
local function PaintChannel( s, w, h )
|
|
SetColor( 0, 0, 0, 255 )
|
|
DrawRect( 0, 0, w, h )
|
|
|
|
SetColor( 50, 50, 50, 255 )
|
|
DrawRect( 4, 4, 8, h - 8 )
|
|
|
|
self.channelState[s.channel] = Lerp( FrameTime() * 8, self.channelState[s.channel], 0 )
|
|
|
|
SetColor( colors.automated.r, colors.automated.g, colors.automated.b, 255 * self.channelState[s.channel] )
|
|
DrawRect( 4, 4, 8, h - 8 )
|
|
end
|
|
|
|
local function OnSelectInstrument( s, _, _, idx )
|
|
if idx == -1 then
|
|
settings.channelInstruments[s.channel] = nil
|
|
else
|
|
settings.channelInstruments[s.channel] = idx
|
|
end
|
|
|
|
self:SaveSettings()
|
|
end
|
|
|
|
for i = 0, 15 do
|
|
self.channelState[i] = 0
|
|
|
|
local panelChannel = vgui.Create( "DPanel", scrollChannels )
|
|
panelChannel:SetSize( wide, 32 )
|
|
panelChannel:Dock( TOP )
|
|
panelChannel:DockMargin( 0, 0, 0, 4 )
|
|
|
|
panelChannel.channel = i
|
|
panelChannel.Paint = PaintChannel
|
|
|
|
local labelIndex = vgui.Create( "DLabel", panelChannel )
|
|
labelIndex:SetFont( "Trebuchet24" )
|
|
labelIndex:SetTextColor( colors.white )
|
|
labelIndex:SetText( "#" .. ( i + 1 ) )
|
|
labelIndex:SetWide( 50 )
|
|
labelIndex:Dock( LEFT )
|
|
labelIndex:DockMargin( 20, 0, 0, 0 )
|
|
|
|
local combo = vgui.Create( "DComboBox", panelChannel )
|
|
combo:SetSortItems( false )
|
|
combo:AddChoice( language.GetPhrase( "musicalk.channels.usecurrent" ), -1, true )
|
|
combo:AddChoice( language.GetPhrase( "musicalk.channels.mute" ), 0 )
|
|
combo:AddSpacer()
|
|
combo:Dock( FILL )
|
|
|
|
local myInstrument = settings.channelInstruments[i] or -1
|
|
|
|
for idx, v in ipairs( self.instruments ) do
|
|
combo:AddChoice( v.name, idx, idx == myInstrument )
|
|
end
|
|
|
|
combo.channel = i
|
|
combo.OnSelect = OnSelectInstrument
|
|
end
|
|
end
|