Added new WIP UI to the world editor for loading worlds/areas
This commit is contained in:
parent
9928a599be
commit
ce0c544168
|
@ -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++)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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");
|
||||
}
|
|
@ -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
|
|
@ -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) );
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue