745 lines
24 KiB
Lua
745 lines
24 KiB
Lua
|
-----------------
|
||
|
-----------------
|
||
|
-- DISPLAYERS --
|
||
|
-----------------
|
||
|
-----------------
|
||
|
|
||
|
-- Displayer are objects attached to instance in the scenario
|
||
|
-- They react to modification events (creations of new objects such as nps, groups ...)
|
||
|
-- and update their display accordingly
|
||
|
-- There is zero or one displayer attached per category of display for each instance in the map
|
||
|
-- For now this include :
|
||
|
-- UI displayers : - They update the scenario window to display new things added to the map
|
||
|
-- Property displayers : - They update the property sheet for an instance when one is displayed
|
||
|
-- Visual displayers : - For now they are only implemented in C++. Their fonction is to update the display of a instance
|
||
|
-- - in the 3D scene
|
||
|
--
|
||
|
-- Displayer at attached at creation time by the C++ code
|
||
|
-- The displayers to add to a specific object are given its the class definition
|
||
|
-- (see r2_base_class.lua for details)
|
||
|
|
||
|
-- helper : update the context toolbar for the given instance if it is the current selected instance
|
||
|
local function updateContextToolbar(instance)
|
||
|
if r2:getSelectedInstance() == instance then
|
||
|
r2.ContextualCommands:update()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
-- The following code describes how to create a basic displayer that just
|
||
|
-- output the events it handles in the log
|
||
|
-- Mots of the time, when creating a new displayer, one will
|
||
|
-- just construct an existing displayer, and redefine methods of interest,
|
||
|
-- possibly calling the parent one
|
||
|
|
||
|
function r2:exampleUIDisplayer()
|
||
|
local handler = {}
|
||
|
local ct = colorTag(0, 0, 255)
|
||
|
------------------------------------------------
|
||
|
-- Called by C++ at creation
|
||
|
function handler:onCreate(instance)
|
||
|
debugInfo(ct .. "Instance " .. instance.InstanceId .." was created")
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
-- Called by C++ just before object is removed (so properties are still readable)
|
||
|
function handler:onErase(instance)
|
||
|
debugInfo(ct .. "Instance " .. instance.InstanceId .." was erased")
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
-- Called by C++ just before object is moved in the object hierarchy
|
||
|
function handler:onPreHrcMove(instance)
|
||
|
updateContextToolbar(instance)
|
||
|
debugInfo(ct .. "Instance " .. instance.InstanceId .." is about to move")
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
-- Called by C++ just after object is move in the object hierarchy
|
||
|
function handler:onPostHrcMove(instance)
|
||
|
updateContextToolbar(instance)
|
||
|
debugInfo(ct .. "Instance " .. instance.InstanceId .." has moved")
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
-- Called by C++ just after object is highlighted by mouse
|
||
|
function handler:onFocus(instance, hasFocus)
|
||
|
if (instance.User.HasFocus ~= hasFocus) then
|
||
|
if hasFocus == true then
|
||
|
debugInfo(ct .. "Instance " .. instance.InstanceId .." has gained focus")
|
||
|
else
|
||
|
debugInfo(ct .. "Instance " .. instance.InstanceId .." has lost focus")
|
||
|
end
|
||
|
instance.User.HasFocus = hasFocus
|
||
|
end
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
-- Called by C++ just after object has been selected
|
||
|
function handler:onSelect(instance, isSelected)
|
||
|
if (isSelected == true) then
|
||
|
debugInfo(ct .. "Instance " .. instance.InstanceId .." is selected")
|
||
|
else
|
||
|
debugInfo(ct .. "Instance " .. instance.InstanceId .." is unselected")
|
||
|
end
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
-- Called by C++ when an attribute of this object has been modified
|
||
|
-- An attribute inside this object has been modified
|
||
|
-- attributeName :Name of the attribute inside this object, as given by its class definition. If the attribute
|
||
|
-- is an array, then an additionnal parameter gives the index of the element being modified in the array (or -1 if the whole array is set)
|
||
|
function handler:onAttrModified(instance, attributeName, indexInArray)
|
||
|
updateContextToolbar(instance)
|
||
|
debugInfo(ct .. "Instance " .. instance.InstanceId .." has an attribute modified : " .. attributeName)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
function r2:onInstanceSelectedInTree(id)
|
||
|
-- is there's an active pick tool then
|
||
|
local currTool = r2:getCurrentTool()
|
||
|
if currTool and currTool:isPickTool() then
|
||
|
local tree = getUICaller()
|
||
|
tree:cancelNextSelectLine() -- don't want real selection, actually ...
|
||
|
if currTool:canPick() then
|
||
|
currTool:pick()
|
||
|
end
|
||
|
-- no-op else ...
|
||
|
return
|
||
|
end
|
||
|
--debugInfo("Seleting instance with id = " .. tostring(id) )
|
||
|
r2:setSelectedInstanceId(id)
|
||
|
end
|
||
|
|
||
|
function r2:onInstanceRightClickInTree(id)
|
||
|
r2:setSelectedInstanceId(id)
|
||
|
r2:displayContextMenu()
|
||
|
end
|
||
|
|
||
|
|
||
|
r2.VerboseEvents = false;
|
||
|
|
||
|
-- before to go to "test mode", store opened/closed nodes in scenario window tree
|
||
|
-- to correctly initialize tree when go back in edition mode
|
||
|
r2.storedClosedTreeNodes = {}
|
||
|
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
-- displayer that update the tree control (scenario window)
|
||
|
function r2:defaultUIDisplayer()
|
||
|
local function eventDebugInfo(msg)
|
||
|
if r2.VerboseEvents == true then
|
||
|
debugInfo(msg)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local handler = {}
|
||
|
local ct = colorTag(255, 0, 255)
|
||
|
------------------------------------------------
|
||
|
-- helper function : notify current act ui displayer that its quota has been modified
|
||
|
function handler:updateCurrentActQuota()
|
||
|
-- defer update to the next frame (many element can be added at once)
|
||
|
r2.UIMainLoop.LeftQuotaModified = true
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function handler:onCut(instance, cutted)
|
||
|
-- NOT IMPLEMENTED
|
||
|
-- debugInfo("On cut " .. tostring(cutted))
|
||
|
-- local tree = getUI(r2.InstanceTreePath)
|
||
|
-- debugInfo(tostring(select(cutted, 127, 255)))
|
||
|
-- instance.User.TreeNode.Color.G = select(cutted, 0, 255)
|
||
|
-- tree:forceRebuild()
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function handler:onCreate(instance)
|
||
|
--eventDebugInfo(ct .. "Instance " .. instance.InstanceId .." was created")
|
||
|
self:addTreeNode(instance)
|
||
|
-- if my quota is not 0, then we should update
|
||
|
-- the current act quota ..
|
||
|
--if instance:getUsedQuota() ~= 0 then
|
||
|
-- self:updateCurrentActQuota()
|
||
|
--end
|
||
|
if instance:hasScenarioCost() ~= false then
|
||
|
self:updateCurrentActQuota()
|
||
|
end
|
||
|
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function handler:onPostCreate(instance)
|
||
|
|
||
|
-- Special : if the cookie 'AskName' is set (by C++ or lua), then show property and ask name
|
||
|
-- to user for that object
|
||
|
if instance.User.AskName then
|
||
|
if instance.User.ShowProps then
|
||
|
r2:showProperties(instance)
|
||
|
instance.User.ShowProps = nil
|
||
|
end
|
||
|
if instance.User.Select then
|
||
|
r2:setSelectedInstanceId(instance.InstanceId)
|
||
|
end
|
||
|
local propWindow = r2.CurrentPropertyWindow
|
||
|
|
||
|
-- tmp : quick & dirty access to the widget ...
|
||
|
if propWindow and propWindow.active then
|
||
|
local editBox = propWindow:find("Name"):find("eb")
|
||
|
if editBox then
|
||
|
setCaptureKeyboard(editBox)
|
||
|
editBox:setSelectionAll()
|
||
|
end
|
||
|
end
|
||
|
instance.User.AskName = nil -- get rid of cookie
|
||
|
end
|
||
|
-- Special : if the cookie 'Select' is set (by C++ or lua), then the object should be selected after creation
|
||
|
if instance.User.Select then
|
||
|
r2:setSelectedInstanceId(instance.InstanceId)
|
||
|
end
|
||
|
if type(instance.User.CreateFunc) == "function" then
|
||
|
instance.User.CreateFunc(instance)
|
||
|
end
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function handler:onErase(instance)
|
||
|
--eventDebugInfo(ct .. "Instance " .. instance.InstanceId .." was erased")
|
||
|
self:removeTreeNode(instance)
|
||
|
-- if my quota is not 0, then we should update
|
||
|
-- the current act quota ..
|
||
|
if instance:hasScenarioCost() ~= false then
|
||
|
self:updateCurrentActQuota()
|
||
|
end
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function handler:onPreHrcMove(instance)
|
||
|
updateContextToolbar(instance)
|
||
|
--eventDebugInfo(ct .. "Instance " .. instance.InstanceId .." is about to move")
|
||
|
self:removeTreeNode(instance)
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function handler:onPostHrcMove(instance)
|
||
|
|
||
|
-- if parent is a group, for its creation you don't know category of children : people or creature
|
||
|
-- you check it for first child
|
||
|
local parent = instance.ParentInstance
|
||
|
if instance:isGrouped() and parent.Components.Size==1 then
|
||
|
self:onErase(parent)
|
||
|
self:onCreate(parent)
|
||
|
self:onPostCreate(parent)
|
||
|
end
|
||
|
|
||
|
updateContextToolbar(instance)
|
||
|
--eventDebugInfo(ct .. "Instance " .. instance.InstanceId .." has moved")
|
||
|
--eventDebugInfo(ct .. "New parent is " .. instance.ParentInstance.InstanceId)
|
||
|
local nodes = self:addTreeNode(instance)
|
||
|
if (r2:getSelectedInstance() == instance) and nodes then
|
||
|
for k, node in pairs(nodes) do
|
||
|
assert(node)
|
||
|
assert(node:getParentTree())
|
||
|
assert(node:getParentTree().selectNodeById)
|
||
|
node:getParentTree():selectNodeById(node.Id, false)
|
||
|
end
|
||
|
end
|
||
|
-- if my quota is not 0, then we should update
|
||
|
-- the current act quota ..
|
||
|
if instance:hasScenarioCost() ~= false then
|
||
|
self:updateCurrentActQuota()
|
||
|
end
|
||
|
|
||
|
-- if instance has Components, its children's nodes have been deleted at onPreHrcMove call
|
||
|
if instance.Components then
|
||
|
for i=0, instance.Components.Size-1 do
|
||
|
local child = instance.Components[i]
|
||
|
self:onCreate(child)
|
||
|
end
|
||
|
|
||
|
self:onPostCreate(instance)
|
||
|
end
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function handler:onFocus(instance, hasFocus)
|
||
|
if (instance.User.HasFocus ~= hasFocus) then
|
||
|
if hasFocus == true then
|
||
|
--eventDebugInfo(ct .. "Instance " .. instance.InstanceId .." has gained focus")
|
||
|
else
|
||
|
--eventDebugInfo(ct .. "Instance " .. instance.InstanceId .." has lost focus")
|
||
|
end
|
||
|
instance.User.HasFocus = hasFocus
|
||
|
end
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function handler:onSelect(instance, isSelected)
|
||
|
if not instance.User.TreeNodes then
|
||
|
return
|
||
|
end
|
||
|
for k, treeNode in pairs(instance.User.TreeNodes) do
|
||
|
|
||
|
if not (treeNode == nil or treeNode.isNil == true) then
|
||
|
|
||
|
local tree = treeNode:getParentTree()
|
||
|
if (isSelected == true) then
|
||
|
--eventDebugInfo(ct .. "Instance " .. instance.InstanceId .." is selected")
|
||
|
tree:selectNodeById(instance.InstanceId, false)
|
||
|
else
|
||
|
--eventDebugInfo(ct .. "Instance " .. instance.InstanceId .." is unselected")
|
||
|
tree:unselect()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function handler:onAttrModified(instance, attributeName, indexInArray)
|
||
|
if attributeName == "Position" or attributeName == "Angle" then
|
||
|
return
|
||
|
end
|
||
|
if attributeName == "Selectable" then
|
||
|
self:removeTreeNode(instance)
|
||
|
self:addTreeNode(instance)
|
||
|
end
|
||
|
|
||
|
updateContextToolbar(instance)
|
||
|
if not instance.User.TreeNodes then
|
||
|
return
|
||
|
end
|
||
|
local nodes = instance.User.TreeNodes
|
||
|
for k, node in pairs(nodes) do
|
||
|
local tree = node:getParentTree()
|
||
|
if attributeName == 'Name' then
|
||
|
setupNodeName(instance)
|
||
|
if node:getFather() then
|
||
|
node:getFather():sortByBitmap()
|
||
|
end
|
||
|
tree:forceRebuild()
|
||
|
tree:selectNodeById(node.Id, false) -- reforce the selection
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if attr == "Ghost" then
|
||
|
if instance.Ghost then
|
||
|
self:removeTreeNode(instance)
|
||
|
end
|
||
|
end
|
||
|
--eventDebugInfo(ct .. "Instance " .. instance.InstanceId .." has an attribute modified : " .. attributeName)
|
||
|
end
|
||
|
|
||
|
function setupNodeName(instance)
|
||
|
local treeNodes = instance.User.TreeNodes
|
||
|
if not treeNodes then return end
|
||
|
|
||
|
for k, treeNode in pairs(treeNodes) do
|
||
|
if not (treeNode == nil or treeNode.isNil == true) then
|
||
|
local tree = treeNode:getParentTree()
|
||
|
|
||
|
treeNode.Text = instance:getDisplayName()
|
||
|
if tree then -- nb : tree may be nil if node is setupped before being attached to its parent tree
|
||
|
tree:forceRebuild()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function handler:storeClosedTreeNodes()
|
||
|
|
||
|
function downInTree(node, nodeTable)
|
||
|
|
||
|
for i=0, node:getNumChildren()-1 do
|
||
|
local child = node:getChild(i)
|
||
|
assert(child)
|
||
|
|
||
|
nodeTable[child.Id] = child.Opened
|
||
|
|
||
|
if child:getNumChildren()>0 then
|
||
|
downInTree(child, nodeTable)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
r2.storedClosedTreeNodes = {}
|
||
|
|
||
|
-- scenary objects
|
||
|
r2.storedClosedTreeNodes[r2.Scenario:getBaseAct().InstanceId] = {}
|
||
|
local objectNodes = r2.storedClosedTreeNodes[r2.Scenario:getBaseAct().InstanceId]
|
||
|
|
||
|
local container = getUI("ui:interface:r2ed_scenario")
|
||
|
--local objectsRoot = container:find("content_tree_list"):getRootNode():getNodeFromId("scenery_objects")
|
||
|
local objectsRoot = container:find("content_tree_list"):getRootNode()
|
||
|
assert(objectsRoot)
|
||
|
downInTree(objectsRoot, objectNodes)
|
||
|
|
||
|
-- entities and components
|
||
|
if r2.Scenario.Acts.Size>1 then
|
||
|
for i=1, r2.Scenario.Acts.Size-1 do
|
||
|
local act = r2.Scenario.Acts[i]
|
||
|
local peopleRoot = act:getContentTree():getRootNode():getNodeFromId("people")
|
||
|
assert(peopleRoot)
|
||
|
local creatureRoot = act:getContentTree():getRootNode():getNodeFromId("creatures")
|
||
|
assert(creatureRoot)
|
||
|
--local componentRoot = act:getMacroContentTree():getRootNode():getNodeFromId("macro_components")
|
||
|
local componentRoot = act:getMacroContentTree():getRootNode()
|
||
|
assert(componentRoot)
|
||
|
|
||
|
r2.storedClosedTreeNodes[act.InstanceId] = {}
|
||
|
local actNodes = r2.storedClosedTreeNodes[act.InstanceId]
|
||
|
|
||
|
downInTree(peopleRoot, actNodes)
|
||
|
downInTree(creatureRoot, actNodes)
|
||
|
downInTree(componentRoot, actNodes)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function handler:addPermanentNodes()
|
||
|
|
||
|
if r2.ScenarioInstanceId then
|
||
|
local scenario = r2:getInstanceFromId(r2.ScenarioInstanceId)
|
||
|
if scenario and scenario.Acts.Size>0 then
|
||
|
local addToTreesTable = {}
|
||
|
scenario:getBaseAct():appendInstancesByType(addToTreesTable, "LogicEntity")
|
||
|
for k, instance in pairs(addToTreesTable) do
|
||
|
self:addTreeNode(instance)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- private
|
||
|
function handler:addTreeNode(instance)
|
||
|
|
||
|
if instance.Ghost then return nil end
|
||
|
|
||
|
local parentNodes = instance:getParentTreeNode()
|
||
|
|
||
|
if parentNodes==nil then return nil end
|
||
|
|
||
|
if instance.User.TreeNodes==nil then instance.User.TreeNodes = {} end
|
||
|
|
||
|
for actId,parentNode in pairs(parentNodes) do
|
||
|
|
||
|
local alreadyAdded = false
|
||
|
|
||
|
for k2, treeNode in pairs(instance.User.TreeNodes) do
|
||
|
if not (treeNode==nil or treeNode.isNil==true) then
|
||
|
|
||
|
local father = treeNode:getFather()
|
||
|
if father==parentNode then
|
||
|
alreadyAdded=true
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if not alreadyAdded then
|
||
|
|
||
|
if parentNode == nil then
|
||
|
return nil -- one of the ancestors may be unselectable
|
||
|
end
|
||
|
if not instance.SelectableFromRoot then
|
||
|
return nil
|
||
|
end
|
||
|
local tree = parentNode:getParentTree()
|
||
|
local treeNode = SNode()
|
||
|
|
||
|
-- store reference in object
|
||
|
table.insert(instance.User.TreeNodes, treeNode)
|
||
|
|
||
|
treeNode.Bitmap = instance:getPermanentStatutIcon()
|
||
|
local openTree = true
|
||
|
if r2.storedClosedTreeNodes[actId] then
|
||
|
openTree = (r2.storedClosedTreeNodes[actId][instance.InstanceId]==true)
|
||
|
end
|
||
|
treeNode.Opened = openTree
|
||
|
|
||
|
treeNode.Id = instance.InstanceId
|
||
|
treeNode.AHName = "lua"
|
||
|
local ahParams = "r2:onInstanceSelectedInTree('" .. instance.InstanceId .. "')"
|
||
|
--eventDebugInfo(ahParams)
|
||
|
treeNode.AHParams = ahParams
|
||
|
treeNode.AHNameRight = "lua"
|
||
|
treeNode.AHParamsRight = "r2:onInstanceRightClickInTree('" .. instance.InstanceId .. "')"
|
||
|
treeNode.AHNameClose = "lua"
|
||
|
treeNode.AHParamsClose = "r2.storedClosedTreeNodes = {}"
|
||
|
|
||
|
setupNodeName(instance)
|
||
|
|
||
|
assert(parentNode)
|
||
|
parentNode:addChildSortedByBitmap(treeNode)
|
||
|
parentNode.Show = (parentNode:getNumChildren() ~= 0)
|
||
|
|
||
|
tree:forceRebuild()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return instance.User.TreeNodes
|
||
|
end
|
||
|
function handler:removeTreeNode(instance)
|
||
|
|
||
|
local nodes = instance.User.TreeNodes
|
||
|
if nodes == nil or nodes.isNil then
|
||
|
return
|
||
|
end
|
||
|
for k, node in pairs(nodes) do
|
||
|
if not (node == nil or node.isNil == true) then
|
||
|
local tree = node:getParentTree()
|
||
|
if node:getFather().isNil then
|
||
|
if (node == node:getParentTree():getRootNode()) then
|
||
|
--debugInfo("ROOT NODE")
|
||
|
node:getParentTree():setRootNode(nil)
|
||
|
else
|
||
|
--debugInfo("ISOLATED NODE")
|
||
|
deleteReflectable(node) -- isolated node (the tree was never built ?)
|
||
|
end
|
||
|
else
|
||
|
-- update parent node visibility only if a direct son of the root node
|
||
|
if node:getFather() then
|
||
|
if (node:getFather():getFather() == tree:getRootNode()) then
|
||
|
node:getFather().Show = (node:getFather():getNumChildren() > 1)
|
||
|
end
|
||
|
node:getFather():deleteChild(node)
|
||
|
end
|
||
|
|
||
|
end
|
||
|
tree:forceRebuild()
|
||
|
end
|
||
|
end
|
||
|
instance.User.TreeNodes = nil
|
||
|
end
|
||
|
|
||
|
return handler
|
||
|
|
||
|
end
|
||
|
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
-- special display for groups in scenario window
|
||
|
function r2:groupUIDisplayer()
|
||
|
local handler = self:defaultUIDisplayer()
|
||
|
function handler:updateLeaderColor(instance)
|
||
|
if not instance.User.TreeNodes then
|
||
|
return
|
||
|
end
|
||
|
for k, node in pairs(instance.User.TreeNodes) do
|
||
|
local tree = node:getParentTree()
|
||
|
for i = 0, instance.Components.Size - 1 do
|
||
|
--debugInfo("I = " .. tostring(i))
|
||
|
local treeNodes = instance.Components[i].User.TreeNodes
|
||
|
if treeNodes then
|
||
|
for k2, treeNode in pairs(treeNodes) do
|
||
|
if i == 0 then
|
||
|
treeNode.Color = CRGBA(255, 0, 0) -- mark leader in red
|
||
|
else
|
||
|
treeNode.Color = CRGBA(255, 255, 255)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
tree:forceRebuild()
|
||
|
end
|
||
|
end
|
||
|
--
|
||
|
local oldOnAttrModified = handler.onAttrModified
|
||
|
function handler:onAttrModified(instance, attrName, indexInArray)
|
||
|
if attrName == "Components" then
|
||
|
self:updateLeaderColor(instance)
|
||
|
end
|
||
|
oldOnAttrModified(self, instance, attrName, indexInArray)
|
||
|
end
|
||
|
--
|
||
|
-- local oldOnCreate = handler.onCreate
|
||
|
-- function handler:onCreate(instance)
|
||
|
-- debugInfo("On create group")
|
||
|
-- oldOnCreate(self, instance)
|
||
|
-- end
|
||
|
--
|
||
|
local oldOnPostCreate = handler.onPostCreate
|
||
|
function handler:onPostCreate(instance)
|
||
|
oldOnPostCreate(self, instance)
|
||
|
self:updateLeaderColor(instance)
|
||
|
end
|
||
|
--
|
||
|
return handler
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
-----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
-- Displayer for ACTS. In the ui, acts are added into the act combo box --
|
||
|
-- in the environment of the container we store a table that gives the act Instance id,
|
||
|
-- and the index of the tree control for each line in the combo box
|
||
|
-- Table has the following look
|
||
|
-- ActTable = { { Act = ..., TreeIndex = ... }, -- combo box line 1
|
||
|
-- { Act = ..., TreeIndex = ... }, -- combo box line 2
|
||
|
-- { Act = ..., TreeIndex = ... }, -- combo box line 3 etc.
|
||
|
-- }
|
||
|
|
||
|
|
||
|
r2.ActUIDisplayer = {}
|
||
|
r2.ActUIDisplayer.ActTable = {} -- table that map each line of the combo box to an act
|
||
|
r2.ActUIDisplayer.LastSelfCreatedActInstanceId = nil -- id of the last act created by the pionner (not by another pionner)
|
||
|
-- When created, an act change will automatically occur
|
||
|
|
||
|
------------------------------------------------
|
||
|
-- helper function : notify current act ui displayer that its quota has been modified
|
||
|
function r2.ActUIDisplayer:updateCurrentActQuota()
|
||
|
-- defer update to the next frame (many element can be added at once)
|
||
|
r2.UIMainLoop.LeftQuotaModified = true
|
||
|
end
|
||
|
|
||
|
------------------------------------------------
|
||
|
function r2.ActUIDisplayer:updateActName(act)
|
||
|
|
||
|
if act and not act:isBaseAct() then
|
||
|
|
||
|
local actTable = self:getActTable()
|
||
|
for index, entry in pairs(actTable) do
|
||
|
if entry.Act == act then
|
||
|
local comboBox = self:getActComboBox()
|
||
|
|
||
|
local actTitle = act:getName()
|
||
|
if act==r2.Scenario:getCurrentAct() then
|
||
|
actTitle = actTitle .. " [" .. i18n.get("uiR2EDCurrentActComboBox"):toUtf8() .."]"
|
||
|
end
|
||
|
local text = ucstring()
|
||
|
text:fromUtf8(actTitle)
|
||
|
comboBox:setText(index - 1, text)
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
------------------------------------------------
|
||
|
function r2.ActUIDisplayer:onAttrModified(instance, attributeName, indexInArray)
|
||
|
|
||
|
-- if title is modified, then must update names of all entities in the scene
|
||
|
if attributeName == "Name" then
|
||
|
local npcs = {}
|
||
|
r2:getCurrentAct():appendInstancesByType(npcs, "Npc")
|
||
|
for k, npc in pairs(npcs) do
|
||
|
npc.DisplayerVisual:updateName()
|
||
|
end
|
||
|
|
||
|
self:updateActName(instance)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
------------------------------------------------
|
||
|
function r2.ActUIDisplayer:onCreate(act)
|
||
|
|
||
|
local container = self:getContainer()
|
||
|
local comboBox = self:getActComboBox()
|
||
|
|
||
|
local tree, macroTree
|
||
|
if not act:isBaseAct() then
|
||
|
local text = ucstring()
|
||
|
local index = r2.logicComponents:searchElementIndex(act)-2
|
||
|
local actTitle = act:getName()
|
||
|
if type(actTitle) ~= "string" then
|
||
|
text:fromUtf8("bad type for title : " .. type(actTitle))
|
||
|
comboBox:insertText(index, text)
|
||
|
else
|
||
|
text:fromUtf8(actTitle)
|
||
|
comboBox:insertText(index, text)
|
||
|
end
|
||
|
|
||
|
tree = self:findFreeTreeCtrl()
|
||
|
macroTree = self:findFreeTreeCtrl(true)
|
||
|
local actTable = self:getActTable()
|
||
|
table.insert(actTable, index+1, { Act = act, Tree = tree , MacroTree = macroTree})
|
||
|
end
|
||
|
|
||
|
-- store tree in the act for future insertion of items
|
||
|
act.User.ContentTree = tree
|
||
|
act.User.MacroContentTree = macroTree
|
||
|
self:updateCurrentActQuota()
|
||
|
|
||
|
-- add permanent nodes to act node
|
||
|
r2:defaultUIDisplayer():addPermanentNodes()
|
||
|
end
|
||
|
|
||
|
------------------------------------------------
|
||
|
function r2.ActUIDisplayer:onPostCreate(act)
|
||
|
-- when a new act is created, select this act as the default
|
||
|
if act.InstanceId == self.LastSelfCreatedActInstanceId then
|
||
|
-- the act was just created by pionner on that computer, so change right now
|
||
|
r2.ScenarioWindow:setAct(act)
|
||
|
self.LastSelfCreatedActInstanceId = nil
|
||
|
end
|
||
|
r2.ScenarioWindow:updateUIFromCurrentAct()
|
||
|
self:updateCurrentActQuota()
|
||
|
end
|
||
|
|
||
|
------------------------------------------------
|
||
|
function r2.ActUIDisplayer:onErase(erasedAct)
|
||
|
-- clean tree content
|
||
|
local tree = erasedAct.User.ContentTree
|
||
|
local macroTree = erasedAct.User.MacroContentTree
|
||
|
if tree then
|
||
|
r2:cleanTreeNode(tree, "people")
|
||
|
r2:cleanTreeNode(tree, "creatures")
|
||
|
end
|
||
|
if macroTree then
|
||
|
--r2:cleanTreeNode(macroTree, "macro_components")
|
||
|
r2:cleanTreeRootNode(macroTree)
|
||
|
end
|
||
|
local actTable = self:getActTable()
|
||
|
for index, entry in pairs(actTable) do
|
||
|
if entry.Act == erasedAct then
|
||
|
self:getActComboBox():removeTextByIndex(index - 1)
|
||
|
table.remove(actTable, index)
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
|
||
|
self:updateCurrentActQuota()
|
||
|
end
|
||
|
------------------------------------------------
|
||
|
function r2.ActUIDisplayer:getActTable()
|
||
|
return self.ActTable
|
||
|
end
|
||
|
|
||
|
------------------------------------------------
|
||
|
function r2.ActUIDisplayer:getContainer()
|
||
|
return getUI("ui:interface:r2ed_scenario")
|
||
|
end
|
||
|
|
||
|
------------------------------------------------
|
||
|
function r2.ActUIDisplayer:getActComboBox()
|
||
|
return self:getContainer():find("act_combo_box")
|
||
|
end
|
||
|
|
||
|
-----------------------------------------------
|
||
|
function r2.ActUIDisplayer:findFreeTreeCtrl(macroTree)
|
||
|
|
||
|
local treeName = "act_tree_"
|
||
|
if macroTree==true then treeName="macro_act_tree_" end
|
||
|
for i = 0, r2:getMaxNumberOfAdditionnalActs() - 1 do
|
||
|
local tree = self:getContainer():find(treeName .. tostring(i))
|
||
|
local used = false
|
||
|
for index, entry in pairs(self:getActTable()) do
|
||
|
local entryTree = entry.Tree
|
||
|
if macroTree==true then entryTree = entry.MacroTree end
|
||
|
if entryTree == tree then
|
||
|
used = true
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
if not used then
|
||
|
return tree
|
||
|
end
|
||
|
end
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
|
||
|
function r2:createActUIDisplayer()
|
||
|
return r2.ActUIDisplayer
|
||
|
end
|
||
|
|