Merge remote-tracking branch 'scrawl/terrain'

This commit is contained in:
Marc Zinnschlag 2014-10-09 12:56:42 +02:00
commit c85735abed
14 changed files with 244 additions and 8 deletions

View file

@ -26,7 +26,7 @@ opencs_units (model/world
opencs_units_noqt (model/world opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope landtexture land
) )
opencs_hdrs_noqt (model/world opencs_hdrs_noqt (model/world
@ -76,7 +76,7 @@ opencs_units (view/widget
opencs_units (view/render opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget previewwidget terrainstorage
) )
opencs_units_noqt (view/render opencs_units_noqt (view/render

View file

@ -539,6 +539,16 @@ CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles()
return mDebugProfiles; return mDebugProfiles;
} }
const CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand() const
{
return mLand;
}
const CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures() const
{
return mLandTextures;
}
const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
{ {
return mResourcesManager.get (id.getType()); return mResourcesManager.get (id.getType());
@ -573,8 +583,11 @@ void CSMWorld::Data::merge()
int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base, bool project) int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base, bool project)
{ {
delete mReader; // Don't delete the Reader yet. Some record types store a reference to the Reader to handle on-demand loading
boost::shared_ptr<ESM::ESMReader> ptr(mReader);
mReaders.push_back(ptr);
mReader = 0; mReader = 0;
mDialogue = 0; mDialogue = 0;
mRefLoadCache.clear(); mRefLoadCache.clear();
@ -598,8 +611,11 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
if (!mReader->hasMoreRecs()) if (!mReader->hasMoreRecs())
{ {
delete mReader; // Don't delete the Reader yet. Some record types store a reference to the Reader to handle on-demand loading
boost::shared_ptr<ESM::ESMReader> ptr(mReader);
mReaders.push_back(ptr);
mReader = 0; mReader = 0;
mDialogue = 0; mDialogue = 0;
mRefLoadCache.clear(); mRefLoadCache.clear();
return true; return true;
@ -626,6 +642,9 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
case ESM::REC_ENCH: mEnchantments.load (*mReader, mBase); break; case ESM::REC_ENCH: mEnchantments.load (*mReader, mBase); break;
case ESM::REC_BODY: mBodyParts.load (*mReader, mBase); break; case ESM::REC_BODY: mBodyParts.load (*mReader, mBase); break;
case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break;
case ESM::REC_LAND: mLand.load(*mReader, mBase); break;
case ESM::REC_CELL: case ESM::REC_CELL:
{ {
mCells.load (*mReader, mBase); mCells.load (*mReader, mBase);
@ -775,7 +794,9 @@ bool CSMWorld::Data::hasId (const std::string& id) const
getCells().searchId (id)!=-1 || getCells().searchId (id)!=-1 ||
getEnchantments().searchId (id)!=-1 || getEnchantments().searchId (id)!=-1 ||
getBodyParts().searchId (id)!=-1 || getBodyParts().searchId (id)!=-1 ||
getReferenceables().searchId (id)!=-1; getReferenceables().searchId (id)!=-1 ||
getLand().searchId (id) != -1 ||
getLandTextures().searchId (id) != -1;
} }
int CSMWorld::Data::count (RecordBase::State state) const int CSMWorld::Data::count (RecordBase::State state) const
@ -795,7 +816,9 @@ int CSMWorld::Data::count (RecordBase::State state) const
count (state, mCells) + count (state, mCells) +
count (state, mEnchantments) + count (state, mEnchantments) +
count (state, mBodyParts) + count (state, mBodyParts) +
count (state, mReferenceables); count (state, mReferenceables) +
count (state, mLand) +
count (state, mLandTextures);
} }
void CSMWorld::Data::setDescription (const std::string& description) void CSMWorld::Data::setDescription (const std::string& description)
@ -838,6 +861,8 @@ std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
appendIds (ids, mEnchantments, listDeleted); appendIds (ids, mEnchantments, listDeleted);
appendIds (ids, mBodyParts, listDeleted); appendIds (ids, mBodyParts, listDeleted);
appendIds (ids, mReferenceables, listDeleted); appendIds (ids, mReferenceables, listDeleted);
appendIds (ids, mLand, listDeleted);
appendIds (ids, mLandTextures, listDeleted);
std::sort (ids.begin(), ids.end()); std::sort (ids.begin(), ids.end());

View file

@ -33,6 +33,8 @@
#include "idcollection.hpp" #include "idcollection.hpp"
#include "universalid.hpp" #include "universalid.hpp"
#include "cell.hpp" #include "cell.hpp"
#include "land.hpp"
#include "landtexture.hpp"
#include "refidcollection.hpp" #include "refidcollection.hpp"
#include "refcollection.hpp" #include "refcollection.hpp"
#include "infocollection.hpp" #include "infocollection.hpp"
@ -74,6 +76,8 @@ namespace CSMWorld
InfoCollection mTopicInfos; InfoCollection mTopicInfos;
InfoCollection mJournalInfos; InfoCollection mJournalInfos;
IdCollection<Cell> mCells; IdCollection<Cell> mCells;
IdCollection<LandTexture> mLandTextures;
IdCollection<Land> mLand;
RefIdCollection mReferenceables; RefIdCollection mReferenceables;
RefCollection mRefs; RefCollection mRefs;
IdCollection<ESM::Filter> mFilters; IdCollection<ESM::Filter> mFilters;
@ -88,6 +92,8 @@ namespace CSMWorld
bool mProject; bool mProject;
std::map<std::string, std::map<ESM::RefNum, std::string> > mRefLoadCache; std::map<std::string, std::map<ESM::RefNum, std::string> > mRefLoadCache;
std::vector<boost::shared_ptr<ESM::ESMReader> > mReaders;
// not implemented // not implemented
Data (const Data&); Data (const Data&);
Data& operator= (const Data&); Data& operator= (const Data&);
@ -195,6 +201,10 @@ namespace CSMWorld
IdCollection<ESM::DebugProfile>& getDebugProfiles(); IdCollection<ESM::DebugProfile>& getDebugProfiles();
const IdCollection<CSMWorld::Land>& getLand() const;
const IdCollection<CSMWorld::LandTexture>& getLandTextures() const;
/// Throws an exception, if \a id does not match a resources list. /// Throws an exception, if \a id does not match a resources list.
const Resources& getResources (const UniversalId& id) const; const Resources& getResources (const UniversalId& id) const;
@ -247,4 +257,4 @@ namespace CSMWorld
}; };
} }
#endif #endif

