Age | Commit message (Collapse) | Author |
|
This replaces type_tag<T>(), which searched and possibly extended the type_tags
unordered_map at runtime. If we called lua_emplace<T>() from different threads,
that would require locking type_tags.
In contrast, the compiler must instantiate a distinct TypeTag<T> for every
distinct T passed to lua_emplace<T>(), so each gets a distinct value at static
initialization time. No locking is required; no lookup; no allocations.
Add a test to llluamanager_test.cpp to verify that each distinct T passed to
lua_emplace<T>() gets its own TypeTag<T>::value, and that each gets its own
destructor -- but that different lua_emplace<T>() calls with the same T share
the same TypeTag<T>::value and the same destructor.
|
|
|
|
|
|
|
|
Add "userQuit" operation to LLAppViewerListener to engage
LLAppViewer::userQuit(), which pops up "Are you sure?" prompt unless
suppressed.
|
|
|
|
|
|
|
|
|
|
|
|
Use ClassName(ctor args) for classes using util.classctor().
|
|
|
|
|
|
|
|
popup:tip() engages 'SystemMessageTip'.
|
|
|
|
|
|
|
|
|
|
Instead of deriving LuaListener from LLInstanceTracker with an int key,
generating a unique int key and storing that key in the Registry, use new
lua_emplace<LuaState>() to store the LuaListener directly in a Lua userdata
object in the Lua Registry.
Because lua_emplace<T>() uses LL.atexit() to guarantee that ~LuaState will
destroy the T object, we no longer need ~LuaState() to make a special call
specifically to destroy the LuaListener, if any. So we no longer need
LuaState::getListener() separate from obtainListener().
Since LuaListener is no longer an LLInstanceTracker subclass, make
LuaState::obtainListener() return LuaListener& rather than LuaListener::ptr_t.
|
|
Make viewer_manifest.py copy them into the viewer install image.
Make the require() function look for them there.
|
|
|
|
|
|
When the user explicitly types 'return expression[, expression]...' we convert
the result of the expressions to LLSD and format them into the LUA Debug
Console, which serves as a useful acknowledgment.
But until now, if the user neither invoked print() nor ran a 'return'
statement, the LUA Debug Console output remained empty. This could be a little
disconcerting: you click Execute, or press Enter, and apparently nothing
happens. You must either monitor viewer log output, or simply trust that the
Lua snippet ran.
When there are no 'return' results, at least emit 'ok'. But when the user is
entering a series of no-output commands, vary the 'ok' output by appending a
counter: 'ok 1', 'ok 2' etc.
|
|
The special case of a Lua snippet that indirectly invokes the
"LLNotifications" listener can result in a recursive call to
LLFloaterLUADebug's handler methods. Defend against that case.
|
|
stringize() constructs, populates and destroys a std::ostringstream, which is
actually less efficient than directly allocating a std::string big enough for
the result of operator+().
Maybe someday we'll specialize stringize(p0, p1) for the case in which they're
both string-like, and invoke operator+() for that situation...
|
|
The expression (payload or {}) is unnecessary, since that value will be
converted to LLSD -- and both Lua nil and empty table convert to
LLSD::isUndefined().
|
|
|
|
WIP: This is known not to work yet.
|
|
The nullary login() call (login with saved credentials) has been tested, but
the binary login(username, password) call is known not to work yet.
|
|
Add listviews(), viewinfo(), click(), doubleclick(), drag(), keypress() and
type().
WIP: These are ported from Python LEAP equivalents, but the Lua implementation
has only been partially tested.
|
|
The 'startup' table, the module's namespace, must be defined near the top
because its local waitfor:process() override references startup.
The byname table's metatable's __index() function wants to raise an error if
you try to access an undefined entry, but it referenced t[k] to check that,
producing infinite recursion. Use rawget(t, k) instead.
Also use new leap.WaitFor(args) syntax instead of leap.WaitFor:new(args).
|
|
The discussions we've read about Lua classes conventionally use
ClassName:new() as the constructor, and so far we've followed that convention.
But setting metaclass(ClassName).__call = ClassName.new permits Lua to respond
to calls of the form ClassName(ctor args) by implicitly calling
ClassName:new(ctor args).
Introduce util.classctor(). Calling util.classctor(ClassName) sets ClassName's
metaclass's __call to ClassName's constructor method. If the constructor method
is named something other than new(), pass ClassName.method as the second arg.
Use util.classctor() on each of our classes that defines a new() method.
Replace ClassName:new(args) calls with ClassName(args) calls throughout.
|
|
in addition to a list {'name1', 'name2', ...}.
|
|
|
|
|
|
|
|
to pick up Featurettes promotion + Brad's GitHub Windows build workaround.
|
|
|
|
following promotion of secondlife/viewer #648: Release/materials featurette
|
|
|
|
|
|
ScopedRegistrarHelper
|
|
There are two conventions for Lua function calls. You can call a function with
positional arguments as usual:
f(1, 2, 3)
Lua makes it easy to handle omitted positional arguments: their values are nil.
But as in C++, positional arguments get harder to read when there are many, or
when you want to omit arguments other than the last ones.
Alternatively, using Lua syntactic sugar, you can pass a single argument which
is a table containing the desired function arguments. For this you can use
table constructor syntax to effect keyword arguments:
f{a=1, b=2, c=3}
A call passing keyword arguments is more readable because you explicitly
associate the parameter name with each argument value. Moreover, it gracefully
handles the case of multiple optional arguments. The reader need not be
concerned about parameters *not* being passed.
Now you're coding a Lua module with a number of functions. Some have numerous
or complicated arguments; some do not. For simplicity, you code the simple
functions to accept positional arguments, the more complicated functions to
accept the single-table argument style.
But how the bleep is a consumer of your module supposed to remember which
calling style to use for a given function?
mapargs() blurs the distinction, accepting either style. Coding a function
like this (where '...' is literal code, not documentation ellipsis):
function f(...)
local args = mapargs({'a', 'b', 'c'}, ...)
-- now use args.a, args.b, args.c
end
supports calls like:
f(1, 2, 3)
f{1, 2, 3}
f{c=3, a=1, b=2}
f{1, 2, c=3}
f{c=3, 1, 2} -- unlike Python!
In every call above, args.a == 1, args.b == 2, args.c == 3.
Moreover, omitting arguments (or explicitly passing nil, positionally or by
keyword) works correctly.
test_mapargs.lua exercises these cases.
|
|
Co-authored-by: Dave Parks <davep@lindenlab.com>
|
|
|
|
|
|
so the user need not reverse-engineer the code to figure out the output.
|
|
|
|
Since timers presents a timers.Timer Lua class supporting queries and
cancellation, make TimersListener::scheduleAfter() and scheduleEvery() respond
immediately so the newly constructed Timer object has the reqid necessary to
perform those subsequent operations.
This requires that Lua invocations of these operations avoid calling the
caller's callback with that initial response.
Reinvent leap.generate() to return a Lua object supporting next() and done()
methods. A plain Lua coroutine that (indirectly) calls fiber.wait() confuses
the fiber scheduler, so avoid implementing generate() as a Lua coroutine.
Add a bit more leap.lua diagnostic output.
|