Merge branch 'fixes' into main/gingo-test
[ryzomcore.git] / ryzom / common / data_common / r2 / r2_plot_item.lua
blobda653016944c6738e312553fc0fe9deae2c55c4b
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"))
11 local plotItem =
13 BaseClass = "BaseClass",
14 Name = "PlotItem",
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",
18 Prop =
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
26 PropertySheetHeader =
28 <ctrl type="sheet" id="item_sheet"
29 onclick_r=""
30 value="LOCAL:R2:CURR_PLOT_ITEM"
31 dragable="false"
32 use_quantity="false"
33 use_quality="false"
34 posref="TL TL" x="0"
35 onclick_l="lua"
36 params_l="r2.PlotItemsPanel:changeItem(r2:getSelectedInstance().IndexInParent)"
38 ]],
41 -- from base class
42 function plotItem.isGlobalObject(this)
43 return true
44 end
47 local plotItemNamePrefix = i18n.get("uiR2EDPlotItemNamePrefix")
50 function plotItem.getDisplayName(this)
51 r2.ScratchUCStr:fromUtf8(this.Name)
52 return concatUCString(plotItemNamePrefix, r2.ScratchUCStr)
53 end
55 function plotItem.isNextSelectable(this)
56 return true
57 end
59 ---------------------------------------------------------------------------------------------------------
60 -- get select bar type
61 function plotItem.SelectBarType(this)
62 return i18n.get("uiR2EDPlotItems"):toUtf8()
63 end
65 ---------------------------------------------------------------------------------------------------------
66 -- get first parent that is selectable in the select bar
67 function plotItem.getFirstSelectBarParent(this)
68 return r2:getCurrentAct()
69 end
71 function plotItem.getSelectBarIcon(this)
72 return "ICO_mission_purse.tga"
73 end
75 r2.registerComponent(plotItem)
79 -- /////////////
80 -- // PRIVATE //
81 -- /////////////
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
117 else
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
150 propWindow:blink(1)
151 local editBox = propWindow:find("Name"):find("eb")
152 if editBox then
153 setCaptureKeyboard(editBox)
154 editBox:setSelectionAll()
156 end
159 ----------------------------------------------------------------------------
160 function r2.PlotItemDisplayerCommon:onPostCreate(instance)
161 self:touch()
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)
185 self:touch()
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)
197 self:touch()
198 if selected then
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
212 if propWindow then
213 self:updateSheetColor(propWindow:find("item_sheet"), instance.SheetId)
217 ----------------------------------------------------------------------------
218 function r2.PlotItemDisplayerCommon:onAttrModified(instance, attributeName, indexInArray)
219 self:touch()
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
246 else
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
258 local index = 0
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
267 slot.active=true
268 index = index + 1
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
277 slot.active=true
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
282 index = index + 1
283 else
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)]
290 slot.active=false
291 index = index + 1
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 -- ///////////////////////////
308 -- UI part
309 r2.PlotItemsPanel =
311 Locked = false, -- flag to avoid recursive selection
312 CreateMode = "",
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
316 Name="",
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
337 else
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")
350 self:pop()
351 return
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
367 else
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
392 return
393 else
394 -- a new item is selected for real
395 r2:setSelectedInstanceId(r2.Scenario.PlotItems[index].InstanceId)
396 r2:displayContextMenu()
400 ----------------------------------------------------------------------------
401 -- private
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)
413 else
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()
426 newItem.Desc = ""
427 newItem.Comment = ""
428 r2.requestInsertNode(r2.Scenario.InstanceId, "PlotItems", -1, "", newItem)
429 return 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")
444 if sheetId ~= 0 then
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
453 -- empty all slots
454 for k = 0, maxNumPlotItems - 1 do
455 setDbProp("LOCAL:R2:PLOT_ITEMS:" .. tostring(k) .. ":SHEET", 0)
456 end
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
468 scenarioWnd:blink(1)
469 scenarioWnd:find("scenario_tabs").selection = 3