From d16fa553c8eab3f044255886ba952bca4ea6ac7a Mon Sep 17 00:00:00 2001
From: Petr Mikheev <ptmikheev@gmail.com>
Date: Sun, 15 May 2022 21:30:08 +0200
Subject: [PATCH] Fix LuaUtil::Callback

---
 apps/openmw/mwlua/asyncbindings.cpp                  | 9 ++++++++-
 apps/openmw/mwlua/luamanagerimp.cpp                  | 2 +-
 apps/openmw_test_suite/lua/test_scriptscontainer.cpp | 6 +++---
 components/lua/scriptscontainer.hpp                  | 4 ++--
 components/lua_ui/widget.cpp                         | 2 +-
 components/lua_ui/widget.hpp                         | 2 +-
 6 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/apps/openmw/mwlua/asyncbindings.cpp b/apps/openmw/mwlua/asyncbindings.cpp
index 0ffb2aad8f..d70e9bfea5 100644
--- a/apps/openmw/mwlua/asyncbindings.cpp
+++ b/apps/openmw/mwlua/asyncbindings.cpp
@@ -6,6 +6,9 @@ namespace sol
 {
     template <>
     struct is_automagical<MWLua::AsyncPackageId> : std::false_type {};
+
+    template <>
+    struct is_automagical<LuaUtil::Callback> : std::false_type {};
 }
 
 namespace MWLua
@@ -50,11 +53,15 @@ namespace MWLua
             asyncId.mContainer->setupUnsavableTimer(
                 TimerType::GAME_TIME, world->getGameTime() + delay, asyncId.mScriptId, std::move(callback));
         };
-        api["callback"] = [](const AsyncPackageId& asyncId, sol::function fn)
+        api["callback"] = [](const AsyncPackageId& asyncId, sol::function fn) -> LuaUtil::Callback
         {
             return LuaUtil::Callback{std::move(fn), asyncId.mHiddenData};
         };
 
+        sol::usertype<LuaUtil::Callback> callbackType = context.mLua->sol().new_usertype<LuaUtil::Callback>("Callback");
+        callbackType[sol::meta_function::call] =
+            [](const LuaUtil::Callback& callback, sol::variadic_args va) { return callback.call(sol::as_args(va)); };
+
         auto initializer = [](sol::table hiddenData)
         {
             LuaUtil::ScriptsContainer::ScriptId id = hiddenData[LuaUtil::ScriptsContainer::sScriptIdKey];
diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp
index 3c458bd7b8..c747d69ab4 100644
--- a/apps/openmw/mwlua/luamanagerimp.cpp
+++ b/apps/openmw/mwlua/luamanagerimp.cpp
@@ -169,7 +169,7 @@ namespace MWLua
 
         // Run queued callbacks
         for (CallbackWithData& c : mQueuedCallbacks)
-            c.mCallback(c.mArg);
+            c.mCallback.call(c.mArg);
         mQueuedCallbacks.clear();
 
         // Engine handlers in local scripts
diff --git a/apps/openmw_test_suite/lua/test_scriptscontainer.cpp b/apps/openmw_test_suite/lua/test_scriptscontainer.cpp
index 779debb4e6..900888929d 100644
--- a/apps/openmw_test_suite/lua/test_scriptscontainer.cpp
+++ b/apps/openmw_test_suite/lua/test_scriptscontainer.cpp
@@ -447,16 +447,16 @@ return {
         callback.mHiddenData[LuaUtil::ScriptsContainer::sScriptIdKey] = LuaUtil::ScriptsContainer::ScriptId{nullptr, 0};
 
         testing::internal::CaptureStdout();
-        callback(1.5);
+        callback.call(1.5);
         EXPECT_EQ(internal::GetCapturedStdout(), "1.5\n");
 
         testing::internal::CaptureStdout();
-        callback(1.5, 2.5);
+        callback.call(1.5, 2.5);
         EXPECT_EQ(internal::GetCapturedStdout(), "1.5\t2.5\n");
 
         testing::internal::CaptureStdout();
         callback.mHiddenData[LuaUtil::ScriptsContainer::sScriptIdKey] = sol::nil;
-        callback(1.5, 2.5);
+        callback.call(1.5, 2.5);
         EXPECT_EQ(internal::GetCapturedStdout(), "Ignored callback to the removed script some_script.lua\n");
     }
 
diff --git a/components/lua/scriptscontainer.hpp b/components/lua/scriptscontainer.hpp
index e065c487c4..f64ec97722 100644
--- a/components/lua/scriptscontainer.hpp
+++ b/components/lua/scriptscontainer.hpp
@@ -252,7 +252,7 @@ namespace LuaUtil
         bool isValid() const { return mHiddenData[ScriptsContainer::sScriptIdKey] != sol::nil; }
 
         template <typename... Args>
-        sol::object operator()(Args&&... args) const
+        sol::object call(Args&&... args) const
         {
             if (isValid())
                 return LuaUtil::call(mFunc, std::forward<Args>(args)...);
@@ -265,7 +265,7 @@ namespace LuaUtil
         template <typename... Args>
         void tryCall(Args&&... args) const
         {
-            try { (*this)(std::forward<Args>(args)...); }
+            try { this->call(std::forward<Args>(args)...); }
             catch (std::exception& e)
             {
                 Log(Debug::Error) << "Error in callback: " << e.what();
diff --git a/components/lua_ui/widget.cpp b/components/lua_ui/widget.cpp
index 49d69f8fd1..c98b7ad38f 100644
--- a/components/lua_ui/widget.cpp
+++ b/components/lua_ui/widget.cpp
@@ -340,7 +340,7 @@ namespace LuaUi
     {
         auto it = mCallbacks.find(name);
         if (it != mCallbacks.end())
-            it->second(argument, mLayout);
+            it->second.call(argument, mLayout);
     }
 
     void WidgetExtension::keyPress(MyGUI::Widget*, MyGUI::KeyCode code, MyGUI::Char ch)
diff --git a/components/lua_ui/widget.hpp b/components/lua_ui/widget.hpp
index b6bef55235..3285f629ac 100644
--- a/components/lua_ui/widget.hpp
+++ b/components/lua_ui/widget.hpp
@@ -111,7 +111,7 @@ namespace LuaUi
                 auto it = w->mCallbacks.find(name);
                 if (it != w->mCallbacks.end())
                 {
-                    sol::object res = it->second(argumentFactory(w), w->mLayout);
+                    sol::object res = it->second.call(argumentFactory(w), w->mLayout);
                     shouldPropagate = res.is<bool>() && res.as<bool>();
                 }
                 if (w->mParent && w->mPropagateEvents && shouldPropagate)