Added the OnClosing callback to cLuaWindow API
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1534 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
b58f0cabad
commit
2eb1240e14
@ -580,8 +580,17 @@ function HandleTestWndCmd(a_Split, a_Player)
|
||||
return true;
|
||||
end
|
||||
|
||||
-- Test out the OnClosing callback's ability to refuse to close the window
|
||||
local attempt = 1;
|
||||
local OnClosing = function(Window, Player)
|
||||
Player:SendMessage("Window closing attempt #" .. attempt);
|
||||
attempt = attempt + 1;
|
||||
return (attempt <= 3); -- refuse twice, then allow
|
||||
end
|
||||
|
||||
local Window = cLuaWindow(WindowType, WindowSizeX, WindowSizeY, "TestWnd");
|
||||
Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64));
|
||||
Window:SetOnClosing(OnClosing);
|
||||
|
||||
a_Player:OpenWindow(Window);
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "LuaWindow.h"
|
||||
#include "UI/SlotArea.h"
|
||||
#include "Plugin_NewLua.h"
|
||||
#include "Player.h"
|
||||
#include "lauxlib.h" // Needed for LUA_REFNIL
|
||||
|
||||
|
||||
@ -20,7 +21,9 @@ cLuaWindow::cLuaWindow(cWindow::WindowType a_WindowType, int a_SlotsX, int a_Slo
|
||||
super(a_WindowType, a_Title),
|
||||
m_Contents(a_SlotsX, a_SlotsY),
|
||||
m_Plugin(NULL),
|
||||
m_LuaRef(LUA_REFNIL)
|
||||
m_LuaRef(LUA_REFNIL),
|
||||
m_OnClosingFnRef(LUA_REFNIL),
|
||||
m_OnSlotChangedFnRef(LUA_REFNIL)
|
||||
{
|
||||
m_SlotAreas.push_back(new cSlotAreaItemGrid(m_Contents, *this));
|
||||
|
||||
@ -53,7 +56,8 @@ cLuaWindow::~cLuaWindow()
|
||||
|
||||
void cLuaWindow::SetLuaRef(cPlugin_NewLua * a_Plugin, int a_LuaRef)
|
||||
{
|
||||
ASSERT(m_Plugin == NULL);
|
||||
// Either m_Plugin is not set or equal to the passed plugin; only one plugin can use one cLuaWindow object
|
||||
ASSERT((m_Plugin == NULL) || (m_Plugin == a_Plugin));
|
||||
ASSERT(m_LuaRef == LUA_REFNIL);
|
||||
m_Plugin = a_Plugin;
|
||||
m_LuaRef = a_LuaRef;
|
||||
@ -72,6 +76,46 @@ bool cLuaWindow::IsLuaReferenced(void) const
|
||||
|
||||
|
||||
|
||||
void cLuaWindow::SetOnClosing(cPlugin_NewLua * a_Plugin, int a_FnRef)
|
||||
{
|
||||
// Either m_Plugin is not set or equal to the passed plugin; only one plugin can use one cLuaWindow object
|
||||
ASSERT((m_Plugin == NULL) || (m_Plugin == a_Plugin));
|
||||
|
||||
// If there already was a function, unreference it first
|
||||
if (m_OnClosingFnRef != LUA_REFNIL)
|
||||
{
|
||||
m_Plugin->Unreference(m_OnClosingFnRef);
|
||||
}
|
||||
|
||||
// Store the new reference
|
||||
m_Plugin = a_Plugin;
|
||||
m_OnClosingFnRef = a_FnRef;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cLuaWindow::ClosedByPlayer(cPlayer & a_Player)
|
||||
{
|
||||
// First notify the plugin through the registered callback:
|
||||
if (m_OnClosingFnRef != LUA_REFNIL)
|
||||
{
|
||||
ASSERT(m_Plugin != NULL);
|
||||
if (m_Plugin->CallbackWindowClosing(m_OnClosingFnRef, *this, a_Player))
|
||||
{
|
||||
// The callback disagrees
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return super::ClosedByPlayer(a_Player);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cLuaWindow::Destroy(void)
|
||||
{
|
||||
super::Destroy();
|
||||
|
@ -58,6 +58,12 @@ public:
|
||||
/// Returns true if SetLuaRef() has been called
|
||||
bool IsLuaReferenced(void) const;
|
||||
|
||||
/// Sets the callback function (Lua reference) to call when the window is about to close
|
||||
void SetOnClosing(cPlugin_NewLua * a_Plugin, int a_FnRef);
|
||||
|
||||
/// Sets the callback function (Lua reference) to call when a slot is changed
|
||||
void SetOnSlotChanged(cPlugin_NewLua * a_Plugin, int a_FnRef);
|
||||
|
||||
protected:
|
||||
/// Contents of the non-inventory part
|
||||
cItemGrid m_Contents;
|
||||
@ -68,7 +74,14 @@ protected:
|
||||
/// The Lua object reference, used for keeping the object alive as long as any player has the window open
|
||||
int m_LuaRef;
|
||||
|
||||
/// The Lua reference for the callback to call when the window is closing for any player
|
||||
int m_OnClosingFnRef;
|
||||
|
||||
/// The Lua reference for the callback to call when a slot has changed
|
||||
int m_OnSlotChangedFnRef;
|
||||
|
||||
// cWindow overrides:
|
||||
virtual bool ClosedByPlayer(cPlayer & a_Player) override;
|
||||
virtual void Destroy(void) override;
|
||||
} ; // tolua_export
|
||||
|
||||
|
@ -938,6 +938,41 @@ static int tolua_cPlayer_OpenWindow(lua_State * tolua_S)
|
||||
|
||||
|
||||
|
||||
static int tolua_cLuaWindow_SetOnClosing(lua_State * tolua_S)
|
||||
{
|
||||
// Function signature: cPlayer:SetOnClosing(CallbackFunction)
|
||||
|
||||
// Retrieve the plugin instance from the Lua state
|
||||
cPlugin_NewLua * Plugin = GetLuaPlugin(tolua_S);
|
||||
if (Plugin == NULL)
|
||||
{
|
||||
// Warning message has already been printed by GetLuaPlugin(), bail out silently
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the parameters:
|
||||
cLuaWindow * self = (cLuaWindow *)tolua_tousertype(tolua_S, 1, NULL);
|
||||
if (self == NULL)
|
||||
{
|
||||
LOGWARNING("%s: invalid self (%p)", __FUNCTION__, self);
|
||||
return 0;
|
||||
}
|
||||
int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); // Store function reference
|
||||
if (FnRef == LUA_REFNIL)
|
||||
{
|
||||
LOGERROR("%s: Cannot create a function reference. Callback not set.", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set the callback
|
||||
self->SetOnClosing(Plugin, FnRef);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int tolua_cPlugin_NewLua_AddWebTab(lua_State * tolua_S)
|
||||
{
|
||||
cPlugin_NewLua * self = (cPlugin_NewLua*)tolua_tousertype(tolua_S,1,0);
|
||||
@ -1265,6 +1300,10 @@ void ManualBindings::Bind( lua_State* tolua_S )
|
||||
tolua_function(tolua_S, "OpenWindow", tolua_cPlayer_OpenWindow);
|
||||
tolua_endmodule(tolua_S);
|
||||
|
||||
tolua_beginmodule(tolua_S, "cLuaWindow");
|
||||
tolua_function(tolua_S, "SetOnClosing", tolua_cLuaWindow_SetOnClosing);
|
||||
tolua_endmodule(tolua_S);
|
||||
|
||||
tolua_beginmodule(tolua_S, "cPlugin_NewLua");
|
||||
tolua_function(tolua_S, "AddWebTab", tolua_cPlugin_NewLua_AddWebTab);
|
||||
tolua_function(tolua_S, "AddTab", tolua_cPlugin_NewLua_AddTab);
|
||||
|
@ -435,7 +435,10 @@ Vector3d cPlayer::GetEyePosition()
|
||||
|
||||
void cPlayer::OpenWindow(cWindow * a_Window)
|
||||
{
|
||||
CloseWindow();
|
||||
if (a_Window != m_CurrentWindow)
|
||||
{
|
||||
CloseWindow();
|
||||
}
|
||||
a_Window->OpenedByPlayer(*this);
|
||||
m_CurrentWindow = a_Window;
|
||||
a_Window->SendWholeWindow(*GetClientHandle());
|
||||
@ -453,8 +456,17 @@ void cPlayer::CloseWindow(void)
|
||||
return;
|
||||
}
|
||||
|
||||
m_CurrentWindow->ClosedByPlayer(*this);
|
||||
m_CurrentWindow = m_InventoryWindow;
|
||||
if (m_CurrentWindow->ClosedByPlayer(*this))
|
||||
{
|
||||
// Close accepted, go back to inventory window (the default):
|
||||
m_CurrentWindow = m_InventoryWindow;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Re-open the window
|
||||
m_CurrentWindow->OpenedByPlayer(*this);
|
||||
m_CurrentWindow->SendWholeWindow(*GetClientHandle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -467,8 +479,7 @@ void cPlayer::CloseWindowIfID(char a_WindowID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_CurrentWindow->ClosedByPlayer(*this);
|
||||
m_CurrentWindow = m_InventoryWindow;
|
||||
CloseWindow();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1665,6 +1665,30 @@ void cPlugin_NewLua::Unreference(int a_LuaRef)
|
||||
|
||||
|
||||
|
||||
bool cPlugin_NewLua::CallbackWindowClosing(int a_FnRef, cWindow & a_Window, cPlayer & a_Player)
|
||||
{
|
||||
cCSLock Lock(m_CriticalSection);
|
||||
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // Push the function to be called
|
||||
tolua_pushusertype(m_LuaState, &a_Window, "cWindow");
|
||||
tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
|
||||
|
||||
// Call function:
|
||||
int s = lua_pcall(m_LuaState, 2, 1, 0);
|
||||
if (report_errors(m_LuaState, s))
|
||||
{
|
||||
LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bRetVal = (tolua_toboolean(m_LuaState, -1, false) > 0);
|
||||
lua_pop(m_LuaState, 1);
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Helper functions
|
||||
bool cPlugin_NewLua::PushFunction(const char * a_FunctionName, bool a_bLogError /* = true */)
|
||||
{
|
||||
|
@ -11,8 +11,12 @@
|
||||
|
||||
|
||||
|
||||
// fwd: Lua
|
||||
typedef struct lua_State lua_State;
|
||||
|
||||
// fwd: UI/Window.h
|
||||
class cWindow;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -101,6 +105,9 @@ public:
|
||||
/// Removes a previously referenced object (luaL_unref())
|
||||
void Unreference(int a_LuaRef);
|
||||
|
||||
/// Calls the plugin-specified "cLuaWindow closing" callback. Returns true only if the callback returned true
|
||||
bool CallbackWindowClosing(int a_FnRef, cWindow & a_Window, cPlayer & a_Player);
|
||||
|
||||
protected:
|
||||
cCriticalSection m_CriticalSection;
|
||||
lua_State * m_LuaState;
|
||||
|
@ -251,7 +251,7 @@ void cWindow::OpenedByPlayer(cPlayer & a_Player)
|
||||
|
||||
|
||||
|
||||
void cWindow::ClosedByPlayer(cPlayer & a_Player)
|
||||
bool cWindow::ClosedByPlayer(cPlayer & a_Player)
|
||||
{
|
||||
// Checks whether the player is still holding an item
|
||||
if (a_Player.IsDraggingItem())
|
||||
@ -285,6 +285,8 @@ void cWindow::ClosedByPlayer(cPlayer & a_Player)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,7 +106,9 @@ public:
|
||||
);
|
||||
|
||||
void OpenedByPlayer(cPlayer & a_Player);
|
||||
void ClosedByPlayer(cPlayer & a_Player);
|
||||
|
||||
/// Called when a player closes this window; notifies all slot areas. Returns true if close accepted
|
||||
virtual bool ClosedByPlayer(cPlayer & a_Player);
|
||||
|
||||
void SendWholeWindow(cClientHandle & a_Client);
|
||||
void BroadcastWholeWindow(void);
|
||||
|
Loading…
Reference in New Issue
Block a user