Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393#include "unpagedworldspacewidget.hpp"
#include <sstream>
#include <components/sceneutil/util.hpp>
#include <apps/opencs/model/world/cell.hpp>#include <apps/opencs/model/world/cellcoordinates.hpp>#include <apps/opencs/model/world/columns.hpp>#include <apps/opencs/model/world/pathgrid.hpp>#include <apps/opencs/model/world/record.hpp>#include <apps/opencs/model/world/subcellcollection.hpp>#include <apps/opencs/view/render/cell.hpp>#include <apps/opencs/view/render/worldspacewidget.hpp>
#include <components/esm3/loadcell.hpp>
#include <osg/Camera>#include <osg/Vec4f>#include <osg/ref_ptr>#include <osgViewer/View>
#include "../../model/doc/document.hpp"
#include "../../model/world/data.hpp"#include "../../model/world/idtable.hpp"
#include "../widget/scenetooltoggle2.hpp"
#include "cameracontroller.hpp"
namespace CSVRender{ class TagBase;}
namespace osg{ class Vec3f;}
void CSVRender::UnpagedWorldspaceWidget::update(){ const CSMWorld::Record<CSMWorld::Cell>& record = dynamic_cast<const CSMWorld::Record<CSMWorld::Cell>&>(mCellsModel->getRecord(mCellId));
osg::Vec4f colour = SceneUtil::colourFromRGB(record.get().mAmbi.mAmbient);
setDefaultAmbient(colour);
bool isInterior = (record.get().mData.mFlags & ESM::Cell::Interior) != 0; bool behaveLikeExterior = (record.get().mData.mFlags & ESM::Cell::QuasiEx) != 0;
setExterior(behaveLikeExterior || !isInterior);
/// \todo deal with mSunlight and mFog/mForDensity
flagAsModified();}
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget( const std::string& cellId, CSMDoc::Document& document, QWidget* parent) : WorldspaceWidget(document, parent) , mDocument(document) , mCellId(cellId){ mCellsModel = &dynamic_cast<CSMWorld::IdTable&>(*document.getData().getTableModel(CSMWorld::UniversalId::Type_Cells));
mReferenceablesModel = &dynamic_cast<CSMWorld::IdTable&>( *document.getData().getTableModel(CSMWorld::UniversalId::Type_Referenceables));
connect(mCellsModel, &CSMWorld::IdTable::dataChanged, this, &UnpagedWorldspaceWidget::cellDataChanged); connect(mCellsModel, &CSMWorld::IdTable::rowsAboutToBeRemoved, this, &UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved);
connect( &document.getData(), &CSMWorld::Data::assetTablesChanged, this, &UnpagedWorldspaceWidget::assetTablesChanged);
update();
mCell = std::make_unique<Cell>(document, mSelectionMarker.get(), mRootNode, mCellId);}
void CSVRender::UnpagedWorldspaceWidget::cellDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight){ int index = mCellsModel->findColumnIndex(CSMWorld::Columns::ColumnId_Modification); QModelIndex cellIndex = mCellsModel->getModelIndex(mCellId, index);
if (cellIndex.row() >= topLeft.row() && cellIndex.row() <= bottomRight.row()) { if (mCellsModel->data(cellIndex).toInt() == CSMWorld::RecordBase::State_Deleted) { emit closeRequest(); } else { /// \todo possible optimisation: check columns and update only if relevant columns have /// changed update(); } }}
void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end){ QModelIndex cellIndex = mCellsModel->getModelIndex(mCellId, 0);
if (cellIndex.row() >= start && cellIndex.row() <= end) emit closeRequest();}
void CSVRender::UnpagedWorldspaceWidget::assetTablesChanged(){ if (mCell) mCell->reloadAssets();}
bool CSVRender::UnpagedWorldspaceWidget::handleDrop( const std::vector<CSMWorld::UniversalId>& universalIdData, DropType type){ if (WorldspaceWidget::handleDrop(universalIdData, type)) return true;
if (type != Type_CellsInterior) return false;
mCellId = universalIdData.begin()->getId();
mCell = std::make_unique<Cell>(getDocument(), mSelectionMarker.get(), mRootNode, mCellId); mCamPositionSet = false; mOrbitCamControl->reset();
update(); emit cellChanged(*universalIdData.begin());
return true;}
void CSVRender::UnpagedWorldspaceWidget::clearSelection(int elementMask){ mCell->setSelection(elementMask, Cell::Selection_Clear); flagAsModified(); mSelectionMarker->detachMarker();}
void CSVRender::UnpagedWorldspaceWidget::invertSelection(int elementMask){ mCell->setSelection(elementMask, Cell::Selection_Invert); flagAsModified();}
void CSVRender::UnpagedWorldspaceWidget::selectAll(int elementMask){ mCell->setSelection(elementMask, Cell::Selection_All); flagAsModified();}
void CSVRender::UnpagedWorldspaceWidget::selectAllWithSameParentId(int elementMask){ mCell->selectAllWithSameParentId(elementMask); flagAsModified();}
void CSVRender::UnpagedWorldspaceWidget::selectInsideCube( const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode){ mCell->selectInsideCube(pointA, pointB, dragMode);}
void CSVRender::UnpagedWorldspaceWidget::selectWithinDistance( const osg::Vec3d& point, float distance, DragMode dragMode){ mCell->selectWithinDistance(point, distance, dragMode);}
std::string CSVRender::UnpagedWorldspaceWidget::getCellId(const osg::Vec3f& point) const{ return mCellId;}
CSVRender::Cell* CSVRender::UnpagedWorldspaceWidget::getCell(const osg::Vec3d& point) const{ return mCell.get();}
CSVRender::Cell* CSVRender::UnpagedWorldspaceWidget::getCell(const CSMWorld::CellCoordinates& coords) const{ return mCell.get();}
osg::ref_ptr<CSVRender::TagBase> CSVRender::UnpagedWorldspaceWidget::getSnapTarget(unsigned int elementMask) const{ return mCell->getSnapTarget(elementMask);}
std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::UnpagedWorldspaceWidget::getSelection( unsigned int elementMask) const{ return mCell->getSelection(elementMask);}
void CSVRender::UnpagedWorldspaceWidget::selectGroup(const std::vector<std::string>& group) const{ mCell->selectFromGroup(group);}
void CSVRender::UnpagedWorldspaceWidget::unhideAll() const{ mCell->unhideAll();}
std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::UnpagedWorldspaceWidget::getEdited( unsigned int elementMask) const{ return mCell->getEdited(elementMask);}
void CSVRender::UnpagedWorldspaceWidget::setSubMode(int subMode, unsigned int elementMask){ mCell->setSubMode(subMode, elementMask); mSelectionMarker->updateSelectionMarker();}
void CSVRender::UnpagedWorldspaceWidget::reset(unsigned int elementMask){ mCell->reset(elementMask);}
void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight){ if (mCell.get()) if (mCell.get()->referenceableDataChanged(topLeft, bottomRight)) flagAsModified();}
void CSVRender::UnpagedWorldspaceWidget::referenceableAboutToBeRemoved(const QModelIndex& parent, int start, int end){ if (mCell.get()) if (mCell.get()->referenceableAboutToBeRemoved(parent, start, end)) flagAsModified();}
void CSVRender::UnpagedWorldspaceWidget::referenceableAdded(const QModelIndex& parent, int start, int end){ if (mCell.get()) { QModelIndex topLeft = mReferenceablesModel->index(start, 0); QModelIndex bottomRight = mReferenceablesModel->index(end, mReferenceablesModel->columnCount());
if (mCell.get()->referenceableDataChanged(topLeft, bottomRight)) flagAsModified(); }}
void CSVRender::UnpagedWorldspaceWidget::referenceDataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight){ if (mCell.get()) if (mCell.get()->referenceDataChanged(topLeft, bottomRight)) flagAsModified();}
void CSVRender::UnpagedWorldspaceWidget::referenceAboutToBeRemoved(const QModelIndex& parent, int start, int end){ if (mCell.get()) if (mCell.get()->referenceAboutToBeRemoved(parent, start, end)) flagAsModified();}
void CSVRender::UnpagedWorldspaceWidget::referenceAdded(const QModelIndex& parent, int start, int end){ if (mCell.get()) if (mCell.get()->referenceAdded(parent, start, end)) flagAsModified();}
void CSVRender::UnpagedWorldspaceWidget::pathgridDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight){ const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
int rowStart = -1; int rowEnd = -1;
if (topLeft.parent().isValid()) { rowStart = topLeft.parent().row(); rowEnd = bottomRight.parent().row(); } else { rowStart = topLeft.row(); rowEnd = bottomRight.row(); }
for (int row = rowStart; row <= rowEnd; ++row) { const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get(); if (ESM::RefId::stringRefId(mCellId) == pathgrid.mId) { mCell->pathgridModified(); flagAsModified(); return; } }}
void CSVRender::UnpagedWorldspaceWidget::pathgridAboutToBeRemoved(const QModelIndex& parent, int start, int end){ const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (!parent.isValid()) { // Pathgrid going to be deleted for (int row = start; row <= end; ++row) { const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get(); if (ESM::RefId::stringRefId(mCellId) == pathgrid.mId) { mCell->pathgridRemoved(); flagAsModified(); return; } } }}
void CSVRender::UnpagedWorldspaceWidget::pathgridAdded(const QModelIndex& parent, int start, int end){ const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (!parent.isValid()) { for (int row = start; row <= end; ++row) { const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get(); if (ESM::RefId::stringRefId(mCellId) == pathgrid.mId) { mCell->pathgridModified(); flagAsModified(); return; } } }}
void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons(CSVWidget::SceneToolToggle2* tool){ WorldspaceWidget::addVisibilitySelectorButtons(tool); tool->addButton(Button_Terrain, Mask_Terrain, "Terrain", "", true);}
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction(){ osg::Vec3d eye, center, up; mView->getCamera()->getViewMatrixAsLookAt(eye, center, up); osg::Vec3d position = eye;
std::ostringstream stream;
stream << "player->positionCell " << position.x() << ", " << position.y() << ", " << position.z() << ", 0, \"" << mCellId << "\"";
return stream.str();}
CSVRender::WorldspaceWidget::DropRequirements CSVRender::UnpagedWorldspaceWidget::getDropRequirements( CSVRender::WorldspaceWidget::DropType type) const{ DropRequirements requirements = WorldspaceWidget::getDropRequirements(type);
if (requirements != ignored) return requirements;
switch (type) { case Type_CellsInterior: return canHandle;
case Type_CellsExterior: return needPaged;
default: return ignored; }}
CSVRender::Object* CSVRender::UnpagedWorldspaceWidget::getObjectByReferenceId(const std::string& referenceId){ return mCell->getObjectByReferenceId(referenceId);}