Intagrated Tracy, debugged animations

This commit is contained in:
2026-02-12 14:00:05 +03:00
parent 7947690e80
commit 74a1adfb27
25 changed files with 1553 additions and 2109 deletions

View File

@@ -7,6 +7,7 @@
#include "CharacterModule.h"
#include "items.h"
#include "CharacterAIModule.h"
#include <tracy/Tracy.hpp>
namespace ECS
{
struct ActionExec {
@@ -231,7 +232,6 @@ public:
Ogre::Vector3 direction =
(targetPosition - npc.position).normalisedCopy();
targetPosition -= direction * radius;
std::cout << action->get_name();
}
public:
@@ -245,21 +245,20 @@ public:
private:
int update(float delta) override
{
OgreAssert(false, "update");
return OK;
}
void finish(int rc) override
{
if (rc == OK)
bb.apply(action->effects);
OgreAssert(false, "finish");
}
void activate() override
{
std::cout << action->get_name();
const ActionNodeActions::RunActionNode *runaction =
static_cast<const ActionNodeActions::RunActionNode
*>(action);
if (runaction)
std::cout << "Is Run" << std::endl;
OgreAssert(false, "activate");
}
@@ -329,14 +328,32 @@ public:
jactionPrereq["is_seated"] = 0;
jactionEffect["is_seated"] = 1;
} else if (action == "use") {
if (props["tags"].find("toilet") !=
props["tags"].end()) {
std::cout << "toilet" << std::endl;
OgreAssert(false, "props: " + props.dump(4));
OgreAssert(props["tags"].is_array(), "bad formed tags");
const nlohmann::json &tags = props["tags"];
if (tags.size() == 1 &&
tags[0].get<Ogre::String>() == "") {
} else {
std::cout << "use: " << props.dump(4)
<< std::endl;
// OgreAssert(false, "props: " + props.dump(4));
bool have_bits = false;
if (std::find(tags.begin(), tags.end(),
"dance-pole") != tags.end()) {
jactionPrereq["is_pole_dancing"] = 0;
jactionEffect["is_pole_dancing"] = 1;
have_bits = true;
}
if (std::find(tags.begin(), tags.end(),
"toilet") != tags.end()) {
jactionPrereq["toilet"] = 1;
jactionEffect["toilet"] = 0;
have_bits = true;
}
if (!have_bits) {
std::cout << "use: " << props.dump(4)
<< std::endl;
// OgreAssert(false, "props: " + props.dump(4));
OgreAssert(tags.size() == 0,
"Some tags: " +
props.dump(4));
}
}
} else {
OgreAssert(false, "props: " + props.dump(4));
@@ -363,27 +380,32 @@ public:
};
struct ActionExecCommon : ActionExec {
private:
float delay;
int update(float delta) override
{
std::cout << "running: " << action->get_name() << std::endl;
return OK;
delay -= delta;
if (delay > 0.0f)
return BUSY;
else
return OK;
}
void finish(int rc) override
{
if (rc == OK)
bb.apply(action->effects);
std::cout << "finish: " << action->get_name() << std::endl;
}
void activate() override
{
std::cout << action->get_name();
std::cout << "!";
delay = 1.0f;
}
public:
ActionExecCommon(ActionExec::PlanExecData &data,
goap::BaseAction<Blackboard> *action)
: ActionExec(data, action)
, delay(0.0f)
{
}
};
@@ -439,20 +461,30 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
{ "thirsty", 1 } } },
{ { { "thirsty", 0 } } },
10 },
#if 0
{ "DrinkWater",
{ { { "have_water", 1 }, { "thirsty", 1 } } },
{ { { "have_water", 1 },
{ "thirsty", 1 },
{ "is_seated", 0 } } },
{ { { "thirsty", 0 } } },
2000 },
#endif
{ "EatMedicine",
{ { { "have_medicine", 1 }, { "healthy", 0 } } },
{ "EatMedicineSeated",
{ { { "have_medicine", 1 },
{ "healthy", 0 },
{ "is_seated", 1 } } },
{ { { "healthy", 1 } } },
100 },
{ "EatMedicine",
{ { { "have_medicine", 1 },
{ "healthy", 0 },
{ "is_seated", 0 } } },
{ { { "healthy", 1 } } },
10000 },
#if 0
{ "UseToilet",
{ { { "toilet", 1 } } },
{ { { "toilet", 0 } } },
100 },
#endif
{ "GetFood",
{ { { "have_food", 0 } } },
{ { { "have_food", 1 } } },
@@ -478,25 +510,15 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
.kind(flecs::OnUpdate)
.each([this](flecs::entity town, TownAI &ai,
const TownNPCs &npcs) {
Ogre::Root::getSingleton().getWorkQueue()->addTask(
[this, town, npcs, &ai]() {
Ogre::Root::getSingleton()
.getWorkQueue()
->addMainThreadTask([this, town,
npcs,
&ai]() {
std::lock_guard<
std::mutex>
lock(ecs_mutex);
createBlackboards(
town, npcs, ai);
});
});
ZoneScopedN("CreateBlackboards");
std::lock_guard<std::mutex> lock(ecs_mutex);
createBlackboards(town, npcs, ai);
});
ecs.system<ActionNodeList, TownAI, TownNPCs>("UpdateDynamicActions")
.kind(flecs::OnUpdate)
.each([](flecs::entity e, ActionNodeList &alist, TownAI &ai,
TownNPCs &npcs) {
ZoneScopedN("UpdateDynamicActions");
std::lock_guard<std::mutex> lock(ecs_mutex);
if (ai.nodeActions.size() > 0)
return;
@@ -527,12 +549,31 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
.interval(0.1f)
.each([this](flecs::entity town, ActionNodeList &alist,
TownAI &ai, TownNPCs &npcs) {
ZoneScopedN("UpdateDynamicNodes");
std::lock_guard<std::mutex> lock(ecs_mutex);
ECS::get_mut<ActionNodeList>().updateDynamicNodes();
});
struct MeasureTime {
std::chrono::system_clock::time_point start;
std::string what;
MeasureTime(const std::string &s)
: start(std::chrono::high_resolution_clock::now())
, what(s)
{
}
~MeasureTime()
{
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<float, std::milli> elapsed =
end - start;
std::cout << what << " " << elapsed.count()
<< std::endl;
}
};
ecs.system<TownNPCs>("UpdateNPCPositions")
.kind(flecs::OnUpdate)
.each([](flecs::entity e, TownNPCs &npcs) {
ZoneScopedN("UpdateNPCPositions");
for (auto it = npcs.npcs.begin(); it != npcs.npcs.end();
it++) {
auto &npc = npcs.npcs.at(it->first);
@@ -549,49 +590,62 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
.interval(0.1f)
.each([this](flecs::entity town, ActionNodeList &alist,
TownAI &ai, const TownNPCs &npcs) {
Ogre::Root::getSingleton().getWorkQueue()->addTask(
[this, town, &alist, npcs, &ai]() {
{
std::lock_guard<std::mutex> lock(
ecs_mutex);
ZoneScopedN("UpdateBlackboards");
updateBlackboards(town, alist,
npcs, ai);
}
Ogre::Root::getSingleton()
.getWorkQueue()
->addMainThreadTask([this, town,
&alist]() {
town.modified<TownAI>();
town.modified<TownNPCs>();
ECS::modified<
ActionNodeList>();
});
});
Ogre::Root::getSingleton().getWorkQueue()->addTask([this,
town,
&alist,
npcs,
&ai]() {
{
std::lock_guard<std::mutex> lock(
ecs_mutex);
ZoneScopedN(
"UpdateBlackboards::Thread");
updateBlackboards(town, alist, npcs,
ai);
}
Ogre::Root::getSingleton()
.getWorkQueue()
->addMainThreadTask([this, town,
&alist]() {
ZoneScopedN(
"UpdateBlackboards::MainThread");
town.modified<TownAI>();
town.modified<TownNPCs>();
ECS::modified<ActionNodeList>();
});
});
});
ecs.system<TownAI, TownNPCs>("PlanAI")
.kind(flecs::OnUpdate)
.interval(0.5f)
.each([&](flecs::entity town, TownAI &ai,
const TownNPCs &npcs) {
Ogre::Root::getSingleton().getWorkQueue()->addTask(
[this, town, npcs, &ai]() {
std::lock_guard<std::mutex> lock(
ecs_mutex);
buildPlans(town, npcs, ai);
Ogre::Root::getSingleton()
.getWorkQueue()
->addMainThreadTask([this,
town]() {
town.modified<TownAI>();
});
});
ZoneScopedN("PlanAI");
Ogre::Root::getSingleton().getWorkQueue()->addTask([this,
town,
npcs,
&ai]() {
ZoneScopedN("PlanAI::Thread");
std::lock_guard<std::mutex> lock(ecs_mutex);
buildPlans(town, npcs, ai);
Ogre::Root::getSingleton()
.getWorkQueue()
->addMainThreadTask([this, town]() {
ZoneScopedN(
"PlanAI::MainThread");
town.modified<TownAI>();
});
});
});
static std::unordered_map<int, struct PlanExec> plan_exec;
ecs.system<const EngineData, TownNPCs, TownAI>("RunPLAN")
.kind(flecs::OnUpdate)
.each([&](flecs::entity town, const EngineData &eng,
TownNPCs &npcs, TownAI &ai) {
ZoneScopedN("RunPLAN");
for (const auto &plans : ai.plans) {
if (plan_exec.find(plans.first) !=
plan_exec.end()) {
@@ -758,6 +812,7 @@ void CharacterAIModule::buildPlans(flecs::entity town, const TownNPCs &npcs,
void CharacterAIModule::createBlackboards(flecs::entity town,
const TownNPCs &npcs, TownAI &ai)
{
ZoneScopedN("createBlackboards");
OgreAssert(town.is_valid(), "Bad town entity");
std::lock_guard<std::mutex> lock(*ai.mutex);
for (auto it = npcs.npcs.begin(); it != npcs.npcs.end(); it++) {
@@ -871,6 +926,7 @@ void CharacterAIModule::updateBlackboards(flecs::entity town,
ActionNodeList &alist,
const TownNPCs &npcs, TownAI &ai)
{
ZoneScopedN("updateBlackboards");
std::lock_guard<std::mutex> lock(*ai.mutex);
OgreAssert(town.is_valid(), "Bad town entity");
alist.build();
@@ -1124,7 +1180,8 @@ void Blackboard::query_ai()
const TownNPCs &npcs = town.get<TownNPCs>();
const float distance = 10000.0f;
Ogre::Vector3 position(0, 0, 0);
if (npcs.npcs.at(index).e.is_valid())
if (npcs.npcs.at(index).e.is_valid() &&
npcs.npcs.at(index).e.has<CharacterBase>())
position = npcs.npcs.at(index)
.e.get<CharacterBase>()
.mBodyNode->_getDerivedPosition();