#include "unpagedworldspacewidget.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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& record = dynamic_cast&>(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(*document.getData().getTableModel(CSMWorld::UniversalId::Type_Cells)); mReferenceablesModel = &dynamic_cast( *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(document, 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& universalIdData, DropType type) { if (WorldspaceWidget::handleDrop(universalIdData, type)) return true; if (type != Type_CellsInterior) return false; mCellId = universalIdData.begin()->getId(); mCell = std::make_unique(getDocument(), 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(); } 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::UnpagedWorldspaceWidget::getSnapTarget(unsigned int elementMask) const { return mCell->getSnapTarget(elementMask); } std::vector> CSVRender::UnpagedWorldspaceWidget::getSelection( unsigned int elementMask) const { return mCell->getSelection(elementMask); } void CSVRender::UnpagedWorldspaceWidget::selectGroup(const std::vector& group) const { mCell->selectFromGroup(group); } void CSVRender::UnpagedWorldspaceWidget::unhideAll() const { mCell->unhideAll(); } std::vector> CSVRender::UnpagedWorldspaceWidget::getEdited( unsigned int elementMask) const { return mCell->getEdited(elementMask); } void CSVRender::UnpagedWorldspaceWidget::setSubMode(int subMode, unsigned int elementMask) { mCell->setSubMode(subMode, elementMask); } 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& 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& 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& 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::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements( CSVRender::WorldspaceWidget::DropType type) const { dropRequirments requirements = WorldspaceWidget::getDropRequirements(type); if (requirements != ignored) return requirements; switch (type) { case Type_CellsInterior: return canHandle; case Type_CellsExterior: return needPaged; default: return ignored; } }