1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-30 09:36:43 +00:00

Handle changes to race record when rendering actors

This commit is contained in:
Kyle Cooley 2018-08-23 22:40:43 -04:00 committed by Andrei Kortunov
parent b2115b60e6
commit 1276e0fa9b
7 changed files with 98 additions and 16 deletions

View file

@ -89,12 +89,12 @@ opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget editmode instancemode instanceselectionmode instancemovemode previewwidget editmode instancemode instanceselectionmode instancemovemode
orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller
cellwater terraintexturemode cellwater terraintexturemode actor
) )
opencs_units_noqt (view/render opencs_units_noqt (view/render
lighting lightingday lightingnight lightingbright object cell terrainstorage tagbase lighting lightingday lightingnight lightingbright object cell terrainstorage tagbase
cellarrow cellmarker cellborder pathgrid actor cellarrow cellmarker cellborder pathgrid
) )
opencs_hdrs_noqt (view/render opencs_hdrs_noqt (view/render

View file

@ -1,7 +1,6 @@
#include "actoradapter.hpp" #include "actoradapter.hpp"
#include <iostream> #include <components/debug/debuglog.hpp>
#include <components/esm/loadarmo.hpp> #include <components/esm/loadarmo.hpp>
#include <components/esm/loadclot.hpp> #include <components/esm/loadclot.hpp>
#include <components/esm/loadnpc.hpp> #include <components/esm/loadnpc.hpp>
@ -45,17 +44,56 @@ namespace CSMWorld
void ActorAdapter::handleReferenceableChanged(const QModelIndex& topLeft, const QModelIndex& botRight) void ActorAdapter::handleReferenceableChanged(const QModelIndex& topLeft, const QModelIndex& botRight)
{ {
// TODO // Setup
const int TypeColumn = mReferenceables.findColumnIndex(CSMWorld::Columns::ColumnId_RecordType);
int rowStart = getHighestIndex(topLeft).row();
int rowEnd = getHighestIndex(botRight).row();
// Handle each record
for (int row = rowStart; row <= rowEnd; ++row)
{
int type = mReferenceables.getData(row, TypeColumn).toInt();
if (type == CSMWorld::UniversalId::Type_Creature || type == CSMWorld::UniversalId::Type_Npc)
{
// Update the cached npc or creature
std::string refId = mReferenceables.getId(row);
if (mActorPartMaps.find(refId) != mActorPartMaps.end())
updateActor(refId);
}
else if (type == CSMWorld::UniversalId::Type_Armor)
{
// TODO update everything?
// store all items referenced when creating map and check against that here
}
else if (type == CSMWorld::UniversalId::Type_Clothing)
{
// TODO update everything?
}
}
} }
void ActorAdapter::handleRaceChanged(const QModelIndex& topLeft, const QModelIndex& botRight) void ActorAdapter::handleRaceChanged(const QModelIndex& topLeft, const QModelIndex& botRight)
{ {
// TODO int rowStart = getHighestIndex(topLeft).row();
int rowEnd = getHighestIndex(botRight).row();
for (int row = rowStart; row <= rowEnd; ++row)
{
std::string raceId = mRaces.getId(row);
updateNpcsWithRace(raceId);
}
} }
void ActorAdapter::handleBodyPartChanged(const QModelIndex& topLeft, const QModelIndex& botRight) void ActorAdapter::handleBodyPartChanged(const QModelIndex& topLeft, const QModelIndex& botRight)
{ {
// TODO // TODO
Log(Debug::Info) << "Body Part Changed (" << topLeft.row() << ", " << topLeft.column() << ") (" << botRight.row() << ", " << botRight.column() << ")";
}
QModelIndex ActorAdapter::getHighestIndex(QModelIndex index) const
{
while (index.parent().isValid())
index = index.parent();
return index;
} }
ActorAdapter::RacePartMap& ActorAdapter::getOrCreateRacePartMap(const std::string& raceId, bool isFemale) ActorAdapter::RacePartMap& ActorAdapter::getOrCreateRacePartMap(const std::string& raceId, bool isFemale)
@ -174,10 +212,6 @@ namespace CSMWorld
npcMap.emplace(static_cast<ESM::PartReferenceType>(part.mPart), bodyPartId); npcMap.emplace(static_cast<ESM::PartReferenceType>(part.mPart), bodyPartId);
} }
} }
else if (recordType == CSMWorld::UniversalId::Type_Weapon)
{
// TODO
}
} }
} }
} }
@ -233,10 +267,24 @@ namespace CSMWorld
} }
mActorPartMaps[refId] = npcMap; mActorPartMaps[refId] = npcMap;
emit actorChanged(refId);
} }
void ActorAdapter::updateCreature(const std::string& refId) void ActorAdapter::updateCreature(const std::string& refId)
{ {
// TODO emit actorChanged(refId);
}
void ActorAdapter::updateNpcsWithRace(const std::string& raceId)
{
for (auto it : mActorPartMaps)
{
auto& refId = it.first;
auto& npc = dynamic_cast<const Record<ESM::NPC>&>(mReferenceables.getRecord(refId)).get();
if (npc.mRace == raceId)
{
updateNpc(refId);
}
}
} }
} }

View file

