2018-12-26 23:59:59 -07:00

284 lines
11 KiB
C++

#include "WModifyTab.h"
#include "ui_WModifyTab.h"
#include "CLinkDialog.h"
#include "CSelectInstanceDialog.h"
#include "CWorldEditor.h"
#include "Editor/Undo/UndoCommands.h"
#include <Core/Scene/CScriptNode.h>
#include <QScrollArea>
#include <QScrollBar>
WModifyTab::WModifyTab(CWorldEditor *pEditor, QWidget *pParent)
: QWidget(pParent)
, ui(new Ui::WModifyTab)
, mIsPicking(false)
{
ui->setupUi(this);
mpWorldEditor = pEditor;
ui->PropertyView->SetEditor(mpWorldEditor);
int PropViewWidth = ui->PropertyView->width();
ui->PropertyView->header()->resizeSection(0, PropViewWidth * 0.3);
ui->PropertyView->header()->resizeSection(1, PropViewWidth * 0.3);
ui->PropertyView->header()->setSectionResizeMode(1, QHeaderView::Fixed);
mpInLinkModel = new CLinkModel(this);
mpInLinkModel->SetConnectionType(ELinkType::Incoming);
mpOutLinkModel = new CLinkModel(this);
mpOutLinkModel->SetConnectionType(ELinkType::Outgoing);
mpAddFromViewportAction = new QAction("Choose from viewport", this);
mpAddFromListAction = new QAction("Choose from list", this);
mpAddLinkMenu = new QMenu(this);
mpAddLinkMenu->addAction(mpAddFromViewportAction);
mpAddLinkMenu->addAction(mpAddFromListAction);
ui->AddOutgoingConnectionToolButton->setMenu(mpAddLinkMenu);
ui->AddIncomingConnectionToolButton->setMenu(mpAddLinkMenu);
ui->InLinksTableView->setModel(mpInLinkModel);
ui->OutLinksTableView->setModel(mpOutLinkModel);
connect(ui->InLinksTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnLinkTableDoubleClick(QModelIndex)));
connect(ui->OutLinksTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnLinkTableDoubleClick(QModelIndex)));
connect(ui->InLinksTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(OnLinksSelectionModified()));
connect(ui->OutLinksTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(OnLinksSelectionModified()));
connect(ui->AddOutgoingConnectionToolButton, SIGNAL(triggered(QAction*)), this, SLOT(OnAddLinkActionClicked(QAction*)));
connect(ui->AddIncomingConnectionToolButton, SIGNAL(triggered(QAction*)), this, SLOT(OnAddLinkActionClicked(QAction*)));
connect(ui->DeleteOutgoingConnectionButton, SIGNAL(clicked()), this, SLOT(OnDeleteLinksClicked()));
connect(ui->DeleteIncomingConnectionButton, SIGNAL(clicked()), this, SLOT(OnDeleteLinksClicked()));
connect(ui->EditOutgoingConnectionButton, SIGNAL(clicked()), this, SLOT(OnEditLinkClicked()));
connect(ui->EditIncomingConnectionButton, SIGNAL(clicked()), this, SLOT(OnEditLinkClicked()));
connect(mpWorldEditor, SIGNAL(MapChanged(CWorld*,CGameArea*)), this, SLOT(OnMapChanged()));
connect(mpWorldEditor, SIGNAL(SelectionTransformed()), this, SLOT(OnWorldSelectionTransformed()));
connect(mpWorldEditor, SIGNAL(InstanceLinksModified(const QList<CScriptObject*>&)), this, SLOT(OnInstanceLinksModified(const QList<CScriptObject*>&)));
connect(mpWorldEditor->Selection(), SIGNAL(Modified()), this, SLOT(GenerateUI()));
ClearUI();
}
WModifyTab::~WModifyTab()
{
delete ui;
}
void WModifyTab::ClearUI()
{
ui->ObjectsTabWidget->hide();
ui->PropertyView->SetInstance(nullptr);
mpSelectedNode = nullptr;
}
// ************ PUBLIC SLOTS ************
void WModifyTab::GenerateUI()
{
if (mIsPicking)
mpWorldEditor->ExitPickMode();
if (mpWorldEditor->Selection()->Size() == 1)
{
if (mpSelectedNode != mpWorldEditor->Selection()->Front())
{
mpSelectedNode = mpWorldEditor->Selection()->Front();
if (mpSelectedNode->NodeType() == ENodeType::Script)
{
CScriptNode *pScriptNode = static_cast<CScriptNode*>(mpSelectedNode);
CScriptObject *pObj = pScriptNode->Instance();
// Set up UI
ui->ObjectsTabWidget->show();
ui->PropertyView->SetInstance(pObj);
mpInLinkModel->SetObject(pObj);
mpOutLinkModel->SetObject(pObj);
}
// disabled this for now! implemented it as a quick test, it's cool it works,
// but it's buggy & not ready for deployment
#if 0
else
{
CStructRef Properties = mpSelectedNode->GetProperties();
ui->PropertyView->SetProperties(Properties);
if (Properties.IsValid())
ui->ObjectsTabWidget->show();
}
#endif
ui->InLinksTableView->clearSelection();
ui->OutLinksTableView->clearSelection();
ui->InLinksTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
ui->OutLinksTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
}
}
else
ClearUI();
}
void WModifyTab::OnInstanceLinksModified(const QList<CScriptObject*>& rkInstances)
{
if (mpSelectedNode && mpSelectedNode->NodeType() == ENodeType::Script)
{
CScriptObject *pInstance = static_cast<CScriptNode*>(mpSelectedNode)->Instance();
if (pInstance && rkInstances.contains(pInstance))
{
mpInLinkModel->layoutChanged();
mpOutLinkModel->layoutChanged();
ui->InLinksTableView->clearSelection();
ui->OutLinksTableView->clearSelection();
}
}
}
void WModifyTab::OnWorldSelectionTransformed()
{
ui->PropertyView->UpdateEditorProperties(QModelIndex());
}
void WModifyTab::OnMapChanged()
{
ClearUI();
}
void WModifyTab::OnLinksSelectionModified()
{
if (sender() == ui->InLinksTableView->selectionModel())
{
uint32 NumSelectedRows = ui->InLinksTableView->selectionModel()->selectedRows().size();
ui->EditIncomingConnectionButton->setEnabled(NumSelectedRows == 1);
ui->DeleteIncomingConnectionButton->setEnabled(NumSelectedRows > 0);
}
else
{
uint32 NumSelectedRows = ui->OutLinksTableView->selectionModel()->selectedRows().size();
ui->EditOutgoingConnectionButton->setEnabled(NumSelectedRows == 1);
ui->DeleteOutgoingConnectionButton->setEnabled(NumSelectedRows > 0);
}
}
void WModifyTab::OnAddLinkActionClicked(QAction *pAction)
{
if (mpSelectedNode && mpSelectedNode->NodeType() == ENodeType::Script)
{
mAddLinkType = (sender() == ui->AddOutgoingConnectionToolButton ? ELinkType::Outgoing : ELinkType::Incoming);
if (pAction == mpAddFromViewportAction)
{
mpWorldEditor->EnterPickMode(ENodeType::Script, true, false, false);
connect(mpWorldEditor, SIGNAL(PickModeClick(SRayIntersection,QMouseEvent*)), this, SLOT(OnPickModeClick(SRayIntersection)));
connect(mpWorldEditor, SIGNAL(PickModeExited()), this, SLOT(OnPickModeExit()));
mIsPicking = true;
}
else if (pAction == mpAddFromListAction)
{
if (mIsPicking)
mpWorldEditor->ExitPickMode();
CSelectInstanceDialog Dialog(mpWorldEditor, this);
Dialog.exec();
CScriptObject *pTarget = Dialog.SelectedInstance();
if (pTarget)
{
CLinkDialog *pLinkDialog = mpWorldEditor->LinkDialog();
CScriptObject *pSelected = static_cast<CScriptNode*>(mpSelectedNode)->Instance();
CScriptObject *pSender = (mAddLinkType == ELinkType::Outgoing ? pSelected : pTarget);
CScriptObject *pReceiver = (mAddLinkType == ELinkType::Outgoing ? pTarget : pSelected);
pLinkDialog->NewLink(pSender, pReceiver);
pLinkDialog->show();
}
}
}
}
void WModifyTab::OnPickModeClick(const SRayIntersection& rkIntersect)
{
mpWorldEditor->ExitPickMode();
CScriptObject *pTarget = static_cast<CScriptNode*>(rkIntersect.pNode)->Instance();
if (pTarget)
{
CLinkDialog *pDialog = mpWorldEditor->LinkDialog();
CScriptObject *pSelected = static_cast<CScriptNode*>(mpSelectedNode)->Instance();
CScriptObject *pSender = (mAddLinkType == ELinkType::Outgoing ? pSelected : pTarget);
CScriptObject *pReceiver = (mAddLinkType == ELinkType::Outgoing ? pTarget : pSelected);
pDialog->NewLink(pSender, pReceiver);
pDialog->show();
}
}
void WModifyTab::OnPickModeExit()
{
disconnect(mpWorldEditor, SIGNAL(PickModeClick(SRayIntersection,QMouseEvent*)), this, 0);
disconnect(mpWorldEditor, SIGNAL(PickModeExited()), this, 0);
mIsPicking = false;
}
void WModifyTab::OnDeleteLinksClicked()
{
if (mpSelectedNode && mpSelectedNode->NodeType() == ENodeType::Script)
{
ELinkType Type = (sender() == ui->DeleteOutgoingConnectionButton ? ELinkType::Outgoing : ELinkType::Incoming);
QModelIndexList SelectedIndices = (Type == ELinkType::Outgoing ? ui->OutLinksTableView->selectionModel()->selectedRows() : ui->InLinksTableView->selectionModel()->selectedRows());
if (!SelectedIndices.isEmpty())
{
QVector<uint32> Indices;
for (int iIdx = 0; iIdx < SelectedIndices.size(); iIdx++)
Indices << SelectedIndices[iIdx].row();
CScriptObject *pInst = static_cast<CScriptNode*>(mpSelectedNode)->Instance();
CDeleteLinksCommand *pCmd = new CDeleteLinksCommand(mpWorldEditor, pInst, Type, Indices);
mpWorldEditor->UndoStack().push(pCmd);
}
}
}
void WModifyTab::OnEditLinkClicked()
{
if (mpSelectedNode && mpSelectedNode->NodeType() == ENodeType::Script)
{
ELinkType Type = (sender() == ui->EditOutgoingConnectionButton ? ELinkType::Outgoing : ELinkType::Incoming);
QModelIndexList SelectedIndices = (Type == ELinkType::Outgoing ? ui->OutLinksTableView->selectionModel()->selectedRows() : ui->InLinksTableView->selectionModel()->selectedRows());
if (SelectedIndices.size() == 1)
{
CScriptObject *pInst = static_cast<CScriptNode*>(mpSelectedNode)->Instance();
CLinkDialog *pDialog = mpWorldEditor->LinkDialog();
pDialog->EditLink(pInst->Link(Type, SelectedIndices.front().row()));
pDialog->show();
}
}
}
// ************ PRIVATE SLOTS ************
void WModifyTab::OnLinkTableDoubleClick(QModelIndex Index)
{
if (Index.column() == 0)
{
// The link table will only be visible if the selected node is a script node
CScriptNode *pNode = static_cast<CScriptNode*>(mpSelectedNode);
uint32 InstanceID;
if (sender() == ui->InLinksTableView)
InstanceID = pNode->Instance()->Link(ELinkType::Incoming, Index.row())->SenderID();
else if (sender() == ui->OutLinksTableView)
InstanceID = pNode->Instance()->Link(ELinkType::Outgoing, Index.row())->ReceiverID();
CScriptNode *pLinkedNode = pNode->Scene()->NodeForInstanceID(InstanceID);
if (pLinkedNode)
mpWorldEditor->ClearAndSelectNode(pLinkedNode);
ui->InLinksTableView->clearSelection();
ui->OutLinksTableView->clearSelection();
}
}