BaseScriptComponent.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. //========================================================================
  2. // BaseScriptComponent.cpp - Component for exposing actors to Lua
  3. //
  4. // Part of the GameCode4 Application
  5. //
  6. // GameCode4 is the sample application that encapsulates much of the source code
  7. // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David
  8. // "Rez" Graham, published by Charles River Media.
  9. // ISBN-10: 1133776574 | ISBN-13: 978-1133776574
  10. //
  11. // If this source code has found it's way to you, and you think it has helped you
  12. // in any way, do the authors a favor and buy a new copy of the book - there are
  13. // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com
  14. // by clicking here:
  15. // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller=
  16. //
  17. // There's a companion web site at http://www.mcshaffry.com/GameCode/
  18. //
  19. // The source code is managed and maintained through Google Code:
  20. // http://code.google.com/p/gamecode4/
  21. //
  22. // (c) Copyright 2012 Michael L. McShaffry and David Graham
  23. //
  24. // This program is free software; you can redistribute it and/or
  25. // modify it under the terms of the GNU Lesser GPL v3
  26. // as published by the Free Software Foundation.
  27. //
  28. // This program is distributed in the hope that it will be useful,
  29. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  31. // http://www.gnu.org/licenses/lgpl-3.0.txt for more details.
  32. //
  33. // You should have received a copy of the GNU Lesser GPL v3
  34. // along with this program; if not, write to the Free Software
  35. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  36. //
  37. //========================================================================
  38. #include "../Unix/GameCodeStd.h"
  39. #include "BaseScriptComponent.h"
  40. #include "../LUAScripting/LuaStateManager.h"
  41. // This is the name of the metatable where all the function definitions exported to Lua will live.
  42. static const char* METATABLE_NAME = "BaseScriptComponentMetaTable";
  43. const char* BaseScriptComponent::g_Name = "BaseScriptComponent";
  44. BaseScriptComponent::BaseScriptComponent(void)
  45. {
  46. m_scriptObject = sol::object();
  47. m_scriptDestructor = sol::nil;
  48. }
  49. BaseScriptComponent::~BaseScriptComponent(void)
  50. {
  51. // call the script destructor if there is one
  52. if (m_scriptDestructor.valid())
  53. {
  54. m_scriptDestructor(m_scriptObject);
  55. }
  56. // clear out the script object
  57. m_scriptObject = sol::object();
  58. // if we were given a path for this script object, set it to nil
  59. if (!m_scriptObjectName.empty())
  60. {
  61. m_scriptObjectName += " = nil;";
  62. LuaStateManager::Get()->VExecuteString(m_scriptObjectName.c_str());
  63. }
  64. }
  65. bool BaseScriptComponent::VInit(TiXmlElement* pData)
  66. {
  67. LuaStateManager* pStateMgr = LuaStateManager::Get();
  68. GCC_ASSERT(pStateMgr);
  69. sol::state_view lua = pStateMgr->GetLuaState();
  70. sol::global_table global_table = pStateMgr->GetGlobalVars();
  71. // load the <ScriptObject> tag and validate it
  72. TiXmlElement* pScriptObjectElement = pData->FirstChildElement("ScriptObject");
  73. if (!pScriptObjectElement)
  74. {
  75. GCC_ERROR("No <ScriptObject> tag in XML. This won't be a very useful script component.");
  76. return true; // technically it succeeded even though it won't be accessible
  77. }
  78. // read all the attribute
  79. const char* temp = NULL;
  80. temp = pScriptObjectElement->Attribute("var");
  81. if (temp)
  82. m_scriptObjectName = temp;
  83. temp = pScriptObjectElement->Attribute("constructor");
  84. if (temp)
  85. m_constructorName = temp;
  86. temp = pScriptObjectElement->Attribute("destructor");
  87. if (temp)
  88. m_destructorName = temp;
  89. // Having a var attribute will export the instance of this object to that name.
  90. if (!m_scriptObjectName.empty())
  91. {
  92. m_scriptObject = pStateMgr->CreatePath(m_scriptObjectName.c_str());
  93. if (m_scriptObject != sol::nil)
  94. {
  95. CreateScriptObject();
  96. }
  97. }
  98. // The scriptConstructor attribute will also cause a Lua object to be created if one wasn't created in
  99. // the previous step. The scriptConstructor string is treated as a function of the form f(scriptObject)
  100. // and is called.
  101. if (!m_constructorName.empty())
  102. {
  103. m_scriptConstructor = global_table[m_constructorName.c_str()];
  104. if (m_scriptConstructor.valid())
  105. {
  106. // m_scriptObject could be nil if there was no scriptObject attribute. If this is the case,
  107. // the Lua object is created here.
  108. if (m_scriptObject == sol::nil)
  109. {
  110. m_scriptObject = lua.create_table();
  111. CreateScriptObject();
  112. }
  113. }
  114. }
  115. // The scriptDestructor attribute is treated as a function in the form of f(scriptObject) and is called
  116. // when the C++ ScriptObject instance is destroyed.
  117. if (!m_destructorName.empty())
  118. {
  119. m_scriptDestructor = global_table[m_destructorName];
  120. }
  121. return true;
  122. }
  123. void BaseScriptComponent::VPostInit(void)
  124. {
  125. // call the script constructor if one exists
  126. if (m_scriptConstructor.valid())
  127. {
  128. sol::protected_function_result result = m_scriptConstructor(m_scriptObject);
  129. if (!result.valid())
  130. {
  131. sol::error err = result;
  132. GCC_ERROR(std::string("Script constructor failed: ") + err.what());
  133. }
  134. }
  135. }
  136. TiXmlElement* BaseScriptComponent::VGenerateXml(void)
  137. {
  138. TiXmlElement* pBaseElement = GCC_NEW TiXmlElement(VGetName());
  139. // ScriptObject
  140. TiXmlElement* pScriptObjectElement = GCC_NEW TiXmlElement("ScriptObject");
  141. if (!m_scriptObjectName.empty())
  142. pScriptObjectElement->SetAttribute("var", m_scriptObjectName.c_str());
  143. if (!m_constructorName.empty())
  144. pScriptObjectElement->SetAttribute("constructor", m_constructorName.c_str());
  145. if (!m_destructorName.empty())
  146. pScriptObjectElement->SetAttribute("destructor", m_destructorName.c_str());
  147. pBaseElement->LinkEndChild(pScriptObjectElement);
  148. return pBaseElement;
  149. }
  150. void BaseScriptComponent::CreateScriptObject(void)
  151. {
  152. sol::state_view lua = LuaStateManager::Get()->GetLuaState();
  153. m_scriptObject = sol::make_object(lua, this);
  154. }
  155. void BaseScriptComponent::RegisterScriptFunctions(void)
  156. {
  157. // create the metatable
  158. sol::state_view lua = LuaStateManager::Get()->GetLuaState();
  159. lua.new_usertype<BaseScriptComponent>(METATABLE_NAME,
  160. "GetActorId", &BaseScriptComponent::GetActorId//,
  161. // "GetPos", &BaseScriptComponent::GetActorId,
  162. // "SetPos", &BaseScriptComponent::GetActorId,
  163. // "GetLookAt", &BaseScriptComponent::GetActorId,
  164. // "GetYOrientationRadians", &BaseScriptComponent::GetActorId,
  165. // "RotateY", &BaseScriptComponent::GetActorId,
  166. // "Stop", &BaseScriptComponent::GetActorId,
  167. // "SetPosition", &BaseScriptComponent::GetActorId,
  168. );
  169. }
  170. ActorId BaseScriptComponent::GetActorId(void)
  171. {
  172. return m_pOwner->GetId();
  173. }