Implemented World Editor Link/Unlink actions

This commit is contained in:
parax0 2016-03-07 14:44:09 -07:00
parent 93d6e8dd14
commit 0b5c7c8e90
6 changed files with 219 additions and 18 deletions

View File

@ -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 += \

View File

@ -0,0 +1,89 @@
#ifndef CCONFIRMUNLINKDIALOG_H
#define CCONFIRMUNLINKDIALOG_H
#include <QDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
// 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

View File

@ -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 <QMessageBox>
#include <QOpenGLContext>
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<CScriptNode*>(rkIntersect.pNode)->Object();
}
else
{
mpNewLinkReceiver = static_cast<CScriptNode*>(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<CScriptNode*> SelectedScriptNodes;
foreach (CSceneNode *pNode, mSelection)
{
if (pNode->NodeType() == eScriptNode)
SelectedScriptNodes << static_cast<CScriptNode*>(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<u32> 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<u32> 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.

View File

@ -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();

View File

@ -494,6 +494,9 @@
</property>
</action>
<action name="ActionLink">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/Link.png</normaloff>:/icons/Link.png</iconset>

View File

@ -79,7 +79,7 @@
</widget>
<widget class="QWidget" name="ConnectionsTab">
<attribute name="title">
<string>Connections</string>
<string>Links</string>
</attribute>
<layout class="QVBoxLayout" name="ConnectionsLayout">
<property name="leftMargin">
@ -169,7 +169,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<iconset>
<normaloff>:/icons/Plus.png</normaloff>:/icons/Plus.png</iconset>
</property>
<property name="popupMode">
@ -221,7 +221,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<iconset>
<normaloff>:/icons/Minus v2.png</normaloff>:/icons/Minus v2.png</iconset>
</property>
</widget>
@ -282,7 +282,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<iconset>
<normaloff>:/icons/Plus.png</normaloff>:/icons/Plus.png</iconset>
</property>
<property name="popupMode">
@ -325,7 +325,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<iconset>
<normaloff>:/icons/Minus v2.png</normaloff>:/icons/Minus v2.png</iconset>
</property>
</widget>
@ -359,8 +359,6 @@
<header>Editor/PropertyEdit/CPropertyView.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../Icons.qrc"/>
</resources>
<resources/>
<connections/>
</ui>