refactored object rendering into a separate class
parent
30f8e279ed
commit
0c1ad54e68
@ -0,0 +1,217 @@
|
||||
|
||||
#include "object.hpp"
|
||||
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreSceneNode.h>
|
||||
#include <OgreEntity.h>
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/ref.hpp"
|
||||
#include "../../model/world/refidcollection.hpp"
|
||||
|
||||
void CSVRender::Object::clearSceneNode (Ogre::SceneNode *node)
|
||||
{
|
||||
for (Ogre::SceneNode::ObjectIterator iter = node->getAttachedObjectIterator();
|
||||
iter.hasMoreElements(); )
|
||||
{
|
||||
Ogre::MovableObject* object = dynamic_cast<Ogre::MovableObject*> (iter.getNext());
|
||||
node->getCreator()->destroyMovableObject (object);
|
||||
}
|
||||
|
||||
for (Ogre::SceneNode::ChildNodeIterator iter = node->getChildIterator();
|
||||
iter.hasMoreElements(); )
|
||||
{
|
||||
Ogre::SceneNode* childNode = dynamic_cast<Ogre::SceneNode*> (iter.getNext());
|
||||
clearSceneNode (childNode);
|
||||
node->getCreator()->destroySceneNode (childNode);
|
||||
}
|
||||
}
|
||||
|
||||
void CSVRender::Object::clear()
|
||||
{
|
||||
mObject.setNull();
|
||||
|
||||
clearSceneNode (mBase);
|
||||
}
|
||||
|
||||
void CSVRender::Object::update()
|
||||
{
|
||||
clear();
|
||||
|
||||
std::string model;
|
||||
int error = 0; // 1 referemceanöe does not exist, 2 referenceable does not specify a mesh
|
||||
|
||||
const CSMWorld::RefIdCollection& referenceables = mData.getReferenceables();
|
||||
|
||||
int index = referenceables.searchId (mReferenceableId);
|
||||
|
||||
if (index==-1)
|
||||
error = 1;
|
||||
else
|
||||
{
|
||||
// xxx check for Deleted state (error 1)
|
||||
|
||||
model = referenceables.getData (index,
|
||||
referenceables.findColumnIndex (CSMWorld::Columns::ColumnId_Model)).
|
||||
toString().toUtf8().constData();
|
||||
|
||||
if (model.empty())
|
||||
error = 2;
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
Ogre::Entity* entity = mBase->getCreator()->createEntity (Ogre::SceneManager::PT_CUBE);
|
||||
entity->setMaterialName("BaseWhite"); /// \todo adjust material according to error
|
||||
|
||||
mBase->attachObject (entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
mObject = NifOgre::Loader::createObjects (mBase, "Meshes\\" + model);
|
||||
}
|
||||
}
|
||||
|
||||
void CSVRender::Object::adjust()
|
||||
{
|
||||
if (mReferenceId.empty())
|
||||
return;
|
||||
|
||||
const CSMWorld::CellRef& reference = getReference();
|
||||
|
||||
// position
|
||||
if (!mForceBaseToZero)
|
||||
{
|
||||
Ogre::Vector3 (reference.mPos.pos[0], reference.mPos.pos[1], reference.mPos.pos[2]);
|
||||
|
||||
mBase->setPosition (Ogre::Vector3 (
|
||||
reference.mPos.pos[0], reference.mPos.pos[1], reference.mPos.pos[2]));
|
||||
}
|
||||
|
||||
// orientation
|
||||
Ogre::Quaternion xr (Ogre::Radian (-reference.mPos.pos[0]), Ogre::Vector3::UNIT_X);
|
||||
|
||||
Ogre::Quaternion yr (Ogre::Radian (-reference.mPos.pos[1]), Ogre::Vector3::UNIT_Y);
|
||||
|
||||
Ogre::Quaternion zr (Ogre::Radian (-reference.mPos.pos[2]), Ogre::Vector3::UNIT_Z);
|
||||
|
||||
mBase->setOrientation (xr*yr*zr);
|
||||
|
||||
// scale
|
||||
mBase->setScale (reference.mScale, reference.mScale, reference.mScale);
|
||||
}
|
||||
|
||||
const CSMWorld::CellRef& CSVRender::Object::getReference() const
|
||||
{
|
||||
if (mReferenceId.empty())
|
||||
throw std::logic_error ("object does not represent a reference");
|
||||
|
||||
return mData.getReferences().getRecord (mReferenceId).get();
|
||||
}
|
||||
|
||||
CSVRender::Object::Object (const CSMWorld::Data& data, Ogre::SceneNode *cellNode,
|
||||
const std::string& id, bool referenceable, bool forceBaseToZero)
|
||||
: mData (data), mBase (0), mForceBaseToZero (forceBaseToZero)
|
||||
{
|
||||
mBase = cellNode->createChildSceneNode();
|
||||
|
||||
if (referenceable)
|
||||
{
|
||||
mReferenceableId = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReferenceId = id;
|
||||
mReferenceableId = getReference().mRefID;
|
||||
}
|
||||
|
||||
update();
|
||||
adjust();
|
||||
}
|
||||
|
||||
CSVRender::Object::~Object()
|
||||
{
|
||||
clear();
|
||||
|
||||
if (mBase)
|
||||
mBase->getCreator()->destroySceneNode (mBase);
|
||||
}
|
||||
|
||||
bool CSVRender::Object::ReferenceableDataChanged (const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight)
|
||||
{
|
||||
const CSMWorld::RefIdCollection& referenceables = mData.getReferenceables();
|
||||
|
||||
int index = referenceables.searchId (mReferenceableId);
|
||||
|
||||
if (index!=-1 && index>=topLeft.row() && index<=bottomRight.row())
|
||||
{
|
||||
update();
|
||||
adjust();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSVRender::Object::ReferenceableAboutToBeRemoved (const QModelIndex& parent, int start,
|
||||
int end)
|
||||
{
|
||||
const CSMWorld::RefIdCollection& referenceables = mData.getReferenceables();
|
||||
|
||||
int index = referenceables.searchId (mReferenceableId);
|
||||
|
||||
if (index!=-1 && index>=start && index<=end)
|
||||
{
|
||||
// Deletion of referenceable-type objects is handled outside of Object.
|
||||
if (!mReferenceId.empty())
|
||||
{
|
||||
update();
|
||||
adjust();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSVRender::Object::ReferenceDataChanged (const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight)
|
||||
{
|
||||
if (mReferenceId.empty())
|
||||
return false;
|
||||
|
||||
const CSMWorld::RefCollection& references = mData.getReferences();
|
||||
|
||||
int index = references.searchId (mReferenceId);
|
||||
|
||||
if (index!=-1 && index>=topLeft.row() && index<=bottomRight.row())
|
||||
{
|
||||
int columnIndex =
|
||||
references.findColumnIndex (CSMWorld::Columns::ColumnId_ReferenceableId);
|
||||
|
||||
if (columnIndex>=topLeft.column() && columnIndex<=bottomRight.row())
|
||||
{
|
||||
mReferenceableId =
|
||||
references.getData (index, columnIndex).toString().toUtf8().constData();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
adjust();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string CSVRender::Object::getReferenceId() const
|
||||
{
|
||||
return mReferenceId;
|
||||
}
|
||||
|
||||
std::string CSVRender::Object::getReferenceableId() const
|
||||
{
|
||||
return mReferenceableId;
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
#ifndef OPENCS_VIEW_OBJECT_H
|
||||
#define OPENCS_VIEW_OBJECT_H
|
||||
|
||||
#include <components/nifogre/ogrenifloader.hpp>
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class SceneNode;
|
||||
}
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class Data;
|
||||
class CellRef;
|
||||
}
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
class Object
|
||||
{
|
||||
const CSMWorld::Data& mData;
|
||||
std::string mReferenceId;
|
||||
std::string mReferenceableId;
|
||||
Ogre::SceneNode *mBase;
|
||||
NifOgre::ObjectScenePtr mObject;
|
||||
bool mForceBaseToZero;
|
||||
|
||||
/// Not implemented
|
||||
Object (const Object&);
|
||||
|
||||
/// Not implemented
|
||||
Object& operator= (const Object&);
|
||||
|
||||
/// Destroy all scene nodes and movable objects attached to node.
|
||||
static void clearSceneNode (Ogre::SceneNode *node);
|
||||
|
||||
/// Remove object from node (includes deleting)
|
||||
void clear();
|
||||
|
||||
/// Update model
|
||||
void update();
|
||||
|
||||
/// Adjust position, orientation and scale
|
||||
void adjust();
|
||||
|
||||
/// Throws an exception if *this was constructed with referenceable
|
||||
const CSMWorld::CellRef& getReference() const;
|
||||
|
||||
public:
|
||||
|
||||
Object (const CSMWorld::Data& data, Ogre::SceneNode *cellNode,
|
||||
const std::string& id, bool referenceable, bool forceBaseToZero = false);
|
||||
/// \param forceBaseToZero If this is a reference ignore the coordinates and place
|
||||
/// it at 0, 0, 0 instead.
|
||||
|
||||
~Object();
|
||||
|
||||
/// \return Did this call result in a modification of the visual representation of
|
||||
/// this object?
|
||||
bool ReferenceableDataChanged (const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight);
|
||||
|
||||
/// \return Did this call result in a modification of the visual representation of
|
||||
/// this object?
|
||||
bool ReferenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||
|
||||
/// \return Did this call result in a modification of the visual representation of
|
||||
/// this object?
|
||||
bool ReferenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||
|
||||
/// Returns an empty string if this is a refereceable-type object.
|
||||
std::string getReferenceId() const;
|
||||
|
||||
std::string getReferenceableId() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue