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

248 lines
6 KiB
Lua

local config = octomap.config
local PANEL = {}
function PANEL:Init()
self:Dock(FILL)
for k, v in pairs(config) do self[k] = v end
end
function PANEL:SetOptions(opts)
for k, v in pairs(opts or {}) do self[k] = v end
end
function PANEL:Paint(w, h)
self:UpdateAnimation()
local scale = self.scale
local centerOffX, centerOffY = math.Round(self.cx + self.offX * scale), math.Round(self.cy + self.offY * scale)
local mw, mh = config.mapW * scale, config.mapH * scale
local mx, my = centerOffX - math.Round(mw / 2), centerOffY - math.Round(mh / 2)
draw.NoTexture()
surface.SetDrawColor(config.bgCol)
surface.DrawRect(0, 0, w, h)
surface.SetMaterial(octomap.material)
surface.SetDrawColor(255,255,255, 255)
surface.DrawTexturedRect(mx, my, mw, mh)
for id, marker in pairs(octomap.markers) do
local x, y = centerOffX + math.Round(marker.x * scale), centerOffY + math.Round(marker.y * scale)
marker:Paint(x, y, self)
end
end
function PANEL:Think()
if self.panning then
if not self.allowPan then self.panning = nil end
local newX, newY = gui.MousePos()
local dx, dy = newX - self.lastMX, newY - self.lastMY
if dx ~= 0 then
self.offX = self.offX + math.Round(dx / self.scale)
self.tgtOffX = self.offX
self.lastMX = newX
self:AlignToBounds()
end
if dy ~= 0 then
self.offY = self.offY + math.Round(dy / self.scale)
self.tgtOffY = self.offY
self.lastMY = newY
self:AlignToBounds()
end
end
local ct = CurTime()
for id, marker in pairs(octomap.markers) do
if marker.Think and ct > marker.thinkAfter then
marker.thinkAfter = marker:Think() or ct
end
end
end
function PANEL:UpdateAnimation()
if self.tgtScale ~= self.scale then
self.scale = octolib.math.lerp(self.scale, self.tgtScale, FrameTime() * self.tgtSpeed, 0.001)
end
if self.tgtOffX ~= self.offX or self.tgtOffY ~= self.offY then
local pos = octolib.math.lerpVector(Vector(self.offX, self.offY, 0), Vector(self.tgtOffX, self.tgtOffY, 0), FrameTime() * self.tgtSpeed, 1)
self.offX, self.offY = pos.x, pos.y
end
end
function PANEL:AlignToBounds()
local scale = self.tgtScale
local bx = config.mapW * scale - (self.cx * 2 - self.paddingL - self.paddingR)
local by = config.mapH * scale - (self.cy * 2 - self.paddingT - self.paddingB)
if bx <= 0 then
self.tgtOffX = (self.paddingL - self.paddingR) / 2 / scale
else
local half = bx / 2
local hpl, hpr = self.paddingL / 2, self.paddingR / 2
local bl, br = (half + hpl - hpr) / scale, -(half + hpr - hpl) / scale
if self.tgtOffX < br then self.tgtOffX = br end
if self.tgtOffX > bl then self.tgtOffX = bl end
end
if by <= 0 then
self.tgtOffY = (self.paddingT - self.paddingB) / 2 / scale
else
local half = by / 2
local hpt, hpb = self.paddingT / 2, self.paddingB / 2
local bt, bb = (half + hpt - hpb) / scale, -(half + hpb - hpt) / scale
if self.tgtOffY < bb then self.tgtOffY = bb end
if self.tgtOffY > bt then self.tgtOffY = bt end
end
end
function PANEL:OnMousePressed(key)
local cx, cy = self:LocalCursorPos()
local mx, my = self:FromPanelToMap(cx, cy)
self.pressX, self.pressY = cx, cy
if key == MOUSE_LEFT then
if self.allowPan then
self.panning = true
self.lastMX, self.lastMY = gui.MousePos()
hook.Add('PlayerButtonUp', 'mapPan', function(ply, but)
if but == MOUSE_LEFT then
if IsValid(self) then self.panning = false end
hook.Remove('PlayerButtonUp', 'mapPan')
end
end)
end
end
-- if key == MOUSE_RIGHT then
-- local m = octomap.getMarker('customTarget')
-- if m then
-- local x, y = m:GetMapPos()
-- if math.abs(x - mx) + math.abs(y - my) < 100 * self.scale then
-- m:Remove()
-- return
-- end
-- end
-- local m = octomap.createMarker('customTarget')
-- :SetMapPos(mx, my)
-- :SetIcon('octoteam/icons-16/location_pin.png')
-- :SetIconOffset(0, -7)
-- :SetClickable(true)
-- function m:LeftClick()
-- self
-- :SetIcon('octoteam/icons-16/tick.png')
-- :SetIconOffset()
-- end
-- end
end
function PANEL:OnMouseReleased(key)
local cx, cy = self:LocalCursorPos()
if math.abs(cx - self.pressX) < 5 and math.abs(cy - self.pressY) < 5 then
for i, marker in ipairs(octomap.clickableMarkers) do
local x, y = self:FromMapToPanel(marker:GetMapPos())
local radius = marker.iconHalfSize + 2
if math.abs(cx - x) < radius and math.abs(cy - y) < radius then
if key == MOUSE_LEFT then
marker:LeftClick(self)
elseif key == MOUSE_RIGHT then
marker:RightClick(self)
end
end
end
end
self.panning = false
end
function PANEL:OnMouseWheeled(d)
if not self.allowPan then return end
local x, y = self:FromPanelToMap(self:LocalCursorPos())
self:Zoom(d, x, y)
end
function PANEL:PerformLayout()
self.cx = self:GetWide() / 2
self.cy = self:GetTall() / 2
self:AlignToBounds()
end
function PANEL:Zoom(d, x, y)
d = d or 1
if not x or not y then
x, y = self:FromPanelToMap(self:LocalCursorPos())
end
local scaleOld = self.tgtScale
self.tgtScale = math.Clamp(self.tgtScale * (d > 0 and 1.25 or 0.8), self.scaleMin, self.scaleMax)
local ch = math.abs(1 - scaleOld / self.tgtScale) * octolib.math.sign(d)
self.tgtOffX = octolib.math.lerpUnclamped(self.tgtOffX, -x, ch)
self.tgtOffY = octolib.math.lerpUnclamped(self.tgtOffY, -y, ch)
self:AlignToBounds()
end
function PANEL:GoTo(x, y, scale)
self.tgtSpeed = 10
timer.Create('octomap.tgtSpeedReset', 1, 1, function()
if not IsValid(self) then return end
self.tgtSpeed = config.tgtSpeed
end)
self.tgtOffX = -x + (self.paddingL - self.paddingR) / 2
self.tgtOffY = -y + (self.paddingT - self.paddingB) / 2
self.tgtScale = scale or self.tgtScale
self:AlignToBounds()
end
function PANEL:FromPanelToMap(x, y)
x, y = x or 0, y or 0
return (x - self.cx) / self.scale - self.offX, (y - self.cy) / self.scale - self.offY
end
function PANEL:FromMapToPanel(x, y)
x, y = x or 0, y or 0
return (x + self.offX) * self.scale + self.cx, (y + self.offY) * self.scale + self.cy
end
function PANEL:GetViewCenter()
return self.cx + (self.paddingL - self.paddingR) / 2, self.cy + (self.paddingT - self.paddingB) / 2
end
vgui.Register('octomap', PANEL, 'DPanel')