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

1659 lines
51 KiB
Lua
Raw Blame History

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