Initial commit
This commit is contained in:
commit
1a0785862d
79
koptilnya/engine_sound.txt
Normal file
79
koptilnya/engine_sound.txt
Normal file
@ -0,0 +1,79 @@
|
||||
--@include libs/utils.txt
|
||||
--@client
|
||||
|
||||
require("libs/utils.txt")
|
||||
|
||||
EngineSound = class("EngineSound")
|
||||
|
||||
accessorFunc(EngineSound, "_masterVolume", "MasterVolume", 1)
|
||||
accessorFunc(EngineSound, "_parent", "Parent", chip())
|
||||
|
||||
function EngineSound:initialize(soundsMap)
|
||||
self._rpm = 0
|
||||
self._soundsMap = soundsMap
|
||||
self._sources = {}
|
||||
|
||||
for k, v in pairs(soundsMap) do
|
||||
bass.loadURL(v.link, "3d noblock", function(snd, err, errtxt)
|
||||
if snd then
|
||||
snd:setPos(self:getParent():getPos())
|
||||
snd:setLooping(true)
|
||||
snd:setVolume(0)
|
||||
|
||||
v.source = snd
|
||||
table.insert(self._sources, snd)
|
||||
elseif errtext then
|
||||
error(errtxt)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
hook.add("think", "EngineSound_think", function()
|
||||
for _, v in pairs(self._sources) do
|
||||
v:setPos(self:getParent():getPos())
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function fadeIn(rpm, range)
|
||||
local fadeIn = 1
|
||||
|
||||
if range and range[1] != range[2] then
|
||||
fadeIn = math.min(math.max((rpm + (range[2] - range[1] * 2)) / (range[2] - range[1]), 1) - 1, 1)
|
||||
end
|
||||
|
||||
return fadeIn
|
||||
end
|
||||
|
||||
local function fadeOut(rpm, range)
|
||||
local fadeOut = 1
|
||||
|
||||
if range and range[1] != range[2] then
|
||||
fadeOut = math.min(math.max((rpm + (range[1] - range[2] * 2)) / (range[1] - range[2]), 1) - 1, 1)
|
||||
end
|
||||
|
||||
return fadeOut
|
||||
end
|
||||
|
||||
function EngineSound:setRPM(rpm)
|
||||
self._rpm = rpm
|
||||
|
||||
for _, v in pairs(self._soundsMap) do
|
||||
if v.source then
|
||||
local pitch = rpm / v.rootPitch
|
||||
local fadeIn = fadeIn(rpm, v.fadeIn)
|
||||
local fadeOut = fadeOut(rpm, v.fadeOut)
|
||||
|
||||
v.source:setVolume(math.max(self:getMasterVolume() * (fadeIn + fadeOut - 1), 0.01))
|
||||
v.source:setPitch(math.max(pitch, 0.01))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function EngineSound:getRPM()
|
||||
return self._rpm
|
||||
end
|
||||
|
||||
function EngineSound:getSources()
|
||||
return self._sources
|
||||
end
|
||||
51
koptilnya/gui/elements/button.txt
Normal file
51
koptilnya/gui/elements/button.txt
Normal file
@ -0,0 +1,51 @@
|
||||
--@include label.txt
|
||||
--@include radius_mixin.txt
|
||||
--@include ../utils.txt
|
||||
|
||||
require("label.txt")
|
||||
require("../utils.txt")
|
||||
|
||||
EButton = class("EButton", ELabel)
|
||||
EButton:include(require("radius_mixin.txt"))
|
||||
|
||||
accessorFunc(EButton, "_textColor", "TextColor", Color(230, 230, 230))
|
||||
accessorFunc(EButton, "_hoveredColor", "HoveredColor", Color(66, 66, 66))
|
||||
accessorFunc(EButton, "_hoveredTextColor", "HoveredTextColor", Color(230, 230, 230))
|
||||
accessorFunc(EButton, "_disabledColor", "DisabledColor", Color(32, 32, 32))
|
||||
accessorFunc(EButton, "_disabledTextColor", "DisabledTextColor", Color(80, 80, 80))
|
||||
|
||||
function EButton:initialize()
|
||||
ELabel.initialize(self)
|
||||
|
||||
self:setText("Button")
|
||||
self:setColor(Color(46, 46, 46))
|
||||
self:setSize(100, 32)
|
||||
self:setRoundedCorners(true)
|
||||
self:setRadius(5)
|
||||
end
|
||||
|
||||
function EButton:paint()
|
||||
local x, y = self:getAbsolutePos()
|
||||
local w, h = self:getSize()
|
||||
local textW, textH = self:getTextSize()
|
||||
local rTL, rTR, rBR, rBL = self:getRoundedCorners()
|
||||
local bgColor, textColor
|
||||
if self:isEnabled() then
|
||||
bgColor = self:isHovered() and self:getHoveredColor() or self:getColor()
|
||||
textColor = self:isHovered() and self:getHoveredTextColor() or self:getTextColor()
|
||||
else
|
||||
bgColor = self:getDisabledColor()
|
||||
textColor = self:getDisabledTextColor()
|
||||
end
|
||||
|
||||
render.setColor(bgColor)
|
||||
if self:getRadius() > 0 and (rTL or rTR or rBR or rBL) then
|
||||
render.drawRoundedBoxEx(self:getRadius(), x, y, w, h, rTL, rTR, rBL, rBR)
|
||||
else
|
||||
render.drawRectFast(x, y, w, h)
|
||||
end
|
||||
|
||||
render.setFont(self:getFont())
|
||||
render.setColor(textColor)
|
||||
render.drawSimpleText(x + w / 2 - textW / 2, y + h / 2 - textH / 2, self:getText())
|
||||
end
|
||||
62
koptilnya/gui/elements/checkbox.txt
Normal file
62
koptilnya/gui/elements/checkbox.txt
Normal file
@ -0,0 +1,62 @@
|
||||
--@include element.txt
|
||||
--@include label.txt
|
||||
--@include ../utils.txt
|
||||
|
||||
require("element.txt")
|
||||
require("label.txt")
|
||||
require("../utils.txt")
|
||||
|
||||
ECheckbox = class("ECheckbox", ELabel)
|
||||
|
||||
accessorFunc(ECheckbox, "_textColor", "TextColor", Color(255, 255, 255))
|
||||
accessorFunc(ECheckbox, "_hoveredColor", "HoveredColor", Color(66, 66, 66))
|
||||
accessorFunc(ECheckbox, "_hoveredTextColor", "HoveredTextColor", Color(255, 255, 255))
|
||||
accessorFunc(ECheckbox, "_disabledColor", "DisabledColor", Color(32, 32, 32))
|
||||
accessorFunc(ECheckbox, "_disabledTextColor", "DisabledTextColor", Color(80, 80, 80))
|
||||
accessorFunc(ECheckbox, "_indent", "Indent", 8)
|
||||
|
||||
function ECheckbox:initialize()
|
||||
ELabel.initialize(self)
|
||||
|
||||
self._checked = false
|
||||
|
||||
self:setText("Checkbox")
|
||||
self:setSize(200, 16)
|
||||
end
|
||||
|
||||
function ECheckbox:setChecked(state)
|
||||
self._checked = state
|
||||
|
||||
self:onChange()
|
||||
end
|
||||
|
||||
function ECheckbox:isChecked()
|
||||
return self._checked
|
||||
end
|
||||
|
||||
function ECheckbox:paint()
|
||||
local x, y = self:getAbsolutePos()
|
||||
local w, h = self:getSize()
|
||||
local textW, textH = self:getTextSize()
|
||||
--[[
|
||||
local bgColor, textColor
|
||||
if self:isEnabled() then
|
||||
bgColor = self:isHovered() and self:getHoveredColor() or self:getColor()
|
||||
textColor = self:isHovered() and self:getHoveredTextColor() or self:getTextColor()
|
||||
else
|
||||
bgColor = self:getDisabledColor()
|
||||
textColor = self:getDisabledTextColor()
|
||||
end
|
||||
]]
|
||||
|
||||
render.setColor(Color(209, 209, 209))
|
||||
render.drawCircle(x, y, h / 2)
|
||||
--render.drawRectOutline(x, y, h, h, -8)
|
||||
|
||||
--render.setColor(Color(209, 209, 209, 0))
|
||||
--render.drawRectFast(x, y, h - 2, h - 2)
|
||||
|
||||
render.setFont(self:getFont())
|
||||
render.setColor(Color(255, 255, 255))
|
||||
render.drawSimpleText(x + h + self:getIndent(), y + h / 2 - textH / 2, self:getText())
|
||||
end
|
||||
359
koptilnya/gui/elements/element.txt
Normal file
359
koptilnya/gui/elements/element.txt
Normal file
@ -0,0 +1,359 @@
|
||||
--@include ../utils.txt
|
||||
--@include ../skins/default.txt
|
||||
|
||||
require("../utils.txt")
|
||||
local defaultSkin = require("../skins/default.txt")
|
||||
|
||||
Element = class("Element")
|
||||
|
||||
accessorFunc(Element, "_x", "X", 0)
|
||||
accessorFunc(Element, "_y", "Y", 0)
|
||||
|
||||
function Element:initialize()
|
||||
self._width = 0
|
||||
self._height = 0
|
||||
self._enabled = true
|
||||
self._visible = true
|
||||
self._draggable = true
|
||||
self._hovered = false
|
||||
self._parent = nil
|
||||
self._firstChild = nil
|
||||
self._prevSibling = nil
|
||||
self._nextSibling = nil
|
||||
self._skin = defaultSkin
|
||||
end
|
||||
|
||||
function Element:setWidth(width)
|
||||
self._width = width
|
||||
|
||||
self:performLayout(self:getSize())
|
||||
end
|
||||
|
||||
function Element:getWidth()
|
||||
return self._width
|
||||
end
|
||||
|
||||
function Element:setHeight(height)
|
||||
self._height = height
|
||||
|
||||
self:performLayout(self:getSize())
|
||||
end
|
||||
|
||||
function Element:getHeight()
|
||||
return self._height
|
||||
end
|
||||
|
||||
function Element:setSize(width, height)
|
||||
self:setWidth(width)
|
||||
self:setHeight(height)
|
||||
end
|
||||
|
||||
function Element:getSize()
|
||||
return self:getWidth(), self:getHeight()
|
||||
end
|
||||
|
||||
function Element:setPos(x, y)
|
||||
self:setX(x)
|
||||
self:setY(y)
|
||||
end
|
||||
|
||||
function Element:getPos()
|
||||
return self._x, self._y
|
||||
end
|
||||
|
||||
function Element:getAbsolutePos(x, y)
|
||||
x = x == nil and self:getX() or x + self:getX()
|
||||
y = y == nil and self:getY() or y + self:getY()
|
||||
|
||||
if self:hasParent() then
|
||||
x, y = self:getParent():getAbsolutePos(x, y)
|
||||
end
|
||||
|
||||
return x, y
|
||||
end
|
||||
|
||||
function Element:getBounds()
|
||||
return self:getX(), self:getY(), self:getX() + self:getWidth(), self:getY() + self:getHeight()
|
||||
end
|
||||
|
||||
function Element:getAbsoluteBounds()
|
||||
local aX, aY = self:getAbsolutePos()
|
||||
|
||||
return aX, aY, aX + self:getWidth(), aY + self:getHeight()
|
||||
end
|
||||
|
||||
function Element:setEnabled(enabled)
|
||||
self._enabled = enabled
|
||||
end
|
||||
|
||||
function Element:isEnabled()
|
||||
return self._enabled
|
||||
end
|
||||
|
||||
function Element:setVisible(visible)
|
||||
self._visible = visible
|
||||
end
|
||||
|
||||
function Element:isVisible()
|
||||
return self._visible
|
||||
end
|
||||
|
||||
function Element:setDraggable(draggable)
|
||||
self._draggable = draggable
|
||||
end
|
||||
|
||||
function Element:isDraggable()
|
||||
return self._draggable
|
||||
end
|
||||
|
||||
function Element:isHovered()
|
||||
return self._hovered
|
||||
end
|
||||
|
||||
function Element:setParent(parent)
|
||||
checkVarClass(parent, Element)
|
||||
|
||||
self._parent = parent
|
||||
end
|
||||
|
||||
function Element:getParent()
|
||||
return self._parent
|
||||
end
|
||||
|
||||
function Element:hasParent()
|
||||
return self:getParent() ~= nil
|
||||
end
|
||||
|
||||
function Element:addChild(child)
|
||||
checkVarClass(child, Element)
|
||||
|
||||
child:setParent(self)
|
||||
child:_setSkin(self._skin)
|
||||
|
||||
if not self._firstChild then
|
||||
self._firstChild = child
|
||||
else
|
||||
local temp = self._firstChild
|
||||
|
||||
while temp._nextSibling do
|
||||
temp = temp._nextSibling
|
||||
end
|
||||
|
||||
temp._nextSibling = child
|
||||
child._prevSibling = temp
|
||||
end
|
||||
end
|
||||
|
||||
function Element:requestFocus()
|
||||
--return
|
||||
end
|
||||
|
||||
function Element:hasFocus()
|
||||
--return self._focus
|
||||
end
|
||||
|
||||
function Element:cursorIntersect(x, y)
|
||||
--local self:getAbsoluteBounds()
|
||||
local aX, aY = self:getAbsolutePos()
|
||||
|
||||
if x >= aX and x <= aX + self:getWidth() and y >= aY and y <= aY + self:getHeight() then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function Element:moveToFront(child)
|
||||
if child then
|
||||
local next = child._nextSibling
|
||||
local prev = child._prevSibling
|
||||
|
||||
if prev then
|
||||
prev._nextSibling = next
|
||||
|
||||
if next then
|
||||
next._prevSibling = prev
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
child._nextSibling = self._firstChild
|
||||
self._firstChild._prevSibling = child
|
||||
child._prevSibling = nil
|
||||
self._firstChild = child
|
||||
end
|
||||
end
|
||||
|
||||
-- PROTECTED
|
||||
|
||||
function Element:_setSkin(skin)
|
||||
self._skin = skin
|
||||
end
|
||||
|
||||
function Element:_postEvent(eventKey, ...)
|
||||
if eventKey == "THINK" then
|
||||
return self:_onThink()
|
||||
elseif eventKey == "PAINT" then
|
||||
return self:_onPaint()
|
||||
elseif eventKey == "MOUSE_PRESSED" then
|
||||
return self:_onMousePressed(...)
|
||||
elseif eventKey == "MOUSE_RELEASED" then
|
||||
return self:_onMouseReleased(...)
|
||||
elseif eventKey == "MOUSE_MOVED" then
|
||||
return self:_onMouseMoved(...)
|
||||
end
|
||||
end
|
||||
|
||||
function Element:_postEventToAll(eventKey, ...)
|
||||
local temp = self._firstChild
|
||||
|
||||
while temp do
|
||||
local next = temp._nextSibling
|
||||
|
||||
if temp:_postEvent(eventKey, ...) then
|
||||
return temp
|
||||
end
|
||||
|
||||
temp = next
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function Element:_postEventToAllReverse(eventKey, ...)
|
||||
local next = self._nextSibling
|
||||
|
||||
if next then
|
||||
next:_postEventToAllReverse(eventKey, ...)
|
||||
end
|
||||
|
||||
self:_postEvent(eventKey, ...)
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function Element:_onThink()
|
||||
if self:isEnabled() then
|
||||
if type(self.think) == "function" then
|
||||
self:think()
|
||||
end
|
||||
|
||||
if self._firstChild then
|
||||
self._firstChild:_postEventToAllReverse("THINK")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Element:_onPaint()
|
||||
if self:isVisible() then
|
||||
--[[
|
||||
if self:hasParent() then
|
||||
render.enableScissorRect(self:getParent():getBounds())
|
||||
end
|
||||
]]
|
||||
|
||||
self:paint()
|
||||
|
||||
if self._firstChild then
|
||||
self._firstChild:_postEventToAllReverse("PAINT")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Element:_onMousePressed(x, y, key, keyName)
|
||||
if self:cursorIntersect(x, y) and self:isEnabled() then
|
||||
local element = self:_postEventToAll("MOUSE_PRESSED", x, y, key, keyName)
|
||||
|
||||
if not element then
|
||||
self:onMousePressed(x, y, key, keyName)
|
||||
|
||||
if self:hasParent() then
|
||||
self:getParent():moveToFront(self)
|
||||
end
|
||||
|
||||
-- focus
|
||||
end
|
||||
|
||||
return true
|
||||
else
|
||||
-- unfocus
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function Element:_onMouseReleased(x, y, key, keyName)
|
||||
if self:cursorIntersect(x, y) and self:isEnabled() then
|
||||
local element = self:_postEventToAll("MOUSE_RELEASED", x, y, key, keyName)
|
||||
|
||||
if not element then
|
||||
self:onMouseReleased(x, y, key, keyName)
|
||||
end
|
||||
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function Element:_onMouseMoved(x, y)
|
||||
if self:cursorIntersect(x, y) and self:isEnabled() then
|
||||
local element = self:_postEventToAll("MOUSE_MOVED", x, y)
|
||||
|
||||
if not element then
|
||||
if not self:isHovered() then
|
||||
self._hovered = true
|
||||
|
||||
self:onMouseEnter()
|
||||
end
|
||||
|
||||
self:onMouseMoved(x, y)
|
||||
end
|
||||
|
||||
return true
|
||||
else
|
||||
if self:isHovered() then
|
||||
self._hovered = false
|
||||
|
||||
self:onMouseLeave()
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function Element:_onButtonPressed(key, keyName)
|
||||
end
|
||||
|
||||
function Element:_onButtonReleased(key, keyName)
|
||||
end
|
||||
|
||||
-- STUB
|
||||
|
||||
function Element:performLayout()
|
||||
end
|
||||
|
||||
function Element:paint()
|
||||
end
|
||||
|
||||
function Element:onMousePressed(x, y, key, keyName)
|
||||
end
|
||||
|
||||
function Element:onMouseReleased(x, y, key, keyName)
|
||||
end
|
||||
|
||||
function Element:onMouseMoved(x, y)
|
||||
end
|
||||
|
||||
function Element:onMouseEnter()
|
||||
end
|
||||
|
||||
function Element:onMouseLeave()
|
||||
end
|
||||
|
||||
function Element:onButtonPressed(key, keyName)
|
||||
end
|
||||
|
||||
function Element:onButtonReleased(key, keyName)
|
||||
end
|
||||
7
koptilnya/gui/elements/empty.txt
Normal file
7
koptilnya/gui/elements/empty.txt
Normal file
@ -0,0 +1,7 @@
|
||||
--@include element.txt
|
||||
--@include ../utils.txt
|
||||
|
||||
require("element.txt")
|
||||
require("../utils.txt")
|
||||
|
||||
EEmpty = class("EEmpty", Element)
|
||||
58
koptilnya/gui/elements/label.txt
Normal file
58
koptilnya/gui/elements/label.txt
Normal file
@ -0,0 +1,58 @@
|
||||
--@include element.txt
|
||||
--@include ../utils.txt
|
||||
|
||||
require("element.txt")
|
||||
require("../utils.txt")
|
||||
|
||||
ELabel = class("ELabel", Element)
|
||||
|
||||
accessorFunc(ELabel, "_color", "Color", Color(255, 255, 255))
|
||||
accessorFunc(ELabel, "_disabledColor", "DisabledColor", Color(200, 200, 200))
|
||||
|
||||
function ELabel:initialize()
|
||||
Element.initialize(self)
|
||||
self._text = ""
|
||||
self._textWidth = 0
|
||||
self._textHeight = 0
|
||||
|
||||
self:setFont("Trebuchet18")
|
||||
self:setText("Label")
|
||||
end
|
||||
|
||||
function ELabel:setText(text)
|
||||
self._text = tostring(text)
|
||||
|
||||
if self:getFont() then
|
||||
render.setFont(self:getFont())
|
||||
|
||||
self._textWidth, self._textHeight = render.getTextSize(self:getText())
|
||||
end
|
||||
end
|
||||
|
||||
function ELabel:getText()
|
||||
return self._text
|
||||
end
|
||||
|
||||
function ELabel:setFont(font)
|
||||
self._font = font
|
||||
|
||||
render.setFont(self:getFont())
|
||||
|
||||
self._textWidth, self._textHeight = render.getTextSize(self:getText())
|
||||
end
|
||||
|
||||
function ELabel:getFont()
|
||||
return self._font
|
||||
end
|
||||
|
||||
function ELabel:getTextSize()
|
||||
return self._textWidth, self._textHeight
|
||||
end
|
||||
|
||||
function ELabel:paint()
|
||||
local x, y = self:getAbsolutePos()
|
||||
|
||||
render.setFont(self:getFont())
|
||||
render.setColor(self:isEnabled() and self:getColor() or self:getDisabledColor())
|
||||
render.drawSimpleText(x, y, self:getText())
|
||||
end
|
||||
112
koptilnya/gui/elements/panel.txt
Normal file
112
koptilnya/gui/elements/panel.txt
Normal file
@ -0,0 +1,112 @@
|
||||
--@include element.txt
|
||||
--@include label.txt
|
||||
--@include button.txt
|
||||
--@include ../utils.txt
|
||||
|
||||
require("element.txt")
|
||||
require("label.txt")
|
||||
require("button.txt")
|
||||
require("../utils.txt")
|
||||
|
||||
EPanel = class("EPanel", Element)
|
||||
|
||||
accessorFunc(EPanel, "_backgroundColor", "BackgroundColor", Color(23, 23, 23))
|
||||
accessorFunc(EPanel, "_parentLock", "ParentLock", false)
|
||||
|
||||
function EPanel:initialize()
|
||||
Element.initialize(self)
|
||||
|
||||
self._minimized = false
|
||||
|
||||
self.title = ELabel:new()
|
||||
self.title:setPos(12, 8)
|
||||
self:addChild(self.title)
|
||||
|
||||
self.minimizeButton = EButton:new()
|
||||
self.minimizeButton:setText("_")
|
||||
self.minimizeButton:setSize(32, 32)
|
||||
self.minimizeButton:setRadius(0)
|
||||
self.minimizeButton:setColor(Color(0, 0, 0))
|
||||
self.minimizeButton:setHoveredColor(Color(25, 25, 25))
|
||||
self:addChild(self.minimizeButton)
|
||||
|
||||
self.closeButton = EButton:new()
|
||||
self.closeButton:setText("X")
|
||||
self.closeButton:setSize(32, 32)
|
||||
self.closeButton:setRadius(0)
|
||||
self.closeButton:setColor(Color(0, 0, 0))
|
||||
self.closeButton:setHoveredColor(Color(25, 25, 25))
|
||||
self:addChild(self.closeButton)
|
||||
|
||||
self:setTitle("Panel")
|
||||
end
|
||||
|
||||
function EPanel:setTitle(title)
|
||||
self.title:setText(title)
|
||||
end
|
||||
|
||||
function EPanel:getTitle()
|
||||
return self.title:getText()
|
||||
end
|
||||
|
||||
function EPanel:setMinimized(state)
|
||||
self._minimized = state
|
||||
end
|
||||
|
||||
function EPanel:isMinimized()
|
||||
return self._minimized
|
||||
end
|
||||
|
||||
function EPanel:onMousePressed(x, y, key, keyName)
|
||||
if keyName == "MOUSE1" then
|
||||
local aX, aY = self:getAbsolutePos()
|
||||
|
||||
if self:isDraggable() and y < aY + 33 then
|
||||
self._dragStartPos = {x - self:getX(), y - self:getY()}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function EPanel:onMouseReleased(x, y, key, keyName)
|
||||
if keyName == "MOUSE1" then
|
||||
if self:isDraggable() then
|
||||
self._dragStartPos = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function EPanel:onMouseMoved(x, y)
|
||||
if self._dragStartPos then
|
||||
local targetX, targetY = x - self._dragStartPos[1], y - self._dragStartPos[2]
|
||||
|
||||
if self:hasParent() and self:getParentLock() then
|
||||
targetX = math.clamp(targetX, 0, 1920 - self:getWidth())
|
||||
targetY = math.clamp(targetY, 0, 1080 - self:getHeight())
|
||||
end
|
||||
|
||||
self:setPos(targetX, targetY)
|
||||
end
|
||||
end
|
||||
|
||||
function EPanel:onMouseLeave()
|
||||
self._dragStartPos = nil
|
||||
end
|
||||
|
||||
function EPanel:performLayout(w, h)
|
||||
self.closeButton:setPos(w - 33, 1)
|
||||
self.minimizeButton:setPos(w - 65, 1)
|
||||
end
|
||||
|
||||
function EPanel:paint()
|
||||
local x, y = self:getAbsolutePos()
|
||||
local w, h = self:getSize()
|
||||
|
||||
render.setColor(Color(255, 255, 255, 10))
|
||||
render.drawRectFast(x, y, w, h)
|
||||
|
||||
render.setColor(Color(0, 0, 0))
|
||||
render.drawRectFast(x + 1, y + 1, w - 2, 32)
|
||||
|
||||
render.setColor(self:getBackgroundColor())
|
||||
render.drawRectFast(x + 1, y + 33, w - 2, h - 34)
|
||||
end
|
||||
49
koptilnya/gui/elements/radius_mixin.txt
Normal file
49
koptilnya/gui/elements/radius_mixin.txt
Normal file
@ -0,0 +1,49 @@
|
||||
--@include ../utils.txt
|
||||
|
||||
require("../utils.txt")
|
||||
|
||||
local MIXIN = {}
|
||||
|
||||
accessorFunc(MIXIN, "_radius", "Radius", 0)
|
||||
|
||||
function MIXIN:included(target)
|
||||
self._roundTopLeftCorner = false
|
||||
self._roundTopRightCorner = false
|
||||
self._roundBottomLeftCorner = false
|
||||
self._roundBottomRightCorner = false
|
||||
end
|
||||
|
||||
function MIXIN:setRoundedCorners(c1, c2, c3, c4)
|
||||
if c1 ~= nil and c2 ~= nil and c3 ~= nil and c4 ~= nil then
|
||||
self._roundTopLeftCorner = c1
|
||||
self._roundTopRightCorner = c2
|
||||
self._roundBottomRightCorner = c3
|
||||
self._roundBottomLeftCorner = c4
|
||||
elseif c1 ~= nil and c2 ~= nil and c3 ~= nil then
|
||||
self._roundTopLeftCorner = c1
|
||||
self._roundTopRightCorner = c2
|
||||
self._roundBottomRightCorner = c3
|
||||
self._roundBottomLeftCorner = c2
|
||||
elseif c1 ~= nil and c2 ~= nil then
|
||||
self._roundTopLeftCorner = c1
|
||||
self._roundTopRightCorner = c2
|
||||
self._roundBottomRightCorner = c1
|
||||
self._roundBottomLeftCorner = c2
|
||||
elseif c1 ~= nil then
|
||||
self._roundTopLeftCorner = c1
|
||||
self._roundTopRightCorner = c1
|
||||
self._roundBottomRightCorner = c1
|
||||
self._roundBottomLeftCorner = c1
|
||||
else
|
||||
self._roundTopLeftCorner = false
|
||||
self._roundTopRightCorner = false
|
||||
self._roundBottomRightCorner = false
|
||||
self._roundBottomLeftCorner = false
|
||||
end
|
||||
end
|
||||
|
||||
function MIXIN:getRoundedCorners()
|
||||
return self._roundTopLeftCorner, self._roundTopRightCorner, self._roundBottomRightCorner, self._roundBottomLeftCorner
|
||||
end
|
||||
|
||||
return MIXIN
|
||||
5
koptilnya/gui/elements/root.txt
Normal file
5
koptilnya/gui/elements/root.txt
Normal file
@ -0,0 +1,5 @@
|
||||
--@include element.txt
|
||||
|
||||
require("element.txt")
|
||||
|
||||
ERoot = class("ERoot", Element)
|
||||
17
koptilnya/gui/elements/shape.txt
Normal file
17
koptilnya/gui/elements/shape.txt
Normal file
@ -0,0 +1,17 @@
|
||||
--@include element.txt
|
||||
--@include ../utils.txt
|
||||
|
||||
require("element.txt")
|
||||
require("../utils.txt")
|
||||
|
||||
EShape = class("EShape", Element)
|
||||
|
||||
accessorFunc(EShape, "_color", "Color", Color(255, 255, 255))
|
||||
|
||||
function EShape:paint()
|
||||
local x, y = self:getAbsolutePos()
|
||||
local w, h = self:getSize()
|
||||
|
||||
render.setColor(self:getColor())
|
||||
render.drawRectFast(x, y, w, h)
|
||||
end
|
||||
81
koptilnya/gui/gui.txt
Normal file
81
koptilnya/gui/gui.txt
Normal file
@ -0,0 +1,81 @@
|
||||
--@include utils.txt
|
||||
--@include render_devices/render_device.txt
|
||||
--@include elements/root.txt
|
||||
--@include skins/default.txt
|
||||
|
||||
require("utils.txt")
|
||||
require("render_devices/render_device.txt")
|
||||
require("elements/root.txt")
|
||||
local defaultSkin = require("skins/default.txt")
|
||||
|
||||
GUI = class("GUI")
|
||||
|
||||
function GUI:initialize(renderDevice, skin)
|
||||
checkVarClass(renderDevice, RenderDevice)
|
||||
|
||||
self.renderDevice = renderDevice
|
||||
self._root = ERoot:new("root")
|
||||
self._root:setSize(renderDevice:getSize())
|
||||
self._root:_setSkin(skin or defaultSkin)
|
||||
|
||||
hook.add("inputPressed", "gui_inputPressed", function(key)
|
||||
local keyName = input.getKeyName(key)
|
||||
|
||||
if key >= 107 and key <= 111 then
|
||||
local x, y = input.getCursorPos()
|
||||
|
||||
self._root:_postEvent("MOUSE_PRESSED", x, y, key, keyName)
|
||||
else
|
||||
self._root:_postEvent("BUTTON_PRESSED", x, y, key, keyName)
|
||||
end
|
||||
end)
|
||||
|
||||
hook.add("inputReleased", "gui_inputReleased", function(key)
|
||||
local keyName = input.getKeyName(key)
|
||||
|
||||
if key >= 107 and key <= 111 then
|
||||
local x, y = input.getCursorPos()
|
||||
|
||||
self._root:_postEvent("MOUSE_RELEASED", x, y, key, keyName)
|
||||
else
|
||||
self._root:_postEvent("BUTTON_RELEASED", x, y, key, keyName)
|
||||
end
|
||||
end)
|
||||
|
||||
self._lastMouseX = 0
|
||||
self._lastMouseY = 0
|
||||
hook.add("think", "gui_think", function()
|
||||
if input.getCursorVisible then
|
||||
local x, y = input.getCursorPos()
|
||||
|
||||
if x ~= self._lastMouseX or y ~= self._lastMouseY then
|
||||
self._lastMouseX = x
|
||||
self._lastMouseY = y
|
||||
|
||||
self._root:_postEvent("MOUSE_MOVED", x, y)
|
||||
end
|
||||
end
|
||||
|
||||
self._root:_postEvent("THINK")
|
||||
end)
|
||||
|
||||
renderDevice.render = function()
|
||||
self._root:_postEvent("PAINT")
|
||||
end
|
||||
end
|
||||
|
||||
function GUI:getRoot()
|
||||
return self._root
|
||||
end
|
||||
|
||||
function GUI:add(element)
|
||||
this._root:addChild(element)
|
||||
end
|
||||
|
||||
function GUI:setVisible(state)
|
||||
self._root:setVisible(state)
|
||||
end
|
||||
|
||||
function GUI:isVisible()
|
||||
self._root:isVisible()
|
||||
end
|
||||
18
koptilnya/gui/render_devices/hud.txt
Normal file
18
koptilnya/gui/render_devices/hud.txt
Normal file
@ -0,0 +1,18 @@
|
||||
--@include render_device.txt
|
||||
|
||||
require("render_device.txt")
|
||||
|
||||
RenderDeviceHUD = class("RenderDeviceHUD", RenderDevice)
|
||||
|
||||
function RenderDeviceHUD:initialize()
|
||||
render.setHUDActive(true)
|
||||
self:setSize(render.getResolution())
|
||||
|
||||
hook.add("hudshoulddraw", "gui_hudshoulddraw", function(name)
|
||||
return name == "CHudGMod" or name == "CHudChat"
|
||||
end)
|
||||
|
||||
hook.add("postdrawhud", "gui_renderer", function()
|
||||
self:render()
|
||||
end)
|
||||
end
|
||||
28
koptilnya/gui/render_devices/render_device.txt
Normal file
28
koptilnya/gui/render_devices/render_device.txt
Normal file
@ -0,0 +1,28 @@
|
||||
--@include ../utils.txt
|
||||
|
||||
require("../utils.txt")
|
||||
|
||||
RenderDevice = class("RenderDevice")
|
||||
|
||||
accessorFunc(RenderDevice, "_width", "Width", 0)
|
||||
accessorFunc(RenderDevice, "_height", "Height", 0)
|
||||
|
||||
function RenderDevice:setHeight(height)
|
||||
self._height = height
|
||||
end
|
||||
|
||||
function RenderDevice:getHeight()
|
||||
return self._height
|
||||
end
|
||||
|
||||
function RenderDevice:setSize(width, height)
|
||||
self:setWidth(width)
|
||||
self:setHeight(height)
|
||||
end
|
||||
|
||||
function RenderDevice:getSize()
|
||||
return self:getWidth(), self:getHeight()
|
||||
end
|
||||
|
||||
function RenderDevice:render()
|
||||
end
|
||||
13
koptilnya/gui/render_devices/screen.txt
Normal file
13
koptilnya/gui/render_devices/screen.txt
Normal file
@ -0,0 +1,13 @@
|
||||
--@include render_device.txt
|
||||
|
||||
require("render_device.txt")
|
||||
|
||||
RenderDeviceScreen = class("RenderDeviceScreen", RenderDevice)
|
||||
|
||||
function RenderDeviceScreen:initialize()
|
||||
self:setSize(512, 512)
|
||||
|
||||
hook.add("render", "gui_renderer", function()
|
||||
self:render()
|
||||
end)
|
||||
end
|
||||
5
koptilnya/gui/skins/default.txt
Normal file
5
koptilnya/gui/skins/default.txt
Normal file
@ -0,0 +1,5 @@
|
||||
local SKIN = {}
|
||||
|
||||
-- :(
|
||||
|
||||
return SKIN
|
||||
0
koptilnya/libs/render.txt
Normal file
0
koptilnya/libs/render.txt
Normal file
11
koptilnya/libs/utils.txt
Normal file
11
koptilnya/libs/utils.txt
Normal file
@ -0,0 +1,11 @@
|
||||
function checkVarClass(var, class, message)
|
||||
if type(var) ~= "table" or var["class"] == nil or not var:isInstanceOf(class) then
|
||||
throw(message == nil and "Wrong variable class." or message, 1, true)
|
||||
end
|
||||
end
|
||||
|
||||
function accessorFunc(tbl, varName, name, defaultValue)
|
||||
tbl[varName] = defaultValue
|
||||
tbl["get" .. name] = function(self) return self[varName] end
|
||||
tbl["set" .. name] = function(self, value) self[varName] = value end
|
||||
end
|
||||
5
koptilnya/mesh_loader/base_entity.txt
Normal file
5
koptilnya/mesh_loader/base_entity.txt
Normal file
@ -0,0 +1,5 @@
|
||||
BaseEntity = class("BaseEntity")
|
||||
|
||||
function BaseEntity:initialize()
|
||||
|
||||
end
|
||||
153
koptilnya/mesh_loader/builder.txt
Normal file
153
koptilnya/mesh_loader/builder.txt
Normal file
@ -0,0 +1,153 @@
|
||||
local MODEL_PLACEHOLDER = "models/holograms/cube.mdl"
|
||||
local BUNDLE_SIZE = 30
|
||||
local SEND_DELAY = 2
|
||||
|
||||
MeshBuilder = class("MeshBuilder")
|
||||
|
||||
function MeshBuilder:initialize()
|
||||
self._objects = {}
|
||||
self._bundle = {}
|
||||
|
||||
if CLIENT then
|
||||
self._meshData = {}
|
||||
|
||||
net.receive("sendHolograms", function(len)
|
||||
local hasNext = net.readBit()
|
||||
|
||||
while hasNext == 1 do
|
||||
local key = net.readString()
|
||||
|
||||
net.readEntity(function(ent)
|
||||
if not self._objects[key] then
|
||||
|
||||
local holo = ent:toHologram()
|
||||
|
||||
if self._meshData[key] then
|
||||
holo:setMesh(self._meshData[key])
|
||||
holo:setRenderBounds(Vector(-200), Vector(200))
|
||||
end
|
||||
|
||||
self._objects[key] = holo
|
||||
end
|
||||
end)
|
||||
|
||||
hasNext = net.readBit()
|
||||
end
|
||||
end)
|
||||
else
|
||||
|
||||
net.receive("sendObjects", function(len, ply)
|
||||
local hasNext = net.readBit()
|
||||
|
||||
while hasNext == 1 do
|
||||
local key = net.readString()
|
||||
local pos = net.readVector()
|
||||
local ang = net.readAngle()
|
||||
local scale = net.readVector()
|
||||
local color = net.readColor()
|
||||
local mat = net.readString()
|
||||
local parent = net.readEntity()
|
||||
|
||||
if not self._objects[key] then
|
||||
if isValid(parent) then
|
||||
pos = parent:localToWorld(pos)
|
||||
ang = parent:localToWorldAngles(ang)
|
||||
end
|
||||
|
||||
local holo = holograms.create(pos, ang, MODEL_PLACEHOLDER, scale)
|
||||
holo:setColor(color)
|
||||
holo:setMaterial(mat)
|
||||
holo:setParent(parent)
|
||||
|
||||
self._objects[key] = holo
|
||||
end
|
||||
|
||||
if not self._bundle[key] then
|
||||
self._bundle[key] = self._objects[key]
|
||||
end
|
||||
|
||||
hasNext = net.readBit()
|
||||
end
|
||||
|
||||
net.start("sendHolograms")
|
||||
for k, v in pairs(self._bundle) do
|
||||
if isValid(v) and type(v) == "Hologram" then
|
||||
net.writeBit(1)
|
||||
net.writeString(k)
|
||||
net.writeEntity(v)
|
||||
end
|
||||
end
|
||||
net.writeBit(0)
|
||||
net.send(ply)
|
||||
|
||||
table.empty(self._bundle)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
function MeshBuilder:setMeshData(meshData)
|
||||
self._meshData = meshData
|
||||
end
|
||||
|
||||
function MeshBuilder:setup(key, pos, ang, scale, color, mat, parent)
|
||||
if not self._objects[key] and not self._bundle[key] and self._meshData[key] then
|
||||
self._bundle[key] = {
|
||||
pos = pos,
|
||||
ang = ang,
|
||||
scale = scale,
|
||||
color = color,
|
||||
mat = mat,
|
||||
parent = isValid(parent) and parent or chip()
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function MeshBuilder:setupAll(pos, ang, scale, color, mat, parent)
|
||||
for _, v in pairs(table.getKeys(self._meshData)) do
|
||||
self:setup(v, pos, ang, scale, color, mat, parent)
|
||||
end
|
||||
end
|
||||
|
||||
function MeshBuilder:build()
|
||||
local function send(objects)
|
||||
net.start("sendObjects")
|
||||
for k, v in pairs(objects) do
|
||||
net.writeBit(1)
|
||||
net.writeString(k)
|
||||
net.writeVector(v.pos)
|
||||
net.writeAngle(v.ang)
|
||||
net.writeVector(v.scale)
|
||||
net.writeColor(v.color)
|
||||
net.writeString(v.mat)
|
||||
net.writeEntity(v.parent)
|
||||
end
|
||||
net.writeBit(0)
|
||||
net.send()
|
||||
end
|
||||
|
||||
local bundleKeys = table.getKeys(self._bundle)
|
||||
if #bundleKeys > BUNDLE_SIZE then
|
||||
local i = 1
|
||||
|
||||
timer.create("send", SEND_DELAY, math.ceil(#bundleKeys / BUNDLE_SIZE), function()
|
||||
local from = (i - 1) * BUNDLE_SIZE + 1
|
||||
local objects = {}
|
||||
|
||||
for _, v in pairs({ unpack(bundleKeys, from, from + BUNDLE_SIZE - 1) }) do
|
||||
objects[v] = self._bundle[v]
|
||||
end
|
||||
|
||||
send(objects)
|
||||
|
||||
if i < math.ceil(#bundleKeys / BUNDLE_SIZE) then
|
||||
i = i + 1
|
||||
else
|
||||
table.empty(self._bundle)
|
||||
end
|
||||
end)
|
||||
else
|
||||
send(self._bundle)
|
||||
end
|
||||
end
|
||||
end
|
||||
36
koptilnya/mesh_loader/parser.txt
Normal file
36
koptilnya/mesh_loader/parser.txt
Normal file
@ -0,0 +1,36 @@
|
||||
local MAX_QUOTA = 0.75
|
||||
|
||||
Parser = class("Parser")
|
||||
|
||||
function Parser:initialize(link)
|
||||
if CLIENT then
|
||||
local triangles = mesh.trianglesLeft()
|
||||
local createFromObjCoroutine = coroutine.create(function(objData)
|
||||
self:OnLoaded(objData, mesh.createFromObj(objData, true))
|
||||
end)
|
||||
|
||||
print("Getting file...")
|
||||
http.get(link, function(objData)
|
||||
local loadMesh = coroutine.wrap(function()
|
||||
self.meshData = mesh.createFromObj(objData, true)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
print("File received, start parsing...")
|
||||
hook.add("think", "loadingMesh", function()
|
||||
while quotaAverage() < quotaMax() * MAX_QUOTA do
|
||||
if loadMesh() then
|
||||
self:onLoaded(objData, self.meshData, triangles - mesh.trianglesLeft())
|
||||
hook.remove("think", "loadingMesh")
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function Parser:onLoaded(objData, meshData, usedTriangles)
|
||||
end
|
||||
32
koptilnya/rpc.txt
Normal file
32
koptilnya/rpc.txt
Normal file
@ -0,0 +1,32 @@
|
||||
--@name RPC
|
||||
--@author Opti1337
|
||||
--@shared
|
||||
|
||||
RPC = {}
|
||||
|
||||
function RPC.add(name, cb)
|
||||
net.receive(name, function()
|
||||
local result = {}
|
||||
|
||||
for i = 1, net.readInt(8) do
|
||||
table.insert(result, net.readType())
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
cb(unpack(result))
|
||||
else
|
||||
RPC.start(name, find.allPlayers(), unpack(result))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function RPC.start(name, target, ...)
|
||||
net.start(name)
|
||||
local args = {...}
|
||||
|
||||
net.writeInt(#args, 8)
|
||||
for _, v in pairs(args) do
|
||||
net.writeType(v)
|
||||
end
|
||||
net.send(target)
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user