Added support for CAUD dependencies, dropped redundant asset ID in dependency trees, various MP3 fixes
This commit is contained in:
parent
5485d42b56
commit
a88afe31e3
Binary file not shown.
|
@ -321,6 +321,14 @@ TWideString SanitizeName(TWideString Name, bool Directory, bool RootDir /*= fals
|
||||||
if (ChopNum > 0) Name = Name.ChopBack(ChopNum);
|
if (ChopNum > 0) Name = Name.ChopBack(ChopNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove spaces from beginning of path
|
||||||
|
u32 NumLeadingSpaces = 0;
|
||||||
|
while (NumLeadingSpaces < Name.Size() && Name[NumLeadingSpaces] == L' ')
|
||||||
|
NumLeadingSpaces++;
|
||||||
|
|
||||||
|
if (NumLeadingSpaces > 0)
|
||||||
|
Name = Name.ChopFront(NumLeadingSpaces);
|
||||||
|
|
||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,6 +140,12 @@ public:
|
||||||
return IndexOf(pkCharacters, 0);
|
return IndexOf(pkCharacters, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline u32 LastIndexOf(CharType Character) const
|
||||||
|
{
|
||||||
|
size_t Pos = mInternalString.find_last_of(Character);
|
||||||
|
return (Pos == _TStdString::npos ? -1 : (u32) Pos);
|
||||||
|
}
|
||||||
|
|
||||||
inline u32 LastIndexOf(const CharType* pkCharacters) const
|
inline u32 LastIndexOf(const CharType* pkCharacters) const
|
||||||
{
|
{
|
||||||
size_t Pos = mInternalString.find_last_of(pkCharacters);
|
size_t Pos = mInternalString.find_last_of(pkCharacters);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "AssetNameGeneration.h"
|
#include "AssetNameGeneration.h"
|
||||||
#include "CGameProject.h"
|
#include "CGameProject.h"
|
||||||
#include "CResourceIterator.h"
|
#include "CResourceIterator.h"
|
||||||
|
#include "Core/Resource/CAudioMacro.h"
|
||||||
#include "Core/Resource/CFont.h"
|
#include "Core/Resource/CFont.h"
|
||||||
#include "Core/Resource/CScan.h"
|
#include "Core/Resource/CScan.h"
|
||||||
#include "Core/Resource/CWorld.h"
|
#include "Core/Resource/CWorld.h"
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
#define PROCESS_AREAS 1
|
#define PROCESS_AREAS 1
|
||||||
#define PROCESS_MODELS 1
|
#define PROCESS_MODELS 1
|
||||||
#define PROCESS_AUDIO_GROUPS 1
|
#define PROCESS_AUDIO_GROUPS 1
|
||||||
|
#define PROCESS_AUDIO_MACROS 1
|
||||||
#define PROCESS_ANIM_CHAR_SETS 1
|
#define PROCESS_ANIM_CHAR_SETS 1
|
||||||
#define PROCESS_STRINGS 1
|
#define PROCESS_STRINGS 1
|
||||||
#define PROCESS_SCANS 1
|
#define PROCESS_SCANS 1
|
||||||
|
@ -19,10 +21,16 @@
|
||||||
|
|
||||||
void ApplyGeneratedName(CResourceEntry *pEntry, const TWideString& rkDir, const TWideString& rkName)
|
void ApplyGeneratedName(CResourceEntry *pEntry, const TWideString& rkDir, const TWideString& rkName)
|
||||||
{
|
{
|
||||||
|
ASSERT(pEntry != nullptr);
|
||||||
TWideString SanitizedName = FileUtil::SanitizeName(rkName, false);
|
TWideString SanitizedName = FileUtil::SanitizeName(rkName, false);
|
||||||
TWideString SanitizedDir = FileUtil::SanitizePath(rkDir, true);
|
TWideString SanitizedDir = FileUtil::SanitizePath(rkDir, true);
|
||||||
if (SanitizedName.IsEmpty()) return;
|
if (SanitizedName.IsEmpty()) return;
|
||||||
|
|
||||||
|
// trying to keep these as consistent with Retro's naming scheme as possible, and
|
||||||
|
// for some reason in MP3 they started using all lowercase folder names...
|
||||||
|
if (pEntry->Game() >= eCorruptionProto)
|
||||||
|
SanitizedDir = SanitizedDir.ToLower();
|
||||||
|
|
||||||
CVirtualDirectory *pNewDir = pEntry->ResourceStore()->GetVirtualDirectory(SanitizedDir, false, true);
|
CVirtualDirectory *pNewDir = pEntry->ResourceStore()->GetVirtualDirectory(SanitizedDir, false, true);
|
||||||
if (pEntry->Directory() == pNewDir && pEntry->Name() == SanitizedName) return;
|
if (pEntry->Directory() == pNewDir && pEntry->Name() == SanitizedName) return;
|
||||||
|
|
||||||
|
@ -39,89 +47,8 @@ void ApplyGeneratedName(CResourceEntry *pEntry, const TWideString& rkDir, const
|
||||||
ASSERT(Success);
|
ASSERT(Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
TWideString MakeWorldName(EGame Game, TWideString RawName)
|
|
||||||
{
|
|
||||||
// The raw world names are basically formatted differently in every single game...
|
|
||||||
// MP1 demo - Remove ! from the beginning
|
|
||||||
if (Game == ePrimeDemo)
|
|
||||||
{
|
|
||||||
if (RawName.StartsWith(L'!'))
|
|
||||||
RawName = RawName.ChopFront(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// MP1 - Remove prefix characters and ending date
|
|
||||||
else if (Game == ePrime)
|
|
||||||
{
|
|
||||||
RawName = RawName.ChopFront(2);
|
|
||||||
bool StartedDate = false;
|
|
||||||
|
|
||||||
while (!RawName.IsEmpty())
|
|
||||||
{
|
|
||||||
wchar_t Chr = RawName.Back();
|
|
||||||
|
|
||||||
if (!StartedDate && Chr >= L'0' && Chr <= L'9')
|
|
||||||
StartedDate = true;
|
|
||||||
else if (StartedDate && Chr != L'_' && (Chr < L'0' || Chr > L'9'))
|
|
||||||
break;
|
|
||||||
|
|
||||||
RawName = RawName.ChopBack(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MP2 demo - Use text between the first and second underscores
|
|
||||||
else if (Game == eEchoesDemo)
|
|
||||||
{
|
|
||||||
u32 UnderscoreA = RawName.IndexOf(L'_');
|
|
||||||
u32 UnderscoreB = RawName.IndexOf(L'_', UnderscoreA + 1);
|
|
||||||
RawName = RawName.SubString(UnderscoreA + 1, UnderscoreB - UnderscoreA - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// MP2 - Remove text before first underscore and after last underscore, strip remaining underscores (except multiplayer maps, which have one underscore)
|
|
||||||
else if (Game == eEchoes)
|
|
||||||
{
|
|
||||||
u32 FirstUnderscore = RawName.IndexOf(L'_');
|
|
||||||
u32 LastUnderscore = RawName.LastIndexOf(L"_");
|
|
||||||
|
|
||||||
if (FirstUnderscore != LastUnderscore)
|
|
||||||
{
|
|
||||||
RawName = RawName.ChopBack(RawName.Size() - LastUnderscore);
|
|
||||||
RawName = RawName.ChopFront(FirstUnderscore + 1);
|
|
||||||
RawName.Remove(L'_');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MP3 proto - Remove ! from the beginning and all text after last underscore
|
|
||||||
else if (Game == eCorruptionProto)
|
|
||||||
{
|
|
||||||
if (RawName.StartsWith(L'!'))
|
|
||||||
RawName = RawName.ChopFront(1);
|
|
||||||
|
|
||||||
u32 LastUnderscore = RawName.LastIndexOf(L"_");
|
|
||||||
RawName = RawName.ChopBack(RawName.Size() - LastUnderscore);
|
|
||||||
}
|
|
||||||
|
|
||||||
// MP3 - Remove text after last underscore
|
|
||||||
else if (Game == eCorruption)
|
|
||||||
{
|
|
||||||
u32 LastUnderscore = RawName.LastIndexOf(L"_");
|
|
||||||
RawName = RawName.ChopBack(RawName.Size() - LastUnderscore);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DKCR - Remove text after second-to-last underscore
|
|
||||||
else if (Game == eReturns)
|
|
||||||
{
|
|
||||||
u32 Underscore = RawName.LastIndexOf(L"_");
|
|
||||||
RawName = RawName.ChopBack(RawName.Size() - Underscore);
|
|
||||||
Underscore = RawName.LastIndexOf(L"_");
|
|
||||||
RawName = RawName.ChopBack(RawName.Size() - Underscore);
|
|
||||||
}
|
|
||||||
|
|
||||||
return RawName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenerateAssetNames(CGameProject *pProj)
|
void GenerateAssetNames(CGameProject *pProj)
|
||||||
{
|
{
|
||||||
// todo: CAUD/CSMP
|
|
||||||
CResourceStore *pStore = pProj->ResourceStore();
|
CResourceStore *pStore = pProj->ResourceStore();
|
||||||
|
|
||||||
#if PROCESS_PACKAGES
|
#if PROCESS_PACKAGES
|
||||||
|
@ -135,7 +62,10 @@ void GenerateAssetNames(CGameProject *pProj)
|
||||||
const SNamedResource& rkRes = pPkg->NamedResourceByIndex(iRes);
|
const SNamedResource& rkRes = pPkg->NamedResourceByIndex(iRes);
|
||||||
if (rkRes.Name.EndsWith("NODEPEND")) continue;
|
if (rkRes.Name.EndsWith("NODEPEND")) continue;
|
||||||
|
|
||||||
|
// Some of Retro's paks reference assets that don't exist, so we need this check here.
|
||||||
CResourceEntry *pRes = pStore->FindEntry(rkRes.ID);
|
CResourceEntry *pRes = pStore->FindEntry(rkRes.ID);
|
||||||
|
|
||||||
|
if (pRes)
|
||||||
ApplyGeneratedName(pRes, pPkg->Name().ToUTF16(), rkRes.Name.ToUTF16());
|
ApplyGeneratedName(pRes, pPkg->Name().ToUTF16(), rkRes.Name.ToUTF16());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,8 +77,9 @@ void GenerateAssetNames(CGameProject *pProj)
|
||||||
|
|
||||||
for (TResourceIterator<eWorld> It(pStore); It; ++It)
|
for (TResourceIterator<eWorld> It(pStore); It; ++It)
|
||||||
{
|
{
|
||||||
// Generate world name
|
// Set world name
|
||||||
TWideString WorldName = MakeWorldName(pProj->Game(), It->Name());
|
CWorld *pWorld = (CWorld*) It->Load();
|
||||||
|
TWideString WorldName = L'!' + pWorld->Name().ToUTF16() + L"_Master";
|
||||||
TWideString WorldDir = kWorldsRoot + WorldName + L'\\';
|
TWideString WorldDir = kWorldsRoot + WorldName + L'\\';
|
||||||
|
|
||||||
TWideString WorldMasterName = L"!" + WorldName + L"_Master";
|
TWideString WorldMasterName = L"!" + WorldName + L"_Master";
|
||||||
|
@ -159,10 +90,9 @@ void GenerateAssetNames(CGameProject *pProj)
|
||||||
const TWideString WorldNamesDir = L"Strings\\Worlds\\General\\";
|
const TWideString WorldNamesDir = L"Strings\\Worlds\\General\\";
|
||||||
const TWideString AreaNamesDir = TWideString::Format(L"Strings\\Worlds\\%s\\", *WorldName);
|
const TWideString AreaNamesDir = TWideString::Format(L"Strings\\Worlds\\%s\\", *WorldName);
|
||||||
|
|
||||||
CWorld *pWorld = (CWorld*) It->Load();
|
|
||||||
CModel *pSkyModel = pWorld->DefaultSkybox();
|
CModel *pSkyModel = pWorld->DefaultSkybox();
|
||||||
CStringTable *pWorldNameTable = pWorld->WorldName();
|
CStringTable *pWorldNameTable = pWorld->NameString();
|
||||||
CStringTable *pDarkWorldNameTable = pWorld->DarkWorldName();
|
CStringTable *pDarkWorldNameTable = pWorld->DarkNameString();
|
||||||
CResource *pSaveWorld = pWorld->SaveWorld();
|
CResource *pSaveWorld = pWorld->SaveWorld();
|
||||||
CResource *pMapWorld = pWorld->MapWorld();
|
CResource *pMapWorld = pWorld->MapWorld();
|
||||||
|
|
||||||
|
@ -418,11 +348,34 @@ void GenerateAssetNames(CGameProject *pProj)
|
||||||
|
|
||||||
#if PROCESS_AUDIO_GROUPS
|
#if PROCESS_AUDIO_GROUPS
|
||||||
// Generate Audio Group names
|
// Generate Audio Group names
|
||||||
|
const TWideString kAudioGrpDir = L"Audio\\";
|
||||||
|
|
||||||
for (TResourceIterator<eAudioGroup> It(pStore); It; ++It)
|
for (TResourceIterator<eAudioGroup> It(pStore); It; ++It)
|
||||||
{
|
{
|
||||||
CAudioGroup *pGroup = (CAudioGroup*) It->Load();
|
CAudioGroup *pGroup = (CAudioGroup*) It->Load();
|
||||||
TWideString GroupName = pGroup->GroupName().ToUTF16();
|
TWideString GroupName = pGroup->GroupName().ToUTF16();
|
||||||
ApplyGeneratedName(*It, L"Audio\\", GroupName);
|
ApplyGeneratedName(*It, kAudioGrpDir, GroupName);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PROCESS_AUDIO_MACROS
|
||||||
|
// Process audio macro/sample names
|
||||||
|
const TWideString kSfxDir = L"Audio\\Uncategorized\\";
|
||||||
|
|
||||||
|
for (TResourceIterator<eAudioMacro> It(pStore); It; ++It)
|
||||||
|
{
|
||||||
|
CAudioMacro *pMacro = (CAudioMacro*) It->Load();
|
||||||
|
TWideString MacroName = pMacro->MacroName().ToUTF16();
|
||||||
|
ApplyGeneratedName(*It, kSfxDir, MacroName);
|
||||||
|
|
||||||
|
for (u32 iSamp = 0; iSamp < pMacro->NumSamples(); iSamp++)
|
||||||
|
{
|
||||||
|
CAssetID SampleID = pMacro->SampleByIndex(iSamp);
|
||||||
|
CResourceEntry *pSample = pStore->FindEntry(SampleID);
|
||||||
|
|
||||||
|
if (pSample && !pSample->IsNamed())
|
||||||
|
ApplyGeneratedName(pSample, kSfxDir, TWideString::Format(L"%s_sample%d", *MacroName, iSamp));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -487,6 +440,8 @@ void GenerateAssetNames(CGameProject *pProj)
|
||||||
|
|
||||||
#if PROCESS_STRINGS
|
#if PROCESS_STRINGS
|
||||||
// Generate string names
|
// Generate string names
|
||||||
|
const TWideString kStringsDir = L"Strings\\Uncategorized\\";
|
||||||
|
|
||||||
for (TResourceIterator<eStringTable> It(pStore); It; ++It)
|
for (TResourceIterator<eStringTable> It(pStore); It; ++It)
|
||||||
{
|
{
|
||||||
if (It->IsNamed()) continue;
|
if (It->IsNamed()) continue;
|
||||||
|
@ -504,7 +459,7 @@ void GenerateAssetNames(CGameProject *pProj)
|
||||||
while (Name.EndsWith(L".") || TWideString::IsWhitespace(Name.Back()))
|
while (Name.EndsWith(L".") || TWideString::IsWhitespace(Name.Back()))
|
||||||
Name = Name.ChopBack(1);
|
Name = Name.ChopBack(1);
|
||||||
|
|
||||||
ApplyGeneratedName(pString->Entry(), pString->Entry()->DirectoryPath(), Name);
|
ApplyGeneratedName(pString->Entry(), kStringsDir, Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,8 +32,7 @@ EDependencyNodeType CDependencyTree::Type() const
|
||||||
|
|
||||||
void CDependencyTree::Serialize(IArchive& rArc)
|
void CDependencyTree::Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
rArc << SERIAL("RootID", mRootID)
|
rArc << SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
|
||||||
<< SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDependencyTree::AddChild(IDependencyNode *pNode)
|
void CDependencyTree::AddChild(IDependencyNode *pNode)
|
||||||
|
|
|
@ -47,12 +47,8 @@ public:
|
||||||
// Basic dependency tree; this class is sufficient for most resource types.
|
// Basic dependency tree; this class is sufficient for most resource types.
|
||||||
class CDependencyTree : public IDependencyNode
|
class CDependencyTree : public IDependencyNode
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
CAssetID mRootID;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDependencyTree() {}
|
CDependencyTree() {}
|
||||||
CDependencyTree(const CAssetID& rkID) : mRootID(rkID) {}
|
|
||||||
|
|
||||||
virtual EDependencyNodeType Type() const;
|
virtual EDependencyNodeType Type() const;
|
||||||
virtual void Serialize(IArchive& rArc);
|
virtual void Serialize(IArchive& rArc);
|
||||||
|
@ -61,10 +57,6 @@ public:
|
||||||
void AddDependency(const CAssetID& rkID, bool AvoidDuplicates = true);
|
void AddDependency(const CAssetID& rkID, bool AvoidDuplicates = true);
|
||||||
void AddDependency(CResource *pRes, bool AvoidDuplicates = true);
|
void AddDependency(CResource *pRes, bool AvoidDuplicates = true);
|
||||||
void AddCharacterDependency(const CAnimationParameters& rkAnimParams);
|
void AddCharacterDependency(const CAnimationParameters& rkAnimParams);
|
||||||
|
|
||||||
// Accessors
|
|
||||||
inline void SetID(const CAssetID& rkID) { mRootID = rkID; }
|
|
||||||
inline CAssetID ID() const { return mRootID; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Node representing a single resource dependency.
|
// Node representing a single resource dependency.
|
||||||
|
@ -217,7 +209,6 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CAreaDependencyTree() : CDependencyTree() {}
|
CAreaDependencyTree() : CDependencyTree() {}
|
||||||
CAreaDependencyTree(const CAssetID& rkID) : CDependencyTree(rkID) {}
|
|
||||||
|
|
||||||
virtual EDependencyNodeType Type() const;
|
virtual EDependencyNodeType Type() const;
|
||||||
virtual void Serialize(IArchive& rArc);
|
virtual void Serialize(IArchive& rArc);
|
||||||
|
|
|
@ -482,11 +482,13 @@ void CGameExporter::ExportResourceEditorData()
|
||||||
{
|
{
|
||||||
if (!It->IsTransient())
|
if (!It->IsTransient())
|
||||||
{
|
{
|
||||||
// Worlds need to know which areas can have duplicates. We only have this info at export time.
|
// Worlds need some info we can only get from the pak at export time; namely, which areas can
|
||||||
|
// have duplicates, as well as the world's internal name.
|
||||||
if (It->ResourceType() == eWorld)
|
if (It->ResourceType() == eWorld)
|
||||||
{
|
{
|
||||||
CWorld *pWorld = (CWorld*) It->Load();
|
CWorld *pWorld = (CWorld*) It->Load();
|
||||||
|
|
||||||
|
// Set area duplicate flags
|
||||||
for (u32 iArea = 0; iArea < pWorld->NumAreas(); iArea++)
|
for (u32 iArea = 0; iArea < pWorld->NumAreas(); iArea++)
|
||||||
{
|
{
|
||||||
CAssetID AreaID = pWorld->AreaResourceID(iArea);
|
CAssetID AreaID = pWorld->AreaResourceID(iArea);
|
||||||
|
@ -495,6 +497,10 @@ void CGameExporter::ExportResourceEditorData()
|
||||||
if (Find != mAreaDuplicateMap.end())
|
if (Find != mAreaDuplicateMap.end())
|
||||||
pWorld->SetAreaAllowsPakDuplicates(iArea, Find->second);
|
pWorld->SetAreaAllowsPakDuplicates(iArea, Find->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set world name
|
||||||
|
TString WorldName = MakeWorldName(pWorld->ID());
|
||||||
|
pWorld->SetName(WorldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save raw resource + generate dependencies
|
// Save raw resource + generate dependencies
|
||||||
|
@ -546,3 +552,115 @@ void CGameExporter::ExportResource(SResourceInstance& rRes)
|
||||||
rRes.Exported = true;
|
rRes.Exported = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TString CGameExporter::MakeWorldName(CAssetID WorldID)
|
||||||
|
{
|
||||||
|
CResourceEntry *pWorldEntry = mpStore->FindEntry(WorldID);
|
||||||
|
ASSERT(pWorldEntry && pWorldEntry->ResourceType() == eWorld);
|
||||||
|
|
||||||
|
// Find the original world name in the package resource names
|
||||||
|
TString WorldName;
|
||||||
|
|
||||||
|
for (u32 iPkg = 0; iPkg < mpProject->NumPackages(); iPkg++)
|
||||||
|
{
|
||||||
|
CPackage *pPkg = mpProject->PackageByIndex(iPkg);
|
||||||
|
|
||||||
|
for (u32 iRes = 0; iRes < pPkg->NumNamedResources(); iRes++)
|
||||||
|
{
|
||||||
|
const SNamedResource& rkRes = pPkg->NamedResourceByIndex(iRes);
|
||||||
|
|
||||||
|
if (rkRes.ID == WorldID && !rkRes.Name.EndsWith("_NODEPEND"))
|
||||||
|
{
|
||||||
|
WorldName = rkRes.Name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WorldName.IsEmpty()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix up the name; remove date/time, leading exclamation points, etc
|
||||||
|
if (!WorldName.IsEmpty())
|
||||||
|
{
|
||||||
|
// World names are basically formatted differently in every game...
|
||||||
|
// MP1 demo - Remove ! from the beginning
|
||||||
|
if (mGame == ePrimeDemo)
|
||||||
|
{
|
||||||
|
if (WorldName.StartsWith('!'))
|
||||||
|
WorldName = WorldName.ChopFront(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MP1 - Remove prefix characters and ending date
|
||||||
|
else if (mGame == ePrime)
|
||||||
|
{
|
||||||
|
WorldName = WorldName.ChopFront(2);
|
||||||
|
bool StartedDate = false;
|
||||||
|
|
||||||
|
while (!WorldName.IsEmpty())
|
||||||
|
{
|
||||||
|
char Chr = WorldName.Back();
|
||||||
|
|
||||||
|
if (!StartedDate && Chr >= '0' && Chr <= '9')
|
||||||
|
StartedDate = true;
|
||||||
|
else if (StartedDate && Chr != '_' && (Chr < '0' || Chr > '9'))
|
||||||
|
break;
|
||||||
|
|
||||||
|
WorldName = WorldName.ChopBack(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MP2 demo - Use text between the first and second underscores
|
||||||
|
else if (mGame == eEchoesDemo)
|
||||||
|
{
|
||||||
|
u32 UnderscoreA = WorldName.IndexOf('_');
|
||||||
|
u32 UnderscoreB = WorldName.IndexOf('_', UnderscoreA + 1);
|
||||||
|
|
||||||
|
if (UnderscoreA != UnderscoreB && UnderscoreA != -1 && UnderscoreB != -1)
|
||||||
|
WorldName = WorldName.SubString(UnderscoreA + 1, UnderscoreB - UnderscoreA - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MP2 - Remove text before first underscore and after last underscore, strip remaining underscores (except multiplayer maps, which have one underscore)
|
||||||
|
else if (mGame == eEchoes)
|
||||||
|
{
|
||||||
|
u32 FirstUnderscore = WorldName.IndexOf('_');
|
||||||
|
u32 LastUnderscore = WorldName.LastIndexOf('_');
|
||||||
|
|
||||||
|
if (FirstUnderscore != LastUnderscore && FirstUnderscore != -1 && LastUnderscore != -1)
|
||||||
|
{
|
||||||
|
WorldName = WorldName.ChopBack(WorldName.Size() - LastUnderscore);
|
||||||
|
WorldName = WorldName.ChopFront(FirstUnderscore + 1);
|
||||||
|
WorldName.Remove('_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MP3 proto - Remove ! from the beginning and all text after last underscore
|
||||||
|
else if (mGame == eCorruptionProto)
|
||||||
|
{
|
||||||
|
if (WorldName.StartsWith('!'))
|
||||||
|
WorldName = WorldName.ChopFront(1);
|
||||||
|
|
||||||
|
u32 LastUnderscore = WorldName.LastIndexOf('_');
|
||||||
|
WorldName = WorldName.ChopBack(WorldName.Size() - LastUnderscore);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MP3 - Remove text after last underscore
|
||||||
|
else if (mGame == eCorruption)
|
||||||
|
{
|
||||||
|
u32 LastUnderscore = WorldName.LastIndexOf('_');
|
||||||
|
|
||||||
|
if (LastUnderscore != -1)
|
||||||
|
WorldName = WorldName.ChopBack(WorldName.Size() - LastUnderscore);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DKCR - Remove text after second-to-last underscore
|
||||||
|
else if (mGame == eReturns)
|
||||||
|
{
|
||||||
|
u32 Underscore = WorldName.LastIndexOf('_');
|
||||||
|
WorldName = WorldName.ChopBack(WorldName.Size() - Underscore);
|
||||||
|
Underscore = WorldName.LastIndexOf('_');
|
||||||
|
WorldName = WorldName.ChopBack(WorldName.Size() - Underscore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return WorldName;
|
||||||
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@ protected:
|
||||||
void ExportCookedResources();
|
void ExportCookedResources();
|
||||||
void ExportResourceEditorData();
|
void ExportResourceEditorData();
|
||||||
void ExportResource(SResourceInstance& rRes);
|
void ExportResource(SResourceInstance& rRes);
|
||||||
|
TString MakeWorldName(CAssetID WorldID);
|
||||||
|
|
||||||
// Convenience Functions
|
// Convenience Functions
|
||||||
inline SResourceInstance* FindResourceInstance(const CAssetID& rkID)
|
inline SResourceInstance* FindResourceInstance(const CAssetID& rkID)
|
||||||
|
|
|
@ -61,7 +61,7 @@ void CResourceEntry::UpdateDependencies()
|
||||||
|
|
||||||
if (!mpTypeInfo->CanHaveDependencies())
|
if (!mpTypeInfo->CanHaveDependencies())
|
||||||
{
|
{
|
||||||
mpDependencies = new CDependencyTree(ID());
|
mpDependencies = new CDependencyTree();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ void CResourceEntry::UpdateDependencies()
|
||||||
if (!mpResource)
|
if (!mpResource)
|
||||||
{
|
{
|
||||||
Log::Error("Unable to update cached dependencies; failed to load resource");
|
Log::Error("Unable to update cached dependencies; failed to load resource");
|
||||||
mpDependencies = new CDependencyTree(ID());
|
mpDependencies = new CDependencyTree();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ public:
|
||||||
|
|
||||||
CDependencyTree* BuildDependencyTree() const
|
CDependencyTree* BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
CDependencyTree *pTree = new CDependencyTree();
|
||||||
AddDependenciesToTree(pTree);
|
AddDependenciesToTree(pTree);
|
||||||
return pTree;
|
return pTree;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ public:
|
||||||
|
|
||||||
CDependencyTree* BuildDependencyTree() const
|
CDependencyTree* BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
CDependencyTree *pTree = new CDependencyTree();
|
||||||
|
|
||||||
// Character dependencies
|
// Character dependencies
|
||||||
for (u32 iChar = 0; iChar < mCharacters.size(); iChar++)
|
for (u32 iChar = 0; iChar < mCharacters.size(); iChar++)
|
||||||
|
|
|
@ -18,7 +18,7 @@ CAnimation::CAnimation(CResourceEntry *pEntry /*= 0*/)
|
||||||
|
|
||||||
CDependencyTree* CAnimation::BuildDependencyTree() const
|
CDependencyTree* CAnimation::BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
CDependencyTree *pTree = new CDependencyTree();
|
||||||
pTree->AddDependency(mpEventData);
|
pTree->AddDependency(mpEventData);
|
||||||
return pTree;
|
return pTree;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ CGameArea::~CGameArea()
|
||||||
CDependencyTree* CGameArea::BuildDependencyTree() const
|
CDependencyTree* CGameArea::BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
// Base dependencies
|
// Base dependencies
|
||||||
CAreaDependencyTree *pTree = new CAreaDependencyTree(ID());
|
CAreaDependencyTree *pTree = new CAreaDependencyTree();
|
||||||
|
|
||||||
std::set<CAssetID> MatTextures;
|
std::set<CAssetID> MatTextures;
|
||||||
mpMaterialSet->GetUsedTextureIDs(MatTextures);
|
mpMaterialSet->GetUsedTextureIDs(MatTextures);
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef CAUDIOMACRO_H
|
||||||
|
#define CAUDIOMACRO_H
|
||||||
|
|
||||||
|
#include "CResource.h"
|
||||||
|
|
||||||
|
class CAudioMacro : public CResource
|
||||||
|
{
|
||||||
|
DECLARE_RESOURCE_TYPE(eAudioMacro)
|
||||||
|
friend class CUnsupportedFormatLoader;
|
||||||
|
|
||||||
|
TString mMacroName;
|
||||||
|
std::vector<CAssetID> mSamples;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CAudioMacro(CResourceEntry *pEntry = 0)
|
||||||
|
: CResource(pEntry)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual CDependencyTree* BuildDependencyTree() const
|
||||||
|
{
|
||||||
|
CDependencyTree *pTree = new CDependencyTree();
|
||||||
|
|
||||||
|
for (u32 iSamp = 0; iSamp < mSamples.size(); iSamp++)
|
||||||
|
pTree->AddDependency(mSamples[iSamp]);
|
||||||
|
|
||||||
|
return pTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
inline TString MacroName() const { return mMacroName; }
|
||||||
|
inline u32 NumSamples() const { return mSamples.size(); }
|
||||||
|
inline CAssetID SampleByIndex(u32 Index) const { return mSamples[Index]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CAUDIOMACRO_H
|
|
@ -52,7 +52,7 @@ public:
|
||||||
|
|
||||||
CDependencyTree* BuildDependencyTree() const
|
CDependencyTree* BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
CDependencyTree *pTree = new CDependencyTree();
|
||||||
|
|
||||||
for (auto DepIt = mDependencies.begin(); DepIt != mDependencies.end(); DepIt++)
|
for (auto DepIt = mDependencies.begin(); DepIt != mDependencies.end(); DepIt++)
|
||||||
pTree->AddDependency(*DepIt);
|
pTree->AddDependency(*DepIt);
|
||||||
|
|
|
@ -24,7 +24,7 @@ inline float PtsToFloat(s32 Pt)
|
||||||
|
|
||||||
CDependencyTree* CFont::BuildDependencyTree() const
|
CDependencyTree* CFont::BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
CDependencyTree *pOut = new CDependencyTree(ID());
|
CDependencyTree *pOut = new CDependencyTree();
|
||||||
pOut->AddDependency(mpFontTexture);
|
pOut->AddDependency(mpFontTexture);
|
||||||
return pOut;
|
return pOut;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CResource() {}
|
virtual ~CResource() {}
|
||||||
virtual CDependencyTree* BuildDependencyTree() const { return new CDependencyTree(ID()); }
|
virtual CDependencyTree* BuildDependencyTree() const { return new CDependencyTree(); }
|
||||||
virtual void Serialize(IArchive& /*rArc*/) {}
|
virtual void Serialize(IArchive& /*rArc*/) {}
|
||||||
|
|
||||||
inline CResourceEntry* Entry() const { return mpEntry; }
|
inline CResourceEntry* Entry() const { return mpEntry; }
|
||||||
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
if (Game() >= eCorruptionProto)
|
if (Game() >= eCorruptionProto)
|
||||||
Log::Warning("CScan::BuildDependencyTree not handling Corruption dependencies");
|
Log::Warning("CScan::BuildDependencyTree not handling Corruption dependencies");
|
||||||
|
|
||||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
CDependencyTree *pTree = new CDependencyTree();
|
||||||
|
|
||||||
if (Game() <= ePrime)
|
if (Game() <= ePrime)
|
||||||
pTree->AddDependency(mFrameID);
|
pTree->AddDependency(mFrameID);
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
CDependencyTree* BuildDependencyTree() const
|
CDependencyTree* BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
// STRGs can reference FONTs with the &font=; formatting tag and TXTRs with the &image=; tag
|
// STRGs can reference FONTs with the &font=; formatting tag and TXTRs with the &image=; tag
|
||||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
CDependencyTree *pTree = new CDependencyTree();
|
||||||
EIDLength IDLength = (Game() <= eEchoes ? e32Bit : e64Bit);
|
EIDLength IDLength = (Game() <= eEchoes ? e32Bit : e64Bit);
|
||||||
|
|
||||||
for (u32 iLang = 0; iLang < mLangTables.size(); iLang++)
|
for (u32 iLang = 0; iLang < mLangTables.size(); iLang++)
|
||||||
|
|
|
@ -19,7 +19,7 @@ CWorld::~CWorld()
|
||||||
|
|
||||||
CDependencyTree* CWorld::BuildDependencyTree() const
|
CDependencyTree* CWorld::BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
CDependencyTree *pTree = new CDependencyTree();
|
||||||
|
|
||||||
for (u32 iArea = 0; iArea < mAreas.size(); iArea++)
|
for (u32 iArea = 0; iArea < mAreas.size(); iArea++)
|
||||||
{
|
{
|
||||||
|
@ -81,10 +81,11 @@ TString CWorld::AreaInGameName(u32 AreaIndex) const
|
||||||
// ************ SERIALIZATION ************
|
// ************ SERIALIZATION ************
|
||||||
void CWorld::Serialize(IArchive& rArc)
|
void CWorld::Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
rArc << SERIAL("WorldNameString", mpWorldName);
|
rArc << SERIAL("Name", mName)
|
||||||
|
<< SERIAL("NameString", mpWorldName);
|
||||||
|
|
||||||
if (rArc.Game() == eEchoesDemo || rArc.Game() == eEchoes)
|
if (rArc.Game() == eEchoesDemo || rArc.Game() == eEchoes)
|
||||||
rArc << SERIAL("DarkWorldNameString", mpDarkWorldName);
|
rArc << SERIAL("DarkNameString", mpDarkWorldName);
|
||||||
|
|
||||||
rArc << SERIAL("WorldSaveInfo", mpSaveWorld)
|
rArc << SERIAL("WorldSaveInfo", mpSaveWorld)
|
||||||
<< SERIAL("WorldMap", mpMapWorld)
|
<< SERIAL("WorldMap", mpMapWorld)
|
||||||
|
|
|
@ -14,6 +14,7 @@ class CWorld : public CResource
|
||||||
friend class CWorldCooker;
|
friend class CWorldCooker;
|
||||||
|
|
||||||
// Instances of CResource pointers are placeholders for unimplemented resource types (eg CMapWorld)
|
// Instances of CResource pointers are placeholders for unimplemented resource types (eg CMapWorld)
|
||||||
|
TString mName;
|
||||||
TResPtr<CStringTable> mpWorldName;
|
TResPtr<CStringTable> mpWorldName;
|
||||||
TResPtr<CStringTable> mpDarkWorldName;
|
TResPtr<CStringTable> mpDarkWorldName;
|
||||||
TResPtr<CResource> mpSaveWorld;
|
TResPtr<CResource> mpSaveWorld;
|
||||||
|
@ -93,8 +94,9 @@ public:
|
||||||
friend void Serialize(IArchive& rArc, SAudioGrp& rAudioGrp);
|
friend void Serialize(IArchive& rArc, SAudioGrp& rAudioGrp);
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
inline CStringTable* WorldName() const { return mpWorldName; }
|
inline TString Name() const { return mName; }
|
||||||
inline CStringTable* DarkWorldName() const { return mpDarkWorldName; }
|
inline CStringTable* NameString() const { return mpWorldName; }
|
||||||
|
inline CStringTable* DarkNameString() const { return mpDarkWorldName; }
|
||||||
inline CResource* SaveWorld() const { return mpSaveWorld; }
|
inline CResource* SaveWorld() const { return mpSaveWorld; }
|
||||||
inline CModel* DefaultSkybox() const { return mpDefaultSkybox; }
|
inline CModel* DefaultSkybox() const { return mpDefaultSkybox; }
|
||||||
inline CResource* MapWorld() const { return mpMapWorld; }
|
inline CResource* MapWorld() const { return mpMapWorld; }
|
||||||
|
@ -107,6 +109,7 @@ public:
|
||||||
inline CStringTable* AreaName(u32 AreaIndex) const { return mAreas[AreaIndex].pAreaName; }
|
inline CStringTable* AreaName(u32 AreaIndex) const { return mAreas[AreaIndex].pAreaName; }
|
||||||
inline bool DoesAreaAllowPakDuplicates(u32 AreaIndex) const { return mAreas[AreaIndex].AllowPakDuplicates; }
|
inline bool DoesAreaAllowPakDuplicates(u32 AreaIndex) const { return mAreas[AreaIndex].AllowPakDuplicates; }
|
||||||
|
|
||||||
|
inline void SetName(const TString& rkName) { mName = rkName; }
|
||||||
inline void SetAreaAllowsPakDuplicates(u32 AreaIndex, bool Allow) { mAreas[AreaIndex].AllowPakDuplicates = Allow; }
|
inline void SetAreaAllowsPakDuplicates(u32 AreaIndex, bool Allow) { mAreas[AreaIndex].AllowPakDuplicates = Allow; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
case eAnimEventData: return new CAnimEventData(pEntry);
|
case eAnimEventData: return new CAnimEventData(pEntry);
|
||||||
case eAnimSet: return new CAnimSet(pEntry);
|
case eAnimSet: return new CAnimSet(pEntry);
|
||||||
case eArea: return new CGameArea(pEntry);
|
case eArea: return new CGameArea(pEntry);
|
||||||
|
case eAudioMacro: return new CAudioMacro(pEntry);
|
||||||
case eAudioGroup: return new CAudioGroup(pEntry);
|
case eAudioGroup: return new CAudioGroup(pEntry);
|
||||||
case eAudioLookupTable: return new CAudioLookupTable(pEntry);
|
case eAudioLookupTable: return new CAudioLookupTable(pEntry);
|
||||||
case eCharacter: return new CAnimSet(pEntry);
|
case eCharacter: return new CAnimSet(pEntry);
|
||||||
|
@ -69,6 +70,7 @@ public:
|
||||||
case eAnimEventData: pRes = CAnimEventLoader::LoadEVNT(rInput, pEntry); break;
|
case eAnimEventData: pRes = CAnimEventLoader::LoadEVNT(rInput, pEntry); break;
|
||||||
case eAnimSet: pRes = CAnimSetLoader::LoadANCS(rInput, pEntry); break;
|
case eAnimSet: pRes = CAnimSetLoader::LoadANCS(rInput, pEntry); break;
|
||||||
case eArea: pRes = CAreaLoader::LoadMREA(rInput, pEntry); break;
|
case eArea: pRes = CAreaLoader::LoadMREA(rInput, pEntry); break;
|
||||||
|
case eAudioMacro: pRes = CUnsupportedFormatLoader::LoadCAUD(rInput, pEntry); break;
|
||||||
case eAudioGroup: pRes = CAudioGroupLoader::LoadAGSC(rInput, pEntry); break;
|
case eAudioGroup: pRes = CAudioGroupLoader::LoadAGSC(rInput, pEntry); break;
|
||||||
case eAudioLookupTable: pRes = CAudioGroupLoader::LoadATBL(rInput, pEntry); break;
|
case eAudioLookupTable: pRes = CAudioGroupLoader::LoadATBL(rInput, pEntry); break;
|
||||||
case eBinaryData: pRes = CUnsupportedFormatLoader::LoadDUMB(rInput, pEntry); break;
|
case eBinaryData: pRes = CUnsupportedFormatLoader::LoadDUMB(rInput, pEntry); break;
|
||||||
|
|
|
@ -1,6 +1,53 @@
|
||||||
#include "CUnsupportedFormatLoader.h"
|
#include "CUnsupportedFormatLoader.h"
|
||||||
#include "Core/GameProject/CGameProject.h"
|
#include "Core/GameProject/CGameProject.h"
|
||||||
|
|
||||||
|
CAudioMacro* CUnsupportedFormatLoader::LoadCAUD(IInputStream& rCAUD, CResourceEntry *pEntry)
|
||||||
|
{
|
||||||
|
u32 Magic = rCAUD.ReadLong();
|
||||||
|
ASSERT(Magic == FOURCC('CAUD'));
|
||||||
|
|
||||||
|
u32 Version = rCAUD.ReadLong();
|
||||||
|
EGame Game = (Version == 0x2 ? eCorruptionProto :
|
||||||
|
Version == 0x9 ? eCorruption :
|
||||||
|
Version == 0xE ? eReturns :
|
||||||
|
eUnknownGame);
|
||||||
|
ASSERT(Game != eUnknownGame && Game == pEntry->Game());
|
||||||
|
|
||||||
|
CAudioMacro *pMacro = new CAudioMacro(pEntry);
|
||||||
|
pMacro->mMacroName = rCAUD.ReadString();
|
||||||
|
|
||||||
|
// DKCR needs some reverse engineering work still in order to parse the file correctly, unfortunately
|
||||||
|
if (Game == eReturns)
|
||||||
|
{
|
||||||
|
Log::Warning("DKCR CAUD dependencies not being handled!");
|
||||||
|
return pMacro;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip past the rest of the header
|
||||||
|
u32 NumVolGroups = rCAUD.ReadLong();
|
||||||
|
|
||||||
|
for (u32 iVol = 0; iVol < NumVolGroups; iVol++)
|
||||||
|
rCAUD.ReadString();
|
||||||
|
|
||||||
|
u32 SkipAmt = (Game == eCorruptionProto ? 0x10 : 0x14);
|
||||||
|
rCAUD.Seek(SkipAmt, SEEK_CUR);
|
||||||
|
u32 NumSamples = rCAUD.ReadLong();
|
||||||
|
|
||||||
|
for (u32 iSamp = 0; iSamp < NumSamples; iSamp++)
|
||||||
|
{
|
||||||
|
u32 SampleDataSize = rCAUD.ReadLong();
|
||||||
|
u32 SampleDataEnd = rCAUD.Tell() + SampleDataSize;
|
||||||
|
|
||||||
|
CAssetID SampleID(rCAUD, Game);
|
||||||
|
ASSERT(gpResourceStore->IsResourceRegistered(SampleID) == true);
|
||||||
|
pMacro->mSamples.push_back(SampleID);
|
||||||
|
|
||||||
|
rCAUD.Seek(SampleDataEnd, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pMacro;
|
||||||
|
}
|
||||||
|
|
||||||
CDependencyGroup* CUnsupportedFormatLoader::LoadCSNG(IInputStream& rCSNG, CResourceEntry *pEntry)
|
CDependencyGroup* CUnsupportedFormatLoader::LoadCSNG(IInputStream& rCSNG, CResourceEntry *pEntry)
|
||||||
{
|
{
|
||||||
u32 Magic = rCSNG.ReadLong();
|
u32 Magic = rCSNG.ReadLong();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef CUNSUPPORTEDFORMATLOADER_H
|
#ifndef CUNSUPPORTEDFORMATLOADER_H
|
||||||
#define CUNSUPPORTEDFORMATLOADER_H
|
#define CUNSUPPORTEDFORMATLOADER_H
|
||||||
|
|
||||||
|
#include "Core/Resource/CAudioMacro.h"
|
||||||
#include "Core/Resource/CDependencyGroup.h"
|
#include "Core/Resource/CDependencyGroup.h"
|
||||||
|
|
||||||
// This class is responsible for loading formats that aren't yet fully supported.
|
// This class is responsible for loading formats that aren't yet fully supported.
|
||||||
|
@ -11,6 +12,7 @@ class CUnsupportedFormatLoader
|
||||||
CUnsupportedFormatLoader() {}
|
CUnsupportedFormatLoader() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static CAudioMacro* LoadCAUD(IInputStream& rCAUD, CResourceEntry *pEntry);
|
||||||
static CDependencyGroup* LoadCSNG(IInputStream& rCSNG, CResourceEntry *pEntry);
|
static CDependencyGroup* LoadCSNG(IInputStream& rCSNG, CResourceEntry *pEntry);
|
||||||
static CDependencyGroup* LoadDUMB(IInputStream& rDUMB, CResourceEntry *pEntry);
|
static CDependencyGroup* LoadDUMB(IInputStream& rDUMB, CResourceEntry *pEntry);
|
||||||
static CDependencyGroup* LoadFRME(IInputStream& rFRME, CResourceEntry *pEntry);
|
static CDependencyGroup* LoadFRME(IInputStream& rFRME, CResourceEntry *pEntry);
|
||||||
|
|
|
@ -32,7 +32,7 @@ CModel::~CModel()
|
||||||
|
|
||||||
CDependencyTree* CModel::BuildDependencyTree() const
|
CDependencyTree* CModel::BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
CDependencyTree *pTree = new CDependencyTree();
|
||||||
std::set<CAssetID> TextureIDs;
|
std::set<CAssetID> TextureIDs;
|
||||||
|
|
||||||
for (u32 iSet = 0; iSet < mMaterialSets.size(); iSet++)
|
for (u32 iSet = 0; iSet < mMaterialSets.size(); iSet++)
|
||||||
|
|
|
@ -1,233 +0,0 @@
|
||||||
#include "CStartWindow.h"
|
|
||||||
#include "ui_CStartWindow.h"
|
|
||||||
#include "CAboutDialog.h"
|
|
||||||
#include "CErrorLogDialog.h"
|
|
||||||
#include "CPakToolDialog.h"
|
|
||||||
#include "UICommon.h"
|
|
||||||
|
|
||||||
#include "Editor/ModelEditor/CModelEditorWindow.h"
|
|
||||||
#include "Editor/WorldEditor/CWorldEditor.h"
|
|
||||||
#include <Core/GameProject/CResourceStore.h>
|
|
||||||
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QProcess>
|
|
||||||
|
|
||||||
CStartWindow::CStartWindow(QWidget *parent)
|
|
||||||
: QMainWindow(parent)
|
|
||||||
, ui(new Ui::CStartWindow)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
REPLACE_WINDOWTITLE_APPVARS;
|
|
||||||
|
|
||||||
mpWorld = nullptr;
|
|
||||||
mpWorldEditor = new CWorldEditor(0);
|
|
||||||
|
|
||||||
connect(ui->ActionAbout, SIGNAL(triggered()), this, SLOT(About()));
|
|
||||||
connect(ui->ActionCharacterEditor, SIGNAL(triggered()), this, SLOT(LaunchCharacterEditor()));
|
|
||||||
}
|
|
||||||
|
|
||||||
CStartWindow::~CStartWindow()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
delete mpWorldEditor;
|
|
||||||
delete mpModelEditor;
|
|
||||||
delete mpCharEditor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::closeEvent(QCloseEvent *pEvent)
|
|
||||||
{
|
|
||||||
if (mpWorldEditor->close())
|
|
||||||
qApp->quit();
|
|
||||||
else
|
|
||||||
pEvent->ignore();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::on_actionOpen_MLVL_triggered()
|
|
||||||
{
|
|
||||||
QString WorldFile = QFileDialog::getOpenFileName(this, "Open MLVL", "", "Metroid Prime World (*.MLVL)");
|
|
||||||
if (WorldFile.isEmpty()) return;
|
|
||||||
|
|
||||||
if (mpWorldEditor->close())
|
|
||||||
{
|
|
||||||
TString Dir = TO_TSTRING(WorldFile).GetFileDirectory();
|
|
||||||
gpResourceStore->SetTransientLoadDir(Dir);
|
|
||||||
mpWorld = gpResourceStore->LoadResource(WorldFile.toStdString());
|
|
||||||
|
|
||||||
QString QStrDir = TO_QSTRING(Dir);
|
|
||||||
mpWorldEditor->SetWorldDir(QStrDir);
|
|
||||||
mpWorldEditor->SetPakFileList(CPakToolDialog::TargetListForFolder(QStrDir));
|
|
||||||
mpWorldEditor->SetPakTarget(CPakToolDialog::TargetPakForFolder(QStrDir));
|
|
||||||
|
|
||||||
FillWorldUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::FillWorldUI()
|
|
||||||
{
|
|
||||||
CStringTable *pWorldName = mpWorld->WorldName();
|
|
||||||
if (pWorldName)
|
|
||||||
{
|
|
||||||
TWideString WorldName = pWorldName->String("ENGL", 0);
|
|
||||||
ui->WorldNameLabel->setText( QString("<font size=5><b>") + TO_QSTRING(WorldName) + QString("</b></font>") );
|
|
||||||
ui->WorldNameSTRGLineEdit->setText(TO_QSTRING(pWorldName->Source()));
|
|
||||||
|
|
||||||
// hack to get around lack of UTF16 -> UTF8 support
|
|
||||||
TString WorldNameTStr = TO_TSTRING(QString::fromStdWString(WorldName.ToStdString()));
|
|
||||||
Log::Write("Loaded " + mpWorld->Source() + " (" + WorldNameTStr + ")");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ui->WorldNameLabel->clear();
|
|
||||||
ui->WorldNameSTRGLineEdit->clear();
|
|
||||||
Log::Write("Loaded " + mpWorld->Source() + " (unnamed world)");
|
|
||||||
}
|
|
||||||
|
|
||||||
CStringTable *pDarkWorldName = mpWorld->DarkWorldName();
|
|
||||||
if (pDarkWorldName)
|
|
||||||
ui->DarkWorldNameSTRGLineEdit->setText(TO_QSTRING(pDarkWorldName->Source()));
|
|
||||||
else
|
|
||||||
ui->DarkWorldNameSTRGLineEdit->clear();
|
|
||||||
|
|
||||||
CModel *pDefaultSkybox = mpWorld->DefaultSkybox();
|
|
||||||
if (pDefaultSkybox)
|
|
||||||
ui->DefaultSkyboxCMDLLineEdit->setText(TO_QSTRING(pDefaultSkybox->Source()));
|
|
||||||
else
|
|
||||||
ui->DefaultSkyboxCMDLLineEdit->clear();
|
|
||||||
|
|
||||||
CResource *pSaveWorld = mpWorld->SaveWorld();
|
|
||||||
if (pSaveWorld)
|
|
||||||
ui->WorldSAVWLineEdit->setText(TO_QSTRING(pSaveWorld->Source()));
|
|
||||||
else
|
|
||||||
ui->WorldSAVWLineEdit->clear();
|
|
||||||
|
|
||||||
CResource *pMapWorld = mpWorld->MapWorld();
|
|
||||||
if (pMapWorld)
|
|
||||||
ui->WorldMAPWLineEdit->setText(TO_QSTRING(pMapWorld->Source()));
|
|
||||||
else
|
|
||||||
ui->WorldMAPWLineEdit->clear();
|
|
||||||
|
|
||||||
u32 NumAreas = mpWorld->NumAreas();
|
|
||||||
ui->AreaSelectComboBox->blockSignals(true);
|
|
||||||
ui->AreaSelectComboBox->clear();
|
|
||||||
ui->AreaSelectComboBox->blockSignals(false);
|
|
||||||
ui->AreaSelectComboBox->setDisabled(false);
|
|
||||||
|
|
||||||
for (u32 iArea = 0; iArea < NumAreas; iArea++)
|
|
||||||
{
|
|
||||||
CStringTable *pAreaName = mpWorld->AreaName(iArea);
|
|
||||||
QString AreaName = (pAreaName != nullptr) ? TO_QSTRING(pAreaName->String("ENGL", 0)) : QString("!!") + TO_QSTRING(mpWorld->AreaInternalName(iArea));
|
|
||||||
ui->AreaSelectComboBox->addItem(AreaName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::FillAreaUI()
|
|
||||||
{
|
|
||||||
ui->AreaNameLineEdit->setDisabled(false);
|
|
||||||
ui->AreaNameSTRGLineEdit->setDisabled(false);
|
|
||||||
ui->AreaMREALineEdit->setDisabled(false);
|
|
||||||
ui->AttachedAreasList->setDisabled(false);
|
|
||||||
|
|
||||||
ui->AreaSelectComboBox->blockSignals(true);
|
|
||||||
ui->AreaSelectComboBox->setCurrentIndex(mSelectedAreaIndex);
|
|
||||||
ui->AreaSelectComboBox->blockSignals(false);
|
|
||||||
|
|
||||||
ui->AreaNameLineEdit->setText(TO_QSTRING(mpWorld->AreaInternalName(mSelectedAreaIndex)));
|
|
||||||
|
|
||||||
CStringTable *pAreaName = mpWorld->AreaName(mSelectedAreaIndex);
|
|
||||||
if (pAreaName)
|
|
||||||
ui->AreaNameSTRGLineEdit->setText(TO_QSTRING(pAreaName->Source()));
|
|
||||||
else
|
|
||||||
ui->AreaNameSTRGLineEdit->clear();
|
|
||||||
|
|
||||||
CAssetID MREA = mpWorld->AreaResourceID(mSelectedAreaIndex);
|
|
||||||
ui->AreaMREALineEdit->setText(TO_QSTRING(MREA.ToString()) + QString(".MREA"));
|
|
||||||
|
|
||||||
u32 NumAttachedAreas = mpWorld->AreaAttachedCount(mSelectedAreaIndex);
|
|
||||||
ui->AttachedAreasList->clear();
|
|
||||||
|
|
||||||
for (u32 iArea = 0; iArea < NumAttachedAreas; iArea++)
|
|
||||||
{
|
|
||||||
u32 AttachedAreaIndex = mpWorld->AreaAttachedID(mSelectedAreaIndex, iArea);
|
|
||||||
|
|
||||||
CStringTable *AttachedAreaSTRG = mpWorld->AreaName(AttachedAreaIndex);
|
|
||||||
QString AttachedStr;
|
|
||||||
|
|
||||||
if (AttachedAreaSTRG)
|
|
||||||
AttachedStr = TO_QSTRING(AttachedAreaSTRG->String("ENGL", 0));
|
|
||||||
else
|
|
||||||
AttachedStr = QString("!") + TO_QSTRING(mpWorld->AreaInternalName(AttachedAreaIndex));
|
|
||||||
|
|
||||||
ui->AttachedAreasList->addItem(AttachedStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->LaunchWorldEditorButton->setDisabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::on_AreaSelectComboBox_currentIndexChanged(int Index)
|
|
||||||
{
|
|
||||||
mSelectedAreaIndex = Index;
|
|
||||||
FillAreaUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::on_AttachedAreasList_doubleClicked(const QModelIndex& rkIndex)
|
|
||||||
{
|
|
||||||
mSelectedAreaIndex = mpWorld->AreaAttachedID(mSelectedAreaIndex, rkIndex.row());
|
|
||||||
FillAreaUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::on_LaunchWorldEditorButton_clicked()
|
|
||||||
{
|
|
||||||
if (mpWorldEditor->CheckUnsavedChanges())
|
|
||||||
{
|
|
||||||
Log::ClearErrorLog();
|
|
||||||
|
|
||||||
mpWorldEditor->SetArea(mpWorld, mSelectedAreaIndex);
|
|
||||||
gpResourceStore->DestroyUnreferencedResources();
|
|
||||||
|
|
||||||
mpWorldEditor->setWindowModality(Qt::WindowModal);
|
|
||||||
mpWorldEditor->showMaximized();
|
|
||||||
|
|
||||||
// Display errors
|
|
||||||
CErrorLogDialog ErrorDialog(mpWorldEditor);
|
|
||||||
bool HasErrors = ErrorDialog.GatherErrors();
|
|
||||||
|
|
||||||
if (HasErrors)
|
|
||||||
ErrorDialog.exec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::on_actionLaunch_model_viewer_triggered()
|
|
||||||
{
|
|
||||||
mpModelEditor->setWindowModality(Qt::ApplicationModal);
|
|
||||||
mpModelEditor->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::on_actionExtract_PAK_triggered()
|
|
||||||
{
|
|
||||||
QString Pak = QFileDialog::getOpenFileName(this, "Select pak", "", "Package (*.pak)");
|
|
||||||
|
|
||||||
if (!Pak.isEmpty())
|
|
||||||
{
|
|
||||||
CPakToolDialog::EResult Result = CPakToolDialog::Extract(Pak, 0, this);
|
|
||||||
|
|
||||||
if (Result == CPakToolDialog::eSuccess)
|
|
||||||
Result = CPakToolDialog::DumpList(Pak, 0, this);
|
|
||||||
|
|
||||||
if (Result == CPakToolDialog::eSuccess)
|
|
||||||
QMessageBox::information(this, "Success", "Extracted pak successfully!");
|
|
||||||
else if (Result == CPakToolDialog::eError)
|
|
||||||
QMessageBox::warning(this, "Error", "Unable to extract pak.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::LaunchCharacterEditor()
|
|
||||||
{
|
|
||||||
mpCharEditor->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStartWindow::About()
|
|
||||||
{
|
|
||||||
CAboutDialog Dialog(this);
|
|
||||||
Dialog.exec();
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
#ifndef PWESTARTWINDOW_H
|
|
||||||
#define PWESTARTWINDOW_H
|
|
||||||
|
|
||||||
#include "WorldEditor/CWorldEditor.h"
|
|
||||||
#include "ModelEditor/CModelEditorWindow.h"
|
|
||||||
#include "CharacterEditor/CCharacterEditor.h"
|
|
||||||
#include <Core/GameProject/CResourceStore.h>
|
|
||||||
#include <Core/Resource/CWorld.h>
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class CStartWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CStartWindow : public QMainWindow
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Ui::CStartWindow *ui;
|
|
||||||
|
|
||||||
TResPtr<CWorld> mpWorld;
|
|
||||||
u32 mSelectedAreaIndex;
|
|
||||||
|
|
||||||
CWorldEditor *mpWorldEditor;
|
|
||||||
CModelEditorWindow *mpModelEditor;
|
|
||||||
CCharacterEditor *mpCharEditor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit CStartWindow(QWidget *pParent = 0);
|
|
||||||
~CStartWindow();
|
|
||||||
void closeEvent(QCloseEvent *pEvent);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_actionOpen_MLVL_triggered();
|
|
||||||
void on_AreaSelectComboBox_currentIndexChanged(int Index);
|
|
||||||
void on_AttachedAreasList_doubleClicked(const QModelIndex& rkIndex);
|
|
||||||
void on_LaunchWorldEditorButton_clicked();
|
|
||||||
void on_actionLaunch_model_viewer_triggered();
|
|
||||||
void on_actionExtract_PAK_triggered();
|
|
||||||
|
|
||||||
void LaunchCharacterEditor();
|
|
||||||
void About();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void FillWorldUI();
|
|
||||||
void FillAreaUI();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PWESTARTWINDOW_H
|
|
|
@ -1,283 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>CStartWindow</class>
|
|
||||||
<widget class="QMainWindow" name="CStartWindow">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>327</width>
|
|
||||||
<height>487</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>%APP_FULL_NAME%</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="centralwidget">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="WorldNameLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="WorldGroupBox">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
|
||||||
<string>World</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="WorldNameSTRGLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>World Name STRG</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="WorldNameSTRGLineEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="DarkWorldNameSTRGLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Dark World Name STRG</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLineEdit" name="DarkWorldNameSTRGLineEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="DefaultSkyboxCMDLLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Default Skybox CMDL</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLineEdit" name="DefaultSkyboxCMDLLineEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="WorldSAVWLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>World SAVW</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLineEdit" name="WorldSAVWLineEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="WorldMAPWLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>World MAPW</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLineEdit" name="WorldMAPWLineEdit"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="AreaGroupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Area</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="AreaSelectComboBox">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout_2">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="AreaNameLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Area Name</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="AreaNameLineEdit">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="AreaNameSTRGLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Area Name STRG</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLineEdit" name="AreaNameSTRGLineEdit">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="AreaMREALabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Area MREA</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLineEdit" name="AreaMREALineEdit">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
|
||||||
<property name="sizeConstraint">
|
|
||||||
<enum>QLayout::SetDefaultConstraint</enum>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="AttachedAreasLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Attached Areas</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QListWidget" name="AttachedAreasList">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="LaunchWorldEditorButton">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch World Editor</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QMenuBar" name="menubar">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>327</width>
|
|
||||||
<height>21</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<widget class="QMenu" name="menuFile">
|
|
||||||
<property name="title">
|
|
||||||
<string>File</string>
|
|
||||||
</property>
|
|
||||||
<addaction name="actionOpen_MLVL"/>
|
|
||||||
<addaction name="actionExtract_PAK"/>
|
|
||||||
<addaction name="ActionExportGame"/>
|
|
||||||
</widget>
|
|
||||||
<widget class="QMenu" name="menuTools">
|
|
||||||
<property name="title">
|
|
||||||
<string>Tools</string>
|
|
||||||
</property>
|
|
||||||
<addaction name="actionLaunch_model_viewer"/>
|
|
||||||
<addaction name="ActionCharacterEditor"/>
|
|
||||||
</widget>
|
|
||||||
<widget class="QMenu" name="menuHelp">
|
|
||||||
<property name="title">
|
|
||||||
<string>Help</string>
|
|
||||||
</property>
|
|
||||||
<addaction name="ActionAbout"/>
|
|
||||||
</widget>
|
|
||||||
<addaction name="menuFile"/>
|
|
||||||
<addaction name="menuTools"/>
|
|
||||||
<addaction name="menuHelp"/>
|
|
||||||
</widget>
|
|
||||||
<action name="actionOpen_pak">
|
|
||||||
<property name="text">
|
|
||||||
<string>Create new...</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionOpen_MLVL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Open</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionExtract_PAK">
|
|
||||||
<property name="text">
|
|
||||||
<string>Extract PAK</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionLaunch_model_viewer">
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch model editor</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="ActionAbout">
|
|
||||||
<property name="text">
|
|
||||||
<string>About</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="ActionCharacterEditor">
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch character editor</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="ActionExportGame">
|
|
||||||
<property name="text">
|
|
||||||
<string>Export Game</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
|
@ -125,7 +125,6 @@ HEADERS += \
|
||||||
CGizmo.h \
|
CGizmo.h \
|
||||||
CNodeSelection.h \
|
CNodeSelection.h \
|
||||||
CSceneViewport.h \
|
CSceneViewport.h \
|
||||||
CStartWindow.h \
|
|
||||||
INodeEditor.h \
|
INodeEditor.h \
|
||||||
TestDialog.h \
|
TestDialog.h \
|
||||||
UICommon.h \
|
UICommon.h \
|
||||||
|
@ -212,7 +211,6 @@ SOURCES += \
|
||||||
CBasicViewport.cpp \
|
CBasicViewport.cpp \
|
||||||
CGizmo.cpp \
|
CGizmo.cpp \
|
||||||
CSceneViewport.cpp \
|
CSceneViewport.cpp \
|
||||||
CStartWindow.cpp \
|
|
||||||
INodeEditor.cpp \
|
INodeEditor.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
TestDialog.cpp \
|
TestDialog.cpp \
|
||||||
|
@ -255,7 +253,6 @@ SOURCES += \
|
||||||
|
|
||||||
# UI Files
|
# UI Files
|
||||||
FORMS += \
|
FORMS += \
|
||||||
CStartWindow.ui \
|
|
||||||
TestDialog.ui \
|
TestDialog.ui \
|
||||||
ModelEditor/CModelEditorWindow.ui \
|
ModelEditor/CModelEditorWindow.ui \
|
||||||
Widgets/WScanPreviewPanel.ui \
|
Widgets/WScanPreviewPanel.ui \
|
||||||
|
|
|
@ -80,7 +80,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
||||||
|
|
||||||
QAction *pGenerateAssetNamesAction = new QAction("Generate Asset Names", this);
|
QAction *pGenerateAssetNamesAction = new QAction("Generate Asset Names", this);
|
||||||
pImportNamesMenu->addAction(pGenerateAssetNamesAction);
|
pImportNamesMenu->addAction(pGenerateAssetNamesAction);
|
||||||
#if !PUBLIC_RELEASE
|
#if PUBLIC_RELEASE
|
||||||
pGenerateAssetNamesAction->setVisible(false);
|
pGenerateAssetNamesAction->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -315,6 +315,7 @@ void CResourceBrowser::OnImportPakContentsTxt()
|
||||||
{
|
{
|
||||||
QStringList PathList = UICommon::OpenFilesDialog(this, "Open pak contents list", "*.pak.contents.txt");
|
QStringList PathList = UICommon::OpenFilesDialog(this, "Open pak contents list", "*.pak.contents.txt");
|
||||||
if (PathList.isEmpty()) return;
|
if (PathList.isEmpty()) return;
|
||||||
|
SelectDirectory(nullptr);
|
||||||
|
|
||||||
foreach(const QString& rkPath, PathList)
|
foreach(const QString& rkPath, PathList)
|
||||||
mpStore->ImportNamesFromPakContentsTxt(TO_TSTRING(rkPath), false);
|
mpStore->ImportNamesFromPakContentsTxt(TO_TSTRING(rkPath), false);
|
||||||
|
@ -325,6 +326,7 @@ void CResourceBrowser::OnImportPakContentsTxt()
|
||||||
|
|
||||||
void CResourceBrowser::OnGenerateAssetNames()
|
void CResourceBrowser::OnGenerateAssetNames()
|
||||||
{
|
{
|
||||||
|
SelectDirectory(nullptr);
|
||||||
GenerateAssetNames(mpStore->Project());
|
GenerateAssetNames(mpStore->Project());
|
||||||
RefreshResources();
|
RefreshResources();
|
||||||
RefreshDirectories();
|
RefreshDirectories();
|
||||||
|
@ -346,6 +348,8 @@ void CResourceBrowser::OnImportNamesFromAssetNameMap()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SelectDirectory(nullptr);
|
||||||
|
|
||||||
for (CResourceIterator It(mpStore); It; ++It)
|
for (CResourceIterator It(mpStore); It; ++It)
|
||||||
{
|
{
|
||||||
TString Dir, Name;
|
TString Dir, Name;
|
||||||
|
|
|
@ -87,6 +87,9 @@ public:
|
||||||
|
|
||||||
QModelIndex GetIndexForDirectory(CVirtualDirectory *pDir)
|
QModelIndex GetIndexForDirectory(CVirtualDirectory *pDir)
|
||||||
{
|
{
|
||||||
|
if (!pDir)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
QVector<int> Indices;
|
QVector<int> Indices;
|
||||||
CVirtualDirectory *pOriginal = pDir;
|
CVirtualDirectory *pOriginal = pDir;
|
||||||
CVirtualDirectory *pParent = pDir->Parent();
|
CVirtualDirectory *pParent = pDir->Parent();
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
#define TYPES_NODE_TYPE_SHIFT 1
|
#define TYPES_NODE_TYPE_SHIFT 1
|
||||||
#define TYPES_ITEM_TYPE_SHIFT 0
|
#define TYPES_ITEM_TYPE_SHIFT 0
|
||||||
|
|
||||||
CInstancesModel::CInstancesModel(QObject *pParent)
|
CInstancesModel::CInstancesModel(CWorldEditor *pEditor, QObject *pParent)
|
||||||
: QAbstractItemModel(pParent)
|
: QAbstractItemModel(pParent)
|
||||||
, mpEditor(nullptr)
|
, mpEditor(pEditor)
|
||||||
, mpScene(nullptr)
|
, mpScene(pEditor->Scene())
|
||||||
, mpArea(nullptr)
|
, mpArea(nullptr)
|
||||||
, mpCurrentMaster(nullptr)
|
, mpCurrentMaster(nullptr)
|
||||||
, mModelType(eLayers)
|
, mModelType(eLayers)
|
||||||
|
@ -37,6 +37,16 @@ CInstancesModel::CInstancesModel(QObject *pParent)
|
||||||
, mChangingLayout(false)
|
, mChangingLayout(false)
|
||||||
{
|
{
|
||||||
mBaseItems << "Script";
|
mBaseItems << "Script";
|
||||||
|
|
||||||
|
connect(gpEdApp, SIGNAL(ActiveProjectChanged(CGameProject*)), this, SLOT(OnActiveProjectChanged(CGameProject*)));
|
||||||
|
connect(mpEditor, SIGNAL(MapChanged(CWorld*,CGameArea*)), this, SLOT(OnMapChange()));
|
||||||
|
connect(mpEditor, SIGNAL(NodeAboutToBeSpawned()), this, SLOT(NodeAboutToBeCreated()));
|
||||||
|
connect(mpEditor, SIGNAL(NodeSpawned(CSceneNode*)), this, SLOT(NodeCreated(CSceneNode*)));
|
||||||
|
connect(mpEditor, SIGNAL(NodeAboutToBeDeleted(CSceneNode*)), this, SLOT(NodeAboutToBeDeleted(CSceneNode*)));
|
||||||
|
connect(mpEditor, SIGNAL(NodeDeleted()), this, SLOT(NodeDeleted()));
|
||||||
|
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), this, SLOT(PropertyModified(CScriptObject*,IProperty*)));
|
||||||
|
connect(mpEditor, SIGNAL(InstancesLayerAboutToChange()), this, SLOT(InstancesLayerPreChange()));
|
||||||
|
connect(mpEditor, SIGNAL(InstancesLayerChanged(QList<CScriptNode*>)), this, SLOT(InstancesLayerPostChange(QList<CScriptNode*>)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CInstancesModel::~CInstancesModel()
|
CInstancesModel::~CInstancesModel()
|
||||||
|
@ -311,35 +321,6 @@ QVariant CInstancesModel::data(const QModelIndex& rkIndex, int Role) const
|
||||||
return QVariant::Invalid;
|
return QVariant::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInstancesModel::SetEditor(CWorldEditor *pEditor)
|
|
||||||
{
|
|
||||||
if (mpEditor)
|
|
||||||
disconnect(mpEditor, 0, this, 0);
|
|
||||||
|
|
||||||
mpEditor = pEditor;
|
|
||||||
mpScene = (pEditor ? pEditor->Scene() : nullptr);
|
|
||||||
connect(mpEditor, SIGNAL(NodeAboutToBeSpawned()), this, SLOT(NodeAboutToBeCreated()));
|
|
||||||
connect(mpEditor, SIGNAL(NodeSpawned(CSceneNode*)), this, SLOT(NodeCreated(CSceneNode*)));
|
|
||||||
connect(mpEditor, SIGNAL(NodeAboutToBeDeleted(CSceneNode*)), this, SLOT(NodeAboutToBeDeleted(CSceneNode*)));
|
|
||||||
connect(mpEditor, SIGNAL(NodeDeleted()), this, SLOT(NodeDeleted()));
|
|
||||||
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), this, SLOT(PropertyModified(CScriptObject*,IProperty*)));
|
|
||||||
connect(mpEditor, SIGNAL(InstancesLayerAboutToChange()), this, SLOT(InstancesLayerPreChange()));
|
|
||||||
connect(mpEditor, SIGNAL(InstancesLayerChanged(QList<CScriptNode*>)), this, SLOT(InstancesLayerPostChange(QList<CScriptNode*>)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CInstancesModel::SetMaster(CMasterTemplate *pMaster)
|
|
||||||
{
|
|
||||||
mpCurrentMaster = pMaster;
|
|
||||||
GenerateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CInstancesModel::SetArea(CGameArea *pArea)
|
|
||||||
{
|
|
||||||
beginResetModel();
|
|
||||||
mpArea = pArea;
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CInstancesModel::SetModelType(EInstanceModelType Type)
|
void CInstancesModel::SetModelType(EInstanceModelType Type)
|
||||||
{
|
{
|
||||||
mModelType = Type;
|
mModelType = Type;
|
||||||
|
@ -378,6 +359,35 @@ CScriptObject* CInstancesModel::IndexObject(const QModelIndex& rkIndex) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ PUBLIC SLOTS ************
|
// ************ PUBLIC SLOTS ************
|
||||||
|
void CInstancesModel::OnActiveProjectChanged(CGameProject *pProj)
|
||||||
|
{
|
||||||
|
if (mModelType == eTypes)
|
||||||
|
{
|
||||||
|
if (pProj)
|
||||||
|
{
|
||||||
|
EGame ProjGame = pProj->Game();
|
||||||
|
mpCurrentMaster = CMasterTemplate::MasterForGame(ProjGame);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mpCurrentMaster = nullptr;
|
||||||
|
|
||||||
|
GenerateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInstancesModel::OnMapChange()
|
||||||
|
{
|
||||||
|
if (mModelType == eTypes)
|
||||||
|
GenerateList();
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
mpArea = mpEditor->ActiveArea();
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CInstancesModel::NodeAboutToBeCreated()
|
void CInstancesModel::NodeAboutToBeCreated()
|
||||||
{
|
{
|
||||||
if (!mChangingLayout)
|
if (!mChangingLayout)
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
private:
|
private:
|
||||||
CWorldEditor *mpEditor;
|
CWorldEditor *mpEditor;
|
||||||
CScene *mpScene;
|
CScene *mpScene;
|
||||||
TResPtr<CGameArea> mpArea;
|
CGameArea *mpArea;
|
||||||
CMasterTemplate *mpCurrentMaster;
|
CMasterTemplate *mpCurrentMaster;
|
||||||
EInstanceModelType mModelType;
|
EInstanceModelType mModelType;
|
||||||
QList<CScriptTemplate*> mTemplateList;
|
QList<CScriptTemplate*> mTemplateList;
|
||||||
|
@ -43,7 +43,7 @@ private:
|
||||||
bool mChangingLayout;
|
bool mChangingLayout;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CInstancesModel(QObject *pParent = 0);
|
explicit CInstancesModel(CWorldEditor *pEditor, QObject *pParent = 0);
|
||||||
~CInstancesModel();
|
~CInstancesModel();
|
||||||
QVariant headerData(int Section, Qt::Orientation Orientation, int Role) const;
|
QVariant headerData(int Section, Qt::Orientation Orientation, int Role) const;
|
||||||
QModelIndex index(int Row, int Column, const QModelIndex& rkParent = QModelIndex()) const;
|
QModelIndex index(int Row, int Column, const QModelIndex& rkParent = QModelIndex()) const;
|
||||||
|
@ -52,9 +52,6 @@ public:
|
||||||
int columnCount(const QModelIndex& rkParent) const;
|
int columnCount(const QModelIndex& rkParent) const;
|
||||||
QVariant data(const QModelIndex& rkIndex, int Role) const;
|
QVariant data(const QModelIndex& rkIndex, int Role) const;
|
||||||
|
|
||||||
void SetEditor(CWorldEditor *pEditor);
|
|
||||||
void SetMaster(CMasterTemplate *pMaster);
|
|
||||||
void SetArea(CGameArea *pArea);
|
|
||||||
void SetModelType(EInstanceModelType Type);
|
void SetModelType(EInstanceModelType Type);
|
||||||
void SetShowColumnEnabled(bool Enabled);
|
void SetShowColumnEnabled(bool Enabled);
|
||||||
CScriptLayer* IndexLayer(const QModelIndex& rkIndex) const;
|
CScriptLayer* IndexLayer(const QModelIndex& rkIndex) const;
|
||||||
|
@ -62,6 +59,9 @@ public:
|
||||||
CScriptObject* IndexObject(const QModelIndex& rkIndex) const;
|
CScriptObject* IndexObject(const QModelIndex& rkIndex) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void OnActiveProjectChanged(CGameProject *pProj);
|
||||||
|
void OnMapChange();
|
||||||
|
|
||||||
void NodeAboutToBeCreated();
|
void NodeAboutToBeCreated();
|
||||||
void NodeCreated(CSceneNode *pNode);
|
void NodeCreated(CSceneNode *pNode);
|
||||||
void NodeAboutToBeDeleted(CSceneNode *pNode);
|
void NodeAboutToBeDeleted(CSceneNode *pNode);
|
||||||
|
|
|
@ -5,6 +5,8 @@ CSelectInstanceDialog::CSelectInstanceDialog(CWorldEditor *pEditor, QWidget *pPa
|
||||||
: QDialog(pParent)
|
: QDialog(pParent)
|
||||||
, ui(new Ui::CSelectInstanceDialog)
|
, ui(new Ui::CSelectInstanceDialog)
|
||||||
, mpEditor(pEditor)
|
, mpEditor(pEditor)
|
||||||
|
, mLayersModel(pEditor, this)
|
||||||
|
, mTypesModel(pEditor, this)
|
||||||
, mValidSelection(false)
|
, mValidSelection(false)
|
||||||
, mpLayersInst(nullptr)
|
, mpLayersInst(nullptr)
|
||||||
, mpTypesInst(nullptr)
|
, mpTypesInst(nullptr)
|
||||||
|
@ -12,14 +14,9 @@ CSelectInstanceDialog::CSelectInstanceDialog(CWorldEditor *pEditor, QWidget *pPa
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
mLayersModel.SetModelType(CInstancesModel::eLayers);
|
mLayersModel.SetModelType(CInstancesModel::eLayers);
|
||||||
mLayersModel.SetEditor(pEditor);
|
|
||||||
mLayersModel.SetArea(pEditor->ActiveArea());
|
|
||||||
mLayersModel.SetShowColumnEnabled(false);
|
mLayersModel.SetShowColumnEnabled(false);
|
||||||
|
|
||||||
mTypesModel.SetModelType(CInstancesModel::eTypes);
|
mTypesModel.SetModelType(CInstancesModel::eTypes);
|
||||||
mTypesModel.SetEditor(pEditor);
|
|
||||||
mTypesModel.SetArea(pEditor->ActiveArea());
|
|
||||||
mTypesModel.SetMaster(CMasterTemplate::MasterForGame(pEditor->CurrentGame()));
|
|
||||||
mTypesModel.SetShowColumnEnabled(false);
|
mTypesModel.SetShowColumnEnabled(false);
|
||||||
|
|
||||||
int Col0Width = ui->LayersTreeView->width() * 0.9;
|
int Col0Width = ui->LayersTreeView->width() * 0.9;
|
||||||
|
|
|
@ -254,6 +254,7 @@ bool CWorldEditor::CloseWorld()
|
||||||
|
|
||||||
mpArea = nullptr;
|
mpArea = nullptr;
|
||||||
mpWorld = nullptr;
|
mpWorld = nullptr;
|
||||||
|
gpResourceStore->DestroyUnreferencedResources(); // this should destroy the area!
|
||||||
|
|
||||||
emit MapChanged(mpWorld, mpArea);
|
emit MapChanged(mpWorld, mpArea);
|
||||||
return true;
|
return true;
|
||||||
|
@ -338,9 +339,6 @@ bool CWorldEditor::SetArea(CWorld *pWorld, int AreaIndex)
|
||||||
emit MapChanged(mpWorld, mpArea);
|
emit MapChanged(mpWorld, mpArea);
|
||||||
emit LayersModified();
|
emit LayersModified();
|
||||||
|
|
||||||
// Make sure old area is destroyed
|
|
||||||
gpResourceStore->DestroyUnreferencedResources();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,8 +94,8 @@ void CWorldInfoSidebar::OnWorldTreeClicked(QModelIndex Index)
|
||||||
CWorld *pWorld = mModel.WorldForIndex(RealIndex);
|
CWorld *pWorld = mModel.WorldForIndex(RealIndex);
|
||||||
mpUI->WorldNameLabel->setText( TO_QSTRING(pWorld->InGameName()) );
|
mpUI->WorldNameLabel->setText( TO_QSTRING(pWorld->InGameName()) );
|
||||||
mpUI->WorldSelector->SetResource(pWorld);
|
mpUI->WorldSelector->SetResource(pWorld);
|
||||||
mpUI->WorldNameSelector->SetResource(pWorld->WorldName());
|
mpUI->WorldNameSelector->SetResource(pWorld->NameString());
|
||||||
mpUI->DarkWorldNameSelector->SetResource(pWorld->DarkWorldName());
|
mpUI->DarkWorldNameSelector->SetResource(pWorld->DarkNameString());
|
||||||
mpUI->SkySelector->SetResource(pWorld->DefaultSkybox());
|
mpUI->SkySelector->SetResource(pWorld->DefaultSkybox());
|
||||||
|
|
||||||
// Fill in area info
|
// Fill in area info
|
||||||
|
|
|
@ -54,18 +54,23 @@ QVariant CWorldTreeModel::data(const QModelIndex& rkIndex, int Role) const
|
||||||
// World
|
// World
|
||||||
if (IndexIsWorld(rkIndex))
|
if (IndexIsWorld(rkIndex))
|
||||||
{
|
{
|
||||||
QString WorldAssetName = TO_QSTRING( pWorld->Entry()->Name() );
|
QString WorldName = TO_QSTRING( pWorld->Name() );
|
||||||
CStringTable *pWorldNameString = pWorld->WorldName();
|
CStringTable *pWorldNameString = pWorld->NameString();
|
||||||
|
|
||||||
if (rkIndex.column() == 1)
|
// For Corruption worlds, we swap the columns around. This is because Corruption's in-game world names
|
||||||
return WorldAssetName;
|
// are often missing, confusing, or just straight-up inaccurate, which makes the internal name a better
|
||||||
|
// means of telling worlds apart.
|
||||||
|
u32 InternalNameCol = (pWorld->Game() == eCorruption ? 0 : 1);
|
||||||
|
|
||||||
|
if (rkIndex.column() == InternalNameCol)
|
||||||
|
return WorldName;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (pWorldNameString)
|
if (pWorldNameString)
|
||||||
return TO_QSTRING( pWorldNameString->String("ENGL", 0) );
|
return TO_QSTRING( pWorldNameString->String("ENGL", 0) );
|
||||||
else
|
else
|
||||||
return WorldAssetName;
|
return WorldName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,6 +223,14 @@ void CWorldTreeModel::OnProjectChanged(CGameProject *pProj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort in alphabetical order for MP3
|
||||||
|
if (pProj->Game() == eCorruption)
|
||||||
|
{
|
||||||
|
qSort(mWorldList.begin(), mWorldList.end(), [](const SWorldInfo& rkLeft, const SWorldInfo& rkRight) -> bool {
|
||||||
|
return (rkLeft.pWorld->Name().ToUpper() < rkRight.pWorld->Name().ToUpper());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
|
@ -14,17 +14,17 @@ WInstancesTab::WInstancesTab(CWorldEditor *pEditor, QWidget *parent) :
|
||||||
|
|
||||||
mpEditor = pEditor;
|
mpEditor = pEditor;
|
||||||
mpScene = mpEditor->Scene();
|
mpScene = mpEditor->Scene();
|
||||||
connect(mpEditor, SIGNAL(MapChanged(CWorld*,CGameArea*)), this, SLOT(OnMapChange(CWorld*,CGameArea*)));
|
|
||||||
|
|
||||||
mpLayersModel = new CInstancesModel(this);
|
mpLayersModel = new CInstancesModel(pEditor, this);
|
||||||
mpLayersModel->SetModelType(CInstancesModel::eLayers);
|
mpLayersModel->SetModelType(CInstancesModel::eLayers);
|
||||||
mpLayersModel->SetEditor(mpEditor);
|
mpTypesModel = new CInstancesModel(pEditor, this);
|
||||||
mpTypesModel = new CInstancesModel(this);
|
|
||||||
mpTypesModel->SetModelType(CInstancesModel::eTypes);
|
mpTypesModel->SetModelType(CInstancesModel::eTypes);
|
||||||
mpTypesModel->SetEditor(mpEditor);
|
|
||||||
mLayersProxyModel.setSourceModel(mpLayersModel);
|
mLayersProxyModel.setSourceModel(mpLayersModel);
|
||||||
mTypesProxyModel.setSourceModel(mpTypesModel);
|
mTypesProxyModel.setSourceModel(mpTypesModel);
|
||||||
|
|
||||||
|
connect(mpLayersModel, SIGNAL(modelReset()), this, SLOT(ExpandTopLevelItems()));
|
||||||
|
connect(mpTypesModel, SIGNAL(modelReset()), this, SLOT(ExpandTopLevelItems()));
|
||||||
|
|
||||||
int ColWidth = ui->LayersTreeView->width() * 0.29;
|
int ColWidth = ui->LayersTreeView->width() * 0.29;
|
||||||
|
|
||||||
ui->LayersTreeView->setModel(&mLayersProxyModel);
|
ui->LayersTreeView->setModel(&mLayersProxyModel);
|
||||||
|
@ -79,15 +79,6 @@ WInstancesTab::~WInstancesTab()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ PRIVATE SLOTS ************
|
// ************ PRIVATE SLOTS ************
|
||||||
void WInstancesTab::OnMapChange(CWorld*, CGameArea *pNewArea)
|
|
||||||
{
|
|
||||||
EGame Game = mpEditor->CurrentGame();
|
|
||||||
CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(Game);
|
|
||||||
mpTypesModel->SetMaster(pMaster);
|
|
||||||
mpLayersModel->SetArea(pNewArea);
|
|
||||||
ExpandTopLevelItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WInstancesTab::OnTreeClick(QModelIndex Index)
|
void WInstancesTab::OnTreeClick(QModelIndex Index)
|
||||||
{
|
{
|
||||||
// Single click is used to process show/hide events
|
// Single click is used to process show/hide events
|
||||||
|
|
|
@ -47,7 +47,6 @@ public:
|
||||||
~WInstancesTab();
|
~WInstancesTab();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void OnMapChange(CWorld*, CGameArea *pNewArea);
|
|
||||||
void OnTreeClick(QModelIndex Index);
|
void OnTreeClick(QModelIndex Index);
|
||||||
void OnTreeDoubleClick(QModelIndex Index);
|
void OnTreeDoubleClick(QModelIndex Index);
|
||||||
|
|
||||||
|
|
|
@ -5453,7 +5453,7 @@
|
||||||
<property ID="0x7A6412F6" name="Unknown"/>
|
<property ID="0x7A6412F6" name="Unknown"/>
|
||||||
<property ID="0x7A64E529" name="Unknown"/>
|
<property ID="0x7A64E529" name="Unknown"/>
|
||||||
<property ID="0x7A6E0DE9" name="Unknown"/>
|
<property ID="0x7A6E0DE9" name="Unknown"/>
|
||||||
<property ID="0x7A6E3DDB" name="WeaponVulnerability"/>
|
<property ID="0x7A6E3DDB" name="Phazon (Charged)"/>
|
||||||
<property ID="0x7A74AA86" name="Unknown"/>
|
<property ID="0x7A74AA86" name="Unknown"/>
|
||||||
<property ID="0x7A797E4F" name="Unknown"/>
|
<property ID="0x7A797E4F" name="Unknown"/>
|
||||||
<property ID="0x7A7B330E" name="Unknown"/>
|
<property ID="0x7A7B330E" name="Unknown"/>
|
||||||
|
|
Loading…
Reference in New Issue