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:
Kyzentun
2014-06-26 21:33:54 -06:00
parent 0b7ca07576
commit 27c6a54d82
9 changed files with 204 additions and 1 deletions
+126
View File
@@ -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 );
}
};