Added support for enum combo boxes, and added casing combo box and property ID pools to the property name generator
This commit is contained in:
parent
ef6759df4a
commit
1d724b69d9
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -83,7 +83,7 @@ bool VectorContains(std::vector<T>& Vector, const T& kElement)
|
|||
template<typename T>
|
||||
bool VectorAddUnique(std::vector<T>& Vector, const T& kElement)
|
||||
{
|
||||
if (!VectorContainsElement(Vector, kElement))
|
||||
if (!VectorContains(Vector, kElement))
|
||||
{
|
||||
Vector.push_back(kElement);
|
||||
return true;
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,21 @@
|
|||
#include "Core/IProgressNotifier.h"
|
||||
#include <Common/Common.h>
|
||||
|
||||
/** 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<TString> 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<SPropertyIdTypePair> 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<TString> mTypeNames;
|
||||
|
||||
/** Mapping of valid ID/type pairs; if empty, all property names in NPropertyMap are allowed */
|
||||
std::unordered_map<u32, const char*> 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
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
#define CGENERATEPROPERTYNAMESDIALOG_H
|
||||
|
||||
#include "CProgressBarNotifier.h"
|
||||
#include "Editor/Widgets/TEnumComboBox.h"
|
||||
#include <Core/Resource/Script/Property/CPropertyNameGenerator.h>
|
||||
#include <Core/Resource/Script/Property/IProperty.h>
|
||||
#include <Core/Resource/Script/Property/CEnumProperty.h>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QFuture>
|
||||
|
@ -11,6 +14,8 @@
|
|||
#include <QTimer>
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
using CNameCasingComboBox = TEnumComboBox<ENameCasing>;
|
||||
|
||||
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<SPropertyIdTypePair> mIdPairs;
|
||||
|
||||
/** Future/future watcher for name generation task */
|
||||
QFuture<void> mFuture;
|
||||
QFutureWatcher<void> 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();
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="1,3">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="SettingsGroupBox">
|
||||
<property name="sizePolicy">
|
||||
|
@ -66,15 +66,18 @@
|
|||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="SuffixLineEdit"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Casing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="CNameCasingComboBox" name="CasingComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="UseUnderscoresCheckBox">
|
||||
<property name="text">
|
||||
<string>Use underscores</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LogOutputCheckBox">
|
||||
<property name="text">
|
||||
|
@ -232,6 +235,46 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="IdPoolGroupBox">
|
||||
<property name="title">
|
||||
<string>IDs</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QListWidget" name="IdPoolList">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ClearIdPoolButton">
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -382,6 +425,11 @@
|
|||
<extends>QTreeWidget</extends>
|
||||
<header>Editor/Widgets/CCheckableTreeWidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>CNameCasingComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>Editor/CGeneratePropertyNamesDialog.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="Icons.qrc"/>
|
||||
|
|
|
@ -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 += \
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef TENUMCOMBOBOX_H
|
||||
#define TENUMCOMBOBOX_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <codegen/EnumReflection.h>
|
||||
|
||||
/**
|
||||
* Combo box subclass that auto-fills with an enum
|
||||
* No custom signals because Q_OBJECT macro doesn't support templates
|
||||
*/
|
||||
template<typename EnumT>
|
||||
class TEnumComboBox : public QComboBox
|
||||
{
|
||||
/** Vector forming an index -> enum mapping */
|
||||
QVector<EnumT> mValueList;
|
||||
|
||||
public:
|
||||
/** Constructor */
|
||||
explicit TEnumComboBox(QWidget* pParent = 0)
|
||||
: QComboBox(pParent)
|
||||
{
|
||||
for (TEnumReflection<EnumT>::CIterator It; It; ++It)
|
||||
{
|
||||
if (It.Value() != TEnumReflection<EnumT>::ErrorValue())
|
||||
{
|
||||
addItem( It.Name() );
|
||||
mValueList << It.Value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EnumT currentEnum() const
|
||||
{
|
||||
return mValueList[ currentIndex() ];
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TENUMCOMBOBOX_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;
|
||||
|
||||
|
|
|
@ -61,6 +61,9 @@
|
|||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue