1
0
Fork 0
mirror of https://github.com/Reuh/wirefame.git synced 2026-01-18 02:23:04 +00:00
wirefame/wirefame/group.lua
2021-02-18 17:22:21 +01:00

170 lines
3.8 KiB
Lua

local wirefame = require((...):match("^(.*)%.wirefame%.group$"))
local model_mt = require((...):match("^(.*)group$").."model")
local m4, v3, bb3, bs3 = wirefame.m4, wirefame.v3, wirefame.bb3, wirefame.bs3
local unpack = table.unpack or unpack
--- Group methods.
local group_mt = {
--- Add a model to the node.
add = function(self, ...)
assert(not self.filtered, "can't add to a filtered group")
for _, m in ipairs({...}) do
self.n = self.n + 1
table.insert(self, m)
if m.parent == nil then
m.parent = self
if self.scene then
m:onAddToScene(self.scene)
end
m:setTransform(0, self:updateFinalTransform())
end
end
return self
end,
--- Remove a model from the node.
remove = function(self, ...)
assert(not self.filtered, "can't remove from a filtered group")
for _, m in ipairs({...}) do
for i=1, self.n do
if self[i] == m then
self.n = self.n - 1
table.remove(self, i)
m.parent = nil
if m.scene then
m:onRemoveFromScene(m.scene)
end
return self
end
end
end
error("can't find model to remove")
end,
--- All these methods and properties of model are present, but operate on the whole group.
-- Overwrite some model methods:
onAddToScene = function(self, scene)
self.scene = scene
for i=1, self.n do
self[i]:onAddToScene(scene)
end
end,
onRemoveFromScene = function(self, scene)
self.scene = nil
for i=1, self.n do
self[i]:onRemoveFromScene(scene)
end
end,
get = function(self, ...)
local l = {}
for i=1, self.n do
local il = self[i]:get(...)
if #il > 0 then
table.insert(l, il)
end
end
l.n = #l
l.filtered = true
return setmetatable(l, {__index = self, __tostring = self.__tostring})
end,
boundingBox = function(self)
if #self > 0 then
self:updateFinalTransform()
local r = self[1]:boundingBox()
for i=2, self.n do
r:include(self[i]:boundingBox())
end
return r
else
return bb3(v3(0,0,0), v3(0,0,0))
end
end,
boundingSphere = function(self)
if #self > 0 then
self:updateFinalTransform()
local r = self[1]:boundingSphere()
for i=2, self.n do
r:include(self[i]:boundingSphere())
end
return r
else
return bs3(v3(0,0,0), 0)
end
end,
initShader = function(self, shader)
for i=1, self.n do
self[i]:initShader(shader)
end
end,
sendFinalTransform = function(self, tr)
if self.filtered then self = getmetatable(self).__index end
for i=1, self.n do
self[i]:setTransform(0, tr)
end
end,
setColor = function(self, r, g, b, a) -- apply color to all children
self.color[1], self.color[2], self.color[3], self.color[4] = r, g, b, a or 1
for i=1, self.n do
self[i]:setColor(r, g, b, a)
end
return self
end,
draw = function(self, shader, transp)
-- Transparency sort
if transp then
if self.color[4] >= 1 then return end
else
if self.color[4] < 1 then return end
end
-- Transformation matrix
self:updateFinalTransform()
-- Draw
for i=1, self.n do
self[i]:draw(shader, transp)
end
end,
__tostring = function(self)
local mt = getmetatable(self)
setmetatable(self, nil)
local str = "group: "..(tostring(self):gsub("^table: ", ""))
setmetatable(self, mt)
return str
end
}
for k, v in pairs(model_mt) do
if group_mt[k] == nil then
group_mt[k] = v
end
end
group_mt.__index = group_mt
--- Create a group of models.
function wirefame.group(t)
local group = {
-- Size
n = 0,
-- Tags
tags = {},
-- Group transformation matrices
transformStack = { n = 1, changed = true, names = {}, [0] = m4.identity(), m4.identity() },
finalTransform = nil,
-- Group color
color = { wirefame.defaultColor[1], wirefame.defaultColor[2], wirefame.defaultColor[3], wirefame.defaultColor[4] },
-- Hierarchy
parent = nil,
scene = nil
}
-- Create & return object
return setmetatable(group, group_mt):add(unpack(t))
end
return group_mt