@ -60,6 +60,11 @@ namespace CSMWorld
private: private:
ActorAdapter(const ActorAdapter&) = delete;
ActorAdapter& operator=(const ActorAdapter&) = delete;
QModelIndex getHighestIndex(QModelIndex) const;
RacePartMap& getOrCreateRacePartMap(const std::string& raceId, bool isFemale); RacePartMap& getOrCreateRacePartMap(const std::string& raceId, bool isFemale);
void updateRaceParts(const std::string& raceId); void updateRaceParts(const std::string& raceId);
@ -67,6 +72,8 @@ namespace CSMWorld
void updateNpc(const std::string& refId); void updateNpc(const std::string& refId);
void updateCreature(const std::string& refId); void updateCreature(const std::string& refId);
void updateNpcsWithRace(const std::string& raceId);
RefIdCollection& mReferenceables; RefIdCollection& mReferenceables;
IdCollection<ESM::Race>& mRaces; IdCollection<ESM::Race>& mRaces;
IdCollection<ESM::BodyPart>& mBodyParts; IdCollection<ESM::BodyPart>& mBodyParts;

View file

@ -20,6 +20,7 @@ namespace CSVRender
Actor::Actor(const std::string& id, int type, CSMWorld::Data& data) Actor::Actor(const std::string& id, int type, CSMWorld::Data& data)
: mId(id) : mId(id)
, mInitialized(false)
, mType(type) , mType(type)
, mData(data) , mData(data)
, mBaseNode(new osg::Group()) , mBaseNode(new osg::Group())
@ -45,7 +46,22 @@ namespace CSVRender
} }
catch (std::exception& e) catch (std::exception& e)
{ {
Log(Debug::Error) << "Exception in Actor::update(): " << e.what(); Log(Debug::Info) << "Exception in Actor::update(): " << e.what();
}
if (!mInitialized)
{
mInitialized = true;
connect(mData.getActorAdapter(), SIGNAL(actorChanged(const std::string&)), this, SLOT(handleActorChanged(const std::string&)));
}
}
void Actor::handleActorChanged(const std::string& refId)
{
if (mId == refId)
{
Log(Debug::Info) << "Actor::actorChanged " << mId;
update();
} }
} }

View file

@ -5,6 +5,8 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <QObject>
#include <components/esm/loadarmo.hpp> #include <components/esm/loadarmo.hpp>
#include <components/sceneutil/visitor.hpp> #include <components/sceneutil/visitor.hpp>
@ -26,8 +28,9 @@ namespace SceneUtil
namespace CSVRender namespace CSVRender
{ {
/// Handles loading an npc or creature /// Handles loading an npc or creature
class Actor class Actor : public QObject
{ {
Q_OBJECT
public: public:
/// Creates an actor. /// Creates an actor.
/// \param id The referenceable id /// \param id The referenceable id
@ -41,6 +44,9 @@ namespace CSVRender
/// (Re)creates the npc or creature renderable /// (Re)creates the npc or creature renderable
void update(); void update();
private slots:
void handleActorChanged(const std::string& refId);
private: private:
void updateCreature(); void updateCreature();
void updateNpc(); void updateNpc();
@ -54,6 +60,7 @@ namespace CSVRender
static const std::string MeshPrefix; static const std::string MeshPrefix;
std::string mId; std::string mId;
bool mInitialized;
int mType; int mType;
CSMWorld::Data& mData; CSMWorld::Data& mData;

View file

@ -134,9 +134,10 @@ void CSVRender::Object::update()
{ {
if (recordType == CSMWorld::UniversalId::Type_Npc || recordType == CSMWorld::UniversalId::Type_Creature) if (recordType == CSMWorld::UniversalId::Type_Npc || recordType == CSMWorld::UniversalId::Type_Creature)
{ {
Actor actor(mReferenceableId, recordType, mData); if (!mActor)
actor.update(); mActor.reset(new Actor(mReferenceableId, recordType, mData));
mBaseNode->addChild(actor.getBaseNode()); mActor->update();
mBaseNode->addChild(mActor->getBaseNode());
} }
else else
{ {

View file

@ -1,6 +1,7 @@
#ifndef OPENCS_VIEW_OBJECT_H #ifndef OPENCS_VIEW_OBJECT_H
#define OPENCS_VIEW_OBJECT_H #define OPENCS_VIEW_OBJECT_H
#include <memory>
#include <string> #include <string>
#include <osg/ref_ptr> #include <osg/ref_ptr>
@ -41,6 +42,7 @@ namespace CSMWorld
namespace CSVRender namespace CSVRender
{ {
class Actor;
class Object; class Object;
// An object to attach as user data to the osg::Node, allows us to get an Object back from a Node when we are doing a ray query // An object to attach as user data to the osg::Node, allows us to get an Object back from a Node when we are doing a ray query
@ -98,6 +100,7 @@ namespace CSVRender
osg::ref_ptr<osg::Node> mMarker[3]; osg::ref_ptr<osg::Node> mMarker[3];
int mSubMode; int mSubMode;
float mMarkerTransparency; float mMarkerTransparency;
std::unique_ptr<Actor> mActor;
/// Not implemented /// Not implemented
Object (const Object&); Object (const Object&);