summaryrefslogtreecommitdiff
path: root/indra/newview/scripts/lua/require
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/scripts/lua/require')
-rw-r--r--indra/newview/scripts/lua/require/LLInventory.lua41
-rw-r--r--indra/newview/scripts/lua/require/UI.lua5
-rw-r--r--indra/newview/scripts/lua/require/result_view.lua98
3 files changed, 132 insertions, 12 deletions
diff --git a/indra/newview/scripts/lua/require/LLInventory.lua b/indra/newview/scripts/lua/require/LLInventory.lua
index dd1b910250..2c80a8602b 100644
--- a/indra/newview/scripts/lua/require/LLInventory.lua
+++ b/indra/newview/scripts/lua/require/LLInventory.lua
@@ -1,12 +1,28 @@
local leap = require 'leap'
local mapargs = require 'mapargs'
+local result_view = require 'result_view'
+
+local function result(keys)
+ -- capture result_view() instances for both categories and items
+ local result_table = {
+ categories=result_view(keys.categories),
+ items=result_view(keys.items),
+ -- call result_table:close() to release result sets before garbage
+ -- collection or script completion
+ close = function(self)
+ result_view.close(keys.categories[1], keys.items[1])
+ end
+ }
+ -- When the result_table is destroyed, close its result_views.
+ return LL.setdtor('LLInventory result', result_table, result_table.close)
+end
local LLInventory = {}
-- Get the items/folders info by provided IDs,
-- reply will contain "items" and "categories" tables accordingly
function LLInventory.getItemsInfo(item_ids)
- return leap.request('LLInventory', {op = 'getItemsInfo', item_ids=item_ids})
+ return result(leap.request('LLInventory', {op = 'getItemsInfo', item_ids=item_ids}))
end
-- Get the table of folder type names, which can be later used to get the ID of the basic folders
@@ -19,30 +35,33 @@ function LLInventory.getBasicFolderID(ft_name)
return leap.request('LLInventory', {op = 'getBasicFolderID', ft_name=ft_name}).id
end
--- Get the table of asset type names, which can be later used to get the specific items via LLInventory.collectDescendentsIf(...)
+-- Get the table of asset type names, which can be later used to get the specific items via LLInventory.collectDescendantsIf(...)
function LLInventory.getAssetTypeNames()
return leap.request('LLInventory', {op = 'getAssetTypeNames'}).names
end
--- Get the direct descendents of the 'folder_id' provided,
+-- Get the direct descendants of the 'folder_id' provided,
-- reply will contain "items" and "categories" tables accordingly
-function LLInventory.getDirectDescendents(folder_id)
- return leap.request('LLInventory', {op = 'getDirectDescendents', folder_id=folder_id})
+function LLInventory.getDirectDescendants(folder_id)
+ return result(leap.request('LLInventory', {op = 'getDirectDescendants', folder_id=folder_id}))
end
+-- backwards compatibility
+LLInventory.getDirectDescendents = LLInventory.getDirectDescendants
--- Get the descendents of the 'folder_id' provided, which pass specified filters
+-- Get the descendants of the 'folder_id' provided, which pass specified filters
-- reply will contain "items" and "categories" tables accordingly
--- LLInventory.collectDescendentsIf{ folder_id -- parent folder ID
+-- LLInventory.collectDescendantsIf{ folder_id -- parent folder ID
-- [, name] -- name (substring)
-- [, desc] -- description (substring)
-- [, type] -- asset type
-- [, limit] -- item count limit in reply, maximum and default is 100
-- [, filter_links]} -- EXCLUDE_LINKS - don't show links, ONLY_LINKS - only show links, INCLUDE_LINKS - show links too (default)
-function LLInventory.collectDescendentsIf(...)
+function LLInventory.collectDescendantsIf(...)
local args = mapargs('folder_id,name,desc,type,filter_links,limit', ...)
- args.op = 'collectDescendentsIf'
- return leap.request('LLInventory', args)
+ args.op = 'collectDescendantsIf'
+ return result(leap.request('LLInventory', args))
end
-
+-- backwards compatibility
+LLInventory.collectDescendentsIf = LLInventory.collectDescendantsIf
return LLInventory
diff --git a/indra/newview/scripts/lua/require/UI.lua b/indra/newview/scripts/lua/require/UI.lua
index bbcae3514a..73a76fa6b8 100644
--- a/indra/newview/scripts/lua/require/UI.lua
+++ b/indra/newview/scripts/lua/require/UI.lua
@@ -2,6 +2,7 @@
local leap = require 'leap'
local mapargs = require 'mapargs'
+local result_view = require 'result_view'
local Timer = (require 'timers').Timer
local util = require 'util'
@@ -234,7 +235,9 @@ function UI.closeAllFloaters()
end
function UI.getFloaterNames()
- return leap.request("LLFloaterReg", {op = "getFloaterNames"}).floaters
+ local key_length = leap.request("LLFloaterReg", {op = "getFloaterNames"}).floaters
+ local view = result_view(key_length)
+ return LL.setdtor('registered floater names', view, view.close)
end
return UI
diff --git a/indra/newview/scripts/lua/require/result_view.lua b/indra/newview/scripts/lua/require/result_view.lua
new file mode 100644
index 0000000000..5301d7838c
--- /dev/null
+++ b/indra/newview/scripts/lua/require/result_view.lua
@@ -0,0 +1,98 @@
+local leap = require 'leap'
+
+-- metatable for every result_view() table
+local mt = {
+ __len = function(self)
+ return self.length
+ end,
+ __index = function(self, i)
+ -- right away, convert to 0-relative indexing
+ i -= 1
+ -- can we find this index within the current slice?
+ local reli = i - self.start
+ if 0 <= reli and reli < #self.slice then
+ -- Lua 1-relative indexing
+ return self.slice[reli + 1]
+ end
+ -- is this index outside the overall result set?
+ if not (0 <= i and i < self.length) then
+ return nil
+ end
+ -- fetch a new slice starting at i, using provided fetch()
+ local start
+ self.slice, start = self.fetch(self.key, i)
+ -- It's possible that caller-provided fetch() function forgot
+ -- to return the adjusted start index of the new slice. In
+ -- Lua, 0 tests as true, so if fetch() returned (slice, 0),
+ -- we'll duly reset self.start to 0. Otherwise, assume the
+ -- requested index was not adjusted: that the returned slice
+ -- really does start at i.
+ self.start = start or i
+ -- Hopefully this slice contains the desired i.
+ -- Back to 1-relative indexing.
+ return self.slice[i - self.start + 1]
+ end,
+ -- We purposely avoid putting any array entries (int keys) into
+ -- our table so that access to any int key will always call our
+ -- __index() metamethod. Moreover, we want any table iteration to
+ -- call __index(table, i) however many times; we do NOT want it to
+ -- retrieve key, length, start, slice.
+ -- So turn 'for k, v in result' into 'for k, v in ipairs(result)'.
+ __iter = ipairs,
+ -- This result set provides read-only access.
+ -- We do not support pushing updates to individual items back to
+ -- C++; for the intended use cases, that makes no sense.
+ __newindex = function(self, i, value)
+ error("result_view is a read-only data structure", 2)
+ end
+}
+
+-- result_view(key_length, fetch) returns a table which stores only a slice
+-- of a result set plus some control values, yet presents read-only virtual
+-- access to the entire result set.
+-- key_length: {result set key, total result set length}
+-- fetch: function(key, start) that returns (slice, adjusted start)
+local result_view = setmetatable(
+ {
+ -- generic fetch() function
+ fetch = function(key, start)
+ local fetched = leap.request(
+ 'LLInventory',
+ {op='getSlice', result=key, index=start})
+ return fetched.slice, fetched.start
+ end,
+ -- generic close() function accepting variadic result-set keys
+ close = function(...)
+ local keys = table.pack(...)
+ -- table.pack() produces a table with an array entry for every
+ -- parameter, PLUS an 'n' key with the count. Unfortunately that
+ -- 'n' key bollixes our conversion to LLSD, which requires either
+ -- all int keys (for an array) or all string keys (for a map).
+ keys.n = nil
+ leap.send('LLInventory', {op='closeResult', result=keys})
+ end
+ },
+ {
+ -- result_view(key_length, fetch) calls this
+ __call = function(class, key_length, fetch)
+ return setmetatable(
+ {
+ key=key_length[1],
+ length=key_length[2],
+ -- C++ result sets use 0-based indexing, so internally we do too
+ start=0,
+ -- start with a dummy array with length 0
+ slice={},
+ -- if caller didn't pass fetch() function, use generic
+ fetch=fetch or class.fetch,
+ -- returned view:close() will close result set with passed key
+ close=function(self) class.close(key_length[1]) end
+ },
+ -- use our special metatable
+ mt
+ )
+ end
+ }
+)
+
+return result_view