1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-19 22:53:53 +00:00

Don't expose LuaUtil::Callback to lua (!2733 for 0.48)

This commit is contained in:
Petr Mikheev 2023-02-14 09:40:22 +01:00
parent 628017a817
commit 1540c9679f
6 changed files with 50 additions and 28 deletions

View file

@ -109,9 +109,9 @@ namespace MWLua
MWBase::Environment::get().getWorld()->castRenderingRay(res, from, to, false, false);
return res;
};
api["asyncCastRenderingRay"] = [context](const LuaUtil::Callback& callback, const osg::Vec3f& from,
const osg::Vec3f& to) {
context.mLuaManager->addAction([context, callback, from, to] {
api["asyncCastRenderingRay"] = [context](
const sol::table& callback, const osg::Vec3f& from, const osg::Vec3f& to) {
context.mLuaManager->addAction([context, callback = LuaUtil::Callback::fromLua(callback), from, to] {
MWPhysics::RayCastingResult res;
MWBase::Environment::get().getWorld()->castRenderingRay(res, from, to, false, false);
context.mLuaManager->queueCallback(callback, sol::main_object(context.mLua->sol(), sol::in_place, res));

View file

@ -4,7 +4,7 @@
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <components/lua/scriptscontainer.hpp>
#include <components/lua/asyncpackage.hpp>
#include <components/lua/storage.hpp>
namespace
@ -24,17 +24,16 @@ namespace
LuaUtil::LuaStorage storage(mLua);
std::vector<std::string> callbackCalls;
LuaUtil::Callback callback{
sol::make_object(mLua, [&](const std::string& section, const sol::optional<std::string>& key)
{
if (key)
callbackCalls.push_back(section + "_" + *key);
else
callbackCalls.push_back(section + "_*");
}),
sol::table(mLua, sol::create)
sol::table callbackHiddenData(mLua, sol::create);
callbackHiddenData[LuaUtil::ScriptsContainer::sScriptIdKey] = LuaUtil::ScriptsContainer::ScriptId{};
sol::table callback(mLua, sol::create);
callback[1] = [&](const std::string& section, const sol::optional<std::string>& key) {
if (key)
callbackCalls.push_back(section + "_" + *key);
else
callbackCalls.push_back(section + "_*");
};
callback.mHiddenData[LuaUtil::ScriptsContainer::sScriptIdKey] = "fakeId";
callback[2] = LuaUtil::AsyncPackageId{ nullptr, 0, callbackHiddenData };
mLua["mutable"] = storage.getMutableSection("test");
mLua["ro"] = storage.getReadOnlySection("test");

View file

@ -22,6 +22,21 @@ namespace LuaUtil
std::string mName;
};
Callback Callback::fromLua(const sol::table& t)
{
return Callback{ t.raw_get<sol::main_protected_function>(1), t.raw_get<AsyncPackageId>(2).mHiddenData };
}
bool Callback::isLuaCallback(const sol::object& t)
{
if (!t.is<sol::table>())
return false;
sol::object meta = sol::table(t)[sol::metatable_key];
if (!meta.is<sol::table>())
return false;
return sol::table(meta).raw_get_or<bool, std::string_view, bool>("isCallback", false);
}
sol::function getAsyncPackageInitializer(
lua_State* L, std::function<double()> simulationTimeFn, std::function<double()> gameTimeFn)
{
@ -53,13 +68,20 @@ namespace LuaUtil
asyncId.mContainer->setupUnsavableTimer(
TimerType::GAME_TIME, gameTimeFn() + delay, asyncId.mScriptId, std::move(callback));
};
api["callback"] = [](const AsyncPackageId& asyncId, sol::main_protected_function fn) -> Callback {
return Callback{ std::move(fn), asyncId.mHiddenData };
};
sol::usertype<Callback> callbackType = lua.new_usertype<Callback>("Callback");
callbackType[sol::meta_function::call]
= [](const Callback& callback, sol::variadic_args va) { return callback.call(sol::as_args(va)); };
sol::table callbackMeta = sol::table::create(L);
callbackMeta[sol::meta_function::call] = [](const sol::table& callback, sol::variadic_args va) {
return Callback::fromLua(callback).call(sol::as_args(va));
};
callbackMeta[sol::meta_function::to_string] = [] { return "Callback"; };
callbackMeta[sol::meta_function::metatable] = false;
callbackMeta["isCallback"] = true;
api["callback"] = [callbackMeta](const AsyncPackageId& asyncId, sol::main_protected_function fn) -> sol::table {
sol::table c = sol::table::create(fn.lua_state(), 2);
c.raw_set(1, std::move(fn), 2, asyncId);
c[sol::metatable_key] = callbackMeta;
return c;
};
auto initializer = [](sol::table hiddenData) {
ScriptsContainer::ScriptId id = hiddenData[ScriptsContainer::sScriptIdKey];

View file

@ -22,6 +22,9 @@ namespace LuaUtil
sol::main_protected_function mFunc;
sol::table mHiddenData; // same object as Script::mHiddenData in ScriptsContainer
static bool isLuaCallback(const sol::object&);
static Callback fromLua(const sol::table&);
bool isValid() const { return mHiddenData[ScriptsContainer::sScriptIdKey] != sol::nil; }
template <typename... Args>

View file

@ -108,8 +108,7 @@ namespace LuaUtil
return section.mSection->get(key).getCopy(s);
};
sview["asTable"] = [](const SectionView& section) { return section.mSection->asTable(); };
sview["subscribe"] = [](const SectionView& section, const Callback& callback)
{
sview["subscribe"] = [](const SectionView& section, const sol::table& callback) {
std::vector<Callback>& callbacks = section.mSection->mCallbacks;
if (!callbacks.empty() && callbacks.size() == callbacks.capacity())
{
@ -117,7 +116,7 @@ namespace LuaUtil
[&](const Callback& c) { return !c.isValid(); }),
callbacks.end());
}
callbacks.push_back(callback);
callbacks.push_back(Callback::fromLua(callback));
};
sview["reset"] = [](const SectionView& section, const sol::optional<sol::table>& newValues)
{

View file

@ -104,13 +104,12 @@ namespace LuaUi
if (!eventsObj.is<sol::table>())
throw std::logic_error("The \"events\" layout field must be a table of callbacks");
auto events = eventsObj.as<sol::table>();
events.for_each([ext](const sol::object& name, const sol::object& callback)
{
if (name.is<std::string>() && callback.is<LuaUtil::Callback>())
ext->setCallback(name.as<std::string>(), callback.as<LuaUtil::Callback>());
events.for_each([ext](const sol::object& name, const sol::object& callback) {
if (name.is<std::string>() && LuaUtil::Callback::isLuaCallback(callback))
ext->setCallback(name.as<std::string>(), LuaUtil::Callback::fromLua(callback));
else if (!name.is<std::string>())
Log(Debug::Warning) << "UI event key must be a string";
else if (!callback.is<LuaUtil::Callback>())
else
Log(Debug::Warning) << "UI event handler for key \"" << name.as<std::string>()
<< "\" must be an openmw.async.callback";
});