View file

@ -0,0 +1,28 @@
#include "land.hpp"
#include <sstream>
namespace CSMWorld
{
Land::Land()
{
mLand.reset(new ESM::Land());
}
void Land::load(ESM::ESMReader &esm)
{
mLand->load(esm);
std::ostringstream stream;
stream << "#" << mLand->mX << " " << mLand->mY;
mId = stream.str();
}
void Land::blank()
{
/// \todo
}
}

View file

@ -0,0 +1,29 @@
#ifndef CSM_WORLD_LAND_H
#define CSM_WORLD_LAND_H
#include <string>
#include <boost/shared_ptr.hpp>
#include <components/esm/loadland.hpp>
namespace CSMWorld
{
/// \brief Wrapper for Land record. Encodes X and Y cell index in the ID.
///
/// \todo Add worldspace support to the Land record.
/// \todo Add a proper copy constructor (currently worked around using shared_ptr)
struct Land
{
Land();
boost::shared_ptr<ESM::Land> mLand;
std::string mId;
/// Loads the metadata and ID
void load (ESM::ESMReader &esm);
void blank();
};
}
#endif

View file

@ -0,0 +1,21 @@
#include "landtexture.hpp"
#include <components/esm/esmreader.hpp>
namespace CSMWorld
{
void LandTexture::load(ESM::ESMReader &esm)
{
ESM::LandTexture::load(esm);
int plugin = esm.getIndex();
std::ostringstream stream;
stream << mIndex << "_" << plugin;
mId = stream.str();
}
}

View file

@ -0,0 +1,22 @@
#ifndef CSM_WORLD_LANDTEXTURE_H
#define CSM_WORLD_LANDTEXTURE_H
#include <string>
#include <components/esm/loadltex.hpp>
namespace CSMWorld
{
/// \brief Wrapper for LandTexture record. Encodes mIndex and the plugin index (obtained from ESMReader)
/// in the ID.
///
/// \attention The mId field of the ESM::LandTexture struct is not used.
struct LandTexture : public ESM::LandTexture
{
std::string mId;
void load (ESM::ESMReader &esm);
};
}
#endif

View file

