|
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 |
|
|
|
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 |
|
|