diff --git a/CHANGELOG.md b/CHANGELOG.md index 989a49acc..795473128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -135,6 +135,7 @@ Feature #4968: Scalable UI widget skins Feature #4994: Persistent pinnable windows hiding Feature #5000: Compressed BSA format support + Feature #5005: Editor: Instance window via Scene window Feature #5010: Native graphics herbalism support Feature #5031: Make GetWeaponType function return different values for tools Feature #5033: Magic armor mitigation for creatures diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 9bc0e0877..a206fad6f 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -247,6 +247,9 @@ void CSMPrefs::State::declare() addValues (landeditOutsideVisibleCell); declareInt ("texturebrush-maximumsize", "Maximum texture brush size", 50). setMin (1); + declareBool ("open-list-view", "Open displays list view", false). + setTooltip ("When opening a reference from the scene view, it will open the" + " instance list view instead of the individual instance record view."); declareCategory ("Key Bindings"); @@ -331,6 +334,7 @@ void CSMPrefs::State::declare() declareShortcut ("scene-navi-primary", "Camera Rotation From Mouse Movement", QKeySequence(Qt::LeftButton)); declareShortcut ("scene-navi-secondary", "Camera Translation From Mouse Movement", QKeySequence(Qt::ControlModifier | (int)Qt::LeftButton)); + declareShortcut ("scene-open-primary", "Primary Open", QKeySequence(Qt::ShiftModifier | (int)Qt::LeftButton)); declareShortcut ("scene-edit-primary", "Primary Edit", QKeySequence(Qt::RightButton)); declareShortcut ("scene-edit-secondary", "Secondary Edit", QKeySequence(Qt::ControlModifier | (int)Qt::RightButton)); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 42dbe51ac..343495518 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -22,6 +22,7 @@ #include "../../model/world/idtable.hpp" #include "../world/subviews.hpp" +#include "../world/scenesubview.hpp" #include "../world/tablesubview.hpp" #include "../tools/subviews.hpp" @@ -626,6 +627,20 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin connect (view, SIGNAL (updateSubViewIndices (SubView *)), this, SLOT (updateSubViewIndices (SubView *))); + CSVWorld::TableSubView* tableView = dynamic_cast(view); + if (tableView) + { + connect (this, SIGNAL (requestFocus (const std::string&)), + tableView, SLOT (requestFocus (const std::string&))); + } + + CSVWorld::SceneSubView* sceneView = dynamic_cast(view); + if (sceneView) + { + connect(sceneView, SIGNAL(requestFocus(const std::string&)), + this, SLOT(onRequestFocus(const std::string&))); + } + view->show(); if (!hint.empty()) @@ -1065,3 +1080,16 @@ void CSVDoc::View::createScrollArea() mScroll->setWidget(&mSubViewWindow); setCentralWidget(mScroll); } + +void CSVDoc::View::onRequestFocus (const std::string& id) +{ + if(CSMPrefs::get()["3D Scene Editing"]["open-list-view"].isTrue()) + { + addReferencesSubView(); + emit requestFocus(id); + } + else + { + addSubView(CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Reference, id)); + } +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index c4046a7a1..52057ab37 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -140,6 +140,8 @@ namespace CSVDoc void mergeDocument (CSMDoc::Document *document); + void requestFocus (const std::string& id); + public slots: void addSubView (const CSMWorld::UniversalId& id, const std::string& hint = ""); @@ -262,6 +264,8 @@ namespace CSVDoc void moveScrollBarToEnd(int min, int max); void merge(); + + void onRequestFocus (const std::string& id); }; } diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index 5f0852c90..03451bc1b 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -29,6 +29,8 @@ void CSVRender::EditMode::setEditLock (bool locked) } +void CSVRender::EditMode::primaryOpenPressed (const WorldspaceHitResult& hit) {} + void CSVRender::EditMode::primaryEditPressed (const WorldspaceHitResult& hit) {} void CSVRender::EditMode::secondaryEditPressed (const WorldspaceHitResult& hit) {} diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index f9b7027f9..9f3b28957 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -39,6 +39,9 @@ namespace CSVRender /// Default-implementation: Ignored. virtual void setEditLock (bool locked); + /// Default-implementation: Ignored. + virtual void primaryOpenPressed (const WorldspaceHitResult& hit); + /// Default-implementation: Ignored. virtual void primaryEditPressed (const WorldspaceHitResult& hit); diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index 1cf8a5698..0cf58038d 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -94,6 +94,8 @@ CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidg parent), mSubMode (0), mSubModeId ("move"), mSelectionMode (0), mDragMode (DragMode_None), mDragAxis (-1), mLocked (false), mUnitScaleDist(1) { + connect(this, SIGNAL(requestFocus(const std::string&)), + worldspaceWidget, SIGNAL(requestFocus(const std::string&))); } void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar) @@ -174,6 +176,18 @@ void CSVRender::InstanceMode::primaryEditPressed (const WorldspaceHitResult& hit primarySelectPressed (hit); } +void CSVRender::InstanceMode::primaryOpenPressed (const WorldspaceHitResult& hit) +{ + if(hit.tag) + { + if (CSVRender::ObjectTag *objectTag = dynamic_cast (hit.tag.get())) + { + const std::string refId = objectTag->mObject->getReferenceId(); + emit requestFocus(refId); + } + } +} + void CSVRender::InstanceMode::secondaryEditPressed (const WorldspaceHitResult& hit) { if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue()) diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index 933cae529..6ddaa254f 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -55,6 +55,8 @@ namespace CSVRender virtual void setEditLock (bool locked); + virtual void primaryOpenPressed (const WorldspaceHitResult& hit); + virtual void primaryEditPressed (const WorldspaceHitResult& hit); virtual void secondaryEditPressed (const WorldspaceHitResult& hit); @@ -83,6 +85,10 @@ namespace CSVRender virtual int getSubMode() const; + signals: + + void requestFocus (const std::string& id); + private slots: void subModeChanged (const std::string& id); diff --git a/apps/opencs/view/render/pathgridmode.cpp b/apps/opencs/view/render/pathgridmode.cpp index a9cce0200..8863ad235 100644 --- a/apps/opencs/view/render/pathgridmode.cpp +++ b/apps/opencs/view/render/pathgridmode.cpp @@ -63,6 +63,10 @@ namespace CSVRender } } + void PathgridMode::primaryOpenPressed(const WorldspaceHitResult& hitResult) + { + } + void PathgridMode::primaryEditPressed(const WorldspaceHitResult& hitResult) { if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue() && diff --git a/apps/opencs/view/render/pathgridmode.hpp b/apps/opencs/view/render/pathgridmode.hpp index e34208f8c..a012a67e4 100644 --- a/apps/opencs/view/render/pathgridmode.hpp +++ b/apps/opencs/view/render/pathgridmode.hpp @@ -21,6 +21,8 @@ namespace CSVRender virtual void deactivate(CSVWidget::SceneToolbar* toolbar); + virtual void primaryOpenPressed(const WorldspaceHitResult& hit); + virtual void primaryEditPressed(const WorldspaceHitResult& hit); virtual void secondaryEditPressed(const WorldspaceHitResult& hit); diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 274e64742..4205188e4 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -77,6 +77,10 @@ void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) EditMode::deactivate(toolbar); } +void CSVRender::TerrainTextureMode::primaryOpenPressed(const WorldspaceHitResult& hit) // Apply changes here +{ +} + void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult& hit) // Apply changes here { CSMDoc::Document& document = getWorldspaceWidget().getDocument(); diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 5184f0f73..10ea842c9 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -35,6 +35,8 @@ namespace CSVRender /// \brief Editmode for terrain texture grid TerrainTextureMode(WorldspaceWidget*, QWidget* parent = nullptr); + void primaryOpenPressed (const WorldspaceHitResult& hit); + /// \brief Create single command for one-click texture editing void primaryEditPressed (const WorldspaceHitResult& hit); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 7e405266e..1eca61e73 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -101,6 +101,9 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg // Shortcuts CSMPrefs::Shortcut* primaryEditShortcut = new CSMPrefs::Shortcut("scene-edit-primary", "scene-speed-modifier", CSMPrefs::Shortcut::SM_Detach, this); + CSMPrefs::Shortcut* primaryOpenShortcut = new CSMPrefs::Shortcut("scene-open-primary", this); + + connect(primaryOpenShortcut, SIGNAL(activated(bool)), this, SLOT(primaryOpen(bool))); connect(primaryEditShortcut, SIGNAL(activated(bool)), this, SLOT(primaryEdit(bool))); connect(primaryEditShortcut, SIGNAL(secondary(bool)), this, SLOT(speedMode(bool))); @@ -696,6 +699,8 @@ void CSVRender::WorldspaceWidget::handleInteractionPress (const WorldspaceHitRes editMode.primarySelectPressed (hit); else if (type == InteractionType_SecondarySelect) editMode.secondarySelectPressed (hit); + else if (type == InteractionType_PrimaryOpen) + editMode.primaryOpenPressed (hit); } CSVRender::EditMode *CSVRender::WorldspaceWidget::getEditMode() @@ -703,6 +708,11 @@ CSVRender::EditMode *CSVRender::WorldspaceWidget::getEditMode() return dynamic_cast (mEditMode->getCurrent()); } +void CSVRender::WorldspaceWidget::primaryOpen(bool activate) +{ + handleInteraction(InteractionType_PrimaryOpen, activate); +} + void CSVRender::WorldspaceWidget::primaryEdit(bool activate) { handleInteraction(InteractionType_PrimaryEdit, activate); diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 9160ca47e..06c182b0c 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -91,6 +91,7 @@ namespace CSVRender InteractionType_PrimarySelect, InteractionType_SecondaryEdit, InteractionType_SecondarySelect, + InteractionType_PrimaryOpen, InteractionType_None }; @@ -263,6 +264,8 @@ namespace CSVRender void showToolTip(); + void primaryOpen(bool activate); + void primaryEdit(bool activate); void secondaryEdit(bool activate); @@ -283,6 +286,8 @@ namespace CSVRender void dataDropped(const std::vector& data); + void requestFocus (const std::string& id); + friend class MouseState; }; } diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 4b129d32a..44542c529 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -83,6 +83,9 @@ void CSVWorld::SceneSubView::makeConnections (CSVRender::UnpagedWorldspaceWidget connect(widget, SIGNAL(cellChanged(const CSMWorld::UniversalId&)), this, SLOT(cellSelectionChanged(const CSMWorld::UniversalId&))); + + connect(widget, SIGNAL(requestFocus (const std::string&)), + this, SIGNAL(requestFocus (const std::string&))); } void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget* widget) @@ -94,6 +97,9 @@ void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget* connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); + + connect(widget, SIGNAL(requestFocus (const std::string&)), + this, SIGNAL(requestFocus (const std::string&))); } CSVWidget::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget, widgetType type) diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index 0f18e8c30..85f7d0925 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -82,6 +82,10 @@ namespace CSVWorld void cellSelectionChanged (const CSMWorld::UniversalId& id); void handleDrop(const std::vector& data); + + signals: + + void requestFocus (const std::string& id); }; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index eb7b8e334..11c2be5fc 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -737,7 +737,12 @@ void CSVWorld::Table::requestFocus (const std::string& id) QModelIndex index = mProxyModel->getModelIndex (id, 0); if (index.isValid()) - scrollTo (index, QAbstractItemView::PositionAtTop); + { + // This will scroll to the row. + selectRow (index.row()); + // This will actually select it. + selectionModel()->select (index, QItemSelectionModel::Select | QItemSelectionModel::Rows); + } } void CSVWorld::Table::recordFilterChanged (std::shared_ptr filter) diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 12e29995d..b0bae7fdf 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -165,3 +165,8 @@ bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event) } return false; } + +void CSVWorld::TableSubView::requestFocus (const std::string& id) +{ + mTable->requestFocus(id); +} diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index 7d143d927..1adf862d5 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -60,6 +60,10 @@ namespace CSVWorld void cloneRequest (const CSMWorld::UniversalId& toClone); void createFilterRequest(std::vector< CSMWorld::UniversalId >& types, Qt::DropAction action); + + public slots: + + void requestFocus (const std::string& id); }; }