Nikita Kruglickiy 09be0ea795 UPDATE
2023-05-22 19:06:26 +03:00

225 lines
5.9 KiB
Plaintext

-- @name koptilnya/mesh_loader/cl_builder
-- @client
-- @include /koptilnya/libs/table.txt
-- @include obj_parser.txt
-- @include /koptilnya/libs/utils.txt
-- @include /koptilnya/libs/constants.txt
require("/koptilnya/libs/table.txt")
require("obj_parser.txt")
require("/koptilnya/libs/utils.txt")
require("/koptilnya/libs/constants.txt")
MeshBuilder = class("MeshBuilder")
function MeshBuilder:initialize(link)
self.link = link
self.meshData = {}
self._objects = {}
self._cachedMaterials = {}
self._parser = ObjParser:new(link)
self._parser.onLoaded = function(parser, objData)
self:_onObjLoaded(objData)
end
self._parser.onParsed = function(parser, meshData, usedTriangles)
self:_onObjParsed(meshData, usedTriangles)
end
self._parser:parse()
if IS_ME then
net.receive("initialized", function()
net.readEntity(function(ply)
notification.addProgress(tostring(ply:getUserID()), string.format("%s is loading mesh", ply:getName()))
end)
end)
net.receive("obj_parsed", function()
net.readEntity(function(ply)
notification.kill(tostring(ply:getUserID()))
end)
end)
net.receive("player_disconnect", function()
notification.kill(net.readString())
end)
net.receive("starfall_error", function()
net.readEntity(function(ply)
notification.kill(tostring(ply:getUserID()))
end)
end)
end
hook.add("starfallerror", "_starfallerror", function(ent, ply, err)
if ent ~= chip() then return end
net.start("starfall_error")
net.writeEntity(ply)
net.send()
end)
net.receive("objects", function()
self:_onReceiveObjects()
end)
hook.add("Removed", "_Removed", function()
for k, v in pairs(self._cachedMaterials) do
if type(v) == "Material" then
v:destroy()
end
end
end)
end
function MeshBuilder:_onObjLoaded(objData)
self:onObjLoaded(objData)
end
function MeshBuilder:_onObjParsed(meshData, usedTriangles)
net.start("obj_parsed")
net.send()
self:onObjParsed(meshData, usedTriangles)
self.meshData = meshData
self:_applyMeshes()
end
function MeshBuilder:_onReceiveObjects()
self._objects = {}
local hasNext = net.readBit()
while hasNext == 1 do
local name = net.readString()
local mat = net.readTable()
net.readEntity(function(ent)
local holo = ent:toHologram()
local isCustomMaterial = (#table.getKeys(mat) > 1 and mat.basetexture) or isURL(mat.basetexture)
if (isCustomMaterial) then
mat = self:_createMaterial(mat.shader, mat.basetexture, mat.bumpmap, mat.options)
else
hasErr, mat = pcall(material.load, mat.basetexture)
if not hasErr then
mat = material.load("models/debug/debugwhite")
end
end
local object = {name = name, mat = mat, holo = holo}
table.insert(self._objects, object)
end)
hasNext = net.readBit()
end
timer.simple(0.5, function()
self:onHologramsReceived(self._objects)
self:_applyMeshes()
end)
end
function MeshBuilder:_applyMeshes()
for _, v in pairs(self._objects) do
if self.meshData[v.name] ~= nil then
local color = v.holo:getColor()
v.holo:setRenderBounds(Vector(-200), Vector(200))
v.holo:setMesh(self.meshData[v.name])
v.holo:setMeshMaterial(v.mat)
v.meshApplied = true
end
end
if #self._objects > 0 then
self:onMeshesApplied()
end
end
function MeshBuilder:_setTexture(mat, name, texture, layoutOptions)
if isURL(texture) then
texture = texture .. "#hack" .. math.random(1337)
layoutOptions = layoutOptions or {}
mat:setTextureURL(name, texture, function(_, _, _, _, layout)
if not layout then return end
local x = layoutOptions.x or 0
local y = layoutOptions.y or 0
local w = layoutOptions.w or 1024
local h = layoutOptions.h or 1024
layout(x, y, w, h)
end)
else
mat:setTexture(name, texture)
end
end
function MeshBuilder:_createMaterial(shader, basetexture, bumpmap, options)
shader = shader or "VertexLitGeneric"
basetexture = basetexture or "models/debug/debugwhite"
bumpmap = bumpmap or ""
options = options or {}
local checksum = crc(shader .. basetexture .. bumpmap .. json.encode(options))
if self._cachedMaterials[checksum] ~= nil then
return self._cachedMaterials[checksum]
end
local mat = material.create(shader)
self:_setTexture(mat, "$basetexture", basetexture, options.baseLayout)
if bumpmap ~= "" then
self:_setTexture(mat, "$bumpmap", bumpmap, options.bumpLayout)
end
options.baseLayout = nil
options.bumpLayout = nil
for k, v in pairs(options) do
if k == "envmap" then
mat:setTexture("$envmap", v)
elseif type(v) == "string" then
mat:setString("$" .. k, v)
elseif type(v) == "number" then
if string.match(tostring(v), "%.") then
mat:setFloat("$" .. k, v)
else
mat:setInt("$" .. k, v)
end
elseif type(v) == "nil" then
mat:setUndefined("$" .. k, v)
elseif type(v) == "Vector" then
mat:setVector("$" .. k, v)
end
end
self._cachedMaterials[checksum] = mat
--mat:recompute()
return mat
end
-- STUB
function MeshBuilder:onObjLoaded(objData)
end
function MeshBuilder:onObjParsed(meshData, usedTriangles)
end
function MeshBuilder:onHologramsReceived(objects)
end
function MeshBuilder:onMeshesApplied()
end