Added property name generation system using dictionary attacks and added a UI dialog that allows you to search for property names and apply them to templates
This commit is contained in:
parent
ebab154a38
commit
3d72c9e4b2
File diff suppressed because it is too large
Load Diff
|
@ -231,7 +231,8 @@ HEADERS += \
|
||||||
IProgressNotifier.h \
|
IProgressNotifier.h \
|
||||||
IUIRelay.h \
|
IUIRelay.h \
|
||||||
Resource/CResTypeFilter.h \
|
Resource/CResTypeFilter.h \
|
||||||
GameProject/COpeningBanner.h
|
GameProject/COpeningBanner.h \
|
||||||
|
Resource/Script/CPropertyNameGenerator.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
@ -340,4 +341,5 @@ SOURCES += \
|
||||||
CompressionUtil.cpp \
|
CompressionUtil.cpp \
|
||||||
IUIRelay.cpp \
|
IUIRelay.cpp \
|
||||||
GameProject\COpeningBanner.cpp \
|
GameProject\COpeningBanner.cpp \
|
||||||
IProgressNotifier.cpp
|
IProgressNotifier.cpp \
|
||||||
|
Resource/Script/CPropertyNameGenerator.cpp
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
mTaskCount = Math::Max(mTaskCount, TaskIndex + 1);
|
mTaskCount = Math::Max(mTaskCount, TaskIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Report(int StepIndex, int StepCount, const TString& rkStepDesc)
|
void Report(int StepIndex, int StepCount, const TString& rkStepDesc = "")
|
||||||
{
|
{
|
||||||
ASSERT(mTaskCount >= 1);
|
ASSERT(mTaskCount >= 1);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
class IUIRelay
|
class IUIRelay
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual void AsyncMessageBox(const TString& rkInfoBoxTitle, const TString& rkMessage) = 0;
|
||||||
virtual bool AskYesNoQuestion(const TString& rkInfoBoxTitle, const TString& rkQuestion) = 0;
|
virtual bool AskYesNoQuestion(const TString& rkInfoBoxTitle, const TString& rkQuestion) = 0;
|
||||||
};
|
};
|
||||||
extern IUIRelay *gpUIRelay;
|
extern IUIRelay *gpUIRelay;
|
||||||
|
|
|
@ -223,7 +223,11 @@ void CMasterTemplate::RenameProperty(IPropertyTemplate *pTemp, const TString& rk
|
||||||
{
|
{
|
||||||
u32 ID = pTemp->PropertyID();
|
u32 ID = pTemp->PropertyID();
|
||||||
if (ID <= 0xFF) ID = CreatePropertyID(pTemp);
|
if (ID <= 0xFF) ID = CreatePropertyID(pTemp);
|
||||||
|
RenameProperty(ID, rkNewName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMasterTemplate::RenameProperty(u32 ID, const TString& rkNewName)
|
||||||
|
{
|
||||||
// Master name list
|
// Master name list
|
||||||
auto NameIt = smPropertyNames.find(ID);
|
auto NameIt = smPropertyNames.find(ID);
|
||||||
TString Original;
|
TString Original;
|
||||||
|
@ -249,17 +253,15 @@ void CMasterTemplate::RenameProperty(IPropertyTemplate *pTemp, const TString& rk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TString> CMasterTemplate::XMLsUsingID(u32 ID)
|
void CMasterTemplate::XMLsUsingID(u32 ID, std::vector<TString>& rOutList)
|
||||||
{
|
{
|
||||||
auto InfoIt = smIDMap.find(ID);
|
auto InfoIt = smIDMap.find(ID);
|
||||||
|
|
||||||
if (InfoIt != smIDMap.end())
|
if (InfoIt != smIDMap.end())
|
||||||
{
|
{
|
||||||
const SPropIDInfo& rkInfo = InfoIt->second;
|
const SPropIDInfo& rkInfo = InfoIt->second;
|
||||||
return rkInfo.XMLList;
|
rOutList = rkInfo.XMLList;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return std::vector<TString>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<IPropertyTemplate*>* CMasterTemplate::TemplatesWithMatchingID(IPropertyTemplate *pTemp)
|
const std::vector<IPropertyTemplate*>* CMasterTemplate::TemplatesWithMatchingID(IPropertyTemplate *pTemp)
|
||||||
|
|
|
@ -69,7 +69,8 @@ public:
|
||||||
static u32 CreatePropertyID(IPropertyTemplate *pTemp);
|
static u32 CreatePropertyID(IPropertyTemplate *pTemp);
|
||||||
static void AddProperty(IPropertyTemplate *pTemp, const TString& rkTemplateName = "");
|
static void AddProperty(IPropertyTemplate *pTemp, const TString& rkTemplateName = "");
|
||||||
static void RenameProperty(IPropertyTemplate *pTemp, const TString& rkNewName);
|
static void RenameProperty(IPropertyTemplate *pTemp, const TString& rkNewName);
|
||||||
static std::vector<TString> XMLsUsingID(u32 ID);
|
static void RenameProperty(u32 ID, const TString& rkNewName);
|
||||||
|
static void XMLsUsingID(u32 ID, std::vector<TString>& rOutList);
|
||||||
static const std::vector<IPropertyTemplate*>* TemplatesWithMatchingID(IPropertyTemplate *pTemp);
|
static const std::vector<IPropertyTemplate*>* TemplatesWithMatchingID(IPropertyTemplate *pTemp);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
#include "CPropertyNameGenerator.h"
|
||||||
|
#include "IUIRelay.h"
|
||||||
|
#include "Core/Resource/Factory/CTemplateLoader.h"
|
||||||
|
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||||
|
#include <Common/Hash/CCRC32.h>
|
||||||
|
|
||||||
|
/** Default constructor */
|
||||||
|
CPropertyNameGenerator::CPropertyNameGenerator()
|
||||||
|
: mWordListLoadStarted(false)
|
||||||
|
, mWordListLoadFinished(false)
|
||||||
|
, mIsRunning(false)
|
||||||
|
, mFinishedRunning(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPropertyNameGenerator::Warmup()
|
||||||
|
{
|
||||||
|
// Clear output from previous runs
|
||||||
|
ASSERT(!mWordListLoadStarted || mWordListLoadFinished);
|
||||||
|
mWordListLoadFinished = false;
|
||||||
|
mWordListLoadStarted = true;
|
||||||
|
mWords.clear();
|
||||||
|
|
||||||
|
// Load the word list from the file
|
||||||
|
FILE* pListFile = fopen("../resources/WordList.txt", "r");
|
||||||
|
ASSERT(pListFile);
|
||||||
|
|
||||||
|
while (!feof(pListFile))
|
||||||
|
{
|
||||||
|
char WordBuffer[256];
|
||||||
|
fgets(&WordBuffer[0], 256, pListFile);
|
||||||
|
|
||||||
|
// Capitalize first letter
|
||||||
|
if (WordBuffer[0] >= 'a' && WordBuffer[0] <= 'z')
|
||||||
|
{
|
||||||
|
WordBuffer[0] -= 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWord Word;
|
||||||
|
Word.Word = TString(WordBuffer).Trimmed();
|
||||||
|
Word.Usages = 0;
|
||||||
|
mWords.push_back(Word);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(pListFile);
|
||||||
|
mWordListLoadFinished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& rkParams, IProgressNotifier* pProgress)
|
||||||
|
{
|
||||||
|
// Make sure all prerequisite data is loaded!
|
||||||
|
ASSERT(!mIsRunning);
|
||||||
|
ASSERT(rkParams.TypeNames.size() > 0);
|
||||||
|
mGeneratedNames.clear();
|
||||||
|
mIsRunning = true;
|
||||||
|
mFinishedRunning = false;
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
if (mWordListLoadStarted)
|
||||||
|
while (!mWordListLoadFinished) {}
|
||||||
|
else
|
||||||
|
Warmup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the number of steps involved in this task.
|
||||||
|
const int kNumWords = mWords.size();
|
||||||
|
const int kMaxWords = rkParams.MaxWords;
|
||||||
|
int TestsDone = 0;
|
||||||
|
int TotalTests = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < kMaxWords; i++)
|
||||||
|
TotalTests *= kNumWords;
|
||||||
|
|
||||||
|
pProgress->SetOneShotTask("Generating property names");
|
||||||
|
pProgress->Report(TestsDone, TotalTests);
|
||||||
|
|
||||||
|
// Configure params needed to run the name generation!
|
||||||
|
bool WriteToLog = rkParams.PrintToLog;
|
||||||
|
bool SaveResults = true;
|
||||||
|
|
||||||
|
// The prefix only needs to be hashed this one time
|
||||||
|
CCRC32 PrefixHash;
|
||||||
|
PrefixHash.Hash( *rkParams.Prefix );
|
||||||
|
|
||||||
|
// Use a stack to keep track of the current word we are on. We can use this
|
||||||
|
// to cache the hash of a word and then re-use it later instead of recaculating
|
||||||
|
// the same hashes over and over. Init the stack with the first word.
|
||||||
|
struct SWordCache
|
||||||
|
{
|
||||||
|
int WordIndex;
|
||||||
|
CCRC32 Hash;
|
||||||
|
};
|
||||||
|
std::vector<SWordCache> WordCache;
|
||||||
|
|
||||||
|
SWordCache FirstWord { -1, CCRC32() };
|
||||||
|
WordCache.push_back(FirstWord);
|
||||||
|
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
// Increment the current word, handle wrapping back to 0, and update cached hashes as needed.
|
||||||
|
int RecalcIndex = WordCache.size() - 1;
|
||||||
|
WordCache.back().WordIndex++;
|
||||||
|
|
||||||
|
while (WordCache[RecalcIndex].WordIndex >= kNumWords)
|
||||||
|
{
|
||||||
|
WordCache[RecalcIndex].WordIndex = 0;
|
||||||
|
|
||||||
|
if (RecalcIndex > 0)
|
||||||
|
{
|
||||||
|
RecalcIndex--;
|
||||||
|
WordCache[RecalcIndex].WordIndex++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SWordCache NewWord { 0, CCRC32() };
|
||||||
|
WordCache.push_back(NewWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've hit the word limit, break out and end the name generation system.
|
||||||
|
if (WordCache.size() > kMaxWords)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Now that all words are updated, calculate the new hashes.
|
||||||
|
CCRC32 LastValidHash = (RecalcIndex > 0 ? WordCache[RecalcIndex-1].Hash : PrefixHash);
|
||||||
|
|
||||||
|
for (; RecalcIndex < WordCache.size(); RecalcIndex++)
|
||||||
|
{
|
||||||
|
int Index = WordCache[RecalcIndex].WordIndex;
|
||||||
|
LastValidHash.Hash( *mWords[Index].Word );
|
||||||
|
WordCache[RecalcIndex].Hash = LastValidHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We got our hash yay! Now hash the suffix and then we can test with each type name
|
||||||
|
CCRC32 BaseHash = LastValidHash;
|
||||||
|
BaseHash.Hash( *rkParams.Suffix );
|
||||||
|
|
||||||
|
for (int TypeIdx = 0; TypeIdx < rkParams.TypeNames.size(); TypeIdx++)
|
||||||
|
{
|
||||||
|
CCRC32 FullHash = BaseHash;
|
||||||
|
FullHash.Hash( *rkParams.TypeNames[TypeIdx] );
|
||||||
|
u32 PropertyID = FullHash.Digest();
|
||||||
|
|
||||||
|
// Check if this hash is a property ID - it's valid if there are any XMLs using this ID
|
||||||
|
SGeneratedPropertyName PropertyName;
|
||||||
|
CMasterTemplate::XMLsUsingID(PropertyID, PropertyName.XmlList);
|
||||||
|
|
||||||
|
if (PropertyName.XmlList.size() > 0)
|
||||||
|
{
|
||||||
|
// Generate a string with the complete name. (We wait to do this until now to avoid needless string allocation)
|
||||||
|
PropertyName.Name = rkParams.Prefix;
|
||||||
|
|
||||||
|
for (int WordIdx = 0; WordIdx < WordCache.size(); WordIdx++)
|
||||||
|
{
|
||||||
|
int Index = WordCache[WordIdx].WordIndex;
|
||||||
|
PropertyName.Name += mWords[Index].Word;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyName.Name += rkParams.Suffix;
|
||||||
|
PropertyName.Type = rkParams.TypeNames[TypeIdx];
|
||||||
|
PropertyName.ID = PropertyID;
|
||||||
|
|
||||||
|
if (SaveResults)
|
||||||
|
{
|
||||||
|
mGeneratedNames.push_back(PropertyName);
|
||||||
|
|
||||||
|
// Check if we have too many saved results. This can cause memory issues and crashing.
|
||||||
|
// 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.");
|
||||||
|
WriteToLog = true;
|
||||||
|
SaveResults = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log this out
|
||||||
|
if ( WriteToLog )
|
||||||
|
{
|
||||||
|
TString DelimitedXmlList;
|
||||||
|
|
||||||
|
for (int XmlIdx = 0; XmlIdx < PropertyName.XmlList.size(); XmlIdx++)
|
||||||
|
{
|
||||||
|
DelimitedXmlList += PropertyName.XmlList[XmlIdx] + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
TString LogMsg = TString::Format("%s [%s] : 0x%08X\n", *PropertyName.Name, *PropertyName.Type, PropertyName.ID) + DelimitedXmlList;
|
||||||
|
Log::Write(LogMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every 250 tests, check with the progress notifier. Update the progress
|
||||||
|
// bar and check whether the user has requested to cancel the operation.
|
||||||
|
TestsDone++;
|
||||||
|
|
||||||
|
if ( (TestsDone % 250) == 0 )
|
||||||
|
{
|
||||||
|
if (pProgress->ShouldCancel())
|
||||||
|
break;
|
||||||
|
|
||||||
|
pProgress->Report(TestsDone, TotalTests);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsRunning = false;
|
||||||
|
mFinishedRunning = true;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
#ifndef CPROPERTYNAMEGENERATOR_H
|
||||||
|
#define CPROPERTYNAMEGENERATOR_H
|
||||||
|
|
||||||
|
#include "Core/IProgressNotifier.h"
|
||||||
|
#include <Common/Common.h>
|
||||||
|
|
||||||
|
/** Parameters for using the name generator */
|
||||||
|
struct SPropertyNameGenerationParameters
|
||||||
|
{
|
||||||
|
/** Maximum number of words per name; name generation will complete when all possibilities have been checked */
|
||||||
|
int MaxWords;
|
||||||
|
|
||||||
|
/** Prefix to include at the beginning of every name */
|
||||||
|
TString Prefix;
|
||||||
|
|
||||||
|
/** Suffix to include at the end of every name */
|
||||||
|
TString Suffix;
|
||||||
|
|
||||||
|
/** List of valid type suffixes */
|
||||||
|
std::vector<TString> TypeNames;
|
||||||
|
|
||||||
|
/** Whether to print the output from the generation process to the log */
|
||||||
|
bool PrintToLog;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A generated property name */
|
||||||
|
struct SGeneratedPropertyName
|
||||||
|
{
|
||||||
|
TString Name;
|
||||||
|
TString Type;
|
||||||
|
u32 ID;
|
||||||
|
std::vector<TString> XmlList;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Generates property names and validates them against know property IDs. */
|
||||||
|
class CPropertyNameGenerator
|
||||||
|
{
|
||||||
|
/** Whether we have started loading the word list */
|
||||||
|
bool mWordListLoadStarted;
|
||||||
|
|
||||||
|
/** Whether the word list has been fully loaded */
|
||||||
|
bool mWordListLoadFinished;
|
||||||
|
|
||||||
|
/** Whether the generation process is running */
|
||||||
|
bool mIsRunning;
|
||||||
|
|
||||||
|
/** Whether the generation process finished running */
|
||||||
|
bool mFinishedRunning;
|
||||||
|
|
||||||
|
/** List of words */
|
||||||
|
struct SWord
|
||||||
|
{
|
||||||
|
TString Word;
|
||||||
|
int Usages;
|
||||||
|
};
|
||||||
|
std::vector<SWord> mWords;
|
||||||
|
|
||||||
|
/** List of output generated property names */
|
||||||
|
std::list<SGeneratedPropertyName> mGeneratedNames;
|
||||||
|
|
||||||
|
/** List of word indices */
|
||||||
|
std::vector<int> mWordIndices;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Default constructor */
|
||||||
|
CPropertyNameGenerator();
|
||||||
|
|
||||||
|
/** Prepares the generator for running name generation */
|
||||||
|
void Warmup();
|
||||||
|
|
||||||
|
/** Run the name generation system */
|
||||||
|
void Generate(const SPropertyNameGenerationParameters& rkParams, IProgressNotifier* pProgressNotifier);
|
||||||
|
|
||||||
|
/** Accessors */
|
||||||
|
bool IsRunning() const
|
||||||
|
{
|
||||||
|
return mIsRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::list<SGeneratedPropertyName>& GetOutput() const
|
||||||
|
{
|
||||||
|
return mGeneratedNames;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CPROPERTYNAMEGENERATOR_H
|
|
@ -315,10 +315,10 @@ const char* HashablePropTypeName(EPropertyType Prop)
|
||||||
case eFloatProperty: return "float";
|
case eFloatProperty: return "float";
|
||||||
case eStringProperty: return "string";
|
case eStringProperty: return "string";
|
||||||
case eColorProperty: return "Color";
|
case eColorProperty: return "Color";
|
||||||
case eVector3Property: return "Vector3f";
|
case eVector3Property: return "Vector";
|
||||||
case eSoundProperty: return "SfxId";
|
case eSoundProperty: return "sound";
|
||||||
case eAssetProperty: return "asset";
|
case eAssetProperty: return "asset";
|
||||||
case eMayaSplineProperty: return "MayaSpline";
|
case eMayaSplineProperty: return "spline";
|
||||||
|
|
||||||
// All other types are either invalid or need a custom reimplementation because they can return multiple strings (like struct)
|
// All other types are either invalid or need a custom reimplementation because they can return multiple strings (like struct)
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -338,7 +338,7 @@ public:
|
||||||
|
|
||||||
const char* GetTypeNameString() const
|
const char* GetTypeNameString() const
|
||||||
{
|
{
|
||||||
return (Game() < eCorruptionProto ? "AnimationParameters" : "CharacterAnimationSet");
|
return (Game() < eCorruptionProto ? "AnimationSet" : "CharacterAnimationSet");
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLEMENT_TEMPLATE_CLONE(TCharacterTemplate)
|
IMPLEMENT_TEMPLATE_CLONE(TCharacterTemplate)
|
||||||
|
|
|
@ -0,0 +1,307 @@
|
||||||
|
#include "CGeneratePropertyNamesDialog.h"
|
||||||
|
#include "ui_CGeneratePropertyNamesDialog.h"
|
||||||
|
|
||||||
|
#include "Editor/Widgets/CCheckableTreeWidgetItem.h"
|
||||||
|
#include "UICommon.h"
|
||||||
|
#include <Core/Resource/Cooker/CTemplateWriter.h>
|
||||||
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
CGeneratePropertyNamesDialog::CGeneratePropertyNamesDialog(QWidget* pParent)
|
||||||
|
: QDialog(pParent)
|
||||||
|
, mpUI( new Ui::CGeneratePropertyNamesDialog )
|
||||||
|
, mFutureWatcher( this )
|
||||||
|
, mRunningNameGeneration( false )
|
||||||
|
, mCanceledNameGeneration( false )
|
||||||
|
{
|
||||||
|
mpUI->setupUi(this);
|
||||||
|
mNotifier.SetProgressBar( mpUI->ProgressBar );
|
||||||
|
|
||||||
|
connect( mpUI->AddSuffixButton, SIGNAL(pressed()), this, SLOT(AddSuffix()) );
|
||||||
|
connect( mpUI->RemoveSuffixButton, SIGNAL(pressed()), this, SLOT(DeleteSuffix()) );
|
||||||
|
connect( mpUI->StartButton, SIGNAL(pressed()), this, SLOT(StartGeneration()) );
|
||||||
|
connect( mpUI->CancelButton, SIGNAL(pressed()), this, SLOT(CancelGeneration()) );
|
||||||
|
connect( mpUI->CheckAllButton, SIGNAL(pressed()), this, SLOT(CheckAll()) );
|
||||||
|
connect( mpUI->UncheckAllButton, SIGNAL(pressed()), this, SLOT(UncheckAll()) );
|
||||||
|
connect( mpUI->ApplyButton, SIGNAL(pressed()), this, SLOT(ApplyChanges()) );
|
||||||
|
connect( mpUI->OutputTreeWidget, SIGNAL(CheckStateChanged(QTreeWidgetItem*)),
|
||||||
|
this, SLOT(OnTreeItemChecked(QTreeWidgetItem*)) );
|
||||||
|
connect( mpUI->OutputTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
|
||||||
|
this, SLOT(OnTreeItemDoubleClicked(QTreeWidgetItem*)) );
|
||||||
|
|
||||||
|
// Configure default tree view split sizes
|
||||||
|
// I don't know why it needs to be multiplied by 1.5, it just does
|
||||||
|
int TreeWidth = mpUI->OutputTreeWidget->width();
|
||||||
|
mpUI->OutputTreeWidget->setColumnWidth(0, TreeWidth * 1.5);
|
||||||
|
mpUI->OutputTreeWidget->setHeaderHidden(false);
|
||||||
|
|
||||||
|
// Allow the generator to initialize in the background while the user is getting set up
|
||||||
|
QtConcurrent::run(&mGenerator, &CPropertyNameGenerator::Warmup);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGeneratePropertyNamesDialog::~CGeneratePropertyNamesDialog()
|
||||||
|
{
|
||||||
|
delete mpUI;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Close event override */
|
||||||
|
void CGeneratePropertyNamesDialog::closeEvent(QCloseEvent*)
|
||||||
|
{
|
||||||
|
if (mRunningNameGeneration)
|
||||||
|
{
|
||||||
|
CancelGeneration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add an item to the suffix list */
|
||||||
|
void CGeneratePropertyNamesDialog::AddSuffix()
|
||||||
|
{
|
||||||
|
QListWidgetItem* pNewItem = new QListWidgetItem("New Suffix", mpUI->TypeSuffixesListWidget);
|
||||||
|
pNewItem->setFlags( Qt::ItemIsEditable |
|
||||||
|
Qt::ItemIsEnabled |
|
||||||
|
Qt::ItemIsSelectable );
|
||||||
|
mpUI->TypeSuffixesListWidget->setCurrentItem(pNewItem, QItemSelectionModel::ClearAndSelect);
|
||||||
|
mpUI->TypeSuffixesListWidget->editItem(pNewItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Deletes an item from the suffix list */
|
||||||
|
void CGeneratePropertyNamesDialog::DeleteSuffix()
|
||||||
|
{
|
||||||
|
if (mpUI->TypeSuffixesListWidget->selectedItems().size() > 0)
|
||||||
|
{
|
||||||
|
int Row = mpUI->TypeSuffixesListWidget->currentRow();
|
||||||
|
delete mpUI->TypeSuffixesListWidget->takeItem(Row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Start name generation */
|
||||||
|
void CGeneratePropertyNamesDialog::StartGeneration()
|
||||||
|
{
|
||||||
|
ASSERT(!mRunningNameGeneration);
|
||||||
|
mRunningNameGeneration = true;
|
||||||
|
mCanceledNameGeneration = false;
|
||||||
|
mTaskOutput.clear();
|
||||||
|
mCheckedItems.clear();
|
||||||
|
mpUI->OutputTreeWidget->clear();
|
||||||
|
|
||||||
|
// Configure the generator
|
||||||
|
SPropertyNameGenerationParameters Params;
|
||||||
|
|
||||||
|
for (int RowIdx = 0; RowIdx < mpUI->TypeSuffixesListWidget->count(); RowIdx++)
|
||||||
|
{
|
||||||
|
QString ItemText = mpUI->TypeSuffixesListWidget->item(RowIdx)->text();
|
||||||
|
Params.TypeNames.push_back( TO_TSTRING(ItemText) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Params.MaxWords = mpUI->NumWordsSpinBox->value();
|
||||||
|
Params.Prefix = TO_TSTRING( mpUI->PrefixLineEdit->text() );
|
||||||
|
Params.Suffix = TO_TSTRING( mpUI->SuffixLineEdit->text() );
|
||||||
|
Params.PrintToLog = mpUI->LogOutputCheckBox->isChecked();
|
||||||
|
|
||||||
|
// Run the task and configure ourselves so we can update correctly
|
||||||
|
connect( &mFutureWatcher, SIGNAL(finished()), this, SLOT(GenerationComplete()) );
|
||||||
|
mFuture = QtConcurrent::run(&mGenerator, &CPropertyNameGenerator::Generate, Params, &mNotifier);
|
||||||
|
mFutureWatcher.setFuture(mFuture);
|
||||||
|
|
||||||
|
mUpdateTimer.start(500);
|
||||||
|
connect( &mUpdateTimer, SIGNAL(timeout()), this, SLOT(CheckForNewResults()) );
|
||||||
|
|
||||||
|
UpdateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Cancel name generation */
|
||||||
|
void CGeneratePropertyNamesDialog::CancelGeneration()
|
||||||
|
{
|
||||||
|
mNotifier.SetCanceled(true);
|
||||||
|
mCanceledNameGeneration = true;
|
||||||
|
UpdateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when name generation is complete */
|
||||||
|
void CGeneratePropertyNamesDialog::GenerationComplete()
|
||||||
|
{
|
||||||
|
mRunningNameGeneration = false;
|
||||||
|
mCanceledNameGeneration = false;
|
||||||
|
mNotifier.SetCanceled(false);
|
||||||
|
mUpdateTimer.stop();
|
||||||
|
|
||||||
|
mTaskOutput = QList<SGeneratedPropertyName>::fromStdList(
|
||||||
|
mGenerator.GetOutput()
|
||||||
|
);
|
||||||
|
|
||||||
|
mpUI->ProgressBar->setValue( mpUI->ProgressBar->maximum() );
|
||||||
|
|
||||||
|
disconnect( &mFutureWatcher, 0, this, 0 );
|
||||||
|
disconnect( &mUpdateTimer, 0, this, 0 );
|
||||||
|
UpdateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when an item in the output tree has been checked or unchecked */
|
||||||
|
void CGeneratePropertyNamesDialog::OnTreeItemChecked(QTreeWidgetItem* pItem)
|
||||||
|
{
|
||||||
|
if (pItem->checkState(0) == Qt::Checked)
|
||||||
|
mCheckedItems.append(pItem);
|
||||||
|
else
|
||||||
|
mCheckedItems.removeOne(pItem);
|
||||||
|
|
||||||
|
UpdateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when an item in the output tree has been double clicked */
|
||||||
|
void CGeneratePropertyNamesDialog::OnTreeItemDoubleClicked(QTreeWidgetItem* pItem)
|
||||||
|
{
|
||||||
|
// Check whether this is an XML path
|
||||||
|
if (pItem->parent() != nullptr)
|
||||||
|
{
|
||||||
|
QString Text = pItem->text(0);
|
||||||
|
|
||||||
|
if (Text.endsWith(".xml"))
|
||||||
|
{
|
||||||
|
TString TStrText = TO_TSTRING(Text);
|
||||||
|
TString DirPath = "../templates/" + TStrText.GetFileDirectory();
|
||||||
|
TString AbsPath = FileUtil::MakeAbsolute(DirPath) + TStrText.GetFileName();
|
||||||
|
UICommon::OpenInExternalApplication( TO_QSTRING(AbsPath) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check all items in the output tree */
|
||||||
|
void CGeneratePropertyNamesDialog::CheckAll()
|
||||||
|
{
|
||||||
|
mpUI->OutputTreeWidget->blockSignals(true);
|
||||||
|
mCheckedItems.clear();
|
||||||
|
mCheckedItems.reserve( mpUI->OutputTreeWidget->topLevelItemCount() );
|
||||||
|
|
||||||
|
for (int RowIdx = 0; RowIdx < mpUI->OutputTreeWidget->topLevelItemCount(); RowIdx++)
|
||||||
|
{
|
||||||
|
QTreeWidgetItem* pItem = mpUI->OutputTreeWidget->topLevelItem(RowIdx);
|
||||||
|
pItem->setCheckState( 0, Qt::Checked );
|
||||||
|
mCheckedItems << pItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpUI->OutputTreeWidget->blockSignals(false);
|
||||||
|
UpdateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Uncheck all items in the output tree */
|
||||||
|
void CGeneratePropertyNamesDialog::UncheckAll()
|
||||||
|
{
|
||||||
|
mpUI->OutputGroupBox->blockSignals(true);
|
||||||
|
|
||||||
|
for (int RowIdx = 0; RowIdx < mpUI->OutputTreeWidget->topLevelItemCount(); RowIdx++)
|
||||||
|
{
|
||||||
|
QTreeWidgetItem* pItem = mpUI->OutputTreeWidget->topLevelItem(RowIdx);
|
||||||
|
pItem->setCheckState( 0, Qt::Unchecked );
|
||||||
|
}
|
||||||
|
|
||||||
|
mCheckedItems.clear();
|
||||||
|
mpUI->OutputTreeWidget->blockSignals(false);
|
||||||
|
UpdateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Apply generated names on selected items */
|
||||||
|
void CGeneratePropertyNamesDialog::ApplyChanges()
|
||||||
|
{
|
||||||
|
// make sure the user really wants to do this
|
||||||
|
QString WarningText =
|
||||||
|
QString("Are you sure you want to rename %1 %2? This operation cannot be undone.")
|
||||||
|
.arg(mCheckedItems.size())
|
||||||
|
.arg(mCheckedItems.size() == 1 ? "property" : "properties");
|
||||||
|
|
||||||
|
bool ReallyRename = UICommon::YesNoQuestion(this, "Warning", WarningText);
|
||||||
|
|
||||||
|
if (!ReallyRename)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform rename operation
|
||||||
|
for (int ItemIdx = 0; ItemIdx < mCheckedItems.size(); ItemIdx++)
|
||||||
|
{
|
||||||
|
QTreeWidgetItem* pItem = mCheckedItems[ItemIdx];
|
||||||
|
u32 ID = TO_TSTRING( pItem->text(2) ).ToInt32();
|
||||||
|
|
||||||
|
QString NewName = pItem->text(0);
|
||||||
|
CMasterTemplate::RenameProperty( ID, TO_TSTRING(NewName) );
|
||||||
|
pItem->setText(3, NewName);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTemplateWriter::SavePropertyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check progress on name generation task and display results on the UI */
|
||||||
|
void CGeneratePropertyNamesDialog::CheckForNewResults()
|
||||||
|
{
|
||||||
|
const std::list<SGeneratedPropertyName>& rkOutput = mGenerator.GetOutput();
|
||||||
|
|
||||||
|
QTreeWidget* pTreeWidget = mpUI->OutputTreeWidget;
|
||||||
|
int CurItemCount = pTreeWidget->topLevelItemCount();
|
||||||
|
|
||||||
|
// Add new items to the tree
|
||||||
|
if (rkOutput.size() > CurItemCount)
|
||||||
|
{
|
||||||
|
std::list<SGeneratedPropertyName>::const_iterator Iter = rkOutput.cbegin();
|
||||||
|
std::list<SGeneratedPropertyName>::const_iterator End = rkOutput.cend();
|
||||||
|
std::advance(Iter, CurItemCount);
|
||||||
|
|
||||||
|
for (; Iter != End; Iter++)
|
||||||
|
{
|
||||||
|
const SGeneratedPropertyName& rkName = *Iter;
|
||||||
|
|
||||||
|
// Add an item to the tree for this name
|
||||||
|
QStringList ColumnText;
|
||||||
|
ColumnText << TO_QSTRING( rkName.Name )
|
||||||
|
<< TO_QSTRING( rkName.Type )
|
||||||
|
<< TO_QSTRING( TString::HexString(rkName.ID) )
|
||||||
|
<< TO_QSTRING( CMasterTemplate::PropertyName(rkName.ID) );
|
||||||
|
|
||||||
|
QTreeWidgetItem* pItem = new CCheckableTreeWidgetItem(pTreeWidget, ColumnText);
|
||||||
|
pItem->setFlags(Qt::ItemIsEnabled |
|
||||||
|
Qt::ItemIsSelectable |
|
||||||
|
Qt::ItemIsUserCheckable);
|
||||||
|
pItem->setCheckState(0, Qt::Unchecked);
|
||||||
|
|
||||||
|
// Add children items
|
||||||
|
for (int XmlIdx = 0; XmlIdx < rkName.XmlList.size(); XmlIdx++)
|
||||||
|
{
|
||||||
|
QString XmlName = TO_QSTRING( rkName.XmlList[XmlIdx] );
|
||||||
|
ColumnText.clear();
|
||||||
|
ColumnText << XmlName;
|
||||||
|
|
||||||
|
QTreeWidgetItem* pChild = new QTreeWidgetItem(pItem, ColumnText);
|
||||||
|
pChild->setFlags(Qt::ItemIsEnabled);
|
||||||
|
pChild->setFirstColumnSpanned(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates the enabled status of various widgets */
|
||||||
|
void CGeneratePropertyNamesDialog::UpdateUI()
|
||||||
|
{
|
||||||
|
mpUI->TypeSuffixesGroupBox->setEnabled( !mRunningNameGeneration );
|
||||||
|
mpUI->SettingsGroupBox->setEnabled( !mRunningNameGeneration );
|
||||||
|
mpUI->StartButton->setEnabled( !mRunningNameGeneration );
|
||||||
|
mpUI->CancelButton->setEnabled( mRunningNameGeneration && !mCanceledNameGeneration );
|
||||||
|
|
||||||
|
int TotalItems = mpUI->OutputTreeWidget->topLevelItemCount();
|
||||||
|
bool HasResults = TotalItems > 0;
|
||||||
|
bool HasCheckedResults = HasResults && !mCheckedItems.isEmpty();
|
||||||
|
mpUI->CheckAllButton->setEnabled( HasResults );
|
||||||
|
mpUI->UncheckAllButton->setEnabled( HasResults );
|
||||||
|
mpUI->ApplyButton->setEnabled( !mRunningNameGeneration && HasCheckedResults );
|
||||||
|
|
||||||
|
// Update label
|
||||||
|
if (HasResults)
|
||||||
|
{
|
||||||
|
mpUI->NumSelectedLabel->setText(
|
||||||
|
QString("%1 names, %2 selected")
|
||||||
|
.arg(TotalItems)
|
||||||
|
.arg(mCheckedItems.size())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mpUI->NumSelectedLabel->clear();
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
#ifndef CGENERATEPROPERTYNAMESDIALOG_H
|
||||||
|
#define CGENERATEPROPERTYNAMESDIALOG_H
|
||||||
|
|
||||||
|
#include "CProgressBarNotifier.h"
|
||||||
|
#include <Core/Resource/Script/CPropertyNameGenerator.h>
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QFuture>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QTreeWidgetItem>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class CGeneratePropertyNamesDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog box for accessing property name generation functionality.
|
||||||
|
*/
|
||||||
|
class CGeneratePropertyNamesDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Ui::CGeneratePropertyNamesDialog* mpUI;
|
||||||
|
|
||||||
|
/** The name generator */
|
||||||
|
CPropertyNameGenerator mGenerator;
|
||||||
|
|
||||||
|
/** Progress notifier for updating the progress bar */
|
||||||
|
CProgressBarNotifier mNotifier;
|
||||||
|
|
||||||
|
/** Future/future watcher for name generation task */
|
||||||
|
QFuture<void> mFuture;
|
||||||
|
QFutureWatcher<void> mFutureWatcher;
|
||||||
|
|
||||||
|
/** Timer for fetching updates from name generation task */
|
||||||
|
QTimer mUpdateTimer;
|
||||||
|
|
||||||
|
/** Copy of the output buffer from the name generator; only set after completion */
|
||||||
|
QList<SGeneratedPropertyName> mTaskOutput;
|
||||||
|
|
||||||
|
/** Checked items in the output tree widget */
|
||||||
|
QVector<QTreeWidgetItem*> mCheckedItems;
|
||||||
|
|
||||||
|
/** Whether name generation is running */
|
||||||
|
bool mRunningNameGeneration;
|
||||||
|
|
||||||
|
/** Whether name generation has been canceled */
|
||||||
|
bool mCanceledNameGeneration;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CGeneratePropertyNamesDialog(QWidget *pParent = 0);
|
||||||
|
~CGeneratePropertyNamesDialog();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
/** Close event override */
|
||||||
|
virtual void closeEvent(QCloseEvent* pEvent);
|
||||||
|
|
||||||
|
/** Add an item to the suffix list */
|
||||||
|
void AddSuffix();
|
||||||
|
|
||||||
|
/** Deletes an item from the suffix list */
|
||||||
|
void DeleteSuffix();
|
||||||
|
|
||||||
|
/** Start name generation */
|
||||||
|
void StartGeneration();
|
||||||
|
|
||||||
|
/** Cancel name generation */
|
||||||
|
void CancelGeneration();
|
||||||
|
|
||||||
|
/** Called when name generation is complete */
|
||||||
|
void GenerationComplete();
|
||||||
|
|
||||||
|
/** Called when an item in the output tree has been checked or unchecked */
|
||||||
|
void OnTreeItemChecked(QTreeWidgetItem* pItem);
|
||||||
|
|
||||||
|
/** Called when an item in the output tree has been double clicked */
|
||||||
|
void OnTreeItemDoubleClicked(QTreeWidgetItem* pItem);
|
||||||
|
|
||||||
|
/** Check all items in the output tree */
|
||||||
|
void CheckAll();
|
||||||
|
|
||||||
|
/** Uncheck all items in the output tree */
|
||||||
|
void UncheckAll();
|
||||||
|
|
||||||
|
/** Apply generated names on selected items */
|
||||||
|
void ApplyChanges();
|
||||||
|
|
||||||
|
/** Check progress on name generation task and display results on the UI */
|
||||||
|
void CheckForNewResults();
|
||||||
|
|
||||||
|
/** Updates the enabled status of various widgets */
|
||||||
|
void UpdateUI();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CGENERATEPROPERTYNAMESDIALOG_H
|
|
@ -0,0 +1,383 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CGeneratePropertyNamesDialog</class>
|
||||||
|
<widget class="QDialog" name="CGeneratePropertyNamesDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>693</width>
|
||||||
|
<height>604</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Generate Property Names</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="1,3">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="SettingsGroupBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Settings</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="MaxWordsLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max words:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QSpinBox" name="NumWordsSpinBox">
|
||||||
|
<property name="value">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="PrefixLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Prefix:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="PrefixLineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="SuffixLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Suffix:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="SuffixLineEdit"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="LogOutputCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Print output to log</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="TypeSuffixesGroupBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Types</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="TypeSuffixesListWidget">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="verticalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>bool</string>
|
||||||
|
</property>
|
||||||
|
<property name="flags">
|
||||||
|
<set>ItemIsSelectable|ItemIsEditable|ItemIsEnabled</set>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>int</string>
|
||||||
|
</property>
|
||||||
|
<property name="flags">
|
||||||
|
<set>ItemIsSelectable|ItemIsEditable|ItemIsEnabled</set>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>float</string>
|
||||||
|
</property>
|
||||||
|
<property name="flags">
|
||||||
|
<set>ItemIsSelectable|ItemIsEditable|ItemIsEnabled</set>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>asset</string>
|
||||||
|
</property>
|
||||||
|
<property name="flags">
|
||||||
|
<set>ItemIsSelectable|ItemIsEditable|ItemIsEnabled</set>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>choice</string>
|
||||||
|
</property>
|
||||||
|
<property name="flags">
|
||||||
|
<set>ItemIsSelectable|ItemIsEditable|ItemIsEnabled</set>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>enum</string>
|
||||||
|
</property>
|
||||||
|
<property name="flags">
|
||||||
|
<set>ItemIsSelectable|ItemIsEditable|ItemIsEnabled</set>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>string</string>
|
||||||
|
</property>
|
||||||
|
<property name="flags">
|
||||||
|
<set>ItemIsSelectable|ItemIsEditable|ItemIsEnabled</set>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>sound</string>
|
||||||
|
</property>
|
||||||
|
<property name="flags">
|
||||||
|
<set>ItemIsSelectable|ItemIsEditable|ItemIsEnabled</set>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Color</string>
|
||||||
|
</property>
|
||||||
|
<property name="flags">
|
||||||
|
<set>ItemIsSelectable|ItemIsEditable|ItemIsEnabled</set>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<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="AddSuffixButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="Icons.qrc">
|
||||||
|
<normaloff>:/icons/Plus.png</normaloff>:/icons/Plus.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="RemoveSuffixButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="Icons.qrc">
|
||||||
|
<normaloff>:/icons/Minus v2.png</normaloff>:/icons/Minus v2.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="OutputGroupBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>3</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Output</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="CCheckableTreeWidget" name="OutputTreeWidget">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="showDropIndicator" stdset="0">
|
||||||
|
<bool>false</bool>
|
||||||
|
</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="uniformRowHeights">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="headerVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Name</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Type</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>ID</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Current</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="CheckAllButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check All</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="UncheckAllButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Uncheck All</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="NumSelectedLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<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="ApplyButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Apply</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="ProgressBar">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100000</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="StartButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Start</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="CancelButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>CCheckableTreeWidget</class>
|
||||||
|
<extends>QTreeWidget</extends>
|
||||||
|
<header>Editor/Widgets/CCheckableTreeWidget.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="Icons.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef CPROGRESSBARNOTIFIER_H
|
||||||
|
#define CPROGRESSBARNOTIFIER_H
|
||||||
|
|
||||||
|
#include <Math/MathUtil.h>
|
||||||
|
#include <Core/IProgressNotifier.h>
|
||||||
|
#include <QProgressBar>
|
||||||
|
|
||||||
|
/** Progress notifier class that updates a QProgressBar. */
|
||||||
|
class CProgressBarNotifier : public IProgressNotifier
|
||||||
|
{
|
||||||
|
/** The progress bar we are relaying updates to */
|
||||||
|
QProgressBar* mpProgressBar;
|
||||||
|
|
||||||
|
/** Whether the user has requested to cancel */
|
||||||
|
bool mCancel;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CProgressBarNotifier()
|
||||||
|
: IProgressNotifier()
|
||||||
|
, mpProgressBar(nullptr)
|
||||||
|
, mCancel(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline void SetProgressBar(QProgressBar* pProgressBar)
|
||||||
|
{
|
||||||
|
mpProgressBar = pProgressBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetCanceled(bool ShouldCancel)
|
||||||
|
{
|
||||||
|
mCancel = ShouldCancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** IProgressNotifier interface */
|
||||||
|
virtual bool ShouldCancel() const
|
||||||
|
{
|
||||||
|
return mCancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void UpdateProgress(const TString &, const TString &, float ProgressPercent)
|
||||||
|
{
|
||||||
|
if (mpProgressBar)
|
||||||
|
{
|
||||||
|
int Alpha = Math::Lerp(mpProgressBar->minimum(), mpProgressBar->maximum(), ProgressPercent);
|
||||||
|
|
||||||
|
// Defer setValue call so it runs on the correct thread
|
||||||
|
QMetaObject::invokeMethod(mpProgressBar, "setValue", Qt::AutoConnection, Q_ARG(int, Alpha));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CPROGRESSBARNOTIFIER_H
|
|
@ -25,6 +25,13 @@ public:
|
||||||
|
|
||||||
// Note: All function calls should be deferred with QMetaObject::invokeMethod to ensure
|
// Note: All function calls should be deferred with QMetaObject::invokeMethod to ensure
|
||||||
// that they run on the UI thread instead of whatever thread we happen to be on.
|
// that they run on the UI thread instead of whatever thread we happen to be on.
|
||||||
|
virtual void AsyncMessageBox(const TString& rkInfoBoxTitle, const TString& rkMessage)
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(this, "AsyncMessageBoxSlot", Qt::QueuedConnection,
|
||||||
|
Q_ARG(QString, TO_QSTRING(rkInfoBoxTitle)),
|
||||||
|
Q_ARG(QString, TO_QSTRING(rkMessage)) );
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool AskYesNoQuestion(const TString& rkInfoBoxTitle, const TString& rkQuestion)
|
virtual bool AskYesNoQuestion(const TString& rkInfoBoxTitle, const TString& rkQuestion)
|
||||||
{
|
{
|
||||||
bool RetVal;
|
bool RetVal;
|
||||||
|
@ -36,6 +43,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void AsyncMessageBoxSlot(const QString& rkInfoBoxTitle, const QString& rkMessage)
|
||||||
|
{
|
||||||
|
UICommon::InfoMsg(gpEdApp->WorldEditor(), rkInfoBoxTitle, rkMessage);
|
||||||
|
}
|
||||||
|
|
||||||
bool AskYesNoQuestionSlot(const QString& rkInfoBoxTitle, const QString& rkQuestion)
|
bool AskYesNoQuestionSlot(const QString& rkInfoBoxTitle, const QString& rkQuestion)
|
||||||
{
|
{
|
||||||
return UICommon::YesNoQuestion(gpEdApp->WorldEditor(), rkInfoBoxTitle, rkQuestion);
|
return UICommon::YesNoQuestion(gpEdApp->WorldEditor(), rkInfoBoxTitle, rkQuestion);
|
||||||
|
|
|
@ -199,7 +199,11 @@ HEADERS += \
|
||||||
ResourceBrowser/CVirtualDirectoryTreeView.h \
|
ResourceBrowser/CVirtualDirectoryTreeView.h \
|
||||||
CPropertyNameValidator.h \
|
CPropertyNameValidator.h \
|
||||||
Widgets/CSoftValidatorLineEdit.h \
|
Widgets/CSoftValidatorLineEdit.h \
|
||||||
Widgets/CValidityLabel.h
|
Widgets/CValidityLabel.h \
|
||||||
|
CGeneratePropertyNamesDialog.h \
|
||||||
|
CProgressBarNotifier.h \
|
||||||
|
Widgets/CCheckableTreeWidgetItem.h \
|
||||||
|
Widgets/CCheckableTreeWidget.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
@ -274,7 +278,8 @@ SOURCES += \
|
||||||
ResourceBrowser/CResourceTableView.cpp \
|
ResourceBrowser/CResourceTableView.cpp \
|
||||||
ResourceBrowser/CVirtualDirectoryModel.cpp \
|
ResourceBrowser/CVirtualDirectoryModel.cpp \
|
||||||
ResourceBrowser/CVirtualDirectoryTreeView.cpp \
|
ResourceBrowser/CVirtualDirectoryTreeView.cpp \
|
||||||
CPropertyNameValidator.cpp
|
CPropertyNameValidator.cpp \
|
||||||
|
CGeneratePropertyNamesDialog.cpp
|
||||||
|
|
||||||
# UI Files
|
# UI Files
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
@ -300,4 +305,5 @@ FORMS += \
|
||||||
CProjectSettingsDialog.ui \
|
CProjectSettingsDialog.ui \
|
||||||
WorldEditor/CPoiMapSidebar.ui \
|
WorldEditor/CPoiMapSidebar.ui \
|
||||||
CProgressDialog.ui \
|
CProgressDialog.ui \
|
||||||
Widgets/CSelectResourcePanel.ui
|
Widgets/CSelectResourcePanel.ui \
|
||||||
|
CGeneratePropertyNamesDialog.ui
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef CCHECKABLETREEWIDGET_H
|
||||||
|
#define CCHECKABLETREEWIDGET_H
|
||||||
|
|
||||||
|
#include <QTreeWidget>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QTreeWidget subclass that emits a signal when an item is checked or unchecked.
|
||||||
|
* Items must be instantiated as CCheckableTreeWidgetItem, not QTreeWidgetItem.
|
||||||
|
*/
|
||||||
|
class CCheckableTreeWidget : public QTreeWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void CheckStateChanged(QTreeWidgetItem* pItem);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CCheckableTreeWidget(QWidget* pParent = 0)
|
||||||
|
: QTreeWidget(pParent) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCHECKABLETREEWIDGET_H
|
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef CCHECKABLETREEWIDGETITEM_H
|
||||||
|
#define CCHECKABLETREEWIDGETITEM_H
|
||||||
|
|
||||||
|
#include "CCheckableTreeWidget.h"
|
||||||
|
#include <QTreeWidgetItem>
|
||||||
|
|
||||||
|
/** QTreeWidgetItem subclass that emits a signal when checked/unchecked. */
|
||||||
|
class CCheckableTreeWidgetItem : public QTreeWidgetItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Constructors */
|
||||||
|
CCheckableTreeWidgetItem(int type = Type)
|
||||||
|
: QTreeWidgetItem(type) {}
|
||||||
|
|
||||||
|
CCheckableTreeWidgetItem(const QStringList& strings, int type = Type)
|
||||||
|
: QTreeWidgetItem(strings, type) {}
|
||||||
|
|
||||||
|
CCheckableTreeWidgetItem(QTreeWidget* parent, int type = Type)
|
||||||
|
: QTreeWidgetItem(parent, type) {}
|
||||||
|
|
||||||
|
CCheckableTreeWidgetItem(QTreeWidget* parent, const QStringList& strings, int type = Type)
|
||||||
|
: QTreeWidgetItem(parent, strings, type) {}
|
||||||
|
|
||||||
|
CCheckableTreeWidgetItem(QTreeWidget* parent, QTreeWidgetItem* preceding, int type = Type)
|
||||||
|
: QTreeWidgetItem(parent, preceding, type) {}
|
||||||
|
|
||||||
|
CCheckableTreeWidgetItem(QTreeWidgetItem* parent, int type = Type)
|
||||||
|
: QTreeWidgetItem(parent, type) {}
|
||||||
|
|
||||||
|
CCheckableTreeWidgetItem(QTreeWidgetItem* parent, const QStringList& strings, int type = Type)
|
||||||
|
: QTreeWidgetItem(parent, strings, type) {}
|
||||||
|
|
||||||
|
CCheckableTreeWidgetItem(QTreeWidgetItem* parent, QTreeWidgetItem* preceding, int type = Type)
|
||||||
|
: QTreeWidgetItem(parent, preceding, type) {}
|
||||||
|
|
||||||
|
CCheckableTreeWidgetItem(const QTreeWidgetItem& other)
|
||||||
|
: QTreeWidgetItem(other) {}
|
||||||
|
|
||||||
|
/** setData override to catch check state changes */
|
||||||
|
virtual void setData(int Column, int Role, const QVariant& rkValue)
|
||||||
|
{
|
||||||
|
Qt::CheckState OldState = checkState(0);
|
||||||
|
QTreeWidgetItem::setData(Column, Role, rkValue);
|
||||||
|
Qt::CheckState NewState = checkState(0);
|
||||||
|
|
||||||
|
if (OldState != NewState)
|
||||||
|
{
|
||||||
|
CCheckableTreeWidget* pCheckableTree =
|
||||||
|
qobject_cast<CCheckableTreeWidget*>(treeWidget());
|
||||||
|
|
||||||
|
if (pCheckableTree)
|
||||||
|
{
|
||||||
|
pCheckableTree->CheckStateChanged(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCHECKABLETREEWIDGETITEM_H
|
|
@ -34,7 +34,8 @@ CTemplateEditDialog::CTemplateEditDialog(IPropertyTemplate *pTemplate, QWidget *
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CTemplateLoader::LoadAllGames();
|
CTemplateLoader::LoadAllGames();
|
||||||
std::vector<TString> TemplateList = CMasterTemplate::XMLsUsingID(pTemplate->PropertyID());
|
std::vector<TString> TemplateList;
|
||||||
|
CMasterTemplate::XMLsUsingID(pTemplate->PropertyID(), TemplateList);
|
||||||
|
|
||||||
for (u32 iTemp = 0; iTemp < TemplateList.size(); iTemp++)
|
for (u32 iTemp = 0; iTemp < TemplateList.size(); iTemp++)
|
||||||
mpUI->TemplatesListWidget->addItem(TO_QSTRING(TemplateList[iTemp]));
|
mpUI->TemplatesListWidget->addItem(TO_QSTRING(TemplateList[iTemp]));
|
||||||
|
|
|
@ -36,6 +36,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
||||||
, mpArea(nullptr)
|
, mpArea(nullptr)
|
||||||
, mpWorld(nullptr)
|
, mpWorld(nullptr)
|
||||||
, mpLinkDialog(new CLinkDialog(this, this))
|
, mpLinkDialog(new CLinkDialog(this, this))
|
||||||
|
, mpGeneratePropertyNamesDialog(new CGeneratePropertyNamesDialog(this))
|
||||||
, mIsMakingLink(false)
|
, mIsMakingLink(false)
|
||||||
, mpNewLinkSender(nullptr)
|
, mpNewLinkSender(nullptr)
|
||||||
, mpNewLinkReceiver(nullptr)
|
, mpNewLinkReceiver(nullptr)
|
||||||
|
@ -174,6 +175,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
||||||
connect(ui->ActionUnlink, SIGNAL(triggered()), this, SLOT(OnUnlinkClicked()));
|
connect(ui->ActionUnlink, SIGNAL(triggered()), this, SLOT(OnUnlinkClicked()));
|
||||||
|
|
||||||
connect(ui->ActionEditLayers, SIGNAL(triggered()), this, SLOT(EditLayers()));
|
connect(ui->ActionEditLayers, SIGNAL(triggered()), this, SLOT(EditLayers()));
|
||||||
|
connect(ui->ActionGeneratePropertyNames, SIGNAL(triggered()), this, SLOT(GeneratePropertyNames()));
|
||||||
|
|
||||||
connect(ui->ActionDrawWorld, SIGNAL(triggered()), this, SLOT(ToggleDrawWorld()));
|
connect(ui->ActionDrawWorld, SIGNAL(triggered()), this, SLOT(ToggleDrawWorld()));
|
||||||
connect(ui->ActionDrawObjects, SIGNAL(triggered()), this, SLOT(ToggleDrawObjects()));
|
connect(ui->ActionDrawObjects, SIGNAL(triggered()), this, SLOT(ToggleDrawObjects()));
|
||||||
|
@ -1341,3 +1343,9 @@ void CWorldEditor::EditLayers()
|
||||||
Editor.SetArea(mpArea);
|
Editor.SetArea(mpArea);
|
||||||
Editor.exec();
|
Editor.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWorldEditor::GeneratePropertyNames()
|
||||||
|
{
|
||||||
|
// Launch property name generation dialog
|
||||||
|
mpGeneratePropertyNamesDialog->show();
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "CScriptEditSidebar.h"
|
#include "CScriptEditSidebar.h"
|
||||||
#include "CWorldInfoSidebar.h"
|
#include "CWorldInfoSidebar.h"
|
||||||
#include "Editor/INodeEditor.h"
|
#include "Editor/INodeEditor.h"
|
||||||
|
#include "Editor/CGeneratePropertyNamesDialog.h"
|
||||||
#include "Editor/CGizmo.h"
|
#include "Editor/CGizmo.h"
|
||||||
#include "Editor/CSceneViewport.h"
|
#include "Editor/CSceneViewport.h"
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ class CWorldEditor : public INodeEditor
|
||||||
|
|
||||||
CCollisionRenderSettingsDialog *mpCollisionDialog;
|
CCollisionRenderSettingsDialog *mpCollisionDialog;
|
||||||
CLinkDialog *mpLinkDialog;
|
CLinkDialog *mpLinkDialog;
|
||||||
|
CGeneratePropertyNamesDialog* mpGeneratePropertyNamesDialog;
|
||||||
|
|
||||||
bool mIsMakingLink;
|
bool mIsMakingLink;
|
||||||
CScriptObject *mpNewLinkSender;
|
CScriptObject *mpNewLinkSender;
|
||||||
|
@ -177,6 +179,7 @@ private slots:
|
||||||
void DecrementGizmo();
|
void DecrementGizmo();
|
||||||
void EditCollisionRenderSettings();
|
void EditCollisionRenderSettings();
|
||||||
void EditLayers();
|
void EditLayers();
|
||||||
|
void GeneratePropertyNames();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void MapChanged(CWorld *pNewWorld, CGameArea *pNewArea);
|
void MapChanged(CWorld *pNewWorld, CGameArea *pNewArea);
|
||||||
|
|
|
@ -339,11 +339,12 @@
|
||||||
<string>Tools</string>
|
<string>Tools</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="ActionEditLayers"/>
|
<addaction name="ActionEditLayers"/>
|
||||||
|
<addaction name="ActionGeneratePropertyNames"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menuFile"/>
|
<addaction name="menuFile"/>
|
||||||
<addaction name="menuEdit"/>
|
<addaction name="menuEdit"/>
|
||||||
<addaction name="menuTools"/>
|
|
||||||
<addaction name="menuView"/>
|
<addaction name="menuView"/>
|
||||||
|
<addaction name="menuTools"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QToolBar" name="EditModeToolBar">
|
<widget class="QToolBar" name="EditModeToolBar">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -767,6 +768,11 @@
|
||||||
<string>Project Settings</string>
|
<string>Project Settings</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="ActionGeneratePropertyNames">
|
||||||
|
<property name="text">
|
||||||
|
<string>Generate Property Names</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
|
|
@ -46,7 +46,7 @@ template<typename Type>
|
||||||
Type Lerp(const Type& rkA, const Type& rkB, float t)
|
Type Lerp(const Type& rkA, const Type& rkB, float t)
|
||||||
{
|
{
|
||||||
Type Diff = rkB - rkA;
|
Type Diff = rkB - rkA;
|
||||||
return rkA + (Diff * t);
|
return rkA + Type(Diff * t);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool,float> RayPlaneIntersection(const CRay& rkRay, const CPlane& rkPlane);
|
std::pair<bool,float> RayPlaneIntersection(const CRay& rkRay, const CPlane& rkPlane);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue