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

309 lines
7.8 KiB
Lua

gmpanel.scenarios = gmpanel.scenarios or {}
gmpanel.scenarios.list = gmpanel.scenarios.list or {}
gmpanel.scenarios.active = gmpanel.scenarios.active or {}
pcall(function()
local f = file.Read('gmpanel_scenarios.dat')
if f then gmpanel.scenarios.list = pon.decode(f) or {} end
end)
gmpanel.scenarios.save = octolib.func.debounce(function()
file.Write('gmpanel_scenarios.dat', pon.encode(gmpanel.scenarios.list))
end, 1)
local pan, left, editor, scenarios, actionsPan, actions
local function defaultLinePaint(self, w, h, off)
off = off or 0
if self.id % 2 == 1 then
draw.RoundedBox(4, off, off, w - off, h - off, Color(0,0,0, 35))
end
end
local colors = CFG.skinColors
local function scenarioPaint(self, w, h)
local off, off2 = 0, 0
if IsValid(editor) and editor.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))
else defaultLinePaint(self, w, h, off2) end
end
local function addedLineSelect(self)
for _,v in ipairs(scenarios:GetChildren()) do
v.sel = nil
end
self.sel = true
end
local function onModified(self)
local byUid = {}
for _,v in ipairs(gmpanel.scenarios.list) do
byUid[v.uid] = v
end
gmpanel.scenarios.list = {}
for _,v in ipairs(self:GetChildren()) do
gmpanel.scenarios.list[#gmpanel.scenarios.list + 1] = byUid[v.uid]
v.sel = v.uid == editor.editUid or nil
end
gmpanel.scenarios.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.scenarios.list[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 IsValid(editor) then
editor:OpenEditor(saved)
end
end):SetIcon(octolib.icons.silk16('pencil'))
menu:AddOption('Удалить', function()
gmpanel.scenarios.edit(self.uid)
end):SetIcon(octolib.icons.silk16('cross'))
menu:Open()
end
local function rebuildScenarios()
if not IsValid(left) then return end
if IsValid(scenarios) then scenarios:Remove() end
scenarios = left:Add('DScrollPanel')
scenarios:Dock(FILL)
scenarios = scenarios:Add('DListLayout')
scenarios:Dock(FILL)
scenarios:MakeDroppable('gmpanel.scenarios')
function scenarios:AddPanel(i, data)
local cont = self:Add('DPanel')
cont:SetTall(20)
cont.Paint = scenarioPaint
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.scenarios.list) do
scenarios:AddPanel(i, v)
end
scenarios.OnModified = onModified
end
function gmpanel.scenarios.execute(scenData, players)
local uid = table.Count(gmpanel.scenarios.active) + 1
local actions, size = {}, #scenData.actions
for num, action in ipairs(scenData.actions) do
local predefined = gmpanel.actions.available[action.id]
if predefined then
actions[#actions + 1] = function(nxt)
netstream.Request('dbg-event.mapPlayerNames', players):Then(function(names)
gmpanel.scenarios.active[uid] = { num .. ' / ' .. size, predefined.name, table.concat(names, ', ') }
timer.Create('gmpanel.scenario.' .. uid, action._delay or 0, 1, function()
local func = predefined.execute or gmpanel.actions.defaultExecute
func(action, players)
nxt()
end)
end)
end
end
end
actions[#actions + 1] = function(nxt)
gmpanel.scenarios.active[uid] = nil
end
octolib.func.chain(actions)
end
function gmpanel.scenarios.add(scenData)
scenData.uid = octolib.string.uuid():sub(1, 8)
gmpanel.scenarios.list[#gmpanel.scenarios.list + 1] = scenData
gmpanel.scenarios.save()
rebuildScenarios()
return true
end
function gmpanel.scenarios.edit(uid, scenData)
if not uid then return end
local idx
for i,v in ipairs(gmpanel.scenarios.list) do
if v.uid == uid then
idx = i
break
end
end
if not idx then return end
if not scenData then
table.remove(gmpanel.scenarios.list, idx)
if IsValid(editor) and editor.editUid == uid then editor.editUid = nil end
rebuildScenarios()
else
gmpanel.scenarios.list[idx] = scenData
if IsValid(scenarios) then
local cont = scenarios:GetChildren()[idx]
cont:GetChildren()[1]:SetImage(scenData._icon)
cont:GetChildren()[2]:SetText(scenData._name)
end
end
gmpanel.scenarios.save()
end
hook.Add('gmpanel.populateActionsMenu', 'gmpanel.scenarios', function(menu, players)
for _,v in ipairs(gmpanel.scenarios.list) do
menu:AddOption(v._name, function()
gmpanel.scenarios.execute(v, players)
end):SetIcon(v._icon)
end
menu:AddSpacer()
end)
function gmpanel.scenarios.close()
if IsValid(pan) then
pan:Close()
end
end
function gmpanel.scenarios.updateActions()
if IsValid(actions) then actions:Remove() end
if not IsValid(actionsPan) then return end
actions = actionsPan:Add('DListLayout')
actions:Dock(FILL)
actions:MakeDroppable('gmpanel.actions.added')
-- timer.Simple(0, function()
for i,data in ipairs(gmpanel.actions.added) do
local cont = actions:Add('DPanel')
cont:Dock(TOP)
cont:SetTall(20)
cont.Paint = defaultLinePaint
cont:SetMouseInputEnabled(true)
cont.data = data
cont.id = i
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)
end
-- end)
end
local function build()
gmpanel.groups.close()
pan = vgui.Create('DFrame')
pan:SetSize(700, 500)
pan:SetTitle('Сценарии')
pan:Center()
pan:MakePopup()
pan:SetDeleteOnClose(true)
pan:SetSizable(true)
pan:SetMinWidth(700)
pan:SetMinHeight(500)
left = pan:Add('DPanel')
left:Dock(LEFT)
left:SetWide(150)
rebuildScenarios()
local btnImport = left: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.scenarios.add(data)
end)
end
local btnCreate = left:Add('DButton')
btnCreate:Dock(BOTTOM)
btnCreate:SetTall(20)
btnCreate:DockMargin(0, 5, 0, 0)
btnCreate:SetText('Создать сценарий')
btnCreate:SetIcon('octoteam/icons-16/page_white_put.png')
function btnCreate:DoClick()
editor:OpenEditor({})
for _,v in ipairs(scenarios:GetChildren()) do
v.sel = nil
end
end
editor = pan:Add('gmp_scenario_editor')
editor:Dock(FILL)
actionsPan = pan:Add('DPanel')
actionsPan:Dock(RIGHT)
actionsPan:SetWide(150)
actionsPan:SetPaintBackground(false)
actionsPan = actionsPan:Add('DScrollPanel')
actionsPan:Dock(FILL)
actionsPan:DockMargin(5, 0, 0, 0)
local lbl = octolib.label(actionsPan, 'Заготовленные действия')
lbl:DockMargin(0, 0, 0, 5)
lbl:SetContentAlignment(5)
gmpanel.scenarios.updateActions()
end
function gmpanel.scenarios.open()
build()
end