From 0b5c7c8e9083171611f6574a8bf1b1f49c57f1be Mon Sep 17 00:00:00 2001 From: parax0 Date: Mon, 7 Mar 2016 14:44:09 -0700 Subject: [PATCH] Implemented World Editor Link/Unlink actions --- src/Editor/Editor.pro | 3 +- src/Editor/WorldEditor/CConfirmUnlinkDialog.h | 89 +++++++++++++ src/Editor/WorldEditor/CWorldEditor.cpp | 119 ++++++++++++++++-- src/Editor/WorldEditor/CWorldEditor.h | 9 ++ src/Editor/WorldEditor/CWorldEditor.ui | 3 + src/Editor/WorldEditor/WModifyTab.ui | 14 +-- 6 files changed, 219 insertions(+), 18 deletions(-) create mode 100644 src/Editor/WorldEditor/CConfirmUnlinkDialog.h diff --git a/src/Editor/Editor.pro b/src/Editor/Editor.pro index 8e1eacb2..d3159ec5 100644 --- a/src/Editor/Editor.pro +++ b/src/Editor/Editor.pro @@ -148,7 +148,8 @@ HEADERS += \ WorldEditor/CSelectInstanceDialog.h \ Undo/CAddLinkCommand.h \ Undo/CDeleteLinksCommand.h \ - Undo/CEditLinkCommand.h + Undo/CEditLinkCommand.h \ + WorldEditor/CConfirmUnlinkDialog.h # Source Files SOURCES += \ diff --git a/src/Editor/WorldEditor/CConfirmUnlinkDialog.h b/src/Editor/WorldEditor/CConfirmUnlinkDialog.h new file mode 100644 index 00000000..598a4f71 --- /dev/null +++ b/src/Editor/WorldEditor/CConfirmUnlinkDialog.h @@ -0,0 +1,89 @@ +#ifndef CCONFIRMUNLINKDIALOG_H +#define CCONFIRMUNLINKDIALOG_H + +#include +#include +#include +#include +#include + +// This class is basically a workaround for the fact that QMessageBox doesn't allow directly controlling button placement +class CConfirmUnlinkDialog : public QDialog +{ + Q_OBJECT +public: + enum EChoice + { + eAll, + eIncomingOnly, + eOutgoingOnly, + eCancel + }; + +private: + QLabel *mpLabel; + QPushButton *mpAllButton; + QPushButton *mpIncomingButton; + QPushButton *mpOutgoingButton; + QPushButton *mpCancelButton; + QHBoxLayout *mpButtonLayout; + QVBoxLayout *mpDialogLayout; + + EChoice mChoice; + +public: + explicit CConfirmUnlinkDialog(QWidget *pParent = 0) + : QDialog(pParent) + { + mpLabel = new QLabel("Which links should be removed from the selected instances?"); + mpAllButton = new QPushButton("All"); + mpIncomingButton = new QPushButton("Incoming Links"); + mpOutgoingButton = new QPushButton("Outgoing Links"); + mpCancelButton = new QPushButton("Cancel"); + + mpButtonLayout = new QHBoxLayout(); + mpButtonLayout->addWidget(mpAllButton); + mpButtonLayout->addWidget(mpIncomingButton); + mpButtonLayout->addWidget(mpOutgoingButton); + mpButtonLayout->addWidget(mpCancelButton); + + mpDialogLayout = new QVBoxLayout(); + mpDialogLayout->addWidget(mpLabel); + mpDialogLayout->addLayout(mpButtonLayout); + setLayout(mpDialogLayout); + + connect(mpAllButton, SIGNAL(clicked()), this, SLOT(OnAllClicked())); + connect(mpIncomingButton, SIGNAL(clicked()), this, SLOT(OnIncomingClicked())); + connect(mpOutgoingButton, SIGNAL(clicked()), this, SLOT(OnOutgoingClicked())); + connect(mpCancelButton, SIGNAL(clicked()), this, SLOT(OnCancelClicked())); + } + + inline EChoice UserChoice() const { return mChoice; } + +protected slots: + void OnAllClicked() + { + mChoice = eAll; + accept(); + } + + void OnIncomingClicked() + { + mChoice = eIncomingOnly; + accept(); + } + + void OnOutgoingClicked() + { + mChoice = eOutgoingOnly; + accept(); + } + + void OnCancelClicked() + { + mChoice = eCancel; + reject(); + } +}; + +#endif // CCONFIRMUNLINKDIALOG_H diff --git a/src/Editor/WorldEditor/CWorldEditor.cpp b/src/Editor/WorldEditor/CWorldEditor.cpp index b67d468b..75933e98 100644 --- a/src/Editor/WorldEditor/CWorldEditor.cpp +++ b/src/Editor/WorldEditor/CWorldEditor.cpp @@ -1,5 +1,7 @@ #include "CWorldEditor.h" #include "ui_CWorldEditor.h" + +#include "CConfirmUnlinkDialog.h" #include "CLayerEditor.h" #include "WModifyTab.h" #include "WInstancesTab.h" @@ -22,19 +24,20 @@ #include #include -CWorldEditor::CWorldEditor(QWidget *parent) : - INodeEditor(parent), - ui(new Ui::CWorldEditor) +CWorldEditor::CWorldEditor(QWidget *parent) + : INodeEditor(parent) + , ui(new Ui::CWorldEditor) + , mpArea(nullptr) + , mpWorld(nullptr) + , mpLinkDialog(new CLinkDialog(this, this)) + , mpPoiDialog(nullptr) + , mIsMakingLink(false) + , mpNewLinkSender(nullptr) + , mpNewLinkReceiver(nullptr) { Log::Write("Creating World Editor"); ui->setupUi(this); - mpArea = nullptr; - mpWorld = nullptr; - mpLinkDialog = new CLinkDialog(this, this); - mpPoiDialog = nullptr; - mGizmoHovering = false; - mGizmoTransforming = false; mSelectionNodeFlags = eScriptNode | eLightNode; // Start refresh timer @@ -88,6 +91,8 @@ CWorldEditor::CWorldEditor(QWidget *parent) : connect(ui->TransformSpinBox, SIGNAL(ValueChanged(CVector3f)), this, SLOT(OnTransformSpinBoxModified(CVector3f))); connect(ui->TransformSpinBox, SIGNAL(EditingDone(CVector3f)), this, SLOT(OnTransformSpinBoxEdited(CVector3f))); connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double))); + connect(ui->ActionLink, SIGNAL(toggled(bool)), this, SLOT(OnLinkButtonToggled(bool))); + connect(ui->ActionUnlink, SIGNAL(triggered()), this, SLOT(OnUnlinkClicked())); connect(&mUndoStack, SIGNAL(indexChanged(int)), this, SLOT(OnUndoStackIndexChanged())); connect(ui->ActionSave, SIGNAL(triggered()), this, SLOT(Save())); @@ -488,6 +493,102 @@ void CWorldEditor::GizmoModeChanged(CGizmo::EGizmoMode mode) } // ************ PRIVATE SLOTS ************ +void CWorldEditor::OnLinkButtonToggled(bool Enabled) +{ + if (Enabled) + { + EnterPickMode(eScriptNode, true, false, false); + connect(this, SIGNAL(PickModeClick(SRayIntersection,QMouseEvent*)), this, SLOT(OnLinkClick(SRayIntersection))); + connect(this, SIGNAL(PickModeExited()), this, SLOT(OnLinkEnd())); + mIsMakingLink = true; + mpNewLinkSender = nullptr; + mpNewLinkReceiver = nullptr; + } + + else + { + if (mIsMakingLink) + ExitPickMode(); + } +} + +void CWorldEditor::OnLinkClick(const SRayIntersection& rkIntersect) +{ + if (!mpNewLinkSender) + { + mpNewLinkSender = static_cast(rkIntersect.pNode)->Object(); + } + + else + { + mpNewLinkReceiver = static_cast(rkIntersect.pNode)->Object(); + mpLinkDialog->NewLink(mpNewLinkSender, mpNewLinkReceiver); + mpLinkDialog->show(); + ExitPickMode(); + } +} + +void CWorldEditor::OnLinkEnd() +{ + disconnect(this, SIGNAL(PickModeClick(SRayIntersection,QMouseEvent*)), this, SLOT(OnLinkClick(SRayIntersection))); + disconnect(this, SIGNAL(PickModeExited()), this, SLOT(OnLinkEnd())); + ui->ActionLink->setChecked(false); + mIsMakingLink = false; + mpNewLinkSender = nullptr; + mpNewLinkReceiver = nullptr; +} + +void CWorldEditor::OnUnlinkClicked() +{ + QList SelectedScriptNodes; + + foreach (CSceneNode *pNode, mSelection) + { + if (pNode->NodeType() == eScriptNode) + SelectedScriptNodes << static_cast(pNode); + } + + if (!SelectedScriptNodes.isEmpty()) + { + CConfirmUnlinkDialog Dialog(this); + Dialog.exec(); + + if (Dialog.UserChoice() != CConfirmUnlinkDialog::eCancel) + { + mUndoStack.beginMacro("Unlink"); + bool UnlinkIncoming = (Dialog.UserChoice() != CConfirmUnlinkDialog::eOutgoingOnly); + bool UnlinkOutgoing = (Dialog.UserChoice() != CConfirmUnlinkDialog::eIncomingOnly); + + foreach (CScriptNode *pNode, SelectedScriptNodes) + { + CScriptObject *pInst = pNode->Object(); + + if (UnlinkIncoming) + { + QVector LinkIndices; + for (u32 iLink = 0; iLink < pInst->NumLinks(eIncoming); iLink++) + LinkIndices << iLink; + + CDeleteLinksCommand *pCmd = new CDeleteLinksCommand(this, pInst, eIncoming, LinkIndices); + mUndoStack.push(pCmd); + } + + if (UnlinkOutgoing) + { + QVector LinkIndices; + for (u32 iLink = 0; iLink < pInst->NumLinks(eOutgoing); iLink++) + LinkIndices << iLink; + + CDeleteLinksCommand *pCmd = new CDeleteLinksCommand(this, pInst, eOutgoing, LinkIndices); + mUndoStack.push(pCmd); + } + } + + mUndoStack.endMacro(); + } + } +} + void CWorldEditor::OnUndoStackIndexChanged() { // Check the commands that have been executed on the undo stack and find out whether any of them affect the clean state. diff --git a/src/Editor/WorldEditor/CWorldEditor.h b/src/Editor/WorldEditor/CWorldEditor.h index 25ffc010..372e96c5 100644 --- a/src/Editor/WorldEditor/CWorldEditor.h +++ b/src/Editor/WorldEditor/CWorldEditor.h @@ -39,6 +39,10 @@ class CWorldEditor : public INodeEditor CLinkDialog *mpLinkDialog; CPoiMapEditDialog *mpPoiDialog; + bool mIsMakingLink; + CScriptObject *mpNewLinkSender; + CScriptObject *mpNewLinkReceiver; + public: explicit CWorldEditor(QWidget *parent = 0); ~CWorldEditor(); @@ -68,6 +72,11 @@ protected: void GizmoModeChanged(CGizmo::EGizmoMode mode); private slots: + void OnLinkButtonToggled(bool Enabled); + void OnLinkClick(const SRayIntersection& rkIntersect); + void OnLinkEnd(); + void OnUnlinkClicked(); + void OnUndoStackIndexChanged(); void OnPickModeEnter(QCursor Cursor); void OnPickModeExit(); diff --git a/src/Editor/WorldEditor/CWorldEditor.ui b/src/Editor/WorldEditor/CWorldEditor.ui index c4f0ed4c..9c639bd3 100644 --- a/src/Editor/WorldEditor/CWorldEditor.ui +++ b/src/Editor/WorldEditor/CWorldEditor.ui @@ -494,6 +494,9 @@ + + true + :/icons/Link.png:/icons/Link.png diff --git a/src/Editor/WorldEditor/WModifyTab.ui b/src/Editor/WorldEditor/WModifyTab.ui index 07adde18..dfa36fae 100644 --- a/src/Editor/WorldEditor/WModifyTab.ui +++ b/src/Editor/WorldEditor/WModifyTab.ui @@ -79,7 +79,7 @@ - Connections + Links @@ -169,7 +169,7 @@ - + :/icons/Plus.png:/icons/Plus.png @@ -221,7 +221,7 @@ - + :/icons/Minus v2.png:/icons/Minus v2.png @@ -282,7 +282,7 @@ - + :/icons/Plus.png:/icons/Plus.png @@ -325,7 +325,7 @@ - + :/icons/Minus v2.png:/icons/Minus v2.png @@ -359,8 +359,6 @@
Editor/PropertyEdit/CPropertyView.h
- - - +