myspace / CommonLua /Classes /AttachViaProp.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
raw
history blame
7.65 kB
local EDITOR = Platform.editor
local function SpotEntry(obj, idx)
local name = idx >= 0 and obj:GetSpotName(idx) or ""
if name == "" then
return false
end
local offset = idx - obj:GetSpotBeginIndex(name)
return offset == 0 and name or {name, offset}
end
DefineClass.AttachViaProp = {
__parents = { "ComponentAttach" },
properties = {
{ category = "Attach-Via-Prop", id = "AttachList", name = "Attach List", editor = "prop_table", default = "", no_edit = true },
{ category = "Attach-Via-Prop", id = "AttachCounter", name = "Attach Counter", editor = "number", default = 0, dont_save = true, read_only = true },
},
}
function AttachViaProp:SetAttachList(value)
self.AttachList = value
self:UpdatePropAttaches()
end
function AttachViaProp:ResolveSpotIdx(entry)
local spot = entry.spot
local offset
if type(spot) == "table" then
spot, offset = unpack_params(spot)
assert(type(spot) == "string")
assert(type(offset) == "number")
end
if type(spot) == "number" then
-- support for older version
entry.spot = SpotEntry(self, spot)
elseif type(spot) == "string" then
spot = self:HasSpot(spot) and self:GetSpotBeginIndex(spot)
end
return (spot or -1) + (offset or 0)
end
function AttachViaProp:UpdatePropAttaches()
if self.AttachCounter > 0 then
self:ForEachAttach(function(obj)
if rawget(obj, "attach_via_prop") then
DoneObject(obj)
end
end)
self.AttachCounter = nil
end
local list = self.AttachList
for i=#list,1,-1 do
local entry = list[i]
local spot = self:ResolveSpotIdx(entry)
if not spot then
table.remove(list, i)
else
local class = entry.class or ""
local particles = entry.particles or ""
local obj, err
if particles ~= "" then
obj = PlaceParticles(particles)
else
obj = PlaceObject(class)
end
if obj then
rawset(obj, "attach_via_prop", true)
if entry.offset then
obj:SetAttachOffset(entry.offset)
end
if entry.axis then
obj:SetAttachAxis(entry.axis)
end
if entry.angle then
obj:SetAttachAngle(entry.angle)
end
err = self:Attach(obj, spot)
end
if not IsValid(obj) or obj:GetAttachSpot() ~= spot or err then
StoreErrorSource(self, "Failed to attach via props!")
DoneObject(obj)
else
self.AttachCounter = self.AttachCounter + 1
end
end
end
if not EDITOR then
self.AttachList = nil
end
end
----
if EDITOR then
local function SpotName(obj, idx)
local name = obj:GetSpotName(idx)
local anot = obj:GetSpotAnnotation(idx)
return name .. (anot and (" (" .. anot .. ")") or "")
end
local function SpotNamesCombo(obj)
local start_idx, end_idx = obj:GetAllSpots( obj:GetState() )
local items = {}
local names = {}
for idx = start_idx, end_idx do
items[#items + 1] = {value = SpotEntry(obj, idx), text = SpotName(obj, idx)}
end
table.sortby_field(items, "text")
table.insert(items, 1, {value = false, text = ""})
return items
end
if FirstLoad then
l_used_entries = false
end
local function SmartAttachCombo()
local items = {}
local classes = ClassDescendantsList("ComponentAttach")
local tbl = {"", " - Object"}
for i = 1, #classes do
local class = classes[i]
tbl[1] = class
local text = table.concat(tbl)
items[#items + 1] = {value = { class, 1, text }, text = text}
end
local particles = ParticlesComboItems()
local tbl = {"", " - Particle"}
for i = 1, #particles do
local particle = particles[i]
tbl[1] = particle
local text = table.concat(tbl)
items[#items + 1] = {value = { particle, 2, text }, text = text}
end
table.sortby_field(items, "text")
if l_used_entries then
local idx = 1
local tbl = {"> ", ""}
for text, entry in sorted_pairs(l_used_entries) do
tbl[2] = text
table.insert(items, idx, {value = entry, text = table.concat(tbl)})
idx = idx + 1
end
table.insert(items, idx, {value = "", text = ""})
end
table.insert(items, 1, {value = false, text = ""})
return items
end
table.iappend(AttachViaProp.properties, {
{ category = "Attach-Via-Prop", id = "AttachPreview", name = "Attach List", editor = "text", lines = 5, default = "", dont_save = true, read_only = true, min = 10 },
{ category = "Attach-Via-Prop", id = "AttachToSpot", name = "Attach At", editor = "combo", default = false, dont_save = true, items = SpotNamesCombo, min = 0, buttons = {{name = "Add", func = "ButtonAddAttach"}, {name = "Rem", func = "ButtonRemAttach"}, {name = "Rem All", func = "ButtonRemAllAttaches"}}},
{ category = "Attach-Via-Prop", id = "AttachObject", name = "Attach Object", editor = "combo", default = false, dont_save = true, items = SmartAttachCombo },
{ category = "Attach-Via-Prop", id = "AttachWithOffset", name = "Attach Offset ", editor = "point", default = point30, dont_save = true, scale = "m" },
{ category = "Attach-Via-Prop", id = "AttachWithAxis", name = "Attach Axis ", editor = "point", default = axis_z, dont_save = true },
{ category = "Attach-Via-Prop", id = "AttachWithAngle", name = "Attach Angle ", editor = "number", default = 0, dont_save = true, scale = "deg" },
})
function AttachViaProp:GetAttachListCombo()
local items = {}
local list = self.AttachList
for i=#list,1,-1 do
local entry = list[i]
local spot = self:ResolveSpotIdx(entry)
if not spot then
table.remove(list, i)
else
local str = SpotName(self, spot) .. " -- " .. (entry.particles or entry.class or "?")
if entry.offset then
str = str .. " o" .. tostring(entry.offset)
end
if entry.axis then
str = str .. " x" .. tostring(entry.axis)
end
if entry.angle then
str = str .. " a" .. tostring(entry.angle)
end
items[#items + 1] = str
end
end
table.sort(items)
return items
end
function AttachViaProp:GetAttachPreview()
local list = self:GetAttachListCombo()
return table.concat(list, "\n")
end
function ButtonAddAttach(main_obj, object, prop_id)
if type(object.AttachObject) ~= "table" then
return
end
local oname, otype, otext = unpack_params(object.AttachObject)
local class = otype == 1 and oname or ""
local particles = otype == 2 and oname or ""
if class == "" and particles == "" then
return
end
l_used_entries = l_used_entries or {}
l_used_entries[otext] = object.AttachObject
local spot = object.AttachToSpot or nil
local list = object.AttachList
if #list == 0 then
list = {}
object.AttachList = list
end
local offset = object.AttachWithOffset
if offset == point30 then
offset = nil
end
local axis = object.AttachWithAxis
if axis == axis_z then
axis = nil
end
local angle = object.AttachWithAngle
if angle == 0 then
angle = nil
end
if class ~= "" then
list[#list + 1] = {spot = spot, offset = offset, axis = axis, angle = angle, class = class, }
end
if particles ~= "" then
list[#list + 1] = {spot = spot, offset = offset, axis = axis, angle = angle, particles = particles, }
end
object:UpdatePropAttaches()
end
function ButtonRemAllAttaches(main_obj, object, prop_id)
if not object then
return
end
object.AttachList = nil
object:UpdatePropAttaches()
end
function ButtonRemAttach(main_obj, object, prop_id)
if not object then
return
end
local list = object:GetAttachListCombo()
if #list == 0 then
return
end
local entry, err = PropEditorWaitUserInput(main_obj, list[#list], "Select attach to remove", list)
if not entry then
assert(false, err)
return
end
local idx = table.find(list, entry)
if not idx then
return
end
table.remove(object.AttachList, idx)
if #object.AttachList == 0 then
object.AttachList = nil
end
object:UpdatePropAttaches()
end
end -- EDITOR
----