Added new WIP UI to the world editor for loading worlds/areas

This commit is contained in:
Aruki 2017-02-12 00:34:04 -07:00
parent 9928a599be
commit ce0c544168
22 changed files with 871 additions and 289 deletions

View File

@ -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++)

View File

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

View File

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

View File

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

View File

@ -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

View File

@ -0,0 +1,49 @@
#ifndef CTIMEDLINEEDIT_H
#define CTIMEDLINEEDIT_H
#include <QLineEdit>
#include <QTimer>
// 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

View File

@ -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");
}

View File

@ -0,0 +1,28 @@
#ifndef CSCRIPTEDITSIDEBAR_H
#define CSCRIPTEDITSIDEBAR_H
#include <QTabWidget>
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

View File

@ -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<CScriptNode*>(ui->ModifyTabContents->EditNode())->Instance();
else if (mpScriptSidebar->ModifyTab()->IsPicking() && mpScriptSidebar->ModifyTab()->EditNode()->NodeType() == eScriptNode)
pSender = static_cast<CScriptNode*>(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) );

View File

@ -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<CScriptNode*>& rkInstanceList);

View File

@ -14,7 +14,156 @@
<string>%APP_FULL_NAME%</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_5">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QFrame" name="LeftSidebarFrame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QPushButton" name="EditWorldInfoButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolTip">
<string>World Edit Mode</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/World.png</normaloff>:/icons/World.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="EditScriptButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolTip">
<string>Script Edit Mode</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/Modify.png</normaloff>:/icons/Modify.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>546</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
@ -209,167 +358,13 @@
</item>
</layout>
</widget>
<widget class="QTabWidget" name="TabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QFrame" name="RightSidebarFrame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<widget class="QWidget" name="CreateTab">
<attribute name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/Create.png</normaloff>:/icons/Create.png</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Create</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="WEditorProperties" name="CreateTabEditorProperties" native="true"/>
</item>
<item>
<widget class="WCreateTab" name="CreateTabContents" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="ModifyTab">
<attribute name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/Modify.png</normaloff>:/icons/Modify.png</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Modify</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="WEditorProperties" name="ModifyTabEditorProperties" native="true"/>
</item>
<item>
<widget class="WModifyTab" name="ModifyTabContents" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="InstancesTab">
<attribute name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/Instances.png</normaloff>:/icons/Instances.png</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Instances</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="WEditorProperties" name="InstancesTabEditorProperties" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="WInstancesTab" name="InstancesTabContents" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
@ -408,7 +403,7 @@
<x>0</x>
<y>0</y>
<width>1280</width>
<height>21</height>
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -858,18 +853,6 @@
<extends>QDoubleSpinBox</extends>
<header>Editor/Widgets/WDraggableSpinBox.h</header>
</customwidget>
<customwidget>
<class>WModifyTab</class>
<extends>QWidget</extends>
<header>Editor/WorldEditor/WModifyTab.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>WInstancesTab</class>
<extends>QWidget</extends>
<header>Editor/WorldEditor/WInstancesTab.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>WVectorEditor</class>
<extends>QWidget</extends>
@ -882,18 +865,6 @@
<header>Editor/CSceneViewport.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>WEditorProperties</class>
<extends>QWidget</extends>
<header>Editor/WorldEditor/WEditorProperties.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>WCreateTab</class>
<extends>QWidget</extends>
<header>Editor/WorldEditor/WCreateTab.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../Icons.qrc"/>

View File

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

View File

@ -0,0 +1,31 @@
#ifndef CWORLDINFOSIDEBAR_H
#define CWORLDINFOSIDEBAR_H
#include <QWidget>
#include <QSortFilterProxyModel>
#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

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CWorldInfoSidebar</class>
<widget class="QWidget" name="CWorldInfoSidebar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>314</width>
<height>585</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="CTimedLineEdit" name="AreaSearchLineEdit">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>Search...</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTreeView" name="WorldTreeView">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="indentation">
<number>10</number>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>true</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CTimedLineEdit</class>
<extends>QLineEdit</extends>
<header>Editor/Widgets/CTimedLineEdit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,268 @@
#include "CWorldTreeModel.h"
#include "CEditorApplication.h"
#include "CWorldEditor.h"
#include "UICommon.h"
#include <Core/GameProject/CGameProject.h>
#include <QIcon>
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<CAssetID> WorldIDs;
pProj->GetWorldList(WorldIDs);
QList<CAssetID> QWorldIDs = QList<CAssetID>::fromStdList(WorldIDs);
foreach (const CAssetID& rkID, QWorldIDs)
{
CResourceEntry *pEntry = pProj->ResourceStore()->FindEntry(rkID);
if (pEntry)
{
TResPtr<CWorld> 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<CWorldTreeModel*>(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<CWorldTreeModel*>(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;
}

View File

@ -0,0 +1,53 @@
#ifndef CWORLDTREEMODEL_H
#define CWORLDTREEMODEL_H
#include <Core/Resource/CWorld.h>
#include <QAbstractItemModel>
#include <QSortFilterProxyModel>
class CWorldEditor;
class CWorldTreeModel : public QAbstractItemModel
{
Q_OBJECT
struct SWorldInfo
{
TResPtr<CWorld> pWorld;
QList<CResourceEntry*> Areas;
};
QList<SWorldInfo> 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

View File

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

View File

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

View File

@ -6,17 +6,22 @@
#include <Core/Scene/CScene.h>
#include <Core/Scene/CSceneIterator.h>
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

View File

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

View File

@ -10,13 +10,16 @@
#include <QScrollArea>
#include <QScrollBar>
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<CScriptObject*>&)), this, SLOT(OnInstanceLinksModified(const QList<CScriptObject*>&)));
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<CScriptObject*>&)), this, SLOT(OnInstanceLinksModified(const QList<CScriptObject*>&)));
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())

View File

@ -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<CScriptObject*>& rkInstances);
void OnWorldSelectionTransformed();
void OnMapChanged();
void OnLinksSelectionModified();
void OnAddLinkActionClicked(QAction *pAction);