diff --git a/CHANGELOG.md b/CHANGELOG.md index 16174087a9..f6c137b4ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -189,6 +189,7 @@ Bug #8064: Lua move360 script doesn't respect the enableZoom/disableZoom Camera interface setting Feature #1415: Infinite fall failsafe Feature #2566: Handle NAM9 records for manual cell references + Feature #3501: OpenMW-CS: Instance Editing - Shortcuts for axial locking Feature #3537: Shader-based water ripples Feature #5173: Support for NiFogProperty Feature #5492: Let rain and snow collide with statics diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index ba3a544f36..7b3b827583 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -376,6 +376,13 @@ void CSMPrefs::State::declare() declareShortcut(mValues->mKeyBindings.mSceneSave8, "Save Group 8"); declareShortcut(mValues->mKeyBindings.mSceneGroup9, "Selection Group 9"); declareShortcut(mValues->mKeyBindings.mSceneSave9, "Save Group 9"); + declareShortcut(mValues->mKeyBindings.mSceneAxisX, "X Axis Movement Lock"); + declareShortcut(mValues->mKeyBindings.mSceneAxisY, "Y Axis Movement Lock"); + declareShortcut(mValues->mKeyBindings.mSceneAxisZ, "Z Axis Movement Lock"); + declareShortcut(mValues->mKeyBindings.mSceneMoveSubmode, "Move Object Submode"); + declareShortcut(mValues->mKeyBindings.mSceneScaleSubmode, "Scale Object Submode"); + declareShortcut(mValues->mKeyBindings.mSceneRotateSubmode, "Rotate Object Submode"); + declareShortcut(mValues->mKeyBindings.mSceneCameraCycle, "Cycle Camera Mode"); declareSubcategory("1st/Free Camera"); declareShortcut(mValues->mKeyBindings.mFreeForward, "Forward"); diff --git a/apps/opencs/model/prefs/values.hpp b/apps/opencs/model/prefs/values.hpp index b2bf87d753..c4b7010aaf 100644 --- a/apps/opencs/model/prefs/values.hpp +++ b/apps/opencs/model/prefs/values.hpp @@ -436,19 +436,19 @@ namespace CSMPrefs Settings::SettingValue mReporttableRemove{ mIndex, sName, "reporttable-remove", "Delete" }; Settings::SettingValue mReporttableReplace{ mIndex, sName, "reporttable-replace", "" }; Settings::SettingValue mReporttableRefresh{ mIndex, sName, "reporttable-refresh", "" }; - Settings::SettingValue mSceneNaviPrimary{ mIndex, sName, "scene-navi-primary", "LMB" }; - Settings::SettingValue mSceneNaviSecondary{ mIndex, sName, "scene-navi-secondary", "Ctrl+LMB" }; - Settings::SettingValue mSceneOpenPrimary{ mIndex, sName, "scene-open-primary", "Shift+LMB" }; + Settings::SettingValue mSceneNaviPrimary{ mIndex, sName, "scene-navi-primary", "MMB" }; + Settings::SettingValue mSceneNaviSecondary{ mIndex, sName, "scene-navi-secondary", "Ctrl+MMB" }; + Settings::SettingValue mSceneOpenPrimary{ mIndex, sName, "scene-open-primary", "Shift+RMB" }; Settings::SettingValue mSceneEditPrimary{ mIndex, sName, "scene-edit-primary", "RMB" }; Settings::SettingValue mSceneEditSecondary{ mIndex, sName, "scene-edit-secondary", "Ctrl+RMB" }; - Settings::SettingValue mSceneSelectPrimary{ mIndex, sName, "scene-select-primary", "MMB" }; + Settings::SettingValue mSceneSelectPrimary{ mIndex, sName, "scene-select-primary", "LMB" }; Settings::SettingValue mSceneSelectSecondary{ mIndex, sName, "scene-select-secondary", - "Ctrl+MMB" }; - Settings::SettingValue mSceneSelectTertiary{ mIndex, sName, "scene-select-tertiary", "Shift+MMB" }; + "Ctrl+LMB" }; + Settings::SettingValue mSceneSelectTertiary{ mIndex, sName, "scene-select-tertiary", "Shift+LMB" }; Settings::SettingValue mSceneSpeedModifier{ mIndex, sName, "scene-speed-modifier", "Shift" }; Settings::SettingValue mSceneDelete{ mIndex, sName, "scene-delete", "Delete" }; Settings::SettingValue mSceneInstanceDropTerrain{ mIndex, sName, "scene-instance-drop-terrain", - "G" }; + "B" }; Settings::SettingValue mSceneInstanceDropCollision{ mIndex, sName, "scene-instance-drop-collision", "H" }; Settings::SettingValue mSceneInstanceDropTerrainSeparately{ mIndex, sName, @@ -491,6 +491,14 @@ namespace CSMPrefs Settings::SettingValue mSceneSave8{ mIndex, sName, "scene-save-8", "Ctrl+8" }; Settings::SettingValue mSceneGroup9{ mIndex, sName, "scene-group-9", "9" }; Settings::SettingValue mSceneSave9{ mIndex, sName, "scene-save-9", "Ctrl+9" }; + Settings::SettingValue mSceneAxisX{ mIndex, sName, "scene-axis-x", "X" }; + Settings::SettingValue mSceneAxisY{ mIndex, sName, "scene-axis-y", "Y" }; + Settings::SettingValue mSceneAxisZ{ mIndex, sName, "scene-axis-z", "Z" }; + Settings::SettingValue mSceneMoveSubmode{ mIndex, sName, "scene-submode-move", "G" }; + Settings::SettingValue mSceneScaleSubmode{ mIndex, sName, "scene-submode-scale", "V" }; + Settings::SettingValue mSceneRotateSubmode{ mIndex, sName, "scene-submode-rotate", "R" }; + Settings::SettingValue mSceneCameraCycle{ mIndex, sName, "scene-cam-cycle", "Tab" }; + Settings::SettingValue mSceneToggleMarkers{ mIndex, sName, "scene-toggle-markers", "F4" }; Settings::SettingValue mFreeForward{ mIndex, sName, "free-forward", "W" }; Settings::SettingValue mFreeBackward{ mIndex, sName, "free-backward", "S" }; Settings::SettingValue mFreeLeft{ mIndex, sName, "free-left", "A" }; diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index bc821ee25a..5851311035 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -252,6 +252,48 @@ void CSVRender::InstanceMode::getSelectionGroup(const int group) getWorldspaceWidget().selectGroup(targets); } +void CSVRender::InstanceMode::setDragAxis(const char axis) +{ + int newDragAxis; + + const std::vector> selection = getWorldspaceWidget().getSelection(Mask_Reference); + + if (selection.empty()) + return; + + switch (axis) + { + case 'x': + newDragAxis = 0; + break; + case 'y': + newDragAxis = 1; + break; + case 'z': + newDragAxis = 2; + break; + default: + return; + } + + if (newDragAxis == mDragAxis) + newDragAxis = -1; + + if (mSubModeId == "move") + { + mObjectsAtDragStart.clear(); + + for (const auto& object : selection) + if (CSVRender::ObjectTag* objectTag = dynamic_cast(object.get())) + { + const osg::Vec3f thisPoint = objectTag->mObject->getPosition().asVec3(); + mDragStart = thisPoint; + mObjectsAtDragStart.emplace_back(thisPoint); + } + } + mDragAxis = newDragAxis; +} + CSVRender::InstanceMode::InstanceMode( WorldspaceWidget* worldspaceWidget, osg::ref_ptr parentNode, QWidget* parent) : EditMode(worldspaceWidget, Misc::ScalableIcon::load(":scenetoolbar/editing-instance"), @@ -306,6 +348,19 @@ CSVRender::InstanceMode::InstanceMode( connect(new CSMPrefs::Shortcut("scene-save-" + std::to_string(i), worldspaceWidget), qOverload<>(&CSMPrefs::Shortcut::activated), this, [this, i] { this->saveSelectionGroup(i); }); } + + connect(new CSMPrefs::Shortcut("scene-submode-move", worldspaceWidget), qOverload<>(&CSMPrefs::Shortcut::activated), + this, [this] { mSubMode->setButton("move"); }); + + connect(new CSMPrefs::Shortcut("scene-submode-scale", worldspaceWidget), + qOverload<>(&CSMPrefs::Shortcut::activated), this, [this] { mSubMode->setButton("scale"); }); + + connect(new CSMPrefs::Shortcut("scene-submode-rotate", worldspaceWidget), + qOverload<>(&CSMPrefs::Shortcut::activated), this, [this] { mSubMode->setButton("rotate"); }); + + for (const char axis : "xyz") + connect(new CSMPrefs::Shortcut(std::string("scene-axis-") + axis, worldspaceWidget), + qOverload<>(&CSMPrefs::Shortcut::activated), this, [this, axis] { this->setDragAxis(axis); }); } void CSVRender::InstanceMode::activate(CSVWidget::SceneToolbar* toolbar) diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index 9267823e22..45d7c2b6fd 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -133,6 +133,7 @@ namespace CSVRender private slots: + void setDragAxis(const char axis); void subModeChanged(const std::string& id); void deleteSelectedInstances(); void cloneSelectedInstances(); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 089cb01f07..0a02ae456b 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -75,6 +75,7 @@ CSVRender::WorldspaceWidget::WorldspaceWidget(CSMDoc::Document& document, QWidge , mShowToolTips(false) , mToolTipDelay(0) , mInConstructor(true) + , mSelectedNavigationMode(0) { setAcceptDrops(true); @@ -146,6 +147,10 @@ CSVRender::WorldspaceWidget::WorldspaceWidget(CSMDoc::Document& document, QWidge connect(new CSMPrefs::Shortcut("scene-clear-selection", this), qOverload<>(&CSMPrefs::Shortcut::activated), this, [this] { this->clearSelection(Mask_Reference); }); + CSMPrefs::Shortcut* switchPerspectiveShortcut = new CSMPrefs::Shortcut("scene-cam-cycle", this); + connect(switchPerspectiveShortcut, qOverload<>(&CSMPrefs::Shortcut::activated), this, + &WorldspaceWidget::cycleNavigationMode); + mInConstructor = false; } @@ -235,9 +240,11 @@ CSVWidget::SceneToolMode* CSVRender::WorldspaceWidget::makeNavigationSelector(CS tool), "orbit"); - connect(tool, &CSVWidget::SceneToolMode::modeChanged, this, &WorldspaceWidget::selectNavigationMode); + mCameraMode = tool; - return tool; + connect(mCameraMode, &CSVWidget::SceneToolMode::modeChanged, this, &WorldspaceWidget::selectNavigationMode); + + return mCameraMode; } CSVWidget::SceneToolToggle2* CSVRender::WorldspaceWidget::makeSceneVisibilitySelector(CSVWidget::SceneToolbar* parent) @@ -769,6 +776,26 @@ void CSVRender::WorldspaceWidget::toggleHiddenInstances() objectTag->mObject->getRootNode()->setNodeMask(firstMask); } +void CSVRender::WorldspaceWidget::cycleNavigationMode() +{ + switch (++mSelectedNavigationMode) + { + case (CameraMode::FirstPerson): + mCameraMode->setButton("1st"); + break; + case (CameraMode::Orbit): + mCameraMode->setButton("orbit"); + break; + case (CameraMode::Free): + mCameraMode->setButton("free"); + break; + default: + mCameraMode->setButton("1st"); + mSelectedNavigationMode = 0; + break; + } +} + void CSVRender::WorldspaceWidget::handleInteraction(InteractionType type, bool activate) { if (activate) diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 06470d2883..9a7df38620 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -75,6 +75,7 @@ namespace CSVRender CSMDoc::Document& mDocument; unsigned int mInteractionMask; CSVWidget::SceneToolMode* mEditMode; + CSVWidget::SceneToolMode* mCameraMode; bool mLocked; int mDragMode; bool mDragging; @@ -89,6 +90,7 @@ namespace CSVRender bool mShowToolTips; int mToolTipDelay; bool mInConstructor; + int mSelectedNavigationMode; public: enum DropType @@ -225,6 +227,13 @@ namespace CSVRender Button_Terrain = 0x8 }; + enum CameraMode + { + FirstPerson, + Orbit, + Free + }; + virtual void addVisibilitySelectorButtons(CSVWidget::SceneToolToggle2* tool); virtual void addEditModeSelectorButtons(CSVWidget::SceneToolMode* tool); @@ -240,6 +249,8 @@ namespace CSVRender bool getSpeedMode(); + void cycleNavigationMode(); + private: void dragEnterEvent(QDragEnterEvent* event) override;