mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
400 lines
8.7 KiB
Lua
400 lines
8.7 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 L = pace.LanguageString
|
|
|
|
pace.selectControl = {}
|
|
local selectControl = pace.selectControl
|
|
|
|
function selectControl.VecToScreen(vec)
|
|
return vec:ToScreen()
|
|
end
|
|
|
|
function selectControl.GetMousePos()
|
|
return input.GetCursorPos()
|
|
end
|
|
|
|
function selectControl.GUIMousePressed(mcode) end
|
|
function selectControl.GUIMouseReleased(mcode) end
|
|
function selectControl.HUDPaint() end
|
|
|
|
local RENDER_ATTACHMENTS = CreateConVar('pac_render_attachments', '0', {FCVAR_ARCHIVE}, 'Render attachments when selecting bones')
|
|
|
|
function pace.ToggleRenderAttachments()
|
|
RunConsoleCommand('pac_render_attachments', RENDER_ATTACHMENTS:GetBool() and '0' or '1')
|
|
end
|
|
|
|
local font_name = "pac_select"
|
|
local font_scale = 0.05
|
|
|
|
surface.CreateFont(
|
|
font_name,
|
|
{
|
|
font = "DejaVu Sans",
|
|
size = 500 * font_scale,
|
|
weight = 800,
|
|
antialias = true,
|
|
additive = true,
|
|
}
|
|
)
|
|
|
|
local font_name_blur = font_name.."_blur"
|
|
|
|
surface.CreateFont(
|
|
font_name_blur,
|
|
{
|
|
font = "DejaVu Sans",
|
|
size = 500 * font_scale,
|
|
weight = 800,
|
|
antialias = true,
|
|
additive = false,
|
|
blursize = 3,
|
|
}
|
|
)
|
|
|
|
|
|
local function draw_text(text, color, x, y)
|
|
surface.SetFont(font_name_blur)
|
|
surface.SetTextColor(color_black)
|
|
|
|
for i=1, 10 do
|
|
surface.SetTextPos(x,y)
|
|
surface.DrawText(text)
|
|
end
|
|
|
|
surface.SetFont(font_name)
|
|
surface.SetTextColor(color)
|
|
surface.SetTextPos(x,y)
|
|
surface.DrawText(text)
|
|
end
|
|
|
|
local holding
|
|
local area = 20
|
|
local x, y = 0, 0
|
|
local siz = 5
|
|
local sizeSelected = 12
|
|
local sizeHovered = 7
|
|
local currentSizeSelected = 5
|
|
|
|
local hR = 83
|
|
local hG = 167
|
|
local hB = 213
|
|
|
|
local sR = 148
|
|
local sG = 67
|
|
local sB = 201
|
|
|
|
local white = surface.GetTextureID("gui/center_gradient.vtf")
|
|
|
|
function pace.DrawHUDText(x, y, text, lx, ly, mx, my, selected, line_color)
|
|
mx = mx or gui.MouseX()
|
|
my = my or gui.MouseY()
|
|
|
|
local color = selected and Color(128, 255, 128) or color_white
|
|
|
|
surface.SetDrawColor(line_color or color)
|
|
|
|
pace.util.DrawLine(
|
|
Lerp(0.025, mx, x + lx),
|
|
Lerp(0.025, my, y + ly),
|
|
|
|
Lerp(0.05, x + lx, mx),
|
|
Lerp(0.05, y + ly, my),
|
|
selected and 4 or 1
|
|
)
|
|
|
|
surface.SetFont(font_name)
|
|
|
|
local w, h = surface.GetTextSize(text)
|
|
draw_text(text, color, (x + lx) - w / 2, (y + ly) - h / 2)
|
|
end
|
|
|
|
local function checkVisible(pos)
|
|
return
|
|
x > pos.x - area and x < pos.x + area and
|
|
y > pos.y - area and y < pos.y + area
|
|
end
|
|
|
|
local function DrawSelection(pos, r, g, b, sizeToUse)
|
|
if not pos.visible then return false end
|
|
surface.SetDrawColor(r, g, b, 255)
|
|
surface.DrawOutlinedRect(pos.x - (sizeToUse * 0.5), pos.y - (sizeToUse * 0.5), sizeToUse, sizeToUse)
|
|
surface.SetDrawColor(0, 0, 0, 255)
|
|
surface.DrawOutlinedRect(pos.x - (sizeToUse * 0.5) - 1, pos.y - (sizeToUse * 0.5) - 1, sizeToUse + 2, sizeToUse + 2)
|
|
|
|
return checkVisible(pos)
|
|
end
|
|
|
|
function pace.DrawSelection(pos)
|
|
return DrawSelection(pos, 255, 255, 255, siz)
|
|
end
|
|
|
|
function pace.DrawSelectionHovered(pos)
|
|
return DrawSelection(pos, hR, hG, hB, sizeHovered)
|
|
end
|
|
|
|
function pace.DrawSelectionSelected(pos)
|
|
return DrawSelection(pos, sR, sG, sB, sizeSelected + math.sin(RealTime() * 4) * 3)
|
|
end
|
|
|
|
local function get_friendly_name(ent)
|
|
local name = ent.Nick and ent:Nick()
|
|
if not name or name == "" then
|
|
name = language.GetPhrase(ent:GetClass())
|
|
end
|
|
|
|
return ent:EntIndex() .. " - " .. name
|
|
end
|
|
|
|
function pace.StopSelect()
|
|
pac.RemoveHook("GUIMouseReleased", "draw_select")
|
|
pac.RemoveHook("GUIMousePressed", "draw_select")
|
|
pac.RemoveHook("HUDPaint", "draw_select")
|
|
function selectControl.GUIMousePressed(mcode) end
|
|
function selectControl.GUIMouseReleased(mcode) end
|
|
function selectControl.HUDPaint() end
|
|
|
|
timer.Simple(0.1, function()
|
|
pace.IsSelecting = false
|
|
end)
|
|
end
|
|
|
|
local function select_something(tblin, check, getpos, getfriendly, callback, selectCallback, poll)
|
|
local data
|
|
local selected = {}
|
|
holding = nil
|
|
|
|
local function GUIMousePressed(mcode)
|
|
if mcode == MOUSE_LEFT then
|
|
if not selected then
|
|
pace.StopSelect()
|
|
end
|
|
|
|
holding = Vector(selectControl.GetMousePos())
|
|
end
|
|
end
|
|
|
|
local function GUIMouseReleased(mcode)
|
|
if mcode == MOUSE_LEFT then
|
|
if data then
|
|
data.dist = nil
|
|
callback(data)
|
|
pace.StopSelect()
|
|
end
|
|
end
|
|
end
|
|
|
|
local function HUDPaint()
|
|
if poll and not poll() then pace.StopSelect() return end
|
|
|
|
surface.SetAlphaMultiplier(1)
|
|
|
|
x, y = selectControl.GetMousePos()
|
|
|
|
local tbl = {}
|
|
|
|
for key, value in pairs(tblin) do
|
|
if check(key, value) then
|
|
goto CONTINUE
|
|
end
|
|
|
|
local pos = selectControl.VecToScreen(getpos(key, value))
|
|
local friendly = getfriendly(key, value)
|
|
|
|
if checkVisible(pos) then
|
|
table.insert(tbl, {pos = pos, friendly = friendly, dist = pace.util.FastDistance2D(pos.x, pos.y, x, y), key = key, value = value})
|
|
else
|
|
local hit = false
|
|
if selected then
|
|
for i, val in ipairs(selected) do
|
|
if val.key == key and val.value == value then
|
|
hit = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if not hit then
|
|
pace.DrawSelection(pos)
|
|
end
|
|
end
|
|
::CONTINUE::
|
|
end
|
|
|
|
if tbl[1] then
|
|
table.sort(tbl, function(a, b) return a.dist < b.dist end)
|
|
|
|
if not selected or not holding then
|
|
selected = {}
|
|
|
|
local first = tbl[1]
|
|
|
|
for i, v in ipairs(tbl) do
|
|
if math.Round(v.dist / 200) == math.Round(first.dist / 200) then
|
|
table.insert(selected, v)
|
|
else
|
|
break
|
|
end
|
|
end
|
|
|
|
if #selected < 3 and first.dist < area / 4 then
|
|
selected = {first}
|
|
end
|
|
end
|
|
elseif not holding then
|
|
selected = nil
|
|
end
|
|
|
|
if selected then
|
|
if #selected == 1 then
|
|
local v = selected[1]
|
|
pace.DrawSelectionSelected(v.pos)
|
|
pace.DrawHUDText(v.pos.x, v.pos.y, L(v.friendly), 0, -30, v.pos.x, v.pos.y)
|
|
data = v
|
|
if selectCallback then selectCallback(v.key, v.value) end
|
|
else
|
|
table.sort(selected, function(a,b) return L(a.friendly) > L(b.friendly) end)
|
|
|
|
local found
|
|
local rad = math.min(#selected * 30, 400)
|
|
|
|
for k, v in ipairs(selected) do
|
|
local sx = math.sin((k / #selected) * math.pi * 2) * rad
|
|
local sy = math.cos((k / #selected) * math.pi * 2) * rad
|
|
|
|
v.pos = selectControl.VecToScreen(getpos(v.key, v.value))
|
|
|
|
if holding and pace.util.FastDistance2D(v.pos.x + sx, v.pos.y + sy, x, y) < area then
|
|
pace.DrawSelectionSelected(v.pos)
|
|
pace.DrawHUDText(v.pos.x, v.pos.y, L(v.friendly), sx, sy, v.pos.x, v.pos.y, true)
|
|
found = v
|
|
if selectCallback then selectCallback(v.key, v.value) end
|
|
else
|
|
pace.DrawSelectionHovered(v.pos)
|
|
pace.DrawHUDText(v.pos.x, v.pos.y, L(v.friendly), sx, sy, v.pos.x, v.pos.y, false, Color(255, 255, 255, 128))
|
|
end
|
|
end
|
|
|
|
data = found
|
|
end
|
|
end
|
|
end
|
|
|
|
pace.IsSelecting = true
|
|
|
|
selectControl.HUDPaint = HUDPaint
|
|
selectControl.GUIMousePressed = GUIMousePressed
|
|
selectControl.GUIMouseReleased = GUIMouseReleased
|
|
|
|
pac.AddHook("GUIMousePressed", "draw_select", selectControl.GUIMousePressed)
|
|
pac.AddHook("GUIMouseReleased", "draw_select", selectControl.GUIMouseReleased)
|
|
pac.AddHook("HUDPaint", "draw_select", selectControl.HUDPaint)
|
|
end
|
|
|
|
function pace.SelectBone(ent, callback, only_movable)
|
|
if not ent or not ent:IsValid() then return end
|
|
local tbl = table.Copy(pac.GetModelBones(ent))
|
|
|
|
if only_movable then
|
|
local models = ent:GetModel() and util.GetModelMeshes(ent:GetModel())
|
|
|
|
if models then
|
|
for k, v in pairs(tbl) do
|
|
if not v.bone then
|
|
tbl[k] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
for k, v in pairs(tbl) do
|
|
if v.is_special or not RENDER_ATTACHMENTS:GetBool() and v.is_attachment then
|
|
tbl[k] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
select_something(
|
|
tbl,
|
|
|
|
function() end,
|
|
|
|
function(k, v)
|
|
return pac.GetBonePosAng(ent, k)
|
|
end,
|
|
|
|
function(k, v)
|
|
return k
|
|
end,
|
|
|
|
callback,
|
|
|
|
function (key, val)
|
|
if val.is_special or val.is_attachment then return end
|
|
ent.pac_bones_select_target = val.i
|
|
end,
|
|
|
|
function() return ent:IsValid() end
|
|
)
|
|
end
|
|
|
|
function pace.SelectPart(parts, callback)
|
|
select_something(
|
|
parts,
|
|
|
|
function(_, part)
|
|
return part:IsHidden() and part:GetShowInEditor()
|
|
end,
|
|
|
|
function(_, part)
|
|
if part.GetDrawPosition then
|
|
return part:GetDrawPosition()
|
|
end
|
|
|
|
local owner = part:GetOwner()
|
|
if owner:IsValid() then
|
|
return owner:GetPos()
|
|
end
|
|
|
|
owner = part:GetPlayerOwner()
|
|
if owner:IsValid() then
|
|
return owner:GetPos()
|
|
end
|
|
end,
|
|
|
|
function(_, part)
|
|
return part:GetName()
|
|
end,
|
|
|
|
function(data) return callback(data.value) end
|
|
)
|
|
end
|
|
|
|
function pace.SelectEntity(callback)
|
|
select_something(
|
|
ents.GetAll(),
|
|
|
|
function(_, ent)
|
|
return
|
|
not ent:IsValid() or
|
|
ent:EntIndex() == -1
|
|
end,
|
|
|
|
function(_, ent)
|
|
return ent:EyePos()
|
|
end,
|
|
|
|
function(_, ent)
|
|
return get_friendly_name(ent)
|
|
end,
|
|
|
|
function(data) return callback(data.value) end
|
|
)
|
|
end
|