From ce0c5441689997f7286a180753ad43f21b97c777 Mon Sep 17 00:00:00 2001 From: Aruki Date: Sun, 12 Feb 2017 00:34:04 -0700 Subject: [PATCH] Added new WIP UI to the world editor for loading worlds/areas --- src/Core/Resource/CWorld.cpp | 12 +- src/Editor/CEditorApplication.cpp | 4 +- src/Editor/CProjectOverviewDialog.cpp | 2 +- src/Editor/CStartWindow.cpp | 14 +- src/Editor/Editor.pro | 14 +- src/Editor/Widgets/CTimedLineEdit.h | 49 +++ src/Editor/WorldEditor/CScriptEditSidebar.cpp | 17 + src/Editor/WorldEditor/CScriptEditSidebar.h | 28 ++ src/Editor/WorldEditor/CWorldEditor.cpp | 88 +++-- src/Editor/WorldEditor/CWorldEditor.h | 14 +- src/Editor/WorldEditor/CWorldEditor.ui | 341 ++++++++---------- src/Editor/WorldEditor/CWorldInfoSidebar.cpp | 55 +++ src/Editor/WorldEditor/CWorldInfoSidebar.h | 31 ++ src/Editor/WorldEditor/CWorldInfoSidebar.ui | 73 ++++ src/Editor/WorldEditor/CWorldTreeModel.cpp | 268 ++++++++++++++ src/Editor/WorldEditor/CWorldTreeModel.h | 53 +++ src/Editor/WorldEditor/WCreateTab.cpp | 21 +- src/Editor/WorldEditor/WCreateTab.h | 5 +- src/Editor/WorldEditor/WInstancesTab.cpp | 38 +- src/Editor/WorldEditor/WInstancesTab.h | 6 +- src/Editor/WorldEditor/WModifyTab.cpp | 23 +- src/Editor/WorldEditor/WModifyTab.h | 4 +- 22 files changed, 871 insertions(+), 289 deletions(-) create mode 100644 src/Editor/Widgets/CTimedLineEdit.h create mode 100644 src/Editor/WorldEditor/CScriptEditSidebar.cpp create mode 100644 src/Editor/WorldEditor/CScriptEditSidebar.h create mode 100644 src/Editor/WorldEditor/CWorldInfoSidebar.cpp create mode 100644 src/Editor/WorldEditor/CWorldInfoSidebar.h create mode 100644 src/Editor/WorldEditor/CWorldInfoSidebar.ui create mode 100644 src/Editor/WorldEditor/CWorldTreeModel.cpp create mode 100644 src/Editor/WorldEditor/CWorldTreeModel.h diff --git a/src/Core/Resource/CWorld.cpp b/src/Core/Resource/CWorld.cpp index 21946b42..3169a6aa 100644 --- a/src/Core/Resource/CWorld.cpp +++ b/src/Core/Resource/CWorld.cpp @@ -38,9 +38,15 @@ CDependencyTree* CWorld::BuildDependencyTree() const void CWorld::SetAreaLayerInfo(CGameArea *pArea) { - // The AreaIndex parameter is a placeholder until an improved world loader is implemented. - // For now it's the easiest/fastest way to do this because this function is called from - // the start window and the start window already knows the area index. + for (u32 iArea = 0; iArea < mAreas.size(); iArea++) + { + if (mAreas[iArea].AreaResID == pArea->ID()) + { + pArea->SetWorldIndex(iArea); + break; + } + } + SArea& AreaInfo = mAreas[pArea->WorldIndex()]; for (u32 iLyr = 0; iLyr < pArea->NumScriptLayers(); iLyr++) diff --git a/src/Editor/CEditorApplication.cpp b/src/Editor/CEditorApplication.cpp index 284fd76d..c0f454b6 100644 --- a/src/Editor/CEditorApplication.cpp +++ b/src/Editor/CEditorApplication.cpp @@ -56,9 +56,11 @@ bool CEditorApplication::CloseProject() mpResourceBrowser->close(); mpProjectDialog->close(); - delete mpActiveProject; + // Emit before actually deleting the project to allow editor references to clean up + CGameProject *pOldProj = mpActiveProject; mpActiveProject = nullptr; emit ActiveProjectChanged(nullptr); + delete pOldProj; } return true; diff --git a/src/Editor/CProjectOverviewDialog.cpp b/src/Editor/CProjectOverviewDialog.cpp index 70c921f0..97da8867 100644 --- a/src/Editor/CProjectOverviewDialog.cpp +++ b/src/Editor/CProjectOverviewDialog.cpp @@ -134,7 +134,7 @@ void CProjectOverviewDialog::LaunchEditor() { pArea->SetWorldIndex(AreaIdx); mpWorld->SetAreaLayerInfo(pArea); - gpEdApp->WorldEditor()->SetArea(mpWorld, pArea); + gpEdApp->WorldEditor()->SetArea(mpWorld, AreaIdx); gpEdApp->WorldEditor()->showMaximized(); } diff --git a/src/Editor/CStartWindow.cpp b/src/Editor/CStartWindow.cpp index 48bbfef6..c4517500 100644 --- a/src/Editor/CStartWindow.cpp +++ b/src/Editor/CStartWindow.cpp @@ -182,19 +182,7 @@ void CStartWindow::on_LaunchWorldEditorButton_clicked() { Log::ClearErrorLog(); - CAssetID AreaID = mpWorld->AreaResourceID(mSelectedAreaIndex); - TString AreaPath = mpWorld->Entry()->CookedAssetPath().GetFileDirectory() + AreaID.ToString() + ".MREA"; - TResPtr pArea = gpResourceStore->LoadResource(AreaPath); - - if (!pArea) - { - QMessageBox::warning(this, "Error", "Couldn't load area!"); - return; - } - - pArea->SetWorldIndex(mSelectedAreaIndex); - mpWorld->SetAreaLayerInfo(pArea); - mpWorldEditor->SetArea(mpWorld, pArea); + mpWorldEditor->SetArea(mpWorld, mSelectedAreaIndex); gpResourceStore->DestroyUnreferencedResources(); mpWorldEditor->setWindowModality(Qt::WindowModal); diff --git a/src/Editor/Editor.pro b/src/Editor/Editor.pro index 1e5c854a..80554c98 100644 --- a/src/Editor/Editor.pro +++ b/src/Editor/Editor.pro @@ -181,7 +181,11 @@ HEADERS += \ CEditorApplication.h \ IEditor.h \ Widgets/CResourceSelector.h \ - CExportGameDialog.h + CExportGameDialog.h \ + WorldEditor/CScriptEditSidebar.h \ + WorldEditor/CWorldInfoSidebar.h \ + WorldEditor/CWorldTreeModel.h \ + Widgets/CTimedLineEdit.h # Source Files SOURCES += \ @@ -246,7 +250,10 @@ SOURCES += \ ResourceBrowser/CResourceBrowser.cpp \ CEditorApplication.cpp \ Widgets/CResourceSelector.cpp \ - CExportGameDialog.cpp + CExportGameDialog.cpp \ + WorldEditor/CScriptEditSidebar.cpp \ + WorldEditor/CWorldInfoSidebar.cpp \ + WorldEditor/CWorldTreeModel.cpp # UI Files FORMS += \ @@ -271,4 +278,5 @@ FORMS += \ WorldEditor/CCollisionRenderSettingsDialog.ui \ CProjectOverviewDialog.ui \ ResourceBrowser/CResourceBrowser.ui \ - CExportGameDialog.ui + CExportGameDialog.ui \ + WorldEditor/CWorldInfoSidebar.ui diff --git a/src/Editor/Widgets/CTimedLineEdit.h b/src/Editor/Widgets/CTimedLineEdit.h new file mode 100644 index 00000000..2a9b1781 --- /dev/null +++ b/src/Editor/Widgets/CTimedLineEdit.h @@ -0,0 +1,49 @@ +#ifndef CTIMEDLINEEDIT_H +#define CTIMEDLINEEDIT_H + +#include +#include + +// Simple line edit subclass that emits a signal when the user stops typing. +class CTimedLineEdit : public QLineEdit +{ + Q_OBJECT + + QString mCachedText; + float mTimeoutDuration; + QTimer mTimer; + +public: + CTimedLineEdit(QWidget *pParent = 0) + : QLineEdit(pParent) + , mTimeoutDuration(0.3f) + { + connect(this, SIGNAL(textChanged(QString)), this, SLOT(OnTextChanged())); + connect(&mTimer, SIGNAL(timeout()), this, SLOT(OnTimeout())); + } + + inline void SetTimeoutDuration(float Duration) { mTimeoutDuration = Duration; } + inline float TimeoutDuration() const { return mTimeoutDuration; } + +signals: + void StoppedTyping(const QString& rkText); + +protected slots: + virtual void OnTextChanged() + { + mTimer.start(mTimeoutDuration * 1000); + } + + virtual void OnTimeout() + { + mTimer.stop(); + + // Don't emit if the text is the same + if (mCachedText != text()) + emit StoppedTyping(text()); + + mCachedText = text(); + } +}; + +#endif // CTIMEDLINEEDIT_H diff --git a/src/Editor/WorldEditor/CScriptEditSidebar.cpp b/src/Editor/WorldEditor/CScriptEditSidebar.cpp new file mode 100644 index 00000000..b86057c5 --- /dev/null +++ b/src/Editor/WorldEditor/CScriptEditSidebar.cpp @@ -0,0 +1,17 @@ +#include "CScriptEditSidebar.h" +#include "WCreateTab.h" +#include "WModifyTab.h" +#include "WInstancesTab.h" +#include "CWorldEditor.h" + +CScriptEditSidebar::CScriptEditSidebar(CWorldEditor *pEditor) + : QTabWidget(pEditor) +{ + mpCreateTab = new WCreateTab(pEditor, this); + mpModifyTab = new WModifyTab(pEditor, this); + mpInstancesTab = new WInstancesTab(pEditor, this); + + addTab(mpCreateTab, QIcon(":/icons/Create.png"), "Create"); + addTab(mpModifyTab, QIcon(":/icons/Modify.png"), "Modify"); + addTab(mpInstancesTab, QIcon(":/icons/Instances.png"), "Instances"); +} diff --git a/src/Editor/WorldEditor/CScriptEditSidebar.h b/src/Editor/WorldEditor/CScriptEditSidebar.h new file mode 100644 index 00000000..3d845eef --- /dev/null +++ b/src/Editor/WorldEditor/CScriptEditSidebar.h @@ -0,0 +1,28 @@ +#ifndef CSCRIPTEDITSIDEBAR_H +#define CSCRIPTEDITSIDEBAR_H + +#include + +class CWorldEditor; +class WCreateTab; +class WModifyTab; +class WInstancesTab; + +class CScriptEditSidebar : public QTabWidget +{ + Q_OBJECT + + WCreateTab *mpCreateTab; + WModifyTab *mpModifyTab; + WInstancesTab *mpInstancesTab; + +public: + CScriptEditSidebar(CWorldEditor *pEditor); + + // Accessors + inline WCreateTab* CreateTab() const { return mpCreateTab; } + inline WModifyTab* ModifyTab() const { return mpModifyTab; } + inline WInstancesTab* InstancesTab() const { return mpInstancesTab; } +}; + +#endif // CSCRIPTEDITSIDEBAR_H diff --git a/src/Editor/WorldEditor/CWorldEditor.cpp b/src/Editor/WorldEditor/CWorldEditor.cpp index 90c4a01a..c604be81 100644 --- a/src/Editor/WorldEditor/CWorldEditor.cpp +++ b/src/Editor/WorldEditor/CWorldEditor.cpp @@ -4,6 +4,7 @@ #include "CLayerEditor.h" #include "CRepackInfoDialog.h" #include "CTemplateMimeData.h" +#include "WCreateTab.h" #include "WModifyTab.h" #include "WInstancesTab.h" @@ -52,9 +53,7 @@ CWorldEditor::CWorldEditor(QWidget *parent) // Initialize UI stuff ui->MainViewport->SetScene(this, &mScene); - ui->CreateTabContents->SetEditor(this); - ui->ModifyTabContents->SetEditor(this); - ui->InstancesTabContents->SetEditor(this, &mScene); + ui->MainViewport->setAcceptDrops(true); ui->TransformSpinBox->SetOrientation(Qt::Horizontal); ui->TransformSpinBox->layout()->setContentsMargins(0,0,0,0); ui->CamSpeedSpinBox->SetDefaultValue(1.0); @@ -65,6 +64,18 @@ CWorldEditor::CWorldEditor(QWidget *parent) ui->menuEdit->insertActions(ui->ActionCut, mUndoActions); ui->menuEdit->insertSeparator(ui->ActionCut); + // Initialize sidebar + mpCurSidebarWidget = nullptr; + mpRightSidebarLayout = new QVBoxLayout(); + mpRightSidebarLayout->setContentsMargins(0, 0, 0, 0); + ui->RightSidebarFrame->setLayout(mpRightSidebarLayout); + + mpWorldInfoSidebar = new CWorldInfoSidebar(this); + mpWorldInfoSidebar->setHidden(true); + mpScriptSidebar = new CScriptEditSidebar(this); + mpScriptSidebar->setHidden(true); + SetSidebarWidget(mpWorldInfoSidebar); + // Initialize actions addAction(ui->ActionIncrementGizmo); addAction(ui->ActionDecrementGizmo); @@ -156,15 +167,11 @@ CWorldEditor::CWorldEditor(QWidget *parent) connect(ui->ActionCollisionRenderSettings, SIGNAL(triggered()), this, SLOT(EditCollisionRenderSettings())); connect(ui->ActionEditLayers, SIGNAL(triggered()), this, SLOT(EditLayers())); connect(ui->ActionEditPoiToWorldMap, SIGNAL(triggered()), this, SLOT(EditPoiToWorldMap())); - - ui->CreateTabEditorProperties->SyncToEditor(this); - ui->ModifyTabEditorProperties->SyncToEditor(this); - ui->InstancesTabEditorProperties->SyncToEditor(this); - ui->MainViewport->setAcceptDrops(true); } CWorldEditor::~CWorldEditor() { + delete mpScriptSidebar; // For some reason WCreateTab filters an event during the viewport's destructor delete ui; } @@ -196,8 +203,6 @@ bool CWorldEditor::CloseWorld() ExitPickMode(); ClearSelection(); ui->MainViewport->ResetHover(); - ui->ModifyTabContents->ClearUI(); - ui->InstancesTabContents->SetMaster(nullptr); mUndoStack.clear(); mpCollisionDialog->close(); @@ -212,19 +217,18 @@ bool CWorldEditor::CloseWorld() mpArea = nullptr; mpWorld = nullptr; + + emit MapChanged(mpWorld, mpArea); return true; } else return false; } -void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) +void CWorldEditor::SetArea(CWorld *pWorld, int AreaIndex) { ExitPickMode(); ui->MainViewport->ResetHover(); ClearSelection(); - ui->ModifyTabContents->ClearUI(); - ui->InstancesTabContents->SetMaster(nullptr); - ui->InstancesTabContents->SetArea(pArea); mUndoStack.clear(); if (mpPoiDialog) @@ -234,17 +238,24 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) } // Load new area - mpArea = pArea; mpWorld = pWorld; - mScene.SetActiveWorld(pWorld); - mScene.SetActiveArea(pArea); + CAssetID AreaID = mpWorld->AreaResourceID(AreaIndex); + CResourceEntry *pAreaEntry = gpResourceStore->FindEntry(AreaID); + ASSERT(pAreaEntry); + + mpArea = pAreaEntry->Load(); + ASSERT(mpArea); + mpWorld->SetAreaLayerInfo(mpArea); + + mScene.SetActiveWorld(mpWorld); + mScene.SetActiveArea(mpArea); // Snap camera to new area CCamera *pCamera = &ui->MainViewport->Camera(); if (pCamera->MoveMode() == eFreeCamera) { - CTransform4f AreaTransform = pArea->Transform(); + CTransform4f AreaTransform = mpArea->Transform(); CVector3f AreaPosition(AreaTransform[0][3], AreaTransform[1][3], AreaTransform[2][3]); pCamera->Snap(AreaPosition); } @@ -260,12 +271,8 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) bool AllowEGMC = ( (mpWorld->Game() >= eEchoesDemo) && (mpWorld->Game() <= eCorruption) ); ui->ActionEditPoiToWorldMap->setEnabled(AllowEGMC); - // Set up sidebar tabs - CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(mpArea->Game()); - ui->CreateTabContents->SetMaster(pMaster); - ui->InstancesTabContents->SetMaster(pMaster); - // Set up dialogs + CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(mpArea->Game()); mpCollisionDialog->SetupWidgets(); // Won't modify any settings but will update widget visibility status if we've changed games mpLinkDialog->SetMaster(pMaster); @@ -275,8 +282,8 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) if (CurrentGame() < eReturns) { - CStringTable *pAreaNameTable = mpWorld->AreaName(mpArea->WorldIndex()); - TWideString AreaName = pAreaNameTable ? pAreaNameTable->String("ENGL", 0) : (TWideString("!") + mpWorld->AreaInternalName(mpArea->WorldIndex()).ToUTF16()); + CStringTable *pAreaNameTable = mpWorld->AreaName(AreaIndex); + TWideString AreaName = pAreaNameTable ? pAreaNameTable->String("ENGL", 0) : (TWideString("!") + mpWorld->AreaInternalName(AreaIndex).ToUTF16()); if (AreaName.IsEmpty()) AreaName = "[Untitled Area]"; @@ -289,7 +296,7 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) { QString LevelName; if (pWorldNameTable) LevelName = TO_QSTRING(WorldName); - else LevelName = "!" + TO_QSTRING(mpWorld->AreaInternalName(mpArea->WorldIndex())); + else LevelName = "!" + TO_QSTRING(mpWorld->AreaInternalName(AreaIndex)); SET_WINDOWTITLE_APPVARS( QString("%APP_FULL_NAME% - %1[*]").arg(LevelName) ); Log::Write("Loaded level: World " + mpWorld->Source() + " / Area " + mpArea->Source() + " (" + TO_TSTRING(LevelName) + ")"); @@ -299,7 +306,11 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) OnClipboardDataModified(); // Emit signals + emit MapChanged(mpWorld, mpArea); emit LayersModified(); + + // Make sure old area is destroyed + gpResourceStore->DestroyUnreferencedResources(); } bool CWorldEditor::CheckUnsavedChanges() @@ -390,7 +401,7 @@ void CWorldEditor::Paste() PastePoint = Ray.PointOnRay(10.f); } - CPasteNodesCommand *pCmd = new CPasteNodesCommand(this, ui->CreateTabContents->SpawnLayer(), PastePoint); + CPasteNodesCommand *pCmd = new CPasteNodesCommand(this, mpScriptSidebar->CreateTab()->SpawnLayer(), PastePoint); mUndoStack.push(pCmd); } } @@ -748,8 +759,8 @@ void CWorldEditor::UpdateNewLinkLine() } else if (mIsMakingLink && mpNewLinkSender) pSender = mpNewLinkSender; - else if (ui->ModifyTabContents->IsPicking() && ui->ModifyTabContents->EditNode()->NodeType() == eScriptNode) - pSender = static_cast(ui->ModifyTabContents->EditNode())->Instance(); + else if (mpScriptSidebar->ModifyTab()->IsPicking() && mpScriptSidebar->ModifyTab()->EditNode()->NodeType() == eScriptNode) + pSender = static_cast(mpScriptSidebar->ModifyTab()->EditNode())->Instance(); // No sender and no receiver = no line if (!pSender && !pReceiver) @@ -765,7 +776,7 @@ void CWorldEditor::UpdateNewLinkLine() // Compensate for missing sender or missing receiver else { - bool IsPicking = (mIsMakingLink || mpLinkDialog->IsPicking() || ui->ModifyTabContents->IsPicking()); + bool IsPicking = (mIsMakingLink || mpLinkDialog->IsPicking() || mpScriptSidebar->ModifyTab()->IsPicking()); if (ui->MainViewport->underMouse() && !ui->MainViewport->IsMouseInputActive() && IsPicking) { @@ -785,6 +796,23 @@ void CWorldEditor::UpdateNewLinkLine() } // ************ PROTECTED ************ +void CWorldEditor::SetSidebarWidget(QWidget *pWidget) +{ + if (mpCurSidebarWidget) + { + mpRightSidebarLayout->removeWidget(mpCurSidebarWidget); + mpCurSidebarWidget->setHidden(true); + } + + mpCurSidebarWidget = pWidget; + + if (mpCurSidebarWidget) + { + mpRightSidebarLayout->addWidget(pWidget); + mpCurSidebarWidget->setHidden(false); + } +} + void CWorldEditor::GizmoModeChanged(CGizmo::EGizmoMode mode) { ui->TransformSpinBox->SetSingleStep( (mode == CGizmo::eRotate ? 1.0 : 0.1) ); diff --git a/src/Editor/WorldEditor/CWorldEditor.h b/src/Editor/WorldEditor/CWorldEditor.h index fcabdbf7..42304fd2 100644 --- a/src/Editor/WorldEditor/CWorldEditor.h +++ b/src/Editor/WorldEditor/CWorldEditor.h @@ -4,6 +4,8 @@ #include "CCollisionRenderSettingsDialog.h" #include "CLinkDialog.h" #include "CPoiMapEditDialog.h" +#include "CScriptEditSidebar.h" +#include "CWorldInfoSidebar.h" #include "Editor/INodeEditor.h" #include "Editor/CGizmo.h" #include "Editor/CSceneViewport.h" @@ -55,15 +57,23 @@ class CWorldEditor : public INodeEditor QString mPakFileList; QString mPakTarget; + // Sidebars + QVBoxLayout *mpRightSidebarLayout; + QWidget *mpCurSidebarWidget; + + CWorldInfoSidebar *mpWorldInfoSidebar; + CScriptEditSidebar *mpScriptSidebar; + public: explicit CWorldEditor(QWidget *parent = 0); ~CWorldEditor(); void closeEvent(QCloseEvent *pEvent); bool CloseWorld(); - void SetArea(CWorld *pWorld, CGameArea *pArea); + void SetArea(CWorld *pWorld, int AreaIndex); bool CheckUnsavedChanges(); bool HasAnyScriptNodesSelected() const; + inline CWorld* ActiveWorld() const { return mpWorld; } inline CGameArea* ActiveArea() const { return mpArea; } inline EGame CurrentGame() const { return mpArea ? mpArea->Game() : eUnknownGame; } inline CLinkDialog* LinkDialog() const { return mpLinkDialog; } @@ -104,6 +114,7 @@ public slots: void UpdateNewLinkLine(); protected: + void SetSidebarWidget(QWidget *pWidget); void GizmoModeChanged(CGizmo::EGizmoMode Mode); private slots: @@ -149,6 +160,7 @@ private slots: void EditPoiToWorldMap(); signals: + void MapChanged(CWorld *pNewWorld, CGameArea *pNewArea); void LayersModified(); void InstancesLayerAboutToChange(); void InstancesLayerChanged(const QList& rkInstanceList); diff --git a/src/Editor/WorldEditor/CWorldEditor.ui b/src/Editor/WorldEditor/CWorldEditor.ui index 9e39fb6b..c650d1eb 100644 --- a/src/Editor/WorldEditor/CWorldEditor.ui +++ b/src/Editor/WorldEditor/CWorldEditor.ui @@ -14,7 +14,156 @@ %APP_FULL_NAME% - + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + 1 + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + 32 + 32 + + + + World Edit Mode + + + + + + + :/icons/World.png:/icons/World.png + + + + 24 + 24 + + + + true + + + true + + + false + + + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + 32 + 32 + + + + Script Edit Mode + + + + + + + :/icons/Modify.png:/icons/Modify.png + + + + 24 + 24 + + + + true + + + false + + + + + + + Qt::Vertical + + + + 20 + 546 + + + + + + + @@ -209,167 +358,13 @@ - - - - 0 - 0 - + + + QFrame::StyledPanel - - - 0 - 0 - + + QFrame::Raised - - Qt::NoFocus - - - QTabWidget::North - - - QTabWidget::Rounded - - - 0 - - - - 24 - 24 - - - - false - - - - - :/icons/Create.png:/icons/Create.png - - - - - - Create - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - 0 - 1 - - - - - - - - - - :/icons/Modify.png:/icons/Modify.png - - - - - - Modify - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - 0 - 0 - - - - - - - - - - :/icons/Instances.png:/icons/Instances.png - - - - - - Instances - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - - @@ -408,7 +403,7 @@ 0 0 1280 - 21 + 20 @@ -858,18 +853,6 @@ QDoubleSpinBox
Editor/Widgets/WDraggableSpinBox.h
- - WModifyTab - QWidget -
Editor/WorldEditor/WModifyTab.h
- 1 -
- - WInstancesTab - QWidget -
Editor/WorldEditor/WInstancesTab.h
- 1 -
WVectorEditor QWidget @@ -882,18 +865,6 @@
Editor/CSceneViewport.h
1
- - WEditorProperties - QWidget -
Editor/WorldEditor/WEditorProperties.h
- 1 -
- - WCreateTab - QWidget -
Editor/WorldEditor/WCreateTab.h
- 1 -
diff --git a/src/Editor/WorldEditor/CWorldInfoSidebar.cpp b/src/Editor/WorldEditor/CWorldInfoSidebar.cpp new file mode 100644 index 00000000..360f61d0 --- /dev/null +++ b/src/Editor/WorldEditor/CWorldInfoSidebar.cpp @@ -0,0 +1,55 @@ +#include "CWorldInfoSidebar.h" +#include "ui_CWorldInfoSidebar.h" +#include "CWorldEditor.h" +#include "Editor/CEditorApplication.h" + +CWorldInfoSidebar::CWorldInfoSidebar(CWorldEditor *pEditor) + : QWidget(pEditor) + , mpUI(new Ui::CWorldInfoSidebar) + , mModel(pEditor) +{ + mpUI->setupUi(this); + mProxyModel.setSourceModel(&mModel); + mpUI->WorldTreeView->setModel(&mProxyModel); + mpUI->WorldTreeView->header()->setSortIndicator(0, Qt::AscendingOrder); + + QHeaderView *pHeader = mpUI->WorldTreeView->header(); + pHeader->resizeSection(0, pHeader->width() * 2); // I really have no idea how this works, I just got this from trial & error + + connect(mpUI->AreaSearchLineEdit, SIGNAL(StoppedTyping(QString)), this, SLOT(OnAreaFilterStringChanged(QString))); + connect(mpUI->WorldTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnWorldTreeDoubleClicked(QModelIndex))); +} + +CWorldInfoSidebar::~CWorldInfoSidebar() +{ + delete mpUI; +} + +// ************ SLOTS ************ +void CWorldInfoSidebar::OnAreaFilterStringChanged(const QString& rkFilter) +{ + mProxyModel.SetFilterString(rkFilter); + + // Expand top-level items that contain matches for the new filter string + int NumTopLevel = mModel.rowCount(QModelIndex()); + + for (int iRow = 0; iRow < NumTopLevel; iRow++) + { + QModelIndex Index = mModel.index(iRow, 0, QModelIndex()); + QModelIndex ProxyIndex = mProxyModel.mapFromSource(Index); + bool Matches = !rkFilter.isEmpty() && mProxyModel.rowCount(ProxyIndex) > 0; + mpUI->WorldTreeView->setExpanded(ProxyIndex, Matches); + } +} + +void CWorldInfoSidebar::OnWorldTreeDoubleClicked(QModelIndex Index) +{ + QModelIndex RealIndex = mProxyModel.mapToSource(Index); + + if (!mModel.IndexIsWorld(RealIndex)) + { + CWorld *pWorld = mModel.WorldForIndex(RealIndex); + int AreaIndex = mModel.AreaIndexForIndex(RealIndex); + gpEdApp->WorldEditor()->SetArea(pWorld, AreaIndex); + } +} diff --git a/src/Editor/WorldEditor/CWorldInfoSidebar.h b/src/Editor/WorldEditor/CWorldInfoSidebar.h new file mode 100644 index 00000000..1fc201fa --- /dev/null +++ b/src/Editor/WorldEditor/CWorldInfoSidebar.h @@ -0,0 +1,31 @@ +#ifndef CWORLDINFOSIDEBAR_H +#define CWORLDINFOSIDEBAR_H + +#include +#include +#include "CWorldTreeModel.h" + +class CWorldEditor; + +namespace Ui { +class CWorldInfoSidebar; +} + +class CWorldInfoSidebar : public QWidget +{ + Q_OBJECT + + Ui::CWorldInfoSidebar *mpUI; + CWorldTreeModel mModel; + CWorldTreeProxyModel mProxyModel; + +public: + explicit CWorldInfoSidebar(CWorldEditor *pEditor); + ~CWorldInfoSidebar(); + +public slots: + void OnAreaFilterStringChanged(const QString& rkFilter); + void OnWorldTreeDoubleClicked(QModelIndex Index); +}; + +#endif // CWORLDINFOSIDEBAR_H diff --git a/src/Editor/WorldEditor/CWorldInfoSidebar.ui b/src/Editor/WorldEditor/CWorldInfoSidebar.ui new file mode 100644 index 00000000..ad90e623 --- /dev/null +++ b/src/Editor/WorldEditor/CWorldInfoSidebar.ui @@ -0,0 +1,73 @@ + + + CWorldInfoSidebar + + + + 0 + 0 + 314 + 585 + + + + Form + + + + + + + 10 + + + + + + + Search... + + + true + + + + + + + + 10 + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::ScrollPerPixel + + + 10 + + + true + + + true + + + + + + + + CTimedLineEdit + QLineEdit +
Editor/Widgets/CTimedLineEdit.h
+
+
+ + +
diff --git a/src/Editor/WorldEditor/CWorldTreeModel.cpp b/src/Editor/WorldEditor/CWorldTreeModel.cpp new file mode 100644 index 00000000..d72b02cb --- /dev/null +++ b/src/Editor/WorldEditor/CWorldTreeModel.cpp @@ -0,0 +1,268 @@ +#include "CWorldTreeModel.h" +#include "CEditorApplication.h" +#include "CWorldEditor.h" +#include "UICommon.h" +#include +#include + +CWorldTreeModel::CWorldTreeModel(CWorldEditor *pEditor) +{ + connect(gpEdApp, SIGNAL(ActiveProjectChanged(CGameProject*)), this, SLOT(OnProjectChanged(CGameProject*))); + connect(pEditor, SIGNAL(MapChanged(CWorld*,CGameArea*)), this, SLOT(OnMapChanged())); +} + +int CWorldTreeModel::rowCount(const QModelIndex& rkParent) const +{ + if (!rkParent.isValid()) return mWorldList.size(); + else if (IndexIsWorld(rkParent)) return WorldForIndex(rkParent)->NumAreas(); + else return 0; +} + +int CWorldTreeModel::columnCount(const QModelIndex&) const +{ + return 2; +} + +QModelIndex CWorldTreeModel::index(int Row, int Column, const QModelIndex& rkParent) const +{ + if (!hasIndex(Row, Column, rkParent)) + return QModelIndex(); + + // World + if (!rkParent.isValid()) + return createIndex(Row, Column, quint64((Row << 16) | 0xFFFF)); + + // Area + else + return createIndex(Row, Column, quint64((rkParent.row() << 16) | (Row & 0xFFFF)) ); +} + +QModelIndex CWorldTreeModel::parent(const QModelIndex& rkChild) const +{ + if (IndexIsWorld(rkChild)) + return QModelIndex(); + else + return createIndex((rkChild.internalId() >> 16) & 0xFFFF, 0, rkChild.internalId() | 0xFFFF); +} + +QVariant CWorldTreeModel::data(const QModelIndex& rkIndex, int Role) const +{ + if (Role == Qt::DisplayRole || Role == Qt::ToolTipRole) + { + CWorld *pWorld = WorldForIndex(rkIndex); + + // World + if (IndexIsWorld(rkIndex)) + { + QString WorldAssetName = TO_QSTRING( pWorld->Entry()->Name() ); + CStringTable *pWorldNameString = pWorld->WorldName(); + + if (rkIndex.column() == 1) + return WorldAssetName; + + else + { + if (pWorldNameString) + return TO_QSTRING( pWorldNameString->String("ENGL", 0) ); + else + return WorldAssetName; + } + } + + // Area + else + { + u32 AreaIndex = AreaIndexForIndex(rkIndex); + ASSERT(AreaIndex >= 0 && AreaIndex < pWorld->NumAreas()); + + CAssetID AreaAssetID = pWorld->AreaResourceID(AreaIndex); + CResourceEntry *pAreaEntry = pWorld->Entry()->ResourceStore()->FindEntry(AreaAssetID); + ASSERT(pAreaEntry); + + QString AreaAssetName = TO_QSTRING( pAreaEntry->Name() ); + CStringTable *pAreaNameString = pWorld->AreaName(AreaIndex); + + if (rkIndex.column() == 1) + return AreaAssetName; + + else + { + if (pAreaNameString) + return TO_QSTRING( pAreaNameString->String("ENGL", 0) ); + else + return "!!" + AreaAssetName; + } + } + } + + else if (Role == Qt::DecorationRole) + { + static QIcon sWorldIcon = QIcon(":/icons/World.png"); + static QIcon sAreaIcon = QIcon(":/icons/New_16px.png"); + + if (rkIndex.column() == 1) + return QVariant::Invalid; + else if (IndexIsWorld(rkIndex)) + return sWorldIcon; + else + return sAreaIcon; + } + + else if (Role == Qt::FontRole) + { + CWorld *pWorld = WorldForIndex(rkIndex); + ASSERT(pWorld); + + QFont Font; + int PointSize = Font.pointSize() + 2; + + if (IndexIsWorld(rkIndex)) + { + PointSize += 1; + + CWorld *pWorld = WorldForIndex(rkIndex); + if (gpEdApp->WorldEditor()->ActiveWorld() == pWorld) + Font.setBold(true); + } + else + { + CResourceEntry *pEntry = AreaEntryForIndex(rkIndex); + ASSERT(pEntry); + + if (pEntry->IsLoaded()) + { + if (gpEdApp->WorldEditor()->ActiveArea() == pEntry->Resource()) + Font.setBold(true); + else + Font.setItalic(true); + } + } + + Font.setPointSize(PointSize); + return Font; + } + + return QVariant::Invalid; +} + +QVariant CWorldTreeModel::headerData(int Section, Qt::Orientation Orientation, int Role) const +{ + if (Orientation == Qt::Horizontal && Role == Qt::DisplayRole) + { + if (Section == 0) + return "In-Game Name"; + else + return "Internal Name"; + } + return QVariant::Invalid; +} + +bool CWorldTreeModel::IndexIsWorld(const QModelIndex& rkIndex) const +{ + return AreaIndexForIndex(rkIndex) == 0xFFFF; +} + +CWorld* CWorldTreeModel::WorldForIndex(const QModelIndex& rkIndex) const +{ + int WorldIndex = (rkIndex.internalId() >> 16) & 0xFFFF; + return mWorldList[WorldIndex].pWorld; +} + +int CWorldTreeModel::AreaIndexForIndex(const QModelIndex& rkIndex) const +{ + int InternalID = (int) rkIndex.internalId(); + return (InternalID & 0xFFFF); +} + +CResourceEntry* CWorldTreeModel::AreaEntryForIndex(const QModelIndex& rkIndex) const +{ + ASSERT(rkIndex.isValid() && !IndexIsWorld(rkIndex)); + const SWorldInfo& rkInfo = mWorldList[rkIndex.parent().row()]; + return rkInfo.Areas[rkIndex.row()]; +} + +// ************ SLOTS ************ +void CWorldTreeModel::OnProjectChanged(CGameProject *pProj) +{ + beginResetModel(); + mWorldList.clear(); + + if (pProj) + { + std::list WorldIDs; + pProj->GetWorldList(WorldIDs); + QList QWorldIDs = QList::fromStdList(WorldIDs); + + foreach (const CAssetID& rkID, QWorldIDs) + { + CResourceEntry *pEntry = pProj->ResourceStore()->FindEntry(rkID); + + if (pEntry) + { + TResPtr pWorld = pEntry->Load(); + + if (pWorld) + { + SWorldInfo Info; + Info.pWorld = pWorld; + + for (u32 iArea = 0; iArea < pWorld->NumAreas(); iArea++) + { + CAssetID AreaID = pWorld->AreaResourceID(iArea); + CResourceEntry *pAreaEntry = pWorld->Entry()->ResourceStore()->FindEntry(AreaID); + ASSERT(pAreaEntry); + Info.Areas << pAreaEntry; + } + + mWorldList << Info; + } + } + } + } + + endResetModel(); +} + +void CWorldTreeModel::OnMapChanged() +{ + // Flag all data as changed to ensure the font updates correctly based on which areas are loaded + // note we don't know which areas used to be loaded, so flagging those specific indices isn't an option + int MaxRow = rowCount(QModelIndex()) - 1; + int MaxCol = columnCount(QModelIndex()) - 1; + emit dataChanged(index(0, 0, QModelIndex()), index(MaxRow, MaxCol, QModelIndex())); +} + +// ************ PROXY MODEL ************ +bool CWorldTreeProxyModel::lessThan(const QModelIndex& rkSourceLeft, const QModelIndex& rkSourceRight) const +{ + CWorldTreeModel *pModel = qobject_cast(sourceModel()); + ASSERT(pModel != nullptr); + + if (pModel->IndexIsWorld(rkSourceLeft)) + { + ASSERT(pModel->IndexIsWorld(rkSourceRight)); + bool IsLessThan = (rkSourceLeft.row() < rkSourceRight.row()); + return (sortOrder() == Qt::AscendingOrder ? IsLessThan : !IsLessThan); + } + else + return pModel->data(rkSourceLeft, Qt::DisplayRole).toString().toUpper() < pModel->data(rkSourceRight, Qt::DisplayRole).toString().toUpper(); +} + +bool CWorldTreeProxyModel::filterAcceptsRow(int SourceRow, const QModelIndex& rkSourceParent) const +{ + // Always accept worlds + if (!rkSourceParent.isValid() || mFilterString.isEmpty()) + return true; + + CWorldTreeModel *pModel = qobject_cast(sourceModel()); + ASSERT(pModel != nullptr); + + for (int iCol = 0; iCol < pModel->columnCount(rkSourceParent); iCol++) + { + QModelIndex Index = pModel->index(SourceRow, iCol, rkSourceParent); + if (pModel->data(Index, Qt::DisplayRole).toString().contains(mFilterString, Qt::CaseInsensitive)) + return true; + } + + return false; +} diff --git a/src/Editor/WorldEditor/CWorldTreeModel.h b/src/Editor/WorldEditor/CWorldTreeModel.h new file mode 100644 index 00000000..85801334 --- /dev/null +++ b/src/Editor/WorldEditor/CWorldTreeModel.h @@ -0,0 +1,53 @@ +#ifndef CWORLDTREEMODEL_H +#define CWORLDTREEMODEL_H + +#include +#include +#include +class CWorldEditor; + +class CWorldTreeModel : public QAbstractItemModel +{ + Q_OBJECT + + struct SWorldInfo + { + TResPtr pWorld; + QList Areas; + }; + QList mWorldList; + +public: + CWorldTreeModel(CWorldEditor *pEditor); + + int rowCount(const QModelIndex& rkParent) const; + int columnCount(const QModelIndex& rkParent) const; + QModelIndex index(int Row, int Column, const QModelIndex& rkParent) const; + QModelIndex parent(const QModelIndex& rkChild) const; + QVariant data(const QModelIndex& rkIndex, int Role) const; + QVariant headerData(int Section, Qt::Orientation Orientation, int Role) const; + + bool IndexIsWorld(const QModelIndex& rkIndex) const; + CWorld* WorldForIndex(const QModelIndex& rkIndex) const; + int AreaIndexForIndex(const QModelIndex& rkIndex) const; + CResourceEntry* AreaEntryForIndex(const QModelIndex& rkIndex) const; + +public slots: + void OnProjectChanged(CGameProject *pProj); + void OnMapChanged(); +}; + +// Proxy Model +class CWorldTreeProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + QString mFilterString; + +public: + bool lessThan(const QModelIndex& rkSourceLeft, const QModelIndex& rkSourceRight) const; + bool filterAcceptsRow(int SourceRow, const QModelIndex& rkSourceParent) const; + + inline void SetFilterString(const QString& rkFilter) { mFilterString = rkFilter; invalidate(); } +}; + +#endif // CWORLDTREEMODEL_H diff --git a/src/Editor/WorldEditor/WCreateTab.cpp b/src/Editor/WorldEditor/WCreateTab.cpp index 19c651d7..f69cd903 100644 --- a/src/Editor/WorldEditor/WCreateTab.cpp +++ b/src/Editor/WorldEditor/WCreateTab.cpp @@ -4,13 +4,17 @@ #include "CWorldEditor.h" #include "Editor/Undo/UndoCommands.h" -WCreateTab::WCreateTab(QWidget *parent) - : QWidget(parent) +WCreateTab::WCreateTab(CWorldEditor *pEditor, QWidget *pParent /*= 0*/) + : QWidget(pParent) , ui(new Ui::WCreateTab) , mpSpawnLayer(nullptr) { ui->setupUi(this); + mpEditor = pEditor; + mpEditor->Viewport()->installEventFilter(this); + connect(mpEditor, SIGNAL(LayersModified()), this, SLOT(OnLayersChanged())); + connect(ui->SpawnLayerComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSpawnLayerChanged(int))); } @@ -52,19 +56,14 @@ bool WCreateTab::eventFilter(QObject *pObj, QEvent *pEvent) return false; } -void WCreateTab::SetEditor(CWorldEditor *pEditor) -{ - mpEditor = pEditor; - pEditor->Viewport()->installEventFilter(this); - connect(mpEditor, SIGNAL(LayersModified()), this, SLOT(OnLayersChanged())); -} - -void WCreateTab::SetMaster(CMasterTemplate *pMaster) +// ************ PUBLIC SLOTS ************ +void WCreateTab::OnMapChanged() { + EGame Game = mpEditor->CurrentGame(); + CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(Game); ui->TemplateView->SetMaster(pMaster); } -// ************ PUBLIC SLOTS ************ void WCreateTab::OnLayersChanged() { CGameArea *pArea = mpEditor->ActiveArea(); diff --git a/src/Editor/WorldEditor/WCreateTab.h b/src/Editor/WorldEditor/WCreateTab.h index 49f91331..871c47ba 100644 --- a/src/Editor/WorldEditor/WCreateTab.h +++ b/src/Editor/WorldEditor/WCreateTab.h @@ -16,16 +16,15 @@ class WCreateTab : public QWidget CScriptLayer *mpSpawnLayer; public: - explicit WCreateTab(QWidget *parent = 0); + explicit WCreateTab(CWorldEditor *pEditor, QWidget *parent = 0); ~WCreateTab(); bool eventFilter(QObject *, QEvent *); - void SetEditor(CWorldEditor *pEditor); - void SetMaster(CMasterTemplate *pMaster); // Accessors inline CScriptLayer* SpawnLayer() const { return mpSpawnLayer; } public slots: + void OnMapChanged(); void OnLayersChanged(); void OnSpawnLayerChanged(int LayerIndex); diff --git a/src/Editor/WorldEditor/WInstancesTab.cpp b/src/Editor/WorldEditor/WInstancesTab.cpp index 8f7c5883..8c5f6771 100644 --- a/src/Editor/WorldEditor/WInstancesTab.cpp +++ b/src/Editor/WorldEditor/WInstancesTab.cpp @@ -6,17 +6,22 @@ #include #include -WInstancesTab::WInstancesTab(QWidget *parent) : +WInstancesTab::WInstancesTab(CWorldEditor *pEditor, QWidget *parent) : QWidget(parent), ui(new Ui::WInstancesTab) { ui->setupUi(this); - mpEditor = nullptr; + mpEditor = pEditor; + mpScene = mpEditor->Scene(); + connect(mpEditor, SIGNAL(MapChanged(CWorld*,CGameArea*)), this, SLOT(OnMapChange(CWorld*,CGameArea*))); + mpLayersModel = new CInstancesModel(this); mpLayersModel->SetModelType(CInstancesModel::eLayers); + mpLayersModel->SetEditor(mpEditor); mpTypesModel = new CInstancesModel(this); mpTypesModel->SetModelType(CInstancesModel::eTypes); + mpTypesModel->SetEditor(mpEditor); mLayersProxyModel.setSourceModel(mpLayersModel); mTypesProxyModel.setSourceModel(mpTypesModel); @@ -73,27 +78,16 @@ WInstancesTab::~WInstancesTab() delete ui; } -void WInstancesTab::SetEditor(CWorldEditor *pEditor, CScene *pScene) -{ - mpEditor = pEditor; - mpScene = pScene; - mpTypesModel->SetEditor(pEditor); - mpLayersModel->SetEditor(pEditor); -} - -void WInstancesTab::SetMaster(CMasterTemplate *pMaster) -{ - mpTypesModel->SetMaster(pMaster); - ExpandTopLevelItems(); -} - -void WInstancesTab::SetArea(CGameArea *pArea) -{ - mpLayersModel->SetArea(pArea); - ExpandTopLevelItems(); -} - // ************ PRIVATE SLOTS ************ +void WInstancesTab::OnMapChange(CWorld*, CGameArea *pNewArea) +{ + EGame Game = mpEditor->CurrentGame(); + CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(Game); + mpTypesModel->SetMaster(pMaster); + mpLayersModel->SetArea(pNewArea); + ExpandTopLevelItems(); +} + void WInstancesTab::OnTreeClick(QModelIndex Index) { // Single click is used to process show/hide events diff --git a/src/Editor/WorldEditor/WInstancesTab.h b/src/Editor/WorldEditor/WInstancesTab.h index 1de3085d..9d13ed2c 100644 --- a/src/Editor/WorldEditor/WInstancesTab.h +++ b/src/Editor/WorldEditor/WInstancesTab.h @@ -43,13 +43,11 @@ class WInstancesTab : public QWidget CInstancesModel::EIndexType mMenuIndexType; public: - explicit WInstancesTab(QWidget *parent = 0); + explicit WInstancesTab(CWorldEditor *pEditor, QWidget *parent = 0); ~WInstancesTab(); - void SetEditor(CWorldEditor *pEditor, CScene *pScene); - void SetMaster(CMasterTemplate *pMaster); - void SetArea(CGameArea *pArea); private slots: + void OnMapChange(CWorld*, CGameArea *pNewArea); void OnTreeClick(QModelIndex Index); void OnTreeDoubleClick(QModelIndex Index); diff --git a/src/Editor/WorldEditor/WModifyTab.cpp b/src/Editor/WorldEditor/WModifyTab.cpp index a993418e..096cfc75 100644 --- a/src/Editor/WorldEditor/WModifyTab.cpp +++ b/src/Editor/WorldEditor/WModifyTab.cpp @@ -10,13 +10,16 @@ #include #include -WModifyTab::WModifyTab(QWidget *pParent) +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); @@ -49,6 +52,10 @@ WModifyTab::WModifyTab(QWidget *pParent) 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&)), this, SLOT(OnInstanceLinksModified(const QList&))); + connect(mpWorldEditor->Selection(), SIGNAL(Modified()), this, SLOT(GenerateUI())); ClearUI(); } @@ -58,15 +65,6 @@ WModifyTab::~WModifyTab() delete ui; } -void WModifyTab::SetEditor(CWorldEditor *pEditor) -{ - mpWorldEditor = pEditor; - ui->PropertyView->SetEditor(mpWorldEditor); - connect(mpWorldEditor, SIGNAL(SelectionTransformed()), this, SLOT(OnWorldSelectionTransformed())); - connect(mpWorldEditor, SIGNAL(InstanceLinksModified(const QList&)), this, SLOT(OnInstanceLinksModified(const QList&))); - connect(mpWorldEditor->Selection(), SIGNAL(Modified()), this, SLOT(GenerateUI())); -} - void WModifyTab::ClearUI() { ui->ObjectsTabWidget->hide(); @@ -131,6 +129,11 @@ void WModifyTab::OnWorldSelectionTransformed() ui->PropertyView->UpdateEditorProperties(QModelIndex()); } +void WModifyTab::OnMapChanged() +{ + ClearUI(); +} + void WModifyTab::OnLinksSelectionModified() { if (sender() == ui->InLinksTableView->selectionModel()) diff --git a/src/Editor/WorldEditor/WModifyTab.h b/src/Editor/WorldEditor/WModifyTab.h index 6d7e4edf..fa74b0d1 100644 --- a/src/Editor/WorldEditor/WModifyTab.h +++ b/src/Editor/WorldEditor/WModifyTab.h @@ -34,15 +34,15 @@ class WModifyTab : public QWidget bool mIsPicking; public: - explicit WModifyTab(QWidget *pParent = 0); + explicit WModifyTab(CWorldEditor *pEditor, QWidget *pParent = 0); ~WModifyTab(); - void SetEditor(CWorldEditor *pEditor); void ClearUI(); public slots: void GenerateUI(); void OnInstanceLinksModified(const QList& rkInstances); void OnWorldSelectionTransformed(); + void OnMapChanged(); void OnLinksSelectionModified(); void OnAddLinkActionClicked(QAction *pAction);