Fixed AIs and crashes
This commit is contained in:
@@ -387,14 +387,22 @@ public:
|
||||
}
|
||||
void locateResources() override
|
||||
{
|
||||
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
|
||||
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
|
||||
"Characters", true);
|
||||
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
|
||||
"Water", true);
|
||||
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
|
||||
"LuaScripts", false);
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
"./lua-scripts", "FileSystem", "LuaScripts", true,
|
||||
true);
|
||||
OgreBites::ApplicationContext::locateResources();
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
"./characters/male", "FileSystem", "Characters", false,
|
||||
true);
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
"./characters/female", "FileSystem", "Characters",
|
||||
false, true);
|
||||
OgreBites::ApplicationContext::locateResources();
|
||||
}
|
||||
void loadResources() override
|
||||
{
|
||||
|
||||
@@ -271,6 +271,7 @@ public:
|
||||
};
|
||||
ActionNodeActions(int node, const Blackboard &prereq, int cost)
|
||||
{
|
||||
ZoneScoped;
|
||||
OgreAssert(
|
||||
node < ECS::get<ActionNodeList>().dynamicNodes.size(),
|
||||
"bad node " + Ogre::StringConverter::toString(node));
|
||||
@@ -347,6 +348,7 @@ public:
|
||||
have_bits = true;
|
||||
}
|
||||
if (!have_bits) {
|
||||
ZoneScopedN("Use");
|
||||
std::cout << "use: " << props.dump(4)
|
||||
<< std::endl;
|
||||
// OgreAssert(false, "props: " + props.dump(4));
|
||||
@@ -396,8 +398,8 @@ private:
|
||||
}
|
||||
void activate() override
|
||||
{
|
||||
std::cout << action->get_name();
|
||||
std::cout << "!";
|
||||
ZoneScoped;
|
||||
ZoneTextF("%s", action->get_name().c_str());
|
||||
delay = 1.0f;
|
||||
}
|
||||
|
||||
@@ -414,6 +416,7 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
static std::mutex ecs_mutex;
|
||||
ecs.module<CharacterAIModule>();
|
||||
ecs.import <CharacterManagerModule>();
|
||||
ecs.import <PlayerActionModule>();
|
||||
ecs.component<Blackboard>();
|
||||
ecs.component<TownAI>().on_add([](flecs::entity e, TownAI &ai) {
|
||||
std::lock_guard<std::mutex> lock(ecs_mutex);
|
||||
@@ -512,6 +515,7 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
const TownNPCs &npcs) {
|
||||
ZoneScopedN("CreateBlackboards");
|
||||
std::lock_guard<std::mutex> lock(ecs_mutex);
|
||||
OgreAssert(npcs.npcs.size() > 0, "npcs not crated");
|
||||
createBlackboards(town, npcs, ai);
|
||||
});
|
||||
ecs.system<ActionNodeList, TownAI, TownNPCs>("UpdateDynamicActions")
|
||||
@@ -520,11 +524,15 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
TownNPCs &npcs) {
|
||||
ZoneScopedN("UpdateDynamicActions");
|
||||
std::lock_guard<std::mutex> lock(ecs_mutex);
|
||||
OgreAssert(npcs.npcs.size() > 0, "npcs not crated");
|
||||
if (ai.nodeActions.size() > 0)
|
||||
return;
|
||||
if (alist.dynamicNodes.size() == 0)
|
||||
ECS::get_mut<ActionNodeList>()
|
||||
.updateDynamicNodes();
|
||||
OgreAssert(alist.nodes.size() > 0, "bad nodes");
|
||||
if (alist.dynamicNodes.size() == 0)
|
||||
return;
|
||||
OgreAssert(alist.dynamicNodes.size() > 0,
|
||||
"bad dynamic nodes");
|
||||
int nodeIndex;
|
||||
@@ -550,6 +558,7 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
.each([this](flecs::entity town, ActionNodeList &alist,
|
||||
TownAI &ai, TownNPCs &npcs) {
|
||||
ZoneScopedN("UpdateDynamicNodes");
|
||||
OgreAssert(npcs.npcs.size() > 0, "npcs not crated");
|
||||
std::lock_guard<std::mutex> lock(ecs_mutex);
|
||||
ECS::get_mut<ActionNodeList>().updateDynamicNodes();
|
||||
});
|
||||
@@ -574,6 +583,7 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([](flecs::entity e, TownNPCs &npcs) {
|
||||
ZoneScopedN("UpdateNPCPositions");
|
||||
OgreAssert(npcs.npcs.size() > 0, "npcs not crated");
|
||||
for (auto it = npcs.npcs.begin(); it != npcs.npcs.end();
|
||||
it++) {
|
||||
auto &npc = npcs.npcs.at(it->first);
|
||||
@@ -591,6 +601,7 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
.each([this](flecs::entity town, ActionNodeList &alist,
|
||||
TownAI &ai, const TownNPCs &npcs) {
|
||||
ZoneScopedN("UpdateBlackboards");
|
||||
OgreAssert(npcs.npcs.size() > 0, "npcs not crated");
|
||||
|
||||
Ogre::Root::getSingleton().getWorkQueue()->addTask([this,
|
||||
town,
|
||||
@@ -624,6 +635,10 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
.each([&](flecs::entity town, TownAI &ai,
|
||||
const TownNPCs &npcs) {
|
||||
ZoneScopedN("PlanAI");
|
||||
OgreAssert(npcs.npcs.size() > 0, "npcs not crated");
|
||||
OgreAssert(ai.blackboards.size() > 0,
|
||||
"blackboards not crated");
|
||||
OgreAssert(ai.memory.size() > 0, "memory not crated");
|
||||
Ogre::Root::getSingleton().getWorkQueue()->addTask([this,
|
||||
town,
|
||||
npcs,
|
||||
@@ -646,6 +661,10 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
.each([&](flecs::entity town, const EngineData &eng,
|
||||
TownNPCs &npcs, TownAI &ai) {
|
||||
ZoneScopedN("RunPLAN");
|
||||
OgreAssert(npcs.npcs.size() > 0, "npcs not crated");
|
||||
OgreAssert(ai.blackboards.size() > 0,
|
||||
"blackboards not crated");
|
||||
OgreAssert(ai.memory.size() > 0, "memory not crated");
|
||||
for (const auto &plans : ai.plans) {
|
||||
if (plan_exec.find(plans.first) !=
|
||||
plan_exec.end()) {
|
||||
@@ -668,13 +687,19 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
// std::cout << " Goal: ";
|
||||
plan.goal->goal.dump_bits();
|
||||
for (const auto &action : plan.plan) {
|
||||
ActionExec::PlanExecData data({
|
||||
TownNPCs::NPCData &npc =
|
||||
npcs.npcs.at(
|
||||
plans.first),
|
||||
plans.first);
|
||||
Blackboard &bb =
|
||||
ai.blackboards.at(
|
||||
plans.first),
|
||||
plans.first);
|
||||
nlohmann::json &mem =
|
||||
ai.memory.at(
|
||||
plans.first),
|
||||
plans.first);
|
||||
ActionExec::PlanExecData data({
|
||||
npc,
|
||||
bb,
|
||||
mem,
|
||||
|
||||
});
|
||||
// TODO: executor factory is needed
|
||||
@@ -773,19 +798,26 @@ void CharacterAIModule::buildPlans(flecs::entity town, const TownNPCs &npcs,
|
||||
if (plan_tasks.size() > 0) {
|
||||
bool created = (plan_tasks.front())();
|
||||
if (created) {
|
||||
std::cout << plan_tasks.front().blackboard.index << " ";
|
||||
std::cout << "Goal: "
|
||||
<< plan_tasks.front().goal.get_name();
|
||||
plan_tasks.front().goal.goal.dump_bits();
|
||||
std::cout << std::endl;
|
||||
std::cout << "Path: ";
|
||||
for (auto &action : plan_tasks.front().plan.plan) {
|
||||
OgreAssert(action, "No action");
|
||||
std::cout << action->get_name() + " ";
|
||||
ZoneTextF("%d: Goal: %s",
|
||||
plan_tasks.front().blackboard.index,
|
||||
plan_tasks.front().goal.get_name().c_str());
|
||||
{
|
||||
std::cout << plan_tasks.front().blackboard.index
|
||||
<< " ";
|
||||
std::cout << "Goal: "
|
||||
<< plan_tasks.front().goal.get_name();
|
||||
plan_tasks.front().goal.goal.dump_bits();
|
||||
std::cout << std::endl;
|
||||
std::cout << "Path: ";
|
||||
for (auto &action :
|
||||
plan_tasks.front().plan.plan) {
|
||||
OgreAssert(action, "No action");
|
||||
std::cout << action->get_name() + " ";
|
||||
}
|
||||
std::cout << " size: "
|
||||
<< plan_tasks.front().plan.plan.size()
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << " size: "
|
||||
<< plan_tasks.front().plan.plan.size()
|
||||
<< std::endl;
|
||||
ai.plans[plan_tasks.front().blackboard.index].push_back(
|
||||
plan_tasks.front().plan);
|
||||
}
|
||||
|
||||
@@ -88,12 +88,12 @@ void createNPCActionNodes(flecs::entity town, int index)
|
||||
CharacterManagerModule::CharacterManagerModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<CharacterManagerModule>();
|
||||
ecs.import <CharacterModule>();
|
||||
ecs.component<TownNPCs>();
|
||||
ecs.import <CharacterModule>();
|
||||
ecs.import <CharacterAnimationModule>();
|
||||
ecs.import <PhysicsModule>();
|
||||
ecs.import <PlayerActionModule>();
|
||||
ecs.component<TownCharacterHolder>();
|
||||
ecs.component<TownNPCs>();
|
||||
ecs.component<LivesIn>();
|
||||
ecs.system<TerrainItem, TownNPCs>("UpdateCharacters")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -178,15 +178,17 @@ CharacterManagerModule::createPlayer(const Ogre::Vector3 &position,
|
||||
OgreAssert(!player.is_valid(), "Player already created");
|
||||
player = ECS::get().entity("player");
|
||||
OgreAssert(player.is_valid(), "Can't create player");
|
||||
std::cout << "Begin player create" << std::endl;
|
||||
player.add<Player>();
|
||||
ECS::get_mut<CharacterModule>().createCharacter(
|
||||
player, position, rotation, "male_Face.mesh",
|
||||
"male_Hair001.mesh", "male_BodyTop.mesh",
|
||||
"male_BodyBottom.mesh", "male_BodyFeet.mesh");
|
||||
ECS::modified<CharacterModule>();
|
||||
std::cout << "End player create" << std::endl;
|
||||
count++;
|
||||
{
|
||||
ZoneScopedN("PlayerCreate");
|
||||
|
||||
player.add<Player>();
|
||||
ECS::get_mut<CharacterModule>().createCharacter(
|
||||
player, position, rotation, "male_Face.mesh",
|
||||
"male_Hair001.mesh", "male_BodyTop.mesh",
|
||||
"male_BodyBottom.mesh", "male_BodyFeet.mesh");
|
||||
ECS::modified<CharacterModule>();
|
||||
count++;
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
@@ -221,41 +223,33 @@ void CharacterManagerModule::registerTownCharacters(flecs::entity town)
|
||||
nlohmann::json npcs = nlohmann::json::array();
|
||||
if (town.has<TownNPCs>())
|
||||
return;
|
||||
if (j.find("npcs") != j.end())
|
||||
npcs = j["npcs"];
|
||||
if (j.find("npcs") == j.end())
|
||||
return;
|
||||
npcs = j["npcs"];
|
||||
std::cout << npcs.dump(4) << std::endl;
|
||||
if (npcs.size() == 0)
|
||||
return;
|
||||
int index = 0;
|
||||
std::map<int, TownNPCs::NPCData> npcMap;
|
||||
for (auto &npc : npcs) {
|
||||
struct desc {
|
||||
const char *face, *hair, *top, *bottom, *feet;
|
||||
};
|
||||
struct desc models[] = {
|
||||
{ "male_Face.mesh", "male_Hair001.mesh",
|
||||
"male_BodyTop.mesh", "male_BodyBottom.mesh",
|
||||
"male_BodyFeet.mesh" },
|
||||
{ "female_Face.mesh", "female_Hair001.mesh",
|
||||
"female_BodyTop.mesh", "female_BodyBottom.mesh",
|
||||
"female_BodyFeet.mesh" }
|
||||
};
|
||||
int sex = npc["sex"].get<int>();
|
||||
Ogre::Vector3 npcPosition;
|
||||
Ogre::Quaternion npcOrientation;
|
||||
from_json(npc["position"], npcPosition);
|
||||
from_json(npc["orientation"], npcOrientation);
|
||||
TownNPCs::NPCData npcData;
|
||||
npcData.e = flecs::entity();
|
||||
npcData.modelFace = models[sex].face;
|
||||
npcData.modelHair = models[sex].hair;
|
||||
npcData.modelTop = models[sex].top;
|
||||
npcData.modelBottom = models[sex].bottom;
|
||||
npcData.modelFeet = models[sex].feet;
|
||||
npcData.modelFace = npc["slot_face"].get<Ogre::String>();
|
||||
npcData.modelHair = npc["slot_hair"].get<Ogre::String>();
|
||||
npcData.modelTop = npc["slot_top"].get<Ogre::String>();
|
||||
npcData.modelBottom = npc["slot_bottom"].get<Ogre::String>();
|
||||
npcData.modelFeet = npc["slot_feet"].get<Ogre::String>();
|
||||
npcData.orientation = npcOrientation;
|
||||
npcData.position = npcPosition;
|
||||
npcData.props = npc;
|
||||
npcMap[index] = npcData;
|
||||
index++;
|
||||
}
|
||||
OgreAssert(npcMap.size() > 0, "no npcs registered");
|
||||
town.set<TownNPCs>({ npcMap });
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,53 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
{
|
||||
ZoneScoped;
|
||||
struct TriggerPhysicsChange {};
|
||||
ecs.module<CharacterModule>();
|
||||
static std::vector<Ogre::String> part_names;
|
||||
const std::vector<Ogre::String> &groups =
|
||||
Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
|
||||
if (part_names.size() == 0) {
|
||||
int i;
|
||||
for (i = 0; i < groups.size(); i++) {
|
||||
std::vector<Ogre::String> names =
|
||||
*Ogre::ResourceGroupManager::getSingleton()
|
||||
.findResourceNames(groups[i],
|
||||
"body_part_*.json");
|
||||
part_names.insert(part_names.end(), names.begin(),
|
||||
names.end());
|
||||
}
|
||||
}
|
||||
body_parts = nlohmann::json::object();
|
||||
for (auto &g : part_names) {
|
||||
Ogre::String group = Ogre::ResourceGroupManager::getSingleton()
|
||||
.findGroupContainingResource(g);
|
||||
Ogre::DataStreamPtr stream =
|
||||
Ogre::ResourceGroupManager::getSingleton().openResource(
|
||||
g, group);
|
||||
Ogre::String json = stream->getAsString();
|
||||
nlohmann::json jdata = nlohmann::json::parse(json);
|
||||
if (jdata.find("age") == jdata.end())
|
||||
continue;
|
||||
if (jdata.find("sex") == jdata.end())
|
||||
continue;
|
||||
if (jdata.find("slot") == jdata.end())
|
||||
continue;
|
||||
if (jdata.find("mesh") == jdata.end())
|
||||
continue;
|
||||
Ogre::String age = jdata["age"].get<Ogre::String>();
|
||||
Ogre::String sex = jdata["sex"].get<Ogre::String>();
|
||||
Ogre::String slot = jdata["slot"].get<Ogre::String>();
|
||||
Ogre::String mesh = jdata["mesh"].get<Ogre::String>();
|
||||
if (body_parts.find(age) == body_parts.end())
|
||||
body_parts[age] = nlohmann::json::object();
|
||||
if (body_parts[age].find(sex) == body_parts[age].end())
|
||||
body_parts[age][sex] = nlohmann::json::object();
|
||||
if (body_parts[age][sex].find(slot) ==
|
||||
body_parts[age][sex].end())
|
||||
body_parts[age][sex][slot] = nlohmann::json::array();
|
||||
body_parts[age][sex][slot].push_back(mesh);
|
||||
Ogre::MeshManager::getSingleton().load(mesh, "Characters");
|
||||
}
|
||||
std::cout << body_parts.dump(4) << std::endl;
|
||||
ecs.module<CharacterModule>();
|
||||
ecs.component<Character>();
|
||||
ecs.component<Player>();
|
||||
ecs.component<CharacterBase>()
|
||||
@@ -701,4 +747,19 @@ void CharacterModule::remapMeshToMasterSkeleton(Ogre::MeshPtr clothMesh,
|
||||
clothMesh->setSkeletonName(masterSkel->getName());
|
||||
clothMesh->_compileBoneAssignments();
|
||||
}
|
||||
|
||||
void CharacterModule::getSlotMeshes(const Ogre::String &age,
|
||||
const Ogre::String &sex,
|
||||
const Ogre::String &slotName,
|
||||
std::vector<Ogre::String> &meshes)
|
||||
{
|
||||
OgreAssert(body_parts.find(age) != body_parts.end(), "bad age: " + age);
|
||||
OgreAssert(body_parts[age].find(sex) != body_parts[age].end(),
|
||||
"bad sex: " + sex);
|
||||
OgreAssert(body_parts[age][sex].find(slotName) !=
|
||||
body_parts[age][sex].end(),
|
||||
"bad slot: " + slotName);
|
||||
for (auto &slots : body_parts[age][sex][slotName])
|
||||
meshes.push_back(slots.get<Ogre::String>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef CHARACTER_MODULE_H_
|
||||
#define CHARACTER_MODULE_H_
|
||||
#include <flecs.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <Ogre.h>
|
||||
#include "Components.h"
|
||||
namespace ECS
|
||||
@@ -39,23 +40,36 @@ struct CharacterModule {
|
||||
void updateCameraGoal(Camera &camera, Ogre::Real deltaYaw,
|
||||
Ogre::Real deltaPitch, Ogre::Real deltaZoom);
|
||||
void createCharacter(flecs::entity e, const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation, const Ogre::String &faceModel, const Ogre::String &hairModel,
|
||||
const Ogre::String &topModel, const Ogre::String &bottomModel, const Ogre::String &feetModel);
|
||||
const Ogre::Quaternion &rotation,
|
||||
const Ogre::String &faceModel,
|
||||
const Ogre::String &hairModel,
|
||||
const Ogre::String &topModel,
|
||||
const Ogre::String &bottomModel,
|
||||
const Ogre::String &feetModel);
|
||||
std::unordered_map<flecs::entity_t, Ogre::SceneNode *> characterNodes;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Entity *> characterEntitiesFace;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Entity *> characterEntitiesHair;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Entity *>
|
||||
characterEntitiesFace;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Entity *>
|
||||
characterEntitiesHair;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Entity *> characterEntitiesTop;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Entity *> characterEntitiesBottom;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Entity *> characterEntitiesFeet;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Entity *>
|
||||
characterEntitiesBottom;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Entity *>
|
||||
characterEntitiesFeet;
|
||||
std::unordered_map<flecs::entity_t, Ogre::String> characterModelsFace;
|
||||
std::unordered_map<flecs::entity_t, Ogre::String> characterModelsHair;
|
||||
std::unordered_map<flecs::entity_t, Ogre::String> characterModelsTop;
|
||||
std::unordered_map<flecs::entity_t, Ogre::String> characterModelsBottom;
|
||||
std::unordered_map<flecs::entity_t, Ogre::String> characterModelsFeet;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Vector3> characterPositions;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Quaternion> characterOrientations;
|
||||
std::unordered_map<flecs::entity_t, Ogre::Quaternion>
|
||||
characterOrientations;
|
||||
nlohmann::json body_parts;
|
||||
void remapMeshToMasterSkeleton(Ogre::MeshPtr clothMesh,
|
||||
Ogre::MeshPtr masterMesh);
|
||||
Ogre::MeshPtr masterMesh);
|
||||
void getSlotMeshes(const Ogre::String &age, const Ogre::String &sex,
|
||||
const Ogre::String &slotName,
|
||||
std::vector<Ogre::String> &meshes);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -58,8 +58,8 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
|
||||
ecs.component<CharacterBody>().on_remove([](flecs::entity e,
|
||||
CharacterBody &body) {
|
||||
JPH::Character *ch =
|
||||
static_cast<JPH::Character *>(body.ch.get());
|
||||
std::shared_ptr<JPH::Character> ch =
|
||||
std::static_pointer_cast<JPH::Character>(body.ch);
|
||||
if (ch) {
|
||||
if (e.has<JPH::BodyID>())
|
||||
e.remove<JPH::BodyID>();
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
#include "TerrainModule.h"
|
||||
#include "physics.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "CharacterManagerModule.h"
|
||||
#include "items.h"
|
||||
#include "StaticGeometryModule.h"
|
||||
#include "CharacterAIModule.h"
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
namespace ECS
|
||||
@@ -28,6 +30,8 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
|
||||
{
|
||||
ZoneScoped;
|
||||
ecs.module<StaticGeometryModule>();
|
||||
ecs.import <CharacterManagerModule>();
|
||||
ecs.import <CharacterAIModule>();
|
||||
ecs.component<TerrainSlotParent>();
|
||||
ecs.component<TerrainItem>();
|
||||
ecs.component<FurnitureItem>();
|
||||
@@ -89,6 +93,19 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
|
||||
});
|
||||
if (!Ogre::MeshLodGenerator::getSingletonPtr())
|
||||
new Ogre::MeshLodGenerator();
|
||||
ecs.system<TerrainItem>("SetupTowns")
|
||||
.kind(flecs::OnUpdate)
|
||||
.without<TownNPCs>()
|
||||
.without<TownAI>()
|
||||
.each([&](flecs::entity e, TerrainItem &item) {
|
||||
Ogre::String props = item.properties;
|
||||
nlohmann::json jp = nlohmann::json::parse(props);
|
||||
if (jp.find("type") == jp.end())
|
||||
return;
|
||||
Ogre::String itemType = jp["type"].get<Ogre::String>();
|
||||
if (itemType == "town")
|
||||
Geometry::registerTownItem(e);
|
||||
});
|
||||
ecs.system("AddGeometryQueue").kind(flecs::OnUpdate).run([&](flecs::iter &it) {
|
||||
ZoneScopedN("AddGeometryQueue");
|
||||
std::list<flecs::entity> items;
|
||||
@@ -134,9 +151,8 @@ StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
|
||||
const TerrainItem &item) {
|
||||
items.push_back(e);
|
||||
});
|
||||
for (auto e : items) {
|
||||
for (auto e : items)
|
||||
createItemGeometry(e);
|
||||
}
|
||||
addQueue.pop_front();
|
||||
} else {
|
||||
output.push_back(item);
|
||||
|
||||
@@ -313,7 +313,7 @@ void createItemGeometry(flecs::entity e)
|
||||
e.set<TerrainItemNode>({ itemNode, geo });
|
||||
} else if (itemType == "town") {
|
||||
OgreAssert(geo, "Can't create static geometry");
|
||||
createTown(e, itemNode, geo);
|
||||
createTown(e, itemNode, geo);
|
||||
e.set<TerrainItemNode>({ itemNode, geo });
|
||||
std::cout << " town created: " << e.id() << std::endl;
|
||||
} else {
|
||||
@@ -381,5 +381,10 @@ flecs::entity createMeshGeometry(const Ogre::String &meshName,
|
||||
return e;
|
||||
}
|
||||
|
||||
void registerTownItem(flecs::entity e)
|
||||
{
|
||||
registerTown(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ struct harbourMaker {
|
||||
void createItemGeometry(flecs::entity e);
|
||||
void destroyItemGeometry(flecs::entity e);
|
||||
void updateItemGeometry(flecs::entity e);
|
||||
void registerTownItem(flecs::entity e);
|
||||
flecs::entity createMeshGeometry(const Ogre::String &meshName,
|
||||
flecs::entity parente,
|
||||
Ogre::SceneNode *sceneNode,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "PhysicsModule.h"
|
||||
#include "LuaData.h"
|
||||
#include "PlayerActionModule.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "CharacterManagerModule.h"
|
||||
#include "CharacterAIModule.h"
|
||||
#include "items.h"
|
||||
@@ -2142,13 +2143,95 @@ void runAllScriptsForTown(flecs::entity e)
|
||||
j["districts"] = districts;
|
||||
StaticGeometryModule::setItemProperties(e, j.dump());
|
||||
}
|
||||
struct Selector {
|
||||
int selection;
|
||||
Ogre::String result;
|
||||
Ogre::String label;
|
||||
std::vector<Ogre::String> options;
|
||||
Selector(const Ogre::String &label,
|
||||
const std::vector<Ogre::String> &options)
|
||||
: label(label)
|
||||
, options(options)
|
||||
, selection(-1)
|
||||
{
|
||||
}
|
||||
bool select()
|
||||
{
|
||||
bool changed = false;
|
||||
if (selection < 0)
|
||||
selection = 0;
|
||||
if (selection >= options.size())
|
||||
selection = (options.size() > 0) ? options.size() - 1 :
|
||||
0;
|
||||
if (options.size() == 0) {
|
||||
ImGui::Text("None: %s", label.c_str());
|
||||
return false;
|
||||
}
|
||||
if (ImGui::BeginCombo(label.c_str(),
|
||||
options[selection].c_str())) {
|
||||
int i;
|
||||
for (i = 0; i < options.size(); i++) {
|
||||
bool selected = selection == i;
|
||||
if (ImGui::Selectable(options[i].c_str(),
|
||||
selected)) {
|
||||
selection = i;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
if (changed || result.empty())
|
||||
result = options[selection];
|
||||
return changed;
|
||||
}
|
||||
void set_default(const Ogre::String &def)
|
||||
{
|
||||
int index = -1;
|
||||
auto pos = std::find(options.begin(), options.end(), def);
|
||||
if (pos == options.end())
|
||||
index = -1;
|
||||
else {
|
||||
index = std::distance(options.begin(), pos);
|
||||
selection = index;
|
||||
result = options[index];
|
||||
}
|
||||
}
|
||||
};
|
||||
bool editNPCs(nlohmann::json &npcs)
|
||||
{
|
||||
struct slotEdit {
|
||||
const Ogre::String &label;
|
||||
const Ogre::String &slotBase;
|
||||
std::vector<Ogre::String> *options_m;
|
||||
std::vector<Ogre::String> *options_f;
|
||||
const Ogre::String &slot;
|
||||
};
|
||||
static std::vector<Ogre::String> faces_a_m, hairs_a_m, tops_a_m,
|
||||
bottoms_a_m, feet_a_m;
|
||||
static std::vector<Ogre::String> faces_a_f, hairs_a_f, tops_a_f,
|
||||
bottoms_a_f, feet_a_f;
|
||||
ZoneScoped;
|
||||
bool changed = false;
|
||||
ImGui::Text("NPC");
|
||||
int id = 0;
|
||||
struct slotEdit pslots_a[] = {
|
||||
{ "Face", "face", &faces_a_m, &faces_a_f, "slot_face" },
|
||||
{ "Hair", "hair", &hairs_a_m, &hairs_a_f, "slot_hair" },
|
||||
{ "Top", "top", &tops_a_m, &tops_a_f, "slot_top" },
|
||||
{ "Bottom", "bottom", &bottoms_a_m, &bottoms_a_f,
|
||||
"slot_bottom" },
|
||||
{ "Feet", "feet", &feet_a_m, &feet_a_f, "slot_feet" },
|
||||
};
|
||||
for (auto g : pslots_a) {
|
||||
g.options_m->clear();
|
||||
g.options_f->clear();
|
||||
ECS::get_mut<CharacterModule>().getSlotMeshes(
|
||||
"adult", "male", g.slotBase, *g.options_m);
|
||||
ECS::get_mut<CharacterModule>().getSlotMeshes(
|
||||
"adult", "female", g.slotBase, *g.options_f);
|
||||
}
|
||||
for (auto &npc : npcs) {
|
||||
Ogre::String meid = Ogre::StringConverter::toString(id);
|
||||
static char firstName[64] = { 0 };
|
||||
static char lastName[64] = { 0 };
|
||||
static char nickName[64] = { 0 };
|
||||
@@ -2163,6 +2246,21 @@ bool editNPCs(nlohmann::json &npcs)
|
||||
npc["tags"] = "";
|
||||
if (npc.find("sex") == npc.end())
|
||||
npc["sex"] = 1;
|
||||
if (npc["sex"].get<int>() == 0) {
|
||||
for (const auto &m : pslots_a) {
|
||||
if (npc.find(m.slot) == npc.end()) {
|
||||
npc[m.slot] = m.options_m->at(0);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
} else if (npc["sex"].get<int>() == 1) {
|
||||
for (const auto &m : pslots_a) {
|
||||
if (npc.find(m.slot) == npc.end()) {
|
||||
npc[m.slot] = m.options_m->at(0);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(firstName, npc["firstName"].get<Ogre::String>().c_str(),
|
||||
sizeof(firstName));
|
||||
@@ -2173,61 +2271,77 @@ bool editNPCs(nlohmann::json &npcs)
|
||||
strncpy(tags, npc["tags"].get<Ogre::String>().c_str(),
|
||||
sizeof(tags));
|
||||
|
||||
ImGui::InputText(
|
||||
("Last name##" + Ogre::StringConverter::toString(id))
|
||||
.c_str(),
|
||||
lastName, sizeof(lastName));
|
||||
ImGui::InputText(("Last name##" + meid).c_str(), lastName,
|
||||
sizeof(lastName));
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
npc["lastName"] = Ogre::String(lastName);
|
||||
changed = true;
|
||||
}
|
||||
ImGui::InputText(
|
||||
("First name##" + Ogre::StringConverter::toString(id))
|
||||
.c_str(),
|
||||
firstName, sizeof(firstName));
|
||||
ImGui::InputText(("First name##" + meid).c_str(), firstName,
|
||||
sizeof(firstName));
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
npc["firstName"] = Ogre::String(firstName);
|
||||
changed = true;
|
||||
}
|
||||
ImGui::InputText(
|
||||
("Nickname##" + Ogre::StringConverter::toString(id))
|
||||
.c_str(),
|
||||
nickName, sizeof(nickName));
|
||||
ImGui::InputText(("Nickname##" + meid).c_str(), nickName,
|
||||
sizeof(nickName));
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
npc["nickName"] = Ogre::String(nickName);
|
||||
changed = true;
|
||||
}
|
||||
Selector race(("Race##" + meid).c_str(), { "human" });
|
||||
Selector age(("Age##" + meid).c_str(), { "adult" });
|
||||
Selector sex(("Sex##" + meid).c_str(), { "male", "female" });
|
||||
if (npc.find("race") != npc.end())
|
||||
race.set_default(npc["race"].get<Ogre::String>());
|
||||
if (npc.find("age") != npc.end())
|
||||
age.set_default(npc["age"].get<Ogre::String>());
|
||||
if (npc.find("sex") != npc.end())
|
||||
sex.selection = npc["sex"].get<int>();
|
||||
if (race.select()) {
|
||||
npc["race"] = race.result;
|
||||
changed = true;
|
||||
}
|
||||
if (age.select()) {
|
||||
npc["age"] = age.result;
|
||||
changed = true;
|
||||
}
|
||||
/* sex is integer */
|
||||
if (sex.select()) {
|
||||
npc["sex"] = sex.selection;
|
||||
changed = true;
|
||||
}
|
||||
if (sex.selection == 0) {
|
||||
for (const auto &es : pslots_a) {
|
||||
Selector sel((es.label + "##" + meid).c_str(),
|
||||
*es.options_m);
|
||||
sel.set_default(
|
||||
npc[es.slot].get<Ogre::String>());
|
||||
if (sel.select()) {
|
||||
npc[es.slot] = sel.result;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
} else if (sex.selection == 1) {
|
||||
for (const auto &es : pslots_a) {
|
||||
Selector sel((es.label + "##" + meid).c_str(),
|
||||
*es.options_f);
|
||||
sel.set_default(
|
||||
npc[es.slot].get<Ogre::String>());
|
||||
if (sel.select()) {
|
||||
npc[es.slot] = sel.result;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::InputText(
|
||||
("Tags##" + Ogre::StringConverter::toString(id)).c_str(),
|
||||
tags, sizeof(tags));
|
||||
ImGui::InputText(("Tags##" + meid).c_str(), tags, sizeof(tags));
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
npc["tags"] = Ogre::String(tags);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
int selection = npc["sex"].get<int>();
|
||||
const char *items[] = { "Male", "Female" };
|
||||
if (ImGui::Combo(("Sex##" + Ogre::StringConverter::toString(id))
|
||||
.c_str(),
|
||||
&selection, items, 2))
|
||||
npc["sex"] = selection;
|
||||
if (ImGui::SmallButton(
|
||||
("Spawn##" + Ogre::StringConverter::toString(id))
|
||||
.c_str())) {
|
||||
int sex = npc["sex"].get<int>();
|
||||
struct desc {
|
||||
const char *face, *hair, *top, *bottom, *feet;
|
||||
};
|
||||
struct desc models[] = {
|
||||
{ "male_Face.mesh", "male_Hair001.mesh",
|
||||
"male_BodyTop.mesh", "male_BodyBottom.mesh",
|
||||
"male_BodyFeet.mesh" },
|
||||
{ "female_Face.mesh", "female_Hair001.mesh",
|
||||
"female_BodyTop.mesh",
|
||||
"female_BodyBottom.mesh",
|
||||
"female_BodyFeet.mesh" }
|
||||
};
|
||||
if (ImGui::SmallButton(("Spawn##" + meid).c_str())) {
|
||||
Ogre::Vector3 npcPosition;
|
||||
Ogre::Quaternion npcOrientation;
|
||||
from_json(npc["position"], npcPosition);
|
||||
@@ -2236,10 +2350,12 @@ bool editNPCs(nlohmann::json &npcs)
|
||||
// FIXME: create TownCharacterManager and register NPCs through there
|
||||
ECS::get_mut<CharacterManagerModule>()
|
||||
.createCharacterData(
|
||||
models[sex].face, models[sex].hair,
|
||||
models[sex].top, models[sex].bottom,
|
||||
models[sex].feet, npcPosition,
|
||||
npcOrientation);
|
||||
npc["slot_face"].get<Ogre::String>(),
|
||||
npc["slot_hair"].get<Ogre::String>(),
|
||||
npc["slot_top"].get<Ogre::String>(),
|
||||
npc["slot_bottom"].get<Ogre::String>(),
|
||||
npc["slot_feet"].get<Ogre::String>(),
|
||||
npcPosition, npcOrientation);
|
||||
}
|
||||
if (ImGui::SmallButton(
|
||||
("Delete##" + Ogre::StringConverter::toString(id))
|
||||
@@ -2258,9 +2374,39 @@ bool editNPCs(nlohmann::json &npcs)
|
||||
ImGui::InputText("First name", firstName, sizeof(firstName));
|
||||
static char tags[256] = { 0 };
|
||||
ImGui::InputText("Tags", tags, sizeof(tags));
|
||||
static int selection = 0;
|
||||
const char *items[] = { "Male", "Female" };
|
||||
ImGui::Combo("Sex", &selection, items, 2);
|
||||
static Selector race("Race##new_npc", { "human" });
|
||||
static Selector age("Age##new_npc", { "adult" });
|
||||
static Selector sex("Sex##new_npc", { "male", "female" });
|
||||
changed = changed || race.select();
|
||||
changed = changed || age.select();
|
||||
changed = changed || sex.select();
|
||||
static Selector sel_face("Face##new_npc", {});
|
||||
static Selector sel_hair("Hair##new_npc", {});
|
||||
static Selector sel_top("Top##new_npc", {});
|
||||
static Selector sel_bottom("Bottom##new_npc", {});
|
||||
static Selector sel_feet("Feet##new_npc", {});
|
||||
if (changed || sel_face.options.size() == 0) {
|
||||
if (sex.selection == 0) {
|
||||
sel_face = Selector("Face##new_npc", faces_a_m);
|
||||
sel_hair = Selector("Hair##new_npc", hairs_a_m);
|
||||
sel_top = Selector("Top##new_npc", tops_a_m);
|
||||
sel_bottom = Selector("Bottom##new_npc",
|
||||
bottoms_a_m);
|
||||
sel_feet = Selector("Feet##new_npc", feet_a_m);
|
||||
} else if (sex.selection == 1) {
|
||||
sel_face = Selector("Face##new_npc", faces_a_f);
|
||||
sel_hair = Selector("Hair##new_npc", hairs_a_f);
|
||||
sel_top = Selector("Top##new_npc", tops_a_f);
|
||||
sel_bottom = Selector("Bottom##new_npc",
|
||||
bottoms_a_f);
|
||||
sel_feet = Selector("Feet##new_npc", feet_a_f);
|
||||
}
|
||||
}
|
||||
changed = changed || sel_face.select();
|
||||
changed = changed || sel_hair.select();
|
||||
changed = changed || sel_top.select();
|
||||
changed = changed || sel_bottom.select();
|
||||
changed = changed || sel_feet.select();
|
||||
if (ImGui::SmallButton("Add NPC")) {
|
||||
nlohmann::json npc;
|
||||
npc["lastName"] = Ogre::String(lastName);
|
||||
@@ -2274,7 +2420,12 @@ bool editNPCs(nlohmann::json &npcs)
|
||||
.sceneNode->_getDerivedOrientation();
|
||||
to_json(npc["position"], npcPosition);
|
||||
to_json(npc["orientation"], npcOrientation);
|
||||
npc["sex"] = selection;
|
||||
npc["sex"] = sex.selection;
|
||||
npc["slot_hair"] = sel_hair.result;
|
||||
npc["slot_face"] = sel_face.result;
|
||||
npc["slot_top"] = sel_top.result;
|
||||
npc["slot_bottom"] = sel_bottom.result;
|
||||
npc["slot_feet"] = sel_feet.result;
|
||||
npc["health"] = 100;
|
||||
npc["stamina"] = 100;
|
||||
npcs.push_back(npc);
|
||||
@@ -5977,6 +6128,7 @@ struct TownDecorateFurniture : TownTask {
|
||||
float radius =
|
||||
action["radius"]
|
||||
.get<float>();
|
||||
#if 0
|
||||
if (ECS::get()
|
||||
.has<ActionNodeList>()) {
|
||||
ActionNodeList::ActionNode
|
||||
@@ -6019,6 +6171,7 @@ struct TownDecorateFurniture : TownTask {
|
||||
ECS::modified<
|
||||
ActionNodeList>();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6123,12 +6276,209 @@ void createTown(flecs::entity e, Ogre::SceneNode *sceneNode,
|
||||
geo->build();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void registerTown(flecs::entity e)
|
||||
{
|
||||
ZoneScoped;
|
||||
registerTownNPCs(e);
|
||||
if (ECS::get().entity<CharacterAIModule>().is_valid())
|
||||
if (ECS::get().has<CharacterAIModule>()) {
|
||||
ECS::get_mut<CharacterAIModule>().createAI(e);
|
||||
ECS::modified<CharacterAIModule>();
|
||||
}
|
||||
}
|
||||
createTownActionNodes(e);
|
||||
}
|
||||
|
||||
void createTownActionNodes(flecs::entity e)
|
||||
{
|
||||
const TerrainItem &item = e.get<TerrainItem>();
|
||||
Ogre::String props = item.properties;
|
||||
nlohmann::json jprops = nlohmann::json::parse(props);
|
||||
#if 0
|
||||
Ogre::MaterialPtr townMaterial = createTownMaterial(e);
|
||||
#endif
|
||||
for (const auto &jdistrict : jprops["districts"]) {
|
||||
const nlohmann::json &jp = jdistrict;
|
||||
nlohmann::json jlots = nlohmann::json::array();
|
||||
float baseHeight = 4.0f;
|
||||
Ogre::Vector3 localPosition(0, 0, 0);
|
||||
Ogre::Quaternion localRotation = Ogre::Quaternion::IDENTITY;
|
||||
Ogre::Vector3 centerPosition = item.position;
|
||||
Ogre::Quaternion centerOrientation = item.orientation;
|
||||
float delevation = 0.0f;
|
||||
float radius = 50.0f;
|
||||
if (jp.find("elevation") != jp.end())
|
||||
delevation = jp["elevation"].get<float>();
|
||||
if (jp.find("radius") != jp.end())
|
||||
radius = jp["radius"].get<float>();
|
||||
from_json(jp["position"], localPosition);
|
||||
from_json(jp["rotation"], localRotation);
|
||||
centerPosition = centerPosition + localPosition +
|
||||
Ogre::Vector3(0, delevation, 0);
|
||||
centerOrientation = centerOrientation * localRotation;
|
||||
if (jdistrict.find("lots") != jdistrict.end())
|
||||
jlots = jdistrict["lots"];
|
||||
for (const auto &jb : jlots) {
|
||||
float angle = 0.0f;
|
||||
int depth = 10;
|
||||
int width = 10;
|
||||
float distance = radius;
|
||||
float elevation = 0.0f;
|
||||
std::cout << jb.dump() << std::endl;
|
||||
if (jb.find("angle") != jb.end())
|
||||
angle = jb["angle"].get<float>();
|
||||
if (jb.find("depth") != jb.end())
|
||||
depth = jb["depth"].get<int>();
|
||||
if (jb.find("width") != jb.end())
|
||||
width = jb["width"].get<int>();
|
||||
if (jb.find("elevation") != jb.end())
|
||||
elevation = jb["elevation"].get<float>();
|
||||
|
||||
OgreAssert(width > 1 && depth > 1 && baseHeight > 1,
|
||||
"Bad stuff happen");
|
||||
|
||||
Ogre::Quaternion rotation = Ogre::Quaternion(
|
||||
Ogre::Degree(angle), Ogre::Vector3::UNIT_Y);
|
||||
Ogre::Vector3 offset =
|
||||
centerOrientation * rotation *
|
||||
(Ogre::Vector3::UNIT_Z * distance);
|
||||
Ogre::Vector3 worldCenterPosition =
|
||||
centerPosition + offset +
|
||||
Ogre::Vector3(0, elevation, 0);
|
||||
Ogre::Quaternion worldCenterOrientation =
|
||||
centerOrientation * rotation;
|
||||
float outOffset = 1.05f;
|
||||
if (jb.find("furniture_cells") != jb.end()) {
|
||||
for (auto &jfcell : jb["furniture_cells"]) {
|
||||
int x = jfcell["x"].get<int>();
|
||||
int y = jfcell["y"].get<int>();
|
||||
int z = jfcell["z"].get<int>();
|
||||
nlohmann::json furniture =
|
||||
jfcell["furniture"];
|
||||
Ogre::Vector3 cellOffset(
|
||||
x * 2.0f, y * 4.0f, z * 2.0f);
|
||||
Ogre::Vector3 offsetX =
|
||||
worldCenterOrientation *
|
||||
Ogre::Vector3::UNIT_X *
|
||||
(float)x * 2.0f;
|
||||
Ogre::Vector3 offsetZ =
|
||||
worldCenterOrientation *
|
||||
Ogre::Vector3::UNIT_Z *
|
||||
(float)z * 2.0f;
|
||||
Ogre::Vector3 offsetY(0, y * 4.0f, 0);
|
||||
static Ogre::String materialName1 = "";
|
||||
static Ogre::String materialName2 = "";
|
||||
int rotation = 2;
|
||||
if (jfcell.find("rotation") !=
|
||||
jfcell.end())
|
||||
rotation = jfcell["rotation"]
|
||||
.get<int>();
|
||||
|
||||
Ogre::Vector3 offset =
|
||||
worldCenterOrientation *
|
||||
Ogre::Vector3::UNIT_Z * 0.0f;
|
||||
#if 0
|
||||
Ogre::Vector3 furniturePosition =
|
||||
worldCenterPosition + offsetX +
|
||||
offsetZ + offsetY + offset;
|
||||
Ogre::Quaternion furnitureOrientation =
|
||||
worldCenterOrientation *
|
||||
Ogre::Quaternion(
|
||||
Ogre::Degree(
|
||||
90.0f *
|
||||
(float)rotation),
|
||||
Ogre::Vector3::UNIT_Y);
|
||||
#endif
|
||||
|
||||
if (furniture.find("actions") !=
|
||||
furniture.end()) {
|
||||
for (const auto &action :
|
||||
furniture["actions"]) {
|
||||
std::cout
|
||||
<< "SENSOR: "
|
||||
<< action.dump()
|
||||
<< std::endl;
|
||||
std::cout
|
||||
<< furniture
|
||||
.dump()
|
||||
<< std::endl;
|
||||
Ogre::Vector3
|
||||
actionPosition;
|
||||
actionPosition.x =
|
||||
action["position_x"]
|
||||
.get<float>();
|
||||
actionPosition.y =
|
||||
action["position_y"]
|
||||
.get<float>();
|
||||
actionPosition.z =
|
||||
action["position_z"]
|
||||
.get<float>();
|
||||
Ogre::Quaternion worldSensorRotation =
|
||||
worldCenterOrientation *
|
||||
Ogre::Quaternion(
|
||||
Ogre::Degree(
|
||||
90.0f *
|
||||
(float)rotation),
|
||||
Ogre::Vector3::
|
||||
UNIT_Y);
|
||||
Ogre::Vector3 worldSensorPosition =
|
||||
worldCenterPosition +
|
||||
offsetX +
|
||||
offsetZ +
|
||||
offsetY +
|
||||
offset +
|
||||
worldSensorRotation *
|
||||
actionPosition;
|
||||
if (ECS::get()
|
||||
.has<ActionNodeList>()) {
|
||||
ActionNodeList::ActionNode
|
||||
anode;
|
||||
anode.action =
|
||||
action["action"]
|
||||
.get<Ogre::String>();
|
||||
anode.action_text =
|
||||
action["action_text"]
|
||||
.get<Ogre::String>();
|
||||
anode.radius =
|
||||
action["radius"]
|
||||
.get<float>();
|
||||
anode.height =
|
||||
action["height"]
|
||||
.get<float>();
|
||||
anode.props =
|
||||
action;
|
||||
anode.props
|
||||
["town"] =
|
||||
e.id();
|
||||
anode.props
|
||||
["index"] =
|
||||
-1;
|
||||
anode.position =
|
||||
worldSensorPosition;
|
||||
anode.rotation =
|
||||
worldSensorRotation;
|
||||
anode.dynamic =
|
||||
false;
|
||||
ECS::get_mut<
|
||||
ActionNodeList>()
|
||||
.addNode(
|
||||
anode);
|
||||
std::cout
|
||||
<< "action: "
|
||||
<< action.dump(
|
||||
4)
|
||||
<< std::endl;
|
||||
ECS::modified<
|
||||
ActionNodeList>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
#define __TOWN_H__
|
||||
#include <OgreMeshLodGenerator.h>
|
||||
#include <flecs.h>
|
||||
namespace Procedural {
|
||||
namespace Procedural
|
||||
{
|
||||
class TriangleBuffer;
|
||||
}
|
||||
namespace ECS
|
||||
@@ -21,6 +22,8 @@ void clampUV(flecs::entity e, Procedural::TriangleBuffer &tb,
|
||||
Ogre::MaterialPtr createTownMaterial(flecs::entity e, bool force = false);
|
||||
void createTown(flecs::entity e, Ogre::SceneNode *sceneNode,
|
||||
Ogre::StaticGeometry *geo);
|
||||
void registerTown(flecs::entity e);
|
||||
void createTownActionNodes(flecs::entity e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -573,14 +573,13 @@ public:
|
||||
std::thread::hardware_concurrency() - 1)
|
||||
, mDebugRenderer(new DebugRenderer(scnMgr, cameraNode))
|
||||
, object_vs_broadphase_layer_filter{}
|
||||
, object_vs_object_layer_filter{}
|
||||
, object_vs_object_layer_filter{}
|
||||
, debugDraw(false)
|
||||
{
|
||||
static int instanceCount = 0;
|
||||
OgreAssert(instanceCount == 0, "Bad initialisation");
|
||||
instanceCount++;
|
||||
|
||||
|
||||
// This is the max amount of rigid bodies that you can add to the physics system. If you try to add more you'll get an error.
|
||||
// Note: This value is low because this is a simple test. For a real project use something in the order of 65536.
|
||||
const uint cMaxBodies = 65536;
|
||||
@@ -1510,14 +1509,14 @@ public:
|
||||
{
|
||||
return characterBodies.find(id) != characterBodies.end();
|
||||
}
|
||||
void destroyCharacter(JPH::Character *ch)
|
||||
void destroyCharacter(std::shared_ptr<JPH::Character> ch)
|
||||
{
|
||||
characterBodies.erase(characterBodies.find(ch->GetBodyID()));
|
||||
characters.erase(ch);
|
||||
characters.erase(ch.get());
|
||||
Ogre::SceneNode *node = id2node[ch->GetBodyID()];
|
||||
id2node.erase(ch->GetBodyID());
|
||||
node2id.erase(node);
|
||||
OGRE_DELETE ch;
|
||||
ch = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1539,17 +1538,17 @@ JoltPhysicsWrapper::JoltPhysicsWrapper(Ogre::SceneManager *scnMgr,
|
||||
// Install trace and assert callbacks
|
||||
JPH::Trace = TraceImpl;
|
||||
JPH_IF_ENABLE_ASSERTS(JPH::AssertFailed = AssertFailedImpl;)
|
||||
|
||||
|
||||
// Create a factory, this class is responsible for creating instances of classes based on their name or hash and is mainly used for deserialization of saved data.
|
||||
// It is not directly used in this example but still required.
|
||||
JPH::Factory::sInstance = new JPH::Factory();
|
||||
// Register all physics types with the factory and install their collision handlers with the CollisionDispatch class.
|
||||
// If you have your own custom shape types you probably need to register their handlers with the CollisionDispatch before calling this function.
|
||||
// If you implement your own default material (PhysicsMaterial::sDefault) make sure to initialize it before this function or else this function will create one for you.
|
||||
// Register all physics types with the factory and install their collision handlers with the CollisionDispatch class.
|
||||
// If you have your own custom shape types you probably need to register their handlers with the CollisionDispatch before calling this function.
|
||||
// If you implement your own default material (PhysicsMaterial::sDefault) make sure to initialize it before this function or else this function will create one for you.
|
||||
JPH::RegisterTypes();
|
||||
|
||||
phys = std::make_unique<Physics>(scnMgr, cameraNode, nullptr, &contacts);
|
||||
phys = std::make_unique<Physics>(scnMgr, cameraNode, nullptr,
|
||||
&contacts);
|
||||
}
|
||||
|
||||
JoltPhysicsWrapper::~JoltPhysicsWrapper()
|
||||
@@ -1824,7 +1823,7 @@ bool JoltPhysicsWrapper::bodyIsCharacter(JPH::BodyID id) const
|
||||
return phys->bodyIsCharacter(id);
|
||||
}
|
||||
|
||||
void JoltPhysicsWrapper::destroyCharacter(JPH::Character *ch)
|
||||
void JoltPhysicsWrapper::destroyCharacter(std::shared_ptr<JPH::Character> ch)
|
||||
{
|
||||
phys->destroyCharacter(ch);
|
||||
}
|
||||
|
||||
@@ -219,6 +219,6 @@ public:
|
||||
bool raycastQuery(Ogre::Vector3 startPoint, Ogre::Vector3 endPoint,
|
||||
Ogre::Vector3 &position, JPH::BodyID &id);
|
||||
bool bodyIsCharacter(JPH::BodyID id) const;
|
||||
void destroyCharacter(JPH::Character *ch);
|
||||
void destroyCharacter(std::shared_ptr<JPH::Character> ch);
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user