| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- //========================================================================
- // ScriptExports.cpp
- //
- // Part of the GameCode4 Application
- //
- // GameCode4 is the sample application that encapsulates much of the source code
- // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David
- // "Rez" Graham, published by Charles River Media.
- // ISBN-10: 1133776574 | ISBN-13: 978-1133776574
- //
- // If this source code has found it's way to you, and you think it has helped you
- // in any way, do the authors a favor and buy a new copy of the book - there are
- // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com
- // by clicking here:
- // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller=
- //
- // There's a companion web site at http://www.mcshaffry.com/GameCode/
- //
- // The source code is managed and maintained through Google Code:
- // http://code.google.com/p/gamecode4/
- //
- // (c) Copyright 2012 Michael L. McShaffry and David Graham
- //
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the GNU Lesser GPL v3
- // as published by the Free Software Foundation.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- // http://www.gnu.org/licenses/lgpl-3.0.txt for more details.
- //
- // You should have received a copy of the GNU Lesser GPL v3
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- //
- //========================================================================
- #include "../Unix/GameCodeStd.h"
- #include "../ResourceCache/ResCache.h"
- #include "ScriptExports.h"
- #include "LuaStateManager.h"
- #include "../EventManager/Events.h"
- #include <sol/sol.hpp>
- #include <set>
- //---------------------------------------------------------------------------------------------------------------------
- // This is the C++ listener proxy for script event listeners. It pairs a single event type with a Lua callback
- // function. Note that this event can be defined in C++ or Lua. It may also be sent from C++ or Lua.
- //
- // The Lua callback function should take in a table with the event data. The return value is ignored.
- // function Callback(eventData)
- //
- // Chapter 12, page 384
- //---------------------------------------------------------------------------------------------------------------------
- class ScriptEventListener
- {
- EventType m_eventType;
- sol::protected_function m_scriptCallbackFunction;
- public:
- explicit ScriptEventListener(const EventType& eventType, const sol::function scriptCallbackFunction);
- ~ScriptEventListener(void);
- EventListenerDelegate GetDelegate(void) { return MakeDelegate(this, &ScriptEventListener::ScriptEventDelegate); }
- void ScriptEventDelegate(IEventDataPtr pEventPtr);
- };
- //---------------------------------------------------------------------------------------------------------------------
- // This class manages the C++ ScriptListener objects needed for script event listeners.
- // Chapter 12, page 385
- //---------------------------------------------------------------------------------------------------------------------
- class ScriptEventListenerMgr
- {
- typedef std::set<ScriptEventListener*> ScriptEventListenerSet;
- ScriptEventListenerSet m_listeners;
- public:
- ~ScriptEventListenerMgr(void);
- void AddListener(ScriptEventListener* pListener);
- void DestroyListener(ScriptEventListener* pListener);
- };
- //---------------------------------------------------------------------------------------------------------------------
- // Prototypes for the functions to export. - Chapter 12, page 368
- //---------------------------------------------------------------------------------------------------------------------
- class InternalScriptExports
- {
- static ScriptEventListenerMgr* s_pScriptEventListenerMgr;
-
- public:
- static bool Init(void);
- static void Destroy(void);
- // resource loading
- static bool LoadAndExecuteScriptResource(const char* scriptResource);
- // event system
- static unsigned long RegisterEventListener(EventType eventType, sol::function callbackFunction);
- static bool QueueEvent(EventType eventType, sol::object eventData);
- // misc
- static void LuaLog(sol::object text);
- private:
- static std::shared_ptr<ScriptEvent> BuildEvent(EventType eventType, sol::object& eventData);
- };
- ScriptEventListenerMgr* InternalScriptExports::s_pScriptEventListenerMgr = NULL;
- //---------------------------------------------------------------------------------------------------------------------
- // Destructor
- //---------------------------------------------------------------------------------------------------------------------
- ScriptEventListenerMgr::~ScriptEventListenerMgr(void)
- {
- for (auto it = m_listeners.begin(); it != m_listeners.end(); ++it)
- {
- ScriptEventListener* pListener = (*it);
- delete pListener;
- }
- m_listeners.clear();
- }
- //---------------------------------------------------------------------------------------------------------------------
- // Adds a new listener
- //---------------------------------------------------------------------------------------------------------------------
- void ScriptEventListenerMgr::AddListener(ScriptEventListener* pListener)
- {
- m_listeners.insert(pListener);
- }
- //---------------------------------------------------------------------------------------------------------------------
- // Event Listener
- //---------------------------------------------------------------------------------------------------------------------
- ScriptEventListener::ScriptEventListener(const EventType& eventType, const sol::function scriptCallbackFunction)
- : m_scriptCallbackFunction(scriptCallbackFunction)
- {
- m_eventType = eventType;
- }
- ScriptEventListener::~ScriptEventListener(void)
- {
- IEventManager* pEventMgr = IEventManager::Get();
- if (pEventMgr)
- pEventMgr->VRemoveListener(GetDelegate(), m_eventType);
- }
- void ScriptEventListener::ScriptEventDelegate(IEventDataPtr pEvent)
- {
- GCC_ASSERT(m_scriptCallbackFunction.valid()); // this should never happen since it's validated before even creating this object
- // call the lua function
- std::shared_ptr<ScriptEvent> pScriptEvent = static_pointer_cast<ScriptEvent>(pEvent);
- sol::function Callback = m_scriptCallbackFunction;
- Callback(pScriptEvent->GetEventData());
- }
- //---------------------------------------------------------------------------------------------------------------------
- // Initializes the script export system
- //---------------------------------------------------------------------------------------------------------------------
- bool InternalScriptExports::Init(void)
- {
- GCC_ASSERT(s_pScriptEventListenerMgr == NULL);
- s_pScriptEventListenerMgr = GCC_NEW ScriptEventListenerMgr;
-
- return true;
- }
- //---------------------------------------------------------------------------------------------------------------------
- // Destroys the script export system
- //---------------------------------------------------------------------------------------------------------------------
- void InternalScriptExports::Destroy(void)
- {
- GCC_ASSERT(s_pScriptEventListenerMgr != NULL);
- SAFE_DELETE(s_pScriptEventListenerMgr);
- }
- //---------------------------------------------------------------------------------------------------------------------
- // Loads a script resource then executes it. This is used by the require() function in script (defined in
- // PreInit.lua).
- //---------------------------------------------------------------------------------------------------------------------
- bool InternalScriptExports::LoadAndExecuteScriptResource(const char* scriptResource)
- {
- Resource resource(scriptResource);
- std::shared_ptr<ResHandle> pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource);
- if (pResourceHandle)
- return true;
- return false;
- }
- //---------------------------------------------------------------------------------------------------------------------
- // Queue's an event from the script. Returns true if the event was sent, false if not.
- //---------------------------------------------------------------------------------------------------------------------
- bool InternalScriptExports::QueueEvent(EventType eventType, sol::object eventData)
- {
- std::shared_ptr<ScriptEvent> pEvent(BuildEvent(eventType, eventData));
- if (pEvent)
- {
- IEventManager::Get()->VQueueEvent(pEvent);
- return true;
- }
- return false;
- }
- //---------------------------------------------------------------------------------------------------------------------
- // Builds the event to be sent or queued
- //---------------------------------------------------------------------------------------------------------------------
- std::shared_ptr<ScriptEvent> InternalScriptExports::BuildEvent(EventType eventType, sol::object& eventData)
- {
- // create the event from the event type
- std::shared_ptr<ScriptEvent> pEvent(ScriptEvent::CreateEventFromScript(eventType));
- if (!pEvent)
- return std::shared_ptr<ScriptEvent>();
- // set the event data that was passed in
- if (!pEvent->SetEventData(eventData))
- {
- return std::shared_ptr<ScriptEvent>();
- }
- return pEvent;
- }
- //---------------------------------------------------------------------------------------------------------------------
- // Instantiates a C++ ScriptListener object, inserts it into the manager, and returns a handle to it. The script
- // should maintain the handle if it needs to remove the listener at some point. Otherwise, the listener will be
- // destroyed when the program exits.
- //---------------------------------------------------------------------------------------------------------------------
- unsigned long InternalScriptExports::RegisterEventListener(EventType eventType, sol::function callbackFunction)
- {
- GCC_ASSERT(s_pScriptEventListenerMgr);
- if (callbackFunction.valid())
- {
- // create the C++ listener proxy and set it to listen for the event
- ScriptEventListener* pListener = GCC_NEW ScriptEventListener(eventType, callbackFunction);
- s_pScriptEventListenerMgr->AddListener(pListener);
- IEventManager::Get()->VAddListener(pListener->GetDelegate(), eventType);
- // convert the pointer to an unsigned long to use as the handle
- unsigned long handle = reinterpret_cast<unsigned long>(pListener);
- return handle;
- }
- GCC_ERROR("Attempting to register script event listener with invalid callback function");
- return 0;
- }
- void InternalScriptExports::LuaLog(sol::object text)
- {
- if (text.is<std::string>())
- {
- GCC_LOG("Lua", text.as<std::string>());
- }
- else
- {
- const char* typeName = lua_typename(text.lua_state(), static_cast<int>(text.get_type()));
- GCC_LOG("Lua", "<" + std::string(typeName) + ">");
- }
- }
- //---------------------------------------------------------------------------------------------------------------------
- // This function registers all the ScriptExports functions with the scripting system. It is called in
- // Application::Init().
- //---------------------------------------------------------------------------------------------------------------------
- void ScriptExports::Register(void)
- {
- sol::state_view lua = LuaStateManager::Get()->GetLuaState();
- sol::global_table globals = lua.globals();
- // init
- InternalScriptExports::Init();
- // resource loading
- globals["LoadAndExecuteScriptResource"] = &InternalScriptExports::LoadAndExecuteScriptResource;
- // actors
- // globals.RegisterDirect("CreateActor", &InternalScriptExports::CreateActor);
- // event system
- globals["RegisterEventListener"] = &InternalScriptExports::RegisterEventListener;
- // globals.RegisterDirect("RemoveEventListener", &InternalScriptExports::RemoveEventListener);
- globals["QueueEvent"] = &InternalScriptExports::QueueEvent;
- // globals.RegisterDirect("TriggerEvent", &InternalScriptExports::TriggerEvent);
-
- // process system
- // globals.RegisterDirect("AttachProcess", &InternalScriptExports::AttachScriptProcess);
- // math
- // LuaPlus::LuaObject mathTable = globals.GetByName("GccMath");
- // GCC_ASSERT(mathTable.IsTable());
- // mathTable.RegisterDirect("GetYRotationFromVector", &InternalScriptExports::GetYRotationFromVector);
- // mathTable.RegisterDirect("WrapPi", &InternalScriptExports::WrapPi);
- // mathTable.RegisterDirect("GetVectorFromRotation", &InternalScriptExports::GetVectorFromRotation);
-
- // misc
- globals["Log"] = &InternalScriptExports::LuaLog;
- // globals.RegisterDirect("GetTickCount", &InternalScriptExports::GetTickCount);
- // Physics
- // globals.RegisterDirect("ApplyForce", &InternalScriptExports::ApplyForce);
- // globals.RegisterDirect("ApplyTorque", &InternalScriptExports::ApplyTorque);
- }
- //---------------------------------------------------------------------------------------------------------------------
- // This function unregisters all the ScriptExports functions and gives any underlying systems a chance to destroy
- // themselves. It is called in the Application destructor.
- //---------------------------------------------------------------------------------------------------------------------
- void ScriptExports::Unregister(void)
- {
- InternalScriptExports::Destroy();
- }
|