independent slots for clothes, converted to .mesh workflow
This commit is contained in:
@@ -29,27 +29,27 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
if (!anim.configured) {
|
||||
int i, j;
|
||||
e.set<EventData>({});
|
||||
ch.mBodyEnt->getSkeleton()->setBlendMode(
|
||||
Ogre::ANIMBLEND_CUMULATIVE);
|
||||
Ogre::Entity *ent = static_cast<Ogre::Entity *>(
|
||||
ch.mBodyNode->getAttachedObject(0));
|
||||
ent->getSkeleton()->setBlendMode(
|
||||
Ogre::ANIMBLEND_CUMULATIVE);
|
||||
Ogre::AnimationStateSet *animStateSet =
|
||||
ch.mBodyEnt->getAllAnimationStates();
|
||||
ent->getAllAnimationStates();
|
||||
const Ogre::AnimationStateMap &animMap =
|
||||
animStateSet->getAnimationStates();
|
||||
anim.mAnimationSystem =
|
||||
new AnimationSystem::AnimationSystem(
|
||||
false);
|
||||
ch.mBodyEnt->getSkeleton()
|
||||
ent->getSkeleton()
|
||||
->getBone("Root")
|
||||
->removeAllChildren();
|
||||
for (auto it = animMap.begin();
|
||||
it != animMap.end(); it++) {
|
||||
AnimationSystem::Animation *animation =
|
||||
new AnimationSystem::Animation(
|
||||
ch.mBodyEnt
|
||||
->getSkeleton(),
|
||||
ent->getSkeleton(),
|
||||
it->second,
|
||||
ch.mBodyEnt
|
||||
->getSkeleton()
|
||||
ent->getSkeleton()
|
||||
->getAnimation(
|
||||
it->first));
|
||||
#ifdef VDEBUG
|
||||
|
||||
@@ -129,7 +129,11 @@ CharacterManagerModule::CharacterManagerModule(flecs::world &ecs)
|
||||
10000.0f) {
|
||||
if (!data.e.is_valid()) {
|
||||
data.e = createCharacterData(
|
||||
data.model,
|
||||
data.modelFace,
|
||||
data.modelHair,
|
||||
data.modelTop,
|
||||
data.modelBottom,
|
||||
data.modelFeet,
|
||||
data.position,
|
||||
data.orientation);
|
||||
data.e.add<LivesIn>(town);
|
||||
@@ -177,21 +181,27 @@ CharacterManagerModule::createPlayer(const Ogre::Vector3 &position,
|
||||
std::cout << "Begin player create" << std::endl;
|
||||
player.add<Player>();
|
||||
ECS::get_mut<CharacterModule>().createCharacter(
|
||||
player, position, rotation, "normal-male.glb");
|
||||
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++;
|
||||
return player;
|
||||
return player;
|
||||
}
|
||||
flecs::entity
|
||||
CharacterManagerModule::createCharacterData(const Ogre::String model,
|
||||
const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation)
|
||||
|
||||
flecs::entity CharacterManagerModule::createCharacterData(
|
||||
const Ogre::String &modelFace, const Ogre::String &modelHair,
|
||||
const Ogre::String &modelTop, const Ogre::String &modelBottom,
|
||||
const Ogre::String &modelFeet, const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation)
|
||||
{
|
||||
ZoneScoped;
|
||||
flecs::entity e = ECS::get().entity();
|
||||
ECS::get_mut<CharacterModule>().createCharacter(e, position, rotation,
|
||||
model);
|
||||
modelFace, modelHair,
|
||||
modelTop, modelBottom,
|
||||
modelFeet);
|
||||
ECS::modified<CharacterModule>();
|
||||
return e;
|
||||
}
|
||||
@@ -199,8 +209,13 @@ CharacterManagerModule::createCharacterData(const Ogre::String model,
|
||||
void CharacterManagerModule::registerTownCharacters(flecs::entity town)
|
||||
{
|
||||
ZoneScoped;
|
||||
Ogre::MeshManager::getSingleton().load("normal-male.glb", "General");
|
||||
Ogre::MeshManager::getSingleton().load("normal-female.glb", "General");
|
||||
{
|
||||
Ogre::MeshPtr maleMesh = Ogre::MeshManager::getSingleton().load(
|
||||
"normal-male.glb", "Characters");
|
||||
Ogre::MeshPtr femaleMesh =
|
||||
Ogre::MeshManager::getSingleton().load(
|
||||
"normal-female.glb", "Characters");
|
||||
}
|
||||
Ogre::String props = StaticGeometryModule::getItemProperties(town);
|
||||
nlohmann::json j = nlohmann::json::parse(props);
|
||||
nlohmann::json npcs = nlohmann::json::array();
|
||||
@@ -212,17 +227,29 @@ void CharacterManagerModule::registerTownCharacters(flecs::entity town)
|
||||
int index = 0;
|
||||
std::map<int, TownNPCs::NPCData> npcMap;
|
||||
for (auto &npc : npcs) {
|
||||
const char *models[] = { "normal-male.glb",
|
||||
"normal-female.glb" };
|
||||
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" },
|
||||
{ "normal-female.glb", "normal-female.glb",
|
||||
"normal-female.glb", "normal-female.glb",
|
||||
"normal-female.glb" }
|
||||
};
|
||||
int sex = npc["sex"].get<int>();
|
||||
Ogre::Vector3 npcPosition;
|
||||
Ogre::Quaternion npcOrientation;
|
||||
from_json(npc["position"], npcPosition);
|
||||
from_json(npc["orientation"], npcOrientation);
|
||||
Ogre::String model = models[sex];
|
||||
TownNPCs::NPCData npcData;
|
||||
npcData.e = flecs::entity();
|
||||
npcData.model = model;
|
||||
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.orientation = npcOrientation;
|
||||
npcData.position = npcPosition;
|
||||
npcData.props = npc;
|
||||
|
||||
@@ -12,7 +12,11 @@ struct TownNPCs {
|
||||
nlohmann::json props;
|
||||
Ogre::Vector3 position;
|
||||
Ogre::Quaternion orientation;
|
||||
Ogre::String model;
|
||||
Ogre::String modelFace;
|
||||
Ogre::String modelHair;
|
||||
Ogre::String modelTop;
|
||||
Ogre::String modelBottom;
|
||||
Ogre::String modelFeet;
|
||||
std::vector<ActionNodeList::ActionNode> actionNodes;
|
||||
};
|
||||
|
||||
@@ -25,8 +29,12 @@ struct CharacterManagerModule {
|
||||
CharacterManagerModule(flecs::world &ecs);
|
||||
flecs::entity createPlayer(const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation);
|
||||
flecs::entity createCharacterData(const Ogre::String model,
|
||||
const Ogre::Vector3 &position,
|
||||
flecs::entity createCharacterData(const Ogre::String &modelFace,
|
||||
const Ogre::String &modelHair,
|
||||
const Ogre::String &modelTop,
|
||||
const Ogre::String &modelBottom,
|
||||
const Ogre::String &modelFeet,
|
||||
const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation);
|
||||
void removeCharacterData(int id);
|
||||
flecs::entity getPlayer() const
|
||||
|
||||
@@ -22,11 +22,14 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
ecs.component<CharacterBase>()
|
||||
.on_remove([this](flecs::entity e, CharacterBase &ch) {
|
||||
ZoneScoped;
|
||||
// FIXME: clean up data
|
||||
if (characterEntities.find(e) !=
|
||||
characterEntities.end() ||
|
||||
if (characterEntitiesFace.find(e) !=
|
||||
characterEntitiesFace.end() ||
|
||||
characterNodes.find(e) != characterNodes.end()) {
|
||||
characterEntities.erase(e);
|
||||
// FIXME: clean up data
|
||||
characterEntitiesFace.erase(e);
|
||||
characterEntitiesTop.erase(e);
|
||||
characterEntitiesBottom.erase(e);
|
||||
characterEntitiesFeet.erase(e);
|
||||
characterNodes.erase(e);
|
||||
ECS::modified<CharacterModule>();
|
||||
}
|
||||
@@ -34,30 +37,92 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
.on_add([this](flecs::entity e, CharacterBase &ch) {
|
||||
if (characterNodes.find(e) == characterNodes.end()) {
|
||||
ZoneScoped;
|
||||
OgreAssert(characterModels.find(e) !=
|
||||
characterModels.end(),
|
||||
OgreAssert(characterModelsFace.find(e) !=
|
||||
characterModelsFace.end(),
|
||||
"no model set");
|
||||
const EngineData &eng = ECS::get<EngineData>();
|
||||
Ogre::SceneNode *bodyNode =
|
||||
eng.mScnMgr->getRootSceneNode()
|
||||
->createChildSceneNode();
|
||||
Ogre::Entity *bodyEnt =
|
||||
Ogre::Entity *faceEnt =
|
||||
eng.mScnMgr->createEntity(
|
||||
characterModels[e]);
|
||||
characterModelsFace[e]);
|
||||
bodyNode->attachObject(faceEnt);
|
||||
characterNodes[e] = bodyNode;
|
||||
characterEntities[e] = bodyEnt;
|
||||
characterEntitiesFace[e] = faceEnt;
|
||||
Ogre::Entity *hairEnt =
|
||||
eng.mScnMgr->createEntity(
|
||||
characterModelsHair[e]);
|
||||
hairEnt->shareSkeletonInstanceWith(faceEnt);
|
||||
bodyNode->attachObject(hairEnt);
|
||||
characterEntitiesHair[e] = hairEnt;
|
||||
Ogre::Entity *topEnt =
|
||||
eng.mScnMgr->createEntity(
|
||||
characterModelsTop[e]);
|
||||
topEnt->shareSkeletonInstanceWith(faceEnt);
|
||||
bodyNode->attachObject(topEnt);
|
||||
characterEntitiesTop[e] = topEnt;
|
||||
Ogre::Entity *bottomEnt =
|
||||
eng.mScnMgr->createEntity(
|
||||
characterModelsBottom[e]);
|
||||
bottomEnt->shareSkeletonInstanceWith(faceEnt);
|
||||
bodyNode->attachObject(bottomEnt);
|
||||
characterEntitiesBottom[e] = bottomEnt;
|
||||
Ogre::Entity *feetEnt =
|
||||
eng.mScnMgr->createEntity(
|
||||
characterModelsFeet[e]);
|
||||
feetEnt->shareSkeletonInstanceWith(faceEnt);
|
||||
bodyNode->attachObject(feetEnt);
|
||||
characterEntitiesFeet[e] = feetEnt;
|
||||
#if 0
|
||||
if (characterModelsTop.find(e) !=
|
||||
characterModelsTop.end()) {
|
||||
Ogre::String skeletonName =
|
||||
bodyEnt->getMesh()
|
||||
->getSkeletonName();
|
||||
Ogre::MeshPtr mesh =
|
||||
Ogre::MeshManager::getSingleton()
|
||||
.load(characterModelsTop
|
||||
[e],
|
||||
"General");
|
||||
Ogre::String mname = mesh->getName();
|
||||
mesh = mesh->clone(mname + "_clone");
|
||||
OgreAssert(
|
||||
mesh,
|
||||
"No mesh " +
|
||||
characterModelsTop[e]);
|
||||
Ogre::String clothSkeleton =
|
||||
mesh->getSkeletonName();
|
||||
if (clothSkeleton != skeletonName) {
|
||||
mesh->setSkeletonName(
|
||||
skeletonName);
|
||||
mesh->load();
|
||||
if (Ogre::SkeletonManager::getSingleton()
|
||||
.resourceExists(
|
||||
clothSkeleton))
|
||||
Ogre::SkeletonManager::
|
||||
getSingleton()
|
||||
.remove(clothSkeleton);
|
||||
}
|
||||
Ogre::Entity *characterTop =
|
||||
eng.mScnMgr->createEntity(mesh);
|
||||
characterTop->shareSkeletonInstanceWith(
|
||||
bodyEnt);
|
||||
bodyNode->attachObject(characterTop);
|
||||
}
|
||||
#endif
|
||||
ECS::modified<CharacterModule>();
|
||||
}
|
||||
OgreAssert(characterOrientations.find(e) !=
|
||||
characterOrientations.end(),
|
||||
"Bad orientation/position");
|
||||
ch.mBodyEnt = characterEntities[e];
|
||||
ch.mBodyNode = characterNodes[e];
|
||||
ch.mBodyNode->setOrientation(characterOrientations[e]);
|
||||
ch.mBodyNode->setPosition(characterPositions[e]);
|
||||
ch.mBodyNode->attachObject(ch.mBodyEnt);
|
||||
OgreAssert(ch.mBodyEnt->getSkeleton()->hasBone("Root"),
|
||||
"No root bone");
|
||||
OgreAssert(
|
||||
characterEntitiesFace[e]->getSkeleton()->hasBone(
|
||||
"Root"),
|
||||
"No root bone");
|
||||
ch.mBoneMotion = Ogre::Vector3::ZERO;
|
||||
ch.mBonePrevMotion = Ogre::Vector3::ZERO;
|
||||
});
|
||||
@@ -462,6 +527,34 @@ void CharacterModule::updateCameraGoal(Camera &camera, Ogre::Real deltaYaw,
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterModule::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)
|
||||
{
|
||||
ZoneScoped;
|
||||
if (e.has<CharacterBase>() || e.has<AnimationControl>())
|
||||
return;
|
||||
if (characterNodes.find(e) != characterNodes.end())
|
||||
return;
|
||||
e.set<CharacterLocation>({ rotation, position });
|
||||
characterOrientations[e] = rotation;
|
||||
characterPositions[e] = position;
|
||||
characterModelsFace[e] = faceModel;
|
||||
characterModelsHair[e] = hairModel;
|
||||
characterModelsTop[e] = topModel;
|
||||
characterModelsBottom[e] = bottomModel;
|
||||
characterModelsFeet[e] = feetModel;
|
||||
e.set<CharacterVelocity>(
|
||||
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } });
|
||||
e.add<CharacterGravity>();
|
||||
e.add<CharacterBuoyancy>();
|
||||
e.add<Character>();
|
||||
e.add<CharacterBase>();
|
||||
e.add<AnimationControl>();
|
||||
}
|
||||
|
||||
void applyWeightBasedScale(Ogre::Entity *ent,
|
||||
const Ogre::String &targetBoneName,
|
||||
const Ogre::Vector3 &scale)
|
||||
@@ -549,26 +642,63 @@ void applyWeightBasedScale(Ogre::Entity *ent,
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterModule::createCharacter(flecs::entity e,
|
||||
const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation,
|
||||
const Ogre::String model)
|
||||
void CharacterModule::remapMeshToMasterSkeleton(Ogre::MeshPtr clothMesh,
|
||||
Ogre::MeshPtr masterMesh)
|
||||
{
|
||||
ZoneScoped;
|
||||
if (e.has<CharacterBase>() || e.has<AnimationControl>())
|
||||
Ogre::SkeletonPtr masterSkel = masterMesh->getSkeleton();
|
||||
Ogre::SkeletonPtr clothSkel = clothMesh->getSkeleton();
|
||||
|
||||
if (!masterSkel || !clothSkel)
|
||||
return;
|
||||
if (characterNodes.find(e) != characterNodes.end())
|
||||
return;
|
||||
e.set<CharacterLocation>({ rotation, position });
|
||||
characterOrientations[e] = rotation;
|
||||
characterPositions[e] = position;
|
||||
characterModels[e] = model;
|
||||
e.set<CharacterVelocity>(
|
||||
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } });
|
||||
e.add<CharacterGravity>();
|
||||
e.add<CharacterBuoyancy>();
|
||||
e.add<Character>();
|
||||
e.add<CharacterBase>();
|
||||
e.add<AnimationControl>();
|
||||
|
||||
// 1. Create a Lookup Table: ClothIndex -> MasterIndex
|
||||
std::map<unsigned short, unsigned short> indexMap;
|
||||
for (unsigned short i = 0; i < clothSkel->getNumBones(); ++i) {
|
||||
Ogre::String boneName = clothSkel->getBone(i)->getName();
|
||||
if (masterSkel->hasBone(boneName)) {
|
||||
indexMap[i] =
|
||||
masterSkel->getBone(boneName)->getHandle();
|
||||
} else {
|
||||
indexMap[i] = 0; // Fallback to root
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Update the Hardware Buffers for each SubMesh
|
||||
for (unsigned short i = 0; i < clothMesh->getNumSubMeshes(); ++i) {
|
||||
Ogre::SubMesh *sub = clothMesh->getSubMesh(i);
|
||||
Ogre::VertexData *vdata = sub->useSharedVertices ?
|
||||
clothMesh->sharedVertexData :
|
||||
sub->vertexData;
|
||||
|
||||
// Find the element containing bone indices (VES_BLEND_INDICES)
|
||||
const Ogre::VertexElement *idxElem =
|
||||
vdata->vertexDeclaration->findElementBySemantic(
|
||||
Ogre::VES_BLEND_INDICES);
|
||||
if (!idxElem)
|
||||
continue;
|
||||
|
||||
Ogre::HardwareVertexBufferSharedPtr vbuf =
|
||||
vdata->vertexBufferBinding->getBuffer(
|
||||
idxElem->getSource());
|
||||
unsigned char *vertex = static_cast<unsigned char *>(
|
||||
vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
|
||||
|
||||
for (size_t j = 0; j < vdata->vertexCount; ++j) {
|
||||
unsigned char *pIndices;
|
||||
idxElem->baseVertexPointerToElement(vertex, &pIndices);
|
||||
|
||||
// Remap the 4 indices (Ogre hardware skinning usually uses 4 bytes)
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
pIndices[k] = static_cast<unsigned char>(
|
||||
indexMap[pIndices[k]]);
|
||||
}
|
||||
vertex += vbuf->getVertexSize();
|
||||
}
|
||||
vbuf->unlock();
|
||||
}
|
||||
|
||||
// 3. Link to Master Skeleton and rebuild
|
||||
clothMesh->setSkeletonName(masterSkel->getName());
|
||||
clothMesh->_compileBoneAssignments();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ struct CharacterBase {
|
||||
Ogre::Vector3 mBonePrevMotion;
|
||||
Ogre::Vector3 mGoalDirection; // actual intended direction in world-space
|
||||
Ogre::SceneNode *mBodyNode;
|
||||
Ogre::Entity *mBodyEnt;
|
||||
bool is_submerged;
|
||||
};
|
||||
struct CharacterLocation {
|
||||
@@ -40,13 +39,23 @@ 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 model);
|
||||
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 *> characterEntities;
|
||||
std::unordered_map<flecs::entity_t, Ogre::String> characterModels;
|
||||
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::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;
|
||||
void remapMeshToMasterSkeleton(Ogre::MeshPtr clothMesh,
|
||||
Ogre::MeshPtr masterMesh);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -485,23 +485,32 @@ LuaData::LuaData()
|
||||
});
|
||||
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);
|
||||
OgreAssert(lua_gettop(L) == 8, "Invalid parameters");
|
||||
luaL_checktype(L, 1, LUA_TSTRING); // face
|
||||
luaL_checktype(L, 2, LUA_TSTRING); // hair
|
||||
luaL_checktype(L, 3, LUA_TSTRING); // top
|
||||
luaL_checktype(L, 4, LUA_TSTRING); // bottom
|
||||
luaL_checktype(L, 5, LUA_TSTRING); // feet
|
||||
luaL_checktype(L, 6, LUA_TNUMBER);
|
||||
luaL_checktype(L, 7, LUA_TNUMBER);
|
||||
luaL_checktype(L, 8, LUA_TNUMBER);
|
||||
luaL_checktype(L, 9, LUA_TNUMBER);
|
||||
Ogre::String face = lua_tostring(L, 1);
|
||||
Ogre::String hair = lua_tostring(L, 2);
|
||||
Ogre::String top = lua_tostring(L, 3);
|
||||
Ogre::String bottom = lua_tostring(L, 4);
|
||||
Ogre::String feet = lua_tostring(L, 5);
|
||||
float yaw = lua_tonumber(L, 8);
|
||||
float x = lua_tonumber(L, 5);
|
||||
float y = lua_tonumber(L, 6);
|
||||
float z = lua_tonumber(L, 7);
|
||||
Ogre::Quaternion orientation(Ogre::Radian(yaw),
|
||||
Ogre::Vector3::UNIT_Y);
|
||||
Ogre::Vector3 npcPos(x, y, z);
|
||||
flecs::entity e =
|
||||
ECS::get_mut<CharacterManagerModule>()
|
||||
.createCharacterData(type, npcPos, orientation);
|
||||
.createCharacterData(face, hair, top, bottom,
|
||||
feet, npcPos, orientation);
|
||||
ECS::modified<CharacterManagerModule>();
|
||||
lua_pushinteger(L, idmap.add_entity(e));
|
||||
return 1;
|
||||
|
||||
@@ -2216,8 +2216,17 @@ bool editNPCs(nlohmann::json &npcs)
|
||||
("Spawn##" + Ogre::StringConverter::toString(id))
|
||||
.c_str())) {
|
||||
int sex = npc["sex"].get<int>();
|
||||
const char *models[] = { "normal-male.glb",
|
||||
"normal-female.glb" };
|
||||
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" },
|
||||
{ "normal-female.glb", "normal-female.glb",
|
||||
"normal-female.glb", "normal-female.glb",
|
||||
"normal-female.glb" }
|
||||
};
|
||||
Ogre::Vector3 npcPosition;
|
||||
Ogre::Quaternion npcOrientation;
|
||||
from_json(npc["position"], npcPosition);
|
||||
@@ -2225,8 +2234,11 @@ bool editNPCs(nlohmann::json &npcs)
|
||||
|
||||
// FIXME: create TownCharacterManager and register NPCs through there
|
||||
ECS::get_mut<CharacterManagerModule>()
|
||||
.createCharacterData(models[sex], npcPosition,
|
||||
npcOrientation);
|
||||
.createCharacterData(
|
||||
models[sex].face, models[sex].hair,
|
||||
models[sex].top, models[sex].bottom,
|
||||
models[sex].feet, npcPosition,
|
||||
npcOrientation);
|
||||
}
|
||||
if (ImGui::SmallButton(
|
||||
("Delete##" + Ogre::StringConverter::toString(id))
|
||||
|
||||
Reference in New Issue
Block a user