1659 lines
51 KiB
Lua
1659 lines
51 KiB
Lua
|
r2_core = {}
|
|||
|
|
|||
|
r2_core.UserComponentsPath = "./examples/user_components/"
|
|||
|
|
|||
|
r2_core.UserComponentTable = {}
|
|||
|
|
|||
|
r2_core.UserComponentManager = {}
|
|||
|
|
|||
|
local userComponentManager = r2_core.UserComponentManager
|
|||
|
|
|||
|
userComponentManager.CurrentExportList = {}
|
|||
|
|
|||
|
userComponentManager.InstanceIds = {}
|
|||
|
|
|||
|
userComponentManager.Texts = {}
|
|||
|
|
|||
|
userComponentManager.PlotItems = {}
|
|||
|
|
|||
|
userComponentManager.Positions = {}
|
|||
|
|
|||
|
userComponentManager.CurrentDesc = ""
|
|||
|
|
|||
|
userComponentManager.IsInitialized = false
|
|||
|
|
|||
|
userComponentManager.InitialComponentToLoad = 0
|
|||
|
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------
|
|||
|
-- Methods called when the holder specific ui buttons are pressed
|
|||
|
function r2_core:doNothing(x, y, z)
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
function r2_core:testIsExportable(entityId)
|
|||
|
local holder = r2:getInstanceFromId(r2_core.CurrentHolderId)
|
|||
|
assert(holder)
|
|||
|
local k, v = next(holder.Components, nil)
|
|||
|
local entity = r2:getInstanceFromId(entityId)
|
|||
|
|
|||
|
while k do
|
|||
|
if entity.ParentInstance:isKindOf("NpcGrpFeature")
|
|||
|
and entity.ParentInstance.InstanceId == v.InstanceId then
|
|||
|
return false
|
|||
|
end
|
|||
|
if v.InstanceId == entityId then
|
|||
|
return false
|
|||
|
end
|
|||
|
k, v = next(holder.Components, k)
|
|||
|
end
|
|||
|
|
|||
|
return true
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
local function getIndex(id, tbl)
|
|||
|
local k, v = next(tbl, nil)
|
|||
|
while k do
|
|||
|
if v.InstanceId and v.InstanceId == id then
|
|||
|
return k
|
|||
|
end
|
|||
|
k, v = next(tbl, k)
|
|||
|
end
|
|||
|
return -1
|
|||
|
end
|
|||
|
|
|||
|
function r2_core:addEntityToExporter(instanceId)
|
|||
|
local entityId = instanceId
|
|||
|
local tmpInstance = r2:getInstanceFromId(entityId)
|
|||
|
if tmpInstance:isKindOf("Npc") and tmpInstance.ParentInstance:isKindOf("NpcGrpFeature") then
|
|||
|
entityId = tmpInstance.ParentInstance.InstanceId
|
|||
|
end
|
|||
|
|
|||
|
local entity = r2:getInstanceFromId(entityId)
|
|||
|
assert(entity)
|
|||
|
|
|||
|
local parent = entity.ParentInstance
|
|||
|
local parentId = parent.InstanceId
|
|||
|
|
|||
|
r2_core.UserComponentManager:replacePosition(entityId)
|
|||
|
|
|||
|
if parent:isKindOf("DefaultFeature") then
|
|||
|
local index = getIndex(entityId, parent.Components)
|
|||
|
r2.requestMoveNode(parentId, "Components", index, r2_core.CurrentHolderId, "Components", -1)
|
|||
|
elseif parent:isKindOf("Act") then
|
|||
|
local index = getIndex(entityId, parent.Features)
|
|||
|
r2.requestMoveNode(r2:getCurrentAct().InstanceId, "Features", index, r2_core.CurrentHolderId, "Components", -1)
|
|||
|
end
|
|||
|
local container = getUI("ui:interface:r2ed_scenario")
|
|||
|
local tree = container:find("content_tree_list")
|
|||
|
tree:forceRebuild()
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
function r2_core:testCanPickUserComponentElement(instanceId)
|
|||
|
local instance = r2:getInstanceFromId(instanceId)
|
|||
|
assert(instance)
|
|||
|
local parent = instance.ParentInstance
|
|||
|
|
|||
|
local holder = r2:getInstanceFromId(r2_core.CurrentHolderId)
|
|||
|
assert(holder)
|
|||
|
|
|||
|
if parent:isKindOf("NpcGrpFeature") and holder.InstanceId == parent.ParentInstance.InstanceId then
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
if holder.InstanceId == parent.InstanceId then
|
|||
|
return true
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
function r2_core:removeUserComponentElement(instanceId)
|
|||
|
local holder = r2:getInstanceFromId(r2_core.CurrentHolderId)
|
|||
|
assert(holder)
|
|||
|
|
|||
|
local index = getIndex(instanceId, holder.Components)
|
|||
|
|
|||
|
local entity = r2:getInstanceFromId(instanceId)
|
|||
|
assert(entity)
|
|||
|
|
|||
|
local currentAct = r2:getCurrentAct()
|
|||
|
|
|||
|
if entity:isKindOf("Region") or entity:isKindOf("Road") or entity:isBotObject() then
|
|||
|
local refPosition = r2.Scenario.Acts[0].Position
|
|||
|
r2_core.UserComponentManager:restorePosition(instanceId, refPosition)
|
|||
|
r2.requestMoveNode(r2_core.CurrentHolderId, "Components", index, r2.Scenario.Acts[0].Features[0].InstanceId, "Components", -1)
|
|||
|
elseif entity:isKindOf("Npc") then
|
|||
|
local refPosition = currentAct.Position
|
|||
|
if entity.ParentInstance:isKindOf("NpcGrpFeature") then
|
|||
|
local grpId = entity.ParentInstance.InstanceId
|
|||
|
local grpIndex = getIndex(grpId, holder.Components)
|
|||
|
r2_core.UserComponentManager:restorePosition(grpId, refPosition)
|
|||
|
r2.requestMoveNode(r2_core.CurrentHolderId, "Components", grpIndex, currentAct.InstanceId, "Features", -1)
|
|||
|
else
|
|||
|
r2_core.UserComponentManager:restorePosition(instanceId, refPosition)
|
|||
|
r2.requestMoveNode(r2_core.CurrentHolderId, "Components", index, currentAct.Features[0].InstanceId, "Components", -1)
|
|||
|
--getCurrentAct().Features[0].Components
|
|||
|
end
|
|||
|
else
|
|||
|
local refPosition = currentAct.Position
|
|||
|
r2_core.UserComponentManager:restorePosition(instanceId, refPosition)
|
|||
|
r2.requestMoveNode(r2_core.CurrentHolderId, "Components", index, currentAct.InstanceId, "Features", -1)
|
|||
|
--getCurrentAct().Features
|
|||
|
end
|
|||
|
|
|||
|
local container = getUI("ui:interface:r2ed_scenario")
|
|||
|
local tree = container:find("content_tree_list")
|
|||
|
tree:forceRebuild()
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
-- Debug
|
|||
|
local printDebug
|
|||
|
printDebug = function(tbl)
|
|||
|
local k,v = next(tbl, nil)
|
|||
|
while k do
|
|||
|
if type(v) == "table" then
|
|||
|
debugInfo(k .. " : TABLE")
|
|||
|
printDebug(v)
|
|||
|
else
|
|||
|
debugInfo(k .. " = " ..tostring(v))
|
|||
|
end
|
|||
|
k,v = next(tbl, k)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local foundInTable = function(tbl, key)
|
|||
|
local k, v = next(tbl, nil)
|
|||
|
while k do
|
|||
|
if (k == key) then return true end
|
|||
|
k,v = next(tbl, k)
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
local insertExistingId = function(tblSearch, tblInsert, clientid)
|
|||
|
local k, v = next(tblSearch, nil)
|
|||
|
while k do
|
|||
|
if (k == clientid) then
|
|||
|
tblInsert[clientid] = v
|
|||
|
end
|
|||
|
k, v = next(tblSearch, k)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local checkLinkedId = function(instanceIdTbl, refIdTbl)
|
|||
|
local k, v = next(refIdTbl, nil)
|
|||
|
while k do
|
|||
|
local key, value = next(instanceIdTbl, nil)
|
|||
|
while key do
|
|||
|
if key == k and value ~= v then
|
|||
|
refIdTbl[k] = value
|
|||
|
end
|
|||
|
key, value = next(instanceIdTbl, key)
|
|||
|
end
|
|||
|
k, v = next(refIdTbl, k)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local countIds = function(tbl)
|
|||
|
local count = 0
|
|||
|
local k, v = next(tbl, nil)
|
|||
|
while k do
|
|||
|
count = count + 1
|
|||
|
k, v = next(tbl, k)
|
|||
|
end
|
|||
|
return count
|
|||
|
end
|
|||
|
|
|||
|
local countUCIds
|
|||
|
countUCIds = function(tbl)
|
|||
|
local count = 0
|
|||
|
local k, v = next(tbl, nil)
|
|||
|
while k do
|
|||
|
if type(v) ~= "table" and type(v) ~= "userdata" then
|
|||
|
if k == "InstanceId" or string.find(tostring(v), "UserComponent_") ~= nil
|
|||
|
or string.find(tostring(v), "UserText_") ~= nil or string.find(tostring(v), "UserItem_") ~= nil then
|
|||
|
count = count + 1
|
|||
|
end
|
|||
|
elseif type(v) == "table" then
|
|||
|
count = count + countUCIds(v)
|
|||
|
end
|
|||
|
k, v = next(tbl, k)
|
|||
|
end
|
|||
|
return count
|
|||
|
end
|
|||
|
|
|||
|
local findUserSlotIn = function(str)
|
|||
|
local currentSlot = r2.getUserSlot() .."_"
|
|||
|
if string.find(str, currentSlot) ~= nil then
|
|||
|
return true
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:init()
|
|||
|
--init usercomponent table & retrieves entries from file if not empty
|
|||
|
r2_core.UserComponentTable = {}
|
|||
|
local userComponentTableOk = loadfile("save/r2_core_user_component_table.lua")
|
|||
|
if userComponentTableOk then
|
|||
|
userComponentTableOk()
|
|||
|
end
|
|||
|
--doFile on previously loaded user component files
|
|||
|
local ucTable = r2_core.UserComponentTable
|
|||
|
self.InitialComponentToLoad = table.getn(ucTable)
|
|||
|
local k, v = next(ucTable, nil)
|
|||
|
while k do
|
|||
|
--local fun = loadfile(v[2])
|
|||
|
r2.loadUserComponentFile(v[2])
|
|||
|
--if not fun then
|
|||
|
-- debugInfo("Couldn't load file '"..v[2].."' while initializing UserComponentManager.")
|
|||
|
--else
|
|||
|
-- local ok, msg = pcall(fun)
|
|||
|
-- if not ok then
|
|||
|
-- debugInfo("Error while loading component '"..filename.."' err: "..msg)
|
|||
|
-- end
|
|||
|
-- debugInfo("Component '" ..v[2].."' loaded.")
|
|||
|
--end
|
|||
|
k, v = next(ucTable, k)
|
|||
|
end
|
|||
|
|
|||
|
if r2_core.UserComponentManager.IsInitialized == false and r2_core.UserComponentManager.InitialComponentToLoad == 0 then
|
|||
|
r2_core.UserComponentManager.IsInitialized = true
|
|||
|
end
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
function userComponentManager:isInitialized()
|
|||
|
return self.IsInitialized
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
-- Gets all the InstanceIds and the references to InstanceIds and store them separately.
|
|||
|
-- Each refId is unique and is renamed from client1_XX to userComponent_XX.
|
|||
|
-- Returns a table containing all the instanceIds and refIds.
|
|||
|
--
|
|||
|
|
|||
|
function userComponentManager:getRefIdTableFrom(argTbl)
|
|||
|
|
|||
|
local refIdTbl = {}
|
|||
|
local instanceIdTbl = {}
|
|||
|
local plotItemTbl = {}
|
|||
|
|
|||
|
local nbInstance = 0
|
|||
|
local nbText = 0
|
|||
|
local nbItems = 0
|
|||
|
|
|||
|
|
|||
|
local addTextToUCManager = function(instanceId)
|
|||
|
local key, value = next(r2.Scenario.Texts.Texts, nil)
|
|||
|
while key do
|
|||
|
if value.InstanceId == instanceId then
|
|||
|
userComponentManager.Texts[instanceIdTbl[instanceId]] = value.Text
|
|||
|
return
|
|||
|
end
|
|||
|
key, value = next(r2.Scenario.Texts.Texts, key)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local addItemToUCManager = function(instanceId)
|
|||
|
local key, value = next(r2.Scenario.PlotItems, nil)
|
|||
|
debugInfo("Adding '" ..instanceId.."' to manager item table")
|
|||
|
while key do
|
|||
|
if value.InstanceId == instanceId then
|
|||
|
--copy the full plot item into manager's table
|
|||
|
userComponentManager.PlotItems[plotItemTbl[instanceId]] = value
|
|||
|
return
|
|||
|
end
|
|||
|
key, value = next(r2.Scenario.PlotItems, key)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
-- Doesn't insert the value if it's already in the table.
|
|||
|
parseInstanceTable = function(tbl)
|
|||
|
|
|||
|
--parsing string properties
|
|||
|
local key,val = next(tbl, nil)
|
|||
|
while key do
|
|||
|
if (type(val) ~= "userdata") then
|
|||
|
-- If the property is a real InstanceId
|
|||
|
if (key == "InstanceId") then
|
|||
|
-- If the instanceId is not already in the instanceIdTbl then add it as a key, with its usercomponent
|
|||
|
-- translation as value.
|
|||
|
if not foundInTable(instanceIdTbl, tostring(val)) then
|
|||
|
nbInstance = nbInstance + 1
|
|||
|
instanceIdTbl[val] = "UserComponent_"..nbInstance
|
|||
|
end
|
|||
|
-- else if the instanceid found is a reference to another InstanceId
|
|||
|
--elseif (string.find(tostring(val), "Client1_") ~= nil) then
|
|||
|
elseif findUserSlotIn(tostring(val)) then
|
|||
|
--if exporting a dialog, rename specifically the refId pointing to the said text (stored in r2.Scenario.Texts)
|
|||
|
if key == "Says" then
|
|||
|
if not foundInTable(instanceIdTbl, tostring(val)) then
|
|||
|
nbText = nbText + 1
|
|||
|
instanceIdTbl[val] = "UserText_" ..nbText
|
|||
|
addTextToUCManager(val)
|
|||
|
end
|
|||
|
--else if plotItem XXXXXX
|
|||
|
elseif string.find(key, "Item") ~= nil then
|
|||
|
if not foundInTable(plotItemTbl, tostring(val)) then
|
|||
|
nbItems = nbItems + 1
|
|||
|
plotItemTbl[val] = "UserItem_" ..nbItems
|
|||
|
addItemToUCManager(val)
|
|||
|
end
|
|||
|
elseif not foundInTable(refIdTbl, tostring(val)) then
|
|||
|
if foundInTable(instanceIdTbl, tostring(val)) then --a refid pointing to an instanceid present in the component itself (zone...)
|
|||
|
insertExistingId(instanceIdTbl, refIdTbl, tostring(val))
|
|||
|
else
|
|||
|
refIdTbl[val] = "Not exported"
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
key,val = next(tbl, key)
|
|||
|
end
|
|||
|
|
|||
|
--parsing userdatas
|
|||
|
key, val = next(tbl, nil)
|
|||
|
while key do
|
|||
|
if (type(val) == "userdata") then
|
|||
|
parseInstanceTable(val)
|
|||
|
end
|
|||
|
if (type(val) == "table") then
|
|||
|
--inspect(val)
|
|||
|
assert(nil)
|
|||
|
end
|
|||
|
key, val = next(tbl, key)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local i = 1
|
|||
|
|
|||
|
--printDebug(argTbl)
|
|||
|
local nbExportedInstances = table.getn(argTbl)
|
|||
|
|
|||
|
local k, v = next(argTbl, nil)
|
|||
|
while k do
|
|||
|
local tmpInstance = r2:getInstanceFromId(v)
|
|||
|
if tmpInstance ~= nil then
|
|||
|
parseInstanceTable(tmpInstance)
|
|||
|
end
|
|||
|
k, v = next(argTbl, k)
|
|||
|
end
|
|||
|
|
|||
|
checkLinkedId(instanceIdTbl, refIdTbl)
|
|||
|
|
|||
|
userComponentManager.InstanceIds = instanceIdTbl
|
|||
|
|
|||
|
local refIdTable =
|
|||
|
{
|
|||
|
RefIds = refIdTbl,
|
|||
|
InstanceIds = instanceIdTbl,
|
|||
|
PlotItemsId = plotItemTbl
|
|||
|
}
|
|||
|
return refIdTable
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
local generatePreCode = function(fName)
|
|||
|
|
|||
|
local userComponentBody = ""
|
|||
|
|
|||
|
local writePlotItemBlock = function(plotItem, ucId, index)
|
|||
|
--file:write("\t{\n")
|
|||
|
local str = "\t{\n"
|
|||
|
local k, v = next(plotItem, nil)
|
|||
|
while k do
|
|||
|
if k == "InstanceId" then
|
|||
|
--file:write("\t\t[" ..string.format("%q", k).. "]\t=\t" ..string.format("%q", ucId).. ",\n")
|
|||
|
str = str .."\t\t[" ..string.format("%q", k).. "]\t=\t" ..string.format("%q", ucId).. ",\n"
|
|||
|
elseif type(v) == "string" then
|
|||
|
--file:write("\t\t[" ..string.format("%q", k).. "]\t=\t" ..string.format("%q", v).. ",\n")
|
|||
|
str = str .."\t\t[" ..string.format("%q", k).. "]\t=\t" ..string.format("%q", v).. ",\n"
|
|||
|
else
|
|||
|
--file:write("\t\t[" ..string.format("%q", k).. "]\t=\t" ..tostring(v).. ",\n")
|
|||
|
str = str .."\t\t[" ..string.format("%q", k).. "]\t=\t" ..tostring(v).. ",\n"
|
|||
|
end
|
|||
|
k, v = next(plotItem, k)
|
|||
|
end
|
|||
|
--file:write("\t},\n")
|
|||
|
str = str .."\t},\n"
|
|||
|
return str
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
local featureName = fName
|
|||
|
if featureName == nil or featureName == "" then
|
|||
|
featureName = "UnnamedComponent"
|
|||
|
end
|
|||
|
|
|||
|
local str = ""
|
|||
|
-- "-- <Creation_Header>\n"
|
|||
|
--.."-- r2_core.CurrentFeatureName='" ..featureName.. "'\n"
|
|||
|
--.."-- </Creation_Header>\n\n\n"
|
|||
|
str = "r2.Features."..featureName.. " = {}\n\n"
|
|||
|
.."local feature = r2.Features." ..featureName.."\n\n"
|
|||
|
.."feature.Name=\"".. featureName.."\"\n\n"
|
|||
|
.."feature.Description=\"A user exported feature.\"\n"
|
|||
|
.."feature.Components = {}\n\n"
|
|||
|
--file:write(str)
|
|||
|
userComponentBody = userComponentBody .. str
|
|||
|
|
|||
|
|
|||
|
do
|
|||
|
local count = 0
|
|||
|
--file:write("feature.PlotItems = \n{\n")
|
|||
|
userComponentBody = userComponentBody .."feature.PlotItems = \n{\n"
|
|||
|
local k, v = next(userComponentManager.PlotItems, nil)
|
|||
|
while k do
|
|||
|
count = count + 1
|
|||
|
userComponentBody = userComponentBody..writePlotItemBlock(v, k, count)
|
|||
|
k, v = next(userComponentManager.PlotItems, k)
|
|||
|
end
|
|||
|
--file:write("}\n\n")
|
|||
|
userComponentBody = userComponentBody .."}\n\n"
|
|||
|
end
|
|||
|
-- component.createComponent
|
|||
|
str = "feature.createUserComponent = function(x, y)\n\t"
|
|||
|
|
|||
|
.."local comp = r2.newComponent('UserComponentHolder')\n\t"
|
|||
|
.."assert(comp)\n\n\t"
|
|||
|
.."comp.Base = \"palette.entities.botobjects.user_event\"\n\t"
|
|||
|
.."comp.Name = r2:genInstanceName(ucstring('"..featureName.."')):toUtf8()\n\t"
|
|||
|
.."comp.Position.x = x\n\t"
|
|||
|
.."comp.Position.y = y\n\t"
|
|||
|
.."comp.Position.z = r2:snapZToGround(x, y)\n\n\t"
|
|||
|
.."comp.Description = '" ..userComponentManager.CurrentDesc.. "'\n\n\t"
|
|||
|
--file:write(str)
|
|||
|
userComponentBody = userComponentBody .. str
|
|||
|
|
|||
|
do
|
|||
|
--file:write("comp.Texts = \n\t{\n")
|
|||
|
userComponentBody = userComponentBody .."comp.Texts = \n\t{\n"
|
|||
|
local key, value = next(userComponentManager.Texts, nil)
|
|||
|
while key do
|
|||
|
--file:write("\t\t[" ..string.format("%q", key).. "]\t=\t[[" ..value.. "]],\n")
|
|||
|
userComponentBody = userComponentBody .. "\t\t[" ..string.format("%q", key).. "]\t=\t[[" ..value.. "]],\n"
|
|||
|
|
|||
|
key, value = next(userComponentManager.Texts, key)
|
|||
|
end
|
|||
|
--file:write("\t}\n\n\t")
|
|||
|
userComponentBody = userComponentBody .. "\t}\n\n\t"
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
str = "comp.Components = {}\n\t"
|
|||
|
.."local tmpComponents = {}\n\t"
|
|||
|
|
|||
|
userComponentBody = userComponentBody..str
|
|||
|
--file:write(str)
|
|||
|
return userComponentBody
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
local generatePostCode = function(fName)
|
|||
|
local featureName = fName
|
|||
|
if featureName == nil or featureName == "" then
|
|||
|
featureName = "UserFeature"
|
|||
|
end
|
|||
|
|
|||
|
local str = ""
|
|||
|
|
|||
|
str = str .."r2_core.UserComponentManager:insertAll(feature, comp, tmpComponents)\n\n\t"
|
|||
|
.."comp._Seed = os.time()\n\n\t"
|
|||
|
.."return comp\n"
|
|||
|
.."end\n\n\n"
|
|||
|
-- ! component.CreateComponent
|
|||
|
|
|||
|
.."\n\nr2.Features[\""..featureName.."\"] = feature"
|
|||
|
.."\n -- !"..featureName.." user exported\\o/ \n\n\n"
|
|||
|
|
|||
|
return str
|
|||
|
--file:write(str)
|
|||
|
end
|
|||
|
|
|||
|
-------------------------------------------------------------------------------------------------------------------
|
|||
|
-- Generates the LUA code corresponding to the selected instances.
|
|||
|
-- filename: file in which the code will be written.
|
|||
|
-- argTbl: contains all the instanceIds selected for export.
|
|||
|
-- instanceIdTbl: hashtable containing all clientIds (key) and their matching user component id (value). This table
|
|||
|
-- is returned by the getRefIdTableFrom method.
|
|||
|
-- refPosition: reference coordinates chosen by the user on export.
|
|||
|
function userComponentManager:componentToFile(filename, featureName, argTbl, refIdTbl, refPosition)
|
|||
|
|
|||
|
local instanceIdTbl = refIdTbl.InstanceIds
|
|||
|
local plotItemsTbl = refIdTbl.PlotItemsId
|
|||
|
|
|||
|
local body = ""
|
|||
|
|
|||
|
|
|||
|
local function writeTab(file, nb)
|
|||
|
local i = nb
|
|||
|
while i > 0 do
|
|||
|
file:write("\t")
|
|||
|
i = i - 1
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local function writeTabInString(str, nb)
|
|||
|
local tmp = str
|
|||
|
local i = nb
|
|||
|
while i > 0 do
|
|||
|
tmp = tmp..("\t")
|
|||
|
i = i - 1
|
|||
|
end
|
|||
|
return tmp
|
|||
|
end
|
|||
|
|
|||
|
--local function writeDataToFile(file, tbl, nbTab, isTopLevel)
|
|||
|
local function writeDataToString(str, tbl, nbTab, isTopLevel)
|
|||
|
local userComponentBody = str
|
|||
|
|
|||
|
local key,val = next(tbl, nil)
|
|||
|
while key do
|
|||
|
--writing all properties except userdatas
|
|||
|
if type(val) ~= "userdata" then
|
|||
|
|
|||
|
--writeTab(file, nbTab)
|
|||
|
userComponentBody = writeTabInString(userComponentBody, nbTab)
|
|||
|
if isTopLevel == true and key == "InheritPos" then
|
|||
|
--file:write("InheritPos = 1,\n")
|
|||
|
userComponentBody = userComponentBody .. "InheritPos = 1,\n"
|
|||
|
else
|
|||
|
if type(key) == "number" then
|
|||
|
--file:write("[" ..tostring(key + 1).. "] = ")
|
|||
|
userComponentBody = userComponentBody .. "[" ..tostring(key + 1).. "] = "
|
|||
|
else --file:write(tostring(key) .. " = ") end
|
|||
|
userComponentBody = userComponentBody .. tostring(key).. " = "
|
|||
|
end
|
|||
|
|
|||
|
-- String/number value
|
|||
|
if type(val) == "number" then
|
|||
|
--file:write(val..",\n")
|
|||
|
userComponentBody = userComponentBody..tostring(val)..", \n"
|
|||
|
else
|
|||
|
local str = val
|
|||
|
if key == "InstanceId" or findUserSlotIn(val) then
|
|||
|
str = instanceIdTbl[val]
|
|||
|
end
|
|||
|
if str == nil then
|
|||
|
str = plotItemsTbl[val]
|
|||
|
end
|
|||
|
if str == nil then str = "" end --when finding a instanceId which is referring to a non exported entity
|
|||
|
--file:write(string.format("%q", str) ..",\n")
|
|||
|
userComponentBody = userComponentBody .. string.format("%q", str) ..",\n"
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
key,val = next(tbl, key)
|
|||
|
end
|
|||
|
|
|||
|
--writing userdatas
|
|||
|
key, val = next(tbl, key)
|
|||
|
while key do
|
|||
|
if type(val) == "userdata" then
|
|||
|
--writeTab(file, nbTab)
|
|||
|
userComponentBody = writeTabInString(userComponentBody, nbTab)
|
|||
|
if type(key) ~= "number" then
|
|||
|
--file:write(tostring(key) .. " = ")
|
|||
|
userComponentBody = userComponentBody ..tostring(key).. " = "
|
|||
|
end
|
|||
|
|
|||
|
--file:write("\n")
|
|||
|
userComponentBody = userComponentBody .."\n"
|
|||
|
--writeTab(file, nbTab)
|
|||
|
userComponentBody = writeTabInString(userComponentBody, nbTab)
|
|||
|
--file:write("{\n")
|
|||
|
userComponentBody = userComponentBody .."{\n"
|
|||
|
userComponentBody = writeDataToString(userComponentBody, val, nbTab + 1, false)
|
|||
|
--writeTab(file, nbTab)
|
|||
|
userComponentBody = writeTabInString(userComponentBody, nbTab)
|
|||
|
--file:write("},\n")
|
|||
|
userComponentBody = userComponentBody .."}, \n"
|
|||
|
end
|
|||
|
key,val = next(tbl, key)
|
|||
|
end
|
|||
|
|
|||
|
return userComponentBody
|
|||
|
end
|
|||
|
|
|||
|
--
|
|||
|
-- Write a code block for each component of the user feature.
|
|||
|
local function writeComponentBlocks(str, tbl)
|
|||
|
local userComponentBody = str
|
|||
|
local i = 1
|
|||
|
local nbInstanceIds = table.getn(tbl)
|
|||
|
|
|||
|
while i <= nbInstanceIds do
|
|||
|
local tmpInstance = r2:getInstanceFromId(tbl[i])
|
|||
|
if (tmpInstance == nil) then
|
|||
|
debugInfo("Cannot export entity with intanceId= " ..tostring(tbl[i]))
|
|||
|
assert(tmpInstance)
|
|||
|
else
|
|||
|
|
|||
|
local compName = "uComp" ..i --+ 1
|
|||
|
--file:write("do\n\t\t")
|
|||
|
userComponentBody = userComponentBody .. "do\n\t\t"
|
|||
|
--file:write("local " ..compName.. " = \n\t\t{\n")
|
|||
|
userComponentBody = userComponentBody .. "local " ..compName.. " = \n\t\t{\n"
|
|||
|
|
|||
|
--writeDataToFile(file, tmpInstance, 3, true)
|
|||
|
userComponentBody = writeDataToString(userComponentBody, tmpInstance, 3, true)
|
|||
|
|
|||
|
--file:write("\t\t} --!" ..compName.. " \n\n\t\t")
|
|||
|
userComponentBody = userComponentBody .."\t\t} --!" ..compName.. " \n\n\t\t"
|
|||
|
--file:write("table.insert(tmpComponents, "..compName.. ")\n\t")
|
|||
|
userComponentBody = userComponentBody .."table.insert(tmpComponents, "..compName.. ")\n\t"
|
|||
|
--file:write("end\n\n\t")
|
|||
|
userComponentBody = userComponentBody .."end\n\n\t"
|
|||
|
end
|
|||
|
i = i + 1
|
|||
|
end
|
|||
|
return userComponentBody
|
|||
|
end
|
|||
|
|
|||
|
--f = io.open(filename, "w")
|
|||
|
--assert(f)
|
|||
|
|
|||
|
body = body..generatePreCode(featureName)
|
|||
|
|
|||
|
body = writeComponentBlocks(body, argTbl)
|
|||
|
|
|||
|
body = body .. generatePostCode(featureName)
|
|||
|
|
|||
|
--f:close()
|
|||
|
|
|||
|
--return res
|
|||
|
|
|||
|
local headerInfo = {}
|
|||
|
table.insert(headerInfo, {CurrentFeatureName = featureName})
|
|||
|
r2.saveUserComponent(filename, headerInfo, body)
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
-------------------------------------------------------------------------------------------------------------------
|
|||
|
-- Builds a table containing all user component ids (key) with their new instance id (ClientId_n) on import.
|
|||
|
-- tmpComponents: contains all the user feature components, in which all instance ids are user component ids.
|
|||
|
-- currentMaxId: max entity id in the current act (on user feature import).
|
|||
|
local function generateReverseIdTable(tmpComponents, texts, currentMaxId)
|
|||
|
|
|||
|
function findpattern(text, pattern, start)
|
|||
|
return string.sub(text, string.find(text, pattern, start))
|
|||
|
end
|
|||
|
|
|||
|
local function findMaxId(component, maxId, maxPlotItemId)
|
|||
|
local maxIdLocal = maxId
|
|||
|
|
|||
|
local maxItemId = maxPlotItemId
|
|||
|
|
|||
|
local key, value = next(component, nil)
|
|||
|
while key do
|
|||
|
if type(value) ~= "table" then
|
|||
|
if key == "InstanceId"
|
|||
|
or string.find(tostring(value), "UserComponent_") ~= nil then
|
|||
|
local tmpId = tonumber(findpattern(tostring(value), "%d+"))
|
|||
|
if tmpId and tmpId > maxIdLocal then maxIdLocal = tmpId end
|
|||
|
end
|
|||
|
if string.find(tostring(value), "UserItem_") ~= nil then
|
|||
|
local tmpItemId = tonumber(findpattern(tostring(value), "%d+"))
|
|||
|
if tmpItemId and tmpItemId > maxItemId then maxItemId = tmpItemId end
|
|||
|
end
|
|||
|
end
|
|||
|
key, value = next(component, key)
|
|||
|
end
|
|||
|
|
|||
|
--maxIdLocal = maxIdLocal + maxItemId
|
|||
|
|
|||
|
key, value = next(component, nil)
|
|||
|
while key do
|
|||
|
if type(value) == "table" then
|
|||
|
local tmpId, tmpItemId = findMaxId(value, maxIdLocal, maxItemId)
|
|||
|
if tmpId and tmpId > maxIdLocal then maxIdLocal = tmpId end
|
|||
|
if tmpItemId and tmpItemId > maxItemId then maxItemId = tmpItemId end
|
|||
|
end
|
|||
|
key, value = next(component, key)
|
|||
|
end
|
|||
|
return maxIdLocal, maxItemId
|
|||
|
end
|
|||
|
|
|||
|
local reverseIdTable = {}
|
|||
|
local maxId, maxPlotItemId = findMaxId(tmpComponents, 0, 0)
|
|||
|
|
|||
|
local i = 1
|
|||
|
local id = 0
|
|||
|
while i <= maxId do
|
|||
|
id = i + currentMaxId
|
|||
|
local ucName = "UserComponent_" ..i
|
|||
|
--reverseIdTable[ucName] = "Client1_" ..id
|
|||
|
reverseIdTable[ucName] = tostring(r2.getUserSlot()).."_"..id
|
|||
|
i = i + 1
|
|||
|
end
|
|||
|
|
|||
|
local j = 1
|
|||
|
while j <= maxPlotItemId do
|
|||
|
id = i + currentMaxId
|
|||
|
local ucName = "UserItem_" ..j
|
|||
|
--reverseIdTable[ucName] = "Client1_" ..id
|
|||
|
reverseIdTable[ucName] = tostring(r2.getUserSlot()).."_"..id
|
|||
|
j = j + 1
|
|||
|
i = i + 1
|
|||
|
end
|
|||
|
|
|||
|
--register component texts when a dialog has been exported
|
|||
|
if texts ~= nil then
|
|||
|
key, value = next(texts, nil)
|
|||
|
while key do
|
|||
|
local id = r2.registerText(tostring(value))
|
|||
|
reverseIdTable[key] = id.InstanceId
|
|||
|
key, value = next(texts, key)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
return reverseIdTable
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:reattributeClientId(tbl, reverseIdTable)
|
|||
|
local key, value = next(tbl, nil)
|
|||
|
while key do
|
|||
|
if (type(value) ~= "userdata") then
|
|||
|
if key == "InstanceId" or string.find(tostring(value), "UserComponent_") ~= nil
|
|||
|
or string.find(tostring(value), "UserText_") ~= nil
|
|||
|
or string.find(tostring(value), "UserItem_") ~= nil then
|
|||
|
local id = reverseIdTable[value]
|
|||
|
assert(id)
|
|||
|
tbl[key] = id
|
|||
|
end
|
|||
|
end
|
|||
|
key,value = next(tbl, key)
|
|||
|
end
|
|||
|
key, value = next(tbl, nil)
|
|||
|
while key do
|
|||
|
if type(value) ~= "string" and type(value) ~= "number" then
|
|||
|
userComponentManager:reattributeClientId(value, reverseIdTable)
|
|||
|
end
|
|||
|
key, value = next(tbl, key)
|
|||
|
end
|
|||
|
return tbl
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:insertPlotItem(plotItem, reverseIdTable)
|
|||
|
|
|||
|
local function isAlreadyUsed(plotItem)
|
|||
|
local k, v = next(r2.Scenario.PlotItems, nil)
|
|||
|
while k do
|
|||
|
if v.SheetId and v.SheetId == plotItem.SheetId then
|
|||
|
reverseIdTable[plotItem.InstanceId] = v.InstanceId
|
|||
|
return true
|
|||
|
end
|
|||
|
k, v = next(r2.Scenario.PlotItems, k)
|
|||
|
end
|
|||
|
userComponentManager:reattributeClientId(plotItem, reverseIdTable)
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
if isAlreadyUsed(plotItem) == false then
|
|||
|
--insert plot item in scenario
|
|||
|
r2.requestInsertNode(r2.Scenario.InstanceId, "PlotItems", -1, "", plotItem)
|
|||
|
--r2:setCookie(newItem.InstanceId, "SelfCreate", true)
|
|||
|
--TODO = delete plotItem from pitem table in scenario so that it cannot be used twice
|
|||
|
return true
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
-- insertAll is called in the generated userFeature upon instanciation.
|
|||
|
-- Inserts all userComponents into the userFeature's components table after having renamed all
|
|||
|
-- userComponentIds into clientIds.
|
|||
|
--
|
|||
|
function userComponentManager:insertAll(feature, comp, tmpComponents)
|
|||
|
local texts = comp.Texts
|
|||
|
local items = feature.PlotItems
|
|||
|
local components = comp.Components
|
|||
|
local currentMaxId = r2.getMaxId()
|
|||
|
local reverseIdTable = generateReverseIdTable(tmpComponents, texts, currentMaxId)
|
|||
|
|
|||
|
local range = 0
|
|||
|
local nbItems = 0
|
|||
|
|
|||
|
local k, v = next(items, nil)
|
|||
|
while k do
|
|||
|
local inserted = self:insertPlotItem(v, reverseIdTable)
|
|||
|
if inserted == true then
|
|||
|
nbItems = nbItems + 1
|
|||
|
end
|
|||
|
k, v = next(items, k)
|
|||
|
end
|
|||
|
|
|||
|
local key, value = next(tmpComponents, nil)
|
|||
|
while key do
|
|||
|
range= range + countUCIds(value) + 3
|
|||
|
userComponentManager:reattributeClientId(value, reverseIdTable)
|
|||
|
table.insert(components , value)
|
|||
|
key, value = next(tmpComponents, key)
|
|||
|
end
|
|||
|
r2.reserveIdRange(range + nbItems)
|
|||
|
end
|
|||
|
|
|||
|
---------------------------------------------------------------------------------------------------------------------
|
|||
|
-- register the forms needed by the manager (save form, missing ids warning form).
|
|||
|
-- Called along with the other features registerForms method.
|
|||
|
function userComponentManager.registerForms()
|
|||
|
local fileListXML =
|
|||
|
[[
|
|||
|
<group id="tb_enclosing" sizeref="wh" w="-16" h="0" x="16" y="0" posref="TL TL">
|
|||
|
<instance template="inner_thin_border" inherit_gc_alpha="true"/>
|
|||
|
</group>
|
|||
|
<group id="enclosing" sizeref="w" w="-10" h="196" x="5" y="-5" posref="TL TL">
|
|||
|
<group id="file_list"
|
|||
|
type="list"
|
|||
|
active="true" x="16" y="0" posref="TL TL"
|
|||
|
sizeref="w"
|
|||
|
child_resize_h="true"
|
|||
|
max_sizeref="h"
|
|||
|
max_h="0"
|
|||
|
>
|
|||
|
</group>
|
|||
|
<ctrl style="skin_scroll" id="scroll_bar" align="T" target="file_list" />
|
|||
|
</group>
|
|||
|
<group id="gap" posref="BL TL" posparent="enclosing" w="1" h="6" />
|
|||
|
]]
|
|||
|
|
|||
|
function getComponentNameFromFile(filename)
|
|||
|
local prefixedFilename = r2_core.UserComponentsPath..filename
|
|||
|
local f = io.open(prefixedFilename,"r")
|
|||
|
assert(f)
|
|||
|
f:read("*line")
|
|||
|
f:read("*line")
|
|||
|
f:read("*line")
|
|||
|
f:read("*line")
|
|||
|
f:read("*line")
|
|||
|
local line = f:read("*line")
|
|||
|
if string.find(line, "CurrentFeatureName") == nil then
|
|||
|
messageBox("Unable to load a component from this file. Please select another file.")
|
|||
|
return "No components found"
|
|||
|
end
|
|||
|
f:close()
|
|||
|
local luaString = string.sub(line, 3)
|
|||
|
|
|||
|
loadstring(luaString)()
|
|||
|
local componentName = CurrentFeatureName
|
|||
|
CurrentFeatureName = ""
|
|||
|
return componentName
|
|||
|
end
|
|||
|
|
|||
|
local function getComponentFiles(searchPath)
|
|||
|
local files = getPathContent(searchPath)
|
|||
|
local componentFiles = {}
|
|||
|
|
|||
|
for k, v in pairs(files) do
|
|||
|
local prefixedFilename = r2_core.UserComponentsPath..nlfile.getFilename(v)
|
|||
|
local f = io.open(prefixedFilename,"r")
|
|||
|
assert(f)
|
|||
|
local header = r2.getFileHeader(prefixedFilename)
|
|||
|
--TODO : acc<63>s fichier md5
|
|||
|
--local line = f:read("*line")
|
|||
|
--if line == "-- <Creation_Header>" then
|
|||
|
if header.CurrentFeatureName then
|
|||
|
table.insert(componentFiles, v)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
return componentFiles
|
|||
|
end
|
|||
|
|
|||
|
function r2_core.setCurrSelectedFile(filename, formAttr)
|
|||
|
local formInstance = r2.CurrentForm.Env.FormInstance
|
|||
|
--inspect(formInstance)
|
|||
|
if formInstance.LastFileButton then
|
|||
|
formInstance.LastFileButton.pushed = false
|
|||
|
end
|
|||
|
getUICaller().pushed = true
|
|||
|
formInstance.LastFileButton = getUICaller()
|
|||
|
r2.CurrentForm.Env.FormInstance[formAttr] = filename
|
|||
|
if r2.CurrentForm.Env.FormInstance["ComponentName"] then
|
|||
|
r2.CurrentForm.Env.FormInstance["ComponentName"] = getComponentNameFromFile(filename)
|
|||
|
end
|
|||
|
r2.CurrentForm.Env.updateAll()
|
|||
|
local eb = r2.CurrentForm:find("eb")
|
|||
|
setCaptureKeyboard(eb)
|
|||
|
eb:setSelectionAll()
|
|||
|
end
|
|||
|
|
|||
|
function r2.setCurrSelectedComponent(compName)
|
|||
|
local formInstance = r2.CurrentForm.Env.FormInstance
|
|||
|
if formInstance.LastFileButton then
|
|||
|
formInstance.LastFileButton.pushed = false
|
|||
|
end
|
|||
|
getUICaller().pushed = true
|
|||
|
formInstance.LastFileButton = getUICaller()
|
|||
|
r2.CurrentForm.Env.FormInstance.ComponentName = compName
|
|||
|
r2.CurrentForm.Env.updateAll()
|
|||
|
local eb = r2.CurrentForm:find("eb")
|
|||
|
setCaptureKeyboard(eb)
|
|||
|
eb:setSelectionAll()
|
|||
|
end
|
|||
|
|
|||
|
-- called at init to fill the file list
|
|||
|
local function showFileList(formInstance)
|
|||
|
local fileGroupList = r2.CurrentForm:find('file_list')
|
|||
|
r2.CurrentForm.Env.FormInstance["ComponentFileName"] = "UserComponent1.lua"
|
|||
|
r2.CurrentForm.Env.FormInstance["Name"] = "UserComponent1"
|
|||
|
r2.CurrentForm.Env.updateAll()
|
|||
|
--local searchPath = select(config.R2ScenariiPath, "save")
|
|||
|
local searchPath = r2_core.UserComponentsPath
|
|||
|
--local files = getPathContent(searchPath)
|
|||
|
local files = getComponentFiles(searchPath)
|
|||
|
table.sort(files)
|
|||
|
fileGroupList:clear()
|
|||
|
for k, v in pairs(files) do
|
|||
|
if string.lower(nlfile.getExtension(v)) == "lua" then
|
|||
|
local shortFilename = nlfile.getFilename(v)
|
|||
|
local entry = createGroupInstance("r2ed_filelist_entry", "",
|
|||
|
{ id = tostring(k), text = shortFilename,
|
|||
|
params_l="r2_core.setCurrSelectedFile('" .. shortFilename .. "', 'ComponentFileName')" })
|
|||
|
fileGroupList:addChild(entry)
|
|||
|
end
|
|||
|
end
|
|||
|
setCaptureKeyboard(r2.CurrentForm:find("eb"))
|
|||
|
end
|
|||
|
|
|||
|
--called at init to fill load form
|
|||
|
local function showUserComponentFileList(formInstance)
|
|||
|
local fileGroupList = r2.CurrentForm:find('file_list')
|
|||
|
--local searchPath = select(config.R2ScenariiPath, "save")
|
|||
|
local searchPath = r2_core.UserComponentsPath
|
|||
|
local files = getPathContent(searchPath)
|
|||
|
table.sort(files)
|
|||
|
local defaultValue = ""
|
|||
|
fileGroupList:clear()
|
|||
|
for k, v in pairs(files) do
|
|||
|
if string.lower(nlfile.getExtension(v)) == "lua" then
|
|||
|
local shortFilename = nlfile.getFilename(v)
|
|||
|
if defaultValue == "" then defaultValue = shortFilename end
|
|||
|
local entry = createGroupInstance("r2ed_filelist_entry", "",
|
|||
|
{ id = tostring(k), text = shortFilename,
|
|||
|
params_l="r2_core.setCurrSelectedFile('" .. shortFilename .. "', 'FileName')" })
|
|||
|
fileGroupList:addChild(entry)
|
|||
|
end
|
|||
|
end
|
|||
|
setCaptureKeyboard(r2.CurrentForm:find("eb"))
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
--called at init to fill Unload Form
|
|||
|
local function showUserComponentList(formInstance)
|
|||
|
local fileGroupList = r2.CurrentForm:find('file_list')
|
|||
|
local featureNameTable = r2.FeatureTree.getUserComponentList()
|
|||
|
for k, v in pairs(featureNameTable) do
|
|||
|
local entry = createGroupInstance("r2ed_filelist_entry", "",
|
|||
|
{id = tostring(v), text=tostring(v),
|
|||
|
params_l="r2.setCurrSelectedComponent('"..tostring(v).."')" })
|
|||
|
fileGroupList:addChild(entry)
|
|||
|
end
|
|||
|
setCaptureKeyboard(r2.CurrentForm:find("eb"))
|
|||
|
end
|
|||
|
|
|||
|
local function showMissingComponents()
|
|||
|
local formUI = r2:getForm("MissingIdsForm")
|
|||
|
local text = "The following objects are referenced in exported objects but will not be exported:\n"
|
|||
|
local k, v = next(formUI.Env.FormInstance.Value, nil)
|
|||
|
while k do
|
|||
|
text = text .."# " ..v.."\n"
|
|||
|
k, v = next(formUI.Env.FormInstance.Value, k)
|
|||
|
end
|
|||
|
text = text .."Continue anyway?"
|
|||
|
formUI:find('name_list').hardtext = text
|
|||
|
formUI.Env:updateAll()
|
|||
|
formUI.Env.updateSize()
|
|||
|
formUI:updateCoords()
|
|||
|
formUI:center()
|
|||
|
formUI:updateCoords()
|
|||
|
end
|
|||
|
|
|||
|
r2.Forms.MissingIdsForm =
|
|||
|
{
|
|||
|
|
|||
|
Caption = "uiR2EdMissingRefsWarning",
|
|||
|
PropertySheetHeader =
|
|||
|
[[
|
|||
|
<view type="text" id="name_list" multi_line="true" sizeref="w" w="-36" x="4" y="-2" posref="TL TL" global_color="true" fontsize="14" shadow="true" hardtext=""/>
|
|||
|
]],
|
|||
|
|
|||
|
Prop =
|
|||
|
{
|
|||
|
{Name="Value", Type="Table", Visible=false}
|
|||
|
},
|
|||
|
onShow = showMissingComponents
|
|||
|
}
|
|||
|
|
|||
|
r2.Forms.SaveUserComponent =
|
|||
|
{
|
|||
|
Caption = "uiR2EDExportUserComponent",
|
|||
|
PropertySheetHeader = fileListXML,
|
|||
|
Prop =
|
|||
|
{
|
|||
|
{Name="Name", Type="String", Category="uiR2EDRollout_Save", ValidateOnEnter = true },
|
|||
|
{Name="ComponentFileName", Type="String", Category="uiR2EDRollout_Save"},
|
|||
|
{Name="ComponentName", Type="Table", Visible = false}
|
|||
|
},
|
|||
|
onShow = showFileList
|
|||
|
}
|
|||
|
|
|||
|
r2.Forms.LoadUserComponent =
|
|||
|
{
|
|||
|
Caption = "uiR2EDExportLoadUserComponent",
|
|||
|
PropertySheetHeader = fileListXML,
|
|||
|
Prop =
|
|||
|
{
|
|||
|
{Name="FileName", Type="String", Category="uiR2EDRollout_Load", ValidateOnEnter = true },
|
|||
|
{Name="ComponentName", Type="String", Category="uiR2EDRollout_Load", WidgetStyle="StaticText"},
|
|||
|
},
|
|||
|
onShow = showUserComponentFileList
|
|||
|
}
|
|||
|
|
|||
|
r2.Forms.UnloadUserComponent =
|
|||
|
{
|
|||
|
Caption = "uiR2EDExportUnloadUserComponent",
|
|||
|
PropertySheetHeader = fileListXML,
|
|||
|
Prop =
|
|||
|
{
|
|||
|
{Name="ComponentName", Type="String", Category="uiR2EDRollout_Unload", ValidateOnEnter = true },
|
|||
|
},
|
|||
|
onShow = showUserComponentList
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:buildCurrentExportList(holder)
|
|||
|
table.clear(self.CurrentExportList)
|
|||
|
local components = holder.Components
|
|||
|
local k, v = next(components, nil)
|
|||
|
while k do
|
|||
|
if v and v.InstanceId then
|
|||
|
table.insert(self.CurrentExportList, v.InstanceId)
|
|||
|
end
|
|||
|
k, v = next(components, k)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
-- Tbl is a table containing all the instanceIds selected for export.
|
|||
|
function userComponentManager:export(list, refX, refY, refZ)
|
|||
|
|
|||
|
--local exportList = self.CurrentExportList
|
|||
|
local exportList = list
|
|||
|
assert(exportList)
|
|||
|
--builds a table containing all instanceIds and their corresponding userComponentId
|
|||
|
local refIdTable = userComponentManager:getRefIdTableFrom(exportList)
|
|||
|
|
|||
|
local missingIds = refIdTable.RefIds
|
|||
|
local missingIdsCount = 0
|
|||
|
--XXXXXX
|
|||
|
|
|||
|
--TODO = reattribute UC ids for plotitems + container
|
|||
|
|
|||
|
-- User component filename confirmation
|
|||
|
local function onFileOk(form)
|
|||
|
if (form.ComponentFileName ~= nil and type(form.ComponentFileName) == "string" and form.RefPosition ~= nil) then
|
|||
|
if form.ComponentFileName == "" or string.len(form.ComponentFileName) < 2 then
|
|||
|
messageBox(i18n.get("uiR2EDInvalidName"))
|
|||
|
return
|
|||
|
end
|
|||
|
if string.find(form.ComponentFileName, '\.lua', -4) == nil then
|
|||
|
form.ComponentFileName = form.ComponentFileName .. ".lua"
|
|||
|
end
|
|||
|
local refPosition = form.RefPosition
|
|||
|
local filename = form.ComponentFileName
|
|||
|
local prefixedFilename = r2_core.UserComponentsPath..filename
|
|||
|
local featureName = form.Name
|
|||
|
|
|||
|
userComponentManager:computeAllPositions(exportList, refPosition, refIdTable.InstanceIds)
|
|||
|
userComponentManager:componentToFile(prefixedFilename, featureName, exportList, refIdTable, refPosition)
|
|||
|
userComponentManager:clear()
|
|||
|
--the component is automatically loaded on receive save callback
|
|||
|
--r2.loadUserComponentFile(prefixedFilename)
|
|||
|
|
|||
|
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local function onFileCancel(form)
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
-- Position confirmation
|
|||
|
local function posOk(x, y, z)
|
|||
|
debugInfo(string.format("Validate export with reference position (%d, %d, %d)", x, y, z))
|
|||
|
local refPosition = {}
|
|||
|
refPosition["x"] = x
|
|||
|
refPosition["y"] = y
|
|||
|
refPosition["z"] = z
|
|||
|
refPosition["InstanceId"] = ""
|
|||
|
refPosition["Class"] = "Position"
|
|||
|
r2:doForm("SaveUserComponent", {RefPosition=refPosition}, onFileOk, onFileCancel)
|
|||
|
end
|
|||
|
|
|||
|
local function posCancel()
|
|||
|
debugInfo("Export canceled.")
|
|||
|
end
|
|||
|
|
|||
|
-- Export confirmation when missing some ids
|
|||
|
local function confirmExport()
|
|||
|
debugInfo("Export confirmed.")
|
|||
|
r2:choosePos("", posOk, posCancel, "")
|
|||
|
end
|
|||
|
|
|||
|
local function cancelExport()
|
|||
|
debugInfo("Export canceled.")
|
|||
|
end
|
|||
|
|
|||
|
local missingTbl = {}
|
|||
|
local key, value = next(missingIds, nil)
|
|||
|
while key do
|
|||
|
if value == "Not exported" then
|
|||
|
local tmpInstance = r2:getInstanceFromId(key)
|
|||
|
if tmpInstance ~= nil then
|
|||
|
missingIdsCount = missingIdsCount + 1
|
|||
|
table.insert(missingTbl, tmpInstance.Name)
|
|||
|
debugInfo("Object named '" ..tmpInstance.Name .."' is referenced in an exported object but will not be exported.")
|
|||
|
end
|
|||
|
end
|
|||
|
key, value = next(missingIds, key)
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
if missingIdsCount ~= 0 then
|
|||
|
debugInfo(tostring(missingIdsCount) .." object(s) referenced but not exported. Continue anyway?y/n")
|
|||
|
r2:doForm("MissingIdsForm", {Value=missingTbl}, confirmExport, cancelExport)
|
|||
|
else
|
|||
|
--r2:choosePos("", posOk, posCancel, "")
|
|||
|
posOk(refX, refY, refZ)
|
|||
|
end
|
|||
|
|
|||
|
end -- !export
|
|||
|
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:getCurrentExportList()
|
|||
|
return userComponentManager.CurrentExportList
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
function userComponentManager:isInExportList(target)
|
|||
|
local targetId = target.InstanceId
|
|||
|
local k, v = next(self.CurrentExportList, nil)
|
|||
|
while k do
|
|||
|
if v == targetId then
|
|||
|
return true
|
|||
|
end
|
|||
|
-- test if not a son of an already exported element
|
|||
|
local currParent = target.ParentInstance
|
|||
|
while currParent ~= nil do
|
|||
|
if currParent.InstanceId == v then
|
|||
|
return true
|
|||
|
end
|
|||
|
currParent = currParent.ParentInstance
|
|||
|
end
|
|||
|
k, v = next(self.CurrentExportList, k)
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:getCurrentExportList()
|
|||
|
return userComponentManager.CurrentExportList
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
function userComponentManager:isInExportList(target)
|
|||
|
local targetId = target.InstanceId
|
|||
|
local k, v = next(self.CurrentExportList, nil)
|
|||
|
while k do
|
|||
|
if v == targetId then
|
|||
|
return true
|
|||
|
end
|
|||
|
-- test if not a son of an already exported element
|
|||
|
local currParent = target.ParentInstance
|
|||
|
while currParent ~= nil do
|
|||
|
if currParent.InstanceId == v then
|
|||
|
return true
|
|||
|
end
|
|||
|
currParent = currParent.ParentInstance
|
|||
|
end
|
|||
|
k, v = next(self.CurrentExportList, k)
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
---------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:addToExportList(instanceId)
|
|||
|
local instance = r2:getInstanceFromId(instanceId)
|
|||
|
if instance == nil then
|
|||
|
debugInfo("UserComponentManager:AddToExportList : no instance")
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
table.insert(self.CurrentExportList, instanceId)
|
|||
|
|
|||
|
return true
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:clear()
|
|||
|
table.clear(userComponentManager.InstanceIds)
|
|||
|
table.clear(userComponentManager.Texts)
|
|||
|
table.clear(userComponentManager.PlotItems)
|
|||
|
table.clear(userComponentManager.Positions)
|
|||
|
table.clear(userComponentManager.CurrentExportList)
|
|||
|
userComponentManager.CurrentExportList = {}
|
|||
|
userComponentManager.CurrentDesc = ""
|
|||
|
debugInfo("UserComponentManager tables cleared.")
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:computeAllPositions(argTbl, refPosition, refIdTable)
|
|||
|
|
|||
|
local function buildPosition(instance, isTopLevel, refPosition)
|
|||
|
local position = {}
|
|||
|
if not instance.Position then return nil end
|
|||
|
if instance ~= nil and (instance.InheritPos == 0 or isTopLevel == true) then
|
|||
|
position["x"] = r2.getWorldPos(instance).x - refPosition["x"]
|
|||
|
position["y"] = r2.getWorldPos(instance).y - refPosition["y"]
|
|||
|
position["z"] = 0
|
|||
|
else
|
|||
|
position["x"] = instance.Position.x
|
|||
|
position["y"] = instance.Position.y
|
|||
|
position["z"] = instance.Position.z
|
|||
|
end
|
|||
|
position["InstanceId"] = refIdTable[instance.Position.InstanceId]
|
|||
|
position["Class"] = "Position"
|
|||
|
return position
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
local function computePositions(instance, isTopLevel, refPosition)
|
|||
|
assert(instance)
|
|||
|
|
|||
|
local localRefPos = nil
|
|||
|
|
|||
|
localRefPos = buildPosition(instance, isTopLevel, refPosition)
|
|||
|
if localRefPos ~= nil and not userComponentManager.Positions[instance.Position.InstanceId] then
|
|||
|
userComponentManager.Positions[instance.Position.InstanceId] = localRefPos
|
|||
|
elseif localRefPos == nil then
|
|||
|
localRefPos = refPosition
|
|||
|
end
|
|||
|
|
|||
|
local key, value = next(instance, nil)
|
|||
|
while key do
|
|||
|
if type(value) == "userdata" then
|
|||
|
local subInstance = value
|
|||
|
computePositions(subInstance, false, localRefPos)
|
|||
|
end
|
|||
|
key, value = next(instance, key)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
if argTbl == nil then
|
|||
|
else
|
|||
|
local i = 1
|
|||
|
local nbExportedInstances = table.getn(argTbl)
|
|||
|
while i <= nbExportedInstances do
|
|||
|
local tmpInstance = r2:getInstanceFromId(argTbl[i])
|
|||
|
if tmpInstance ~= nil then
|
|||
|
computePositions(tmpInstance, true, refPosition)
|
|||
|
end
|
|||
|
i = i + 1
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
---------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:removeIdFromExportList(id)
|
|||
|
local exportList = self.CurrentExportList
|
|||
|
assert(exportList)
|
|||
|
|
|||
|
local k, v = next(exportList, nil)
|
|||
|
while k do
|
|||
|
if v == id then
|
|||
|
break
|
|||
|
end
|
|||
|
k, v = next(exportList, k)
|
|||
|
end
|
|||
|
if k ~= nil then
|
|||
|
table.remove(exportList,k)
|
|||
|
if table.getn(exportList) == 0 then
|
|||
|
self.CurrentExportList = {}
|
|||
|
end
|
|||
|
debugInfo(tostring(v) .." removed from exportList")
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
function userComponentManager:registerUserComponentData(fileName)
|
|||
|
|
|||
|
local function checkEntry(entry)
|
|||
|
local ucTable = r2_core.UserComponentTable
|
|||
|
local k, v = next(ucTable, nil)
|
|||
|
while k do
|
|||
|
if v[1] == entry[1] and self:isInitialized() == true then
|
|||
|
messageBox("A UserComponent called '"..entry[1].."' is already loaded. Unload it before loading another component with the same name.")
|
|||
|
return false
|
|||
|
end
|
|||
|
if v[2] == entry[2] and self:isInitialized() == true then
|
|||
|
messageBox("This file has already been loaded.")
|
|||
|
return false
|
|||
|
end
|
|||
|
k, v = next(ucTable, k)
|
|||
|
end
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
local f = io.open(fileName,"r")
|
|||
|
assert(f)
|
|||
|
f:read("*line")
|
|||
|
f:read("*line")
|
|||
|
f:read("*line")
|
|||
|
f:read("*line")
|
|||
|
f:read("*line")
|
|||
|
local line = f:read("*line")
|
|||
|
f:close()
|
|||
|
local luaString = string.sub(line, 3)
|
|||
|
|
|||
|
loadstring(luaString)()
|
|||
|
|
|||
|
local currentFeatureName = tostring(CurrentFeatureName)
|
|||
|
|
|||
|
local entry = { currentFeatureName, fileName }
|
|||
|
if checkEntry(entry) == false then return end
|
|||
|
|
|||
|
table.insert(r2_core.UserComponentTable, entry)
|
|||
|
|
|||
|
local userComponentTable = r2_core.UserComponentTable
|
|||
|
local userComponentTableFile = io.open("save/r2_core_user_component_table.lua", "w")
|
|||
|
|
|||
|
userComponentTableFile:write("r2_core.UserComponentTable = \n{\n")
|
|||
|
|
|||
|
local k, v = next(userComponentTable , nil)
|
|||
|
while k do
|
|||
|
if v then
|
|||
|
userComponentTableFile:write("\t{")
|
|||
|
userComponentTableFile:write(string.format("%q", v[1]) ..", ")
|
|||
|
userComponentTableFile:write(string.format("%q", v[2]) ..", ")
|
|||
|
userComponentTableFile:write("},\n")
|
|||
|
end
|
|||
|
k, v = next(userComponentTable, k)
|
|||
|
end
|
|||
|
|
|||
|
userComponentTableFile:write("} --!UserComponentTable")
|
|||
|
|
|||
|
userComponentTableFile:close()
|
|||
|
|
|||
|
end
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:unregisterComponent(featureName)
|
|||
|
local userComponentTable = r2_core.UserComponentTable
|
|||
|
local k, v = next(userComponentTable, nil)
|
|||
|
while k do
|
|||
|
if v[1] == featureName then
|
|||
|
break
|
|||
|
end
|
|||
|
k, v = next(userComponentTable, k)
|
|||
|
end
|
|||
|
|
|||
|
if k ~= nil then
|
|||
|
table.remove(userComponentTable,k)
|
|||
|
if table.getn(userComponentTable) == 0 then
|
|||
|
r2_core.UserComponentTable = {}
|
|||
|
end
|
|||
|
debugInfo(tostring(v[1]) .." removed from loaded usercomponent table.")
|
|||
|
end
|
|||
|
local userComponentTableFile = io.open("save/r2_core_user_component_table.lua", "w")
|
|||
|
|
|||
|
userComponentTableFile:write("r2_core.UserComponentTable = \n{\n")
|
|||
|
|
|||
|
local k, v = next(userComponentTable , nil)
|
|||
|
while k do
|
|||
|
if v then
|
|||
|
userComponentTableFile:write("\t{")
|
|||
|
userComponentTableFile:write(string.format("%q", v[1]) ..", ")
|
|||
|
userComponentTableFile:write(string.format("%q", v[2]) ..", ")
|
|||
|
userComponentTableFile:write("},\n")
|
|||
|
end
|
|||
|
k, v = next(userComponentTable, k)
|
|||
|
end
|
|||
|
|
|||
|
userComponentTableFile:write("} --!UserComponentTable")
|
|||
|
|
|||
|
userComponentTableFile:close()
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:unloadUserComponent()
|
|||
|
|
|||
|
local function checkFeatureName(name)
|
|||
|
local tbl = r2_core.UserComponentTable
|
|||
|
local k, v = next(tbl, nil)
|
|||
|
while k do
|
|||
|
if v[1] == name then
|
|||
|
return true
|
|||
|
end
|
|||
|
k, v = next(tbl, k)
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
local function onChoiceOk(form)
|
|||
|
local featureName = form.ComponentName
|
|||
|
if featureName == "" or checkFeatureName(featureName) == false then
|
|||
|
messageBox("This User Component is not loaded.")
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
userComponentManager:unregisterComponent(featureName)
|
|||
|
r2.FeatureTree.removeUCFromTree(featureName)
|
|||
|
local featureGroupList = r2:getForm("UnloadUserComponent"):find('file_list'):clear()
|
|||
|
--inspect(featureGroupList)
|
|||
|
--local featureNode = featureGroupList:getRootNode():getNodeFromId(featureName)
|
|||
|
--featureNode:getFather():deleteChild(featureNode)
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
local function onChoiceCancel()
|
|||
|
local featureGroupList = r2:getForm("UnloadUserComponent"):find('file_list'):clear()
|
|||
|
end
|
|||
|
|
|||
|
r2:doForm("UnloadUserComponent", {}, onChoiceOk, onChoiceCancel)
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:loadUserComponent(fileName, body, header)
|
|||
|
--TODO : loading md5
|
|||
|
--local ok = loadfile(fileName)
|
|||
|
local ok = loadstring(body)
|
|||
|
if not ok then
|
|||
|
messageBox("UserComponentManager: Couldn't load file '" ..fileName.."'.")
|
|||
|
return false
|
|||
|
end
|
|||
|
ok()
|
|||
|
|
|||
|
assert(header["CurrentFeatureName"])
|
|||
|
local currentFeatureName = header["CurrentFeatureName"]
|
|||
|
|
|||
|
local userFeature = r2.Features[currentFeatureName]
|
|||
|
|
|||
|
local componentId, component = next(userFeature.Components, nil)
|
|||
|
while (component ~= nil)
|
|||
|
do
|
|||
|
debugInfo("Registering user component " .. component.Name)
|
|||
|
r2.registerComponent(component)
|
|||
|
local class = r2.Classes[component.Name]
|
|||
|
class.NameToProp = {}
|
|||
|
for k, prop in pairs(class.Prop) do
|
|||
|
if prop.Name == nil then
|
|||
|
debugInfo("Found a property in class " .. tostring(class.Name) .. " with no field 'Name'")
|
|||
|
end
|
|||
|
class.NameToProp[prop.Name] = prop
|
|||
|
end
|
|||
|
assert(class)
|
|||
|
r2.Subclass(class)
|
|||
|
r2.registerGenerator(class)
|
|||
|
componentId, component = next(userFeature.Components, componentId)
|
|||
|
end
|
|||
|
|
|||
|
r2.FeatureTree.addUserComponentNode(currentFeatureName)
|
|||
|
if self.IsInitialized == false then
|
|||
|
self.InitialComponentToLoad = self.InitialComponentToLoad - 1
|
|||
|
else
|
|||
|
userComponentManager:registerUserComponentData(fileName)
|
|||
|
end
|
|||
|
end
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
|
|||
|
function userComponentManager:loadUserComponentFile()
|
|||
|
|
|||
|
local function onChoiceOk(form)
|
|||
|
local filename = form.FileName
|
|||
|
local prefixedFilename = r2_core.UserComponentsPath..filename
|
|||
|
|
|||
|
r2.loadUserComponentFile(prefixedFilename)
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
local function onChoiceCancel()
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
r2:doForm("LoadUserComponent", {}, onChoiceOk, onChoiceCancel)
|
|||
|
end
|
|||
|
---------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
function userComponentManager:computeNewPosition(instanceId, refPosition)
|
|||
|
|
|||
|
local function buildPosition(instance, isTopLevel, refPosition)
|
|||
|
--local position = {}
|
|||
|
|
|||
|
local position = r2.newComponent("Position")
|
|||
|
if not instance.Position then return nil end
|
|||
|
if instance ~= nil and (instance.InheritPos == 0 or isTopLevel == true) then
|
|||
|
position["x"] = r2.getWorldPos(instance).x - refPosition["x"]
|
|||
|
position["y"] = r2.getWorldPos(instance).y - refPosition["y"]
|
|||
|
position["z"] = r2:snapZToGround(r2.getWorldPos(instance).x, r2.getWorldPos(instance).y) - refPosition["z"]
|
|||
|
else
|
|||
|
position["x"] = instance.Position.x
|
|||
|
position["y"] = instance.Position.y
|
|||
|
position["z"] = instance.Position.z
|
|||
|
end
|
|||
|
--position["InstanceId"] = instance.Position.InstanceId
|
|||
|
--position["Class"] = "Position"
|
|||
|
return position
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
local function computePositions(instance, isTopLevel, refPosition)
|
|||
|
assert(instance)
|
|||
|
|
|||
|
local localRefPos = nil
|
|||
|
|
|||
|
localRefPos = buildPosition(instance, isTopLevel, refPosition)
|
|||
|
if localRefPos ~= nil and not userComponentManager.Positions[instance.Position.InstanceId] then
|
|||
|
userComponentManager.Positions[instance.Position.InstanceId] = localRefPos
|
|||
|
elseif localRefPos == nil then
|
|||
|
localRefPos = refPosition
|
|||
|
end
|
|||
|
|
|||
|
local key, value = next(instance, nil)
|
|||
|
while key do
|
|||
|
if type(value) == "userdata" then
|
|||
|
local subInstance = value
|
|||
|
computePositions(subInstance, false, localRefPos)
|
|||
|
end
|
|||
|
key, value = next(instance, key)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local tmpInstance = r2:getInstanceFromId(instanceId)
|
|||
|
if tmpInstance ~= nil then
|
|||
|
computePositions(tmpInstance, true, refPosition)
|
|||
|
end
|
|||
|
--table.clear(userComponentManager.Positions)
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:insertNewPosition(instanceId)
|
|||
|
local instance = r2:getInstanceFromId(instanceId)
|
|||
|
local newPosition = userComponentManager.Positions[instance.Position.InstanceId]
|
|||
|
if not newPosition then
|
|||
|
debugInfo("Can't retrieve new position for '"..tostring(instance.Position.InstanceId))
|
|||
|
assert(0)
|
|||
|
end
|
|||
|
r2.requestSetNode(instanceId, "Position", newPosition)
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:replacePosition(instanceId)
|
|||
|
local currentHolder = r2:getInstanceFromId(r2_core.CurrentHolderId)
|
|||
|
assert(currentHolder)
|
|||
|
|
|||
|
local refPosition = currentHolder.Position
|
|||
|
|
|||
|
self:computeNewPosition(instanceId, refPosition)
|
|||
|
|
|||
|
self:insertNewPosition(instanceId)
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function userComponentManager:restorePosition(instanceId, refPosition)
|
|||
|
local instance = r2:getInstanceFromId(instanceId)
|
|||
|
local newPosition = r2.newComponent("Position")
|
|||
|
if not instance.Position then return nil end
|
|||
|
if instance ~= nil then
|
|||
|
newPosition["x"] = r2.getWorldPos(instance).x - refPosition["x"]
|
|||
|
newPosition["y"] = r2.getWorldPos(instance).y - refPosition["y"]
|
|||
|
newPosition["z"] = r2:snapZToGround(r2.getWorldPos(instance).x, r2.getWorldPos(instance).y) - refPosition["z"]
|
|||
|
end
|
|||
|
r2.requestSetNode(instanceId, "Position", newPosition)
|
|||
|
end
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
function r2.loadUserComponentCallback(filename, body, header)
|
|||
|
r2_core.UserComponentManager:loadUserComponent(filename, body, header)
|
|||
|
if r2_core.UserComponentManager.IsInitialized == false and r2_core.UserComponentManager.InitialComponentToLoad == 0 then
|
|||
|
debugInfo("# UserComponentManager init done.")
|
|||
|
r2_core.UserComponentManager.IsInitialized = true
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--------------------------------------------------------------------------------------------------------------------
|
|||
|
function r2.displayModifiedUserComponentFileError()
|
|||
|
messageBox("You cannot load a UserComponent file which has been externally modified")
|
|||
|
end
|