dobrograd-13-06-2022/garrysmod/addons/feature-gmpanel/lua/gmpanel/actions/cl_actions.lua

383 lines
9.7 KiB
Lua
Raw Normal View History

2023-11-16 15:01:19 +05:00
gmpanel.actions = gmpanel.actions or {}
gmpanel.actions.available = gmpanel.actions.available or {}
gmpanel.actions.added = gmpanel.actions.added or {}
pcall(function()
local f = file.Read('gmpanel_actions.dat')
if f then gmpanel.actions.added = pon.decode(f) or {} end
end)
local pan, pAvailable, settings, active, right
local colors = CFG.skinColors
local function addedLinePaint(self, w, h)
local off, off2 = 0, 0
if IsValid(settings) and settings.editUid == self.uid then
draw.RoundedBox(4, 0, 0, w, h, colors.g)
off, off2 = 1, 2
end
if self.sel then
draw.RoundedBox(4, off, off, w - off2, h - off2, Color(170,119,102))
elseif self.id % 2 == 1 then
draw.RoundedBox(4, off, off, w - off2, h - off2, Color(0,0,0, 35))
end
end
local function addedLineSelect(self)
for _,v in ipairs(active:GetChildren()) do
v.sel = nil
end
self.sel = true
end
local function onModified(self)
local byUid = {}
for _,v in ipairs(gmpanel.actions.added) do
byUid[v.uid] = v
end
gmpanel.actions.added = {}
for _,v in ipairs(self:GetChildren()) do
gmpanel.actions.added[#gmpanel.actions.added + 1] = byUid[v.uid]
v.sel = v.uid == settings.editUid or nil
end
gmpanel.actions.save()
end
local function addedLineClick(self, mcode)
if isfunction(self.oldMP) then self:oldMP(mcode) end
if mcode ~= MOUSE_RIGHT then return end
self:Select()
local saved = gmpanel.actions.added[self.id]
if not saved then return end
local menu = DermaMenu()
menu:AddOption('Экспортировать', function()
local data = table.Copy(saved)
data.uid = nil
SetClipboardText(pon.encode(data))
octolib.notify.show('Код действия скопирован в буфер обмена')
end):SetIcon(octolib.icons.silk16('page_go'))
menu:AddOption('Редактировать', function()
if not IsValid(settings) then return end
local action = gmpanel.actions.available[saved.id]
if not action then return end
pAvailable.dirty = true
pAvailable:ClearSelection()
for _,v in ipairs(pAvailable:GetLines()) do
if v.id == saved.id then
pAvailable:SelectItem(v)
break
end
end
pAvailable.dirty = nil
settings:Clear()
action.openSettings(settings, saved)
settings.editUid = self.uid
gmpanel.actions.insertButtons(saved.id, saved)
end):SetIcon('octoteam/icons-16/pencil.png')
menu:AddOption('Удалить', function()
gmpanel.actions.editAction(self.uid)
end):SetIcon('octoteam/icons-16/cross.png')
menu:Open()
end
local function rebuildAdded()
if not IsValid(pan) then return end
if IsValid(right) then right:Remove() end
right = pan:Add('DPanel')
right:Dock(RIGHT)
right:SetWide(150)
right:SetPaintBackground(false)
active = octolib.label(right, 'Заготовленные действия')
active:DockMargin(0, 0, 0, 5)
active:SetContentAlignment(5)
active = right:Add('DScrollPanel')
active:Dock(FILL)
active:DockMargin(5, 0, 0, 0)
active = active:Add('DListLayout')
active:Dock(FILL)
active:MakeDroppable('gmpanel.actions.added')
function active:AddPanel(i, data)
local cont = self:Add('DPanel')
cont:SetTall(20)
cont.Paint = addedLinePaint
cont:SetMouseInputEnabled(true)
cont.id = i
cont.uid = data.uid
cont.oldMP, cont.OnMouseReleased, cont.Select = cont.OnMouseReleased, addedLineClick, addedLineSelect
local icon = cont:Add('DImage')
icon:Dock(LEFT)
icon:SetWide(16)
icon:DockMargin(0, 2, 5, 2)
icon:SetImage(data._icon)
local name = cont:Add('DLabel')
name:Dock(FILL)
name:SetText(data._name)
return cont
end
for i,v in ipairs(gmpanel.actions.added) do
active:AddPanel(i, v)
end
active.OnModified = onModified
local btnImport = right:Add('DButton')
btnImport:Dock(BOTTOM)
btnImport:SetTall(20)
btnImport:DockMargin(0, 5, 0, 0)
btnImport:SetText('Импорт действия')
btnImport:SetIcon(octolib.icons.silk16('page_code'))
function btnImport:DoClick()
Derma_StringRequest('Импорт действия', 'Вставь код действия, полученный при экспорте', '', function(inp)
local succ, data = pcall(pon.decode, inp)
if not succ or not istable(data) then
return octolib.notify.show('warning', 'Кажется, код действия поврежден')
end
gmpanel.actions.addAction(data.id, data)
end)
end
end
gmpanel.actions.save = octolib.func.debounce(function()
file.Write('gmpanel_actions.dat', pon.encode(gmpanel.actions.added))
end, 1)
function gmpanel.actions.registerAction(id, action)
gmpanel.actions.available[id] = action
end
function gmpanel.actions.addAction(id, actionData)
if not id or not gmpanel.actions.available[id] then return end
actionData.id = id
actionData.uid = octolib.string.uuid():sub(1, 8)
gmpanel.actions.added[#gmpanel.actions.added + 1] = actionData
gmpanel.actions.save()
rebuildAdded()
gmpanel.scenarios.updateActions()
return true
end
function gmpanel.actions.editAction(uid, actionData)
if not uid then return end
local idx
for i,v in ipairs(gmpanel.actions.added) do
if v.uid == uid then
idx = i
break
end
end
if not idx then return end
if not actionData then
table.remove(gmpanel.actions.added, idx)
rebuildAdded()
else
gmpanel.actions.added[idx] = actionData
if IsValid(active) then
local cont = active:GetChildren()[idx]
cont:GetChildren()[1]:SetImage(actionData._icon)
cont:GetChildren()[2]:SetText(actionData._name)
end
end
gmpanel.scenarios.updateActions()
gmpanel.actions.save()
end
function gmpanel.actions.close()
if IsValid(pan) then
pan:Remove()
end
end
function gmpanel.actions.defaultExecute(dataPassed, players)
dataPassed = table.Copy(dataPassed)
local id = dataPassed.id
dataPassed.id, dataPassed._name, dataPassed._icon = nil
dataPassed.players = players
netstream.Start('dbg-event.execute', id, dataPassed)
end
function gmpanel.actions.insertButtons(id, data)
if not (id and gmpanel.actions.available[id]) then return end
local action = gmpanel.actions.available[id]
data = data or {}
octolib.button(settings, 'Тест', function()
local func = action.execute or gmpanel.actions.defaultExecute
local data
if isfunction(action.getData) then
data = action.getData(settings)
else data = {} end
if data == nil then
octolib.notify.show('warning', 'Кажется, не все поля заполнены верно')
return
end
data = istable(data) and data or {value = data}
data.id = id
data.test = true
func(data, {LocalPlayer():SteamID()})
end)
local btmPan = settings:Add('DPanel')
btmPan:Dock(BOTTOM)
btmPan:SetTall(48)
btmPan:SetPaintBackground(false)
local nameCont = btmPan:Add('DPanel')
nameCont:Dock(LEFT)
nameCont:SetWide(150)
nameCont:SetPaintBackground(false)
octolib.label(nameCont, 'Кнопка:')
local wrapper = nameCont:Add('DPanel')
wrapper:Dock(FILL)
wrapper:DockMargin(0, 0, 0, 5)
local icon = wrapper:Add('DImageButton')
icon:Dock(LEFT)
icon:DockMargin(2, 4, 2, 4)
icon:SetSize(16, 16)
icon:SetIcon(data._icon or 'icon16/control_play.png')
function icon:DoClick()
octolib.icons.picker(function(val)
self:SetImage(val)
end, 'materials/' .. self:GetImage(), 'materials/icon16/')
end
local name = wrapper:Add('DTextEntry')
name:Dock(FILL)
name:SetPaintBackground(false)
name:SetTextColor(color_white)
name:SetValue(data._name or '')
local b = btmPan:Add('DPanel')
b:Dock(RIGHT)
b:DockMargin(0, 0, 0, 5)
b:SetPaintBackground(false)
b:SetWide(100)
b = b:Add('DButton')
b:Dock(BOTTOM)
b:SetTall(30)
b:SetText(settings.editUid and 'Сохранить' or 'Добавить')
b:SetIcon('icon16/folder.png')
function b:DoClick()
if string.Trim(name:GetValue()) == '' then
octolib.notify.show('Пожалуйста, добавь название действия. Тебе так будет проще')
return
end
local data
if isfunction(action.getData) then
data = action.getData(settings)
else data = {} end
if data == nil then
octolib.notify.show('warning', 'Кажется, не все поля заполнены верно')
return
end
data = istable(data) and data or {value = data}
data._name, data._icon = name:GetValue(), icon:GetImage()
if settings.editUid then
data.id = id
data.uid = settings.editUid
gmpanel.actions.editAction(settings.editUid, data)
else gmpanel.actions.addAction(id, data) end
end
end
hook.Add('gmpanel.populateActionsMenu', 'gmpanel.actions', function(menu, players)
for _,v in ipairs(gmpanel.actions.added) do
local action = gmpanel.actions.available[v.id]
if action then
menu:AddOption(v._name, function()
local func = action.execute or gmpanel.actions.defaultExecute
func(v, players)
end):SetIcon(v._icon)
end
end
menu:AddSpacer()
end)
local function build()
gmpanel.actions.close()
pan = vgui.Create('DFrame')
pan:SetSize(700, 500)
pan:SetTitle('Действия')
pan:Center()
pan:MakePopup()
pan:SetDeleteOnClose(true)
pAvailable = pan:Add('DListView')
pAvailable:Dock(LEFT)
pAvailable:SetWide(175)
pAvailable:SetHideHeaders(true)
pAvailable:DockMargin(0, 0, 5, 0)
pAvailable:AddColumn(''):SetFixedWidth(32)
pAvailable:AddColumn(L.title)
pAvailable:SetDataHeight(32)
pAvailable:SetMultiSelect(false)
for k,v in pairs(gmpanel.actions.available) do
local icon = vgui.Create('DImage')
icon:SetImage(v.icon)
pAvailable:AddLine(icon, v.name).id = k
end
settings = pan:Add('DPanel')
settings:Dock(FILL)
settings:DockPadding(5, 5, 5, 5)
function pAvailable:OnRowSelected(_, row)
if self.dirty then return end
for _,v in ipairs(active:GetChildren()) do
v.sel = nil
end
settings:Clear()
gmpanel.actions.available[row.id].openSettings(settings, {})
settings.editUid = nil
gmpanel.actions.insertButtons(row.id, {})
end
rebuildAdded()
end
function gmpanel.actions.open()
build()
end