1 -- plot items. They are global to the scenario and can be given
2 -- by the DM to players
4 -- ////////////////////////////////
5 -- // PLOT ITEM CLASS DEFINITION //
6 -- ////////////////////////////////
8 local maxNumPlotItems
= tonumber(getDefine("r2ed_max_num_plot_items"))
9 local maxNumPlotItemSheets
= tonumber(getDefine("r2ed_max_num_plot_item_sheets"))
13 BaseClass
= "BaseClass",
15 DisplayerUI
= "R2::CDisplayerLua", -- name of the C++ class that displays this object in the ui
16 DisplayerUIParams
= "plotItemDisplayer", -- parameters passed to the ui displayer when it is created
17 Menu
="ui:interface:r2ed_base_menu",
20 { Name
="SheetId", Type
="Number", Visible
=false },
21 { Name
="Name", Type
="String", MaxNumChar
="32", MaxNumChar
="32"},
22 { Name
="Desc", Type
="String" },
23 { Name
="Comment", Type
="String" },
25 -- rollout header : allows to view & change the item sheet
28 <ctrl type="sheet" id="item_sheet"
30 value="LOCAL:R2:CURR_PLOT_ITEM"
36 params_l="r2.PlotItemsPanel:changeItem(r2:getSelectedInstance().IndexInParent)"
42 function plotItem
.isGlobalObject(this
)
47 local plotItemNamePrefix
= i18n
.get("uiR2EDPlotItemNamePrefix")
50 function plotItem
.getDisplayName(this
)
51 r2
.ScratchUCStr
:fromUtf8(this
.Name
)
52 return concatUCString(plotItemNamePrefix
, r2
.ScratchUCStr
)
55 function plotItem
.isNextSelectable(this
)
59 ---------------------------------------------------------------------------------------------------------
60 -- get select bar type
61 function plotItem
.SelectBarType(this
)
62 return i18n
.get("uiR2EDPlotItems"):toUtf8()
65 ---------------------------------------------------------------------------------------------------------
66 -- get first parent that is selectable in the select bar
67 function plotItem
.getFirstSelectBarParent(this
)
68 return r2
:getCurrentAct()
71 function plotItem
.getSelectBarIcon(this
)
72 return "ICO_mission_purse.tga"
75 r2
.registerComponent(plotItem
)
83 local itemUCName
= ucstring() -- keep a ucstring to avoid creation of string on the fly
84 local itemUCDesc
= ucstring() -- keep a ucstring to avoid creation of string on the fly
85 local itemUCComment
= ucstring() -- keep a ucstring to avoid creation of string on the fly
87 local plotItemSheetToDBPath
= {}
89 local plotItemSheetNbRef
= {} -- for each plot item sheet, store the number of references on it
90 -- each sheet must be use 0 or 1 time in the scenario
91 -- a ref count > 1 may happen during concurrent edition
92 -- in which case the user should be warned that some items are duplicated
94 local validItemColor
= CRGBA(255, 255, 255)
95 local duplicatedItemColor
= CRGBA(255, 0, 0)
97 -- /////////////////////////
98 -- // PLOT ITEM DISPLAYER //
99 -- /////////////////////////
101 -- Plot item displayer, shared between items
102 r2
.PlotItemDisplayerCommon
= {}
106 ----------------------------------------------------------------------------
107 -- update name for tooltip display + availability
108 function r2
.PlotItemDisplayerCommon
:updateNameAndAvailability(instance
, sheetId
)
109 if plotItemSheetNbRef
[sheetId
] == 0 then
110 r2
:setPlotItemInfos(sheetId
, i18n
.get("uiR2EDPlotItemDefaultName"), ucstring(), ucstring())
111 setDbProp(plotItemSheetToDBPath
[sheetId
], sheetId
) -- available again
112 elseif plotItemSheetNbRef
[sheetId
] > 1 then
113 -- duplicated slot, may happen during concurrent edition (bad luck)
114 r2
:setPlotItemInfos(sheetId
, i18n
.get("uiR2EDDuplicatedPlotItemName"), ucstring(), ucstring())
115 setDbProp(plotItemSheetToDBPath
[sheetId
], 0) -- available again
116 r2
.PlotItemDisplayerCommon
:touch() -- force to refresh the icon display
118 itemUCName
:fromUtf8(instance
.Name
)
119 itemUCDesc
:fromUtf8(instance
.Desc
)
120 itemUCComment
:fromUtf8(instance
.Comment
)
121 r2
:setPlotItemInfos(sheetId
, itemUCName
, itemUCDesc
, itemUCComment
)
122 setDbProp(plotItemSheetToDBPath
[sheetId
], 0) -- available again
126 ----------------------------------------------------------------------------
127 -- add a reference on a sheet id for a r2 plot item
128 function r2
.PlotItemDisplayerCommon
:addRef(sheetId
)
129 assert(plotItemSheetNbRef
[sheetId
] >= 0)
130 plotItemSheetNbRef
[sheetId
] = plotItemSheetNbRef
[sheetId
] + 1
133 ----------------------------------------------------------------------------
134 -- remove a reference on a sheet id for a r2 plot item
135 -- add a reference on a sheet id
136 function r2
.PlotItemDisplayerCommon
:decRef(sheetId
)
137 assert(plotItemSheetNbRef
[sheetId
] > 0)
138 plotItemSheetNbRef
[sheetId
] = plotItemSheetNbRef
[sheetId
] - 1
142 ----------------------------------------------------------------------------
143 -- show the property window and allows to edit the plot item name
144 function r2
.PlotItemDisplayerCommon
:editPlotItemName(instance
)
145 r2
:setSelectedInstanceId(instance
.InstanceId
)
146 r2
:showProperties(instance
)
147 local propWindow
= r2
.CurrentPropertyWindow
148 -- tmp : quick & dirty access to the widget ...
149 if propWindow
.active
then
151 local editBox
= propWindow
:find("Name"):find("eb")
153 setCaptureKeyboard(editBox
)
154 editBox
:setSelectionAll()
159 ----------------------------------------------------------------------------
160 function r2
.PlotItemDisplayerCommon
:onPostCreate(instance
)
162 setDbProp(plotItemSheetToDBPath
[instance
.SheetId
], 0) -- not available for other plot items
163 -- if created by this client, prompt to enter the name
164 if instance
.User
.SelfCreate
then
165 instance
.User
.SelfCreate
= nil
166 self
:editPlotItemName(instance
)
169 if instance
.User
.AddedMsg
then
170 instance
.User
.AddedMsg
= nil
171 displaySystemInfo(i18n
.get("uiR2EDPlotItemAdded"), "BC")
172 r2
.PlotItemsPanel
:pop()
175 instance
.User
.OldSheetId
= instance
.SheetId
176 self
:addRef(instance
.SheetId
)
177 self
:updateNameAndAvailability(instance
, instance
.SheetId
)
178 if instance
== r2
:getSelectedInstance() then
179 self
:updatePropWindow(instance
)
183 ----------------------------------------------------------------------------
184 function r2
.PlotItemDisplayerCommon
:onErase(instance
)
186 self
:decRef(instance
.SheetId
)
187 self
:updateNameAndAvailability(instance
, instance
.SheetId
)
188 if instance
== r2
.PlotItemsPanel
.ItemSelectCaller
then
189 -- discard item selection window if it was opened
190 getUI("ui:interface:r2ed_choose_plot_item").active
= false
191 self
.ItemSelectCaller
= nil
195 ----------------------------------------------------------------------------
196 function r2
.PlotItemDisplayerCommon
:onSelect(instance
, selected
)
199 self
:updatePropWindow(instance
)
201 getUI("ui:interface:r2ed_scenario"):find("delete_plot_item").frozen
= not selected
202 getUI("ui:interface:r2ed_scenario"):find("plot_item_properties").frozen
= not selected
205 ----------------------------------------------------------------------------
206 function r2
.PlotItemDisplayerCommon
:updatePropWindow(instance
)
207 -- change the icon displayed in the property sheet
208 setDbProp("LOCAL:R2:CURR_PLOT_ITEM:SHEET", instance
.SheetId
)
209 -- get the property window, maybe not shown yet ...
210 local propWindow
= getUI(r2
:getDefaultPropertySheetUIPath("PlotItem"))
211 -- update color of the sheet in the property window
213 self
:updateSheetColor(propWindow
:find("item_sheet"), instance
.SheetId
)
217 ----------------------------------------------------------------------------
218 function r2
.PlotItemDisplayerCommon
:onAttrModified(instance
, attributeName
, indexInArray
)
220 if attributeName
== "SheetId" then
221 self
:decRef(instance
.User
.OldSheetId
)
222 self
:updateNameAndAvailability(instance
, instance
.User
.OldSheetId
)
223 self
:addRef(instance
.SheetId
)
224 instance
.User
.OldSheetId
= instance
.SheetId
225 self
:updateNameAndAvailability(instance
, instance
.SheetId
)
226 if instance
== r2
:getSelectedInstance() then
227 self
:updatePropWindow(instance
)
230 if attributeName
== "Name" or attributeName
== "Desc" or attributeName
== "Comment" then
231 self
:updateNameAndAvailability(instance
, instance
.SheetId
)
236 ----------------------------------------------------------------------------
237 function r2
.PlotItemDisplayerCommon
:touch()
238 -- update will be done in main loop only
239 r2
.UIMainLoop
.PlotItemsModified
= true
242 ----------------------------------------------------------------------------
243 function r2
.PlotItemDisplayerCommon
:updateSheetColor(slot
, sheetId
)
244 if plotItemSheetNbRef
[sheetId
] and plotItemSheetNbRef
[sheetId
] > 1 then
245 slot
.color
= duplicatedItemColor
247 slot
.color
= validItemColor
251 ----------------------------------------------------------------------------
252 function r2
.PlotItemDisplayerCommon
:updateAll()
253 if r2
.Mode
~= "Edit" then return end
254 r2
.PlotItemsPanel
.Locked
= true
255 local window
= getUI("ui:interface:r2ed_scenario")
256 local groupListSheet
= window
:find("plot_items_list")
257 -- update db sheets for items display
259 for k
, v
in specPairs(r2
.Scenario
.PlotItems
) do
260 setDbProp("LOCAL:R2:PLOT_ITEMS:" .. tostring(index
) ..":SHEET", v
.SheetId
)
261 local slot
= groupListSheet
["item_" .. tostring(index
)]
262 slot
.but
.pushed
= (v
== r2
:getSelectedInstance()) -- update selection
263 itemUCName
:fromUtf8(v
.Name
)
264 self
:updateSheetColor(slot
.sheet
, v
.SheetId
)
265 slot
.t
.uc_hardtext
= itemUCName
266 slot
.t
.global_color
= true
270 -- last slot is the "create new item" slot
271 if index
<= maxNumPlotItems
- 1 then
272 -- special sheet here for new item creation
273 --setDbProp("LOCAL:R2:PLOT_ITEMS:" .. tostring(index) ..":SHEET", getSheetId("r2_create_new_plot_item.sitem"))
274 setDbProp("LOCAL:R2:PLOT_ITEMS:" .. tostring(index
) ..":SHEET", 0)
275 local slot
= groupListSheet
["item_" .. tostring(index
)]
276 slot
.but
.pushed
= false
278 slot
.t
.uc_hardtext
= i18n
.get("uiR2EDCreateNewItem")
279 slot
.t
.global_color
= false
280 slot
.sheet
.color
= validItemColor
281 window
:find("new_plot_item").frozen
= false
284 window
:find("new_plot_item").frozen
= true
286 -- remove remaining sheets
287 while index
< maxNumPlotItems
do
288 setDbProp("LOCAL:R2:PLOT_ITEMS:" .. tostring(index
) ..":SHEET", 0)
289 local slot
= groupListSheet
["item_" .. tostring(index
)]
293 r2
.PlotItemsPanel
.Locked
= false
297 -- Displayer ctor, just return a ref on the shared displayer
298 -- Works because we don't store per displayer infos
299 function r2
:plotItemDisplayer()
300 return r2
.PlotItemDisplayerCommon
303 -- ///////////////////////////
304 -- // PLOT ITEM UI HANDLING //
305 -- ///////////////////////////
311 Locked
= false, -- flag to avoid recursive selection
313 ItemSelectCaller
= nil, -- last plot item that called the 'select item' window (or nil if a new item is created)
314 TargetRefId
= -- if CreateMode is "CreateNewAndAffectToRefId", gives the name of the refid to which the item should be affected
317 ParentInstanceId
= ""
322 ----------------------------------------------------------------------------
323 function r2
.PlotItemsPanel
:selectItem(index
)
324 if r2
.PlotItemsPanel
.Locked
then return end -- this is a false selection
325 -- we can't use the sheet here, because concurrent edition may lead to duplicated sheets
326 -- here, a case that wecan resolve only when the scenario is about to be launched...
327 if index
> r2
.Scenario
.PlotItems
.Size
then
328 debugInfo("bad item index")
330 if index
== r2
.Scenario
.PlotItems
.Size
then
331 -- this is the creation slot
332 r2
:setSelectedInstanceId("")
333 enableModalWindow(getUICaller(), "ui:interface:r2ed_choose_plot_item")
334 getUICaller().parent
.but
.pushed
= false
335 self
.CreateMode
= "CreateNew"
336 self
.ItemSelectCaller
= nil
338 -- a new item is selected for real
339 r2
:setSelectedInstanceId(r2
.Scenario
.PlotItems
[index
].InstanceId
)
340 r2
.PlotItemDisplayerCommon
:touch()
344 ----------------------------------------------------------------------------
345 -- for plot item ref. widget (see r2.PlotItemsWidget) : pop the item creation
346 -- window, then affect the created widget to a refid (with name 'refIdName' in object with id 'targetInstanceId')
347 function r2
.PlotItemsPanel
:createNewItemAnAffectToRefId(instanceId
, refIdName
)
348 if r2
.Scenario
.PlotItems
.Size
>= maxNumPlotItems
then
349 displaySystemInfo(i18n
.get("uiR2EDNoMorePlotItems"), "BC")
353 enableModalWindow(getUICaller(), "ui:interface:r2ed_choose_plot_item")
354 self
.CreateMode
= "CreateNewAndAffectToRefId"
355 self
.ItemSelectCaller
= nil
356 self
.TargetRefId
.Name
= refIdName
357 self
.TargetRefId
.ParentInstanceId
= instanceId
360 ----------------------------------------------------------------------------
361 function r2
.PlotItemsPanel
:changeItem(index
)
362 self
:selectItem(index
)
363 -- this is the creation slot
364 if index
== r2
.Scenario
.PlotItems
.Size
then
365 self
.CreateMode
= "CreateNew"
366 self
.ItemSelectCaller
= nil
368 self
.CreateMode
= "Modify"
369 self
.ItemSelectCaller
= r2
.Scenario
.PlotItems
[index
]
371 enableModalWindow(getUICaller(), "ui:interface:r2ed_choose_plot_item")
372 self
.ChangeIndex
= index
374 local window
= getUI("ui:interface:r2ed_scenario")
375 local groupListSheet
= window
:find("plot_items_list")
376 if index
<= maxNumPlotItems
- 1 then
377 local slot
= groupListSheet
["item_" .. tostring(index
)]
378 slot
.but
.pushed
= false
382 ----------------------------------------------------------------------------
383 function r2
.PlotItemsPanel
:rightClickItem(index
)
384 if r2
.PlotItemsPanel
.Locked
then return end -- this is a false selection
385 -- we can't use the sheet here, because concurrent edition may lead to duplicated sheets
386 -- here, a case that wecan resolve only when the scenario is about to be launched...
387 if index
> r2
.Scenario
.PlotItems
.Size
then
388 debugInfo("bad item index")
390 if index
== r2
.Scenario
.PlotItems
.Size
then
391 -- this is the creation slot -> no-op
394 -- a new item is selected for real
395 r2
:setSelectedInstanceId(r2
.Scenario
.PlotItems
[index
].InstanceId
)
396 r2
:displayContextMenu()
400 ----------------------------------------------------------------------------
402 function r2
.PlotItemsPanel
:createNewItem(sheetDbPath
)
403 local sheetId
= getDbProp(sheetDbPath
.. ":SHEET")
404 if self
.CreateMode
== "CreateNew" then
405 local newItem
= self
:requestNewItem(sheetId
)
406 -- since created from this client, add a cookie to pop the property window when the item is created for real
407 r2
:setCookie(newItem
.InstanceId
, "SelfCreate", true)
408 elseif self
.CreateMode
== "CreateNewAndAffectToRefId" then
409 r2
.requestNewAction(i18n
.get("uiR2EDCreatePlotItemAction"))
410 local newItem
= self
:requestNewItem(sheetId
)
411 r2
:setCookie(newItem
.InstanceId
, "AddedMsg", true)
412 r2
.requestSetNode(self
.TargetRefId
.ParentInstanceId
, self
.TargetRefId
.Name
, newItem
.InstanceId
)
414 r2
.requestNewAction(i18n
.get("uiR2EDChangeIconAction"))
415 r2
.requestSetNode(r2
.Scenario
.PlotItems
[self
.ChangeIndex
].InstanceId
, "SheetId", sheetId
)
419 ----------------------------------------------------------------------------
420 -- private: create a new item in the plot item list
421 function r2
.PlotItemsPanel
:requestNewItem(sheetId
)
422 r2
.requestNewAction(i18n
.get("uiR2EDCreateNewPlotItemAction"))
423 local newItem
= r2
.newComponent("PlotItem")
424 newItem
.SheetId
= sheetId
425 newItem
.Name
= i18n
.get("uiR2EDPlotItemDefaultName"):toUtf8()
428 r2
.requestInsertNode(r2
.Scenario
.InstanceId
, "PlotItems", -1, "", newItem
)
432 ----------------------------------------------------------------------------
433 function r2
.PlotItemsPanel
:reinit()
434 -- map sheetid to the good slot in the db
435 plotItemSheetToDBPath
= {}
436 plotItemSheetNbRef
= {}
437 --local window = getUI("ui:interface:r2ed_scenario")
438 --local groupListSheet = window:find("plot_items_list")
439 for k
= 0, maxNumPlotItemSheets
- 1 do
440 local refDbPath
= "LOCAL:R2:REFERENCE_PLOT_ITEMS:" .. tostring(k
) ..":SHEET"
441 local availableDbPath
= "LOCAL:R2:AVAILABLE_PLOT_ITEMS:" .. tostring(k
) ..":SHEET"
442 local sheetId
= getDbProp(refDbPath
)
443 local defaultPlotItemName
= i18n
.get("uiR2EDPlotItemDefaultName")
445 plotItemSheetToDBPath
[sheetId
] = availableDbPath
446 plotItemSheetNbRef
[sheetId
] = 0
447 r2
:setPlotItemInfos(sheetId
, defaultPlotItemName
, ucstring(), ucstring())
448 setDbProp(availableDbPath
, getDbProp(refDbPath
))
450 --local slot = groupListSheet["item_" .. tostring(k)]
451 --slot.active = false
454 for k
= 0, maxNumPlotItems
- 1 do
455 setDbProp("LOCAL:R2:PLOT_ITEMS:" .. tostring(k
) .. ":SHEET", 0)
458 getUI("ui:interface:r2ed_scenario"):find("delete_plot_item").frozen
= true
459 getUI("ui:interface:r2ed_scenario"):find("plot_item_properties").frozen
= true
462 ----------------------------------------------------------------------------
463 -- pop the plot item tab
464 function r2
.PlotItemsPanel
:pop()
465 local scenarioWnd
= getUI("ui:interface:r2ed_scenario")
466 if not scenarioWnd
.active
or scenarioWnd
:find("scenario_tabs").selection
~= 3 then
467 scenarioWnd
.active
= 1
469 scenarioWnd
:find("scenario_tabs").selection
= 3