diff --git a/src/Common/Hash/CCRC32.cpp b/src/Common/Hash/CCRC32.cpp index 9b814cd3..810e3ecd 100644 --- a/src/Common/Hash/CCRC32.cpp +++ b/src/Common/Hash/CCRC32.cpp @@ -106,6 +106,11 @@ void CCRC32::Hash(double v) Hash(&v, 8); } +void CCRC32::Hash(char v) +{ + Hash(&v, 1); +} + void CCRC32::Hash(const char* pkString) { while (*pkString) diff --git a/src/Common/Hash/CCRC32.h b/src/Common/Hash/CCRC32.h index 36dd61ff..bddfb600 100644 --- a/src/Common/Hash/CCRC32.h +++ b/src/Common/Hash/CCRC32.h @@ -32,6 +32,7 @@ public: void Hash(u64 v); void Hash(float v); void Hash(double v); + void Hash(char v); void Hash(const char* pkString); static u32 StaticHashString(const char* pkString); diff --git a/src/Common/NBasics.h b/src/Common/NBasics.h index 4e5eb1bc..48a144ce 100644 --- a/src/Common/NBasics.h +++ b/src/Common/NBasics.h @@ -83,7 +83,7 @@ bool VectorContains(std::vector& Vector, const T& kElement) template bool VectorAddUnique(std::vector& Vector, const T& kElement) { - if (!VectorContainsElement(Vector, kElement)) + if (!VectorContains(Vector, kElement)) { Vector.push_back(kElement); return true; diff --git a/src/Core/Resource/Script/CGameTemplate.cpp b/src/Core/Resource/Script/CGameTemplate.cpp index d98cd2e7..e4e02b6a 100644 --- a/src/Core/Resource/Script/CGameTemplate.cpp +++ b/src/Core/Resource/Script/CGameTemplate.cpp @@ -193,7 +193,6 @@ SMessage CGameTemplate::MessageByIndex(u32 Index) IProperty* CGameTemplate::FindPropertyArchetype(const TString& kTypeName) { auto Iter = mPropertyTemplates.find(kTypeName); - ASSERT(Iter != mPropertyTemplates.end()); // Requested archetype property does not exist; missing or malformed template if (Iter == mPropertyTemplates.end()) { diff --git a/src/Core/Resource/Script/Property/CPropertyNameGenerator.cpp b/src/Core/Resource/Script/Property/CPropertyNameGenerator.cpp index 601ce3bf..12a86760 100644 --- a/src/Core/Resource/Script/Property/CPropertyNameGenerator.cpp +++ b/src/Core/Resource/Script/Property/CPropertyNameGenerator.cpp @@ -28,14 +28,9 @@ void CPropertyNameGenerator::Warmup() while (!feof(pListFile)) { - char WordBuffer[256]; - fgets(&WordBuffer[0], 256, pListFile); - - // Capitalize first letter - if (WordBuffer[0] >= 'a' && WordBuffer[0] <= 'z') - { - WordBuffer[0] -= 0x20; - } + char WordBuffer[64]; + fgets(&WordBuffer[0], 64, pListFile); + WordBuffer[0] = TString::CharToUpper(WordBuffer[0]); SWord Word; Word.Word = TString(WordBuffer).Trimmed(); @@ -53,9 +48,27 @@ void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& r ASSERT(!mIsRunning); ASSERT(rkParams.TypeNames.size() > 0); mGeneratedNames.clear(); + mValidTypePairMap.clear(); mIsRunning = true; mFinishedRunning = false; + // Convert valid type pairs into hashes. + // Also, replace the normal type name list with whatever is in the ID pairs list we were given. + if (!rkParams.ValidIdPairs.empty()) + { + mTypeNames.clear(); + + for (const SPropertyIdTypePair& kPair : rkParams.ValidIdPairs) + { + mValidTypePairMap[ kPair.ID ] = kPair.pkType; + NBasics::VectorAddUnique( mTypeNames, TString(kPair.pkType) ); + } + } + else + { + mTypeNames = rkParams.TypeNames; + } + // If we haven't loaded the word list yet, load it. // If we are still loading the word list, wait until we're finished. if (!mWordListLoadFinished) @@ -132,11 +145,22 @@ void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& r { int Index = WordCache[RecalcIndex].WordIndex; - // Add an underscore if needed - if (RecalcIndex > 0 && rkParams.UseUnderscores) - LastValidHash.Hash("_"); + // For camelcase, hash the first letter of the first word as lowercase + if (RecalcIndex == 0 && rkParams.Casing == ENameCasing::camelCase) + { + const char* pkWord = *mWords[Index].Word; + LastValidHash.Hash( TString::CharToLower( pkWord[0] ) ); + LastValidHash.Hash( &pkWord[1] ); + } + else + { + // Add an underscore for snake case + if (RecalcIndex > 0 && rkParams.Casing == ENameCasing::Snake_Case) + LastValidHash.Hash("_"); + + LastValidHash.Hash( *mWords[Index].Word ); + } - LastValidHash.Hash( *mWords[Index].Word ); WordCache[RecalcIndex].Hash = LastValidHash; } @@ -144,15 +168,15 @@ void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& r CCRC32 BaseHash = LastValidHash; BaseHash.Hash( *rkParams.Suffix ); - for (int TypeIdx = 0; TypeIdx < rkParams.TypeNames.size(); TypeIdx++) + for (int TypeIdx = 0; TypeIdx < mTypeNames.size(); TypeIdx++) { CCRC32 FullHash = BaseHash; - const char* pkTypeName = *rkParams.TypeNames[TypeIdx]; + const char* pkTypeName = *mTypeNames[TypeIdx]; FullHash.Hash( pkTypeName ); u32 PropertyID = FullHash.Digest(); // Check if this hash is a property ID - if (NPropertyMap::IsValidPropertyName(PropertyID, pkTypeName)) + if (IsValidPropertyID(PropertyID, pkTypeName)) { SGeneratedPropertyName PropertyName; NPropertyMap::RetrieveXMLsWithProperty(PropertyID, pkTypeName, PropertyName.XmlList); @@ -164,7 +188,7 @@ void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& r { int Index = WordCache[WordIdx].WordIndex; - if (WordIdx > 0 && rkParams.UseUnderscores) + if (WordIdx > 0 && rkParams.Casing == ENameCasing::Snake_Case) { PropertyName.Name += "_"; } @@ -172,8 +196,13 @@ void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& r PropertyName.Name += mWords[Index].Word; } + if (rkParams.Casing == ENameCasing::camelCase) + { + PropertyName.Name[0] = TString::CharToLower( PropertyName.Name[0] ); + } + PropertyName.Name += rkParams.Suffix; - PropertyName.Type = rkParams.TypeNames[TypeIdx]; + PropertyName.Type = mTypeNames[TypeIdx]; PropertyName.ID = PropertyID; if (SaveResults) @@ -184,7 +213,7 @@ void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& r // If we have too many saved results, then to avoid crashing we will force enable log output. if (mGeneratedNames.size() > 9999) { - gpUIRelay->AsyncMessageBox("Warning", "There are over 10,000 results. To avoid memory issues, results will no longer print to the screen. Check the log for the rest of the output."); + gpUIRelay->AsyncMessageBox("Warning", "There are over 10,000 results. Results will no longer print to the screen. Check the log for the remaining output."); WriteToLog = true; SaveResults = false; } @@ -222,3 +251,21 @@ void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& r mIsRunning = false; mFinishedRunning = true; } + +/** Returns whether a given property ID is valid */ +bool CPropertyNameGenerator::IsValidPropertyID(u32 ID, const char* pkType) +{ + if (!mValidTypePairMap.empty()) + { + auto Find = mValidTypePairMap.find(ID); + + if (Find != mValidTypePairMap.end()) + { + return strcmp( Find->second, pkType ) == 0; + } + else + return false; + } + else + return NPropertyMap::IsValidPropertyName(ID, pkType); +} diff --git a/src/Core/Resource/Script/Property/CPropertyNameGenerator.h b/src/Core/Resource/Script/Property/CPropertyNameGenerator.h index 721cf655..9f5fb6c2 100644 --- a/src/Core/Resource/Script/Property/CPropertyNameGenerator.h +++ b/src/Core/Resource/Script/Property/CPropertyNameGenerator.h @@ -4,6 +4,21 @@ #include "Core/IProgressNotifier.h" #include +/** Name casing parameter */ +enum class ENameCasing +{ + PascalCase, + Snake_Case, + camelCase, +}; + +/** ID/type pairing for ID pool */ +struct SPropertyIdTypePair +{ + u32 ID; + const char* pkType; +}; + /** Parameters for using the name generator */ struct SPropertyNameGenerationParameters { @@ -16,11 +31,14 @@ struct SPropertyNameGenerationParameters /** Suffix to include at the end of every name */ TString Suffix; + /** Name casing to use */ + ENameCasing Casing; + /** List of valid type suffixes */ std::vector TypeNames; - /** Whether to separate words with underscores */ - bool UseUnderscores; + /** List of ID/type pairs to check against. If empty, all properties are valid. */ + std::vector ValidIdPairs; /** Whether to print the output from the generation process to the log */ bool PrintToLog; @@ -50,6 +68,12 @@ class CPropertyNameGenerator /** Whether the generation process finished running */ bool mFinishedRunning; + /** List of valid property types to check against */ + std::vector mTypeNames; + + /** Mapping of valid ID/type pairs; if empty, all property names in NPropertyMap are allowed */ + std::unordered_map mValidTypePairMap; + /** List of words */ struct SWord { @@ -74,6 +98,9 @@ public: /** Run the name generation system */ void Generate(const SPropertyNameGenerationParameters& rkParams, IProgressNotifier* pProgressNotifier); + /** Returns whether a given property ID is valid */ + bool IsValidPropertyID(u32 ID, const char* pkType); + /** Accessors */ bool IsRunning() const { diff --git a/src/Editor/CGeneratePropertyNamesDialog.cpp b/src/Editor/CGeneratePropertyNamesDialog.cpp index b256d8f4..6fd6384c 100644 --- a/src/Editor/CGeneratePropertyNamesDialog.cpp +++ b/src/Editor/CGeneratePropertyNamesDialog.cpp @@ -20,6 +20,7 @@ CGeneratePropertyNamesDialog::CGeneratePropertyNamesDialog(QWidget* pParent) connect( mpUI->AddSuffixButton, SIGNAL(pressed()), this, SLOT(AddSuffix()) ); connect( mpUI->RemoveSuffixButton, SIGNAL(pressed()), this, SLOT(DeleteSuffix()) ); + connect( mpUI->ClearIdPoolButton, SIGNAL(pressed()), this, SLOT(ClearIdPool()) ); connect( mpUI->StartButton, SIGNAL(pressed()), this, SLOT(StartGeneration()) ); connect( mpUI->CancelButton, SIGNAL(pressed()), this, SLOT(CancelGeneration()) ); connect( mpUI->CheckAllButton, SIGNAL(pressed()), this, SLOT(CheckAll()) ); @@ -45,6 +46,56 @@ CGeneratePropertyNamesDialog::~CGeneratePropertyNamesDialog() delete mpUI; } +/** Add a property to the ID pool */ +void CGeneratePropertyNamesDialog::AddToIDPool(IProperty* pProperty) +{ + if (!pProperty->UsesNameMap()) + { + Log::Error("Failed to add property " + pProperty->IDString(false) + " to the generator ID pool because it doesn't use the name map"); + return; + } + + u32 ID = pProperty->ID(); + const char* pkTypeName = pProperty->HashableTypeName(); + mIdPairs << SPropertyIdTypePair { ID, pkTypeName }; + + QString ItemText = QString("%1 [%2]").arg( *TString::HexString(pProperty->ID(), 8, false) ).arg( pkTypeName ); + mpUI->IdPoolList->addItem( ItemText ); + + // We probably don't want to call UpdateUI every single time we add a property, but + // we do need to call it somewhere to make sure the ID list shows up on the UI... + if (mpUI->IdPoolGroupBox->isHidden()) + { + UpdateUI(); + } +} + +/** Populate the ID pool with the children of the given property */ +void CGeneratePropertyNamesDialog::AddChildrenToIDPool(IProperty* pProperty, bool Recursive) +{ + for (u32 ChildIdx = 0; ChildIdx < pProperty->NumChildren(); ChildIdx++) + { + IProperty* pChild = pProperty->ChildByIndex(ChildIdx); + + // Skip children that already have valid property names + if (!pChild->HasAccurateName() && pChild->UsesNameMap()) + { + AddToIDPool(pChild); + } + + if (Recursive) + { + AddChildrenToIDPool(pChild, true); + } + } +} + +/** Show event override */ +void CGeneratePropertyNamesDialog::showEvent(QShowEvent*) +{ + UpdateUI(); +} + /** Close event override */ void CGeneratePropertyNamesDialog::closeEvent(QCloseEvent*) { @@ -52,6 +103,7 @@ void CGeneratePropertyNamesDialog::closeEvent(QCloseEvent*) { CancelGeneration(); } + ClearIdPool(); } /** Add an item to the suffix list */ @@ -75,6 +127,14 @@ void CGeneratePropertyNamesDialog::DeleteSuffix() } } +/** Clear the ID pool */ +void CGeneratePropertyNamesDialog::ClearIdPool() +{ + mIdPairs.clear(); + mpUI->IdPoolList->clear(); + UpdateUI(); +} + /** Start name generation */ void CGeneratePropertyNamesDialog::StartGeneration() { @@ -100,7 +160,8 @@ void CGeneratePropertyNamesDialog::StartGeneration() Params.MaxWords = mpUI->NumWordsSpinBox->value(); Params.Prefix = TO_TSTRING( mpUI->PrefixLineEdit->text() ); Params.Suffix = TO_TSTRING( mpUI->SuffixLineEdit->text() ); - Params.UseUnderscores = mpUI->UseUnderscoresCheckBox->isChecked(); + Params.Casing = mpUI->CasingComboBox->currentEnum(); + Params.ValidIdPairs = mIdPairs.toStdVector(); Params.PrintToLog = mpUI->LogOutputCheckBox->isChecked(); // Run the task and configure ourselves so we can update correctly @@ -287,8 +348,11 @@ void CGeneratePropertyNamesDialog::CheckForNewResults() /** Updates the enabled status of various widgets */ void CGeneratePropertyNamesDialog::UpdateUI() { - mpUI->TypeSuffixesGroupBox->setEnabled( !mRunningNameGeneration ); mpUI->SettingsGroupBox->setEnabled( !mRunningNameGeneration ); + mpUI->TypeSuffixesGroupBox->setEnabled( !mRunningNameGeneration ); + mpUI->TypeSuffixesGroupBox->setHidden( !mIdPairs.isEmpty() ); + mpUI->IdPoolGroupBox->setEnabled( !mRunningNameGeneration ); + mpUI->IdPoolGroupBox->setHidden( mIdPairs.isEmpty() ); mpUI->StartButton->setEnabled( !mRunningNameGeneration ); mpUI->CancelButton->setEnabled( mRunningNameGeneration && !mCanceledNameGeneration ); diff --git a/src/Editor/CGeneratePropertyNamesDialog.h b/src/Editor/CGeneratePropertyNamesDialog.h index df2fc95a..62b2393f 100644 --- a/src/Editor/CGeneratePropertyNamesDialog.h +++ b/src/Editor/CGeneratePropertyNamesDialog.h @@ -2,7 +2,10 @@ #define CGENERATEPROPERTYNAMESDIALOG_H #include "CProgressBarNotifier.h" +#include "Editor/Widgets/TEnumComboBox.h" #include +#include +#include #include #include @@ -11,6 +14,8 @@ #include #include +using CNameCasingComboBox = TEnumComboBox; + namespace Ui { class CGeneratePropertyNamesDialog; } @@ -29,6 +34,9 @@ class CGeneratePropertyNamesDialog : public QDialog /** Progress notifier for updating the progress bar */ CProgressBarNotifier mNotifier; + /** List of ID/type pairs in the ID pool */ + QVector mIdPairs; + /** Future/future watcher for name generation task */ QFuture mFuture; QFutureWatcher mFutureWatcher; @@ -52,7 +60,19 @@ public: explicit CGeneratePropertyNamesDialog(QWidget *pParent = 0); ~CGeneratePropertyNamesDialog(); + /** Add a property to the ID pool */ + void AddToIDPool(IProperty* pProperty); + + /** Populate the ID pool with the children of the given property */ + void AddChildrenToIDPool(IProperty* pProperty, bool Recursive); + + /** Populate the ID pool with enum values */ + void AddEnumValuesToIDPool(CEnumProperty* pEnum); + public slots: + /** Show event override */ + virtual void showEvent(QShowEvent* pEvent); + /** Close event override */ virtual void closeEvent(QCloseEvent* pEvent); @@ -62,6 +82,9 @@ public slots: /** Deletes an item from the suffix list */ void DeleteSuffix(); + /** Clear the ID pool */ + void ClearIdPool(); + /** Start name generation */ void StartGeneration(); diff --git a/src/Editor/CGeneratePropertyNamesDialog.ui b/src/Editor/CGeneratePropertyNamesDialog.ui index 3d92157d..e5a2daf5 100644 --- a/src/Editor/CGeneratePropertyNamesDialog.ui +++ b/src/Editor/CGeneratePropertyNamesDialog.ui @@ -17,7 +17,7 @@ - + @@ -66,15 +66,18 @@ + + + + Casing: + + + + + + - - - - Use underscores - - - @@ -232,6 +235,46 @@ + + + + IDs + + + + + + true + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Clear + + + + + + + + @@ -382,6 +425,11 @@ QTreeWidget
Editor/Widgets/CCheckableTreeWidget.h
+ + CNameCasingComboBox + QComboBox +
Editor/CGeneratePropertyNamesDialog.h
+
diff --git a/src/Editor/Editor.pro b/src/Editor/Editor.pro index e370816e..c86ba1af 100644 --- a/src/Editor/Editor.pro +++ b/src/Editor/Editor.pro @@ -201,7 +201,8 @@ HEADERS += \ CProgressBarNotifier.h \ Widgets/CCheckableTreeWidgetItem.h \ Widgets/CCheckableTreeWidget.h \ - Undo/IEditPropertyCommand.h + Undo/IEditPropertyCommand.h \ + Widgets/TEnumComboBox.h # Source Files SOURCES += \ diff --git a/src/Editor/PropertyEdit/CPropertyView.cpp b/src/Editor/PropertyEdit/CPropertyView.cpp index 3281abe9..2c319630 100644 --- a/src/Editor/PropertyEdit/CPropertyView.cpp +++ b/src/Editor/PropertyEdit/CPropertyView.cpp @@ -28,6 +28,13 @@ CPropertyView::CPropertyView(QWidget *pParent) mpEditTemplateAction = new QAction("Edit template", this); connect(mpEditTemplateAction, SIGNAL(triggered()), this, SLOT(EditPropertyTemplate())); + mpGenNamesForPropertyAction = new QAction("Generate names for this property", this); + mpGenNamesForSiblingsAction = new QAction(this); // Text set in CreateContextMenu() + mpGenNamesForChildrenAction = new QAction(this); // Text set in CreateContextMenu() + connect(mpGenNamesForPropertyAction, SIGNAL(triggered(bool)), this, SLOT(GenerateNamesForProperty())); + connect(mpGenNamesForSiblingsAction, SIGNAL(triggered(bool)), this, SLOT(GenerateNamesForSiblings())); + connect(mpGenNamesForChildrenAction, SIGNAL(triggered(bool)), this, SLOT(GenerateNamesForChildren())); + connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(SetPersistentEditors(QModelIndex))); connect(this, SIGNAL(clicked(QModelIndex)), this, SLOT(edit(QModelIndex))); connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CreateContextMenu(QPoint))); @@ -216,9 +223,9 @@ void CPropertyView::ClosePersistentEditors(const QModelIndex& rkIndex) void CPropertyView::OnPropertyModified(const QModelIndex& rkIndex) { // Check for a character resource being changed. If that's the case we need to remake the persistent editors. - IProperty *pProp = mpModel->PropertyForIndex(rkIndex, true); + IProperty* pProperty = mpModel->PropertyForIndex(rkIndex, true); - if (pProp->Type() == EPropertyType::AnimationSet /*&& rkIndex.internalId() & 0x1*/) + if (pProperty->Type() == EPropertyType::AnimationSet /*&& rkIndex.internalId() & 0x1*/) { ClosePersistentEditors(rkIndex); SetPersistentEditors(rkIndex); @@ -231,12 +238,12 @@ void CPropertyView::CreateContextMenu(const QPoint& rkPos) if (Index.isValid() && Index.column() == 0) { - IProperty *pProp = mpModel->PropertyForIndex(Index, true); - mpMenuProperty = pProp; + IProperty* pProperty = mpModel->PropertyForIndex(Index, true); + mpMenuProperty = pProperty; QMenu Menu; - if (!pProp->IsIntrinsic()) + if (!pProperty->IsIntrinsic()) { Menu.addAction(mpEditTemplateAction); } @@ -246,6 +253,27 @@ void CPropertyView::CreateContextMenu(const QPoint& rkPos) Menu.addAction(mpShowNameValidityAction); } + // Add options for generating property names + if (pProperty->UsesNameMap()) + { + Menu.addSeparator(); + Menu.addAction(mpGenNamesForPropertyAction); + + if (!pProperty->IsRootParent()) + { + QString TypeName = TO_QSTRING( pProperty->Parent()->RootArchetype()->Name() ); + mpGenNamesForSiblingsAction->setText( QString("Generate names for %1 properties").arg(TypeName) ); + Menu.addAction(mpGenNamesForSiblingsAction); + } + + if (pProperty->Type() == EPropertyType::Struct && !pProperty->IsAtomic()) + { + QString TypeName = TO_QSTRING( pProperty->RootArchetype()->Name() ); + mpGenNamesForChildrenAction->setText( QString("Generate names for %1 properties").arg(TypeName) ); + Menu.addAction(mpGenNamesForChildrenAction); + } + } + Menu.exec(viewport()->mapToGlobal(rkPos)); } } @@ -260,3 +288,25 @@ void CPropertyView::EditPropertyTemplate() CTemplateEditDialog Dialog(mpMenuProperty, mpEditor); Dialog.exec(); } + + +void CPropertyView::GenerateNamesForProperty() +{ + CGeneratePropertyNamesDialog* pDialog = mpEditor->NameGeneratorDialog(); + pDialog->AddToIDPool(mpMenuProperty); + pDialog->show(); +} + +void CPropertyView::GenerateNamesForSiblings() +{ + CGeneratePropertyNamesDialog* pDialog = mpEditor->NameGeneratorDialog(); + pDialog->AddChildrenToIDPool(mpMenuProperty->Parent(), false); + pDialog->show(); +} + +void CPropertyView::GenerateNamesForChildren() +{ + CGeneratePropertyNamesDialog* pDialog = mpEditor->NameGeneratorDialog(); + pDialog->AddChildrenToIDPool(mpMenuProperty, false); + pDialog->show(); +} diff --git a/src/Editor/PropertyEdit/CPropertyView.h b/src/Editor/PropertyEdit/CPropertyView.h index e5ba50ea..c03947f2 100644 --- a/src/Editor/PropertyEdit/CPropertyView.h +++ b/src/Editor/PropertyEdit/CPropertyView.h @@ -18,6 +18,9 @@ class CPropertyView : public QTreeView IProperty *mpMenuProperty; QAction *mpShowNameValidityAction; QAction *mpEditTemplateAction; + QAction *mpGenNamesForPropertyAction; + QAction *mpGenNamesForSiblingsAction; + QAction *mpGenNamesForChildrenAction; public: CPropertyView(QWidget *pParent = 0); @@ -38,6 +41,10 @@ public slots: void CreateContextMenu(const QPoint& rkPos); void ToggleShowNameValidity(bool ShouldShow); void EditPropertyTemplate(); + + void GenerateNamesForProperty(); + void GenerateNamesForSiblings(); + void GenerateNamesForChildren(); }; #endif // CPROPERTYVIEW_H diff --git a/src/Editor/Widgets/TEnumComboBox.h b/src/Editor/Widgets/TEnumComboBox.h new file mode 100644 index 00000000..19dee2e2 --- /dev/null +++ b/src/Editor/Widgets/TEnumComboBox.h @@ -0,0 +1,38 @@ +#ifndef TENUMCOMBOBOX_H +#define TENUMCOMBOBOX_H + +#include +#include + +/** + * Combo box subclass that auto-fills with an enum + * No custom signals because Q_OBJECT macro doesn't support templates + */ +template +class TEnumComboBox : public QComboBox +{ + /** Vector forming an index -> enum mapping */ + QVector mValueList; + +public: + /** Constructor */ + explicit TEnumComboBox(QWidget* pParent = 0) + : QComboBox(pParent) + { + for (TEnumReflection::CIterator It; It; ++It) + { + if (It.Value() != TEnumReflection::ErrorValue()) + { + addItem( It.Name() ); + mValueList << It.Value(); + } + } + } + + EnumT currentEnum() const + { + return mValueList[ currentIndex() ]; + } +}; + +#endif // TENUMCOMBOBOX_H diff --git a/src/Editor/WorldEditor/CWorldEditor.h b/src/Editor/WorldEditor/CWorldEditor.h index bb7b221d..8cb01b11 100644 --- a/src/Editor/WorldEditor/CWorldEditor.h +++ b/src/Editor/WorldEditor/CWorldEditor.h @@ -91,6 +91,7 @@ public: inline CGameArea* ActiveArea() const { return mpArea; } inline EGame CurrentGame() const { return gpEdApp->CurrentGame(); } inline CLinkDialog* LinkDialog() const { return mpLinkDialog; } + inline CGeneratePropertyNamesDialog* NameGeneratorDialog() const { return mpGeneratePropertyNamesDialog; } CResourceBrowser* ResourceBrowser() const; CSceneViewport* Viewport() const; diff --git a/src/Editor/WorldEditor/WCreateTab.ui b/src/Editor/WorldEditor/WCreateTab.ui index 20b7698e..8d9b906c 100644 --- a/src/Editor/WorldEditor/WCreateTab.ui +++ b/src/Editor/WorldEditor/WCreateTab.ui @@ -61,6 +61,9 @@ Qt::MoveAction + + true + QAbstractItemView::SelectItems diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 34d052d7..88410435 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -74,13 +74,6 @@ public: gpEditorStore->ConditionalSaveStore(); } - for (int i = 0; i < (int) EGame::Max; i++) - { - CGameTemplate* pGame = NGameList::GetGameTemplate( (EGame) i ); - if (pGame) pGame->Save(); - } - return 0; - // Execute application App.InitEditor(); return App.exec();