Age | Commit message (Collapse) | Author |
|
|
|
Add LuaAutorunPath, LuaCommandPath and LuaRequirePath settings.
|
|
|
|
Passing std::string::c_str() to a (const std::string&) function parameter is
worse than clutter, it's pointless overhead: it forces the compiler to
construct a new std::string instance, instead of passing a const reference to
the one you already have in hand.
|
|
|
|
Remove LL_TEST special case from require() code (to search in the viewer's
source tree). Instead, make llluamanager_test.cpp append to LuaRequirePath to
get the same effect.
|
|
|
|
Streamline and robustify lua_emplace<T>() object cleanup.
|
|
|
|
outfit items
|
|
Remove AutorunLuaScriptFile and the LLLUAmanager::runScriptOnLogin() method
that checked it.
Instead, iterate over LuaAutorunPath directories at viewer startup, iterate
over *.lua files in each and implicitly run those.
LuaCommandPath and LuaRequirePath are not yet implemented.
|
|
|
|
This is redundant (but harmless) on a Posix system, but it fills a missing
puzzle piece on Windows. The point of fsyspath is to be able to interchange
freely between fsyspath and std::string. Existing fsyspath could be
constructed and assigned from std::string, and we could explicitly call its
string() method to get a std::string, but an implicit fsyspath-to-string
conversion that worked on Posix would trip us up on Windows. Fix that.
|
|
|
|
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.
|
|
It turns out that Luau does not honor PUC-Rio Lua's __gc metafunction, so
despite elaborate measures, the previous lua_emplace<T>() implementation would
not have destroyed the contained C++ T object when the resulting userdata
object was garbage-collected.
Moreover, using LL.atexit() as the mechanism to destroy lua_emplace<T>()
userdata objects (e.g. LuaListener) would have been slightly fragile because
we also want to use LL.atexit() to make the final fiber.run() call, when
appropriate. Introducing an order dependency between fiber.run() and the
LuaListener destructor would not be robust.
Both of those problems are addressed by leveraging one of Luau's extensions
over PUC-Rio Lua. A Luau userdata object can have an int tag; and a tag can
have an associated C++ destructor function. When any userdata object bearing
that tag is garbage-collected, Luau will call that destructor; and Luau's
lua_close() function destroys all userdata objects.
The resulting lua_emplace<T>() and lua_toclass<T>() code is far simpler.
It only remains to generate a distinct int tag value for each different C++
type passed to the lua_emplace<T>() template.
unordered_map<std::type_index, int> addresses that need.
|
|
Setting LOGTEST=DEBUG, when many unit/integration tests must be rebuilt and
run, can result in lots of unnecessary output. When we only want DEBUG log
output from a specific test program, make test.cpp recognize an environment
variable LOGTEST_testname, where 'testname' might be the full basename of the
executable, or part of INTEGRATION_TEST_testname or PROJECT_foo_TEST_testname.
When test.cpp notices a non-empty variable by that name, it behaves as if
LOGTEST were set to that value.
|
|
|
|
|
|
UI-related Lua API work
|
|
|
|
|
|
|
|
Add "userQuit" operation to LLAppViewerListener to engage
LLAppViewer::userQuit(), which pops up "Are you sure?" prompt unless
suppressed.
|
|
|
|
|
|
|
|
|
|
|
|
Add nearby chat listener
|
|
|
|
Use ClassName(ctor args) for classes using util.classctor().
|
|
|
|
Add demo script with idle and notification interactions
|
|
|
|
|
|
popup:tip() engages 'SystemMessageTip'.
|
|
|
|
|
|
The help string for each lua_function() must restate the function name and its
arguments. The help string is all that's shown; unless it restates the
function name, LL.help() output lists terse explanations for functions whose
names are not shown.
Make help() prepend "LL." to help output, because these functions must be
accessed via the "builtin" LL table instead of directly populating the global
Lua namespace.
Similarly, before string name lookup, remove "LL." prefix if specified.
|
|
|
|
|
|
On Mac it doesn't seem to matter, but on Windows, leaving it uninitialized can
produce garbage results and even crash the coroutine. This seems strange,
since we've been assuming lua_getinfo() treats its lua_Debug* as output-only.
|
|
We might decide to leave some of them in place.
|
|
|
|
Instead, make fiber.lua call LL.atexit(fiber.run) to schedule that final run()
call at ~LuaState() time using the generic mechanism.
Append an explicit fiber.run() call to a specific test in llluamanager_test.cpp
because the test code wants to interact with multiple Lua fibers *before* we
destroy the LuaState.
|
|
so cleanup happens in reverse order, as is conventional.
Streamline LL.atexit() function: luaL_newmetatable() performs all the
find-or-create named Registry table logic.
|
|
lua_emplace<T>() was passing LL.atexit() a closure binding the new userdata
with a cleanup function. The trouble with that was that a strong reference to
the new userdata would prevent it ever being garbage collected, even if that
was the only remaining reference.
Instead, create a new weak table referencing the userdata, and bind that into
the cleanup function's closure. Then if the only remaining reference to the
userdata is from the weak table, the userdata can be collected.
Make lua_emplace_call_gc<T>() check the bound weak table in case the userdata
has in fact been collected.
Also, in lua_toclass<T>(), use luaL_checkudata() to synopsize comparing the
putative userdata's metatable against the one synthesized by lua_emplace<T>().
This saves several explicit steps.
|
|
source_path() previously reported the path of the module containing the
current (lowest-level) Lua function. The effect was that the Floater.lua
module would always try to look up the XUI file relative to
scripts/lua/require.
It makes more intuitive sense to make source_path() return the path containing
the top-level script, so that a script engaging the Floater.lua module looks
for the XUI file relative to the script.
|
|
|