@ -10,6 +10,9 @@
#include "../../model/world/columns.hpp" #include "../../model/world/columns.hpp"
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
#include "elements.hpp"
#include "terrainstorage.hpp"
bool CSVRender::Cell::removeObject (const std::string& id) bool CSVRender::Cell::removeObject (const std::string& id)
{ {
std::map<std::string, Object *>::iterator iter = std::map<std::string, Object *>::iterator iter =
@ -67,6 +70,18 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
int rows = references.rowCount(); int rows = references.rowCount();
addObjects (0, rows-1); addObjects (0, rows-1);
const CSMWorld::IdCollection<CSMWorld::Land>& land = mData.getLand();
int landIndex = land.searchId(mId);
if (landIndex != -1)
{
mTerrain.reset(new Terrain::TerrainGrid(sceneManager, new TerrainStorage(mData), Element_Terrain, true,
Terrain::Align_XY));
const ESM::Land* esmLand = land.getRecord(mId).get().mLand.get();
mTerrain->loadCell(esmLand->mX,
esmLand->mY);
}
} }
CSVRender::Cell::~Cell() CSVRender::Cell::~Cell()
@ -198,4 +213,4 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int
return false; return false;
return addObjects (start, end); return addObjects (start, end);
} }

View file

@ -6,6 +6,8 @@
#include <OgreVector3.h> #include <OgreVector3.h>
#include <components/terrain/terraingrid.hpp>
#include "object.hpp" #include "object.hpp"
class QModelIndex; class QModelIndex;
@ -29,6 +31,7 @@ namespace CSVRender
std::string mId; std::string mId;
Ogre::SceneNode *mCellNode; Ogre::SceneNode *mCellNode;
std::map<std::string, Object *> mObjects; std::map<std::string, Object *> mObjects;
std::auto_ptr<Terrain::TerrainGrid> mTerrain;
/// Ignored if cell does not have an object with the given ID. /// Ignored if cell does not have an object with the given ID.
/// ///

View file

@ -0,0 +1,43 @@
#include "terrainstorage.hpp"
namespace CSVRender
{
TerrainStorage::TerrainStorage(const CSMWorld::Data &data)
: mData(data)
{
}
ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
{
std::ostringstream stream;
stream << "#" << cellX << " " << cellY;
// The cell isn't guaranteed to have Land. This is because the terrain implementation
// has to wrap the vertices of the last row and column to the next cell, which may be a nonexisting cell
int index = mData.getLand().searchId(stream.str());
if (index == -1)
return NULL;
ESM::Land* land = mData.getLand().getRecord(index).get().mLand.get();
int mask = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX;
if (!land->isDataLoaded(mask))
land->loadData(mask);
return land;
}
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)
{
std::ostringstream stream;
stream << index << "_" << plugin;
return &mData.getLandTextures().getRecord(stream.str()).get();
}
void TerrainStorage::getBounds(float &minX, float &maxX, float &minY, float &maxY)
{
// not needed at the moment - this returns the bounds of the whole world, but we only edit individual cells
throw std::runtime_error("getBounds not implemented");
}
}

View file

@ -0,0 +1,29 @@
#ifndef OPENCS_RENDER_TERRAINSTORAGE_H
#define OPENCS_RENDER_TERRAINSTORAGE_H
#include <components/esmterrain/storage.hpp>
#include "../../model/world/data.hpp"
namespace CSVRender
{
/**
* @brief A bridge between the terrain component and OpenCS's terrain data storage.
*/
class TerrainStorage : public ESMTerrain::Storage
{
public:
TerrainStorage(const CSMWorld::Data& data);
private:
const CSMWorld::Data& mData;
virtual ESM::Land* getLand (int cellX, int cellY);
virtual const ESM::LandTexture* getLandTexture(int index, short plugin);
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY);
};
}
#endif

View file

@ -98,6 +98,8 @@ struct Land
void load(ESMReader &esm); void load(ESMReader &esm);
void save(ESMWriter &esm) const; void save(ESMWriter &esm) const;
void blank() {}
/** /**
* Actually loads data * Actually loads data
*/ */

View file

@ -19,4 +19,10 @@ void LandTexture::save(ESMWriter &esm) const
esm.writeHNCString("DATA", mTexture); esm.writeHNCString("DATA", mTexture);
} }
void LandTexture::blank()
{
mTexture.clear();
mIndex = -1;
}
} }

View file

@ -32,6 +32,9 @@ struct LandTexture
std::string mId, mTexture; std::string mId, mTexture;
int mIndex; int mIndex;
void blank();
///< Set record to default state (does not touch the ID).
void load(ESMReader &esm); void load(ESMReader &esm);
void save(ESMWriter &esm) const; void save(ESMWriter &esm) const;
}; };