khanat-client-data-NeL/data/ryz/ryz_ring/r2_base_class_private.lua

147 lines
4.3 KiB
Lua

------------------------------
-- 'BaseClass' private code --
------------------------------
---------------------------------------------------------------------------------------------------------
-- copy default implementation
-- privates, used by baseClass.copy :
local srcToCopyMapping = {} -- map each instance in the src tree to its shallow vopy
local function isInstance(inst)
return (type(inst) == "table" or type(inst) == "userdata") and inst.InstanceId ~= nil
end
local function isArray(inst)
return type(inst) == "table" and inst.InstanceId == nil
end
local function isInstanceArray(array)
return type(array) == "userdata" and array.Size ~= nil
end
--------------------------------------------------------------
-- create canonical copy
local function canonicalCopy(node)
if isInstance(node) then
assert(node.Class ~= nil)
local newNode = {}
for k, v in specPairs(node) do
-- special case for refId in class definition
--inspect(node:getClass())
local prop = r2.Classes[node.Class].NameToProp[k]
if prop and prop.Type == "RefId" then
newNode[k] = r2.RefId(v)
else
newNode[k] = canonicalCopy(v)
end
end
return newNode
elseif isInstanceArray(node) then
local newArray = {}
for k, v in specPairs(node) do
newArray[k] = canonicalCopy(v)
end
return newArray
else
return node
end
end
--------------------------------------------------------------
-- clone an object into clipboard, refid are unmodified
local function cloneNode(node, mapping)
if isInstance(node) then
assert(node.Class ~= nil)
local newNode = r2.newComponent(node.Class)
for k, v in pairs(node) do
-- special case for refId in class definition
--inspect(node:getClass())
local prop = r2.Classes[node.Class].NameToProp[k]
if prop and prop.Type == "RefId" then
newNode[k] = r2.RefId(v)
elseif k ~= "InstanceId" and k ~= "Class" then
newNode[k] = cloneNode(v, mapping)
end
end
mapping[node.InstanceId] = newNode.InstanceId
return newNode
elseif isArray(node) then
local newArray = {}
-- workaround here : if there are only numbers in the table keys, then sort and insert
-- this allow to preserve order when duplicating a road / place
local plainArray = true
for k, v in pairs(node) do
if type(k) ~= "number" then
plainArray = false
break
end
end
if plainArray then
local indices = {}
for k, v in pairs(node) do
table.insert(indices, k)
end
table.sort(indices)
for i = 1, table.getn(indices) do
table.insert(newArray, cloneNode(node[indices[i]], mapping))
end
else
for k, v in pairs(node) do
newArray[k] = cloneNode(v, mapping)
end
end
return newArray
else
return node
end
end
--------------------------------------------------------------
-- remap refid for internal refs, external refs are left unmodified
local function renameRefIds(node, mapping)
if isInstance(node) then
assert(node.Class ~= nil)
for k, v in pairs(node) do
-- special case for refId in class definition
local prop = r2.Classes[node.Class].NameToProp[k]
if prop and prop.Type == "RefId" then
--debugInfo("***" .. tostring(v))
if mapping[tostring(v)] ~= nil then
--debugInfo("###")
node[k] = mapping[tostring(v)] -- remap internal ref
end
else
renameRefIds(v, mapping)
end
end
mapping[node] = newNode
elseif type(node) == "table" then
for k, v in specPairs(node) do
renameRefIds(v, mapping)
end
return newArray
end
end
function baseClass.copy(this)
return canonicalCopy(this)
end
function baseClass.newCopy(this)
table.clear(srcToCopyMapping)
local result = cloneNode(this, srcToCopyMapping)
renameRefIds(result, srcToCopyMapping)
-- if the name is a generated one, create a new name
if result.Name ~= nil and r2:isPostFixedByNumber(ucstring(result.Name)) then
result.Name = r2:genInstanceName(ucstring(result.Name)):toUtf8()
end
-- the copy of a undeletable object is a deltable object
if result.Deletable ~= nil and result.Deletable==0 then
result.Deletable = 1
end
return result
end