mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 05:43:46 +03:00
Upload
This commit is contained in:
104
lua/sui/libs/bshadows.lua
Normal file
104
lua/sui/libs/bshadows.lua
Normal file
@@ -0,0 +1,104 @@
|
||||
--[[
|
||||
| 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 ScrW = ScrW
|
||||
local ScrH = ScrH
|
||||
|
||||
local sin = math.sin
|
||||
local cos = math.cos
|
||||
local rad = math.rad
|
||||
local ceil = math.ceil
|
||||
|
||||
local Start2D = cam.Start2D
|
||||
local End2D = cam.End2D
|
||||
|
||||
local PushRenderTarget = render.PushRenderTarget
|
||||
local OverrideAlphaWriteEnable = render.OverrideAlphaWriteEnable
|
||||
local Clear = render.Clear
|
||||
local CopyRenderTargetToTexture = render.CopyRenderTargetToTexture
|
||||
local BlurRenderTarget = render.BlurRenderTarget
|
||||
local PopRenderTarget = render.PopRenderTarget
|
||||
local SetMaterial = render.SetMaterial
|
||||
local DrawScreenQuadEx = render.DrawScreenQuadEx
|
||||
local DrawScreenQuad = render.DrawScreenQuad
|
||||
|
||||
local RenderTarget, RenderTarget2
|
||||
local load_render_targets = function()
|
||||
local w, h = ScrW(), ScrH()
|
||||
RenderTarget = GetRenderTarget("sui_bshadows_original" .. w .. h, w, h)
|
||||
RenderTarget2 = GetRenderTarget("sui_bshadows_shadow" .. w .. h, w, h)
|
||||
end
|
||||
load_render_targets()
|
||||
hook.Add("OnScreenSizeChanged", "SUI.BShadows", load_render_targets)
|
||||
|
||||
local ShadowMaterial = CreateMaterial("sui_bshadows", "UnlitGeneric", {
|
||||
["$translucent"] = 1,
|
||||
["$vertexalpha"] = 1,
|
||||
["alpha"] = 1
|
||||
})
|
||||
|
||||
local ShadowMaterialGrayscale = CreateMaterial("sui_bshadows_grayscale", "UnlitGeneric", {
|
||||
["$translucent"] = 1,
|
||||
["$vertexalpha"] = 1,
|
||||
["$alpha"] = 1,
|
||||
["$color"] = "0 0 0",
|
||||
["$color2"] = "0 0 0"
|
||||
})
|
||||
|
||||
local SetTexture = ShadowMaterial.SetTexture
|
||||
|
||||
local BSHADOWS = {}
|
||||
|
||||
BSHADOWS.BeginShadow = function()
|
||||
PushRenderTarget(RenderTarget)
|
||||
|
||||
OverrideAlphaWriteEnable(true, true)
|
||||
Clear(0, 0, 0, 0)
|
||||
OverrideAlphaWriteEnable(false, false)
|
||||
|
||||
Start2D()
|
||||
end
|
||||
|
||||
BSHADOWS.EndShadow = function(intensity, spread, blur, opacity, direction, distance, _shadowOnly)
|
||||
opacity = opacity or 255
|
||||
direction = direction or 0
|
||||
distance = distance or 0
|
||||
|
||||
CopyRenderTargetToTexture(RenderTarget2)
|
||||
|
||||
if blur > 0 then
|
||||
OverrideAlphaWriteEnable(true, true)
|
||||
BlurRenderTarget(RenderTarget2, spread, spread, blur)
|
||||
OverrideAlphaWriteEnable(false, false)
|
||||
end
|
||||
|
||||
PopRenderTarget()
|
||||
|
||||
SetTexture(ShadowMaterial, "$basetexture", RenderTarget)
|
||||
SetTexture(ShadowMaterialGrayscale, "$basetexture", RenderTarget2)
|
||||
|
||||
local xOffset = sin(rad(direction)) * distance
|
||||
local yOffset = cos(rad(direction)) * distance
|
||||
|
||||
SetMaterial(ShadowMaterialGrayscale)
|
||||
for i = 1, ceil(intensity) do
|
||||
DrawScreenQuadEx(xOffset, yOffset, ScrW(), ScrH())
|
||||
end
|
||||
|
||||
if not _shadowOnly then
|
||||
SetTexture(ShadowMaterial, "$basetexture", RenderTarget)
|
||||
SetMaterial(ShadowMaterial)
|
||||
DrawScreenQuad()
|
||||
end
|
||||
|
||||
End2D()
|
||||
end
|
||||
|
||||
sui.BSHADOWS = BSHADOWS
|
||||
442
lua/sui/libs/gif_loader.lua
Normal file
442
lua/sui/libs/gif_loader.lua
Normal file
@@ -0,0 +1,442 @@
|
||||
--[[
|
||||
| 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 byte = string.byte
|
||||
local sub = string.sub
|
||||
local lshift = bit.lshift
|
||||
local rshift = bit.rshift
|
||||
local bor = bit.bor
|
||||
local band = bit.band
|
||||
|
||||
local GIFDecoder = {}
|
||||
local GIFDecoderMethods = {}
|
||||
local GIFDecoder_meta = {__index = GIFDecoderMethods}
|
||||
|
||||
function GIFDecoder.new(buf)
|
||||
local buf_n = #buf
|
||||
local this = setmetatable({
|
||||
p = 1,
|
||||
buf = buf
|
||||
}, GIFDecoder_meta)
|
||||
|
||||
local version = this:read(6)
|
||||
assert(version == "GIF89a" or version == "GIF87a", "wrong file format")
|
||||
|
||||
this.width = this:word()
|
||||
this.height = this:word()
|
||||
|
||||
local pf0 = this:byte()
|
||||
local global_palette_flag = rshift(pf0, 7)
|
||||
local num_global_colors_pow2 = band(pf0, 0x7)
|
||||
local num_global_colors = lshift(1, num_global_colors_pow2 + 1)
|
||||
this:skip(2)
|
||||
|
||||
local global_palette_offset = nil
|
||||
local global_palette_size = nil
|
||||
|
||||
if global_palette_flag > 0 then
|
||||
global_palette_offset = this.p
|
||||
this.global_palette_offset = global_palette_offset
|
||||
global_palette_size = num_global_colors
|
||||
this:skip(num_global_colors * 3)
|
||||
end
|
||||
|
||||
local no_eof = true
|
||||
|
||||
local frames = {}
|
||||
|
||||
local delay = 0
|
||||
local transparent_index = nil
|
||||
local disposal = 1
|
||||
|
||||
while no_eof and this.p <= buf_n do
|
||||
local b = this:byte()
|
||||
if b == 0x3b then
|
||||
no_eof = false
|
||||
elseif b == 0x2c then
|
||||
local x, y, w, h = this:word(), this:word(), this:word(), this:word()
|
||||
local pf2 = this:byte()
|
||||
local local_palette_flag = rshift(pf2, 7)
|
||||
local interlace_flag = band(rshift(pf2, 6), 1)
|
||||
local num_local_colors_pow2 = band(pf2, 0x7)
|
||||
local num_local_colors = lshift(1, num_local_colors_pow2 + 1)
|
||||
local palette_offset = global_palette_offset
|
||||
local palette_size = global_palette_size
|
||||
local has_local_palette = false
|
||||
if local_palette_flag ~= 0 then
|
||||
has_local_palette = true
|
||||
palette_offset = this.p
|
||||
palette_size = num_local_colors
|
||||
this:skip(num_local_colors * 3)
|
||||
end
|
||||
|
||||
local data_offset = this.p
|
||||
|
||||
this:skip(1)
|
||||
this:skip_eob()
|
||||
|
||||
table.insert(frames, {
|
||||
x = x,
|
||||
y = y,
|
||||
width = w,
|
||||
height = h,
|
||||
has_local_palette = has_local_palette,
|
||||
palette_offset = palette_offset,
|
||||
palette_size = palette_size,
|
||||
data_offset = data_offset,
|
||||
data_length = this.p - data_offset,
|
||||
transparent_index = transparent_index,
|
||||
interlaced = interlace_flag > 0,
|
||||
delay = delay,
|
||||
disposal = disposal
|
||||
})
|
||||
elseif b == 0x21 then
|
||||
local b2 = this:byte()
|
||||
if b2 == 0xf9 then
|
||||
local len, flags = this:bytes(2)
|
||||
delay = this:word()
|
||||
local transparent, terminator = this:bytes(2)
|
||||
|
||||
assert(len == 4 and terminator == 0, "Invalid graphics extension block.")
|
||||
|
||||
if flags % 2 == 1 then
|
||||
transparent_index = transparent
|
||||
else
|
||||
transparent_index = nil
|
||||
end
|
||||
|
||||
disposal = math.floor(flags / 4) % 8
|
||||
elseif b2 == 0xff then
|
||||
this:read(this:byte())
|
||||
this:skip_eob()
|
||||
else
|
||||
this:skip_eob()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
this.frames = frames
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
function GIFDecoderMethods:skip(offset)
|
||||
self.p = self.p + offset
|
||||
end
|
||||
|
||||
-- skip to end of block
|
||||
function GIFDecoderMethods:skip_eob()
|
||||
repeat
|
||||
local size = self:byte()
|
||||
self:skip(size)
|
||||
until size == 0
|
||||
end
|
||||
|
||||
function GIFDecoderMethods:byte()
|
||||
local b = byte(self.buf, self.p)
|
||||
self:skip(1)
|
||||
return b
|
||||
end
|
||||
|
||||
function GIFDecoderMethods:bytes(len)
|
||||
local _p = self.p
|
||||
self:skip(len)
|
||||
return byte(self.buf, _p, len + _p - 1)
|
||||
end
|
||||
|
||||
function GIFDecoderMethods:read(len)
|
||||
local _p = self.p
|
||||
self:skip(len)
|
||||
return sub(self.buf, _p, len + _p - 1)
|
||||
end
|
||||
|
||||
function GIFDecoderMethods:word()
|
||||
return bor(self:byte(), lshift(self:byte(), 8))
|
||||
end
|
||||
|
||||
local GifReaderLZWOutputIndexStream = function(this, output, output_length)
|
||||
local min_code_size = this:byte()
|
||||
local clear_code = lshift(1, min_code_size)
|
||||
local eoi_code = clear_code + 1
|
||||
local next_code = eoi_code + 1
|
||||
local cur_code_size = min_code_size + 1
|
||||
|
||||
local code_mask = lshift(1, cur_code_size) - 1
|
||||
local cur_shift = 0
|
||||
local cur = 0
|
||||
local op = 0
|
||||
|
||||
local subblock_size = this:byte()
|
||||
|
||||
local code_table = {}
|
||||
|
||||
local prev_code = nil
|
||||
|
||||
while true do
|
||||
while cur_shift < 16 do
|
||||
if subblock_size == 0 then break end
|
||||
|
||||
cur = bor(cur, lshift(this:byte(), cur_shift))
|
||||
cur_shift = cur_shift + 8
|
||||
|
||||
if subblock_size == 1 then
|
||||
subblock_size = this:byte()
|
||||
else
|
||||
subblock_size = subblock_size - 1
|
||||
end
|
||||
end
|
||||
|
||||
if cur_shift < cur_code_size then break end
|
||||
|
||||
local code = band(cur, code_mask)
|
||||
cur = rshift(cur, cur_code_size)
|
||||
cur_shift = cur_shift - cur_code_size
|
||||
|
||||
if code == clear_code then
|
||||
next_code = eoi_code + 1
|
||||
cur_code_size = min_code_size + 1
|
||||
code_mask = lshift(1, cur_code_size) - 1
|
||||
|
||||
prev_code = null
|
||||
continue
|
||||
elseif code == eoi_code then
|
||||
break
|
||||
end
|
||||
|
||||
local chase_code = code < next_code and code or prev_code
|
||||
local chase_length = 0
|
||||
local chase = chase_code
|
||||
while chase > clear_code do
|
||||
chase = rshift(code_table[chase], 8)
|
||||
chase_length = chase_length + 1
|
||||
end
|
||||
|
||||
local k = chase
|
||||
local op_end = op + chase_length + (chase_code ~= code and 1 or 0)
|
||||
if op_end > output_length then
|
||||
Error("Warning, gif stream longer than expected.")
|
||||
return
|
||||
end
|
||||
|
||||
output[op] = k; op = op + 1
|
||||
op = op + chase_length
|
||||
|
||||
local b = op
|
||||
|
||||
if chase_code ~= code then
|
||||
output[op] = k; op = op + 1
|
||||
end
|
||||
chase = chase_code
|
||||
|
||||
while chase_length > 0 do
|
||||
chase_length = chase_length - 1
|
||||
chase = code_table[chase]
|
||||
b = b - 1
|
||||
output[b] = band(chase, 0xff)
|
||||
|
||||
chase = rshift(chase, 8)
|
||||
end
|
||||
|
||||
if prev_code ~= nil and next_code < 4096 then
|
||||
code_table[next_code] = bor(lshift(prev_code, 8), k)
|
||||
next_code = next_code + 1
|
||||
|
||||
if next_code >= code_mask + 1 and cur_code_size < 12 then
|
||||
cur_code_size = cur_code_size + 1
|
||||
code_mask = bor(lshift(code_mask, 1), 1)
|
||||
end
|
||||
end
|
||||
|
||||
prev_code = code
|
||||
end
|
||||
|
||||
if op ~= output_length then
|
||||
Error("Warning, gif stream shorter than expected.")
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
function GIFDecoderMethods:decode_and_blit_frame_RGBA(frame_num, pixels)
|
||||
local frame = self.frames[frame_num]
|
||||
local num_pixels = frame.width * frame.height
|
||||
local index_stream = {}
|
||||
|
||||
self.p = frame.data_offset
|
||||
GifReaderLZWOutputIndexStream(self, index_stream, num_pixels)
|
||||
local palette_offset = frame.palette_offset
|
||||
|
||||
local trans = frame.transparent_index
|
||||
if trans == nil then
|
||||
trans = 256
|
||||
end
|
||||
|
||||
local width = self.width
|
||||
local framewidth = frame.width
|
||||
local framestride = width - framewidth
|
||||
local xleft = framewidth
|
||||
|
||||
local opbeg = (frame.y * width + frame.x) * 4
|
||||
|
||||
local opend = ((frame.y + frame.height) * width + frame.x) * 4
|
||||
local op = opbeg
|
||||
local scanstride = framestride * 4
|
||||
|
||||
if frame.interlaced == true then
|
||||
scanstride = scanstride + (width * 4 * 7)
|
||||
end
|
||||
|
||||
local interlaceskip = 8
|
||||
|
||||
local i = 0
|
||||
local buf = self.buf
|
||||
while i < num_pixels do
|
||||
local index = index_stream[i]
|
||||
|
||||
if xleft == 0 then
|
||||
op = op + scanstride
|
||||
xleft = framewidth
|
||||
|
||||
if op >= opend then
|
||||
scanstride =
|
||||
framestride * 4 + width * 4 * (interlaceskip - 1)
|
||||
|
||||
op =
|
||||
opbeg +
|
||||
(framewidth + framestride) * lshift(interlaceskip, 1)
|
||||
interlaceskip = rshift(interlaceskip, 1)
|
||||
end
|
||||
end
|
||||
|
||||
if index ~= trans then
|
||||
index = palette_offset + index * 3
|
||||
pixels[op + 0] = byte(buf, index)
|
||||
pixels[op + 1] = byte(buf, index + 1)
|
||||
pixels[op + 2] = byte(buf, index + 2)
|
||||
pixels[op + 3] = 255
|
||||
end
|
||||
|
||||
op = op + 4
|
||||
|
||||
xleft = xleft - 1
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
function GIFDecoderMethods:clear_frame(frame_num, pixels)
|
||||
local frame = self.frames[frame_num]
|
||||
|
||||
self.p = frame.data_offset
|
||||
|
||||
local width = self.width
|
||||
local framewidth = frame.width
|
||||
local framestride = width - framewidth
|
||||
local xleft = framewidth
|
||||
|
||||
local opbeg = (frame.y * width + frame.x) * 4
|
||||
|
||||
local opend = ((frame.y + frame.height) * width + frame.x) * 4
|
||||
local op = opbeg
|
||||
local scanstride = framestride * 4
|
||||
|
||||
if frame.interlaced == true then
|
||||
scanstride = scanstride + (width * 4 * 7)
|
||||
end
|
||||
|
||||
local interlaceskip = 8
|
||||
|
||||
local i = 0
|
||||
local num_pixels = frame.width * frame.height
|
||||
while i < num_pixels do
|
||||
if xleft == 0 then
|
||||
op = op + scanstride
|
||||
xleft = framewidth
|
||||
|
||||
if op >= opend then
|
||||
scanstride =
|
||||
framestride * 4 + width * 4 * (interlaceskip - 1)
|
||||
|
||||
op =
|
||||
opbeg +
|
||||
(framewidth + framestride) * lshift(interlaceskip, 1)
|
||||
interlaceskip = rshift(interlaceskip, 1)
|
||||
end
|
||||
end
|
||||
|
||||
pixels[op + 0] = 0
|
||||
pixels[op + 1] = 0
|
||||
pixels[op + 2] = 0
|
||||
pixels[op + 3] = 0
|
||||
op = op + 4
|
||||
|
||||
xleft = xleft - 1
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
function GIFDecoderMethods:get_frames()
|
||||
local num_pixels = self.width * self.height * 4 + 4
|
||||
local frames = {}
|
||||
local numFrames = #self.frames
|
||||
local last_frame
|
||||
local restore_from
|
||||
for i = 1, numFrames do
|
||||
local frame = self.frames[i]
|
||||
|
||||
local data = {}
|
||||
|
||||
if last_frame then
|
||||
local _data = last_frame.data
|
||||
for k = 0, num_pixels do
|
||||
data[k] = _data[k]
|
||||
end
|
||||
end
|
||||
|
||||
if i > 1 then
|
||||
local last_disposal = last_frame.disposal
|
||||
if last_disposal == 3 then
|
||||
if restore_from then
|
||||
for k = 0, num_pixels do
|
||||
data[k] = restore_from[k]
|
||||
end
|
||||
else
|
||||
self:clear_frame(i - 1, data)
|
||||
end
|
||||
end
|
||||
|
||||
if last_disposal == 2 then
|
||||
self:clear_frame(i - 1, data)
|
||||
end
|
||||
end
|
||||
|
||||
self:decode_and_blit_frame_RGBA(i, data)
|
||||
|
||||
local delay = frame.delay
|
||||
if delay < 2 then
|
||||
delay = 10
|
||||
end
|
||||
|
||||
local disposal = frame.disposal
|
||||
last_frame = {
|
||||
data = data,
|
||||
delay = delay,
|
||||
disposal = disposal
|
||||
}
|
||||
frames[i] = last_frame
|
||||
|
||||
if disposal ~= 3 then
|
||||
restore_from = data
|
||||
end
|
||||
end
|
||||
|
||||
return frames
|
||||
end
|
||||
|
||||
return GIFDecoder.new
|
||||
215
lua/sui/libs/png_encoder.lua
Normal file
215
lua/sui/libs/png_encoder.lua
Normal file
@@ -0,0 +1,215 @@
|
||||
--[[
|
||||
| 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 string = string
|
||||
local table = table
|
||||
local bit = bit
|
||||
|
||||
local char = string.char
|
||||
local byte = string.byte
|
||||
|
||||
local insert = table.insert
|
||||
local concat = table.concat
|
||||
|
||||
local bor = bit.bor
|
||||
local bxor = bit.bxor
|
||||
local band = bit.band
|
||||
local bnot = bit.bnot
|
||||
local lshift = bit.lshift
|
||||
local rshift = bit.rshift
|
||||
|
||||
local ceil = math.ceil
|
||||
|
||||
local SIGNATURE = char(137, 80, 78, 71, 13, 10, 26, 10)
|
||||
|
||||
local crc_table = {}; do
|
||||
local n = 0
|
||||
while n < 256 do
|
||||
local c = n
|
||||
local k = 0
|
||||
while k < 8 do
|
||||
if band(c, 1) ~= 0 then
|
||||
c = bxor(0xedb88320, rshift(c, 1))
|
||||
else
|
||||
c = rshift(c, 1)
|
||||
end
|
||||
k = k + 1
|
||||
end
|
||||
crc_table[n + 1] = c
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
|
||||
local crc = function(buf)
|
||||
local c = 0xffffffff
|
||||
for i = 1, #buf do
|
||||
c = bxor(crc_table[band(bxor(c, byte(buf, i)), 0xff) + 1], rshift(c, 8))
|
||||
end
|
||||
return bxor(c, 0xffffffff)
|
||||
end
|
||||
|
||||
local dword_as_string = function(dword)
|
||||
return char(
|
||||
rshift(band(dword, 0xff000000), 24),
|
||||
rshift(band(dword, 0x00ff0000), 16),
|
||||
rshift(band(dword, 0x0000ff00), 8),
|
||||
band(dword, 0x000000ff)
|
||||
)
|
||||
end
|
||||
|
||||
local create_chunk = function(type, data, length)
|
||||
local CRC = crc(type .. data)
|
||||
return concat({
|
||||
dword_as_string(length or #data),
|
||||
type,
|
||||
data,
|
||||
dword_as_string(CRC)
|
||||
}, "", 1, 4)
|
||||
end
|
||||
|
||||
local create_IHDR; do
|
||||
local ARGS = (
|
||||
-- bit depth
|
||||
char(8) ..
|
||||
-- color type: 6=truecolor with alpha
|
||||
char(6) ..
|
||||
-- compression method: 0=deflate, only allowed value
|
||||
char(0) ..
|
||||
-- filtering: 0=adaptive, only allowed value
|
||||
char(0) ..
|
||||
-- interlacing: 0=none
|
||||
char(0)
|
||||
)
|
||||
|
||||
create_IHDR = function(w, h)
|
||||
return create_chunk("IHDR", concat({
|
||||
dword_as_string(w),
|
||||
dword_as_string(h),
|
||||
ARGS
|
||||
}, "", 1, 3), 13)
|
||||
end
|
||||
end
|
||||
|
||||
local deflate_pack; do
|
||||
local BASE = 6552
|
||||
local NMAX = 5552
|
||||
local adler32 = function(str)
|
||||
local s1 = 1
|
||||
local s2 = 0
|
||||
local n = NMAX
|
||||
|
||||
for i = 1, #str do
|
||||
s1 = s1 + byte(str, i)
|
||||
s2 = s2 + s1
|
||||
|
||||
n = n - 1
|
||||
if n == 0 then
|
||||
s1 = s1 % BASE
|
||||
s2 = s2 % BASE
|
||||
n = NMAX
|
||||
end
|
||||
end
|
||||
|
||||
s1 = s1 % BASE
|
||||
s2 = s2 % BASE
|
||||
|
||||
return bor(lshift(s2, 16), s1)
|
||||
end
|
||||
|
||||
local splitChunks = function(chunk, chunkSize)
|
||||
local len = ceil(#chunk / chunkSize)
|
||||
local ret = {}
|
||||
for i = 1, len do
|
||||
ret[i - 1] = chunk:sub(((i - 1) * chunkSize) + 1, chunkSize)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
deflate_pack = function(str)
|
||||
local ret = {"\x78\x9c"}
|
||||
|
||||
local chunks = splitChunks(str, 0xFFFF)
|
||||
local len = #chunks
|
||||
|
||||
local i = 0
|
||||
while i < (len + 1) do
|
||||
local chunk = chunks[i]
|
||||
local chunk_n = #chunk
|
||||
|
||||
insert(ret, i < len and "\x00" or "\x01")
|
||||
insert(ret, char(band(chunk_n, 0xff), band(rshift(chunk_n, 8), 0xff)))
|
||||
insert(ret, char(band(bnot(chunk_n), 0xff), band(rshift(bnot(chunk_n), 8), 0xff)))
|
||||
insert(ret, chunk)
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
local t = adler32(str)
|
||||
t = char(
|
||||
band(rshift(t, 24), 0xff),
|
||||
band(rshift(t, 16), 0xff),
|
||||
band(rshift(t, 8), 0xff),
|
||||
band(t, 0xff)
|
||||
)
|
||||
|
||||
insert(ret, t)
|
||||
|
||||
return concat(ret)
|
||||
end
|
||||
end
|
||||
|
||||
local create_IDAT; do
|
||||
local slice = function(a, s, e)
|
||||
local ret, j = {}, 0
|
||||
for i = s, e - 1 do
|
||||
ret[j] = char(band(a[i] or 0, 0xFF))
|
||||
j = j + 1
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local array_split_chunks = function(w, h, array, chunkSize)
|
||||
local ret = {}
|
||||
local i = 0
|
||||
local len = ceil((w * h * 4 + 4) / chunkSize)
|
||||
while i < len do
|
||||
ret[i] = slice(array, i * chunkSize, (i + 1) * chunkSize)
|
||||
i = i + 1
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
create_IDAT = function(w, h, chunk)
|
||||
local scanlines = array_split_chunks(w, h, chunk, w * 4)
|
||||
|
||||
local image_bytes = {}
|
||||
for i = 0, #scanlines do
|
||||
local scanline = scanlines[i]
|
||||
insert(image_bytes, char(band(0, 0xFF)))
|
||||
insert(image_bytes, concat(scanline, "", 0, #scanline))
|
||||
end
|
||||
image_bytes = deflate_pack(concat(image_bytes))
|
||||
|
||||
return create_chunk("IDAT", image_bytes)
|
||||
end
|
||||
end
|
||||
|
||||
local IEND = create_chunk("IEND", "", 0)
|
||||
local to_return = {SIGNATURE, nil, nil, IEND}
|
||||
local generate_png = function(w, h, chunk)
|
||||
local IHDR = create_IHDR(w, h)
|
||||
local IDAT = create_IDAT(w, h, chunk)
|
||||
|
||||
to_return[2] = IHDR
|
||||
to_return[3] = IDAT
|
||||
|
||||
return concat(to_return, "", 1, 4)
|
||||
end
|
||||
|
||||
return generate_png
|
||||
924
lua/sui/libs/tdlib/cl_tdlib.lua
Normal file
924
lua/sui/libs/tdlib/cl_tdlib.lua
Normal file
@@ -0,0 +1,924 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
--[[
|
||||
Three's Derma Lib
|
||||
Made by Threebow
|
||||
|
||||
You are free to use this anywhere you like, or sell any addons
|
||||
made using this, as long as I am properly accredited.
|
||||
]]
|
||||
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local Color = Color
|
||||
local render = render
|
||||
local SysTime = SysTime
|
||||
local Lerp, RealFrameTime = Lerp, RealFrameTime
|
||||
local RoundedBox, RoundedBoxEx, NoTexture = draw.RoundedBox, draw.RoundedBoxEx, draw.NoTexture
|
||||
local SetDrawColor, DrawRect = surface.SetDrawColor, surface.DrawRect
|
||||
local DrawPoly = surface.DrawPoly
|
||||
local sui = sui
|
||||
|
||||
local Panel = FindMetaTable("Panel")
|
||||
|
||||
--[[
|
||||
Constants
|
||||
]]
|
||||
local BLUR = CreateMaterial("SUI.TDLib.Blur", "gmodscreenspace", {
|
||||
["$basetexture"] = "_rt_fullframefb",
|
||||
["$blur"] = (1 / 3) * 7,
|
||||
})
|
||||
|
||||
local COL_WHITE_1 = Color(255, 255, 255)
|
||||
local COL_WHITE_2 = Color(255, 255, 255, 30)
|
||||
|
||||
--[[
|
||||
credits to http://slabode.exofire.net/circle_draw.shtml
|
||||
]]
|
||||
local calculate_circle do
|
||||
local cos = math.cos
|
||||
local sin = math.sin
|
||||
local round = math.Round
|
||||
local sqrt = math.sqrt
|
||||
local pi = math.pi
|
||||
calculate_circle = function(circle, x_centre, y_centre, r)
|
||||
if circle.x == x_centre and circle.y == y_centre and circle.r == r then return end
|
||||
|
||||
local step = (2 * pi) / round(6 * sqrt(r))
|
||||
|
||||
local i = 0
|
||||
for theta = 2 * pi, 0, -step do
|
||||
local x = x_centre + r * cos(theta)
|
||||
local y = y_centre - r * sin(theta)
|
||||
i = i + 1
|
||||
circle[i] = {
|
||||
x = x,
|
||||
y = y
|
||||
}
|
||||
end
|
||||
|
||||
for i = i + 1, #circle do
|
||||
circle[i] = nil
|
||||
end
|
||||
|
||||
circle.x = x_centre
|
||||
circle.y = y_centre
|
||||
circle.r = r
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
void DrawArc(float cx, float cy, float r, float start_angle, float arc_angle, int num_segments)
|
||||
{
|
||||
float theta = arc_angle / float(num_segments - 1);//theta is now calculated from the arc angle instead, the - 1 bit comes from the fact that the arc is open
|
||||
|
||||
float tangetial_factor = tanf(theta);
|
||||
|
||||
float radial_factor = cosf(theta);
|
||||
|
||||
|
||||
float x = r * cosf(start_angle);//we now start at the start angle
|
||||
float y = r * sinf(start_angle);
|
||||
|
||||
glBegin(GL_LINE_STRIP);//since the arc is not a closed curve, this is a strip now
|
||||
for(int ii = 0; ii < num_segments; ii++)
|
||||
{
|
||||
glVertex2f(x + cx, y + cy);
|
||||
|
||||
float tx = -y;
|
||||
float ty = x;
|
||||
|
||||
x += tx * tangetial_factor;
|
||||
y += ty * tangetial_factor;
|
||||
|
||||
x *= radial_factor;
|
||||
y *= radial_factor;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
]]
|
||||
|
||||
local copy_color = function(color)
|
||||
return Color(color.r, color.g, color.b, color.a)
|
||||
end
|
||||
|
||||
local color_alpha = function(color, a)
|
||||
color.a = a
|
||||
return color
|
||||
end
|
||||
|
||||
--[[
|
||||
Collection of various utilities
|
||||
]]
|
||||
|
||||
local TDLibUtil = {}
|
||||
|
||||
function TDLibUtil.DrawCircle(circle, x, y, r, color)
|
||||
calculate_circle(circle, x, y, r)
|
||||
|
||||
SetDrawColor(color)
|
||||
NoTexture()
|
||||
DrawPoly(circle)
|
||||
end
|
||||
local DrawCircle = TDLibUtil.DrawCircle
|
||||
|
||||
do
|
||||
local SetMaterial = surface.SetMaterial
|
||||
local UpdateScreenEffectTexture, DrawTexturedRect, SetScissorRect = render.UpdateScreenEffectTexture, surface.DrawTexturedRect, render.SetScissorRect
|
||||
|
||||
local scrW, scrH = ScrW(), ScrH()
|
||||
hook.Add("OnScreenSizeChanged", "SUI.TDLib", function()
|
||||
scrW, scrH = ScrW(), ScrH()
|
||||
end)
|
||||
|
||||
function TDLibUtil.BlurPanel(s)
|
||||
local x, y = s:LocalToScreen(0, 0)
|
||||
|
||||
SetDrawColor(255, 255, 255)
|
||||
SetMaterial(BLUR)
|
||||
|
||||
for i = 1, 2 do
|
||||
UpdateScreenEffectTexture()
|
||||
DrawTexturedRect(x * -1, y * -1, scrW, scrH)
|
||||
end
|
||||
end
|
||||
|
||||
function TDLibUtil.DrawBlur(x, y, w, h)
|
||||
SetDrawColor(255, 255, 255)
|
||||
SetMaterial(BLUR)
|
||||
|
||||
SetScissorRect(x, y, x + w, y + h, true)
|
||||
for i = 1, 2 do
|
||||
UpdateScreenEffectTexture()
|
||||
DrawTexturedRect(-1, -1, scrW, scrH)
|
||||
end
|
||||
SetScissorRect(0, 0, 0, 0, false)
|
||||
end
|
||||
end
|
||||
|
||||
local LibClasses = {}
|
||||
|
||||
do
|
||||
local on_funcs = {}
|
||||
|
||||
function LibClasses:On(name, func)
|
||||
local old_func = self[name]
|
||||
|
||||
if not old_func then
|
||||
self[name] = func
|
||||
return self
|
||||
end
|
||||
|
||||
local name_2 = name .. "_funcs"
|
||||
|
||||
-- we gotta avoid creating 13535035 closures
|
||||
if not on_funcs[name] then
|
||||
on_funcs[name] = function(s, a1, a2, a3, a4)
|
||||
local funcs = s[name_2]
|
||||
local i, n = 0, #funcs
|
||||
::loop::
|
||||
i = i + 1
|
||||
if i <= n then
|
||||
funcs[i](s, a1, a2, a3, a4)
|
||||
goto loop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not self[name_2] then
|
||||
self[name] = on_funcs[name]
|
||||
self[name_2] = {
|
||||
old_func,
|
||||
func
|
||||
}
|
||||
else
|
||||
table.insert(self[name_2], func)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local UnPredictedCurTime = UnPredictedCurTime
|
||||
|
||||
local transition_func = function(s)
|
||||
local transitions = s.transitions
|
||||
local i, n = 0, #transitions
|
||||
::loop::
|
||||
i = i + 1
|
||||
|
||||
if i <= n then
|
||||
local v = transitions[i]
|
||||
local name = v.name
|
||||
local v2 = s[name]
|
||||
if v.func(s) then
|
||||
if v.start_0 then
|
||||
v.start_1, v.start_0 = UnPredictedCurTime(), nil
|
||||
end
|
||||
|
||||
if v2 ~= 1 then
|
||||
s[name] = Lerp((UnPredictedCurTime() - v.start_1) / v.time, v2, 1)
|
||||
end
|
||||
else
|
||||
if v.start_1 then
|
||||
v.start_0, v.start_1 = UnPredictedCurTime(), nil
|
||||
end
|
||||
|
||||
if v2 ~= 0 then
|
||||
s[name] = Lerp((UnPredictedCurTime() - v.start_0) / v.time, v2, 0)
|
||||
end
|
||||
end
|
||||
|
||||
goto loop
|
||||
end
|
||||
end
|
||||
|
||||
function LibClasses:SetupTransition(name, time, func)
|
||||
self[name] = 0
|
||||
|
||||
local transition = {
|
||||
name = name,
|
||||
time = time,
|
||||
func = func,
|
||||
start_0 = 0,
|
||||
start_1 = 0,
|
||||
}
|
||||
|
||||
if self.transitions then
|
||||
for k, v in ipairs(self.transitions) do
|
||||
if v.name == name then
|
||||
self.transitions[k] = transition
|
||||
return self
|
||||
end
|
||||
end
|
||||
table.insert(self.transitions, transition)
|
||||
else
|
||||
self.transitions = {transition}
|
||||
self:On("Think", transition_func)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
function LibClasses:ClearPaint()
|
||||
self.Paint = nil
|
||||
self.Paint_funcs = nil
|
||||
local SetPaintBackgroundEnabled = self.SetPaintBackgroundEnabled
|
||||
if SetPaintBackgroundEnabled then
|
||||
SetPaintBackgroundEnabled(self, false)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function LibClasses:RoundedBox(id, r, x, y, w, h, c)
|
||||
self.colors = self.colors or {}
|
||||
local colors = self.colors
|
||||
|
||||
local id_c = colors[id]
|
||||
if not id_c then
|
||||
id_c = Color(c:Unpack())
|
||||
colors[id] = id_c
|
||||
end
|
||||
|
||||
sui.lerp_color(id_c, c)
|
||||
RoundedBox(r, x, y, w, h, id_c)
|
||||
end
|
||||
|
||||
do
|
||||
local SetFGColor = Panel.SetFGColor
|
||||
|
||||
local set_color = function(s, col)
|
||||
s.m_colText = col
|
||||
SetFGColor(s, col.r, col.g, col.b, col.a)
|
||||
end
|
||||
|
||||
local paint = function(s)
|
||||
local col = s.sui_textcolor
|
||||
sui.lerp_color(col, s.new_col)
|
||||
set_color(s, col)
|
||||
end
|
||||
|
||||
function LibClasses:TextColor(c, use_paint)
|
||||
local col = self.sui_textcolor
|
||||
if not col then
|
||||
col = Color(c:Unpack())
|
||||
self.sui_textcolor = col
|
||||
|
||||
if use_paint then
|
||||
self:On("Paint", paint)
|
||||
end
|
||||
end
|
||||
|
||||
if use_paint then
|
||||
self.new_col = c
|
||||
else
|
||||
sui.lerp_color(col, c)
|
||||
self:SetTextColor(col)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local fade_hover_Paint = function(s, w, h)
|
||||
if s.FadeHovers ~= 0 then
|
||||
color_alpha(s.fadehover_color, s.fadehover_old_alpha * s.FadeHovers)
|
||||
if s.fadehover_radius > 0 then
|
||||
RoundedBox(s.fadehover_radius, 0, 0, w, h, s.fadehover_color)
|
||||
else
|
||||
SetDrawColor(s.fadehover_color)
|
||||
DrawRect(0, 0, w, h)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function LibClasses:FadeHover(color, time, radius, func)
|
||||
color = copy_color(color or COL_WHITE_2)
|
||||
self.fadehover_color = color
|
||||
self.fadehover_radius = radius or 0
|
||||
self.fadehover_old_alpha = color.a
|
||||
self:SetupTransition("FadeHovers", time or 0.8, func or TDLibUtil.HoverFunc)
|
||||
self:On("Paint", fade_hover_Paint)
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
function LibClasses:BarHover(color, height, time)
|
||||
color = color or COL_WHITE_1
|
||||
height = height or 2
|
||||
time = time or 1.6
|
||||
self:SetupTransition("BarHovers", time, TDLibUtil.HoverFunc)
|
||||
self:On("Paint", function(s, w, h)
|
||||
if s.BarHovers ~= 0 then
|
||||
local bar = Round(w * s.BarHovers)
|
||||
SetDrawColor(color)
|
||||
DrawRect((w / 2) - (bar / 2), h - height, bar, height)
|
||||
end
|
||||
end)
|
||||
return self
|
||||
end
|
||||
|
||||
do
|
||||
local paint = function(s, w, h)
|
||||
draw.RoundedBox(0, 0, 0, w, h, s.SUI_GetColor("line"))
|
||||
end
|
||||
|
||||
function LibClasses:Line(dock, m1, m2, m3, m4)
|
||||
self.making_line = true
|
||||
|
||||
local line = self:Add("SAM.Panel")
|
||||
line:Dock(dock or TOP)
|
||||
|
||||
if self.line_margin then
|
||||
line:DockMargin(unpack(self.line_margin))
|
||||
else
|
||||
line:DockMargin(m1 or 0, m2 or 0, m3 or 0, m4 or 10)
|
||||
end
|
||||
|
||||
line.no_scale = true
|
||||
line:SetTall(1)
|
||||
line.Paint = paint
|
||||
|
||||
self.making_line = false
|
||||
return line
|
||||
end
|
||||
|
||||
function LibClasses:LineMargin(m1, m2, m3, m4)
|
||||
self.line_margin = {m1 or 0, m2 or 0, m3 or 0, m4 or 0}
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local background_Paint_1 = function(s)
|
||||
s:SetBGColor(s.background_color)
|
||||
end
|
||||
|
||||
local background_Paint_2 = function(s, w, h)
|
||||
RoundedBoxEx(s.background_radius, 0, 0, w, h, s.background_color, true, true, true, true)
|
||||
end
|
||||
|
||||
local background_Paint_3 = function(s, w, h)
|
||||
RoundedBoxEx(s.background_radius, 0, 0, w, h, s.background_color, s.background_r_tl, s.background_r_tr, s.background_r_bl, s.background_r_br)
|
||||
end
|
||||
|
||||
function LibClasses:Background(color, radius, r_tl, r_tr, r_bl, r_br)
|
||||
self.background_color = color
|
||||
if isnumber(radius) and radius ~= 0 then
|
||||
self.background_radius = radius
|
||||
if isbool(r_tl) or isbool(r_tr) or isbool(r_bl) or isbool(r_br) then
|
||||
self.background_r_tl = r_tl
|
||||
self.background_r_tr = r_tr
|
||||
self.background_r_bl = r_bl
|
||||
self.background_r_br = r_br
|
||||
self:On("Paint", background_Paint_3)
|
||||
else
|
||||
self:On("Paint", background_Paint_2)
|
||||
end
|
||||
else
|
||||
self:SetPaintBackgroundEnabled(true)
|
||||
self:On("ApplySchemeSettings", background_Paint_1)
|
||||
self:On("PerformLayout", background_Paint_1)
|
||||
end
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
function LibClasses:CircleClick(color, speed, target_radius)
|
||||
self.circle_click_color = color or COL_WHITE_2
|
||||
|
||||
speed = speed or 5
|
||||
target_radius = isnumber(target_radius) and target_radius or false
|
||||
|
||||
local radius, alpha, click_x, click_y = 0, -1, 0, 0
|
||||
local circle = {}
|
||||
self:On("Paint", function(s, w)
|
||||
if alpha >= 0 then
|
||||
DrawCircle(circle, click_x, click_y, radius, ColorAlpha(self.circle_click_color, alpha))
|
||||
local frame_time = RealFrameTime()
|
||||
radius, alpha = Lerp(frame_time * speed, radius, target_radius or w), Lerp(frame_time * speed, alpha, -1)
|
||||
end
|
||||
end)
|
||||
self:On("DoClick", function()
|
||||
click_x, click_y = self:CursorPos()
|
||||
radius, alpha = 0, self.circle_click_color.a
|
||||
end)
|
||||
return self
|
||||
end
|
||||
|
||||
do
|
||||
local min = math.min
|
||||
function LibClasses:CircleClick2(color, speed, target_radius, start_radius)
|
||||
color = color or COL_WHITE_2
|
||||
local _color = Color(color:Unpack())
|
||||
|
||||
speed = speed or 5
|
||||
target_radius = isnumber(target_radius) and target_radius or false
|
||||
|
||||
local radius, alpha = 0, -1
|
||||
local circle = {}
|
||||
self:On("Paint", function(s, w, h)
|
||||
if alpha >= 0 then
|
||||
_color.a = alpha
|
||||
DrawCircle(circle, w / 2, h / 2, radius, _color)
|
||||
|
||||
local frame_time = RealFrameTime()
|
||||
radius, alpha = Lerp(frame_time * speed, radius, target_radius or min(w, h) / 2), Lerp(frame_time * speed, alpha, -1)
|
||||
end
|
||||
end)
|
||||
|
||||
self:On("DoClick", function()
|
||||
radius, alpha = start_radius or 0, color.a
|
||||
end)
|
||||
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
-- https://github.com/Facepunch/garrysmod/pull/1520#issuecomment-410458090
|
||||
function LibClasses:Outline(color, width)
|
||||
color = color or COL_WHITE_1
|
||||
width = width or 1
|
||||
self:On("Paint", function(s, w, h)
|
||||
SetDrawColor(color)
|
||||
DrawRect(0, 0, w, width)
|
||||
DrawRect(0, h - width, w, width)
|
||||
DrawRect(0, width, width, h - (width * 2))
|
||||
DrawRect(w - width, width, width, h - (width * 2))
|
||||
end)
|
||||
return self
|
||||
end
|
||||
|
||||
function LibClasses:LinedCorners(color, len)
|
||||
color = color or COL_WHITE_1
|
||||
len = len or 15
|
||||
self:On("Paint", function(s, w, h)
|
||||
SetDrawColor(color)
|
||||
DrawRect(0, 0, len, 1)
|
||||
DrawRect(0, 1, 1, len - 1)
|
||||
DrawRect(w - len, h - 1, len, 1)
|
||||
DrawRect(w - 1, h - len, 1, len - 1)
|
||||
end)
|
||||
return self
|
||||
end
|
||||
|
||||
function LibClasses:SideBlock(color, size, side)
|
||||
color = color or COL_WHITE_1
|
||||
size = size or 3
|
||||
side = side or LEFT
|
||||
self:On("Paint", function(s, w, h)
|
||||
SetDrawColor(color)
|
||||
if side == LEFT then
|
||||
DrawRect(0, 0, size, h)
|
||||
elseif side == TOP then
|
||||
DrawRect(0, 0, w, size)
|
||||
elseif size == RIGHT then
|
||||
DrawRect(w - size, 0, size, h)
|
||||
elseif side == BOTTOM then
|
||||
DrawRect(0, h - size, w, size)
|
||||
end
|
||||
end)
|
||||
return self
|
||||
end
|
||||
|
||||
function LibClasses:Blur()
|
||||
self:On("Paint", TDLibUtil.BlurPanel)
|
||||
return self
|
||||
end
|
||||
|
||||
do
|
||||
local STENCILOPERATION_REPLACE = STENCILOPERATION_REPLACE
|
||||
local STENCILOPERATION_ZERO = STENCILOPERATION_ZERO
|
||||
local STENCILCOMPARISONFUNCTION_NEVER = STENCILCOMPARISONFUNCTION_NEVER
|
||||
local STENCILCOMPARISONFUNCTION_EQUAL = STENCILCOMPARISONFUNCTION_EQUAL
|
||||
|
||||
local ClearStencil = render.ClearStencil
|
||||
local SetStencilEnable = render.SetStencilEnable
|
||||
local SetStencilWriteMask = render.SetStencilWriteMask
|
||||
local SetStencilTestMask = render.SetStencilTestMask
|
||||
local SetStencilFailOperation = render.SetStencilFailOperation
|
||||
local SetStencilPassOperation = render.SetStencilPassOperation
|
||||
local SetStencilZFailOperation = render.SetStencilZFailOperation
|
||||
local SetStencilCompareFunction = render.SetStencilCompareFunction
|
||||
local SetStencilReferenceValue = render.SetStencilReferenceValue
|
||||
|
||||
local color_white = color_white
|
||||
|
||||
local avatar_setplayer = function(s, ply, size)
|
||||
s.avatar:SetPlayer(ply, size)
|
||||
end
|
||||
|
||||
local avatar_setsteamid = function(s, steamid, size)
|
||||
s.avatar:SetSteamID(steamid, size)
|
||||
end
|
||||
|
||||
function LibClasses:CircleAvatar()
|
||||
local avatar = self:Add("AvatarImage")
|
||||
avatar:Dock(FILL)
|
||||
avatar:SetPaintedManually(true)
|
||||
self.avatar = avatar
|
||||
self.SetSteamID = avatar_setsteamid
|
||||
self.SetPlayer = avatar_setplayer
|
||||
|
||||
local circle = {}
|
||||
local PaintManual = avatar.PaintManual
|
||||
self.Paint = function(s, w, h)
|
||||
ClearStencil()
|
||||
SetStencilEnable(true)
|
||||
|
||||
SetStencilWriteMask(1)
|
||||
SetStencilTestMask(1)
|
||||
|
||||
SetStencilFailOperation(STENCILOPERATION_REPLACE)
|
||||
SetStencilPassOperation(STENCILOPERATION_ZERO)
|
||||
SetStencilZFailOperation(STENCILOPERATION_ZERO)
|
||||
SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_NEVER)
|
||||
SetStencilReferenceValue(1)
|
||||
|
||||
local a = w / 2
|
||||
DrawCircle(circle, a, a, a, color_white)
|
||||
|
||||
SetStencilFailOperation(STENCILOPERATION_ZERO)
|
||||
SetStencilPassOperation(STENCILOPERATION_REPLACE)
|
||||
SetStencilZFailOperation(STENCILOPERATION_ZERO)
|
||||
SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL)
|
||||
SetStencilReferenceValue(1)
|
||||
|
||||
PaintManual(avatar)
|
||||
|
||||
SetStencilEnable(false)
|
||||
end
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
function LibClasses:AnimationThinkInternal()
|
||||
local systime = SysTime()
|
||||
|
||||
if self.Term and self.Term <= systime then
|
||||
self:Remove()
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local m_AnimList = self.m_AnimList
|
||||
if not m_AnimList then return end
|
||||
|
||||
for i = #m_AnimList, 1, -1 do
|
||||
local anim = m_AnimList[i]
|
||||
if systime >= anim.StartTime then
|
||||
local frac = math.TimeFraction(anim.StartTime, anim.EndTime, systime)
|
||||
frac = math.Clamp(frac, 0, 1)
|
||||
|
||||
local Think = anim.Think
|
||||
if Think then
|
||||
Think(anim, self, frac ^ (1.0 - (frac - 0.5)))
|
||||
end
|
||||
|
||||
if frac == 1 then
|
||||
local OnEnd = anim.OnEnd
|
||||
if OnEnd then
|
||||
OnEnd(anim, self)
|
||||
end
|
||||
|
||||
m_AnimList[i] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local sort = function(a, b)
|
||||
return a.EndTime > b.EndTime
|
||||
end
|
||||
|
||||
function LibClasses:NewAnimation(length, delay, ease, callback)
|
||||
delay = delay or 0
|
||||
ease = ease or -1
|
||||
|
||||
if self.m_AnimQueue then
|
||||
delay = delay + self:AnimTail()
|
||||
self.m_AnimQueue = false
|
||||
else
|
||||
delay = delay + SysTime()
|
||||
end
|
||||
|
||||
local anim = {
|
||||
StartTime = delay,
|
||||
EndTime = delay + length,
|
||||
Ease = ease,
|
||||
OnEnd = callback
|
||||
}
|
||||
|
||||
self:SetAnimationEnabled(true)
|
||||
|
||||
if self.m_AnimList == nil then
|
||||
self.m_AnimList = {}
|
||||
end
|
||||
|
||||
table.insert(self.m_AnimList, anim)
|
||||
table.sort(self.m_AnimList, sort)
|
||||
|
||||
self.AnimationThink = self.AnimationThinkInternal
|
||||
|
||||
return anim
|
||||
end
|
||||
|
||||
local MoveThink = function(anim, panel, frac)
|
||||
if not anim.startx then
|
||||
anim.startx = panel.x
|
||||
anim.starty = panel.y
|
||||
end
|
||||
|
||||
local x = Lerp(frac, anim.startx, anim.x)
|
||||
local y = Lerp(frac, anim.starty, anim.y)
|
||||
panel:SetPos(x, y)
|
||||
end
|
||||
|
||||
function LibClasses:MoveTo(x, y, length, delay, ease, callback)
|
||||
if self.x == x and self.y == y then return end
|
||||
|
||||
local anim = self:NewAnimation(length, delay, ease, callback)
|
||||
anim.x = x
|
||||
anim.y = y
|
||||
anim.Think = MoveThink
|
||||
end
|
||||
|
||||
local SetSize = Panel.SetSize
|
||||
local SizeThink = function(anim, panel, frac)
|
||||
if not anim.startw then
|
||||
anim.startw, anim.starth = panel:GetSize()
|
||||
end
|
||||
|
||||
local w, h
|
||||
if anim.sizew and anim.sizeh then
|
||||
w = Lerp(frac, anim.startw, anim.w)
|
||||
h = Lerp(frac, anim.starth, anim.h)
|
||||
SetSize(panel, w, h)
|
||||
elseif anim.sizew then
|
||||
w = Lerp(frac, anim.startw, anim.w)
|
||||
SetSize(panel, w, panel.starth)
|
||||
else
|
||||
h = Lerp(frac, anim.starth, anim.h)
|
||||
SetSize(panel, panel.startw, h)
|
||||
end
|
||||
|
||||
if panel:GetDock() > 0 then
|
||||
panel:InvalidateParent()
|
||||
end
|
||||
end
|
||||
|
||||
function LibClasses:SizeTo(w, h, length, delay, ease, callback)
|
||||
local anim = self:NewAnimation(length, delay, ease, callback)
|
||||
|
||||
if w ~= -1 then
|
||||
anim.sizew = true
|
||||
end
|
||||
|
||||
if h ~= -1 then
|
||||
anim.sizeh = true
|
||||
end
|
||||
|
||||
anim.w, anim.h = w, h
|
||||
anim.Think = SizeThink
|
||||
|
||||
return anim
|
||||
end
|
||||
|
||||
local SetVisible = Panel.SetVisible
|
||||
local IsVisible = Panel.IsVisible
|
||||
|
||||
local is_visible = function(s)
|
||||
local state = s.visible_state
|
||||
if state ~= nil then
|
||||
return state
|
||||
else
|
||||
return IsVisible(s)
|
||||
end
|
||||
end
|
||||
|
||||
function LibClasses:AnimatedSetVisible(visible, cb)
|
||||
if visible == is_visible(self) then
|
||||
if cb then
|
||||
cb()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if visible then
|
||||
SetVisible(self, true)
|
||||
end
|
||||
|
||||
self.visible_state = visible
|
||||
self:Stop()
|
||||
|
||||
self:AlphaTo(visible and 255 or 0, 0.2, 0, function()
|
||||
SetVisible(self, visible)
|
||||
self:InvalidateParent(true)
|
||||
if cb then
|
||||
cb()
|
||||
end
|
||||
end)
|
||||
|
||||
self:InvalidateParent(true)
|
||||
end
|
||||
|
||||
function LibClasses:AnimatedToggleVisible()
|
||||
self:AnimatedSetVisible(not is_visible(self))
|
||||
end
|
||||
|
||||
function LibClasses:AnimatedIsVisible()
|
||||
return is_visible(self)
|
||||
end
|
||||
end
|
||||
|
||||
function Panel:SUI_TDLib()
|
||||
for k, v in pairs(LibClasses) do
|
||||
self[k] = v
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
TDLibUtil.Install = Panel.SUI_TDLib
|
||||
|
||||
local count = 0
|
||||
TDLibUtil.Start = function()
|
||||
count = count + 1
|
||||
for k, v in pairs(LibClasses) do
|
||||
if not Panel["SUI_OLD" .. k] then
|
||||
local old = Panel[k]
|
||||
if old == nil then
|
||||
old = v
|
||||
end
|
||||
Panel[k], Panel["SUI_OLD" .. k] = v, old
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
TDLibUtil.End = function()
|
||||
count = count - 1
|
||||
if count > 0 then return end
|
||||
for k, v in pairs(LibClasses) do
|
||||
local old = Panel["SUI_OLD" .. k]
|
||||
if old == v then
|
||||
Panel[k] = nil
|
||||
else
|
||||
Panel[k] = old
|
||||
end
|
||||
Panel["SUI_OLD" .. k] = nil
|
||||
end
|
||||
end
|
||||
|
||||
TDLibUtil.HoverFunc = function(p)
|
||||
return p:IsHovered() and not p:GetDisabled()
|
||||
end
|
||||
|
||||
TDLibUtil.DrawOutlinedBox = function(radius, x, y, w, h, bg, outline, thickness)
|
||||
thickness = thickness or 2
|
||||
draw.RoundedBox(radius, x, y, w, h, outline)
|
||||
draw.RoundedBox(radius, x + thickness, y + thickness, w - (thickness * 2), h - (thickness * 2), bg)
|
||||
end
|
||||
|
||||
do
|
||||
local cos, sin, sqrt = math.cos, math.sin, math.sqrt
|
||||
local clamp, floor = math.Clamp, math.floor
|
||||
local min, max = math.min, math.max
|
||||
|
||||
local calc_ellipse_points = function(rx, ry)
|
||||
local points = sqrt(((rx * ry) / 2) * 6)
|
||||
return max(points, 8)
|
||||
end
|
||||
|
||||
local M_PI = 3.14159265358979323846
|
||||
calc_rect = function(c, r, x, y, w, h)
|
||||
if
|
||||
(c.r == r) and
|
||||
(c.x == x and c.y == y) and
|
||||
(c.w == w and c.h == h)
|
||||
then return end
|
||||
|
||||
r = clamp(r, 0, min(w, h) / 2)
|
||||
|
||||
local rx, ry = r, r
|
||||
if w >= 0.02 then
|
||||
rx = min(rx, w / 2.0 - 0.01)
|
||||
end
|
||||
if h >= 0.02 then
|
||||
ry = min(ry, h / 2.0 - 0.01)
|
||||
end
|
||||
|
||||
local points = max(calc_ellipse_points(rx, ry) / 4, 1)
|
||||
points = floor(points)
|
||||
|
||||
local half_pi = M_PI / 2
|
||||
local angle_shift = half_pi / (points + 1)
|
||||
|
||||
local phi = 0
|
||||
for i = 1, points + 2 do
|
||||
c[i] = {
|
||||
x = x + rx * (1 - cos(phi)),
|
||||
y = y + ry * (1 - sin(phi))
|
||||
}
|
||||
phi = phi + angle_shift
|
||||
end
|
||||
|
||||
phi = half_pi
|
||||
for i = points + 3, 2 * (points + 2) do
|
||||
c[i] = {
|
||||
x = x + w - rx * (1 + cos(phi)),
|
||||
y = y + ry * (1 - sin(phi))
|
||||
}
|
||||
phi = phi + angle_shift
|
||||
end
|
||||
|
||||
phi = 2 * half_pi
|
||||
for i = (2 * (points + 2)) + 1, 3 * (points + 2) do
|
||||
c[i] = {
|
||||
x = x + w - rx * (1 + cos(phi)),
|
||||
y = y + h - ry * (1 + sin(phi))
|
||||
}
|
||||
phi = phi + angle_shift
|
||||
end
|
||||
|
||||
phi = 3 * half_pi
|
||||
for i = (3 * (points + 2)) + 1, 4 * (points + 2) do
|
||||
c[i] = {
|
||||
x = x + rx * (1 - cos(phi)),
|
||||
y = y + h - ry * (1 + sin(phi))
|
||||
}
|
||||
phi = phi + angle_shift
|
||||
end
|
||||
|
||||
local last = (points + 2) * 4 + 1
|
||||
c[last] = c[1]
|
||||
|
||||
for i = last + 1, #c do
|
||||
c[i] = nil
|
||||
end
|
||||
|
||||
c.r = r
|
||||
c.x, c.y = x, y
|
||||
c.w, c.h = w, h
|
||||
end
|
||||
|
||||
TDLibUtil.RoundedBox = function(c, r, x, y, w, h, color)
|
||||
calc_rect(c, r, x, y, w, h)
|
||||
|
||||
SetDrawColor(color)
|
||||
NoTexture()
|
||||
DrawPoly(c)
|
||||
end
|
||||
end
|
||||
|
||||
TDLibUtil.LibClasses = LibClasses
|
||||
|
||||
sui.TDLib = TDLibUtil
|
||||
92
lua/sui/libs/types.lua
Normal file
92
lua/sui/libs/types.lua
Normal file
@@ -0,0 +1,92 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
-- https://gist.github.com/CapsAdmin/0d9c1e77d0fc22d910e182bfeb9812e5
|
||||
local getmetatable = getmetatable
|
||||
|
||||
do
|
||||
local types = {
|
||||
["string"] = "",
|
||||
["boolean"] = true,
|
||||
["number"] = 0,
|
||||
["function"] = function() end,
|
||||
["thread"] = coroutine.create(getmetatable),
|
||||
["Color"] = Color(0, 0, 0),
|
||||
}
|
||||
|
||||
for k, v in pairs(types) do
|
||||
if not getmetatable(v) then
|
||||
debug.setmetatable(v, {MetaName = k})
|
||||
else
|
||||
getmetatable(v).MetaName = k
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sui.type(value)
|
||||
if value == nil then
|
||||
return "nil"
|
||||
end
|
||||
local meta = getmetatable(value)
|
||||
if meta then
|
||||
meta = meta.MetaName
|
||||
if meta then
|
||||
return meta
|
||||
end
|
||||
end
|
||||
return "table"
|
||||
end
|
||||
|
||||
do
|
||||
local function add(name)
|
||||
local new_name = name
|
||||
if name == "bool" then
|
||||
new_name = "boolean"
|
||||
end
|
||||
sui["is" .. name:lower()] = function(value)
|
||||
local meta = getmetatable(value)
|
||||
if meta and meta.MetaName == new_name then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
add("string")
|
||||
add("number")
|
||||
add("bool")
|
||||
add("function")
|
||||
|
||||
add("Angle")
|
||||
add("Vector")
|
||||
add("Panel")
|
||||
add("Matrix")
|
||||
end
|
||||
|
||||
function sui.isentity(value)
|
||||
local meta = getmetatable(value)
|
||||
if meta then
|
||||
if meta.MetaName == "Entity" then
|
||||
return true
|
||||
end
|
||||
meta = meta.MetaBaseClass
|
||||
if meta then
|
||||
return meta.MetaName == "Entity"
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
sui.IsEntity = sui.isentity
|
||||
|
||||
local type = sui.type
|
||||
function sui.istable(value)
|
||||
return type(value) == "table"
|
||||
end
|
||||
Reference in New Issue
Block a user