Added AddInputCallback and RemoveInputCallback to Lua API for screen. ScreenManager now passes input to the lua side of each screen in addition to the engine side.
This commit is contained in:
+126
@@ -7,6 +7,7 @@
|
||||
#include "ScreenManager.h"
|
||||
#include "ActorUtil.h"
|
||||
#include "InputEventPlus.h"
|
||||
#include "InputMapper.h"
|
||||
|
||||
#define NEXT_SCREEN THEME->GetMetric (m_sName,"NextScreen")
|
||||
#define PREV_SCREEN THEME->GetMetric (m_sName,"PrevScreen")
|
||||
@@ -54,6 +55,8 @@ void Screen::Init()
|
||||
m_smSendOnPop = SM_None;
|
||||
m_bRunning = false;
|
||||
|
||||
m_CallingInputCallbacks= false;
|
||||
|
||||
ActorUtil::LoadAllCommandsFromName( *this, m_sName, "Screen" );
|
||||
|
||||
PlayCommandNoRecurse( Message("Init") );
|
||||
@@ -284,6 +287,107 @@ void Screen::ClearMessageQueue( const ScreenMessage SM )
|
||||
m_QueuedMessages.erase( m_QueuedMessages.begin()+i );
|
||||
}
|
||||
|
||||
bool Screen::PassInputToLua(const InputEventPlus& input)
|
||||
{
|
||||
if(m_InputCallbacks.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_CallingInputCallbacks= true;
|
||||
bool handled= false;
|
||||
Lua* L= LUA->Get();
|
||||
|
||||
// Construct the table once, and reuse it.
|
||||
lua_createtable(L, 0, 7);
|
||||
{ // This block is meant to improve clarity. A subtable is created for
|
||||
// storing the DeviceInput member.
|
||||
lua_createtable(L, 0, 8);
|
||||
Enum::Push(L, input.DeviceI.device);
|
||||
lua_setfield(L, -2, "device");
|
||||
Enum::Push(L, input.DeviceI.button);
|
||||
lua_setfield(L, -2, "button");
|
||||
lua_pushnumber(L, input.DeviceI.level);
|
||||
lua_setfield(L, -2, "level");
|
||||
lua_pushinteger(L, input.DeviceI.z);
|
||||
lua_setfield(L, -2, "z");
|
||||
lua_pushboolean(L, input.DeviceI.bDown);
|
||||
lua_setfield(L, -2, "down");
|
||||
lua_pushnumber(L, input.DeviceI.ts.Ago());
|
||||
lua_setfield(L, -2, "ago");
|
||||
lua_pushboolean(L, input.DeviceI.IsJoystick());
|
||||
lua_setfield(L, -2, "is_joystick");
|
||||
lua_pushboolean(L, input.DeviceI.IsMouse());
|
||||
lua_setfield(L, -2, "is_mouse");
|
||||
}
|
||||
lua_setfield(L, -2, "DeviceInput");
|
||||
Enum::Push(L, input.GameI.controller);
|
||||
lua_setfield(L, -2, "controller");
|
||||
LuaHelpers::Push(L, GameButtonToString(INPUTMAPPER->GetInputScheme(), input.GameI.button));
|
||||
lua_setfield(L, -2, "button");
|
||||
Enum::Push(L, input.type);
|
||||
lua_setfield(L, -2, "type");
|
||||
LuaHelpers::Push(L, GameButtonToString(INPUTMAPPER->GetInputScheme(), input.MenuI));
|
||||
lua_setfield(L, -2, "GameButton");
|
||||
Enum::Push(L, input.pn);
|
||||
lua_setfield(L, -2, "PlayerNumber");
|
||||
Enum::Push(L, input.mp);
|
||||
lua_setfield(L, -2, "MultiPlayer");
|
||||
for(map<callback_key_t, LuaReference>::iterator callback= m_InputCallbacks.begin();
|
||||
callback != m_InputCallbacks.end() && !handled; ++callback)
|
||||
{
|
||||
callback->second.PushSelf(L);
|
||||
lua_pushvalue(L, -2);
|
||||
RString error;
|
||||
if(!LuaHelpers::RunScriptOnStack(L, error, 1, 1))
|
||||
{
|
||||
LOG->Warn("Error running input callback: %s", error.c_str());
|
||||
}
|
||||
handled= lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
LUA->Release(L);
|
||||
m_CallingInputCallbacks= false;
|
||||
if(!m_DelayedCallbackRemovals.empty())
|
||||
{
|
||||
for(vector<callback_key_t>::iterator key= m_DelayedCallbackRemovals.begin();
|
||||
key != m_DelayedCallbackRemovals.end(); ++key)
|
||||
{
|
||||
InternalRemoveCallback(*key);
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
void Screen::AddInputCallbackFromStack(lua_State* L)
|
||||
{
|
||||
callback_key_t key= lua_topointer(L, -1);
|
||||
m_InputCallbacks[key]= LuaReference(L);
|
||||
}
|
||||
|
||||
void Screen::RemoveInputCallback(lua_State* L)
|
||||
{
|
||||
callback_key_t key= lua_topointer(L, -1);
|
||||
if(m_CallingInputCallbacks)
|
||||
{
|
||||
m_DelayedCallbackRemovals.push_back(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalRemoveCallback(key);
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::InternalRemoveCallback(callback_key_t key)
|
||||
{
|
||||
map<callback_key_t, LuaReference>::iterator iter= m_InputCallbacks.find(key);
|
||||
if(iter != m_InputCallbacks.end())
|
||||
{
|
||||
m_InputCallbacks.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
@@ -304,6 +408,26 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AddInputCallback(T* p, lua_State* L)
|
||||
{
|
||||
if(!lua_isfunction(L, -1))
|
||||
{
|
||||
luaL_error(L, "Input callback must be a function.");
|
||||
}
|
||||
p->AddInputCallbackFromStack(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int RemoveInputCallback(T* p, lua_State* L)
|
||||
{
|
||||
if(!lua_isfunction(L, -1))
|
||||
{
|
||||
luaL_error(L, "Input callback must be a function.");
|
||||
}
|
||||
p->RemoveInputCallback(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LunaScreen()
|
||||
{
|
||||
ADD_METHOD( GetNextScreenName );
|
||||
@@ -311,6 +435,8 @@ public:
|
||||
ADD_METHOD( PostScreenMessage );
|
||||
ADD_METHOD( lockinput );
|
||||
ADD_METHOD( GetScreenType );
|
||||
ADD_METHOD( AddInputCallback );
|
||||
ADD_METHOD( RemoveInputCallback );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user