diff --git a/src/Editor/CEditorApplication.cpp b/src/Editor/CEditorApplication.cpp index e83a4137..f58a5b31 100644 --- a/src/Editor/CEditorApplication.cpp +++ b/src/Editor/CEditorApplication.cpp @@ -157,12 +157,23 @@ void CEditorApplication::EditResource(CResourceEntry *pEntry) case EResourceType::StringTable: pEd = new CStringEditor((CStringTable*) pRes, mpWorldEditor); break; + + case EResourceType::Tweaks: + { + CTweakEditor* pTweakEditor = mpWorldEditor->TweakEditor(); + pTweakEditor->SetActiveTweakData( (CTweakData*) pRes ); + pEd = pTweakEditor; + break; + } + } if (pEd) { pEd->show(); - mEditingMap[pEntry] = pEd; + + if (pEntry->ResourceType() != EResourceType::Tweaks) + mEditingMap[pEntry] = pEd; } else if (pEntry->ResourceType() != EResourceType::Area) UICommon::InfoMsg(mpWorldEditor, "Unsupported Resource", "This resource type is currently unsupported for editing."); @@ -308,7 +319,11 @@ void CEditorApplication::OnEditorClose() } mEditorWindows.removeOne(pEditor); - delete pEditor; + + if (pEditor != mpWorldEditor->TweakEditor()) + { + delete pEditor; + } if (mpActiveProject) { diff --git a/src/Editor/CTweakEditor.cpp b/src/Editor/CTweakEditor.cpp new file mode 100644 index 00000000..e2c0d988 --- /dev/null +++ b/src/Editor/CTweakEditor.cpp @@ -0,0 +1,108 @@ +#include "CTweakEditor.h" +#include "ui_CTweakEditor.h" + +CTweakEditor::CTweakEditor(QWidget* pParent) + : IEditor(pParent) + , mpUI(new Ui::CTweakEditor) + , mCurrentTweakIndex(-1) + , mHasBeenShown(false) +{ + mpUI->setupUi(this); + mpUI->TweakTabs->setExpanding(false); + SET_WINDOWTITLE_APPVARS("%APP_FULL_NAME% - Tweak Editor"); + + connect(mpUI->TweakTabs, SIGNAL(currentChanged(int)), this, SLOT(SetActiveTweakIndex(int))); +} + +CTweakEditor::~CTweakEditor() +{ + delete mpUI; +} + +bool CTweakEditor::HasTweaks() +{ + return !mTweakAssets.isEmpty(); +} + +void CTweakEditor::showEvent(QShowEvent* pEvent) +{ + // Perform first-time UI initialization + // Property view cannot initialize correctly until first show due to window width not being configured + if (!mHasBeenShown) + { + mpUI->PropertyView->InitColumnWidths(0.6f, 0.3f); + mHasBeenShown = true; + } + + IEditor::showEvent(pEvent); +} + +void CTweakEditor::SetActiveTweakData(CTweakData* pTweakData) +{ + for( int TweakIdx = 0; TweakIdx < mTweakAssets.size(); TweakIdx++ ) + { + if (mTweakAssets[TweakIdx] == pTweakData) + { + SetActiveTweakIndex(TweakIdx); + break; + } + } +} + +void CTweakEditor::SetActiveTweakIndex(int Index) +{ + if( mCurrentTweakIndex != Index ) + { + mCurrentTweakIndex = Index; + + CTweakData* pTweakData = mTweakAssets[Index]; + mpUI->PropertyView->SetIntrinsicProperties(pTweakData->TweakData()); + + mpUI->TweakTabs->blockSignals(true); + mpUI->TweakTabs->setCurrentIndex(Index); + mpUI->TweakTabs->blockSignals(false); + } +} + +void CTweakEditor::OnProjectChanged(CGameProject* pNewProject) +{ + // Close and clear tabs + mCurrentTweakIndex = -1; + mpUI->PropertyView->ClearProperties(); + close(); + + mpUI->TweakTabs->blockSignals(true); + + while (mpUI->TweakTabs->count() > 0) + { + mpUI->TweakTabs->removeTab(0); + } + + mpUI->TweakTabs->blockSignals(false); + mTweakAssets.clear(); + + // Create tweak list + if (pNewProject != nullptr) + { + for (TResPtr pTweakData : pNewProject->TweakManager()->TweakObjects()) + { + mTweakAssets << pTweakData.RawPointer(); + } + } + + // Sort in alphabetical order and create tabs + if (!mTweakAssets.isEmpty()) + { + qSort(mTweakAssets.begin(), mTweakAssets.end(), [](CTweakData* pLeft, CTweakData* pRight) -> bool { + return pLeft->Entry()->Name().ToUpper() < pRight->Entry()->Name().ToUpper(); + }); + + foreach (CTweakData* pTweakData, mTweakAssets) + { + QString TweakName = TO_QSTRING( pTweakData->Entry()->Name() ); + mpUI->TweakTabs->addTab(TweakName); + } + + SetActiveTweakIndex(0); + } +} diff --git a/src/Editor/CTweakEditor.h b/src/Editor/CTweakEditor.h new file mode 100644 index 00000000..4b312ec9 --- /dev/null +++ b/src/Editor/CTweakEditor.h @@ -0,0 +1,39 @@ +#ifndef CTWEAKEDITOR_H +#define CTWEAKEDITOR_H + +#include "Editor/IEditor.h" + +namespace Ui { +class CTweakEditor; +} + +class CTweakEditor : public IEditor +{ + Q_OBJECT + + /** Qt UI */ + Ui::CTweakEditor* mpUI; + + /** List of editable tweak assets */ + QVector mTweakAssets; + + /** Whether the editor window has been shown before */ + bool mHasBeenShown; + + /** Index of tweak data currently being edited */ + int mCurrentTweakIndex; + +public: + explicit CTweakEditor(QWidget* pParent = 0); + ~CTweakEditor(); + bool HasTweaks(); + + virtual void showEvent(QShowEvent* pEvent) override; + +public slots: + void SetActiveTweakData(CTweakData* pTweakData); + void SetActiveTweakIndex(int Index); + void OnProjectChanged(CGameProject* pNewProject); +}; + +#endif // CTWEAKEDITOR_H diff --git a/src/Editor/CTweakEditor.ui b/src/Editor/CTweakEditor.ui new file mode 100644 index 00000000..4c4d8550 --- /dev/null +++ b/src/Editor/CTweakEditor.ui @@ -0,0 +1,120 @@ + + + CTweakEditor + + + + 0 + 0 + 452 + 644 + + + + MainWindow + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 10 + + + + true + + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerPixel + + + + + + + + toolBar + + + + 32 + 32 + + + + TopToolBarArea + + + false + + + + + + + + :/icons/Save.png:/icons/Save.png + + + Save + + + Save + + + Ctrl+S + + + + + + :/icons/SaveAndRepack_32px.png:/icons/SaveAndRepack_32px.png + + + Save and Repack + + + Save and Repack + + + + + + QTabBar + QWidget +
QTabBar
+ 1 +
+ + CPropertyView + QTreeView +
Editor/PropertyEdit/CPropertyView.h
+
+
+ + + + +
diff --git a/src/Editor/Editor.pro b/src/Editor/Editor.pro index ffb7d837..1424675b 100644 --- a/src/Editor/Editor.pro +++ b/src/Editor/Editor.pro @@ -203,7 +203,8 @@ HEADERS += \ StringEditor/CStringEditor.h \ StringEditor/CStringListModel.h \ StringEditor/CStringDelegate.h \ - CCustomDelegate.h + CCustomDelegate.h \ + CTweakEditor.h # Source Files SOURCES += \ @@ -282,7 +283,8 @@ SOURCES += \ StringEditor/CStringEditor.cpp \ StringEditor/CStringListModel.cpp \ IEditor.cpp \ - StringEditor/CStringDelegate.cpp + StringEditor/CStringDelegate.cpp \ + CTweakEditor.cpp # UI Files FORMS += \ @@ -310,7 +312,8 @@ FORMS += \ CProgressDialog.ui \ Widgets/CSelectResourcePanel.ui \ CGeneratePropertyNamesDialog.ui \ - StringEditor/CStringEditor.ui + StringEditor/CStringEditor.ui \ + CTweakEditor.ui # Codegen CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen diff --git a/src/Editor/PropertyEdit/CPropertyDelegate.cpp b/src/Editor/PropertyEdit/CPropertyDelegate.cpp index de5049a3..5c35d342 100644 --- a/src/Editor/PropertyEdit/CPropertyDelegate.cpp +++ b/src/Editor/PropertyEdit/CPropertyDelegate.cpp @@ -27,12 +27,12 @@ CPropertyDelegate::CPropertyDelegate(QObject *pParent /*= 0*/) : QStyledItemDelegate(pParent) - , mpEditor(nullptr) , mpModel(nullptr) , mInRelayWidgetEdit(false) , mEditInProgress(false) , mRelaysBlocked(false) { + mpEditor = gpEdApp->WorldEditor(); } void CPropertyDelegate::SetPropertyModel(CPropertyModel *pModel) @@ -40,11 +40,6 @@ void CPropertyDelegate::SetPropertyModel(CPropertyModel *pModel) mpModel = pModel; } -void CPropertyDelegate::SetEditor(CWorldEditor *pEditor) -{ - mpEditor = pEditor; -} - QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionViewItem& /*rkOption*/, const QModelIndex& rkIndex) const { if (!mpModel) return nullptr; diff --git a/src/Editor/PropertyEdit/CPropertyDelegate.h b/src/Editor/PropertyEdit/CPropertyDelegate.h index 95948a81..a79008ae 100644 --- a/src/Editor/PropertyEdit/CPropertyDelegate.h +++ b/src/Editor/PropertyEdit/CPropertyDelegate.h @@ -18,7 +18,6 @@ class CPropertyDelegate : public QStyledItemDelegate public: CPropertyDelegate(QObject *pParent = 0); void SetPropertyModel(CPropertyModel *pModel); - void SetEditor(CWorldEditor *pEditor); virtual QWidget* createEditor(QWidget *pParent, const QStyleOptionViewItem& rkOption, const QModelIndex& rkIndex) const; virtual void setEditorData(QWidget *pEditor, const QModelIndex &rkIndex) const; diff --git a/src/Editor/PropertyEdit/CPropertyView.cpp b/src/Editor/PropertyEdit/CPropertyView.cpp index 79f534ce..36e296b0 100644 --- a/src/Editor/PropertyEdit/CPropertyView.cpp +++ b/src/Editor/PropertyEdit/CPropertyView.cpp @@ -9,7 +9,6 @@ CPropertyView::CPropertyView(QWidget *pParent) : QTreeView(pParent) - , mpEditor(nullptr) , mpMenuProperty(nullptr) { mpModel = new CPropertyModel(this); @@ -40,6 +39,9 @@ CPropertyView::CPropertyView(QWidget *pParent) connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CreateContextMenu(QPoint))); connect(mpModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(SetPersistentEditors(QModelIndex))); connect(mpModel, SIGNAL(PropertyModified(const QModelIndex&)), this, SLOT(OnPropertyModified(const QModelIndex&))); + + mpEditor = gpEdApp->WorldEditor(); + connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), mpModel, SLOT(NotifyPropertyModified(CScriptObject*,IProperty*))); } void CPropertyView::setModel(QAbstractItemModel *pModel) @@ -84,11 +86,17 @@ bool CPropertyView::event(QEvent *pEvent) else return QTreeView::event(pEvent); } -void CPropertyView::SetEditor(CWorldEditor *pEditor) +void CPropertyView::InitColumnWidths(float NameColumnPercentage, float ValueColumnPercentage) { - mpEditor = pEditor; - mpDelegate->SetEditor(pEditor); - connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), mpModel, SLOT(NotifyPropertyModified(CScriptObject*,IProperty*))); + header()->resizeSection(0, width() * NameColumnPercentage); + header()->resizeSection(1, width() * ValueColumnPercentage); + header()->setSectionResizeMode(1, QHeaderView::Fixed); +} + +void CPropertyView::ClearProperties() +{ + mpObject = nullptr; + mpModel->ConfigureScript(nullptr, nullptr, nullptr); } void CPropertyView::SetIntrinsicProperties(CStructRef InProperties) diff --git a/src/Editor/PropertyEdit/CPropertyView.h b/src/Editor/PropertyEdit/CPropertyView.h index abced927..cc7c38eb 100644 --- a/src/Editor/PropertyEdit/CPropertyView.h +++ b/src/Editor/PropertyEdit/CPropertyView.h @@ -26,7 +26,8 @@ public: CPropertyView(QWidget *pParent = 0); void setModel(QAbstractItemModel *pModel); bool event(QEvent *pEvent); - void SetEditor(CWorldEditor *pEditor); + void InitColumnWidths(float NameColumnPercentage, float ValueColumnPercentage); + void ClearProperties(); void SetIntrinsicProperties(CStructRef InProperties); void SetInstance(CScriptObject *pObj); void UpdateEditorProperties(const QModelIndex& rkParent); diff --git a/src/Editor/WorldEditor/CWorldEditor.cpp b/src/Editor/WorldEditor/CWorldEditor.cpp index 7cf5b476..8c457760 100644 --- a/src/Editor/WorldEditor/CWorldEditor.cpp +++ b/src/Editor/WorldEditor/CWorldEditor.cpp @@ -39,6 +39,7 @@ CWorldEditor::CWorldEditor(QWidget *parent) , mpWorld(nullptr) , mpLinkDialog(new CLinkDialog(this, this)) , mpGeneratePropertyNamesDialog(new CGeneratePropertyNamesDialog(this)) + , mpTweakEditor(new CTweakEditor(this)) , mIsMakingLink(false) , mpNewLinkSender(nullptr) , mpNewLinkReceiver(nullptr) @@ -170,8 +171,9 @@ CWorldEditor::CWorldEditor(QWidget *parent) connect(ui->ActionLink, SIGNAL(toggled(bool)), this, SLOT(OnLinkButtonToggled(bool))); connect(ui->ActionUnlink, SIGNAL(triggered()), this, SLOT(OnUnlinkClicked())); + connect(ui->ActionEditTweaks, SIGNAL(triggered()), mpTweakEditor, SLOT(show())); connect(ui->ActionEditLayers, SIGNAL(triggered()), this, SLOT(EditLayers())); - connect(ui->ActionGeneratePropertyNames, SIGNAL(triggered()), this, SLOT(GeneratePropertyNames())); + connect(ui->ActionGeneratePropertyNames, SIGNAL(triggered()), mpGeneratePropertyNamesDialog, SLOT(show())); connect(ui->ActionDrawWorld, SIGNAL(triggered()), this, SLOT(ToggleDrawWorld())); connect(ui->ActionDrawObjects, SIGNAL(triggered()), this, SLOT(ToggleDrawObjects())); @@ -190,7 +192,7 @@ CWorldEditor::CWorldEditor(QWidget *parent) connect(ui->ActionBloom, SIGNAL(triggered()), this, SLOT(SetBloom())); connect(ui->ActionIncrementGizmo, SIGNAL(triggered()), this, SLOT(IncrementGizmo())); connect(ui->ActionDecrementGizmo, SIGNAL(triggered()), this, SLOT(DecrementGizmo())); - connect(ui->ActionCollisionRenderSettings, SIGNAL(triggered()), this, SLOT(EditCollisionRenderSettings())); + connect(ui->ActionCollisionRenderSettings, SIGNAL(triggered()), mpCollisionDialog, SLOT(show())); connect(ui->ActionAbout, SIGNAL(triggered(bool)), this, SLOT(About())); } @@ -509,6 +511,12 @@ void CWorldEditor::OnActiveProjectChanged(CGameProject *pProj) ResetCamera(); UpdateWindowTitle(); + // Update tweak editor + // We update this here to ensure we can update the menu item correctly without risking + // that this function runs before the tweak editor has a chance to update its tweak list. + mpTweakEditor->OnProjectChanged(pProj); + ui->ActionEditTweaks->setEnabled( mpTweakEditor->HasTweaks() ); + // Default bloom to Fake Bloom for Metroid Prime 3; disable for other games bool AllowBloom = (CurrentGame() == EGame::CorruptionProto || CurrentGame() == EGame::Corruption); AllowBloom ? SetFakeBloom() : SetNoBloom(); @@ -1319,11 +1327,6 @@ void CWorldEditor::DecrementGizmo() mGizmo.DecrementSize(); } -void CWorldEditor::EditCollisionRenderSettings() -{ - mpCollisionDialog->show(); -} - void CWorldEditor::EditLayers() { // Launch layer editor @@ -1331,9 +1334,3 @@ void CWorldEditor::EditLayers() Editor.SetArea(mpArea); Editor.exec(); } - -void CWorldEditor::GeneratePropertyNames() -{ - // Launch property name generation dialog - mpGeneratePropertyNamesDialog->show(); -} diff --git a/src/Editor/WorldEditor/CWorldEditor.h b/src/Editor/WorldEditor/CWorldEditor.h index d32a5449..5dd8b916 100644 --- a/src/Editor/WorldEditor/CWorldEditor.h +++ b/src/Editor/WorldEditor/CWorldEditor.h @@ -6,6 +6,7 @@ #include "CLinkDialog.h" #include "CPoiMapSidebar.h" #include "CScriptEditSidebar.h" +#include "CTweakEditor.h" #include "CWorldInfoSidebar.h" #include "Editor/INodeEditor.h" #include "Editor/CGeneratePropertyNamesDialog.h" @@ -47,31 +48,32 @@ class CWorldEditor : public INodeEditor Q_OBJECT static const int mskMaxRecentProjects = 10; - Ui::CWorldEditor *ui; - QMenu *mpOpenRecentMenu; - QAction *mRecentProjectsActions[ mskMaxRecentProjects ]; + Ui::CWorldEditor* ui; + QMenu* mpOpenRecentMenu; + QAction* mRecentProjectsActions[ mskMaxRecentProjects ]; TResPtr mpWorld; TResPtr mpArea; - CCollisionRenderSettingsDialog *mpCollisionDialog; - CLinkDialog *mpLinkDialog; + CCollisionRenderSettingsDialog* mpCollisionDialog; + CLinkDialog* mpLinkDialog; CGeneratePropertyNamesDialog* mpGeneratePropertyNamesDialog; + CTweakEditor* mpTweakEditor; bool mIsMakingLink; - CScriptObject *mpNewLinkSender; - CScriptObject *mpNewLinkReceiver; + CScriptObject* mpNewLinkSender; + CScriptObject* mpNewLinkReceiver; // Sidebars - QVBoxLayout *mpRightSidebarLayout; - CWorldEditorSidebar *mpCurSidebar; + QVBoxLayout* mpRightSidebarLayout; + CWorldEditorSidebar* mpCurSidebar; - QButtonGroup *mpEditModeButtonGroup; - CWorldInfoSidebar *mpWorldInfoSidebar; - CScriptEditSidebar *mpScriptSidebar; - CPoiMapSidebar *mpPoiMapSidebar; + QButtonGroup* mpEditModeButtonGroup; + CWorldInfoSidebar* mpWorldInfoSidebar; + CScriptEditSidebar* mpScriptSidebar; + CPoiMapSidebar* mpPoiMapSidebar; - QAction *mpPoiMapAction; + QAction* mpPoiMapAction; public: explicit CWorldEditor(QWidget *parent = 0); @@ -86,6 +88,7 @@ public: inline EGame CurrentGame() const { return gpEdApp->CurrentGame(); } inline CLinkDialog* LinkDialog() const { return mpLinkDialog; } inline CGeneratePropertyNamesDialog* NameGeneratorDialog() const { return mpGeneratePropertyNamesDialog; } + inline CTweakEditor* TweakEditor() { return mpTweakEditor; } CResourceBrowser* ResourceBrowser() const; CSceneViewport* Viewport() const; @@ -167,9 +170,7 @@ private slots: void SetBloom(); void IncrementGizmo(); void DecrementGizmo(); - void EditCollisionRenderSettings(); void EditLayers(); - void GeneratePropertyNames(); signals: void MapChanged(CWorld *pNewWorld, CGameArea *pNewArea); diff --git a/src/Editor/WorldEditor/CWorldEditor.ui b/src/Editor/WorldEditor/CWorldEditor.ui index 0b5474c3..87c5a4a5 100644 --- a/src/Editor/WorldEditor/CWorldEditor.ui +++ b/src/Editor/WorldEditor/CWorldEditor.ui @@ -338,6 +338,7 @@ Tools + @@ -785,6 +786,14 @@ About + + + false + + + Edit Tweaks + + diff --git a/src/Editor/WorldEditor/WModifyTab.cpp b/src/Editor/WorldEditor/WModifyTab.cpp index 42a5b25b..fcc3fc5b 100644 --- a/src/Editor/WorldEditor/WModifyTab.cpp +++ b/src/Editor/WorldEditor/WModifyTab.cpp @@ -16,14 +16,9 @@ WModifyTab::WModifyTab(CWorldEditor *pEditor, QWidget *pParent) , mIsPicking(false) { ui->setupUi(this); + ui->PropertyView->InitColumnWidths(0.3f, 0.3f); mpWorldEditor = pEditor; - ui->PropertyView->SetEditor(mpWorldEditor); - - int PropViewWidth = ui->PropertyView->width(); - ui->PropertyView->header()->resizeSection(0, PropViewWidth * 0.3); - ui->PropertyView->header()->resizeSection(1, PropViewWidth * 0.3); - ui->PropertyView->header()->setSectionResizeMode(1, QHeaderView::Fixed); mpInLinkModel = new CLinkModel(this); mpInLinkModel->SetConnectionType(ELinkType::Incoming); diff --git a/templates/MP1/Misc/TweakGui.xml b/templates/MP1/Misc/TweakGui.xml index e267fbff..837d9cb8 100644 --- a/templates/MP1/Misc/TweakGui.xml +++ b/templates/MP1/Misc/TweakGui.xml @@ -461,7 +461,7 @@ ScanSpeeds - + ScanSpeed diff --git a/templates/MP1/Structs/BeamInfo.xml b/templates/MP1/Structs/BeamInfo.xml index 892b6d62..1f5f6bd5 100644 --- a/templates/MP1/Structs/BeamInfo.xml +++ b/templates/MP1/Structs/BeamInfo.xml @@ -5,7 +5,7 @@ true - CoolDown + Cooldown NormalDamage