dobrograd-13-06-2022/garrysmod/addons/feature-gmpanel/lua/gmpanel/actions/cl_actions.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

382 lines
9.7 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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