912 lines
27 KiB
C++
912 lines
27 KiB
C++
#include <OgreFileSystemLayer.h>
|
|
#include "GameData.h"
|
|
#include "Components.h"
|
|
#include "GUIModule.h"
|
|
#include "PhysicsModule.h"
|
|
#include "CharacterModule.h"
|
|
#include "CharacterAnimationModule.h"
|
|
#include "BoatModule.h"
|
|
#include "EventTriggerModule.h"
|
|
#include "SlotsModule.h"
|
|
#include "world-build.h"
|
|
#include "LuaData.h"
|
|
#include "luaaa.hpp"
|
|
extern "C" {
|
|
int luaopen_lpeg(lua_State *L);
|
|
}
|
|
struct FooPosition {
|
|
Ogre::Vector3 value;
|
|
Ogre::Vector3 &get()
|
|
{
|
|
return value;
|
|
}
|
|
};
|
|
namespace luaaa
|
|
{
|
|
template <> struct LuaStack<FooPosition> {
|
|
inline static FooPosition get(lua_State *L, int idx)
|
|
{
|
|
FooPosition result;
|
|
if (lua_istable(L, idx)) {
|
|
lua_pushnil(L);
|
|
while (0 != lua_next(L, idx)) {
|
|
const int top = lua_gettop(L);
|
|
const char *name =
|
|
LuaStack<const char *>::get(L, top - 1);
|
|
if (strncmp(name, "x", 1) == 0)
|
|
result.value.x =
|
|
LuaStack<float>::get(L, top);
|
|
else if (strncmp(name, "y", 1) == 0)
|
|
result.value.y =
|
|
LuaStack<float>::get(L, top);
|
|
else if (strncmp(name, "z", 1) == 0)
|
|
result.value.z =
|
|
LuaStack<float>::get(L, top);
|
|
lua_pop(L, 1);
|
|
}
|
|
lua_pop(L, 0);
|
|
}
|
|
return result;
|
|
}
|
|
inline static void put(lua_State *L, const FooPosition &v)
|
|
{
|
|
lua_newtable(L);
|
|
LuaStack<const char *>::put(L, "x");
|
|
LuaStack<float>::put(L, v.value.x);
|
|
lua_rawset(L, -3);
|
|
LuaStack<const char *>::put(L, "y");
|
|
LuaStack<float>::put(L, v.value.y);
|
|
lua_rawset(L, -3);
|
|
LuaStack<const char *>::put(L, "z");
|
|
LuaStack<float>::put(L, v.value.z);
|
|
lua_rawset(L, -3);
|
|
}
|
|
};
|
|
|
|
}
|
|
namespace ECS
|
|
{
|
|
struct LuaEcsEntity {
|
|
int id;
|
|
flecs::entity e;
|
|
};
|
|
struct idmap {
|
|
std::unordered_map<int, flecs::entity> id2entity;
|
|
std::unordered_map<flecs::entity_t, int> entity2id;
|
|
int next_id;
|
|
idmap()
|
|
: id2entity({})
|
|
, entity2id({})
|
|
, next_id(0)
|
|
{
|
|
}
|
|
int get_next_id()
|
|
{
|
|
next_id++;
|
|
return next_id;
|
|
}
|
|
int add_entity(flecs::entity e)
|
|
{
|
|
if (entity2id.find(e.id()) != entity2id.end())
|
|
return entity2id[e.id()];
|
|
int id = get_next_id();
|
|
id2entity[id] = e;
|
|
entity2id[e.id()] = id;
|
|
return id;
|
|
}
|
|
flecs::entity get_entity(int id)
|
|
{
|
|
OgreAssert(id2entity[id].is_valid(), "Invalid entity");
|
|
return id2entity[id];
|
|
}
|
|
};
|
|
struct idmap idmap;
|
|
|
|
int LuaData::setup_handler()
|
|
{
|
|
luaL_checktype(L, 1, LUA_TFUNCTION);
|
|
lua_pushvalue(L, 1);
|
|
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
setup_handlers.push_back(ref);
|
|
return 0;
|
|
}
|
|
int LuaData::call_handler(const Ogre::String &event)
|
|
{
|
|
int i;
|
|
for (i = 0; i < setup_handlers.size(); i++) {
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, setup_handlers[i]);
|
|
lua_pushstring(L, event.c_str());
|
|
lua_pushinteger(L, -1);
|
|
lua_pushinteger(L, -1);
|
|
if (lua_pcall(L, 3, 0, 0)) {
|
|
Ogre::LogManager::getSingleton().stream()
|
|
<< lua_tostring(L, -1);
|
|
OgreAssert(false, "Lua error");
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int LuaData::call_handler(const Ogre::String &event, flecs::entity e,
|
|
flecs::entity o)
|
|
{
|
|
int i;
|
|
for (i = 0; i < setup_handlers.size(); i++) {
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, setup_handlers[i]);
|
|
lua_pushstring(L, event.c_str());
|
|
lua_pushinteger(L, idmap.add_entity(e));
|
|
lua_pushinteger(L, idmap.add_entity(o));
|
|
if (lua_pcall(L, 3, 0, 0)) {
|
|
Ogre::LogManager::getSingleton().stream()
|
|
<< lua_tostring(L, -1);
|
|
OgreAssert(false, "Lua error");
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int luaLibraryLoader(lua_State *L)
|
|
{
|
|
int i;
|
|
if (!lua_isstring(L, 1)) {
|
|
luaL_error(
|
|
L,
|
|
"luaLibraryLoader: Expected string for first parameter");
|
|
}
|
|
|
|
std::string libraryFile = lua_tostring(L, 1);
|
|
std::cout << libraryFile << std::endl;
|
|
// In order to be compatible with the normal Lua file loader,
|
|
// translate '.' to the file system seperator character.
|
|
// In this case (An ogre resource) '/'
|
|
while (libraryFile.find('.') != std::string::npos)
|
|
libraryFile.replace(libraryFile.find('.'), 1, "/");
|
|
|
|
libraryFile += ".lua";
|
|
std::cout << libraryFile << std::endl;
|
|
Ogre::StringVectorPtr scripts =
|
|
Ogre::ResourceGroupManager::getSingleton().listResourceNames(
|
|
"LuaScripts", false);
|
|
std::vector<Ogre::String> &strings = *scripts;
|
|
for (i = 0; i < strings.size(); i++)
|
|
std::cout << strings[i] << std::endl;
|
|
|
|
if (0 && !Ogre::ResourceGroupManager::getSingleton()
|
|
.resourceExistsInAnyGroup(libraryFile)) {
|
|
// Could not find the file.
|
|
std::string errMessage = "\n no file '" + libraryFile +
|
|
"' found in Ogre resource archives.";
|
|
lua_pushstring(L, errMessage.c_str());
|
|
} else {
|
|
Ogre::DataStreamList streams =
|
|
Ogre::ResourceGroupManager::getSingleton().openResources(
|
|
"*.lua", "LuaScripts");
|
|
Ogre::DataStreamPtr stream =
|
|
Ogre::ResourceGroupManager::getSingleton().openResource(
|
|
libraryFile, "LuaScripts");
|
|
Ogre::String script = stream->getAsString();
|
|
if (luaL_loadbuffer(L, script.c_str(), script.length(),
|
|
libraryFile.c_str())) {
|
|
luaL_error(
|
|
L,
|
|
"Error loading library '%s' from resource archive.\n%s",
|
|
libraryFile.c_str(), lua_tostring(L, -1));
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
struct LuaChildEventTrigger {
|
|
flecs::entity parent_e;
|
|
Ogre::Vector3 position;
|
|
float halfheight;
|
|
float radius;
|
|
Ogre::String event;
|
|
};
|
|
|
|
static void installLibraryLoader(lua_State *L)
|
|
{
|
|
// Insert the c++ func 'luaLibraryLoader' into package.loaders.
|
|
// Inserted at the start of the table in order to take precedence.
|
|
lua_getglobal(L, "table");
|
|
lua_getfield(L, -1, "insert");
|
|
lua_remove(L, -2); // table
|
|
lua_getglobal(L, "package");
|
|
lua_getfield(L, -1, "searchers");
|
|
lua_remove(L, -2); // package
|
|
lua_pushnumber(L, 1); // index where to insert into loaders table
|
|
lua_pushcfunction(L, luaLibraryLoader);
|
|
if (lua_pcall(L, 3, 0, 0))
|
|
Ogre::LogManager::getSingleton().stream() << lua_tostring(L, 1);
|
|
}
|
|
|
|
LuaData::LuaData()
|
|
: L(luaL_newstate())
|
|
{
|
|
luaopen_base(L);
|
|
luaopen_table(L);
|
|
luaopen_package(L);
|
|
luaL_requiref(L, "table", luaopen_table, 1);
|
|
lua_pop(L, 1);
|
|
luaL_requiref(L, "math", luaopen_math, 1);
|
|
lua_pop(L, 1);
|
|
luaL_requiref(L, "package", luaopen_package, 1);
|
|
lua_pop(L, 1);
|
|
luaL_requiref(L, "string", luaopen_string, 1);
|
|
lua_pop(L, 1);
|
|
luaL_requiref(L, "io", luaopen_io, 1);
|
|
lua_pop(L, 1);
|
|
luaL_requiref(L, "lpeg", luaopen_lpeg, 1);
|
|
lua_pop(L, 1);
|
|
#if 0
|
|
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
|
lua_pushcfunction(L, luaopen_lpeg);
|
|
lua_setfield(L, -2, "lpeg");
|
|
lua_pop(L, 1); // remove PRELOAD table
|
|
#endif
|
|
installLibraryLoader(L);
|
|
lua_pop(L, 1);
|
|
|
|
#if 0
|
|
luaaa::LuaClass<Ogre::Vector3> luaVector3(L, "Vector3");
|
|
luaVector3.ctor<float, float, float>();
|
|
luaVector3.get("x", [](Ogre::Vector3 &v) -> float { return v.x; });
|
|
luaVector3.set("x", [](Ogre::Vector3 &v, float value) -> void {
|
|
v.x = value;
|
|
});
|
|
luaVector3.get("y", [](Ogre::Vector3 &v) -> float { return v.y; });
|
|
luaVector3.set("y", [](Ogre::Vector3 &v, float value) -> void {
|
|
v.y = value;
|
|
});
|
|
luaVector3.get("z", [](Ogre::Vector3 &v) -> float { return v.z; });
|
|
luaVector3.set("z", [](Ogre::Vector3 &v, float value) -> void {
|
|
v.z = value;
|
|
});
|
|
luaVector3.fun("squaredLength", &Ogre::Vector3::squaredLength);
|
|
luaVector3.fun("length", &Ogre::Vector3::length);
|
|
luaVector3.fun("squaredDistance", &Ogre::Vector3::squaredDistance);
|
|
luaVector3.fun("distance", &Ogre::Vector3::distance);
|
|
#endif
|
|
luaaa::LuaModule luaECS(L, "_ecs");
|
|
luaECS.fun("position", [](int id) -> FooPosition {
|
|
#if 0
|
|
flecs::entity e = idmap.get_entity(id);
|
|
if (e.has<CharacterBase>()) {
|
|
const CharacterBase &cb = e.get<CharacterBase>();
|
|
return cb.mBodyNode->_getDerivedPosition();
|
|
} else if (e.has<BoatBase>()) {
|
|
const BoatBase &boat = e.get<BoatBase>();
|
|
return boat.mNode->_getDerivedPosition();
|
|
} else if (e.has<EventTrigger>()) {
|
|
const EventTrigger &trigger = e.get<EventTrigger>();
|
|
return trigger.position;
|
|
} else
|
|
return Ogre::Vector3(0, 0, 0);
|
|
#endif
|
|
return FooPosition();
|
|
});
|
|
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
OgreAssert(false, "Crash function called");
|
|
return 0;
|
|
});
|
|
lua_setglobal(L, "crash");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
luaL_checktype(L, 1, LUA_TFUNCTION);
|
|
ECS::get<LuaBase>().mLua->setup_handler();
|
|
return 0;
|
|
});
|
|
lua_setglobal(L, "setup_handler");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
int args = lua_gettop(L);
|
|
if (args < 1)
|
|
return 0;
|
|
ECS::get_mut<GUI>().choices.clear();
|
|
luaL_checktype(L, 1, LUA_TSTRING);
|
|
if (args > 1) {
|
|
luaL_checktype(L, 2, LUA_TTABLE);
|
|
lua_pushnil(L); /* first key */
|
|
while (lua_next(L, 2) != 0) {
|
|
Ogre::String s = lua_tostring(L, -1);
|
|
ECS::get_mut<GUI>().choices.push_back(s);
|
|
lua_pop(L, 1); /* remove value but keep key */
|
|
}
|
|
}
|
|
size_t len;
|
|
Ogre::String message(luaL_tolstring(L, 1, &len));
|
|
std::cout << "narrator message: " << message
|
|
<< " length: " << message.length() << std::endl;
|
|
if (message.length() == 0 && ECS::get_mut<GUI>().narrationBox) {
|
|
ECS::get_mut<GUI>().enabled = false;
|
|
ECS::get_mut<GUI>().grab = true;
|
|
ECS::get_mut<GUI>().grabChanged = true;
|
|
ECS::get_mut<GUI>().narrationText = message;
|
|
ECS::get_mut<GUI>().narrationBox = false;
|
|
ECS::modified<GUI>();
|
|
std::cout << "narration ended\n";
|
|
} else if (message.length() > 0) {
|
|
ECS::get_mut<GUI>().enabled = true;
|
|
ECS::get_mut<GUI>().grab = false;
|
|
ECS::get_mut<GUI>().grabChanged = true;
|
|
ECS::get_mut<GUI>().narrationText = message;
|
|
ECS::get_mut<GUI>().narrationBox = true;
|
|
ECS::modified<GUI>();
|
|
}
|
|
|
|
return 0;
|
|
});
|
|
lua_setglobal(L, "narrate");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
// ECS::get_mut<GUI>().mainMenu = true;
|
|
lua_pushinteger(L, ECS::get<GUI>().narration_answer);
|
|
return 1;
|
|
});
|
|
lua_setglobal(L, "narration_get_answer");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
// ECS::get_mut<GUI>().mainMenu = true;
|
|
ECS::get_mut<GUI>().enabled = true;
|
|
ECS::get_mut<GUI>().mainMenu = true;
|
|
ECS::get_mut<GUI>().grab = false;
|
|
ECS::get_mut<GUI>().grabChanged = true;
|
|
ECS::modified<GUI>();
|
|
return 0;
|
|
});
|
|
lua_setglobal(L, "main_menu");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
luaL_checktype(L, 1, LUA_TSTRING);
|
|
luaL_checktype(L, 2, LUA_TNUMBER);
|
|
luaL_checktype(L, 3, LUA_TNUMBER);
|
|
luaL_checktype(L, 4, LUA_TNUMBER);
|
|
luaL_checktype(L, 5, LUA_TNUMBER);
|
|
Ogre::String what = lua_tostring(L, 1);
|
|
if (what == "boat") {
|
|
float yaw = lua_tonumber(L, 5);
|
|
float x = lua_tonumber(L, 2);
|
|
float y = lua_tonumber(L, 3);
|
|
float z = lua_tonumber(L, 4);
|
|
flecs::entity e = ECS::get().entity();
|
|
Ogre::Quaternion orientation(Ogre::Radian(yaw),
|
|
Ogre::Vector3(0, 1, 0));
|
|
Ogre::Vector3 position(x, y, z);
|
|
e.set<BoatType>(
|
|
{ "boat.scene", position, orientation });
|
|
int ret = idmap.add_entity(e);
|
|
lua_pushinteger(L, ret);
|
|
std::cout << "boat created: " << ret << std::endl;
|
|
return 1;
|
|
} else if (what == "raft") {
|
|
float yaw = lua_tonumber(L, 5);
|
|
float x = lua_tonumber(L, 2);
|
|
float y = lua_tonumber(L, 3);
|
|
float z = lua_tonumber(L, 4);
|
|
flecs::entity e = ECS::get().entity();
|
|
Ogre::Quaternion orientation(Ogre::Radian(yaw),
|
|
Ogre::Vector3(0, 1, 0));
|
|
Ogre::Vector3 position(x, y, z);
|
|
e.set<BoatType>(
|
|
{ "raft.scene", position, orientation });
|
|
int ret = idmap.add_entity(e);
|
|
lua_pushinteger(L, ret);
|
|
std::cout << "raft created: " << ret << std::endl;
|
|
return 1;
|
|
}
|
|
lua_pushinteger(L, -1);
|
|
return 1;
|
|
});
|
|
lua_setglobal(L, "ecs_vehicle_set");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
OgreAssert(lua_gettop(L) == 6, "bad parameters");
|
|
luaL_checktype(L, 1, LUA_TSTRING); // event
|
|
luaL_checktype(L, 2, LUA_TNUMBER); // x
|
|
luaL_checktype(L, 3, LUA_TNUMBER); // y
|
|
luaL_checktype(L, 4, LUA_TNUMBER); // z
|
|
luaL_checktype(L, 5, LUA_TNUMBER); // halfh
|
|
luaL_checktype(L, 6, LUA_TNUMBER); // radius
|
|
flecs::entity e = ECS::get().entity();
|
|
Ogre::String event = lua_tostring(L, 1);
|
|
float x = lua_tonumber(L, 2);
|
|
float y = lua_tonumber(L, 3);
|
|
float z = lua_tonumber(L, 4);
|
|
float h = lua_tonumber(L, 5);
|
|
float r = lua_tonumber(L, 6);
|
|
Ogre::Vector3 position(x, y, z);
|
|
e.set<EventTrigger>({ nullptr, position, h, r, event });
|
|
lua_pushinteger(L, idmap.add_entity(e));
|
|
return 1;
|
|
});
|
|
lua_setglobal(L, "ecs_character_trigger");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
luaL_checktype(L, 1, LUA_TNUMBER); // object
|
|
int object = lua_tointeger(L, 1);
|
|
flecs::entity object_e = idmap.get_entity(object);
|
|
flecs::entity parent_e = object_e.parent();
|
|
lua_pushinteger(L, idmap.add_entity(parent_e));
|
|
return 1;
|
|
});
|
|
lua_setglobal(L, "ecs_parent");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
OgreAssert(lua_gettop(L) == 7, "bad parameters");
|
|
luaL_checktype(L, 1, LUA_TNUMBER); // parent
|
|
luaL_checktype(L, 2, LUA_TSTRING); // event
|
|
luaL_checktype(L, 3, LUA_TNUMBER); // x
|
|
luaL_checktype(L, 4, LUA_TNUMBER); // y
|
|
luaL_checktype(L, 5, LUA_TNUMBER); // z
|
|
luaL_checktype(L, 6, LUA_TNUMBER); // halfh
|
|
luaL_checktype(L, 7, LUA_TNUMBER); // radius
|
|
int parent = lua_tointeger(L, 1);
|
|
std::cout << "parent: " << parent << std::endl;
|
|
flecs::entity parent_e = idmap.get_entity(parent);
|
|
Ogre::String event = lua_tostring(L, 2);
|
|
float x = lua_tonumber(L, 3);
|
|
float y = lua_tonumber(L, 4);
|
|
float z = lua_tonumber(L, 5);
|
|
float h = lua_tonumber(L, 6);
|
|
float r = lua_tonumber(L, 7);
|
|
Ogre::Vector3 position(x, y, z);
|
|
flecs::entity e = ECS::get().entity().child_of(parent_e);
|
|
e.set<LuaChildEventTrigger>(
|
|
{ parent_e, position, h, r, event });
|
|
lua_pushinteger(L, idmap.add_entity(e));
|
|
return 1;
|
|
});
|
|
lua_setglobal(L, "ecs_child_character_trigger");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
luaL_checktype(L, 1, LUA_TNUMBER); // trigger
|
|
luaL_checktype(L, 2, LUA_TNUMBER); // object
|
|
int trigger = lua_tointeger(L, 1);
|
|
int object = lua_tointeger(L, 2);
|
|
flecs::entity trigger_e = idmap.get_entity(trigger);
|
|
flecs::entity object_e = idmap.get_entity(object);
|
|
Ogre::SceneNode *target_node = nullptr;
|
|
Ogre::Any targetAny = trigger_e.get<EventTrigger>()
|
|
.node->getUserObjectBindings()
|
|
.getUserAny("target");
|
|
OgreAssert(targetAny.has_value(), "need target");
|
|
target_node = Ogre::any_cast<Ogre::SceneNode *>(targetAny);
|
|
Ogre::Vector3 position = target_node->_getDerivedPosition();
|
|
Ogre::Quaternion orientation =
|
|
target_node->_getDerivedOrientation();
|
|
if (object_e.has<CharacterBase>()) {
|
|
object_e.get_mut<CharacterBase>()
|
|
.mBodyNode->_setDerivedPosition(position);
|
|
object_e.get_mut<CharacterBase>()
|
|
.mBodyNode->_setDerivedOrientation(orientation);
|
|
}
|
|
return 0;
|
|
});
|
|
lua_setglobal(L, "ecs_trigger_set_position");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
luaL_checktype(L, 1, LUA_TNUMBER); // trigger
|
|
int trigger = lua_tointeger(L, 1);
|
|
flecs::entity trigger_e = idmap.get_entity(trigger);
|
|
Ogre::SceneNode *node = trigger_e.get<EventTrigger>().node;
|
|
Ogre::Any animationAny =
|
|
node->getUserObjectBindings().getUserAny(
|
|
"trigger_animation");
|
|
if (animationAny.has_value()) {
|
|
Ogre::String animation =
|
|
Ogre::any_cast<Ogre::String>(animationAny);
|
|
lua_pushstring(L, animation.c_str());
|
|
return 1;
|
|
}
|
|
lua_pushnil(L);
|
|
return 1;
|
|
});
|
|
lua_setglobal(L, "ecs_trigger_get_animation");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
OgreAssert(lua_gettop(L) == 5, "Invalid parameters");
|
|
luaL_checktype(L, 1, LUA_TSTRING); // type
|
|
luaL_checktype(L, 2, LUA_TNUMBER);
|
|
luaL_checktype(L, 3, LUA_TNUMBER);
|
|
luaL_checktype(L, 4, LUA_TNUMBER);
|
|
luaL_checktype(L, 5, LUA_TNUMBER);
|
|
Ogre::String type = lua_tostring(L, 1);
|
|
float yaw = lua_tonumber(L, 5);
|
|
float x = lua_tonumber(L, 2);
|
|
float y = lua_tonumber(L, 3);
|
|
float z = lua_tonumber(L, 4);
|
|
flecs::entity e = ECS::get().entity();
|
|
Ogre::Quaternion orientation(Ogre::Radian(yaw),
|
|
Ogre::Vector3(0, 1, 0));
|
|
Ogre::Vector3 npcPos(x, y, z);
|
|
e.set<CharacterLocation>({ orientation, npcPos });
|
|
e.set<CharacterConf>({ type });
|
|
e.add<Character>();
|
|
lua_pushinteger(L, idmap.add_entity(e));
|
|
return 1;
|
|
});
|
|
lua_setglobal(L, "ecs_npc_set");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
OgreAssert(lua_gettop(L) == 1, "Bad parameters");
|
|
luaL_checktype(L, 1, LUA_TSTRING); // type
|
|
const char *fileName = lua_tostring(L, 1);
|
|
ECS::get<EngineData>().mScnMgr->getRootSceneNode()->saveChildren(
|
|
fileName);
|
|
return 0;
|
|
});
|
|
lua_setglobal(L, "ecs_save_scene_debug");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
OgreAssert(lua_gettop(L) == 2, "Bad parameters");
|
|
luaL_checktype(L, 1, LUA_TNUMBER); // object
|
|
luaL_checktype(L, 2, LUA_TSTRING); // name
|
|
int object = lua_tointeger(L, 1);
|
|
flecs::entity object_e = idmap.get_entity(object);
|
|
const char *fileName = lua_tostring(L, 2);
|
|
Ogre::SceneNode *node = nullptr;
|
|
if (object_e.has<CharacterBase>())
|
|
node = object_e.get<CharacterBase>().mBodyNode;
|
|
else if (object_e.has<BoatBase>())
|
|
node = object_e.get<BoatBase>().mNode;
|
|
if (node)
|
|
node->saveChildren(fileName);
|
|
return 0;
|
|
});
|
|
lua_setglobal(L, "ecs_save_object_debug");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
luaL_checktype(L, 1, LUA_TBOOLEAN); // object
|
|
ECS::get_mut<EngineData>().enableDbgDraw = lua_toboolean(L, 1);
|
|
ECS::modified<EngineData>();
|
|
return 0;
|
|
});
|
|
lua_setglobal(L, "ecs_set_debug_drawing");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
OgreAssert(lua_gettop(L) >= 1, "Bad parameters");
|
|
luaL_checktype(L, 1, LUA_TSTRING);
|
|
Ogre::String command = lua_tostring(L, 1);
|
|
if (command == "physics-control") {
|
|
OgreAssert(lua_gettop(L) == 3, "Bad parameters");
|
|
luaL_checktype(L, 2, LUA_TNUMBER); // object
|
|
luaL_checktype(L, 3, LUA_TBOOLEAN);
|
|
int object = lua_tointeger(L, 2);
|
|
flecs::entity object_e = idmap.get_entity(object);
|
|
bool enable = lua_toboolean(L, 3);
|
|
OgreAssert(object_e.has<CharacterBase>(),
|
|
"Not a character");
|
|
PhysicsModule::controlPhysics(object_e, enable);
|
|
object_e.add<CharacterUpdatePhysicsState>();
|
|
return 0;
|
|
} else if (command == "is-player") {
|
|
OgreAssert(lua_gettop(L) == 2, "Bad parameters");
|
|
luaL_checktype(L, 2, LUA_TNUMBER); // object
|
|
int object = lua_tointeger(L, 2);
|
|
flecs::entity object_e = idmap.get_entity(object);
|
|
lua_pushboolean(L, object_e.has<Player>());
|
|
return 1;
|
|
} else if (command == "set-actuator") {
|
|
OgreAssert(lua_gettop(L) == 3, "Bad parameters");
|
|
luaL_checktype(L, 2, LUA_TNUMBER); // object
|
|
luaL_checktype(L, 3, LUA_TSTRING); // animation
|
|
Ogre::String animation = lua_tostring(L, 3);
|
|
|
|
int object = lua_tointeger(L, 2);
|
|
flecs::entity object_e = idmap.get_entity(object);
|
|
object_e.set<CharacterVelocity>(
|
|
{ { 0, 0, 0 }, { 0, 0, 0 } });
|
|
if (animation.length() > 0)
|
|
object_e.set<CharacterInActuator>(
|
|
{ animation, { 0, 0, 0 } });
|
|
else
|
|
object_e.remove<CharacterInActuator>();
|
|
return 0;
|
|
} else if (command == "animation-state") {
|
|
OgreAssert(lua_gettop(L) >= 4, "Bad parameters");
|
|
luaL_checktype(L, 2, LUA_TNUMBER); // object
|
|
luaL_checktype(L, 3, LUA_TSTRING); // node
|
|
luaL_checktype(L, 4, LUA_TSTRING); // state
|
|
if (lua_gettop(L) == 5)
|
|
luaL_checktype(L, 5, LUA_TBOOLEAN); // reset
|
|
int object = lua_tointeger(L, 2);
|
|
flecs::entity object_e = idmap.get_entity(object);
|
|
Ogre::String nodeName = lua_tostring(L, 3);
|
|
Ogre::String stateName = lua_tostring(L, 4);
|
|
bool reset = false;
|
|
if (lua_gettop(L) == 5)
|
|
reset = lua_toboolean(L, 5);
|
|
GameWorld::ValueParameter<flecs::entity> *obj =
|
|
object_e.world()
|
|
.get_mut<GameWorld>()
|
|
.allocate_entity(object_e);
|
|
GameWorld::ValueParameter<std::string> *obj_node =
|
|
object_e.world()
|
|
.get_mut<GameWorld>()
|
|
.allocate_string(nodeName);
|
|
GameWorld::ValueParameter<std::string> *obj_state =
|
|
object_e.world()
|
|
.get_mut<GameWorld>()
|
|
.allocate_string(stateName);
|
|
ECS::get_mut<GameWorld>().command("set_animation_state",
|
|
{ obj, obj_node,
|
|
obj_state });
|
|
ECS::modified<GameWorld>();
|
|
|
|
return 0;
|
|
} else if (command == "params-set") {
|
|
OgreAssert(lua_gettop(L) == 4, "Invalid parameters");
|
|
luaL_checktype(L, 2, LUA_TNUMBER);
|
|
luaL_checktype(L, 3, LUA_TSTRING);
|
|
luaL_checktype(L, 4, LUA_TBOOLEAN);
|
|
bool enable = lua_toboolean(L, 4);
|
|
flecs::entity e = idmap.get_entity(lua_tointeger(L, 2));
|
|
Ogre::String what = lua_tostring(L, 3);
|
|
OgreAssert(e.is_valid(), "Invalid character");
|
|
OgreAssert(e.has<Character>(), "Not a character");
|
|
if (what == "gravity") {
|
|
/* clear momentum */
|
|
if (e.has<CharacterVelocity>()) {
|
|
e.get_mut<CharacterVelocity>()
|
|
.gvelocity.y = 0.0f;
|
|
e.get_mut<CharacterVelocity>()
|
|
.velocity.y = 0.0f;
|
|
e.modified<CharacterVelocity>();
|
|
}
|
|
if (enable)
|
|
e.add<CharacterGravity>();
|
|
else
|
|
e.remove<CharacterGravity>();
|
|
} else if (what == "buoyancy") {
|
|
if (enable)
|
|
e.add<CharacterBuoyancy>();
|
|
else
|
|
e.remove<CharacterBuoyancy>();
|
|
} else
|
|
OgreAssert(false, "Bad parameter " + what);
|
|
return 0;
|
|
} else {
|
|
OgreAssert(false, "bad argument " + command);
|
|
return 0;
|
|
}
|
|
});
|
|
lua_setglobal(L, "ecs_character");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
OgreAssert(lua_gettop(L) == 3, "Bad parameters");
|
|
luaL_checktype(L, 1, LUA_TNUMBER); // parent
|
|
luaL_checktype(L, 2, LUA_TNUMBER); // object
|
|
luaL_checktype(L, 3, LUA_TSTRING); // slot
|
|
int parent = lua_tointeger(L, 1);
|
|
int object = lua_tointeger(L, 2);
|
|
Ogre::String slot = lua_tostring(L, 3);
|
|
flecs::entity parent_e = idmap.get_entity(parent);
|
|
flecs::entity object_e = idmap.get_entity(object);
|
|
PhysicsModule::controlPhysics(object_e, false);
|
|
object_e.set<ParentSlot>({ parent_e, slot });
|
|
return 0;
|
|
});
|
|
lua_setglobal(L, "ecs_set_slot");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
flecs::entity e = ECS::get().lookup("player");
|
|
int result = idmap.add_entity(e);
|
|
lua_pushinteger(L, result);
|
|
return result;
|
|
});
|
|
lua_setglobal(L, "ecs_get_player_entity");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
luaL_checktype(L, 1, LUA_TNUMBER); // entity id
|
|
int id = lua_tointeger(L, 1);
|
|
flecs::entity e = idmap.get_entity(id);
|
|
LuaEcsEntity *edata = static_cast<LuaEcsEntity *>(
|
|
lua_newuserdata(L, sizeof(LuaEcsEntity)));
|
|
new (edata) LuaEcsEntity();
|
|
edata->e = e;
|
|
edata->id = e;
|
|
luaL_getmetatable(L, "FlecsEntityMetaTable");
|
|
lua_setmetatable(L, -2);
|
|
return 1;
|
|
});
|
|
lua_setglobal(L, "ecs_get_entity");
|
|
luaL_newmetatable(L, "FlecsEntityMetaTable");
|
|
lua_pushstring(L, "__index");
|
|
lua_pushcfunction(L, [](lua_State *L) -> int {
|
|
luaL_checktype(L, 1, LUA_TUSERDATA); //metatable
|
|
luaL_checktype(L, 2, LUA_TSTRING); //function
|
|
Ogre::String component = lua_tostring(L, 2);
|
|
if (component == "components") {
|
|
lua_pushvalue(L, 1);
|
|
lua_pushcclosure(
|
|
L,
|
|
[](lua_State *L) -> int {
|
|
luaL_checktype(L, lua_upvalueindex(1),
|
|
LUA_TUSERDATA);
|
|
LuaEcsEntity *ent = static_cast<
|
|
LuaEcsEntity *>(lua_touserdata(
|
|
L, lua_upvalueindex(1)));
|
|
std::cout << ent->id << " called!!!\n";
|
|
ent->e.each([&](flecs::id id) {
|
|
flecs::entity cmp =
|
|
ECS::get().entity(id);
|
|
if (cmp.is_alive()) {
|
|
const char *name =
|
|
cmp.name();
|
|
if (name)
|
|
std::cout
|
|
<< "component: "
|
|
<< name
|
|
<< std::endl;
|
|
}
|
|
});
|
|
return 0;
|
|
},
|
|
1);
|
|
} else if (component == "is_trigger") {
|
|
lua_pushvalue(L, 1);
|
|
lua_pushcclosure(
|
|
L,
|
|
[](lua_State *L) -> int {
|
|
luaL_checktype(L, lua_upvalueindex(1),
|
|
LUA_TUSERDATA);
|
|
LuaEcsEntity *ent = static_cast<
|
|
LuaEcsEntity *>(lua_touserdata(
|
|
L, lua_upvalueindex(1)));
|
|
lua_pushboolean(
|
|
L, ent->e.has<EventTrigger>());
|
|
return 1;
|
|
},
|
|
1);
|
|
} else if (component == "is_character") {
|
|
lua_pushvalue(L, 1);
|
|
lua_pushcclosure(
|
|
L,
|
|
[](lua_State *L) -> int {
|
|
luaL_checktype(L, lua_upvalueindex(1),
|
|
LUA_TUSERDATA);
|
|
LuaEcsEntity *ent = static_cast<
|
|
LuaEcsEntity *>(lua_touserdata(
|
|
L, lua_upvalueindex(1)));
|
|
lua_pushboolean(
|
|
L, ent->e.has<Character>());
|
|
return 1;
|
|
},
|
|
1);
|
|
} else if (component == "is_boat") {
|
|
lua_pushvalue(L, 1);
|
|
lua_pushcclosure(
|
|
L,
|
|
[](lua_State *L) -> int {
|
|
luaL_checktype(L, lua_upvalueindex(1),
|
|
LUA_TUSERDATA);
|
|
LuaEcsEntity *ent = static_cast<
|
|
LuaEcsEntity *>(lua_touserdata(
|
|
L, lua_upvalueindex(1)));
|
|
lua_pushboolean(L,
|
|
ent->e.has<BoatBase>());
|
|
return 1;
|
|
},
|
|
1);
|
|
} else if (component == "is_player") {
|
|
lua_pushvalue(L, 1);
|
|
lua_pushcclosure(
|
|
L,
|
|
[](lua_State *L) -> int {
|
|
luaL_checktype(L, lua_upvalueindex(1),
|
|
LUA_TUSERDATA);
|
|
LuaEcsEntity *ent = static_cast<
|
|
LuaEcsEntity *>(lua_touserdata(
|
|
L, lua_upvalueindex(1)));
|
|
lua_pushboolean(L,
|
|
ent->e.has<Player>());
|
|
return 1;
|
|
},
|
|
1);
|
|
} else
|
|
lua_pushnil(L);
|
|
return 1;
|
|
});
|
|
lua_settable(L, -3);
|
|
}
|
|
|
|
LuaData::~LuaData()
|
|
{
|
|
lua_close(L);
|
|
}
|
|
|
|
void LuaData::lateSetup()
|
|
{
|
|
#if 0
|
|
Ogre::DataStreamList streams =
|
|
Ogre::ResourceGroupManager::getSingleton().openResources(
|
|
"*.lua", "LuaScripts");
|
|
while (!streams.empty()) {
|
|
Ogre::DataStreamPtr s = streams.front();
|
|
std::cout << "stream: " << s->getAsString() << "\n";
|
|
streams.pop_front();
|
|
if (luaL_dostring(L, s->getAsString().c_str()) != LUA_OK) {
|
|
std::cout << "error: " << lua_tostring(L, -1) << "\n";
|
|
OgreAssert(false, "Script failure");
|
|
}
|
|
}
|
|
#endif
|
|
Ogre::DataStreamPtr stream =
|
|
Ogre::ResourceGroupManager::getSingleton().openResource(
|
|
"data.lua", "LuaScripts");
|
|
std::cout << "stream: " << stream->getAsString() << "\n";
|
|
if (luaL_dostring(L, stream->getAsString().c_str()) != LUA_OK) {
|
|
std::cout << "error: " << lua_tostring(L, -1) << "\n";
|
|
OgreAssert(false, "Script failure");
|
|
}
|
|
|
|
const char *lua_code = "\n\
|
|
function stuff()\n\
|
|
return 4\n\
|
|
end\n\
|
|
x = stuff()\n\
|
|
";
|
|
luaL_dostring(L, lua_code);
|
|
lua_getglobal(L, "x");
|
|
int x = lua_tonumber(L, 1);
|
|
std::cout << "lua: " << x << "\n";
|
|
}
|
|
|
|
LuaModule::LuaModule(flecs::world &ecs)
|
|
{
|
|
ecs.module<LuaModule>();
|
|
ecs.import <SlotsModule>();
|
|
ecs.component<LuaChildEventTrigger>();
|
|
ecs.component<LuaBase>()
|
|
.on_add([](LuaBase &lua) {
|
|
lua.mLua = new LuaData;
|
|
lua.setup_called = false;
|
|
lua.startup_called = false;
|
|
})
|
|
.add(flecs::Singleton);
|
|
ecs.component<LuaEvent>().add(flecs::Singleton);
|
|
if (!ecs.has<LuaBase>())
|
|
ecs.add<LuaBase>();
|
|
if (!ecs.has<LuaEvent>())
|
|
ecs.set<LuaEvent>({});
|
|
|
|
ecs.system<const EngineData, LuaBase>("LuaUpdate")
|
|
.kind(flecs::OnUpdate)
|
|
.each([](const EngineData &eng, LuaBase &lua) {
|
|
if (!lua.setup_called) {
|
|
lua.mLua->lateSetup();
|
|
lua.mLua->call_handler("setup");
|
|
lua.setup_called = true;
|
|
}
|
|
if (!lua.startup_called) {
|
|
if (eng.startupDelay <= 0.0f) {
|
|
lua.mLua->call_handler("startup");
|
|
lua.startup_called = true;
|
|
}
|
|
}
|
|
});
|
|
ecs.system<const EngineData, const LuaChildEventTrigger>(
|
|
"CreateChildTrigger")
|
|
.kind(flecs::OnUpdate)
|
|
.without<EventTrigger>()
|
|
.write<EventTrigger>()
|
|
.each([](flecs::entity e, const EngineData &env,
|
|
const LuaChildEventTrigger &lct) {
|
|
Ogre::SceneNode *parentNode = nullptr;
|
|
flecs::entity parent_e = lct.parent_e;
|
|
if (parent_e.has<CharacterBase>()) {
|
|
parentNode =
|
|
parent_e.get<CharacterBase>().mBodyNode;
|
|
OgreAssert(
|
|
parent_e.get<CharacterBase>().mBodyNode,
|
|
"bad node");
|
|
|
|
} else if (parent_e.has<BoatBase>()) {
|
|
parentNode = parent_e.get<BoatBase>().mNode;
|
|
OgreAssert(parent_e.get<BoatBase>().mNode,
|
|
"bad node");
|
|
} else
|
|
return;
|
|
EventTrigger &trigger = e.ensure<EventTrigger>();
|
|
OgreAssert(parentNode, "bad parent");
|
|
trigger.position = lct.position;
|
|
trigger.halfheight = lct.halfheight;
|
|
trigger.radius = lct.radius;
|
|
trigger.event = lct.event;
|
|
trigger.parent = parentNode;
|
|
e.modified<EventTrigger>();
|
|
});
|
|
ecs.system<LuaBase, LuaEvent>("HandleLuaEvents")
|
|
.kind(flecs::OnUpdate)
|
|
.each([](LuaBase &base, LuaEvent &evt) {
|
|
while (!evt.events.empty()) {
|
|
LuaEvent::Event &ev = evt.events.front();
|
|
base.mLua->call_handler(ev.event, ev.e1, ev.e2);
|
|
evt.events.pop_front();
|
|
}
|
|
});
|
|
}
|
|
} |