Threads and tasks
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <iostream>
|
||||
#include <flecs.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <lua.hpp>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "CharacterManagerModule.h"
|
||||
@@ -181,6 +182,33 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
|
||||
},
|
||||
1);
|
||||
lua_setfield(L, -2, "_get_properties");
|
||||
lua_pushlightuserdata(L, this);
|
||||
lua_pushcclosure(
|
||||
L,
|
||||
[](lua_State *L) {
|
||||
LuaNarrationHandler *handler =
|
||||
static_cast<LuaNarrationHandler *>(
|
||||
lua_touserdata(
|
||||
L,
|
||||
lua_upvalueindex(1)));
|
||||
lua_pushstring(
|
||||
L, handler->getProperties().c_str());
|
||||
const std::vector<ActionNodeList::ActionNode>
|
||||
&nodes = ECS::get<ActionNodeList>()
|
||||
.dynamicNodes;
|
||||
lua_newtable(L);
|
||||
int i;
|
||||
for (i = 0; i < nodes.size(); i++) {
|
||||
lua_pushinteger(L, i + 1);
|
||||
lua_pushstring(
|
||||
L,
|
||||
nodes[i].props.dump().c_str());
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
return 1;
|
||||
},
|
||||
1);
|
||||
lua_setfield(L, -2, "_get_goals");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
void finish() override
|
||||
@@ -231,7 +259,7 @@ struct SimpleWordHandler : PlayerActionModule::ActionWordHandler {
|
||||
const TownNPCs::NPCData &npc =
|
||||
town.get<TownNPCs>().npcs.at(index);
|
||||
flecs::entity e = npc.e;
|
||||
for (const auto &anode : e.get<NPCActionNodes>().anodes) {
|
||||
for (const auto &anode : npc.actionNodes) {
|
||||
if (anode.action == word) {
|
||||
nlohmann::json props = anode.props;
|
||||
props["initiator"] =
|
||||
@@ -254,17 +282,18 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs)
|
||||
ecs.import <CharacterManagerModule>();
|
||||
ecs.component<ActionNodeList>()
|
||||
.on_add([](flecs::entity e, ActionNodeList &alist) {
|
||||
alist.dirty = true;
|
||||
alist.nodeMutex = std::make_shared<std::mutex>();
|
||||
alist.setDirty();
|
||||
alist.nodes.reserve(1000);
|
||||
alist.dynamicNodes.reserve(1000);
|
||||
alist.selected = -1;
|
||||
alist.busy = false;
|
||||
alist.setUISelected(-1);
|
||||
alist.setReady();
|
||||
})
|
||||
.add(flecs::Singleton);
|
||||
ecs.system<ActionNodeList>("updateNodeList")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([](ActionNodeList &list) {
|
||||
if (list.busy)
|
||||
if (list.isBusy())
|
||||
return;
|
||||
if (list.nodes.size() > 0) {
|
||||
Ogre::SceneNode *cameraNode =
|
||||
@@ -279,49 +308,55 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs)
|
||||
player.get<CharacterBase>()
|
||||
.mBodyNode
|
||||
->_getDerivedPosition();
|
||||
list.query(playerPos, list.points,
|
||||
list.distances);
|
||||
list.UIquery(playerPos);
|
||||
} else {
|
||||
list.query(cameraPos, list.points,
|
||||
list.distances);
|
||||
list.UIquery(cameraPos);
|
||||
}
|
||||
}
|
||||
});
|
||||
ecs.system<ActionNodeList, const Input>("ActivateActionNode")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([this](ActionNodeList &list, const Input &input) {
|
||||
std::lock_guard<std::mutex> lock(*list.nodeMutex);
|
||||
if (input.control & 32)
|
||||
std::cout << "act pressed" << std::endl;
|
||||
if (list.busy)
|
||||
if (list.isBusy())
|
||||
return;
|
||||
if (input.act_pressed && list.selected >= 0) {
|
||||
std::cout << list.dynamicNodes[list.selected]
|
||||
.props.dump(4)
|
||||
<< std::endl;
|
||||
if (input.act_pressed &&
|
||||
list.getUIData().selected >= 0) {
|
||||
std::cout
|
||||
<< list.dynamicNodes[list.getUIData()
|
||||
.selected]
|
||||
.props.dump(4)
|
||||
<< std::endl;
|
||||
flecs::entity_t townid =
|
||||
list.dynamicNodes[list.selected]
|
||||
list.dynamicNodes[list.getUIData()
|
||||
.selected]
|
||||
.props["town"]
|
||||
.get<flecs::entity_t>();
|
||||
flecs::entity town = ECS::get().entity(townid);
|
||||
int index = list.dynamicNodes[list.selected]
|
||||
int index = list.dynamicNodes[list.getUIData()
|
||||
.selected]
|
||||
.props["index"]
|
||||
.get<int>();
|
||||
for (auto it = actionWords.begin();
|
||||
it != actionWords.end(); it++) {
|
||||
if (it->first ==
|
||||
list.dynamicNodes[list.selected]
|
||||
list.dynamicNodes[list.getUIData()
|
||||
.selected]
|
||||
.action) {
|
||||
(*it->second)(
|
||||
town, index,
|
||||
list.dynamicNodes
|
||||
[list.selected]
|
||||
[list.getUIData()
|
||||
.selected]
|
||||
.action);
|
||||
list.busy = true;
|
||||
list.setBusy();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ECS::get<GUI>().enabled)
|
||||
list.busy = false;
|
||||
list.setReady();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -367,8 +402,7 @@ struct LuaWordHandler : PlayerActionModule::ActionWordHandler {
|
||||
const TownNPCs::NPCData &npc =
|
||||
town.get<TownNPCs>().npcs.at(index);
|
||||
flecs::entity e = npc.e;
|
||||
for (const auto &anode :
|
||||
e.get<NPCActionNodes>().anodes) {
|
||||
for (const auto &anode : npc.actionNodes) {
|
||||
if (anode.action == word) {
|
||||
nlohmann::json props = anode.props;
|
||||
props["initiator"] =
|
||||
@@ -426,27 +460,41 @@ int PlayerActionModule::setupLuaActionHandler(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ActionNodeList::updateDynamicNodes()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*nodeMutex);
|
||||
if (dynamicNodes.size() > nodes.size())
|
||||
dynamicNodes.resize(nodes.size());
|
||||
else {
|
||||
dynamicNodes.clear();
|
||||
dynamicNodes.insert(dynamicNodes.end(), nodes.begin(),
|
||||
nodes.end());
|
||||
}
|
||||
ECS::get().query_builder<const TownNPCs>().each(
|
||||
[this](flecs::entity town, const TownNPCs &npcs) {
|
||||
for (auto it = npcs.npcs.begin(); it != npcs.npcs.end();
|
||||
it++) {
|
||||
dynamicNodes.insert(
|
||||
dynamicNodes.end(),
|
||||
it->second.actionNodes.begin(),
|
||||
it->second.actionNodes.end());
|
||||
}
|
||||
});
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void ActionNodeList::build()
|
||||
{
|
||||
dynamicNodes.clear();
|
||||
dynamicNodes.insert(dynamicNodes.end(), nodes.begin(), nodes.end());
|
||||
ECS::get().query_builder<const NPCActionNodes>().each(
|
||||
[&](flecs::entity e, const NPCActionNodes &anodes) {
|
||||
dynamicNodes.insert(dynamicNodes.end(),
|
||||
anodes.anodes.begin(),
|
||||
anodes.anodes.end());
|
||||
});
|
||||
|
||||
std::lock_guard<std::mutex> lock(*nodeMutex);
|
||||
indexObj = std::make_shared<ActionNodeList::indexObject>(dynamicNodes);
|
||||
indexObj->index.buildIndex();
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
bool ActionNodeList::query(const Ogre::Vector3 &position,
|
||||
std::vector<size_t> &points,
|
||||
std::vector<float> &distances)
|
||||
bool ActionNodeList::_query(const Ogre::Vector3 &position,
|
||||
std::vector<size_t> &points,
|
||||
std::vector<float> &distances)
|
||||
{
|
||||
build();
|
||||
std::vector<size_t> tmppoints;
|
||||
std::vector<float> tmpdistances;
|
||||
points.clear();
|
||||
@@ -455,6 +503,10 @@ bool ActionNodeList::query(const Ogre::Vector3 &position,
|
||||
distances.reserve(4);
|
||||
tmppoints.resize(4);
|
||||
tmpdistances.resize(4);
|
||||
if (!indexObj) {
|
||||
dirty = true;
|
||||
return false;
|
||||
}
|
||||
nanoflann::KNNResultSet<float> resultSet(4);
|
||||
resultSet.init(tmppoints.data(), tmpdistances.data());
|
||||
bool ret = indexObj->index.findNeighbors(resultSet, &position.x,
|
||||
@@ -467,4 +519,108 @@ bool ActionNodeList::query(const Ogre::Vector3 &position,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ActionNodeList::query_ai(const Ogre::Vector3 &position, float distance,
|
||||
std::vector<size_t> &points,
|
||||
std::vector<float> &distances)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*nodeMutex);
|
||||
std::vector<size_t> tmppoints;
|
||||
std::vector<float> tmpdistances;
|
||||
points.clear();
|
||||
points.reserve(100);
|
||||
distances.clear();
|
||||
distances.reserve(100);
|
||||
tmppoints.resize(100);
|
||||
tmpdistances.resize(100);
|
||||
if (!indexObj) {
|
||||
dirty = true;
|
||||
return false;
|
||||
}
|
||||
nanoflann::KNNResultSet<float> resultSet(100);
|
||||
resultSet.init(tmppoints.data(), tmpdistances.data());
|
||||
bool ret = indexObj->index.findNeighbors(resultSet, &position.x,
|
||||
nanoflann::SearchParameters());
|
||||
int i;
|
||||
for (i = 0; i < resultSet.size(); i++)
|
||||
if (tmpdistances[i] < distance) {
|
||||
points.push_back(tmppoints[i]);
|
||||
distances.push_back(tmpdistances[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ActionNodeList::addNode(ActionNode &node)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*nodeMutex);
|
||||
int index = nodes.size();
|
||||
nodes.push_back(node);
|
||||
dirty = true;
|
||||
return index;
|
||||
}
|
||||
|
||||
void ActionNodeList::removeNode(int index)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*nodeMutex);
|
||||
nodes.erase(nodes.begin() + index);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
const ActionNodeList::UIData &ActionNodeList::getUIData()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*uidata.mutex);
|
||||
return uidata;
|
||||
}
|
||||
|
||||
void ActionNodeList::setUISelected(int selected)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*uidata.mutex);
|
||||
|
||||
uidata.selected = selected;
|
||||
}
|
||||
|
||||
void ActionNodeList::setUIPoints(const std::vector<size_t> &points,
|
||||
const std::vector<float> &distances)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*uidata.mutex);
|
||||
uidata.points = points;
|
||||
uidata.distances = distances;
|
||||
}
|
||||
|
||||
void ActionNodeList::UIquery(const Ogre::Vector3 &position)
|
||||
{
|
||||
bool needBuild = false;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*nodeMutex);
|
||||
if (dirty || !indexObj)
|
||||
needBuild = true;
|
||||
}
|
||||
if (needBuild)
|
||||
build();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*uidata.mutex);
|
||||
_query(position, uidata.points, uidata.distances);
|
||||
}
|
||||
}
|
||||
|
||||
void ActionNodeList::setDirty()
|
||||
{
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void ActionNodeList::setReady()
|
||||
{
|
||||
busy = false;
|
||||
}
|
||||
|
||||
void ActionNodeList::setBusy()
|
||||
{
|
||||
busy = true;
|
||||
}
|
||||
|
||||
bool ActionNodeList::isBusy()
|
||||
{
|
||||
return busy;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user