Fixed issues in MP3 package list building

This commit is contained in:
Aruki 2017-05-09 14:16:41 -06:00
parent f72f82d519
commit 560706d285
22 changed files with 269 additions and 48 deletions

View File

@ -33,9 +33,11 @@ CAssetID::CAssetID(u64 ID, EIDLength Length)
mID &= 0xFFFFFFFF;
}
void CAssetID::Write(IOutputStream& rOutput) const
void CAssetID::Write(IOutputStream& rOutput, EIDLength ForcedLength /*= eInvalidIDLength*/) const
{
if (mLength == e32Bit)
EIDLength Length = (ForcedLength == eInvalidIDLength ? mLength : ForcedLength);
if (Length == e32Bit)
rOutput.WriteLong(ToLong());
else
rOutput.WriteLongLong(ToLongLong());
@ -53,9 +55,11 @@ CAssetID::CAssetID(IInputStream& rInput, EGame Game)
*this = CAssetID(rInput, (Game <= eEchoes ? e32Bit : e64Bit));
}
TString CAssetID::ToString() const
TString CAssetID::ToString(EIDLength ForcedLength /*= eInvalidIDLength*/) const
{
if (mLength == e32Bit)
EIDLength Length = (ForcedLength == eInvalidIDLength ? mLength : ForcedLength);
if (Length == e32Bit)
return TString::HexString(ToLong(), 8, false, true);
else
return TString::FromInt64(ToLongLong(), 16, 16).ToUpper();

View File

@ -24,8 +24,8 @@ public:
CAssetID(u64 ID, EIDLength Length);
CAssetID(IInputStream& rInput, EIDLength Length);
CAssetID(IInputStream& rInput, EGame Game);
void Write(IOutputStream& rOutput) const;
TString ToString() const;
void Write(IOutputStream& rOutput, EIDLength ForcedLength = eInvalidIDLength) const;
TString ToString(EIDLength ForcedLength = eInvalidIDLength) const;
bool IsValid() const;
// Operators

View File

@ -68,7 +68,7 @@ public:
virtual void SerializePrimitive(TString& rValue) { mpStream->WriteSizedString(rValue); }
virtual void SerializePrimitive(TWideString& rValue) { mpStream->WriteSizedWideString(rValue); }
virtual void SerializePrimitive(CFourCC& rValue) { rValue.Write(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue) { rValue.Write(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue) { rValue.Write(*mpStream, CAssetID::GameIDLength(Game())); }
virtual void SerializeHexPrimitive(u8& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializeHexPrimitive(u16& rValue) { mpStream->WriteShort(rValue); }

View File

@ -120,7 +120,7 @@ public:
virtual void SerializePrimitive(TString& rValue) { mpStream->WriteSizedString(rValue); }
virtual void SerializePrimitive(TWideString& rValue) { mpStream->WriteSizedWideString(rValue); }
virtual void SerializePrimitive(CFourCC& rValue) { rValue.Write(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue) { rValue.Write(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue) { rValue.Write(*mpStream, CAssetID::GameIDLength(Game())); }
virtual void SerializeHexPrimitive(u8& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializeHexPrimitive(u16& rValue) { mpStream->WriteShort(rValue); }

View File

@ -116,7 +116,7 @@ public:
virtual void SerializePrimitive(TString& rValue) { WriteParam(*rValue); }
virtual void SerializePrimitive(TWideString& rValue) { WriteParam(*rValue.ToUTF8()); }
virtual void SerializePrimitive(CFourCC& rValue) { WriteParam(*rValue.ToString()); }
virtual void SerializePrimitive(CAssetID& rValue) { WriteParam(*rValue.ToString()); }
virtual void SerializePrimitive(CAssetID& rValue) { WriteParam(*rValue.ToString( CAssetID::GameIDLength(Game()) )); }
virtual void SerializeHexPrimitive(u8& rValue) { WriteParam(*TString::HexString(rValue, 2)); }
virtual void SerializeHexPrimitive(u16& rValue) { WriteParam(*TString::HexString(rValue, 4)); }

View File

@ -225,7 +225,8 @@ HEADERS += \
Resource/Cooker/CResourceCooker.h \
Resource/CAudioMacro.h \
CompressionUtil.h \
Resource/Animation/CSourceAnimData.h
Resource/Animation/CSourceAnimData.h \
Resource/CMapArea.h
# Source Files
SOURCES += \

View File

@ -143,6 +143,24 @@ CAssetID CGameProject::FindNamedResource(const TString& rkName) const
return CAssetID::InvalidID(mGame);
}
CPackage* CGameProject::FindPackage(const TString& rkName) const
{
if (mGame == eCorruptionProto || mGame == eCorruption)
{
for (u32 iPkg = 0; iPkg < mPackages.size(); iPkg++)
{
CPackage *pPackage = mPackages[iPkg];
if (pPackage->Name() == rkName)
{
return pPackage;
}
}
}
return nullptr;
}
CGameProject* CGameProject::CreateProjectForExport(
const TString& rkProjRootDir,
EGame Game,

View File

@ -67,6 +67,7 @@ public:
void Serialize(IArchive& rArc);
void GetWorldList(std::list<CAssetID>& rOut) const;
CAssetID FindNamedResource(const TString& rkName) const;
CPackage* FindPackage(const TString& rkName) const;
// Static
static CGameProject* CreateProjectForExport(

View File

@ -236,28 +236,56 @@ void CPackage::CompareOriginalAssetList(const std::list<CAssetID>& rkNewList)
return;
}
// Skip past header + named resources
// Determine pak version
u32 PakVersion = Pak.ReadLong();
ASSERT(PakVersion == 0x00030005);
Pak.Seek(0x4, SEEK_CUR);
u32 NumNamedResources = Pak.ReadLong();
for (u32 iName = 0; iName < NumNamedResources; iName++)
{
Pak.Seek(0x8, SEEK_CUR);
u32 NameLen = Pak.ReadLong();
Pak.Seek(NameLen, SEEK_CUR);
}
// Build a set out of the original pak resource list
u32 NumResources = Pak.ReadLong();
std::set<CAssetID> OldListSet;
for (u32 iRes = 0; iRes < NumResources; iRes++)
// Read MP1/2 pak
if (PakVersion == 0x00030005)
{
Pak.Seek(0x8, SEEK_CUR);
OldListSet.insert( CAssetID(Pak, e32Bit) );
Pak.Seek(0x8, SEEK_CUR);
Pak.Seek(0x4, SEEK_CUR);
u32 NumNamedResources = Pak.ReadLong();
for (u32 iName = 0; iName < NumNamedResources; iName++)
{
Pak.Seek(0x8, SEEK_CUR);
u32 NameLen = Pak.ReadLong();
Pak.Seek(NameLen, SEEK_CUR);
}
// Build a set out of the original pak resource list
u32 NumResources = Pak.ReadLong();
for (u32 iRes = 0; iRes < NumResources; iRes++)
{
Pak.Seek(0x8, SEEK_CUR);
OldListSet.insert( CAssetID(Pak, e32Bit) );
Pak.Seek(0x8, SEEK_CUR);
}
}
// Read MP3/DKCR pak
else
{
ASSERT(PakVersion == 0x2);
// Skip named resources
Pak.Seek(0x44, SEEK_SET);
CFourCC StringSecType = Pak.ReadLong();
u32 StringSecSize = Pak.ReadLong();
ASSERT(StringSecType == "STRG");
Pak.Seek(0x80 + StringSecSize, SEEK_SET);
// Read resource table
u32 NumResources = Pak.ReadLong();
for (u32 iRes = 0; iRes < NumResources; iRes++)
{
Pak.Seek(0x8, SEEK_CUR);
OldListSet.insert( CAssetID(Pak, e64Bit) );
Pak.Seek(0x8, SEEK_CUR);
}
}
// Check for missing resources in the new list

View File

@ -3,6 +3,7 @@
// ************ CCharacterUsageMap ************
bool CCharacterUsageMap::IsCharacterUsed(const CAssetID& rkID, u32 CharacterIndex) const
{
if (mpStore->Game() >= eCorruptionProto) return true;
auto Find = mUsageMap.find(rkID);
if (Find == mUsageMap.end()) return false;
@ -172,6 +173,7 @@ void CCharacterUsageMap::ParseDependencyNode(IDependencyNode *pNode)
void CPackageDependencyListBuilder::BuildDependencyList(bool AllowDuplicates, std::list<CAssetID>& rOut)
{
mEnableDuplicates = AllowDuplicates;
FindUniversalAreaAssets();
// Iterate over all resources and parse their dependencies
for (u32 iRes = 0; iRes < mpkPackage->NumNamedResources(); iRes++)
@ -186,6 +188,8 @@ void CPackageDependencyListBuilder::BuildDependencyList(bool AllowDuplicates, st
continue;
}
mIsUniversalAreaAsset = (mUniversalAreaAssets.find(rkRes.ID) != mUniversalAreaAssets.end());
if (rkRes.Type == "MLVL")
{
mpWorld = (CWorld*) pEntry->Load();
@ -217,7 +221,8 @@ void CPackageDependencyListBuilder::AddDependency(CResourceEntry *pCurEntry, con
if (!IsValid) return;
if ( ( mCurrentAreaHasDuplicates && mAreaUsedAssets.find(rkID) != mAreaUsedAssets.end()) ||
(!mCurrentAreaHasDuplicates && mPackageUsedAssets.find(rkID) != mPackageUsedAssets.end()) )
(!mCurrentAreaHasDuplicates && mPackageUsedAssets.find(rkID) != mPackageUsedAssets.end()) ||
(!mIsUniversalAreaAsset && mUniversalAreaAssets.find(rkID) != mUniversalAreaAssets.end() ) )
return;
// Entry is valid, parse its sub-dependencies
@ -258,6 +263,10 @@ void CPackageDependencyListBuilder::AddDependency(CResourceEntry *pCurEntry, con
// Revert current animset ID
if (ResType == eAnimSet)
mCurrentAnimSetID = CAssetID::InvalidID(mGame);
// Revert duplicate flag
else if (ResType == eArea)
mCurrentAreaHasDuplicates = false;
}
void CPackageDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurEntry, IDependencyNode *pNode, std::list<CAssetID>& rOut)
@ -316,6 +325,58 @@ void CPackageDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurE
}
}
void CPackageDependencyListBuilder::FindUniversalAreaAssets()
{
CGameProject *pProject = mpStore->Project();
CPackage *pPackage = pProject->FindPackage("UniverseArea");
if (pPackage)
{
// Iterate over all the package contents, keep track of all universal area assets
for (u32 ResIdx = 0; ResIdx < pPackage->NumNamedResources(); ResIdx++)
{
const SNamedResource& rkRes = pPackage->NamedResourceByIndex(ResIdx);
if (rkRes.ID.IsValid())
{
mUniversalAreaAssets.insert(rkRes.ID);
// For the universal area world, load it into memory to make sure we can exclude the area/map IDs
if (rkRes.Type == "MLVL")
{
CWorld *pUniverseWorld = gpResourceStore->LoadResource<CWorld>(rkRes.ID);
if (pUniverseWorld)
{
// Area IDs
for (u32 AreaIdx = 0; AreaIdx < pUniverseWorld->NumAreas(); AreaIdx++)
{
CAssetID AreaID = pUniverseWorld->AreaResourceID(AreaIdx);
if (AreaID.IsValid())
mUniversalAreaAssets.insert(AreaID);
}
// Map IDs
CDependencyGroup *pMapWorld = (CDependencyGroup*) pUniverseWorld->MapWorld();
if (pMapWorld)
{
for (u32 DepIdx = 0; DepIdx < pMapWorld->NumDependencies(); DepIdx++)
{
CAssetID DepID = pMapWorld->DependencyByIndex(DepIdx);
if (DepID.IsValid())
mUniversalAreaAssets.insert(DepID);
}
}
}
}
}
}
}
}
// ************ CAreaDependencyListBuilder ************
void CAreaDependencyListBuilder::BuildDependencyList(std::list<CAssetID>& rAssetsOut, std::list<u32>& rLayerOffsetsOut, std::set<CAssetID> *pAudioGroupsOut)
{

View File

@ -46,8 +46,10 @@ class CPackageDependencyListBuilder
CCharacterUsageMap mCharacterUsageMap;
std::set<CAssetID> mPackageUsedAssets;
std::set<CAssetID> mAreaUsedAssets;
std::set<CAssetID> mUniversalAreaAssets;
bool mEnableDuplicates;
bool mCurrentAreaHasDuplicates;
bool mIsUniversalAreaAsset;
bool mIsPlayerActor;
public:
@ -64,6 +66,7 @@ public:
void BuildDependencyList(bool AllowDuplicates, std::list<CAssetID>& rOut);
void AddDependency(CResourceEntry *pCurEntry, const CAssetID& rkID, std::list<CAssetID>& rOut);
void EvaluateDependencyNode(CResourceEntry *pCurEntry, IDependencyNode *pNode, std::list<CAssetID>& rOut);
void FindUniversalAreaAssets();
};
// ************ CAreaDependencyListBuilder ************

View File

@ -140,7 +140,7 @@ const SSetCharacter* CAnimationParameters::GetCurrentSetCharacter(s32 NodeIndex
{
CAnimSet *pSet = AnimSet();
if (pSet && pSet->Type() == eAnimSet)
if (pSet && (pSet->Type() == eAnimSet || pSet->Type() == eCharacter))
{
if (NodeIndex == -1)
NodeIndex = mCharIndex;

View File

@ -0,0 +1,25 @@
#ifndef CMAPAREA_H
#define CMAPAREA_H
#include "CResource.h"
// Barebones class
class CMapArea : public CResource
{
friend class CUnsupportedFormatLoader;
CAssetID mNameString;
public:
CMapArea(CResourceEntry *pEntry = 0)
: CResource(pEntry)
{}
CDependencyTree* BuildDependencyTree() const
{
CDependencyTree *pTree = new CDependencyTree();
pTree->AddDependency(mNameString);
return pTree;
}
};
#endif // CMAPAREA_H

View File

@ -242,7 +242,6 @@ void CResTypeInfo::CResTypeInfoFactory::InitTypes()
CResTypeInfo *pType = new CResTypeInfo(eMapArea, "Area Map");
AddExtension(pType, "MAPA", ePrimeDemo, eCorruption);
pType->mHidden = true;
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eMapWorld, "World Map");
@ -371,7 +370,7 @@ void CResTypeInfo::CResTypeInfoFactory::InitTypes()
}
{
CResTypeInfo *pType = new CResTypeInfo(eStateMachine2, "State Machine 2");
AddExtension(pType, "FSM2", eEchoesDemo, eEchoes);
AddExtension(pType, "FSM2", eEchoesDemo, eCorruption);
pType->mRawExtension = "fsm2";
}
{

View File

@ -16,11 +16,6 @@
// Must be included on every CResource subclass.
#define DECLARE_RESOURCE_TYPE(ResTypeEnum) \
public: \
virtual EResType Type() const \
{ \
return ResTypeEnum; \
} \
\
static EResType StaticType() \
{ \
return ResTypeEnum; \
@ -52,6 +47,7 @@ public:
inline CResourceEntry* Entry() const { return mpEntry; }
inline CResTypeInfo* TypeInfo() const { return mpEntry->TypeInfo(); }
inline EResType Type() const { return mpEntry->TypeInfo()->Type(); }
inline TString Source() const { return mpEntry ? mpEntry->CookedAssetPath(true).GetFileName() : ""; }
inline TString FullSource() const { return mpEntry ? mpEntry->CookedAssetPath(true) : ""; }
inline CAssetID ID() const { return mpEntry ? mpEntry->ID() : CAssetID::skInvalidID64; }

View File

@ -45,6 +45,7 @@ public:
case eDynamicCollision: return new CCollisionMeshGroup(pEntry);
case eDependencyGroup: return new CDependencyGroup(pEntry);
case eFont: return new CFont(pEntry);
case eMapArea: return new CMapArea(pEntry);
case eModel: return new CModel(pEntry);
case eScan: return new CScan(pEntry);
case eSkeleton: return new CSkeleton(pEntry);
@ -81,6 +82,7 @@ public:
case eFont: pRes = CFontLoader::LoadFONT(rInput, pEntry); break;
case eGuiFrame: pRes = CUnsupportedFormatLoader::LoadFRME(rInput, pEntry); break;
case eHintSystem: pRes = CUnsupportedFormatLoader::LoadHINT(rInput, pEntry); break;
case eMapArea: pRes = CUnsupportedFormatLoader::LoadMAPA(rInput, pEntry); break;
case eMapWorld: pRes = CUnsupportedFormatLoader::LoadMAPW(rInput, pEntry); break;
case eMapUniverse: pRes = CUnsupportedFormatLoader::LoadMAPU(rInput, pEntry); break;
case eMidi: pRes = CUnsupportedFormatLoader::LoadCSNG(rInput, pEntry); break;
@ -97,6 +99,12 @@ public:
case eTexture: pRes = CTextureDecoder::LoadTXTR(rInput, pEntry); break;
case eWorld: pRes = CWorldLoader::LoadMLVL(rInput, pEntry); break;
case eStateMachine:
// AFSM and FSMC currently unsupported
if (pEntry->Game() == eCorruptionProto || pEntry->Game() == eCorruption)
pRes = CUnsupportedFormatLoader::LoadFSM2(rInput, pEntry);
break;
case eBurstFireData:
case eParticle:
case eParticleElectric:

View File

@ -1,5 +1,7 @@
#include "CUnsupportedFormatLoader.h"
#include "Core/GameProject/CGameProject.h"
#include "Core/GameProject/CResourceIterator.h"
#include "Core/Resource/CWorld.h"
CAudioMacro* CUnsupportedFormatLoader::LoadCAUD(IInputStream& rCAUD, CResourceEntry *pEntry)
{
@ -253,11 +255,12 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadFSM2(IInputStream& rFSM2, CResou
u32 NumUnkA = rFSM2.ReadLong();
u32 NumUnkB = rFSM2.ReadLong();
u32 NumUnkC = rFSM2.ReadLong();
ASSERT(Version == 1);
ASSERT(Version == 1 || Version == 2);
for (u32 iState = 0; iState < NumStates; iState++)
{
rFSM2.ReadString();
if (Version >= 2) rFSM2.Seek(0x10, SEEK_CUR);
u32 UnkCount = rFSM2.ReadLong();
for (u32 iUnk = 0; iUnk < UnkCount; iUnk++)
@ -270,6 +273,7 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadFSM2(IInputStream& rFSM2, CResou
for (u32 iUnkA = 0; iUnkA < NumUnkA; iUnkA++)
{
rFSM2.ReadString();
if (Version >= 2) rFSM2.Seek(0x10, SEEK_CUR);
rFSM2.Seek(0x4, SEEK_CUR);
u32 UnkCount = rFSM2.ReadLong();
@ -285,6 +289,7 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadFSM2(IInputStream& rFSM2, CResou
for (u32 iUnkB = 0; iUnkB < NumUnkB; iUnkB++)
{
rFSM2.ReadString();
if (Version >= 2) rFSM2.Seek(0x10, SEEK_CUR);
u32 UnkCount = rFSM2.ReadLong();
for (u32 iUnkB2 = 0; iUnkB2 < UnkCount; iUnkB2++)
@ -297,6 +302,7 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadFSM2(IInputStream& rFSM2, CResou
for (u32 iUnkC = 0; iUnkC < NumUnkC; iUnkC++)
{
rFSM2.ReadString();
if (Version >= 2) rFSM2.Seek(0x10, SEEK_CUR);
u32 UnkCount = rFSM2.ReadLong();
for (u32 iUnkC2 = 0; iUnkC2 < UnkCount; iUnkC2++)
@ -305,7 +311,7 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadFSM2(IInputStream& rFSM2, CResou
rFSM2.Seek(0x4, SEEK_CUR);
}
pOut->AddDependency( CAssetID(rFSM2, eEchoes) );
pOut->AddDependency( CAssetID(rFSM2, pEntry->Game()) );
}
return pOut;
@ -362,20 +368,83 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadHINT(IInputStream& rHINT, CResou
rHINT.ReadString(); // Skip hint name
rHINT.Seek(0x8, SEEK_CUR); // Skip unknown + appear time
pGroup->AddDependency( CAssetID(rHINT, Game) ); // Pop-up STRG
rHINT.Seek(0x8, SEEK_CUR); // Skip unknowns
rHINT.Seek(0x4, SEEK_CUR); // Skip unknowns
if (Game <= eEchoes)
{
rHINT.Seek(0x4, SEEK_CUR);
pGroup->AddDependency( CAssetID(rHINT, Game) ); // Target MLVL
pGroup->AddDependency( CAssetID(rHINT, Game) ); // Target MREA
rHINT.Seek(0x4, SEEK_CUR); // Skip target room index
pGroup->AddDependency( CAssetID(rHINT, Game) ); // Map STRG
}
else
{
u32 NumLocations = rHINT.ReadLong();
for (u32 iLoc = 0; iLoc < NumLocations; iLoc++)
{
rHINT.Seek(0x14, SEEK_CUR); // Skip world/area ID, area index
pGroup->AddDependency( CAssetID(rHINT, Game) ); // Objective string
rHINT.Seek(0xC, SEEK_CUR); // Skip unknown data
}
}
}
return pGroup;
}
CMapArea* CUnsupportedFormatLoader::LoadMAPA(IInputStream& /*rMAPA*/, CResourceEntry *pEntry)
{
TResPtr<CMapArea> pMap = new CMapArea(pEntry);
// We don't actually read the file. Just fetch the name string so we can build the dependency tree.
CAssetID MapAreaID = pMap->ID();
// Find a MapWorld that contains this MapArea
CAssetID MapWorldID;
u32 WorldIndex = -1;
for (TResourceIterator<eMapWorld> It; It; ++It)
{
CDependencyGroup *pGroup = (CDependencyGroup*) It->Load();
for (u32 AreaIdx = 0; AreaIdx < pGroup->NumDependencies(); AreaIdx++)
{
if (pGroup->DependencyByIndex(AreaIdx) == MapAreaID)
{
WorldIndex = AreaIdx;
MapWorldID = pGroup->ID();
break;
}
}
if (WorldIndex != -1)
break;
}
// Find a world that contains this MapWorld
if (WorldIndex != -1)
{
for (TResourceIterator<eWorld> It; It; ++It)
{
CWorld *pWorld = (CWorld*) It->Load();
CDependencyGroup *pMapWorld = (CDependencyGroup*) pWorld->MapWorld();
if (pMapWorld && pMapWorld->ID() == MapWorldID)
{
CStringTable *pNameString = pWorld->AreaName(WorldIndex);
pMap->mNameString = (pNameString ? pNameString->ID() : CAssetID::InvalidID(pEntry->Game()));
break;
}
}
}
pMap->Entry()->ResourceStore()->DestroyUnreferencedResources();
return pMap;
}
CDependencyGroup* CUnsupportedFormatLoader::LoadMAPW(IInputStream& rMAPW, CResourceEntry *pEntry)
{
u32 Magic = rMAPW.ReadLong();

View File

@ -3,6 +3,7 @@
#include "Core/Resource/CAudioMacro.h"
#include "Core/Resource/CDependencyGroup.h"
#include "Core/Resource/CMapArea.h"
// This class is responsible for loading formats that aren't yet fully supported.
// This is needed so we have access to the full dependency list of all resource types.
@ -19,6 +20,7 @@ public:
static CDependencyGroup* LoadFSM2(IInputStream& rFSM2, CResourceEntry *pEntry);
static CDependencyGroup* LoadHIER(IInputStream& rHIER, CResourceEntry *pEntry);
static CDependencyGroup* LoadHINT(IInputStream& rHINT, CResourceEntry *pEntry);
static CMapArea* LoadMAPA(IInputStream& rMAPA, CResourceEntry *pEntry);
static CDependencyGroup* LoadMAPW(IInputStream& rMAPW, CResourceEntry *pEntry);
static CDependencyGroup* LoadMAPU(IInputStream& rMAPU, CResourceEntry *pEntry);
static CDependencyGroup* LoadRULE(IInputStream& rRULE, CResourceEntry *pEntry);

View File

@ -27,7 +27,7 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL)
{
mpWorld->mpWorldName = gpResourceStore->LoadResource(rMLVL.ReadLongLong(), eStringTable);
rMLVL.Seek(0x4, SEEK_CUR); // Skipping unknown value
mpWorld->mpSaveWorld = gpResourceStore->LoadResource(rMLVL.ReadLongLong(), eStringTable);
mpWorld->mpSaveWorld = gpResourceStore->LoadResource(rMLVL.ReadLongLong(), eSaveWorld);
mpWorld->mpDefaultSkybox = gpResourceStore->LoadResource(rMLVL.ReadLongLong(), eModel);
}

View File

@ -655,7 +655,7 @@ CModel* CScriptNode::ActiveModel() const
{
if (mpDisplayAsset->Type() == eModel)
return static_cast<CModel*>(mpDisplayAsset.RawPointer());
else if (mpDisplayAsset->Type() == eAnimSet)
else if (mpDisplayAsset->Type() == eAnimSet || mpDisplayAsset->Type() == eCharacter)
return static_cast<CAnimSet*>(mpDisplayAsset.RawPointer())->Character(mCharIndex)->pModel;
}
@ -664,7 +664,7 @@ CModel* CScriptNode::ActiveModel() const
CAnimSet* CScriptNode::ActiveAnimSet() const
{
if (mpDisplayAsset && mpDisplayAsset->Type() == eAnimSet)
if (mpDisplayAsset && (mpDisplayAsset->Type() == eAnimSet || mpDisplayAsset->Type() == eCharacter))
return static_cast<CAnimSet*>(mpDisplayAsset.RawPointer());
else
return nullptr;
@ -739,7 +739,7 @@ void CScriptNode::SetDisplayAsset(CResource *pRes)
{
mpDisplayAsset = pRes;
bool IsAnimSet = (pRes && pRes->Type() == eAnimSet);
bool IsAnimSet = (pRes && (pRes->Type() == eAnimSet || pRes->Type() == eCharacter));
mCharIndex = (IsAnimSet ? mpInstance->ActiveCharIndex() : -1);
mAnimIndex = (IsAnimSet ? mpInstance->ActiveAnimIndex() : -1);

View File

@ -78,9 +78,13 @@ void CProjectSettingsDialog::SetupPackagesList()
void CProjectSettingsDialog::CookPackage()
{
u32 PackageIdx = mpUI->PackagesList->currentRow();
CPackage *pPackage = mpProject->PackageByIndex(PackageIdx);
pPackage->Cook();
SetupPackagesList();
if (PackageIdx != -1)
{
CPackage *pPackage = mpProject->PackageByIndex(PackageIdx);
pPackage->Cook();
SetupPackagesList();
}
}
void CProjectSettingsDialog::CookAllDirtyPackages()

View File

@ -763,7 +763,7 @@ void CModelEditorWindow::ConvertToDDS()
if (Input.isEmpty()) return;
TString TexFilename = TO_TSTRING(Input);
TResPtr<CTexture> pTex = gpResourceStore->LoadResource(TexFilename);
CTexture *pTex = CTextureDecoder::LoadDDS( CFileInStream(TexFilename, IOUtil::eLittleEndian), nullptr );
TString OutName = TexFilename.GetFilePathWithoutExtension() + ".dds";
CFileOutStream Out(OutName, IOUtil::eLittleEndian);
@ -775,6 +775,8 @@ void CModelEditorWindow::ConvertToDDS()
if (!Success) QMessageBox::warning(this, "Error", "Couldn't write output DDS!");
else QMessageBox::information(this, "Success", "Successfully converted to DDS!");
}
delete pTex;
}
void CModelEditorWindow::ConvertToTXTR()