Pulled from master, fixed conflict
This commit is contained in:
commit
81fd1c0f3e
@ -1,5 +0,0 @@
|
|||||||
Anchor = class("Anchor")
|
|
||||||
|
|
||||||
function Anchor:initialize(pos, ang, parent, relativeTo)
|
|
||||||
|
|
||||||
end
|
|
||||||
@ -1,132 +0,0 @@
|
|||||||
-- @name Engine
|
|
||||||
-- @author DarkSupah, Opti1337, .hemp
|
|
||||||
-- @shared
|
|
||||||
-- @include ../libs/constants.txt
|
|
||||||
-- @include ./engine.txt
|
|
||||||
-- @include ./gearbox.txt
|
|
||||||
-- @include ./input.txt
|
|
||||||
require("../libs/constants.txt")
|
|
||||||
require("./engine.txt")
|
|
||||||
require("./gearbox.txt")
|
|
||||||
require("./input.txt")
|
|
||||||
|
|
||||||
local configPath = "engine/"
|
|
||||||
|
|
||||||
local inputConfigPath = "input.json"
|
|
||||||
local engineConfigPath = "engine.json"
|
|
||||||
local gearboxConfigPath = "gearbox.json"
|
|
||||||
|
|
||||||
Controller = class("Controller")
|
|
||||||
|
|
||||||
function Controller:initialize(inputController, engine, gearbox, axles)
|
|
||||||
self.inputController = inputController
|
|
||||||
self.engine = engine
|
|
||||||
self.gearbox = gearbox
|
|
||||||
self.axles = axles
|
|
||||||
|
|
||||||
if SERVER then
|
|
||||||
hook.add("PlayerEnteredVehicle", "enterHandler", function(ply, vehicle)
|
|
||||||
if (vehicle == wire.ports.Seat) then
|
|
||||||
self.inputController:setPlayer(ply)
|
|
||||||
hook.run("DriverChanged", ply)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
hook.add("PlayerLeaveVehicle", "exitHandler", function(ply, vehicle)
|
|
||||||
if (vehicle == wire.ports.Seat) then
|
|
||||||
self.inputController:setPlayer(NULL_ENTITY)
|
|
||||||
hook.run("DriverChanged", NULL_ENTITY)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
net.receive("serverConfigs", function()
|
|
||||||
local inputConfig = net.readTable()
|
|
||||||
local engineConfig = net.readTable()
|
|
||||||
local gearboxConfig = net.readTable()
|
|
||||||
|
|
||||||
self.inputController:setConfig(inputConfig)
|
|
||||||
self.engine:setConfig(engineConfig)
|
|
||||||
self.gearbox:setConfig(gearboxConfig)
|
|
||||||
|
|
||||||
net.start("clientConfigs")
|
|
||||||
net.writeTable(inputConfig)
|
|
||||||
net.writeTable(engineConfig)
|
|
||||||
net.writeTable(gearboxConfig)
|
|
||||||
net.send()
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
if CLIENT then
|
|
||||||
net.receive("clientConfigs", function()
|
|
||||||
self.inputController:setConfig(net.readTable())
|
|
||||||
self.engine:setConfig(net.readTable())
|
|
||||||
self.gearbox:setConfig(net.readTable())
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function Controller:update()
|
|
||||||
self.inputController:update()
|
|
||||||
self.engine:update()
|
|
||||||
self.gearbox:update()
|
|
||||||
|
|
||||||
self.engine:setThrottle(self.inputController.throttle.value)
|
|
||||||
end
|
|
||||||
|
|
||||||
local inputController = InputController:new()
|
|
||||||
|
|
||||||
local engine = Engine:new()
|
|
||||||
local gearbox = Gearbox:new()
|
|
||||||
|
|
||||||
local controller = Controller:new(inputController, engine, gearbox)
|
|
||||||
|
|
||||||
if SERVER then
|
|
||||||
wire.adjustPorts({
|
|
||||||
Seat = "entity"
|
|
||||||
}, {
|
|
||||||
Input = "table",
|
|
||||||
Engine = "table"
|
|
||||||
})
|
|
||||||
|
|
||||||
if wire.ports.Seat:isValid() then
|
|
||||||
local possibleDriver = wire.ports.Seat:getDriver()
|
|
||||||
|
|
||||||
if possibleDriver:isValid() then
|
|
||||||
controller.inputController:setPlayer(possibleDriver)
|
|
||||||
wire.ports.Driver = possibleDriver
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
hook.add("DriverChanged", "driverChangeHandler", function(ply)
|
|
||||||
wire.ports.Driver = ply
|
|
||||||
end)
|
|
||||||
|
|
||||||
hook.add("tick", "update", function()
|
|
||||||
controller:update()
|
|
||||||
|
|
||||||
wire.ports.Engine = controller.engine
|
|
||||||
wire.ports.Input = controller.inputController
|
|
||||||
|
|
||||||
end)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
if CLIENT then
|
|
||||||
if CURRENT_PLAYER == OWNER then
|
|
||||||
local inputConfigFile = file.read(configPath .. inputConfigPath)
|
|
||||||
local inputConfig = json.decode(inputConfigFile)
|
|
||||||
|
|
||||||
local engineConfigFile = file.read(configPath .. engineConfigPath)
|
|
||||||
local engineConfig = json.decode(engineConfigFile)
|
|
||||||
|
|
||||||
local gearboxConfigFile = file.read(configPath .. gearboxConfigPath)
|
|
||||||
local gearboxConfig = json.decode(gearboxConfigFile)
|
|
||||||
|
|
||||||
net.start("serverConfigs")
|
|
||||||
net.writeTable(inputConfig)
|
|
||||||
net.writeTable(engineConfig)
|
|
||||||
net.writeTable(gearboxConfig)
|
|
||||||
net.send()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
-- @include ./math.txt
|
|
||||||
require("./math.txt")
|
|
||||||
|
|
||||||
Engine = class("Engine")
|
|
||||||
|
|
||||||
function Engine:initialize()
|
|
||||||
self.config = {}
|
|
||||||
|
|
||||||
if SERVER then
|
|
||||||
self.active = true
|
|
||||||
|
|
||||||
self.desiredRPM = 0
|
|
||||||
self.RPM = 0
|
|
||||||
|
|
||||||
self.throttle = 0
|
|
||||||
|
|
||||||
self.flywheelInertiaMoment = 0
|
|
||||||
self.volume = 0
|
|
||||||
self.peakTq = 0
|
|
||||||
self.torque = 0
|
|
||||||
self.power = 0
|
|
||||||
|
|
||||||
self.gearboxRPM = 0
|
|
||||||
|
|
||||||
self.torqueTable = {}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if SERVER then
|
|
||||||
|
|
||||||
function Engine:setThrottle(throttle)
|
|
||||||
self.throttle = throttle
|
|
||||||
end
|
|
||||||
|
|
||||||
function Engine:update()
|
|
||||||
-- check if config table is not empty
|
|
||||||
if next(self.config) ~= nil then
|
|
||||||
local activeCoeff = self.active and 1 or 0
|
|
||||||
|
|
||||||
self.desiredRPM = self.throttle * self.config.maxRPM + self.config.idleRPM
|
|
||||||
|
|
||||||
local masterThrottle = activeCoeff * self.RPM > self.config.maxRPM and 0 or 1
|
|
||||||
|
|
||||||
self.RPM = math.lerp(1 / (self.flywheelInertiaMoment * 100), self.RPM, self.desiredRPM * masterThrottle)
|
|
||||||
|
|
||||||
self:calculateTorque()
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function Engine:updateStats()
|
|
||||||
local bore = self.config.bore
|
|
||||||
local stroke = self.config.stroke
|
|
||||||
local flywheelMass = self.config.flywheelMass
|
|
||||||
local cylinders = self.config.cylinders
|
|
||||||
local BMEP = self.config.BMEP
|
|
||||||
|
|
||||||
self.flywheelInertiaMoment = (stroke / 1000) * flywheelMass
|
|
||||||
|
|
||||||
self.volume = math.floor((bore / 2) ^ 2 * stroke * cylinders * math.pi / 1000)
|
|
||||||
|
|
||||||
self.peakTq = (stroke / bore) * self.volume * BMEP / 100
|
|
||||||
|
|
||||||
self.torqueTable = {}
|
|
||||||
|
|
||||||
for i = 1, #self.config.curve do
|
|
||||||
table.insert(self.torqueTable, self:getTorqueValue(i / #self.config.curve))
|
|
||||||
end
|
|
||||||
|
|
||||||
print("Peak Torque: " .. math.ceil(self.peakTq) .. "nm")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Engine:calculateTorque()
|
|
||||||
local RPMfrac = math.min(1, self.RPM / self.config.maxRPM)
|
|
||||||
local tableCount = table.count(self.torqueTable)
|
|
||||||
|
|
||||||
local lerpTo = math.ceil(RPMfrac * tableCount)
|
|
||||||
local lerpFrom = math.floor(RPMfrac * tableCount)
|
|
||||||
|
|
||||||
local lerpToVal = self.torqueTable[lerpTo] or 0
|
|
||||||
local lerpFromVal = self.torqueTable[lerpFrom] or 0
|
|
||||||
|
|
||||||
local frac = (RPMfrac * tableCount) % 1
|
|
||||||
local minActiveThrottle = self.config.idleRPM / self.config.maxRPM
|
|
||||||
|
|
||||||
local value = math.lerp(frac, lerpFromVal, lerpToVal) * self.peakTq
|
|
||||||
|
|
||||||
local overdrive = math.clamp(1 - self.gearboxRPM / self.desiredRPM, -1, 0)
|
|
||||||
|
|
||||||
local idleRPM = self.config.idleRPM
|
|
||||||
local maxRPM = self.config.maxRPM
|
|
||||||
local brakeTorqueCoeff = self.config.brakeTorqueCoeff
|
|
||||||
|
|
||||||
local RPMLimiter = math.clamp(1 - self.throttle * (self.gearboxRPM / self.desiredRPM), self.throttle, 1)
|
|
||||||
local netTq = value * math.max(self.throttle, idleRPM / maxRPM) * RPMLimiter
|
|
||||||
|
|
||||||
self.torque = netTq
|
|
||||||
end
|
|
||||||
|
|
||||||
function Engine:getTorqueValue(num)
|
|
||||||
local torque = 0
|
|
||||||
|
|
||||||
for key, segment in pairs(self.config.curve) do
|
|
||||||
torque = torque + segment * polinom(key, table.count(self.config.curve), num)
|
|
||||||
end
|
|
||||||
|
|
||||||
return torque
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function Engine:setConfig(config)
|
|
||||||
self.config = config
|
|
||||||
|
|
||||||
if SERVER then
|
|
||||||
self:updateStats()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
Gearbox = class("Gearbox")
|
|
||||||
|
|
||||||
function Gearbox:initialize()
|
|
||||||
self.config = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
function Gearbox:update()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function Gearbox:setConfig(config)
|
|
||||||
self.config = config
|
|
||||||
end
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
-- @include ../libs/constants.txt
|
|
||||||
require("../libs/constants.txt")
|
|
||||||
|
|
||||||
InputController = class("InputController")
|
|
||||||
|
|
||||||
function InputController:initialize()
|
|
||||||
self.ply = NULL_ENTITY
|
|
||||||
|
|
||||||
self.config = {} -- keys and pedal speed config
|
|
||||||
|
|
||||||
if SERVER then
|
|
||||||
self.throttle = {
|
|
||||||
target = 0,
|
|
||||||
value = 0
|
|
||||||
}
|
|
||||||
self.brake = {
|
|
||||||
target = 0,
|
|
||||||
value = 0
|
|
||||||
}
|
|
||||||
self.clutch = {
|
|
||||||
target = 0,
|
|
||||||
value = 0
|
|
||||||
}
|
|
||||||
self.start = {
|
|
||||||
target = 0,
|
|
||||||
value = 0,
|
|
||||||
type = "keyPress"
|
|
||||||
}
|
|
||||||
|
|
||||||
net.receive("input", function()
|
|
||||||
local inputName = net.readString()
|
|
||||||
local target = net.readBool()
|
|
||||||
|
|
||||||
if self[inputName] then
|
|
||||||
self[inputName].target = target and (self.config[inputName] and self.config[inputName].max or 1) or 0
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
if CLIENT then
|
|
||||||
function setTargetInput(pressedKey, target)
|
|
||||||
local key = string.upper(input.getKeyName(pressedKey))
|
|
||||||
|
|
||||||
if self.keyToInputName[key] then
|
|
||||||
net.start("input")
|
|
||||||
net.writeString(self.keyToInputName[key].inputName)
|
|
||||||
net.writeBool(target)
|
|
||||||
net.send()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
hook.add("inputPressed", "inputPress", function(key)
|
|
||||||
if (self.ply ~= NULL_ENTITY and self.ply == CURRENT_PLAYER) then
|
|
||||||
setTargetInput(key, true)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
hook.add("inputReleased", "inputRelease", function(key)
|
|
||||||
if (self.ply ~= NULL_ENTITY and self.ply == CURRENT_PLAYER) then
|
|
||||||
setTargetInput(key, false)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
net.receive("changePlayer", function()
|
|
||||||
self.ply = net.readEntity()
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
if SERVER then
|
|
||||||
function InputController:setPlayer(ply)
|
|
||||||
self.ply = ply
|
|
||||||
net.start("changePlayer")
|
|
||||||
net.writeEntity(ply or NULL_ENTITY)
|
|
||||||
net.send()
|
|
||||||
end
|
|
||||||
|
|
||||||
function InputController:update()
|
|
||||||
for key in pairs(self.config) do
|
|
||||||
if self[key] then
|
|
||||||
local pressSpeed = self.config[key].press or 1
|
|
||||||
local releaseSpeed = self.config[key].release or 1
|
|
||||||
|
|
||||||
self[key].value = math.lerp(self[key].target == 1 and pressSpeed or releaseSpeed, self[key].value,
|
|
||||||
self[key].target)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function InputController:setConfig(config)
|
|
||||||
self.config = table.copy(config)
|
|
||||||
|
|
||||||
local keyToInputName = {}
|
|
||||||
|
|
||||||
for key, value in pairs(config) do
|
|
||||||
keyToInputName[string.upper(value.key)] = {
|
|
||||||
inputName = key
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
self.keyToInputName = table.copy(keyToInputName)
|
|
||||||
end
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
function factorial(number)
|
|
||||||
local res = 1
|
|
||||||
|
|
||||||
for i = 1, number do
|
|
||||||
res = i * res
|
|
||||||
end
|
|
||||||
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
function polinom(i, n, t)
|
|
||||||
return factorial(n) / (factorial(i) * factorial(n - i)) * (t ^ i) * (1 - t) ^ (n - i)
|
|
||||||
end
|
|
||||||
@ -1,48 +1,50 @@
|
|||||||
--@include libs/utils.txt
|
-- @include libs/utils.txt
|
||||||
--@client
|
-- @client
|
||||||
|
|
||||||
require("/koptilnya/libs/utils.txt")
|
require("/koptilnya/libs/utils.txt")
|
||||||
|
|
||||||
EngineSound = class("EngineSound")
|
EngineSound = class("EngineSound")
|
||||||
|
|
||||||
accessorFunc(EngineSound, "_rpm", "RPM", 0)
|
|
||||||
accessorFunc(EngineSound, "_masterVolume", "MasterVolume", 1)
|
accessorFunc(EngineSound, "_masterVolume", "MasterVolume", 1)
|
||||||
accessorFunc(EngineSound, "_parent", "Parent", chip())
|
accessorFunc(EngineSound, "_parent", "Parent", chip())
|
||||||
|
|
||||||
local function fadeIn(rpm, range)
|
local function fadeIn(rpm, range)
|
||||||
local fadeIn = 1
|
local fadeIn = 1
|
||||||
|
|
||||||
if range and range[1] != range[2] then
|
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)
|
fadeIn = math.min(math.max((rpm + (range[2] - range[1] * 2)) / (range[2] - range[1]), 1) - 1, 1)
|
||||||
|
elseif range and range[1] == range[2] then
|
||||||
|
fadeIn = rpm >= range[1] and 1 or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
return fadeIn
|
return fadeIn
|
||||||
end
|
end
|
||||||
|
|
||||||
local function fadeOut(rpm, range)
|
local function fadeOut(rpm, range)
|
||||||
local fadeOut = 1
|
local fadeOut = 1
|
||||||
|
|
||||||
if range and range[1] != range[2] then
|
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)
|
fadeOut = math.min(math.max((rpm + (range[1] - range[2] * 2)) / (range[1] - range[2]), 1) - 1, 1)
|
||||||
|
elseif range and range[1] == range[2] then
|
||||||
|
fadeOut = rpm >= range[1] and 1 or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
return fadeOut
|
return fadeOut
|
||||||
end
|
end
|
||||||
|
|
||||||
function EngineSound:initialize(soundsMap)
|
function EngineSound:initialize(soundsMap)
|
||||||
self.pitchDamping = 0.2
|
self.pitchDamping = 0.2
|
||||||
self.volumeDamping = 0.3
|
self.volumeDamping = 0.3
|
||||||
|
|
||||||
|
self._rpm = 0
|
||||||
self._soundsMap = soundsMap
|
self._soundsMap = soundsMap
|
||||||
self._lastRPM = 0
|
|
||||||
|
|
||||||
for k, v in pairs(soundsMap) do
|
for k, v in pairs(soundsMap) do
|
||||||
bass.loadURL(v.link, "3d noblock", function(snd, err, errtxt)
|
bass.loadURL(v.link, "3d noblock", function(snd, err, errtxt)
|
||||||
if snd then
|
if snd then
|
||||||
snd:setPos(self:getParent():getPos())
|
snd:setPos(self:getParent():getPos())
|
||||||
snd:setLooping(true)
|
snd:setLooping(true)
|
||||||
snd:setVolume(0)
|
snd:setVolume(0)
|
||||||
|
|
||||||
v.source = snd
|
v.source = snd
|
||||||
v.lastPitch = 1
|
v.lastPitch = 1
|
||||||
v.lastVolume = 0
|
v.lastVolume = 0
|
||||||
@ -51,28 +53,34 @@ function EngineSound:initialize(soundsMap)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
hook.add("think", "EngineSound_think", function()
|
hook.add("think", "EngineSound_think", function()
|
||||||
for _, v in pairs(self._soundsMap) do
|
for _, v in pairs(self._soundsMap) do
|
||||||
if v.source then
|
if v.source then
|
||||||
v.source:setPos(self:getParent():getPos())
|
v.source:setPos(self:getParent():getPos())
|
||||||
|
|
||||||
local fadeIn = fadeIn(self._rpm, v.fadeIn)
|
local fadeIn = fadeIn(self:getRPM(), v.fadeIn)
|
||||||
local fadeOut = fadeOut(self._rpm, v.fadeOut)
|
local fadeOut = fadeOut(self:getRPM(), v.fadeOut)
|
||||||
local targetVolume = self:getMasterVolume() * (fadeIn + fadeOut - 1)
|
local targetVolume = self:getMasterVolume() * (fadeIn + fadeOut - 1)
|
||||||
local targetPitch = self._rpm / v.rootPitch
|
local targetPitch = self:getRPM() / v.rootPitch
|
||||||
|
|
||||||
local pitch = math.lerp(self.pitchDamping, v.lastPitch, targetPitch)
|
local pitch = math.lerp(self.pitchDamping, v.lastPitch, targetPitch)
|
||||||
local volume = math.lerp(self.volumeDamping, v.lastVolume, targetVolume)
|
local volume = math.lerp(self.volumeDamping, v.lastVolume, targetVolume)
|
||||||
|
|
||||||
v.source:setVolume(volume)
|
v.source:setVolume(volume)
|
||||||
v.source:setPitch(pitch)
|
v.source:setPitch(pitch)
|
||||||
|
|
||||||
v.lastVolume = volume
|
v.lastVolume = volume
|
||||||
v.lastPitch = pitch
|
v.lastPitch = pitch
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
_lastRPM = _rpm
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function EngineSound:setRPM(rpm)
|
||||||
|
self._rpm = math.max(rpm, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
function EngineSound:getRPM()
|
||||||
|
return self._rpm
|
||||||
|
end
|
||||||
|
|||||||
66
koptilnya/engine_sounds/abarth_exterior.txt
Normal file
66
koptilnya/engine_sounds/abarth_exterior.txt
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
--@name Abarth Exterior engine sound
|
||||||
|
--@shared
|
||||||
|
--@include /koptilnya/engine_sound.txt
|
||||||
|
|
||||||
|
require("/koptilnya/engine_sound.txt")
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
wire.adjustInputs({"RPM"}, {"NORMAL"})
|
||||||
|
|
||||||
|
hook.add("input", "wireinput", function(name, value)
|
||||||
|
if name == "RPM" then
|
||||||
|
net.start("rpm")
|
||||||
|
net.writeFloat(value)
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
function init()
|
||||||
|
local engineSound = EngineSound:new({
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/b05fhpa6llc4sjj/ext_fa01_on_1500.ogg",
|
||||||
|
rootPitch = 1500,
|
||||||
|
fadeOut = Vector(1400, 1800)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/cus2007qr25nlqg/ext_fa01_on_4250.ogg",
|
||||||
|
rootPitch = 4250,
|
||||||
|
fadeIn = Vector(1400, 1800),
|
||||||
|
fadeOut = Vector(3400, 3800)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/ug9n6dtac1ayioi/ext_fa01_on_5250.ogg",
|
||||||
|
rootPitch = 5250,
|
||||||
|
fadeIn = Vector(3400, 3800),
|
||||||
|
fadeOut = Vector(4800, 5200)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/ihdefqw30pwd059/ext_fa01_on_6000.ogg",
|
||||||
|
rootPitch = 6000,
|
||||||
|
fadeIn = Vector(4800, 5200),
|
||||||
|
fadeOut = Vector(5600, 6000)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/7m98qruc8bhopyn/ext_fa01_on_6500.ogg",
|
||||||
|
rootPitch = 6500,
|
||||||
|
fadeIn = Vector(5600, 6000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
net.receive("rpm", function(len)
|
||||||
|
engineSound:setRPM(net.readFloat())
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if hasPermission("bass.loadURL") then
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
setupPermissionRequest({"bass.loadURL"}, "", true)
|
||||||
|
|
||||||
|
hook.add("permissionrequest", "permission", function()
|
||||||
|
if hasPermission("bass.loadURL") then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
66
koptilnya/engine_sounds/bmw_e30_exterior.txt
Normal file
66
koptilnya/engine_sounds/bmw_e30_exterior.txt
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
--@name BMW E30 exterior engine sound
|
||||||
|
--@shared
|
||||||
|
--@include /koptilnya/engine_sound.txt
|
||||||
|
|
||||||
|
require("/koptilnya/engine_sound.txt")
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
wire.adjustInputs({"RPM"}, {"NORMAL"})
|
||||||
|
|
||||||
|
hook.add("input", "wireinput", function(name, value)
|
||||||
|
if name == "RPM" then
|
||||||
|
net.start("rpm")
|
||||||
|
net.writeFloat(value)
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
function init()
|
||||||
|
local engineSound = EngineSound:new({
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/5lk7xkrrgozbgl2/ext_e30_idle.ogg",
|
||||||
|
rootPitch = 1000,
|
||||||
|
fadeOut = Vector(1000, 1500)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/oiz3ccf6cenul8t/ext_e30_on_2500.ogg",
|
||||||
|
rootPitch = 2500,
|
||||||
|
fadeIn = Vector(1000, 1500),
|
||||||
|
fadeOut = Vector(2500, 3000)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/346ly2b0ete839f/ext_e30_on_4500.ogg",
|
||||||
|
rootPitch = 4500,
|
||||||
|
fadeIn = Vector(2500, 3000),
|
||||||
|
fadeOut = Vector(4500, 5000)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/wlyeqqwhaqe8oo5/ext_e30_on_6000.ogg",
|
||||||
|
rootPitch = 6000,
|
||||||
|
fadeIn = Vector(4500, 5000),
|
||||||
|
fadeOut = Vector(6500, 7000)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/vijeiwwsgthlxzn/ext_e30_on_8500.ogg",
|
||||||
|
rootPitch = 8500,
|
||||||
|
fadeIn = Vector(6500, 7000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
net.receive("rpm", function(len)
|
||||||
|
engineSound:setRPM(net.readFloat())
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if hasPermission("bass.loadURL") then
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
setupPermissionRequest({"bass.loadURL"}, "", true)
|
||||||
|
|
||||||
|
hook.add("permissionrequest", "permission", function()
|
||||||
|
if hasPermission("bass.loadURL") then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
68
koptilnya/engine_sounds/bmw_e30_interior.txt
Normal file
68
koptilnya/engine_sounds/bmw_e30_interior.txt
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
--@name BMW E30 interior engine sound
|
||||||
|
--@shared
|
||||||
|
--@include /koptilnya/engine_sound.txt
|
||||||
|
|
||||||
|
require("/koptilnya/engine_sound.txt")
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
wire.adjustInputs({"RPM"}, {"NORMAL"})
|
||||||
|
|
||||||
|
hook.add("input", "wireinput", function(name, value)
|
||||||
|
if name == "RPM" then
|
||||||
|
net.start("rpm")
|
||||||
|
net.writeFloat(value)
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
function init()
|
||||||
|
local engineSound = EngineSound:new({
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/wwda7cpdsrlsotb/e30_idle.ogg",
|
||||||
|
rootPitch = 1000,
|
||||||
|
fadeIn = Vector(0, 1),
|
||||||
|
fadeOut = Vector(1000, 1500)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/5e9x082jdjgm2ym/e30_on_3500.ogg",
|
||||||
|
rootPitch = 3500,
|
||||||
|
fadeIn = Vector(1000, 1500),
|
||||||
|
fadeOut = Vector(3500, 4000)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/83c3v08sjut5a9o/e30_on_5000.ogg",
|
||||||
|
rootPitch = 5000,
|
||||||
|
fadeIn = Vector(3500, 4000),
|
||||||
|
fadeOut = Vector(5000, 5500)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/a6d3356uc7xstf1/e30_on_7000.ogg",
|
||||||
|
rootPitch = 7000,
|
||||||
|
fadeIn = Vector(5000, 5500),
|
||||||
|
fadeOut = Vector(7000, 7500)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link = "https://dl.dropboxusercontent.com/s/pwpuldfs6w93ezb/e30_on_8500.ogg",
|
||||||
|
rootPitch = 8500,
|
||||||
|
fadeIn = Vector(7000, 7500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
engineSound:setMasterVolume(0.8)
|
||||||
|
|
||||||
|
net.receive("rpm", function(len)
|
||||||
|
engineSound:setRPM(net.readFloat())
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if hasPermission("bass.loadURL") then
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
setupPermissionRequest({"bass.loadURL"}, "", true)
|
||||||
|
|
||||||
|
hook.add("permissionrequest", "permission", function()
|
||||||
|
if hasPermission("bass.loadURL") then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -12,7 +12,7 @@ function EButton:initialize()
|
|||||||
self:setText("Button")
|
self:setText("Button")
|
||||||
self:setSize(100, 32)
|
self:setSize(100, 32)
|
||||||
self:setRoundedCorners(true)
|
self:setRoundedCorners(true)
|
||||||
self:setRadius(5)
|
self:setRadius(0)
|
||||||
self:setColorScheme({
|
self:setColorScheme({
|
||||||
bg = {
|
bg = {
|
||||||
Color(46, 46, 46),
|
Color(46, 46, 46),
|
||||||
|
|||||||
@ -48,8 +48,7 @@ function ECheckbox:paint(x, y, w, h)
|
|||||||
render.drawRectFast(x + 4, y + 4, w - 8, h - 8)
|
render.drawRectFast(x + 4, y + 4, w - 8, h - 8)
|
||||||
|
|
||||||
render.setColor(self:getColorFromScheme("border"))
|
render.setColor(self:getColorFromScheme("border"))
|
||||||
render.drawRectOutline(x, y, w, h, 1)
|
render.drawRectOutline(x, y, w, h, 2)
|
||||||
render.drawRectOutline(x + 1, y + 1, w - 2, h - 2, 1)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- STUB
|
-- STUB
|
||||||
|
|||||||
12
koptilnya/gui/elements/icon_button.txt
Normal file
12
koptilnya/gui/elements/icon_button.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
--@include button.txt
|
||||||
|
--@include radius_mixin.txt
|
||||||
|
|
||||||
|
require("label.txt")
|
||||||
|
|
||||||
|
EIconButton = class("EIconButton", EButton)
|
||||||
|
|
||||||
|
function EIconButton:initialize()
|
||||||
|
EButton.initialize(self)
|
||||||
|
|
||||||
|
self:setFont(GUI.fonts.icons)
|
||||||
|
end
|
||||||
@ -8,6 +8,7 @@ ELabel = class("ELabel", Element)
|
|||||||
|
|
||||||
function ELabel:initialize()
|
function ELabel:initialize()
|
||||||
Element.initialize(self)
|
Element.initialize(self)
|
||||||
|
|
||||||
self._text = ""
|
self._text = ""
|
||||||
self._textWidth = 0
|
self._textWidth = 0
|
||||||
self._textHeight = 0
|
self._textHeight = 0
|
||||||
|
|||||||
@ -2,12 +2,15 @@
|
|||||||
--@include label.txt
|
--@include label.txt
|
||||||
--@include button.txt
|
--@include button.txt
|
||||||
--@include /koptilnya/libs/utils.txt
|
--@include /koptilnya/libs/utils.txt
|
||||||
|
--@include /koptilnya/gui/segoe_mdl2_assets_icons.txt
|
||||||
|
|
||||||
require("element.txt")
|
require("element.txt")
|
||||||
require("label.txt")
|
require("label.txt")
|
||||||
require("button.txt")
|
require("button.txt")
|
||||||
require("/koptilnya/libs/utils.txt")
|
require("/koptilnya/libs/utils.txt")
|
||||||
|
|
||||||
|
local segoeIcons = require("/koptilnya/gui/segoe_mdl2_assets_icons.txt")
|
||||||
|
|
||||||
EPanel = class("EPanel", Element)
|
EPanel = class("EPanel", Element)
|
||||||
|
|
||||||
accessorFunc(EPanel, "_parentLock", "ParentLock", false)
|
accessorFunc(EPanel, "_parentLock", "ParentLock", false)
|
||||||
@ -15,6 +18,8 @@ accessorFunc(EPanel, "_parentLock", "ParentLock", false)
|
|||||||
function EPanel:initialize()
|
function EPanel:initialize()
|
||||||
Element.initialize(self)
|
Element.initialize(self)
|
||||||
|
|
||||||
|
self._minimizable = true
|
||||||
|
self._closeable = true
|
||||||
self._minimized = false
|
self._minimized = false
|
||||||
self._lastHeight = 0
|
self._lastHeight = 0
|
||||||
|
|
||||||
@ -32,7 +37,7 @@ function EPanel:initialize()
|
|||||||
|
|
||||||
self.minimizeButton = EButton:new()
|
self.minimizeButton = EButton:new()
|
||||||
self.minimizeButton:setFont(GUI.fonts["icons"])
|
self.minimizeButton:setFont(GUI.fonts["icons"])
|
||||||
self.minimizeButton:setText(string.utf8char(0xE73F))
|
self.minimizeButton:setText(segoeIcons.ChromeMinimize)
|
||||||
self.minimizeButton:setSize(32, 32)
|
self.minimizeButton:setSize(32, 32)
|
||||||
self.minimizeButton:setRadius(0)
|
self.minimizeButton:setRadius(0)
|
||||||
self.minimizeButton:setColorScheme(colorScheme)
|
self.minimizeButton:setColorScheme(colorScheme)
|
||||||
@ -43,7 +48,7 @@ function EPanel:initialize()
|
|||||||
|
|
||||||
self.closeButton = EButton:new()
|
self.closeButton = EButton:new()
|
||||||
self.closeButton:setFont(GUI.fonts["icons"])
|
self.closeButton:setFont(GUI.fonts["icons"])
|
||||||
self.closeButton:setText(string.utf8char(0xE006))
|
self.closeButton:setText(string.utf8char(0xE8BB))
|
||||||
self.closeButton:setSize(32, 32)
|
self.closeButton:setSize(32, 32)
|
||||||
self.closeButton:setRadius(0)
|
self.closeButton:setRadius(0)
|
||||||
self.closeButton:setColorScheme(colorScheme)
|
self.closeButton:setColorScheme(colorScheme)
|
||||||
@ -74,28 +79,52 @@ function EPanel:getTitle()
|
|||||||
return self.title:getText()
|
return self.title:getText()
|
||||||
end
|
end
|
||||||
|
|
||||||
function EPanel:setMinimized(state)
|
function EPanel:setMinimizable(state)
|
||||||
self._minimized = state
|
self._minimizable = state
|
||||||
|
|
||||||
|
self.minimizeButton:setEnabled(state)
|
||||||
|
self.minimizeButton:setVisible(state)
|
||||||
|
end
|
||||||
|
|
||||||
|
function EPanel:isMinimizable()
|
||||||
|
return self._minimizable
|
||||||
|
end
|
||||||
|
|
||||||
|
function EPanel:setCloseable(state)
|
||||||
|
self._closeable = state
|
||||||
|
|
||||||
|
self.closeButton:setEnabled(state)
|
||||||
|
self.closeButton:setVisible(state)
|
||||||
end
|
end
|
||||||
|
|
||||||
function EPanel:isMinimized()
|
function EPanel:isMinimized()
|
||||||
return self._minimized
|
return self._minimized
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function EPanel:setMinimized(state)
|
||||||
|
self._minimized = state
|
||||||
|
end
|
||||||
|
|
||||||
|
function EPanel:isCloseable()
|
||||||
|
return self._minimizable
|
||||||
|
end
|
||||||
|
|
||||||
function EPanel:close()
|
function EPanel:close()
|
||||||
self:setVisible(false)
|
self:setVisible(false)
|
||||||
self:setEnabled(false)
|
self:setEnabled(false)
|
||||||
|
self:onClose()
|
||||||
end
|
end
|
||||||
|
|
||||||
function EPanel:open()
|
function EPanel:open()
|
||||||
self:setVisible(true)
|
self:setVisible(true)
|
||||||
self:setEnabled(true)
|
self:setEnabled(true)
|
||||||
|
self:onOpen()
|
||||||
end
|
end
|
||||||
|
|
||||||
function EPanel:minimize()
|
function EPanel:minimize()
|
||||||
self._lastHeight = self:getHeight()
|
self._lastHeight = self:getHeight()
|
||||||
|
|
||||||
self.minimizeButton:setText(string.utf8char(10063))
|
self.minimizeButton:setText(segoeIcons.ChromeMaximize)
|
||||||
self:setMinimized(true)
|
self:setMinimized(true)
|
||||||
self:setHeight(34)
|
self:setHeight(34)
|
||||||
|
|
||||||
@ -110,7 +139,7 @@ function EPanel:minimize()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function EPanel:maximize()
|
function EPanel:maximize()
|
||||||
self.minimizeButton:setText("_")
|
self.minimizeButton:setText(segoeIcons.ChromeMinimize)
|
||||||
self:setMinimized(false)
|
self:setMinimized(false)
|
||||||
self:setHeight(self._lastHeight)
|
self:setHeight(self._lastHeight)
|
||||||
|
|
||||||
@ -181,4 +210,12 @@ function EPanel:paint(x, y, w, h)
|
|||||||
|
|
||||||
render.setColor(self:getColorFromScheme("bg"))
|
render.setColor(self:getColorFromScheme("bg"))
|
||||||
render.drawRectFast(x + 1, y + 33, w - 2, h - 34)
|
render.drawRectFast(x + 1, y + 33, w - 2, h - 34)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- STUB
|
||||||
|
|
||||||
|
function EPanel:onClose()
|
||||||
|
end
|
||||||
|
|
||||||
|
function EPanel:onOpen()
|
||||||
end
|
end
|
||||||
@ -10,6 +10,6 @@ accessorFunc(EShape, "_color", "Color", Color(255, 255, 255))
|
|||||||
accessorFunc(EShape, "_hoveredColor", "HoveredColor", Color(150, 150, 150))
|
accessorFunc(EShape, "_hoveredColor", "HoveredColor", Color(150, 150, 150))
|
||||||
|
|
||||||
function EShape:paint(x, y, w, h)
|
function EShape:paint(x, y, w, h)
|
||||||
render.setColor(self:isHovered() and self:getHoveredColor() or self:getColor())
|
render.setColor(self:getColor())
|
||||||
render.drawRectFast(x, y, w, h)
|
render.drawRectFast(x, y, w, h)
|
||||||
end
|
end
|
||||||
@ -8,14 +8,14 @@ GUI = class("GUI")
|
|||||||
|
|
||||||
GUI.static.fonts = {
|
GUI.static.fonts = {
|
||||||
main = render.createFont("Roboto", 16, 700, true),
|
main = render.createFont("Roboto", 16, 700, true),
|
||||||
icons = render.createFont("Segoe MDL2 Assets", 32, 400, true)
|
icons = render.createFont("Segoe MDL2 Assets", 16, 400, true, false, false, false, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
function GUI:initialize(renderDevice)
|
function GUI:initialize(renderDevice)
|
||||||
checkVarClass(renderDevice, RenderDevice)
|
checkVarClass(renderDevice, RenderDevice)
|
||||||
|
|
||||||
self.renderDevice = renderDevice
|
self.renderDevice = renderDevice
|
||||||
self._root = ERoot:new("root")
|
self._root = ERoot:new()
|
||||||
self._root:setSize(renderDevice:getSize())
|
self._root:setSize(renderDevice:getSize())
|
||||||
|
|
||||||
hook.add("inputPressed", "gui_inputPressed", function(key)
|
hook.add("inputPressed", "gui_inputPressed", function(key)
|
||||||
@ -45,6 +45,10 @@ function GUI:initialize(renderDevice)
|
|||||||
self._lastMouseX = 0
|
self._lastMouseX = 0
|
||||||
self._lastMouseY = 0
|
self._lastMouseY = 0
|
||||||
hook.add("think", "gui_think", function()
|
hook.add("think", "gui_think", function()
|
||||||
|
if not hasPermission("input") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if input.getCursorVisible then
|
if input.getCursorVisible then
|
||||||
local x, y = input.getCursorPos()
|
local x, y = input.getCursorPos()
|
||||||
|
|
||||||
|
|||||||
@ -5,12 +5,15 @@ require("render_device.txt")
|
|||||||
RenderDeviceHUD = class("RenderDeviceHUD", RenderDevice)
|
RenderDeviceHUD = class("RenderDeviceHUD", RenderDevice)
|
||||||
|
|
||||||
function RenderDeviceHUD:initialize()
|
function RenderDeviceHUD:initialize()
|
||||||
enableHud(player(), true)
|
--if player() == owner() then
|
||||||
|
-- enableHud(player(), true)
|
||||||
|
--end
|
||||||
|
|
||||||
self:setSize(render.getResolution())
|
self:setSize(render.getResolution())
|
||||||
|
|
||||||
hook.add("hudshoulddraw", "gui_hudshoulddraw", function(name)
|
--hook.add("hudshoulddraw", "gui_hudshoulddraw", function(name)
|
||||||
return name == "CHudGMod" or name == "CHudChat"
|
-- return name == "CHudGMod" or name == "CHudChat"
|
||||||
end)
|
--end)
|
||||||
|
|
||||||
hook.add("postdrawhud", "gui_renderer", function()
|
hook.add("postdrawhud", "gui_renderer", function()
|
||||||
self:render()
|
self:render()
|
||||||
|
|||||||
@ -4,6 +4,7 @@ require("/koptilnya/libs/utils.txt")
|
|||||||
|
|
||||||
RenderDevice = class("RenderDevice")
|
RenderDevice = class("RenderDevice")
|
||||||
|
|
||||||
|
accessorFunc(RenderDevice, "_player", "Player", nil)
|
||||||
accessorFunc(RenderDevice, "_width", "Width", 0)
|
accessorFunc(RenderDevice, "_width", "Width", 0)
|
||||||
accessorFunc(RenderDevice, "_height", "Height", 0)
|
accessorFunc(RenderDevice, "_height", "Height", 0)
|
||||||
|
|
||||||
@ -24,5 +25,7 @@ function RenderDevice:getSize()
|
|||||||
return self:getWidth(), self:getHeight()
|
return self:getWidth(), self:getHeight()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- STUB
|
||||||
|
|
||||||
function RenderDevice:render()
|
function RenderDevice:render()
|
||||||
end
|
end
|
||||||
1384
koptilnya/gui/segoe_mdl2_assets_icons.txt
Normal file
1384
koptilnya/gui/segoe_mdl2_assets_icons.txt
Normal file
File diff suppressed because it is too large
Load Diff
113
koptilnya/joystick_data.txt
Normal file
113
koptilnya/joystick_data.txt
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
-- @name Joystick Data
|
||||||
|
-- @author Opti1337
|
||||||
|
JOYSTICK_INPUT_TYPE = {Axis = 1, Button = 2}
|
||||||
|
|
||||||
|
local CONFIG = {
|
||||||
|
Steer = {
|
||||||
|
DeviceId = 0,
|
||||||
|
InputId = 0,
|
||||||
|
Type = JOYSTICK_INPUT_TYPE.Axis,
|
||||||
|
Handler = function(value)
|
||||||
|
return math.remap(value, 0, 65535, -1, 1)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
Clutch = {
|
||||||
|
DeviceId = 0,
|
||||||
|
InputId = 4,
|
||||||
|
Type = JOYSTICK_INPUT_TYPE.Button,
|
||||||
|
Handler = function(value)
|
||||||
|
return math.remap(value, 0, 128, 0, 1)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
Throttle = {
|
||||||
|
DeviceId = 0,
|
||||||
|
InputId = 5,
|
||||||
|
Type = JOYSTICK_INPUT_TYPE.Button,
|
||||||
|
Handler = function(value)
|
||||||
|
return math.remap(value, 0, 128, 0, 1)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
Brake = {
|
||||||
|
DeviceId = 0,
|
||||||
|
InputId = 2,
|
||||||
|
Type = JOYSTICK_INPUT_TYPE.Button,
|
||||||
|
Handler = function(value)
|
||||||
|
return math.remap(value, 0, 128, 0, 1)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
Handbrake = {
|
||||||
|
DeviceId = 0,
|
||||||
|
InputId = 0,
|
||||||
|
Type = JOYSTICK_INPUT_TYPE.Button,
|
||||||
|
Handler = function(value)
|
||||||
|
return math.remap(value, 0, 128, 0, 1)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
GearUp = {
|
||||||
|
DeviceId = 0,
|
||||||
|
InputId = 1,
|
||||||
|
Type = JOYSTICK_INPUT_TYPE.Button,
|
||||||
|
Handler = function(value)
|
||||||
|
return math.remap(value, 0, 128, 0, 1)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
GearDown = {
|
||||||
|
DeviceId = 0,
|
||||||
|
InputId = 3,
|
||||||
|
Type = JOYSTICK_INPUT_TYPE.Button,
|
||||||
|
Handler = function(value)
|
||||||
|
return math.remap(value, 0, 128, 0, 1)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if CLIENT and player() == owner() then
|
||||||
|
local data = {}
|
||||||
|
local isDirty = false
|
||||||
|
|
||||||
|
hook.add("think", "_think", function()
|
||||||
|
for k, v in pairs(CONFIG) do
|
||||||
|
local value = 0
|
||||||
|
|
||||||
|
if v.Type == JOYSTICK_INPUT_TYPE.Axis then
|
||||||
|
value = joystick.getAxis(v.DeviceId, v.InputId)
|
||||||
|
elseif v.Type == JOYSTICK_INPUT_TYPE.Button then
|
||||||
|
value = joystick.getButton(v.DeviceId, v.InputId)
|
||||||
|
end
|
||||||
|
|
||||||
|
if v.Handler ~= nil and type(v.Handler) == "function" then
|
||||||
|
value = v.Handler(value) or value
|
||||||
|
end
|
||||||
|
|
||||||
|
if not isDirty and data[k] ~= value then
|
||||||
|
isDirty = true
|
||||||
|
end
|
||||||
|
|
||||||
|
data[k] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
if isDirty then
|
||||||
|
net.start("data")
|
||||||
|
for k in pairs(CONFIG) do
|
||||||
|
net.writeFloat(data[k])
|
||||||
|
end
|
||||||
|
net.send({}, true)
|
||||||
|
|
||||||
|
isDirty = false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
elseif SERVER then
|
||||||
|
local outputs = {}
|
||||||
|
|
||||||
|
for _, v in pairs(table.getKeys(CONFIG)) do
|
||||||
|
outputs[v] = "NORMAL"
|
||||||
|
end
|
||||||
|
|
||||||
|
wire.adjustPorts({}, outputs)
|
||||||
|
|
||||||
|
net.receive("data", function()
|
||||||
|
for k in pairs(CONFIG) do
|
||||||
|
wire.ports[k] = net.readFloat()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
-- @name koptilnya/libs/render
|
||||||
--@client
|
--@client
|
||||||
|
|
||||||
function render.drawWedge(x, y, w, h, angle, mouthSize, fidelity)
|
function render.drawWedge(x, y, w, h, angle, mouthSize, fidelity)
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
-- @name koptilnya/libs/table
|
||||||
|
|
||||||
function table.chunk(tbl, size)
|
function table.chunk(tbl, size)
|
||||||
size = size or 1
|
size = size or 1
|
||||||
size = size > 0 and size or 1
|
size = size > 0 and size or 1
|
||||||
@ -41,4 +43,24 @@ function table.merge(table1, table2)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return newTable
|
return newTable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function table.contains(tbl, ...)
|
||||||
|
local argCount = #arg
|
||||||
|
|
||||||
|
if argCount == 1 then
|
||||||
|
return table.hasValue(tbl, arg[1])
|
||||||
|
elseif argCount > 1 then
|
||||||
|
local result = true
|
||||||
|
|
||||||
|
for _, v in pairs(arg) do
|
||||||
|
if not table.hasValue(tbl, v) then
|
||||||
|
result = true
|
||||||
|
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
-- @name koptilnya/libs/utils
|
||||||
|
|
||||||
function checkVarClass(var, class, message)
|
function checkVarClass(var, class, message)
|
||||||
if type(var) ~= "table" or var["class"] == nil or not var:isInstanceOf(class) then
|
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)
|
throw(message == nil and "Wrong variable class." or message, 1, true)
|
||||||
@ -14,11 +16,11 @@ function accessorFunc(tbl, varName, name, defaultValue)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function rotateAround(entity, pivot, angles)
|
function rotateAround(entity, pivot, angles)
|
||||||
local pos = entity:getPos()
|
local pos = entity:getPos()
|
||||||
local localPivotPos = entity:worldToLocal(pivot)
|
local localPivotPos = entity:worldToLocal(pivot)
|
||||||
|
|
||||||
entity:setAngles(angles)
|
entity:setAngles(angles)
|
||||||
pos = pos + (pivot - entity:localToWorld(localPivotPos))
|
pos = pos + (pivot - entity:localToWorld(localPivotPos))
|
||||||
entity:setPos(pos)
|
entity:setPos(pos)
|
||||||
end
|
end
|
||||||
|
|||||||
49
koptilnya/libs/workers.txt
Normal file
49
koptilnya/libs/workers.txt
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
-- @name koptilnya/libs/workers
|
||||||
|
|
||||||
|
WORKERS = {}
|
||||||
|
WORKERS_QUOTA = 0.4
|
||||||
|
|
||||||
|
local function execWorker(worker)
|
||||||
|
local status
|
||||||
|
|
||||||
|
while math.max(quotaAverage(), quotaUsed()) < quotaMax() * WORKERS_QUOTA do
|
||||||
|
status = worker()
|
||||||
|
|
||||||
|
if status == 1 or status == 2 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return status
|
||||||
|
end
|
||||||
|
|
||||||
|
local function procWorkers()
|
||||||
|
local i = 1
|
||||||
|
while i <= #WORKERS do
|
||||||
|
local status = execWorker(WORKERS[i])
|
||||||
|
|
||||||
|
if status == 2 then
|
||||||
|
table.remove(WORKERS, i)
|
||||||
|
elseif status == 1 then
|
||||||
|
i = i + 1
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #WORKERS == 0 then
|
||||||
|
hook.remove("think", "workers_think")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function addWorker(worker)
|
||||||
|
local status = execWorker(worker)
|
||||||
|
|
||||||
|
if status ~= 2 then
|
||||||
|
if #WORKERS == 0 then
|
||||||
|
hook.add("think", "workers_think", procWorkers)
|
||||||
|
end
|
||||||
|
|
||||||
|
WORKERS[#WORKERS + 1] = worker
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
-- @name koptilnya/mesh_loader/builder
|
||||||
-- @include sv_builder.txt
|
-- @include sv_builder.txt
|
||||||
-- @include cl_builder.txt
|
-- @include cl_builder.txt
|
||||||
if SERVER then
|
if SERVER then
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
-- @name koptilnya/mesh_loader/cl_builder
|
||||||
-- @client
|
-- @client
|
||||||
-- @include /koptilnya/libs/table.txt
|
-- @include /koptilnya/libs/table.txt
|
||||||
-- @include obj_parser.txt
|
-- @include obj_parser.txt
|
||||||
@ -6,20 +7,32 @@ require("obj_parser.txt")
|
|||||||
|
|
||||||
MeshBuilder = class("MeshBuilder")
|
MeshBuilder = class("MeshBuilder")
|
||||||
|
|
||||||
function MeshBuilder:initialize(link, maxQuota)
|
function MeshBuilder:initialize(link)
|
||||||
self.link = link
|
self.link = link
|
||||||
self.meshData = {}
|
self.meshData = {}
|
||||||
|
|
||||||
self._objects = {}
|
self._objects = {}
|
||||||
self._parser = ObjParser:new(link, maxQuota)
|
self._parser = ObjParser:new(link)
|
||||||
self._parser.onLoaded = function(parser, objData, meshData, usedTriangles)
|
self._parser.onLoaded = function(parser, objData)
|
||||||
|
self:onObjLoaded(objData)
|
||||||
|
end
|
||||||
|
self._parser.onParsed = function(parser, meshData, usedTriangles)
|
||||||
|
net.start("obj_parsed")
|
||||||
|
net.send()
|
||||||
|
|
||||||
|
self:onObjParsed(meshData, usedTriangles)
|
||||||
|
|
||||||
self.meshData = meshData
|
self.meshData = meshData
|
||||||
|
|
||||||
net.start("ready")
|
self:_applyMeshes()
|
||||||
net.send()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
net.receive("holograms", function()
|
net.start("initialized")
|
||||||
|
net.send()
|
||||||
|
|
||||||
|
net.receive("objects", function()
|
||||||
|
self._objects = {}
|
||||||
|
|
||||||
local hasNext = net.readBit()
|
local hasNext = net.readBit()
|
||||||
|
|
||||||
while hasNext == 1 do
|
while hasNext == 1 do
|
||||||
@ -27,17 +40,17 @@ function MeshBuilder:initialize(link, maxQuota)
|
|||||||
|
|
||||||
net.readEntity(function(ent)
|
net.readEntity(function(ent)
|
||||||
local holo = ent:toHologram()
|
local holo = ent:toHologram()
|
||||||
|
local object = {name = name, holo = holo}
|
||||||
|
|
||||||
table.insert(self._objects, {name = name, holo = holo})
|
table.insert(self._objects, object)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
hasNext = net.readBit()
|
hasNext = net.readBit()
|
||||||
end
|
end
|
||||||
|
|
||||||
self:_applyMeshes()
|
timer.simple(0.5, function()
|
||||||
|
|
||||||
timer.simple(0, function()
|
|
||||||
self:onHologramsReceived(self._objects)
|
self:onHologramsReceived(self._objects)
|
||||||
|
self:_applyMeshes()
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -47,9 +60,25 @@ function MeshBuilder:_applyMeshes()
|
|||||||
if self.meshData[v.name] ~= nil then
|
if self.meshData[v.name] ~= nil then
|
||||||
v.holo:setMesh(self.meshData[v.name])
|
v.holo:setMesh(self.meshData[v.name])
|
||||||
v.holo:setRenderBounds(Vector(-200), Vector(200))
|
v.holo:setRenderBounds(Vector(-200), Vector(200))
|
||||||
|
v.meshApplied = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if #self._objects > 0 then
|
||||||
|
self:onMeshesApplied()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- STUB
|
||||||
|
|
||||||
|
function MeshBuilder:onObjLoaded(objData)
|
||||||
|
end
|
||||||
|
|
||||||
|
function MeshBuilder:onObjParsed(meshData, usedTriangles)
|
||||||
end
|
end
|
||||||
|
|
||||||
function MeshBuilder:onHologramsReceived(objects)
|
function MeshBuilder:onHologramsReceived(objects)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MeshBuilder:onMeshesApplied()
|
||||||
|
end
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
|
-- @name koptilnya/mesh_loader/obj_parser
|
||||||
-- @client
|
-- @client
|
||||||
|
-- @include /koptilnya/libs/workers.txt
|
||||||
|
require("/koptilnya/libs/workers.txt")
|
||||||
|
|
||||||
ObjParser = class("ObjParser")
|
ObjParser = class("ObjParser")
|
||||||
|
|
||||||
local initialChipName = chip():getChipName()
|
local initialChipName = chip():getChipName()
|
||||||
@ -6,35 +10,44 @@ local function setStatus(status)
|
|||||||
setName(string.format("%s (%s)", initialChipName, status))
|
setName(string.format("%s (%s)", initialChipName, status))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ObjParser:initialize(link, maxQuota)
|
function ObjParser:initialize(link)
|
||||||
self.maxQuota = maxQuota or 0.6
|
addWorker(coroutine.wrap(function()
|
||||||
|
setStatus("Getting file...")
|
||||||
|
|
||||||
local triangles = mesh.trianglesLeft()
|
while not http.canRequest() do
|
||||||
|
coroutine.yield(1)
|
||||||
|
end
|
||||||
|
|
||||||
setStatus("Getting file...")
|
local objData
|
||||||
http.get(link, function(objData)
|
http.get(link, function(response)
|
||||||
objData = string.gsub(objData, "\nl%s%d+%s%d+", "")
|
objData = response
|
||||||
|
objData = string.gsub(response, "\nl%s%d+%s%d+", "")
|
||||||
local loadMesh = coroutine.wrap(function()
|
|
||||||
self.meshData = mesh.createFromObj(objData, true, true)
|
|
||||||
|
|
||||||
return true
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
while not objData do
|
||||||
|
coroutine.yield(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
self:onLoaded(objData)
|
||||||
|
|
||||||
|
local triangles = mesh.trianglesLeft()
|
||||||
|
|
||||||
setStatus("File received, start parsing...")
|
setStatus("File received, start parsing...")
|
||||||
hook.add("think", "loadingMesh", function()
|
|
||||||
while math.max(quotaAverage(), quotaUsed()) < quotaMax() * self.maxQuota do
|
|
||||||
if loadMesh() then
|
|
||||||
setName(initialChipName)
|
|
||||||
self:onLoaded(objData, self.meshData, triangles - mesh.trianglesLeft())
|
|
||||||
hook.remove("think", "loadingMesh")
|
|
||||||
|
|
||||||
return
|
self.meshData = mesh.createFromObj(objData, true)
|
||||||
end
|
|
||||||
end
|
self:onParsed(self.meshData, triangles - mesh.trianglesLeft())
|
||||||
end)
|
|
||||||
end)
|
setName(initialChipName)
|
||||||
|
|
||||||
|
return 2
|
||||||
|
end))
|
||||||
end
|
end
|
||||||
|
|
||||||
function ObjParser:onLoaded(objData, meshData, usedTriangles)
|
-- STUB
|
||||||
|
|
||||||
|
function ObjParser:onLoaded(objData)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ObjParser:onParsed(meshData, usedTriangles)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,54 +1,111 @@
|
|||||||
|
-- @name koptilnya/mesh_loader/sv_builder
|
||||||
-- @server
|
-- @server
|
||||||
|
-- @include /koptilnya/libs/workers.txt
|
||||||
|
require("/koptilnya/libs/workers.txt")
|
||||||
|
|
||||||
MeshBuilder = class("MeshBuilder")
|
MeshBuilder = class("MeshBuilder")
|
||||||
|
|
||||||
function MeshBuilder:initialize(link, modelPlaceholder)
|
function MeshBuilder:initialize(link, modelPlaceholder)
|
||||||
self.link = link
|
self.link = link
|
||||||
self.modelPlaceholder = modelPlaceholder or "models/holograms/cube.mdl"
|
self.modelPlaceholder = modelPlaceholder or "models/holograms/cube.mdl"
|
||||||
self.isReady = false
|
|
||||||
|
|
||||||
self._objectsNames = {}
|
self._objectsNames = {}
|
||||||
self._objects = {}
|
self._objects = {}
|
||||||
self._readyPlayers = {}
|
self._objectsToSend = {}
|
||||||
|
self._playersWithAccess = {}
|
||||||
|
self._firstTimePlayers = find.allPlayers()
|
||||||
|
self._firstTimeSended = false
|
||||||
|
|
||||||
http.get(link, function(response)
|
net.receive("obj_parsed", function(len, ply)
|
||||||
for object in string.gmatch(response, "^?\n?o%s([%w_%.%-]+)") do
|
if DEBUG_MODE then
|
||||||
|
print(string.format("%s parsed the .obj", ply:getName()))
|
||||||
|
end
|
||||||
|
|
||||||
|
self:onPlayerParsedObj(ply)
|
||||||
|
end)
|
||||||
|
|
||||||
|
net.receive("initialized", function(len, ply)
|
||||||
|
if DEBUG_MODE then
|
||||||
|
print(string.format("%s initialized", ply:getName()))
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(self._playersWithAccess, ply)
|
||||||
|
|
||||||
|
if self._firstTimeSended then
|
||||||
|
self:_sendObjects(ply)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("ClientInitialized", "MeshBuilder_ClientInitialized", function(ply)
|
||||||
|
if #self._firstTimePlayers > 0 then
|
||||||
|
table.removeByValue(self._firstTimePlayers, ply)
|
||||||
|
|
||||||
|
if #self._firstTimePlayers == 0 then
|
||||||
|
self:_sendObjects(self._playersWithAccess)
|
||||||
|
|
||||||
|
self._firstTimeSended = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("PlayerConnected", "MeshBuilder_PlayerConnected", function(ply)
|
||||||
|
if not self._firstTimeSended then
|
||||||
|
table.insert(self._firstTimePlayers, ply)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("PlayerDisconnected", "MeshBuilder_PlayerDisconnected", function(ply)
|
||||||
|
table.removeByValue(self._firstTimePlayers, ply)
|
||||||
|
end)
|
||||||
|
|
||||||
|
addWorker(coroutine.wrap(function()
|
||||||
|
while not http.canRequest() do
|
||||||
|
coroutine.yield(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local objData
|
||||||
|
http.get(link, function(response)
|
||||||
|
objData = response
|
||||||
|
end)
|
||||||
|
|
||||||
|
while not objData do
|
||||||
|
coroutine.yield(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
self:onObjectLoaded(objData)
|
||||||
|
|
||||||
|
for object in string.gmatch(objData, "^?\n?o%s([%w_%.%-]+)") do
|
||||||
table.insert(self._objectsNames, object)
|
table.insert(self._objectsNames, object)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self:onObjectParsed(self._objectsNames)
|
||||||
timer.simple(0, function()
|
|
||||||
self.isReady = true
|
|
||||||
self:onReady(self._objectsNames)
|
|
||||||
end)
|
|
||||||
|
|
||||||
for _, v in pairs(self._readyPlayers) do
|
return 2
|
||||||
self:_sendHolograms(v)
|
end))
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
net.receive("ready", function(len, ply)
|
|
||||||
table.insert(self._readyPlayers, ply)
|
|
||||||
|
|
||||||
self:_sendHolograms(ply)
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MeshBuilder:_sendHolograms(ply)
|
function MeshBuilder:_sendObjects(target)
|
||||||
if #self._objects == 0 then
|
if #self._objectsToSend == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
net.start("holograms")
|
net.start("objects")
|
||||||
for _, v in pairs(self._objects) do
|
for _, v in pairs(self._objectsToSend) do
|
||||||
net.writeBit(1)
|
net.writeBit(1)
|
||||||
net.writeString(v.name)
|
net.writeString(v.name)
|
||||||
net.writeEntity(v.holo)
|
net.writeEntity(v.holo)
|
||||||
end
|
end
|
||||||
net.writeBit(0)
|
net.writeBit(0)
|
||||||
net.send(ply)
|
net.send(target)
|
||||||
end
|
end
|
||||||
|
|
||||||
function MeshBuilder:onReady(objectsNames)
|
function MeshBuilder:reset()
|
||||||
|
for _, v in pairs(self._objects) do
|
||||||
|
v.holo:remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
self._objects = {}
|
||||||
|
self._objectsToSend = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
function MeshBuilder:build(name, pos, ang, scale, color, mat, parent, relativeTo)
|
function MeshBuilder:build(name, pos, ang, scale, color, mat, parent, relativeTo)
|
||||||
@ -66,12 +123,27 @@ function MeshBuilder:build(name, pos, ang, scale, color, mat, parent, relativeTo
|
|||||||
end
|
end
|
||||||
|
|
||||||
table.insert(self._objects, {name = name, holo = holo})
|
table.insert(self._objects, {name = name, holo = holo})
|
||||||
|
|
||||||
return name, holo
|
return holo
|
||||||
end
|
end
|
||||||
|
|
||||||
function MeshBuilder:buildAll(pos, ang, scale, color, mat, parent, relativeTo)
|
function MeshBuilder:getResult()
|
||||||
for _, v in pairs(self._objectsNames) do
|
table.copyFromTo(self._objects, self._objectsToSend)
|
||||||
self:build(v, pos, ang, scale, color, mat, parent, relativeTo)
|
|
||||||
|
if self._firstTimeSended then
|
||||||
|
self:_sendObjects(self._playersWithAccess)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return self._objectsToSend
|
||||||
|
end
|
||||||
|
|
||||||
|
-- STUB
|
||||||
|
|
||||||
|
function MeshBuilder:onObjectLoaded(objData)
|
||||||
|
end
|
||||||
|
|
||||||
|
function MeshBuilder:onObjectParsed(objectsNames)
|
||||||
|
end
|
||||||
|
|
||||||
|
function MeshBuilder:onPlayerParsedObj(ply)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
-- @include sv_builder.txt
|
|
||||||
-- @include cl_builder.txt
|
|
||||||
if SERVER then
|
|
||||||
require("sv_builder.txt")
|
|
||||||
else
|
|
||||||
require("cl_builder.txt")
|
|
||||||
end
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
-- @client
|
|
||||||
-- @include /koptilnya/libs/table.txt
|
|
||||||
-- @include obj_parser.txt
|
|
||||||
require("/koptilnya/libs/table.txt")
|
|
||||||
require("obj_parser.txt")
|
|
||||||
|
|
||||||
MeshBuilder = class("MeshBuilder")
|
|
||||||
|
|
||||||
function MeshBuilder:initialize(link, maxQuota)
|
|
||||||
self.link = link
|
|
||||||
self.meshData = {}
|
|
||||||
|
|
||||||
self._objects = {}
|
|
||||||
self._parser = ObjParser:new(link, maxQuota)
|
|
||||||
self._parser.onLoaded = function(parser, objData, meshData, usedTriangles)
|
|
||||||
self.meshData = meshData
|
|
||||||
|
|
||||||
self:_applyMeshes()
|
|
||||||
end
|
|
||||||
|
|
||||||
net.receive("holograms", function()
|
|
||||||
local newObjects = {}
|
|
||||||
local hasNext = net.readBit()
|
|
||||||
|
|
||||||
while hasNext == 1 do
|
|
||||||
local name = net.readString()
|
|
||||||
|
|
||||||
net.readEntity(function(ent)
|
|
||||||
local holo = ent:toHologram()
|
|
||||||
local object = {name = name, holo = holo, meshApplied = false}
|
|
||||||
|
|
||||||
table.insert(newObjects, object)
|
|
||||||
table.insert(self._objects, object)
|
|
||||||
end)
|
|
||||||
|
|
||||||
hasNext = net.readBit()
|
|
||||||
end
|
|
||||||
|
|
||||||
timer.simple(0, function()
|
|
||||||
self:_applyMeshes()
|
|
||||||
self:onHologramsReceived(newObjects, self._objects)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function MeshBuilder:_applyMeshes()
|
|
||||||
for _, v in pairs(self._objects) do
|
|
||||||
if self.meshData[v.name] ~= nil and not v.meshApplied then
|
|
||||||
v.holo:setMesh(self.meshData[v.name])
|
|
||||||
v.holo:setRenderBounds(Vector(-200), Vector(200))
|
|
||||||
v.meshApplied = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function MeshBuilder:onHologramsReceived(objects)
|
|
||||||
end
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
-- @client
|
|
||||||
ObjParser = class("ObjParser")
|
|
||||||
|
|
||||||
local initialChipName = chip():getChipName()
|
|
||||||
local function setStatus(status)
|
|
||||||
setName(string.format("%s (%s)", initialChipName, status))
|
|
||||||
end
|
|
||||||
|
|
||||||
function ObjParser:initialize(link, maxQuota)
|
|
||||||
self.maxQuota = maxQuota or 0.6
|
|
||||||
|
|
||||||
local triangles = mesh.trianglesLeft()
|
|
||||||
|
|
||||||
setStatus("Getting file...")
|
|
||||||
http.get(link, function(objData)
|
|
||||||
objData = string.gsub(objData, "\nl%s%d+%s%d+", "")
|
|
||||||
|
|
||||||
local loadMesh = coroutine.wrap(function()
|
|
||||||
self.meshData = mesh.createFromObj(objData, true, true)
|
|
||||||
|
|
||||||
return true
|
|
||||||
end)
|
|
||||||
|
|
||||||
setStatus("File received, start parsing...")
|
|
||||||
hook.add("think", "loadingMesh", function()
|
|
||||||
while math.max(quotaAverage(), quotaUsed()) < quotaMax() * self.maxQuota do
|
|
||||||
if loadMesh() then
|
|
||||||
setName(initialChipName)
|
|
||||||
self:onLoaded(objData, self.meshData, triangles - mesh.trianglesLeft())
|
|
||||||
hook.remove("think", "loadingMesh")
|
|
||||||
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function ObjParser:onLoaded(objData, meshData, usedTriangles)
|
|
||||||
end
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
-- @server
|
|
||||||
MeshBuilder = class("MeshBuilder")
|
|
||||||
|
|
||||||
function MeshBuilder:initialize(link, modelPlaceholder)
|
|
||||||
self.link = link
|
|
||||||
self.modelPlaceholder = modelPlaceholder or "models/holograms/cube.mdl"
|
|
||||||
|
|
||||||
self._objects = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
function MeshBuilder:_sendHolograms()
|
|
||||||
if #self._objects == 0 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
net.start("holograms")
|
|
||||||
for _, v in pairs(self._objects) do
|
|
||||||
net.writeBit(1)
|
|
||||||
net.writeString(v.name)
|
|
||||||
net.writeEntity(v.holo)
|
|
||||||
print(v.name)
|
|
||||||
end
|
|
||||||
net.writeBit(0)
|
|
||||||
net.send()
|
|
||||||
end
|
|
||||||
|
|
||||||
function MeshBuilder:reset()
|
|
||||||
self._objects = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
function MeshBuilder:build(name, pos, ang, scale, color, mat, parent, relativeTo)
|
|
||||||
if isValid(relativeTo) then
|
|
||||||
pos = relativeTo:localToWorld(pos)
|
|
||||||
ang = relativeTo:localToWorldAngles(ang)
|
|
||||||
end
|
|
||||||
|
|
||||||
local holo = holograms.create(pos, ang, self.modelPlaceholder, scale)
|
|
||||||
holo:setColor(color)
|
|
||||||
holo:setMaterial(mat)
|
|
||||||
|
|
||||||
if isValid(parent) then
|
|
||||||
holo:setParent(parent)
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(self._objects, {name = name, holo = holo})
|
|
||||||
end
|
|
||||||
|
|
||||||
function MeshBuilder:getResult()
|
|
||||||
local result = self._objects
|
|
||||||
|
|
||||||
self:_sendHolograms()
|
|
||||||
self:reset()
|
|
||||||
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
95
koptilnya/models/example.txt
Normal file
95
koptilnya/models/example.txt
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
--@name Mesh loader example
|
||||||
|
--@author Opti1337
|
||||||
|
--@shared
|
||||||
|
-- @include /koptilnya/mesh_loader/builder.txt
|
||||||
|
require("/koptilnya/mesh_loader/builder.txt")
|
||||||
|
|
||||||
|
local LINK = "https://www.dropbox.com/s/k4rte84qv0s3k1d/vaz_2101_wheel.obj?dl=1"
|
||||||
|
local SCALE = Vector(1)
|
||||||
|
|
||||||
|
local builder = {}
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
-- Создаем экземпляр MeshBuilder на сервере
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
|
||||||
|
builder.onObjectLoaded = function(builder, objData)
|
||||||
|
--[[
|
||||||
|
Вызывается, когда .obj загружен на сервере
|
||||||
|
objData {string} - Внутренности .obj
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
builder.onObjectParsed = function(builder, objectsName)
|
||||||
|
--[[
|
||||||
|
Вызывается, когда .obj разобран на сервере
|
||||||
|
objectsNames {table} - Таблица с названиями объектов в .obj
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
builder.onPlayerParsedObj = function(builder, ply)
|
||||||
|
--[[
|
||||||
|
Вызывается, когда игрок разобрал .obj
|
||||||
|
ply {player} - Игрок, который разобрал .obj
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Настраиваем конкретный меш
|
||||||
|
(название_объекта, позиция, угол, размер, цвет, материал, парент, относительно_чего_позиционировать)
|
||||||
|
]]
|
||||||
|
builder:build("wheel", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber", chip(), chip())
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Получаем текущий результат и отправляем его по возможности клиентам. Обычно вызывается после всех вызовов build
|
||||||
|
]]
|
||||||
|
builder:getResult()
|
||||||
|
else -- CLIENT
|
||||||
|
function init()
|
||||||
|
-- Создаем экземпляр MeshBuilder на клиенте
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
|
||||||
|
builder.onObjLoaded = function(builder, objData)
|
||||||
|
--[[
|
||||||
|
Вызывается, когда .obj загружен на клиенте
|
||||||
|
objData {string} - Внутренности .obj
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
builder.onObjParsed = function(builder, meshData, usedTriangles)
|
||||||
|
--[[
|
||||||
|
Вызывается, когда .obj разобран на клиенте
|
||||||
|
meshData {table} - Таблица с мешами
|
||||||
|
usedTriangles {int} - Сколько использовано треугольников
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
builder.onHologramsReceived = function(builder, objects)
|
||||||
|
--[[
|
||||||
|
Вызывается, когда были получен список голограмм от сервера
|
||||||
|
objects {table} - Таблица объектов
|
||||||
|
name {string} - Имя объекта
|
||||||
|
holo {entity} - Голограмма
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
builder.onMeshesApplied = function(builder)
|
||||||
|
--[[
|
||||||
|
Вызывается, когда меши были применены к голограммам
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if hasPermission("http.get") and hasPermission("mesh") and hasPermission("entities.setRenderProperty", chip()) then
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
-- Настраиваем нужные права, если их нет
|
||||||
|
setupPermissionRequest({"http.get", "mesh", "entities.setRenderProperty"}, "", true)
|
||||||
|
|
||||||
|
-- Хук, который срабатывает при изменении прав
|
||||||
|
hook.add("permissionrequest", "_permissionrequest", function()
|
||||||
|
if permissionRequestSatisfied() then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
70
koptilnya/models/ford_f-150_raptor.txt
Normal file
70
koptilnya/models/ford_f-150_raptor.txt
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
-- @shared
|
||||||
|
-- @name Ford F-150 Raptor
|
||||||
|
-- @author Opti1337, .hemp
|
||||||
|
-- @include /koptilnya/mesh_loader/builder.txt
|
||||||
|
require("/koptilnya/mesh_loader/builder.txt")
|
||||||
|
|
||||||
|
DEBUG_MODE = true
|
||||||
|
|
||||||
|
local LINK = "https://drive.google.com/uc?id=1PvM_NNtdl43L_r2LZz_E9lO_JhWexFxW"
|
||||||
|
local SCALE = Vector(0.9)
|
||||||
|
|
||||||
|
local builder = {}
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
|
||||||
|
builder:build("Podnojki", Vector(0), Angle(0), SCALE, Color(200, 200, 200), "sprops/textures/sprops_chrome", chip(), chip())
|
||||||
|
builder:build("Kenguryatnik", Vector(0), Angle(0), SCALE, Color(200, 200, 200), "sprops/textures/sprops_chrome", chip(), chip())
|
||||||
|
builder:build("AntennaSerebro", Vector(0), Angle(0), SCALE, Color(200, 200, 200), "sprops/textures/sprops_chrome", chip(), chip())
|
||||||
|
builder:build("Vihlop", Vector(0), Angle(0), SCALE, Color(200, 200, 200), "sprops/textures/sprops_chrome", chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Podtumanniki", Vector(0), Angle(0), SCALE, Color(100, 100, 100), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Nomera", Vector(0), Angle(0), SCALE, Color(54, 225, 220), "sprops/sprops_grid_orange_12x12", chip(), chip())
|
||||||
|
builder:build("Okna", Vector(0), Angle(0), SCALE, Color(0, 0, 0, 200), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Skobi", Vector(0), Angle(0), SCALE, Color(55, 55, 55, 255), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Nakladki", Vector(0), Angle(0), SCALE, Color(44, 44, 44, 255), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Black", Vector(0), Angle(0), SCALE, Color(0, 0, 0), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("SalonKraskiyCvet", Vector(0), Angle(0), SCALE, Color(225, 55, 55), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Korpus", Vector(0), Angle(0), SCALE, Color(155, 0, 0), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Salon", Vector(0), Angle(0), SCALE, Color(110, 100, 100), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Sidushki", Vector(0), Angle(0), SCALE, Color(110, 100, 100), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Vozduhovodi", Vector(0), Angle(0), SCALE, Color(50, 50, 50), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Lampochki", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Rama", Vector(0), Angle(0), SCALE, Color(80, 80, 80), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("VihlopInner", Vector(0), Angle(0), SCALE, Color(30, 30, 30), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("PerednieFari", Vector(0), Angle(0), SCALE, Color(80, 80, 80), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Steklo", Vector(0), Angle(0), SCALE, Color(255, 255, 255, 200), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("StekloZadneiFari", Vector(0), Angle(0), SCALE, Color(255, 0, 0), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("StekloZadneiFari2", Vector(0), Angle(0), SCALE, Color(225, 55, 55), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("KorpusZadneiFari", Vector(0), Angle(0), SCALE, Color(225, 55, 55), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Multimedia", Vector(0), Angle(0), SCALE, Color(225, 255, 255), "models/debug/debugwhite", chip(), chip())
|
||||||
|
|
||||||
|
builder:build("KorpusAntenni", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber2", chip(), chip())
|
||||||
|
builder:build("Shnorkel", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber2", chip(), chip())
|
||||||
|
builder:build("Plastik", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber2", chip(), chip())
|
||||||
|
builder:build("RailingPlastik", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber2", chip(), chip())
|
||||||
|
builder:build("SalonGovno", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber2", chip(), chip())
|
||||||
|
builder:build("Dvorniki", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber2", chip(), chip())
|
||||||
|
builder:build("Antenna", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber2", chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Railing", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/trans/wheels/wheel_d_rim1", chip(), chip())
|
||||||
|
|
||||||
|
local result = builder:getResult()
|
||||||
|
else
|
||||||
|
function init()
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
end
|
||||||
|
|
||||||
|
if hasPermission("http.get") and hasPermission("mesh") and hasPermission("entities.setRenderProperty", chip()) then
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
setupPermissionRequest({"http.get", "mesh", "entities.setRenderProperty"}, "", true)
|
||||||
|
|
||||||
|
hook.add("permissionrequest", "_permissionrequest", function()
|
||||||
|
if permissionRequestSatisfied() then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
43
koptilnya/models/helicopter.txt
Normal file
43
koptilnya/models/helicopter.txt
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
--@name Helicopter
|
||||||
|
--@author Opti1337
|
||||||
|
--@shared
|
||||||
|
-- @include /koptilnya/mesh_loader/builder.txt
|
||||||
|
require("/koptilnya/mesh_loader/builder.txt")
|
||||||
|
|
||||||
|
DEBUG_MODE = true
|
||||||
|
|
||||||
|
local LINK = "https://drive.google.com/uc?id=171YCCoAebzS0y1WRLQ8FZ6lyG_aZZtUB"
|
||||||
|
local SCALE = Vector(0.5)
|
||||||
|
|
||||||
|
local builder = {}
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
|
||||||
|
builder:build("heli.016", Vector(0), Angle(0), SCALE, Color(0, 203, 0), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("heli.001_heli.017", Vector(0), Angle(0), SCALE, Color(255, 225, 255, 90), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("heli.002_heli.018", Vector(0), Angle(0), SCALE, Color(255, 225, 255), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("heli.003_heli.019", Vector(0), Angle(0), SCALE, Color(231, 0, 0), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("heli.004_heli.020", Vector(0), Angle(0), SCALE, Color(96, 96, 203), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("heli.005_heli.021", Vector(0), Angle(0), SCALE, Color(130, 130, 130), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("heli.006_heli.022", Vector(0), Angle(0), SCALE, Color(255, 224, 0), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("heli.007_heli.023", Vector(0), Angle(0), SCALE, Color(255, 225, 255), "models/debug/debugwhite", chip(), chip())
|
||||||
|
|
||||||
|
builder:getResult()
|
||||||
|
else
|
||||||
|
function init()
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
end
|
||||||
|
|
||||||
|
if hasPermission("http.get") and hasPermission("mesh") and hasPermission("entities.setRenderProperty", chip()) then
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
setupPermissionRequest({"http.get", "mesh", "entities.setRenderProperty"}, "", true)
|
||||||
|
|
||||||
|
hook.add("permissionrequest", "_permissionrequest", function()
|
||||||
|
if permissionRequestSatisfied() then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
74
koptilnya/models/jdm_wheels.txt
Normal file
74
koptilnya/models/jdm_wheels.txt
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
-- @shared
|
||||||
|
-- @name JDM Wheels
|
||||||
|
-- @author Opti1337, .hemp
|
||||||
|
-- @include /koptilnya/mesh_loader/builder.txt
|
||||||
|
|
||||||
|
require("/koptilnya/mesh_loader/builder.txt")
|
||||||
|
|
||||||
|
local LINK = "https://www.dropbox.com/s/uu2tia6ac13cobu/jdmwheel1.obj?dl=1"
|
||||||
|
local SCALE = Vector(0.6)
|
||||||
|
local MATERIALS = {
|
||||||
|
Center = "models/debug/debugwhite",
|
||||||
|
Bolt = "sprops/textures/sprops_chrome",
|
||||||
|
Chrome = "sprops/trans/wheels/wheel_d_rim1",
|
||||||
|
Plastic = "sprops/textures/sprops_rubber2",
|
||||||
|
Rim = "sprops/trans/wheels/wheel_d_rim1",
|
||||||
|
RimAround = "sprops/trans/wheels/wheel_d_rim1"
|
||||||
|
}
|
||||||
|
local COLORS = {
|
||||||
|
Center = Color(45,45,45),
|
||||||
|
Bolt = Color(255, 255, 255),
|
||||||
|
Chrome = Color(255, 255, 255),
|
||||||
|
Plastic = Color(255, 255, 255),
|
||||||
|
Rim = Color(255, 255, 255),
|
||||||
|
RimAround = Color(255,255,255)
|
||||||
|
}
|
||||||
|
local OFFSET = 1
|
||||||
|
|
||||||
|
local builder = {}
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
wire.adjustPorts(
|
||||||
|
{
|
||||||
|
Wheels = "ARRAY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
|
||||||
|
hook.add("input", "_input", function(name, value)
|
||||||
|
if name == "Wheels" then
|
||||||
|
builder:reset()
|
||||||
|
|
||||||
|
for _, wheel in pairs(wire.ports.Wheels) do
|
||||||
|
builder:build("center", Vector(0, OFFSET - 0.6, 0), Angle(0), SCALE, COLORS.Center, MATERIALS.Center, wheel, wheel)
|
||||||
|
builder:build("bolt", Vector(0, OFFSET- 0.6, 0), Angle(0), SCALE, COLORS.Bolt, MATERIALS.Bolt, wheel, wheel)
|
||||||
|
builder:build("chrome", Vector(0, OFFSET - 1, 0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, wheel, wheel)
|
||||||
|
builder:build("plastic", Vector(0, OFFSET, 0), Angle(0), SCALE, COLORS.Plastic, MATERIALS.Plastic, wheel, wheel)
|
||||||
|
builder:build("rim1", Vector(0, OFFSET, 0), Angle(0), SCALE - Vector(0, 0.1, 0), COLORS.RimAround, MATERIALS.Rim, wheel, wheel)
|
||||||
|
builder:build("rimAround", Vector(0, OFFSET, 0), Angle(0), SCALE - Vector(0, 0.1, 0), COLORS.Rim, MATERIALS.RimAround, wheel, wheel)
|
||||||
|
builder:build("tyre", Vector(0, OFFSET, 0), Angle(0), SCALE - Vector(0, 0.1, 0), Color(255, 255, 255), "sprops/textures/sprops_rubber", wheel, wheel)
|
||||||
|
end
|
||||||
|
|
||||||
|
builder:getResult()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
function init()
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
end
|
||||||
|
|
||||||
|
if hasPermission("http.get") and hasPermission("mesh") and hasPermission("entities.setRenderProperty", chip()) then
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
setupPermissionRequest({"http.get", "mesh", "entities.setRenderProperty"}, "", true)
|
||||||
|
|
||||||
|
hook.add("permissionrequest", "_permissionrequest", function()
|
||||||
|
if permissionRequestSatisfied() then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
44
koptilnya/models/toyota_altezza.txt
Normal file
44
koptilnya/models/toyota_altezza.txt
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
-- @shared
|
||||||
|
-- @name Toyota Altezza
|
||||||
|
-- @author Opti1337, .hemp
|
||||||
|
-- @include /koptilnya/mesh_loader/builder.txt
|
||||||
|
require("/koptilnya/mesh_loader/builder.txt")
|
||||||
|
|
||||||
|
DEBUG_MODE = true
|
||||||
|
|
||||||
|
local LINK = "https://www.dropbox.com/s/ovw7f8q65tlcdy5/is300.obj?dl=1"
|
||||||
|
local SCALE = Vector(0.8, 0.79, 0.8)
|
||||||
|
|
||||||
|
local builder = {}
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
|
||||||
|
builder:build("body_Mesh_0", Vector(0), Angle(0), SCALE, Color(54, 225, 220), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("chrome_Mesh_1", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_chrome", chip(), chip())
|
||||||
|
builder:build("glass_Mesh_2", Vector(0), Angle(0), SCALE, Color(55, 55, 55, 200), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("hood_Mesh_3", Vector(0), Angle(0), SCALE, Color(255, 255, 255, 255), "sprops/textures/sprops_cfiber2", chip(), chip())
|
||||||
|
builder:build("interier_Mesh_4", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber2", chip(), chip())
|
||||||
|
builder:build("plastic_Mesh_5", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_rubber2", chip(), chip())
|
||||||
|
builder:build("redGlass_Mesh_6", Vector(0), Angle(0), SCALE, Color(225, 55, 55, 255), "models/debug/debugwhite", chip(), chip())
|
||||||
|
builder:build("Reshetka_Mesh_7", Vector(0), Angle(0), SCALE, Color(225, 255, 255, 255), "models/props_interiors/metalfence007a", chip(), chip())
|
||||||
|
builder:build("w_plastic_Mesh_8", Vector(0), Angle(0), SCALE, Color(225, 255, 255, 255), "models/combine_scanner/scanner_eye", chip(), chip())
|
||||||
|
|
||||||
|
builder:getResult()
|
||||||
|
else
|
||||||
|
function init()
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
end
|
||||||
|
|
||||||
|
if hasPermission("http.get") and hasPermission("mesh") and hasPermission("entities.setRenderProperty", chip()) then
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
setupPermissionRequest({"http.get", "mesh", "entities.setRenderProperty"}, "", true)
|
||||||
|
|
||||||
|
hook.add("permissionrequest", "_permissionrequest", function()
|
||||||
|
if permissionRequestSatisfied() then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
174
koptilnya/models/vaz_2106.txt
Normal file
174
koptilnya/models/vaz_2106.txt
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
-- @name VAZ 2106
|
||||||
|
-- @author Opti1337, DarkSupah
|
||||||
|
-- @include /koptilnya/mesh_loader/builder.txt
|
||||||
|
require("/koptilnya/mesh_loader/builder.txt")
|
||||||
|
|
||||||
|
local LINK = "https://www.dropbox.com/s/x2esgnl33i8if2w/vaz2106.obj?dl=1"
|
||||||
|
local SCALE = Vector(0.9)
|
||||||
|
local MATERIALS = {
|
||||||
|
Exterior = "phoenix_storms/mrref2",
|
||||||
|
Chrome = "models/shiny",
|
||||||
|
Plastic = "models/debug/debugwhite",
|
||||||
|
Glass = "phoenix_storms/mrref2",
|
||||||
|
Under = "sprops/textures/gear_metal",
|
||||||
|
DoorInterior = "sprops/textures/sprops_rubber2",
|
||||||
|
InteriorFloor = "models/debug/debugwhite",
|
||||||
|
DashboardBase = "models/debug/debugwhite",
|
||||||
|
Seats = "sprops/textures/sprops_rubber2",
|
||||||
|
Interior = "models/debug/debugwhite",
|
||||||
|
DoorHandle = "sprops/textures/sprops_chrome",
|
||||||
|
Grill = "models/debug/debugwhite",
|
||||||
|
Shelf = "models/debug/debugwhite",
|
||||||
|
Sideskirts = "models/debug/debugwhite",
|
||||||
|
Vent = "models/debug/debugwhite",
|
||||||
|
InteriorFrame = "models/debug/debugwhite",
|
||||||
|
LightsContainer = "models/debug/debugwhite",
|
||||||
|
Lights = "models/debug/debugwhite",
|
||||||
|
FrontLights = "sprops/trans/wheels/wheel_d_rim2",
|
||||||
|
Insulation = "models/debug/debugwhite",
|
||||||
|
DashButtons = "models/debug/debugwhite",
|
||||||
|
FrontLightsClose = "models/debug/debugwhite",
|
||||||
|
FrontLightsCloseGlass = "models/debug/debugwhite",
|
||||||
|
FrontLightsFar = "models/debug/debugwhite",
|
||||||
|
FrontLightsFarGlass = "models/debug/debugwhite"
|
||||||
|
}
|
||||||
|
local COLORS = {
|
||||||
|
Exterior = Color(30, 30, 30, 255),
|
||||||
|
Chrome = Color(180, 180, 180, 255),
|
||||||
|
Plastic = Color(110, 110, 110, 255),
|
||||||
|
Glass = Color(50, 50, 50, 200),
|
||||||
|
Under = Color(150, 150, 150, 255),
|
||||||
|
DoorInterior = Color(120, 120, 120, 255),
|
||||||
|
InteriorFloor = Color(30, 30, 30, 255),
|
||||||
|
DashboardBase = Color(30, 30, 30, 255),
|
||||||
|
Seats = Color(150, 150, 150, 255),
|
||||||
|
InteriorRoof = Color(30, 30, 30, 255),
|
||||||
|
DoorHandle = Color(210, 210, 210, 255),
|
||||||
|
Grill = Color(30, 30, 30, 255),
|
||||||
|
Shelf = Color(30, 30, 30, 255),
|
||||||
|
Sideskirts = Color(30, 30, 30, 255),
|
||||||
|
Vent = Color(40, 40, 40, 255),
|
||||||
|
InteriorFrame = Color(30, 30, 30, 255),
|
||||||
|
LightsContainer = Color(50, 50, 50, 255),
|
||||||
|
ReverseLights = Color(240, 240, 240, 255),
|
||||||
|
Blinkers = Color(255, 140, 0, 255),
|
||||||
|
FrontParkingLights = Color(190, 190, 190, 255),
|
||||||
|
RearParkingLights = Color(180, 80, 50, 255),
|
||||||
|
StopLights = Color(220, 60, 20, 255),
|
||||||
|
Insulation = Color(60, 60, 60, 255),
|
||||||
|
DashButtons = Color(60, 60, 60, 255),
|
||||||
|
FrontLightsClose = Color(130, 130, 130, 255),
|
||||||
|
FrontLightsCloseGlass = Color(245, 240, 240, 255),
|
||||||
|
FrontLightsFar = Color(130, 130, 130, 255),
|
||||||
|
FrontLightsFarGlass = Color(255, 220, 40, 255)
|
||||||
|
}
|
||||||
|
|
||||||
|
local builder = {}
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
|
||||||
|
builder:build("Body__Exterior", Vector(0), Angle(0), SCALE, COLORS.Exterior, MATERIALS.Exterior, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Glass", Vector(0), Angle(0), SCALE, COLORS.Glass, MATERIALS.Glass, chip(), chip())
|
||||||
|
builder:build("Body__WindowsLine__Rubber", Vector(0), Angle(0), SCALE, COLORS.Insulation, MATERIALS.Insulation, chip(), chip())
|
||||||
|
builder:build("Body__TrunkLine__Rubber", Vector(0), Angle(0), SCALE, COLORS.Insulation, MATERIALS.Insulation, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__DoorLocks__Locks", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__TrunkPinstripe__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__FuelCapLine__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__Under__Bottom", Vector(0), Angle(0), SCALE, COLORS.Under, MATERIALS.Under, chip(), chip())
|
||||||
|
builder:build("Body__Misc__Exterior", Vector(0), Angle(0), SCALE, COLORS.Exterior, MATERIALS.Exterior, chip(), chip())
|
||||||
|
builder:build("Interior__Seats__Seat", Vector(0), Angle(0), SCALE, COLORS.Seats, MATERIALS.Seats, chip(), chip())
|
||||||
|
builder:build("Interior__RoofCover__InteriorRoof", Vector(0), Angle(0), SCALE, COLORS.InteriorRoof, MATERIALS.Interior, chip(), chip())
|
||||||
|
builder:build("Body__Grill__GrillPlastic", Vector(0), Angle(0), SCALE, COLORS.Grill, MATERIALS.Grill, chip(), chip())
|
||||||
|
builder:build("Body__FrontLightsFrame__Plastic", Vector(0), Angle(0), SCALE, COLORS.Grill, MATERIALS.Grill, chip(), chip())
|
||||||
|
builder:build("Interior__RearPanel__Panel", Vector(0), Angle(0), SCALE, COLORS.Shelf, MATERIALS.Shelf, chip(), chip())
|
||||||
|
builder:build("Body__Sideskirts__Plastic", Vector(0), Angle(0), SCALE, COLORS.Sideskirts, MATERIALS.Sideskirts, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__DoorsFrame__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__FrontBumper__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
builder:build("Body__FrontBumper__Plastic", Vector(0), Angle(0), SCALE, COLORS.Plastic, MATERIALS.Plastic, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__RearBumper__Chrome", Vector(2, 0, 0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
builder:build("Body__RearBumper__Plastic", Vector(2, 0, 0), Angle(0), SCALE, COLORS.Plastic, MATERIALS.Plastic, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Interior__Floor__InteriorFloor", Vector(0), Angle(0), SCALE, COLORS.InteriorFloor, MATERIALS.InteriorFloor, chip(), chip())
|
||||||
|
builder:build("Interior__DashBase__Dashboard", Vector(0), Angle(0), SCALE, COLORS.DashboardBase, MATERIALS.DashboardBase, chip(), chip())
|
||||||
|
builder:build("Dashboard__Vents__Vents", Vector(0), Angle(0), SCALE, COLORS.Vent, MATERIALS.Vent, chip(), chip())
|
||||||
|
builder:build("Dashboard__Buttons__Buttons", Vector(0), Angle(0), SCALE, COLORS.DashButtons, MATERIALS.DashButtons, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__InteriorFrame__Plastic", Vector(0), Angle(0), SCALE, COLORS.InteriorFrame, MATERIALS.InteriorFrame, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("FrontLights__BlinkerBase__Plastic", Vector(0), Angle(0), SCALE, COLORS.LightsContainer, MATERIALS.LightsContainer, chip(), chip())
|
||||||
|
builder:build("Body__RearLightsContainer__Plastic", Vector(0), Angle(0), SCALE, COLORS.LightsContainer, MATERIALS.LightsContainer, chip(), chip())
|
||||||
|
builder:build("Body__RearLightHolders__Plastic", Vector(0), Angle(0), SCALE, COLORS.LightsContainer, MATERIALS.LightsContainer, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__FrontLights__CloseLight", Vector(0), Angle(0), SCALE, COLORS.FrontLightsClose, MATERIALS.FrontLightsClose, chip(), chip())
|
||||||
|
builder:build("Body__CloseLights__Glass", Vector(0), Angle(0), SCALE, COLORS.FrontLightsCloseGlass, MATERIALS.FrontLightsCloseGlass, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__FrontLights__FarLight", Vector(0), Angle(0), SCALE, COLORS.FrontLightsFar, MATERIALS.FrontLightsFar, chip(), chip())
|
||||||
|
builder:build("Body__FarLights__Glass", Vector(0), Angle(0), SCALE, COLORS.FrontLightsFarGlass, MATERIALS.FrontLightsFarGlass, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__ReverseLights__ReverseLight", Vector(0), Angle(0), SCALE, COLORS.ReverseLights, MATERIALS.Lights, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__LeftBlinkers__Blinker", Vector(0), Angle(0), SCALE, COLORS.Blinkers, MATERIALS.Lights, chip(), chip())
|
||||||
|
builder:build("Body__RightBlinkers__Blinker", Vector(0), Angle(0), SCALE, COLORS.Blinkers, MATERIALS.Lights, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__ParkingLights__ParkingLight", Vector(0), Angle(0), SCALE, COLORS.RearParkingLights, MATERIALS.Lights, chip(), chip())
|
||||||
|
builder:build("FrontLights__ParkingLights__ParkingLights2", Vector(0), Angle(0), SCALE, COLORS.FrontParkingLights, MATERIALS.Lights, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__StopLights__StopLights", Vector(0), Angle(0), SCALE, COLORS.StopLights, MATERIALS.Lights, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__Hood__Exterior", Vector(0), Angle(0), SCALE, COLORS.Exterior, MATERIALS.Exterior, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__Trunk__Exterior", Vector(0), Angle(0), SCALE, COLORS.Exterior, MATERIALS.Exterior, chip(), chip())
|
||||||
|
builder:build("Trunk__Strip__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
builder:build("Trunk__Button__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__LeftFrontDoor__Exterior", Vector(0), Angle(0), SCALE, COLORS.Exterior, MATERIALS.Exterior, chip(), chip())
|
||||||
|
builder:build("LeftFrontDoor__Frame__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
builder:build("LeftFrontDoor__Glass__Glass", Vector(0), Angle(0), SCALE, COLORS.Glass, MATERIALS.Glass, chip(), chip())
|
||||||
|
builder:build("LeftFrontDoor__Interior__DoorInterior", Vector(0), Angle(0), SCALE, COLORS.DoorInterior, MATERIALS.DoorInterior, chip(), chip())
|
||||||
|
builder:build("LeftFrontDoor__Handle__Chrome", Vector(0), Angle(0), SCALE, COLORS.DoorHandle, MATERIALS.DoorHandle, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__RightFrontDoor__Exterior", Vector(0), Angle(0), SCALE, COLORS.Exterior, MATERIALS.Exterior, chip(), chip())
|
||||||
|
builder:build("RightFrontDoor__Frame__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
builder:build("RightFrontDoor__Glass__Glass", Vector(0), Angle(0), SCALE, COLORS.Glass, MATERIALS.Glass, chip(), chip())
|
||||||
|
builder:build("RightFrontDoor__Interior__DoorInterior", Vector(0), Angle(0), SCALE, COLORS.DoorInterior, MATERIALS.DoorInterior, chip(), chip())
|
||||||
|
builder:build("RightFrontDoor__Handle__Chrome", Vector(0), Angle(0), SCALE, COLORS.DoorHandle, MATERIALS.DoorHandle, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__LeftRearDoor__Exterior", Vector(0), Angle(0), SCALE, COLORS.Exterior, MATERIALS.Exterior, chip(), chip())
|
||||||
|
builder:build("LeftRearDoor__Frame__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
builder:build("LeftRearDoor__Glass__Glass", Vector(0), Angle(0), SCALE, COLORS.Glass, MATERIALS.Glass, chip(), chip())
|
||||||
|
builder:build("LeftRearDoor__Interior__DoorInterior", Vector(0), Angle(0), SCALE, COLORS.DoorInterior, MATERIALS.DoorInterior, chip(), chip())
|
||||||
|
builder:build("LeftRearDoor__Handle__Chrome", Vector(0), Angle(0), SCALE, COLORS.DoorHandle, MATERIALS.DoorHandle, chip(), chip())
|
||||||
|
|
||||||
|
builder:build("Body__RightRearDoor__Exterior", Vector(0), Angle(0), SCALE, COLORS.Exterior, MATERIALS.Exterior, chip(), chip())
|
||||||
|
builder:build("RightRearDoor__Frame__Chrome", Vector(0), Angle(0), SCALE, COLORS.Chrome, MATERIALS.Chrome, chip(), chip())
|
||||||
|
builder:build("RightRearDoor__Glass__Glass", Vector(0), Angle(0), SCALE, COLORS.Glass, MATERIALS.Glass, chip(), chip())
|
||||||
|
builder:build("RightRearDoor__Interior__DoorInterior", Vector(0), Angle(0), SCALE, COLORS.DoorInterior, MATERIALS.DoorInterior, chip(), chip())
|
||||||
|
builder:build("RightRearDoor__Handle__Chrome", Vector(0), Angle(0), SCALE, COLORS.DoorHandle, MATERIALS.DoorHandle, chip(), chip())
|
||||||
|
|
||||||
|
builder:getResult()
|
||||||
|
else
|
||||||
|
function init()
|
||||||
|
builder = MeshBuilder:new(LINK)
|
||||||
|
end
|
||||||
|
|
||||||
|
if hasPermission("http.get") and hasPermission("mesh") and hasPermission("entities.setRenderProperty", chip()) then
|
||||||
|
init()
|
||||||
|
else
|
||||||
|
setupPermissionRequest({"http.get", "mesh", "entities.setRenderProperty"}, "", true)
|
||||||
|
|
||||||
|
hook.add("permissionrequest", "_permissionrequest", function()
|
||||||
|
if permissionRequestSatisfied() then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,32 +0,0 @@
|
|||||||
--@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
|
|
||||||
5
koptilnya/steering/input.txt
Normal file
5
koptilnya/steering/input.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Input = class("Input")
|
||||||
|
|
||||||
|
function Input:initialize(keyMap)
|
||||||
|
|
||||||
|
end
|
||||||
@ -14,39 +14,43 @@ local frontConfig = {
|
|||||||
Camber = -5,
|
Camber = -5,
|
||||||
Caster = 5,
|
Caster = 5,
|
||||||
Ackermann = 1.1,
|
Ackermann = 1.1,
|
||||||
Lock = 50
|
Lock = 50,
|
||||||
|
CorrectionOn = 0.8,
|
||||||
|
CorrectionOff = 0.2
|
||||||
}
|
}
|
||||||
local rearConfig = {
|
local rearConfig = {
|
||||||
Camber = -5,
|
Camber = -5,
|
||||||
Caster = -5,
|
Caster = -5,
|
||||||
Ackermann = 1.2,
|
Ackermann = 1.2,
|
||||||
Lock = 5
|
Lock = 5,
|
||||||
|
CorrectionOn = 0.8,
|
||||||
|
CorrectionOff = 0.2
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Fucking slaves, get you ass back here
|
-- Fucking slaves, get you ass back here
|
||||||
local SLAVES = {
|
local _slaves = {
|
||||||
E1 = "entity",
|
E1 = "entity",
|
||||||
E2 = "entity",
|
E2 = "entity",
|
||||||
E3 = "entity",
|
E3 = "entity",
|
||||||
E4 = "entity"
|
E4 = "entity"
|
||||||
}
|
}
|
||||||
|
|
||||||
local AXLES = {SteerAxle:new(frontConfig, wire.ports.E1, wire.ports.E2),
|
local _axles = {SteerAxle:new(frontConfig, wire.ports.E1, wire.ports.E2),
|
||||||
SteerAxle:new(rearConfig, wire.ports.E3, wire.ports.E4)}
|
SteerAxle:new(rearConfig, wire.ports.E3, wire.ports.E4)}
|
||||||
|
|
||||||
local INPUTS = {
|
local _inputs = {
|
||||||
Base = "entity",
|
Base = "entity",
|
||||||
Seat = "entity"
|
Seat = "entity"
|
||||||
}
|
}
|
||||||
|
|
||||||
local OUTPUTS = {
|
local _outputs = {
|
||||||
SteerNormalized = "number",
|
SteerNormalized = "number",
|
||||||
Driver = "entity"
|
Driver = "entity"
|
||||||
}
|
}
|
||||||
|
|
||||||
local ALL_INPUTS = table.merge(INPUTS, SLAVES)
|
local _allInputs = table.merge(_inputs, _slaves)
|
||||||
|
|
||||||
wire.adjustPorts(ALL_INPUTS, OUTPUTS)
|
wire.adjustPorts(_allInputs, _outputs)
|
||||||
|
|
||||||
local steeringController = SteeringController:new(wire.ports.Base)
|
local steeringController = SteeringController:new(wire.ports.Base)
|
||||||
|
|
||||||
|
|||||||
@ -9,5 +9,15 @@ function SteerAxle:initialize(config, leftWheel, rightWheel)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function SteerAxle:update()
|
function SteerAxle:update()
|
||||||
|
self:_updateSlave(self.leftWheel)
|
||||||
|
self:_updateSlave(self.rightWheel)
|
||||||
|
end
|
||||||
|
|
||||||
|
function SteerAxle:_updateSlave(slave)
|
||||||
|
if slave:isValid() and not slave:isPlayerHolding() then
|
||||||
|
slave:setAngles(base:localToWorldAngles(Angle(0, 0, 0)))
|
||||||
|
if not slave:isFrozen() then
|
||||||
|
slave:setFrozen()
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
580
koptilnya/torque_editor.txt
Normal file
580
koptilnya/torque_editor.txt
Normal file
@ -0,0 +1,580 @@
|
|||||||
|
-- @name Torque editor
|
||||||
|
-- @author Opti1337
|
||||||
|
-- @shared
|
||||||
|
-- @include /koptilnya/libs/render.txt
|
||||||
|
-- @include /koptilnya/gui/render_devices/hud.txt
|
||||||
|
-- @include /koptilnya/gui/gui.txt
|
||||||
|
-- @include /koptilnya/gui/elements/panel.txt
|
||||||
|
-- @include /koptilnya/gui/elements/label.txt
|
||||||
|
-- @include /koptilnya/gui/elements/shape.txt
|
||||||
|
-- @include /koptilnya/gui/elements/button.txt
|
||||||
|
-- @include /koptilnya/gui/segoe_mdl2_assets_icons.txt
|
||||||
|
local points = {Vector(0, 0)}
|
||||||
|
local zoom = 1
|
||||||
|
local zoomBase = 100
|
||||||
|
local scroll = 0
|
||||||
|
|
||||||
|
if SERVER then
|
||||||
|
local user
|
||||||
|
|
||||||
|
wire.adjustPorts({Seat = "ENTITY"}, {})
|
||||||
|
|
||||||
|
local function setUser(ply)
|
||||||
|
user = ply
|
||||||
|
|
||||||
|
net.start("setUser")
|
||||||
|
net.writeEntity(ply)
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function resetUser()
|
||||||
|
user = nil
|
||||||
|
|
||||||
|
net.start("resetUser")
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
|
||||||
|
hook.add("ClientInitialized", "_ClientInitialized", function(ply)
|
||||||
|
net.start("init")
|
||||||
|
net.writeFloat(zoom)
|
||||||
|
net.writeFloat(scroll)
|
||||||
|
net.writeTable(points)
|
||||||
|
net.send(ply)
|
||||||
|
end)
|
||||||
|
|
||||||
|
net.receive("settings", function(len, ply)
|
||||||
|
zoom = net.readFloat()
|
||||||
|
scroll = net.readFloat()
|
||||||
|
|
||||||
|
net.start("settings")
|
||||||
|
net.writeFloat(zoom)
|
||||||
|
net.writeFloat(scroll)
|
||||||
|
net.send(find.allPlayers(function(p)
|
||||||
|
return p ~= ply
|
||||||
|
end))
|
||||||
|
end)
|
||||||
|
|
||||||
|
net.receive("points", function(len, ply)
|
||||||
|
points = net.readTable()
|
||||||
|
|
||||||
|
net.start("points")
|
||||||
|
net.writeTable(points)
|
||||||
|
net.send(find.allPlayers(function(p)
|
||||||
|
return p ~= ply
|
||||||
|
end))
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("PlayerEnteredVehicle", "_PlayerEnteredVehicle", function(ply, veh)
|
||||||
|
if veh == wire.ports.Seat then
|
||||||
|
setUser(ply)
|
||||||
|
|
||||||
|
enableHud(ply, true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("PlayerLeaveVehicle", "_PlayerLeaveVehicle", function(ply, veh)
|
||||||
|
if veh == wire.ports.Seat then
|
||||||
|
resetUser()
|
||||||
|
|
||||||
|
enableHud(ply, false)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
require("/koptilnya/libs/render.txt")
|
||||||
|
require("/koptilnya/gui/render_devices/hud.txt")
|
||||||
|
require("/koptilnya/gui/gui.txt")
|
||||||
|
require("/koptilnya/gui/elements/panel.txt")
|
||||||
|
require("/koptilnya/gui/elements/label.txt")
|
||||||
|
require("/koptilnya/gui/elements/shape.txt")
|
||||||
|
require("/koptilnya/gui/elements/button.txt")
|
||||||
|
|
||||||
|
local segoeIcons = require("/koptilnya/gui/segoe_mdl2_assets_icons.txt")
|
||||||
|
|
||||||
|
local labelsFont = render.createFont("Roboto", 16, 400, true)
|
||||||
|
local numbersFont = render.createFont("Roboto Mono", 20)
|
||||||
|
local scr = {w = 682, h = 512}
|
||||||
|
local padding = 61
|
||||||
|
local workspace = {x = padding, y = 0, w = scr.w - padding, h = scr.h - padding}
|
||||||
|
local gridSize = Vector(100, 1)
|
||||||
|
local zoomSteps = {0.05, 0.1, 0.25, 0.5, 1, 2, 4}
|
||||||
|
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
setupPermissionRequest({"file.write", "file.read", "input"}, "", false)
|
||||||
|
|
||||||
|
local cellSize = Vector((workspace.w - 1) / gridSize.x, workspace.h / gridSize.y)
|
||||||
|
|
||||||
|
local crosshair
|
||||||
|
local user
|
||||||
|
|
||||||
|
local function sendSettings()
|
||||||
|
net.start("settings")
|
||||||
|
net.writeFloat(zoom)
|
||||||
|
net.writeFloat(scroll)
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sendPoints()
|
||||||
|
net.start("points")
|
||||||
|
net.writeTable(points)
|
||||||
|
net.send()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function cursorIntersectWorkspace(x, y)
|
||||||
|
x = x >= workspace.x and x < workspace.x + workspace.w
|
||||||
|
y = y >= workspace.y and y <= workspace.y + workspace.h
|
||||||
|
|
||||||
|
return x and y
|
||||||
|
end
|
||||||
|
|
||||||
|
local function fromWorkspacePos(x, y)
|
||||||
|
return workspace.x + x, workspace.y + workspace.h - 1 - y
|
||||||
|
end
|
||||||
|
|
||||||
|
local function toWorkspacePos(x, y)
|
||||||
|
return x - workspace.x, workspace.y + workspace.h - 1 - y
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getNearestGridPoint(x, y)
|
||||||
|
x, y = toWorkspacePos(x, y)
|
||||||
|
|
||||||
|
x = math.clamp(x, 0, workspace.w - 1)
|
||||||
|
y = math.clamp(y, 0, workspace.h - 1)
|
||||||
|
|
||||||
|
x = math.round(x / cellSize.x) * cellSize.x
|
||||||
|
y = math.round(y / cellSize.y) * cellSize.y
|
||||||
|
|
||||||
|
x, y = fromWorkspacePos(x, y)
|
||||||
|
|
||||||
|
return x, y
|
||||||
|
end
|
||||||
|
|
||||||
|
local function zoomIn()
|
||||||
|
local zoomId = table.keyFromValue(zoomSteps, zoom)
|
||||||
|
|
||||||
|
local nextZoom
|
||||||
|
if zoomId < #zoomSteps then
|
||||||
|
nextZoom = zoomSteps[zoomId + 1]
|
||||||
|
zoom = nextZoom
|
||||||
|
|
||||||
|
sendSettings()
|
||||||
|
end
|
||||||
|
|
||||||
|
return nextZoom
|
||||||
|
end
|
||||||
|
|
||||||
|
local function zoomOut()
|
||||||
|
local zoomId = table.keyFromValue(zoomSteps, zoom)
|
||||||
|
|
||||||
|
local prevZoom
|
||||||
|
if zoomId > 1 then
|
||||||
|
prevZoom = zoomSteps[zoomId - 1]
|
||||||
|
zoom = prevZoom
|
||||||
|
|
||||||
|
sendSettings()
|
||||||
|
end
|
||||||
|
|
||||||
|
return prevZoom
|
||||||
|
end
|
||||||
|
|
||||||
|
local function scrollUp()
|
||||||
|
scroll = scroll + 1
|
||||||
|
|
||||||
|
sendSettings()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function scrollDown()
|
||||||
|
scroll = math.max(scroll - 1, 0)
|
||||||
|
|
||||||
|
sendSettings()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function addPoint()
|
||||||
|
if crosshair ~= nil then
|
||||||
|
local x, y = toWorkspacePos(crosshair.x, crosshair.y)
|
||||||
|
|
||||||
|
x = math.round(x / cellSize.x)
|
||||||
|
y = y / (workspace.h - 1) * (zoomBase / zoom) + (zoomBase / zoom / 10 * scroll)
|
||||||
|
|
||||||
|
--- GOVNO ----------------------------
|
||||||
|
|
||||||
|
local replaceId
|
||||||
|
for i, point in ipairs(points) do
|
||||||
|
if point.x == x then
|
||||||
|
replaceId = i
|
||||||
|
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if replaceId ~= nil then
|
||||||
|
points[replaceId] = Vector(x, y)
|
||||||
|
else
|
||||||
|
table.insert(points, Vector(x, y))
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sortByMember(points, "x", true)
|
||||||
|
|
||||||
|
sendPoints()
|
||||||
|
|
||||||
|
--- KONEC GOVNA ----------------------
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function removePoint()
|
||||||
|
if crosshair ~= nil then
|
||||||
|
local x, y = toWorkspacePos(crosshair.x, crosshair.y)
|
||||||
|
|
||||||
|
x = math.round(x / cellSize.x)
|
||||||
|
y = y / (workspace.h - 1) * (zoomBase / zoom) + (zoomBase / zoom / 10 * scroll)
|
||||||
|
|
||||||
|
--- GOVNO ----------------------------
|
||||||
|
|
||||||
|
local replaceId
|
||||||
|
for i, point in ipairs(points) do
|
||||||
|
if point.x == x then
|
||||||
|
replaceId = i
|
||||||
|
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if replaceId ~= nil then
|
||||||
|
table.remove(points, replaceId)
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sortByMember(points, "x", true)
|
||||||
|
|
||||||
|
sendPoints()
|
||||||
|
|
||||||
|
--- KONEC GOVNA ----------------------
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getTorqueAt(t)
|
||||||
|
if #points == 0 then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
if t == 0 then
|
||||||
|
return points[1].y
|
||||||
|
elseif t == 100 then
|
||||||
|
return points[#points].y
|
||||||
|
else
|
||||||
|
local segment
|
||||||
|
|
||||||
|
local prevPoint
|
||||||
|
for k, point in pairs(points) do
|
||||||
|
if t <= point.x then
|
||||||
|
segment = {prevPoint, point}
|
||||||
|
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
prevPoint = point
|
||||||
|
end
|
||||||
|
|
||||||
|
return math.lerp((t - segment[1].x) / (segment[2].x - segment[1].x), segment[1].y, segment[2].y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function exportPoints()
|
||||||
|
if not hasPermission("file.write") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local result = ""
|
||||||
|
|
||||||
|
for k, v in pairs(points) do
|
||||||
|
result = result .. "\tVector(" .. (v.x / 100) .. ", " .. v.y .. ")"
|
||||||
|
|
||||||
|
if k ~= #points then
|
||||||
|
result = result .. ",\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result = "array(\n" .. result
|
||||||
|
result = result .. "\n)"
|
||||||
|
|
||||||
|
file.write("torque_export_result.txt", result)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function exportTorqueMap()
|
||||||
|
if not hasPermission("file.write") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local result = ""
|
||||||
|
|
||||||
|
for i = 0, 100 do
|
||||||
|
result = result .. "\t" .. getTorqueAt(i)
|
||||||
|
|
||||||
|
if i ~= 100 then
|
||||||
|
result = result .. ",\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result = "array(\n" .. result
|
||||||
|
result = result .. "\n)"
|
||||||
|
|
||||||
|
file.write("torque_export_result.txt", result)
|
||||||
|
end
|
||||||
|
|
||||||
|
net.receive("setUser", function()
|
||||||
|
net.readEntity(function(ent)
|
||||||
|
user = ent
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
net.receive("resetUser", function()
|
||||||
|
user = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
net.receive("init", function()
|
||||||
|
zoom = net.readFloat()
|
||||||
|
scroll = net.readFloat()
|
||||||
|
points = net.readTable()
|
||||||
|
end)
|
||||||
|
|
||||||
|
net.receive("settings", function()
|
||||||
|
zoom = net.readFloat()
|
||||||
|
scroll = net.readFloat()
|
||||||
|
end)
|
||||||
|
|
||||||
|
net.receive("points", function()
|
||||||
|
points = net.readTable()
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("hudconnected", "_hudconnected", function()
|
||||||
|
-- renderDevice:setPlayer()
|
||||||
|
if not hasPermission("file.write") or not hasPermission("file.read") then
|
||||||
|
sendPermissionRequest()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("huddisconnected", "_huddisconnected", function()
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("inputPressed", "_inputPressed", function(button)
|
||||||
|
if not hasPermission("input") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if player() == user then
|
||||||
|
local keyName = input.getKeyName(button)
|
||||||
|
|
||||||
|
if keyName == "t" then
|
||||||
|
input.enableCursor(input.getCursorVisible())
|
||||||
|
elseif keyName == "MOUSE1" then
|
||||||
|
if not input.getCursorVisible() then
|
||||||
|
addPoint()
|
||||||
|
end
|
||||||
|
elseif keyName == "MOUSE2" then
|
||||||
|
if not input.getCursorVisible() then
|
||||||
|
removePoint()
|
||||||
|
end
|
||||||
|
elseif keyName == "MWHEELUP" then
|
||||||
|
if input.isShiftDown() then
|
||||||
|
zoomIn()
|
||||||
|
else
|
||||||
|
scrollUp()
|
||||||
|
end
|
||||||
|
elseif keyName == "MWHEELDOWN" then
|
||||||
|
if input.isShiftDown() then
|
||||||
|
zoomOut()
|
||||||
|
else
|
||||||
|
scrollDown()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.add("render", "_render", function()
|
||||||
|
local cursorX, cursorY
|
||||||
|
|
||||||
|
if isValid(user) then
|
||||||
|
cursorX, cursorY = render.cursorPos(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
local x, y
|
||||||
|
|
||||||
|
--- Background
|
||||||
|
x, y = fromWorkspacePos(0, workspace.h - 1)
|
||||||
|
|
||||||
|
render.setColor(Color(15, 15, 15))
|
||||||
|
render.drawRectFast(x, y, workspace.w, workspace.h)
|
||||||
|
|
||||||
|
render.setColor(Color(40, 40, 40))
|
||||||
|
render.setFont(labelsFont)
|
||||||
|
|
||||||
|
--- Throttle axis label
|
||||||
|
x, y = fromWorkspacePos(30, 31)
|
||||||
|
|
||||||
|
render.drawRectFast(x, y, 20, 1)
|
||||||
|
render.drawSimpleText(x + 22, y - 8, "RPM")
|
||||||
|
|
||||||
|
--- Torque axis label
|
||||||
|
x, y = fromWorkspacePos(30, 50)
|
||||||
|
|
||||||
|
render.drawRectFast(x, y, 1, 20)
|
||||||
|
render.drawRotatedSimpleText(x - 8, y - 2, "Torque", -90)
|
||||||
|
|
||||||
|
render.setColor(Color(255, 255, 255))
|
||||||
|
|
||||||
|
--- Throttle axis
|
||||||
|
x, y = fromWorkspacePos(0, 0)
|
||||||
|
|
||||||
|
render.drawRectFast(x, y, workspace.w, 1)
|
||||||
|
|
||||||
|
--- Torque axis
|
||||||
|
x, y = fromWorkspacePos(0, workspace.h - 1)
|
||||||
|
|
||||||
|
render.drawRectFast(x, y, 1, workspace.h)
|
||||||
|
|
||||||
|
--- Axes lines & numbers
|
||||||
|
for i = 1, 10 do
|
||||||
|
|
||||||
|
--- Throttle axis
|
||||||
|
local segmentSize = (workspace.w - 1) / 10
|
||||||
|
|
||||||
|
x, y = fromWorkspacePos(segmentSize * i, 0)
|
||||||
|
|
||||||
|
local length = 20
|
||||||
|
local text = tostring(math.remap(i, 0, 10, 1000, 6000)) -- tostring(i * 10)
|
||||||
|
|
||||||
|
render.drawRect(x, y - 20, 1, 20)
|
||||||
|
render.drawRect(x - segmentSize / 2, y - 10, 1, 10)
|
||||||
|
|
||||||
|
render.setFont(numbersFont)
|
||||||
|
render.drawSimpleText(x - (9 * #text), y, text)
|
||||||
|
|
||||||
|
--- Torque axis
|
||||||
|
segmentSize = (workspace.h - 1) / 10
|
||||||
|
x, y = fromWorkspacePos(0, segmentSize * i)
|
||||||
|
text = tostring(zoomBase / zoom / 10 * (i + scroll))
|
||||||
|
|
||||||
|
render.drawRect(x, y, 20, 1)
|
||||||
|
render.drawRect(x, y + segmentSize / 2, 10, 1)
|
||||||
|
|
||||||
|
render.setFont(numbersFont)
|
||||||
|
render.drawSimpleText(x - (10 * #text), y - 2, text)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Zero
|
||||||
|
x, y = fromWorkspacePos(-40, 0)
|
||||||
|
|
||||||
|
render.setFont(numbersFont)
|
||||||
|
render.drawSimpleText(x, y, "1000")
|
||||||
|
|
||||||
|
if cursorX ~= nil and cursorIntersectWorkspace(cursorX, cursorY) then
|
||||||
|
x, y = fromWorkspacePos(0, workspace.h - 1)
|
||||||
|
cursorX = getNearestGridPoint(cursorX, cursorY)
|
||||||
|
cursorY = math.clamp(cursorY, workspace.y, workspace.y + workspace.h - 1)
|
||||||
|
|
||||||
|
crosshair = {x = cursorX, y = cursorY}
|
||||||
|
|
||||||
|
render.setColor(Color(60, 60, 60, 200))
|
||||||
|
render.drawRect(x, cursorY, workspace.w, 1)
|
||||||
|
render.drawRect(cursorX, y, 1, workspace.h)
|
||||||
|
else
|
||||||
|
crosshair = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
render.setColor(Color(255, 150, 50))
|
||||||
|
|
||||||
|
local prevPointData
|
||||||
|
for _, point in pairs(points) do
|
||||||
|
x, y = fromWorkspacePos(cellSize.x * point.x, (workspace.h - 1) / (zoomBase / zoom) * point.y - ((workspace.h - 1) / 10 * scroll))
|
||||||
|
|
||||||
|
if prevPointData ~= nil then
|
||||||
|
render.drawLine(prevPointData.x, prevPointData.y, x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
render.drawRect(x - 1, y - 1, 3, 3)
|
||||||
|
|
||||||
|
prevPointData = {point = point, x = x, y = y}
|
||||||
|
end
|
||||||
|
--[[
|
||||||
|
local t = (math.cos(timer.curtime() * 0.5) + 1) / 2 * 100
|
||||||
|
|
||||||
|
x, y = fromWorkspacePos(cellSize.x * t, (workspace.h - 1) / (zoomBase / zoom) * getTorqueAt(t) - ((workspace.h - 1) / 10 * scroll))
|
||||||
|
|
||||||
|
render.setColor(Color(0, 0, 255, 180))
|
||||||
|
render.drawRect(x - 3, y - 3, 7, 7)
|
||||||
|
|
||||||
|
render.drawRect(x, workspace.y, 1, workspace.h)
|
||||||
|
]]
|
||||||
|
end)
|
||||||
|
|
||||||
|
local renderDevice = RenderDeviceHUD:new()
|
||||||
|
local scrW, scrH = 1920, 1080
|
||||||
|
|
||||||
|
local gui = GUI:new(renderDevice)
|
||||||
|
|
||||||
|
local panel = EPanel:new()
|
||||||
|
panel:setTitle("Torque Editor")
|
||||||
|
panel:setDraggable(false)
|
||||||
|
panel:setMinimizable(false)
|
||||||
|
panel:setCloseable(false)
|
||||||
|
panel:setPos(scrW - 180 - 20, scrH - 226 - 20)
|
||||||
|
panel:setSize(180, 226)
|
||||||
|
gui:add(panel)
|
||||||
|
|
||||||
|
local importButton = EButton:new()
|
||||||
|
importButton:setPos(11, 43)
|
||||||
|
importButton:setSize(158, 24)
|
||||||
|
importButton:setText("Import")
|
||||||
|
importButton.onMousePressed = function(_, x, y, key, keyName)
|
||||||
|
if keyName == "MOUSE1" then
|
||||||
|
end
|
||||||
|
end
|
||||||
|
panel:addChild(importButton)
|
||||||
|
|
||||||
|
local dividerShape = EShape:new()
|
||||||
|
dividerShape:setPos(11, 82)
|
||||||
|
dividerShape:setSize(158, 1)
|
||||||
|
dividerShape:setColor(Color(60, 60, 60))
|
||||||
|
panel:addChild(dividerShape)
|
||||||
|
|
||||||
|
local exportLabel = ELabel:new()
|
||||||
|
exportLabel:setPos(11, 97)
|
||||||
|
exportLabel:setText("Export as")
|
||||||
|
panel:addChild(exportLabel)
|
||||||
|
|
||||||
|
--[[
|
||||||
|
local exportCurveButton = EButton:new()
|
||||||
|
exportCurveButton:setPos(11, 123)
|
||||||
|
exportCurveButton:setText("Points array")
|
||||||
|
exportCurveButton:setSize(158, 24)
|
||||||
|
exportCurveButton.onMousePressed = function(_, x, y, key, keyName)
|
||||||
|
if keyName == "MOUSE1" then
|
||||||
|
exportPoints()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
panel:addChild(exportCurveButton)
|
||||||
|
]]
|
||||||
|
|
||||||
|
local pointsArrayLabel = ELabel:new()
|
||||||
|
pointsArrayLabel:setPos(11, 123)
|
||||||
|
pointsArrayLabel:setText("Points array")
|
||||||
|
pointsArrayLabel:setColorScheme(Color(200, 200, 200))
|
||||||
|
panel:addChild(pointsArrayLabel)
|
||||||
|
|
||||||
|
local exportMapButton = EButton:new()
|
||||||
|
exportMapButton:setPos(11, 157)
|
||||||
|
exportMapButton:setText("Torque map")
|
||||||
|
exportMapButton:setSize(158, 24)
|
||||||
|
exportMapButton.onMousePressed = function(_, x, y, key, keyName)
|
||||||
|
if keyName == "MOUSE1" then
|
||||||
|
exportTorqueMap()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
panel:addChild(exportMapButton)
|
||||||
|
|
||||||
|
local pointsCountLabel = ELabel:new()
|
||||||
|
pointsCountLabel:setPos(11, 200)
|
||||||
|
pointsCountLabel:setText("Points count: " .. #points)
|
||||||
|
panel:addChild(pointsCountLabel)
|
||||||
Loading…
x
Reference in New Issue
Block a user