diff --git a/src/Core/Core.pro b/src/Core/Core.pro index d8ce220e..f7c748a9 100644 --- a/src/Core/Core.pro +++ b/src/Core/Core.pro @@ -119,7 +119,6 @@ HEADERS += \ Resource/CMaterialPass.h \ Resource/CMaterialSet.h \ Resource/CResource.h \ - Resource/CScan.h \ Resource/CTexture.h \ Resource/CWorld.h \ Resource/EResType.h \ @@ -252,7 +251,10 @@ HEADERS += \ Tweaks/CTweakManager.h \ Tweaks/CTweakData.h \ Tweaks/CTweakLoader.h \ - Tweaks/CTweakCooker.h + Tweaks/CTweakCooker.h \ + Resource/Scan/CScan.h \ + Resource/Scan/SScanParametersMP1.h \ + Resource/Scan/ELogbookCategory.h # Source Files SOURCES += \ @@ -367,7 +369,8 @@ SOURCES += \ Resource/StringTable/CStringTable.cpp \ Tweaks/CTweakManager.cpp \ Tweaks/CTweakLoader.cpp \ - Tweaks/CTweakCooker.cpp + Tweaks/CTweakCooker.cpp \ + Resource/Scan/CScan.cpp # Codegen CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen diff --git a/src/Core/GameProject/AssetNameGeneration.cpp b/src/Core/GameProject/AssetNameGeneration.cpp index 03ac2f67..a6ca5274 100644 --- a/src/Core/GameProject/AssetNameGeneration.cpp +++ b/src/Core/GameProject/AssetNameGeneration.cpp @@ -3,9 +3,10 @@ #include "CResourceIterator.h" #include "Core/Resource/CAudioMacro.h" #include "Core/Resource/CFont.h" -#include "Core/Resource/CScan.h" #include "Core/Resource/CWorld.h" #include "Core/Resource/Animation/CAnimSet.h" +#include "Core/Resource/Scan/CScan.h" +#include "Core/Resource/Scan/SScanParametersMP1.h" #include "Core/Resource/Script/CScriptLayer.h" #include @@ -311,10 +312,15 @@ void GenerateAssetNames(CGameProject *pProj) ApplyGeneratedName(pEntry, pEntry->DirectoryPath(), ScanName); CScan *pScan = (CScan*) pEntry->Load(); - if (pScan && pScan->ScanText()) + if (pScan) { - CResourceEntry *pStringEntry = pScan->ScanText()->Entry(); - ApplyGeneratedName(pStringEntry, pStringEntry->DirectoryPath(), ScanName); + CAssetID StringID = pScan->ScanStringPropertyRef(); + CResourceEntry* pStringEntry = gpResourceStore->FindEntry(StringID); + + if (pStringEntry) + { + ApplyGeneratedName(pStringEntry, pStringEntry->DirectoryPath(), ScanName); + } } } } @@ -609,16 +615,10 @@ void GenerateAssetNames(CGameProject *pProj) CScan *pScan = (CScan*) It->Load(); TString ScanName; - if (pProj->Game() >= EGame::EchoesDemo) - { - CAssetID DisplayAsset = pScan->LogbookDisplayAssetID(); - CResourceEntry *pEntry = pStore->FindEntry(DisplayAsset); - if (pEntry && pEntry->IsNamed()) ScanName = pEntry->Name(); - } - if (ScanName.IsEmpty()) { - CStringTable *pString = pScan->ScanText(); + CAssetID StringID = pScan->ScanStringPropertyRef().Get(); + CStringTable *pString = (CStringTable*) gpResourceStore->LoadResource(StringID, EResourceType::StringTable); if (pString) ScanName = pString->Entry()->Name(); } @@ -626,13 +626,14 @@ void GenerateAssetNames(CGameProject *pProj) if (!ScanName.IsEmpty() && pProj->Game() <= EGame::Prime) { - CAssetID FrameID = pScan->GuiFrame(); - CResourceEntry *pEntry = pStore->FindEntry(FrameID); + const SScanParametersMP1& kParms = *static_cast(pScan->ScanData().DataPointer()); + + CResourceEntry *pEntry = pStore->FindEntry(kParms.GuiFrame); if (pEntry) ApplyGeneratedName(pEntry, pEntry->DirectoryPath(), "ScanFrame"); for (uint32 iImg = 0; iImg < 4; iImg++) { - CAssetID ImageID = pScan->ScanImage(iImg); + CAssetID ImageID = kParms.ScanImages[iImg].Texture; CResourceEntry *pImgEntry = pStore->FindEntry(ImageID); if (pImgEntry) ApplyGeneratedName(pImgEntry, pImgEntry->DirectoryPath(), TString::Format("%s_Image%d", *ScanName, iImg)); } diff --git a/src/Core/GameProject/CDependencyTree.cpp b/src/Core/GameProject/CDependencyTree.cpp index 6eb8834a..f43d9709 100644 --- a/src/Core/GameProject/CDependencyTree.cpp +++ b/src/Core/GameProject/CDependencyTree.cpp @@ -30,6 +30,70 @@ void IDependencyNode::GetAllResourceReferences(std::set& rOutSet) cons mChildren[iChild]->GetAllResourceReferences(rOutSet); } +void IDependencyNode::ParseProperties(CResourceEntry* pParentEntry, CStructProperty* pProperties, void* pData) +{ + // Recursive function for parsing dependencies in properties + for (uint32 PropertyIdx = 0; PropertyIdx < pProperties->NumChildren(); PropertyIdx++) + { + IProperty* pProp = pProperties->ChildByIndex(PropertyIdx); + EPropertyType Type = pProp->Type(); + + // Technically we aren't parsing array children, but it's not really worth refactoring this function + // to support it when there aren't any array properties that contain any asset references anyway... + if (Type == EPropertyType::Struct) + ParseProperties( pParentEntry, TPropCast(pProp), pData ); + + else if (Type == EPropertyType::Sound) + { + uint32 SoundID = TPropCast(pProp)->Value(pData); + + if (SoundID != -1) + { + CGameProject* pProj = pParentEntry->Project(); + SSoundInfo Info = pProj->AudioManager()->GetSoundInfo(SoundID); + + if (Info.pAudioGroup) + { + CPropertyDependency *pDep = new CPropertyDependency(pProp->IDString(true), Info.pAudioGroup->ID()); + mChildren.push_back(pDep); + } + } + } + + else if (Type == EPropertyType::Asset) + { + CAssetID ID = TPropCast(pProp)->Value(pData); + + if (ID.IsValid()) + { + CPropertyDependency *pDep = new CPropertyDependency(pProp->IDString(true), ID); + mChildren.push_back(pDep); + } + } + + else if (Type == EPropertyType::AnimationSet) + { + CAnimationParameters Params = TPropCast(pProp)->Value(pData); + CAssetID ID = Params.ID(); + + if (ID.IsValid()) + { + // Character sets are removed starting in MP3, so we only need char property dependencies in Echoes and earlier + if (pProperties->Game() <= EGame::Echoes) + { + CCharPropertyDependency *pDep = new CCharPropertyDependency(pProp->IDString(true), ID, Params.CharacterIndex()); + mChildren.push_back(pDep); + } + else + { + CPropertyDependency *pDep = new CPropertyDependency(pProp->IDString(true), ID); + mChildren.push_back(pDep); + } + } + } + } +} + // Serialization constructor IDependencyNode* IDependencyNode::ArchiveConstructor(EDependencyNodeType Type) { @@ -149,76 +213,10 @@ CScriptInstanceDependency* CScriptInstanceDependency::BuildTree(CScriptObject *p { CScriptInstanceDependency *pInst = new CScriptInstanceDependency(); pInst->mObjectType = pInstance->ObjectTypeID(); - ParseStructDependencies(pInst, pInstance, pInstance->Template()->Properties()); + pInst->ParseProperties(pInstance->Area()->Entry(), pInstance->Template()->Properties(), pInstance->PropertyData()); return pInst; } -void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependency* pInst, CScriptObject* pInstance, CStructProperty *pStruct) -{ - // Recursive function for parsing script dependencies and loading them into the script instance dependency - void* pPropertyData = pInstance->PropertyData(); - - for (uint32 PropertyIdx = 0; PropertyIdx < pStruct->NumChildren(); PropertyIdx++) - { - IProperty *pProp = pStruct->ChildByIndex(PropertyIdx); - EPropertyType Type = pProp->Type(); - - // Technically we aren't parsing array children, but it's not really worth refactoring this function - // to support it when there aren't any array properties that contain any asset references anyway... - if (Type == EPropertyType::Struct) - ParseStructDependencies(pInst, pInstance, TPropCast(pProp)); - - else if (Type == EPropertyType::Sound) - { - uint32 SoundID = TPropCast(pProp)->Value(pPropertyData); - - if (SoundID != -1) - { - CGameProject *pProj = pInstance->Area()->Entry()->Project(); - SSoundInfo Info = pProj->AudioManager()->GetSoundInfo(SoundID); - - if (Info.pAudioGroup) - { - CPropertyDependency *pDep = new CPropertyDependency(pProp->IDString(true), Info.pAudioGroup->ID()); - pInst->mChildren.push_back(pDep); - } - } - } - - else if (Type == EPropertyType::Asset) - { - CAssetID ID = TPropCast(pProp)->Value(pPropertyData); - - if (ID.IsValid()) - { - CPropertyDependency *pDep = new CPropertyDependency(pProp->IDString(true), ID); - pInst->mChildren.push_back(pDep); - } - } - - else if (Type == EPropertyType::AnimationSet) - { - CAnimationParameters Params = TPropCast(pProp)->Value(pPropertyData); - CAssetID ID = Params.ID(); - - if (ID.IsValid()) - { - // Character sets are removed starting in MP3, so we only need char property dependencies in Echoes and earlier - if (pStruct->Game() <= EGame::Echoes) - { - CCharPropertyDependency *pDep = new CCharPropertyDependency(pProp->IDString(true), ID, Params.CharacterIndex()); - pInst->mChildren.push_back(pDep); - } - else - { - CPropertyDependency *pDep = new CPropertyDependency(pProp->IDString(true), ID); - pInst->mChildren.push_back(pDep); - } - } - } - } -} - // ************ CSetCharacterDependency ************ EDependencyNodeType CSetCharacterDependency::Type() const { diff --git a/src/Core/GameProject/CDependencyTree.h b/src/Core/GameProject/CDependencyTree.h index 93fd9395..68b4d775 100644 --- a/src/Core/GameProject/CDependencyTree.h +++ b/src/Core/GameProject/CDependencyTree.h @@ -39,6 +39,7 @@ public: virtual void Serialize(IArchive& rArc) = 0; virtual void GetAllResourceReferences(std::set& rOutSet) const; virtual bool HasDependency(const CAssetID& rkID) const; + void ParseProperties(CResourceEntry* pParentEntry, CStructProperty* pProperties, void* pData); // Serialization constructor static IDependencyNode* ArchiveConstructor(EDependencyNodeType Type); @@ -144,8 +145,6 @@ public: // Static static CScriptInstanceDependency* BuildTree(CScriptObject *pInstance); -protected: - static void ParseStructDependencies(CScriptInstanceDependency *pTree, CScriptObject* pInstance, CStructProperty *pStruct); }; // Node representing an animset character. Indicates what index the character is within the animset. diff --git a/src/Core/Resource/Animation/CAnimationParameters.h b/src/Core/Resource/Animation/CAnimationParameters.h index 5f21b06e..4d9c1a9a 100644 --- a/src/Core/Resource/Animation/CAnimationParameters.h +++ b/src/Core/Resource/Animation/CAnimationParameters.h @@ -2,9 +2,10 @@ #define CANIMATIONPARAMETERS_H #include "Core/Resource/TResPtr.h" -#include "Core/Resource/Model/CModel.h" #include +class CModel; + class CAnimationParameters { EGame mGame; diff --git a/src/Core/Resource/CResTypeInfo.cpp b/src/Core/Resource/CResTypeInfo.cpp index cc355d7e..effcb0b5 100644 --- a/src/Core/Resource/CResTypeInfo.cpp +++ b/src/Core/Resource/CResTypeInfo.cpp @@ -381,12 +381,12 @@ void CResTypeInfo::CResTypeInfoFactory::InitTypes() { CResTypeInfo *pType = new CResTypeInfo(EResourceType::StringTable, "String Table", "strg"); AddExtension(pType, "STRG", EGame::PrimeDemo, EGame::DKCReturns); + pType->mCanBeSerialized = true; } { CResTypeInfo *pType = new CResTypeInfo(EResourceType::Texture, "Texture", "txtr"); AddExtension(pType, "TXTR", EGame::PrimeDemo, EGame::DKCReturns); pType->mCanHaveDependencies = false; - pType->mCanBeSerialized = true; } { CResTypeInfo *pType = new CResTypeInfo(EResourceType::Tweaks, "Tweak Data", "ctwk"); diff --git a/src/Core/Resource/CScan.h b/src/Core/Resource/CScan.h deleted file mode 100644 index 680569d9..00000000 --- a/src/Core/Resource/CScan.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef CSCAN_H -#define CSCAN_H - -#include "CResource.h" -#include "TResPtr.h" -#include "Core/Resource/Animation/CAnimationParameters.h" -#include "Core/Resource/StringTable/CStringTable.h" -#include - -class CScan : public CResource -{ - DECLARE_RESOURCE_TYPE(Scan) - friend class CScanLoader; - -public: - // This likely needs revising when MP2/MP3 support is added - enum class ELogbookCategory - { - None, - PirateData, - ChozoLore, - Creatures, - Research - }; - - struct SScanInfoSecondaryModel - { - CAssetID ModelID; - CAnimationParameters AnimParams; - TString AttachBoneName; - }; - -private: - // Common - TResPtr mpStringTable; - bool mIsSlow; - bool mIsImportant; - ELogbookCategory mCategory; - - // MP1 - CAssetID mFrameID; - CAssetID mScanImageTextures[4]; - - // MP2/3 - bool mUseLogbookModelPostScan; - CAssetID mPostOverrideTexture; - float mLogbookDefaultRotX; - float mLogbookDefaultRotZ; - float mLogbookScale; - CAssetID mLogbookModel; - CAnimationParameters mLogbookAnimParams; - CAnimationParameters mUnknownAnimParams; - std::vector mSecondaryModels; - - // MP3 - std::vector mDependencyList; - -public: - CScan(CResourceEntry *pEntry = 0) - : CResource(pEntry) - , mpStringTable(nullptr) - , mIsSlow(false) - , mIsImportant(false) - , mCategory(ELogbookCategory::None) - {} - - CDependencyTree* BuildDependencyTree() const - { - CDependencyTree *pTree = new CDependencyTree(); - - // Corruption's SCAN has a list of all assets - just grab that - if (Game() >= EGame::CorruptionProto) - { - for (uint32 iDep = 0; iDep < mDependencyList.size(); iDep++) - { - pTree->AddDependency(mDependencyList[iDep]); - } - - return pTree; - } - - // Otherwise add all the dependencies we need from the properties - if (Game() <= EGame::Prime) - pTree->AddDependency(mFrameID); - - pTree->AddDependency(mpStringTable); - - if (Game() <= EGame::Prime) - { - for (uint32 iImg = 0; iImg < 4; iImg++) - pTree->AddDependency(mScanImageTextures[iImg]); - } - - else if (Game() <= EGame::Echoes) - { - pTree->AddDependency(mPostOverrideTexture); - pTree->AddDependency(mLogbookModel); - pTree->AddCharacterDependency(mLogbookAnimParams); - pTree->AddCharacterDependency(mUnknownAnimParams); - - for (uint32 iSec = 0; iSec < mSecondaryModels.size(); iSec++) - { - const SScanInfoSecondaryModel& rkSecModel = mSecondaryModels[iSec]; - pTree->AddDependency(rkSecModel.ModelID); - pTree->AddCharacterDependency(rkSecModel.AnimParams); - } - } - - return pTree; - } - - // Accessors - inline CStringTable* ScanText() const { return mpStringTable; } - inline bool IsImportant() const { return mIsImportant; } - inline bool IsSlow() const { return mIsSlow; } - inline ELogbookCategory LogbookCategory() const { return mCategory; } - inline CAssetID GuiFrame() const { return mFrameID; } - inline CAssetID ScanImage(uint32 ImgIndex) const { return mScanImageTextures[ImgIndex]; } - inline CAssetID LogbookDisplayAssetID() const { return (mLogbookAnimParams.ID().IsValid() ? mLogbookAnimParams.ID() : mLogbookModel); } -}; - -#endif // CSCAN_H diff --git a/src/Core/Resource/Factory/CScanLoader.cpp b/src/Core/Resource/Factory/CScanLoader.cpp index e5150fed..38d86280 100644 --- a/src/Core/Resource/Factory/CScanLoader.cpp +++ b/src/Core/Resource/Factory/CScanLoader.cpp @@ -1,306 +1,83 @@ #include "CScanLoader.h" #include "Core/GameProject/CResourceStore.h" +#include "CScriptLoader.h" #include -CScanLoader::CScanLoader() +CScan* CScanLoader::LoadScanMP1(IInputStream& SCAN, CResourceEntry* pEntry) { -} - -CScan* CScanLoader::LoadScanMP1(IInputStream& rSCAN) -{ - // Basic support at the moment - don't read animation/scan image data - mpScan->mFrameID = CAssetID(rSCAN, k32Bit); - mpScan->mpStringTable = gpResourceStore->LoadResource(rSCAN.ReadLong(), EResourceType::StringTable); - mpScan->mIsSlow = (rSCAN.ReadLong() != 0); - mpScan->mCategory = (CScan::ELogbookCategory) rSCAN.ReadLong(); - mpScan->mIsImportant = (rSCAN.ReadByte() == 1); - - for (uint32 iImg = 0; iImg < 4; iImg++) - { - mpScan->mScanImageTextures[iImg] = CAssetID(rSCAN, k32Bit); - rSCAN.Seek(0x18, SEEK_CUR); - } - - return mpScan; -} - -CScan* CScanLoader::LoadScanMP2(IInputStream& rSCAN) -{ - // The SCAN format in MP2 embeds a SNFO object using the same format as SCLY - // However since the contents of the file are consistent there's no need to delegate to CScriptLoader - rSCAN.Skip(0x1); - uint32 NumInstances = rSCAN.ReadLong(); - - if (NumInstances != 1) - { - errorf("%s: SCAN has multiple instances", *rSCAN.GetSourceString()); - return nullptr; - } - - uint32 ScanInfoStart = rSCAN.Tell(); - - CFourCC SNFO(rSCAN); - if (SNFO != FOURCC('SNFO')) - { - errorf("%s [0x%X]: Unrecognized SCAN object type: %s", *rSCAN.GetSourceString(), ScanInfoStart, *SNFO.ToString()); - return nullptr; - } - - uint16 InstanceSize = rSCAN.ReadShort(); - uint32 InstanceEnd = rSCAN.Tell() + InstanceSize; - rSCAN.Skip(0x4); - - uint16 NumConnections = rSCAN.ReadShort(); - if (NumConnections > 0) - { - warnf("%s [0x%X]: SNFO object in SCAN has connections", *rSCAN.GetSourceString(), ScanInfoStart); - rSCAN.Skip(NumConnections * 0xC); - } - - uint32 BasePropID = rSCAN.ReadLong(); - if (BasePropID != 0xFFFFFFFF) - { - errorf("%s [0x%X]: Invalid base property ID: 0x%08X", *rSCAN.GetSourceString(), rSCAN.Tell() - 4, BasePropID); - return nullptr; - } - - rSCAN.Skip(0x2); - uint16 NumProperties = rSCAN.ReadShort(); - - switch (NumProperties) - { - case 0x14: - case 0xB: - mpScan = new CScan(mpEntry); - LoadParamsMP2(rSCAN, NumProperties); - break; - case 0x12: - case 0x15: - case 0x16: - mpScan = new CScan(mpEntry); - LoadParamsMP3(rSCAN, NumProperties); - break; - default: - errorf("%s [0x%X]: Invalid SNFO property count: 0x%X", *rSCAN.GetSourceString(), rSCAN.Tell() - 2, NumProperties); - return nullptr; - } - - // Load MP3 dependency list - if (mpScan->Game() == EGame::Corruption) - { - rSCAN.GoTo(InstanceEnd); - uint32 NumDeps = rSCAN.ReadLong(); - - for (uint32 DepIdx = 0; DepIdx < NumDeps; DepIdx++) - { - rSCAN.Skip(4); - CAssetID ID(rSCAN, mpScan->Game()); - mpScan->mDependencyList.push_back(ID); - } - } - - return mpScan; -} - -void CScanLoader::LoadParamsMP2(IInputStream& rSCAN, uint16 NumProperties) -{ - // Function begins after the SNFO property count - mpScan->mSecondaryModels.resize(9); - - for (uint32 iProp = 0; iProp < NumProperties; iProp++) - { - uint32 PropertyID = rSCAN.ReadLong(); - uint16 PropertySize = rSCAN.ReadShort(); - uint32 Next = rSCAN.Tell() + PropertySize; - - switch (PropertyID) - { - case 0x2F5B6423: - mpScan->mpStringTable = gpResourceStore->LoadResource(rSCAN.ReadLong(), EResourceType::StringTable); - break; - - case 0xC308A322: - mpScan->mIsSlow = (rSCAN.ReadLong() != 0); - break; - - case 0x7B714814: - mpScan->mIsImportant = rSCAN.ReadBool(); - break; - - case 0x1733B1EC: - mpScan->mUseLogbookModelPostScan = rSCAN.ReadBool(); - break; - - case 0x53336141: - mpScan->mPostOverrideTexture = CAssetID(rSCAN, mVersion); - break; - - case 0x3DE0BA64: - mpScan->mLogbookDefaultRotX = rSCAN.ReadFloat(); - break; - - case 0x2ADD6628: - mpScan->mLogbookDefaultRotZ = rSCAN.ReadFloat(); - break; - - case 0xD0C15066: - mpScan->mLogbookScale = rSCAN.ReadFloat(); - break; - - case 0xB7ADC418: - mpScan->mLogbookModel = CAssetID(rSCAN, mVersion); - break; - - case 0x15694EE1: - mpScan->mLogbookAnimParams = CAnimationParameters(rSCAN, mVersion); - break; - - case 0x58F9FE99: - mpScan->mUnknownAnimParams = CAnimationParameters(rSCAN, mVersion); - break; - - case 0x1C5B4A3A: - LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[0] ); - break; - - case 0x8728A0EE: - LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[1] ); - break; - - case 0xF1CD99D3: - LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[2] ); - break; - - case 0x6ABE7307: - LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[3] ); - break; - - case 0x1C07EBA9: - LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[4] ); - break; - - case 0x8774017D: - LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[5] ); - break; - - case 0xF1913840: - LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[6] ); - break; - - case 0x6AE2D294: - LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[7] ); - break; - - case 0x1CE2091C: - LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[8] ); - break; - } - - rSCAN.GoTo(Next); - } - - mpScan->mCategory = CScan::ELogbookCategory::None; -} - -void CScanLoader::LoadParamsMP3(IInputStream& rSCAN, uint16 NumProperties) -{ - // Function begins after the SNFO property count - for (uint32 iProp = 0; iProp < NumProperties; iProp++) - { - uint32 PropertyID = rSCAN.ReadLong(); - uint16 PropertySize = rSCAN.ReadShort(); - uint32 Next = rSCAN.Tell() + PropertySize; - - switch (PropertyID) - { - case 0x2F5B6423: - mpScan->mpStringTable = gpResourceStore->LoadResource(rSCAN.ReadLongLong(), EResourceType::StringTable); - break; - - case 0xC308A322: - mpScan->mIsSlow = (rSCAN.ReadLong() != 0); - break; - - case 0x7B714814: - mpScan->mIsImportant = (rSCAN.ReadByte() != 0); - break; - } - - rSCAN.GoTo(Next); - } - - mpScan->mCategory = CScan::ELogbookCategory::None; -} - -void CScanLoader::LoadScanInfoSecondaryModel(IInputStream& rSCAN, CScan::SScanInfoSecondaryModel& rSecondaryModel) -{ - uint16 NumProperties = rSCAN.ReadShort(); - - for (uint32 iProp = 0; iProp < NumProperties; iProp++) - { - uint32 PropertyID = rSCAN.ReadLong(); - uint16 PropertySize = rSCAN.ReadShort(); - uint32 Next = rSCAN.Tell() + PropertySize; - - switch (PropertyID) - { - case 0x1F7921BC: - rSecondaryModel.ModelID = CAssetID(rSCAN, mVersion); - break; - - case 0xCDD202D1: - rSecondaryModel.AnimParams = CAnimationParameters(rSCAN, mVersion); - break; - - case 0x3EA2BED8: - rSecondaryModel.AttachBoneName = rSCAN.ReadString(); - break; - } - - rSCAN.GoTo(Next); - } -} - -// ************ STATIC/PUBLIC ************ -CScan* CScanLoader::LoadSCAN(IInputStream& rSCAN, CResourceEntry *pEntry) -{ - if (!rSCAN.IsValid()) return nullptr; - - /* Switching to EGame enum here isn't really useful unfortunately - * because the MP1 demo can be 1, 2, or 3, while MP1 is 5 and MP2+ is 2 - * MP1 is the only one that starts with 5 so that is a consistent check for now - * Better version checks will be implemented when the other versions are - * better-understood. */ - uint32 FileVersion = rSCAN.ReadLong(); - uint32 Magic = rSCAN.ReadLong(); - - // Echoes+ - if (FileVersion == FOURCC('SCAN')) - { - // The MP2 load function will check for MP3 - CScanLoader Loader; - Loader.mVersion = EGame::Echoes; - Loader.mpEntry = pEntry; - if (Magic == 0x01000000) rSCAN.Seek(-4, SEEK_CUR); // The version number isn't present in the Echoes demo - return Loader.LoadScanMP2(rSCAN); - } + // Validate magic + uint Magic = SCAN.ReadLong(); if (Magic != 0x0BADBEEF) { - errorf("%s: Invalid SCAN magic: 0x%08X", *rSCAN.GetSourceString(), Magic); + errorf("Invalid magic in SCAN asset: 0x%08X", Magic); return nullptr; } - if (FileVersion != 5) - { - errorf("%s: Unsupported SCAN version: 0x%X", *rSCAN.GetSourceString(), FileVersion); - return nullptr; - } - - // MP1 SCAN - read the file! - CScanLoader Loader; - Loader.mVersion = EGame::Prime; - Loader.mpScan = new CScan(pEntry); - Loader.mpEntry = pEntry; - return Loader.LoadScanMP1(rSCAN); + // The SCAN format in MP2 and later games uses the script loader to load SCAN parameters. + // The MP1 format is not loaded the same way, as far as I'm aware, and is loaded the same + // way as a normal file format... however, since we support all games, we need to support + // the script object method for proper MP2/3 support (including dealing with property names/IDs). + // So, it's simplest to use the script loader to load the MP1 SCAN format as well... that enables + // us to just create one class for all SCAN assets that works for every game. + mpScan = new CScan(pEntry); + CScriptLoader::LoadStructData(SCAN, mpScan->ScanData()); + return mpScan; +} + +CScan* CScanLoader::LoadScanMP2(IInputStream& SCAN, CResourceEntry* pEntry) +{ + // Validate version + uint Version = SCAN.ReadLong(); + + if (Version != 2) + { + errorf("Unrecognized SCAN version: %d", Version); + return nullptr; + } + + // The SCAN format in MP2 embeds a ScannableObjectInfo script object using the same file format as SCLY. + // As such we use CScriptLoader to load parameters, but since we don't actually want to create a script + // object, we will skip past the script object/layer header and just load the properties directly. + SCAN.Skip(0x17); + mpScan = new CScan(pEntry); + CScriptLoader::LoadStructData(SCAN, mpScan->ScanData()); + return mpScan; +} + +// ************ STATIC/PUBLIC ************ +CScan* CScanLoader::LoadSCAN(IInputStream& SCAN, CResourceEntry *pEntry) +{ + if (!SCAN.IsValid()) return nullptr; + + // MP1 SCAN format starts with a version number and then follows with a magic. + // The demo can be 1, 2, or 3, while the final build is 5. + // The MP2 SCAN format starts with a 'SCAN' magic. + uint VersionCheck = SCAN.ReadLong(); + + // Echoes+ + if (VersionCheck == FOURCC('SCAN')) + { + CScanLoader Loader; + return Loader.LoadScanMP2(SCAN, pEntry); + } + // MP1 + else if (VersionCheck <= 5) + { + if (VersionCheck == 5) + { + CScanLoader Loader; + return Loader.LoadScanMP1(SCAN, pEntry); + } + else + { + errorf("%s: Unsupported SCAN version: %d", VersionCheck); + return nullptr; + } + } + else + { + errorf("Failed to identify SCAN version: 0x%X", VersionCheck); + return nullptr; + } } diff --git a/src/Core/Resource/Factory/CScanLoader.h b/src/Core/Resource/Factory/CScanLoader.h index b75333f5..e2068292 100644 --- a/src/Core/Resource/Factory/CScanLoader.h +++ b/src/Core/Resource/Factory/CScanLoader.h @@ -7,15 +7,10 @@ class CScanLoader { TResPtr mpScan; - CResourceEntry *mpEntry; - EGame mVersion; - CScanLoader(); - CScan* LoadScanMP1(IInputStream& rSCAN); - CScan* LoadScanMP2(IInputStream& rSCAN); - void LoadParamsMP2(IInputStream& rSCAN, uint16 NumProperties); - void LoadParamsMP3(IInputStream& rSCAN, uint16 NumProperties); - void LoadScanInfoSecondaryModel(IInputStream& rSCAN, CScan::SScanInfoSecondaryModel& rSecondaryModel); + CScanLoader() {} + CScan* LoadScanMP1(IInputStream& SCAN, CResourceEntry* pEntry); + CScan* LoadScanMP2(IInputStream& SCAN, CResourceEntry* pEntry); public: static CScan* LoadSCAN(IInputStream& rSCAN, CResourceEntry *pEntry); diff --git a/src/Core/Resource/Scan/CScan.cpp b/src/Core/Resource/Scan/CScan.cpp new file mode 100644 index 00000000..8efa4f2e --- /dev/null +++ b/src/Core/Resource/Scan/CScan.cpp @@ -0,0 +1,51 @@ +#include "CScan.h" + +CScan::CScan(CResourceEntry* pEntry /*= 0*/) + : CResource(pEntry) +{ + CGameTemplate* pGameTemplate = NGameList::GetGameTemplate( Game() ); + mpTemplate = pGameTemplate->FindMiscTemplate("ScannableObjectInfo"); + ASSERT( mpTemplate != nullptr ); + + CStructProperty* pProperties = mpTemplate->Properties(); + mPropertyData.resize( pProperties->DataSize() ); + pProperties->Construct( mPropertyData.data() ); +} + +CStructRef CScan::ScanData() const +{ + return CStructRef((void*) mPropertyData.data(), mpTemplate->Properties()); +} + +/** Convenience property accessors */ +CAssetRef CScan::ScanStringPropertyRef() const +{ + const uint kStringIdMP1 = 0x1; + const uint kStringIdMP2 = 0x2F5B6423; + + IProperty* pProperty = mpTemplate->Properties()->ChildByID( + Game() <= EGame::Prime ? kStringIdMP1 : kStringIdMP2 + ); + + return CAssetRef( (void*) mPropertyData.data(), pProperty ); +} + +CBoolRef CScan::IsCriticalPropertyRef() const +{ + const uint kIsCriticalIdMP1 = 0x4; + const uint kIsCriticalIdMP2 = 0x7B714814; + + IProperty* pProperty = mpTemplate->Properties()->ChildByID( + Game() <= EGame::Prime ? kIsCriticalIdMP1 : kIsCriticalIdMP2 + ); + + return CBoolRef( (void*) mPropertyData.data(), pProperty ); +} + +/** CResource interface */ +CDependencyTree* CScan::BuildDependencyTree() const +{ + CDependencyTree* pTree = new CDependencyTree(); + pTree->ParseProperties(Entry(), ScanData().Property(), ScanData().DataPointer()); + return pTree; +} diff --git a/src/Core/Resource/Scan/CScan.h b/src/Core/Resource/Scan/CScan.h new file mode 100644 index 00000000..b8e19bc6 --- /dev/null +++ b/src/Core/Resource/Scan/CScan.h @@ -0,0 +1,34 @@ +#ifndef CSCAN_H +#define CSCAN_H + +#include +#include "Core/Resource/Animation/CAnimationParameters.h" +#include "Core/Resource/Script/CGameTemplate.h" +#include "Core/Resource/Script/NGameList.h" + +/** Scannable object parameters from SCAN assets */ +class CScan : public CResource +{ + DECLARE_RESOURCE_TYPE(Scan) + friend class CScanLoader; + friend class CScanCooker; + + /** Script template specifying scan data layout */ + CScriptTemplate* mpTemplate; + + /** Scan property data */ + std::vector mPropertyData; + +public: + CScan(CResourceEntry* pEntry = 0); + CStructRef ScanData() const; + + /** Convenience property accessors */ + CAssetRef ScanStringPropertyRef() const; + CBoolRef IsCriticalPropertyRef() const; + + /** CResource interface */ + virtual CDependencyTree* BuildDependencyTree() const override; +}; + +#endif // CSCAN_H diff --git a/src/Core/Resource/Scan/ELogbookCategory.h b/src/Core/Resource/Scan/ELogbookCategory.h new file mode 100644 index 00000000..cb195b63 --- /dev/null +++ b/src/Core/Resource/Scan/ELogbookCategory.h @@ -0,0 +1,14 @@ +#ifndef ELOGBOOKCATEGORY_H +#define ELOGBOOKCATEGORY_H + +/** Logbook category for scannable objects in MP1, used in SCAN and SAVW */ +enum class ELogbookCategory +{ + None = 0, + SpacePirateData = 1, + ChozoLore = 2, + Creatures = 3, + Research = 4 +}; + +#endif // ELOGBOOKCATEGORY_H diff --git a/src/Core/Resource/Scan/SScanParametersMP1.h b/src/Core/Resource/Scan/SScanParametersMP1.h new file mode 100644 index 00000000..624102f4 --- /dev/null +++ b/src/Core/Resource/Scan/SScanParametersMP1.h @@ -0,0 +1,60 @@ +#ifndef SSCANPARAMETERSMP1_H +#define SSCANPARAMETERSMP1_H + +#include "ELogbookCategory.h" +#include + +/** Struct mapping to SCAN property layout in MP1 */ +enum class EScanSpeed +{ + Normal = 0, + Slow = 1, +}; + +enum class EScanImagePane +{ + Pane0 = 0, + Pane1 = 1, + Pane2 = 2, + Pane3 = 3, + Pane01 = 4, + Pane12 = 5, + Pane23 = 6, + Pane012 = 7, + Pane123 = 8, + Pane0123 = 9, + Pane4 = 10, + Pane5 = 11, + Pane6 = 12, + Pane7 = 13, + Pane45 = 14, + Pane56 = 15, + Pane67 = 16, + Pane456 = 17, + Pane567 = 18, + Pane4567 = 19, + None = -1 +}; + +struct SScanImage +{ + CAssetID Texture; + float AppearPercentage; + EScanImagePane Pane; + int32 AnimationCellWidth; + int32 AnimationCellHeight; + float AnimationSwapInterval; + float FadeDuration; +}; + +struct SScanParametersMP1 +{ + CAssetID GuiFrame; + CAssetID String; + EScanSpeed Speed; + ELogbookCategory LogbookCategory; + bool IsCritical; + SScanImage ScanImages[4]; +}; + +#endif // SSCANPARAMETERSMP1_H diff --git a/src/Core/Resource/Script/Property/CAnimationSetProperty.h b/src/Core/Resource/Script/Property/CAnimationSetProperty.h index 90f3fde2..5248da64 100644 --- a/src/Core/Resource/Script/Property/CAnimationSetProperty.h +++ b/src/Core/Resource/Script/Property/CAnimationSetProperty.h @@ -2,6 +2,7 @@ #define CANIMATIONSETPROPERTY_H #include "IProperty.h" +#include "Core/Resource/Animation/CAnimationParameters.h" class CAnimationSetProperty : public TSerializeableTypedProperty< CAnimationParameters, EPropertyType::AnimationSet > { diff --git a/src/Core/Resource/Script/Property/IProperty.h b/src/Core/Resource/Script/Property/IProperty.h index 4f3f4d01..6b788e4c 100644 --- a/src/Core/Resource/Script/Property/IProperty.h +++ b/src/Core/Resource/Script/Property/IProperty.h @@ -1,7 +1,6 @@ #ifndef IPROPERTY_H #define IPROPERTY_H -#include "Core/Resource/Animation/CAnimationParameters.h" #include #include #include diff --git a/src/Core/ScriptExtra/CPointOfInterestExtra.cpp b/src/Core/ScriptExtra/CPointOfInterestExtra.cpp index c76d8bb1..8835e501 100644 --- a/src/Core/ScriptExtra/CPointOfInterestExtra.cpp +++ b/src/Core/ScriptExtra/CPointOfInterestExtra.cpp @@ -1,5 +1,6 @@ #include "CPointOfInterestExtra.h" +//@todo pull these values from tweaks instead of hardcoding them const CColor CPointOfInterestExtra::skRegularColor = CColor::Integral(0xFF,0x70,0x00); const CColor CPointOfInterestExtra::skImportantColor = CColor::Integral(0xFF,0x00,0x00); @@ -19,14 +20,17 @@ CPointOfInterestExtra::CPointOfInterestExtra(CScriptObject *pInstance, CScene *p void CPointOfInterestExtra::PropertyModified(IProperty* pProperty) { if (mScanProperty.Property() == pProperty) + { mpScanData = gpResourceStore->LoadResource( mScanProperty.Get() ); + mScanIsCritical = (mpScanData ? mpScanData->IsCriticalPropertyRef() : CBoolRef()); + } } void CPointOfInterestExtra::ModifyTintColor(CColor& Color) { if (mpScanData) { - if (mpScanData->IsImportant()) Color *= skImportantColor; + if (mScanIsCritical) Color *= skImportantColor; else Color *= skRegularColor; } } diff --git a/src/Core/ScriptExtra/CPointOfInterestExtra.h b/src/Core/ScriptExtra/CPointOfInterestExtra.h index ae699718..6f878b3c 100644 --- a/src/Core/ScriptExtra/CPointOfInterestExtra.h +++ b/src/Core/ScriptExtra/CPointOfInterestExtra.h @@ -2,7 +2,7 @@ #define CPOINTOFINTERESTEXTRA_H #include "CScriptExtra.h" -#include "Core/Resource/CScan.h" +#include "Core/Resource/Scan/CScan.h" #include class CPointOfInterestExtra : public CScriptExtra @@ -10,6 +10,7 @@ class CPointOfInterestExtra : public CScriptExtra // Tint POI billboard orange/red depending on scan importance CAssetRef mScanProperty; TResPtr mpScanData; + CBoolRef mScanIsCritical; public: explicit CPointOfInterestExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent = 0); diff --git a/src/Editor/Editor.pro b/src/Editor/Editor.pro index 4af9bb56..c410c1ee 100644 --- a/src/Editor/Editor.pro +++ b/src/Editor/Editor.pro @@ -97,14 +97,9 @@ HEADERS += \ Undo/CTranslateNodeCommand.h \ Undo/EUndoCommand.h \ Undo/UndoCommands.h \ - Widgets/IPreviewPanel.h \ Widgets/WColorPicker.h \ Widgets/WDraggableSpinBox.h \ Widgets/WIntegralSpinBox.h \ - Widgets/WScanPreviewPanel.h \ - Widgets/WStringPreviewPanel.h \ - Widgets/WTextureGLWidget.h \ - Widgets/WTexturePreviewPanel.h \ Widgets/WVectorEditor.h \ WorldEditor/CLayerEditor.h \ WorldEditor/CLayerModel.h \ @@ -216,14 +211,9 @@ SOURCES += \ Undo/CRotateNodeCommand.cpp \ Undo/CScaleNodeCommand.cpp \ Undo/CTranslateNodeCommand.cpp \ - Widgets/IPreviewPanel.cpp \ Widgets/WColorPicker.cpp \ Widgets/WDraggableSpinBox.cpp \ Widgets/WIntegralSpinBox.cpp \ - Widgets/WScanPreviewPanel.cpp \ - Widgets/WStringPreviewPanel.cpp \ - Widgets/WTextureGLWidget.cpp \ - Widgets/WTexturePreviewPanel.cpp \ Widgets/WVectorEditor.cpp \ WorldEditor/CLayerEditor.cpp \ WorldEditor/CLayerModel.cpp \ @@ -293,8 +283,6 @@ SOURCES += \ FORMS += \ TestDialog.ui \ ModelEditor/CModelEditorWindow.ui \ - Widgets/WScanPreviewPanel.ui \ - Widgets/WTexturePreviewPanel.ui \ WorldEditor/CLayerEditor.ui \ WorldEditor/CWorldEditor.ui \ WorldEditor/WCreateTab.ui \ diff --git a/src/Editor/Widgets/IPreviewPanel.cpp b/src/Editor/Widgets/IPreviewPanel.cpp deleted file mode 100644 index 49796cc8..00000000 --- a/src/Editor/Widgets/IPreviewPanel.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "IPreviewPanel.h" -#include "WScanPreviewPanel.h" -#include "WStringPreviewPanel.h" -#include "WTexturePreviewPanel.h" - -IPreviewPanel::IPreviewPanel(QWidget *parent) : QFrame(parent) -{ - setFrameShape(QFrame::StyledPanel); - setFrameShadow(QFrame::Plain); - setLineWidth(2); -} - -// Can add more if more preview types are implemented -// Not every resource type is really suitable for this though unfortunately -IPreviewPanel* IPreviewPanel::CreatePanel(EResourceType Type, QWidget *pParent) -{ - switch (Type) - { - case EResourceType::Texture: return new WTexturePreviewPanel(pParent); - case EResourceType::StringTable: return new WStringPreviewPanel(pParent); - case EResourceType::Scan: return new WScanPreviewPanel(pParent); - default: return nullptr; - } -} diff --git a/src/Editor/Widgets/IPreviewPanel.h b/src/Editor/Widgets/IPreviewPanel.h deleted file mode 100644 index acbd401c..00000000 --- a/src/Editor/Widgets/IPreviewPanel.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef IPREVIEWPANEL_H -#define IPREVIEWPANEL_H - -#include -#include - -#include - -class IPreviewPanel : public QFrame -{ -public: - explicit IPreviewPanel(QWidget *parent = 0); - virtual EResourceType ResType() = 0; - virtual void SetResource(CResource *pRes) = 0; - static IPreviewPanel* CreatePanel(EResourceType Type, QWidget *pParent = 0); -}; - -#endif // IPREVIEWPANEL_H diff --git a/src/Editor/Widgets/WScanPreviewPanel.cpp b/src/Editor/Widgets/WScanPreviewPanel.cpp deleted file mode 100644 index 8121e22a..00000000 --- a/src/Editor/Widgets/WScanPreviewPanel.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "WScanPreviewPanel.h" -#include "ui_WScanPreviewPanel.h" -#include "WStringPreviewPanel.h" -#include - -WScanPreviewPanel::WScanPreviewPanel(QWidget *pParent) - : IPreviewPanel(pParent) - , ui(new Ui::WScanPreviewPanel) -{ - ui->setupUi(this); - - ui->ScanTextWidget->setFrameShape(QFrame::NoFrame); - ui->ScanTextWidget->layout()->setContentsMargins(9,0,9,9); -} - -WScanPreviewPanel::~WScanPreviewPanel() -{ - delete ui; -} - -QSize WScanPreviewPanel::sizeHint() const -{ - return QSize(400, 0); -} - -EResourceType WScanPreviewPanel::ResType() -{ - return EResourceType::Scan; -} - -void WScanPreviewPanel::SetResource(CResource *pRes) -{ - // Clear existing UI - ui->ScanTypeLabel->clear(); - ui->ScanSpeedLabel->clear(); - ui->ScanCategoryLabel->clear(); - - // Set up new UI - if (pRes && (pRes->Type() == EResourceType::Scan)) - { - CScan *pScan = static_cast(pRes); - - // Scan type - if (pScan->IsImportant()) - ui->ScanTypeLabel->setText("Important"); - else - { - if (pScan->Game() <= EGame::Prime) - ui->ScanTypeLabel->setText("Normal"); - else - ui->ScanTypeLabel->setText("Normal"); - } - - // Scan speed - if (pScan->IsSlow()) - ui->ScanSpeedLabel->setText("Slow"); - else - ui->ScanSpeedLabel->setText("Fast"); - - // Scan category - switch (pScan->LogbookCategory()) - { - case CScan::ELogbookCategory::None: - ui->ScanCategoryLabel->setText("None"); - break; - case CScan::ELogbookCategory::ChozoLore: - ui->ScanCategoryLabel->setText("Chozo Lore"); - break; - case CScan::ELogbookCategory::PirateData: - ui->ScanCategoryLabel->setText("Pirate Data"); - break; - case CScan::ELogbookCategory::Creatures: - ui->ScanCategoryLabel->setText("Creatures"); - break; - case CScan::ELogbookCategory::Research: - ui->ScanCategoryLabel->setText("Research"); - break; - } - - // Scan text - ui->ScanTextWidget->SetResource(pScan->ScanText()); - - // Show logbook category? (Yes on MP1, no on MP2+) - if (pScan->Game() <= EGame::Prime) - { - ui->CategoryInfoLabel->show(); - ui->ScanCategoryLabel->show(); - } - - else - { - ui->CategoryInfoLabel->hide(); - ui->ScanCategoryLabel->hide(); - } - } - - else - ui->ScanTextWidget->SetResource(nullptr); -} diff --git a/src/Editor/Widgets/WScanPreviewPanel.h b/src/Editor/Widgets/WScanPreviewPanel.h deleted file mode 100644 index 6b5f46e2..00000000 --- a/src/Editor/Widgets/WScanPreviewPanel.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef WSCANPREVIEWPANEL_H -#define WSCANPREVIEWPANEL_H - -#include "IPreviewPanel.h" - -namespace Ui { -class WScanPreviewPanel; -} - -class WScanPreviewPanel : public IPreviewPanel -{ - Q_OBJECT - -public: - explicit WScanPreviewPanel(QWidget *pParent = 0); - ~WScanPreviewPanel(); - QSize sizeHint() const; - EResourceType ResType(); - void SetResource(CResource *pRes); - -private: - Ui::WScanPreviewPanel *ui; -}; - -#endif // WSCANPREVIEWPANEL_H diff --git a/src/Editor/Widgets/WScanPreviewPanel.ui b/src/Editor/Widgets/WScanPreviewPanel.ui deleted file mode 100644 index df30c17e..00000000 --- a/src/Editor/Widgets/WScanPreviewPanel.ui +++ /dev/null @@ -1,159 +0,0 @@ - - - WScanPreviewPanel - - - - 0 - 0 - 400 - 38 - - - - - 0 - 0 - - - - - 400 - 0 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 9 - - - 0 - - - 9 - - - 0 - - - - - - - Type: - - - - - - - TextLabel - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Logbook: - - - - - - - TextLabel - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Speed: - - - - - - - TextLabel - - - - - - - - - - - - 0 - 1 - - - - - - - - - WStringPreviewPanel - QWidget -
Editor/Widgets/WStringPreviewPanel.h
- 1 -
-
- - -
diff --git a/src/Editor/Widgets/WStringPreviewPanel.cpp b/src/Editor/Widgets/WStringPreviewPanel.cpp deleted file mode 100644 index cc1b9824..00000000 --- a/src/Editor/Widgets/WStringPreviewPanel.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "WStringPreviewPanel.h" -#include "Editor/UICommon.h" -#include - -#include -#include - -WStringPreviewPanel::WStringPreviewPanel(QWidget *pParent) - : IPreviewPanel(pParent) -{ - mpLayout = new QVBoxLayout(this); - mpLayout->setAlignment(Qt::AlignTop); - mpLayout->setSpacing(0); - setLayout(mpLayout); -} - -WStringPreviewPanel::~WStringPreviewPanel() -{ -} - -QSize WStringPreviewPanel::sizeHint() const -{ - return QSize(400, 0); -} - -EResourceType WStringPreviewPanel::ResType() -{ - return EResourceType::StringTable; -} - -void WStringPreviewPanel::SetResource(CResource *pRes) -{ - foreach(const QLabel *pLabel, mLabels) - delete pLabel; - mLabels.clear(); - - if (pRes && (pRes->Type() == EResourceType::StringTable)) - { - CStringTable *pString = static_cast(pRes); - mLabels.reserve(pString->NumStrings()); - - for (uint32 iStr = 0; iStr < pString->NumStrings(); iStr++) - { - QString text = TO_QSTRING(pString->GetString(ELanguage::English, iStr)); - QLabel *pLabel = new QLabel(text, this); - pLabel->setWordWrap(true); - pLabel->setFrameStyle(QFrame::Plain | QFrame::Box); - pLabel->setMargin(3); - mLabels.push_back(pLabel); - mpLayout->addWidget(pLabel); - } - } -} diff --git a/src/Editor/Widgets/WStringPreviewPanel.h b/src/Editor/Widgets/WStringPreviewPanel.h deleted file mode 100644 index d266d580..00000000 --- a/src/Editor/Widgets/WStringPreviewPanel.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef WSTRINGPREVIEWPANEL_H -#define WSTRINGPREVIEWPANEL_H - -#include "IPreviewPanel.h" -#include -#include -#include - -class WStringPreviewPanel : public IPreviewPanel -{ - Q_OBJECT - - QVector mLabels; - QVBoxLayout *mpLayout; - -public: - explicit WStringPreviewPanel(QWidget *pParent = 0); - ~WStringPreviewPanel(); - QSize sizeHint() const; - EResourceType ResType(); - void SetResource(CResource *pRes); -}; - -#endif // WSTRINGPREVIEWPANEL_H diff --git a/src/Editor/Widgets/WTextureGLWidget.cpp b/src/Editor/Widgets/WTextureGLWidget.cpp deleted file mode 100644 index 4057f0fb..00000000 --- a/src/Editor/Widgets/WTextureGLWidget.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#include "WTextureGLWidget.h" -#include -#include -#include -#include -#include -#include - -WTextureGLWidget::WTextureGLWidget(QWidget *pParent, CTexture *pTex) - : QOpenGLWidget(pParent) -{ - SetTexture(pTex); - mInitialized = false; -} - -WTextureGLWidget::~WTextureGLWidget() -{ - if (mInitialized) CGraphics::ReleaseContext(mContextID); -} - -void WTextureGLWidget::initializeGL() -{ - CGraphics::Initialize(); - glEnable(GL_BLEND); - mContextID = CGraphics::GetContextIndex(); - mInitialized = true; -} - -void WTextureGLWidget::paintGL() -{ - CGraphics::SetActiveContext(mContextID); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glClearColor(1.f, 0.f, 0.f, 0.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); - - // Set matrices to identity - CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity; - CGraphics::sMVPBlock.ViewMatrix = CMatrix4f::skIdentity; - CGraphics::sMVPBlock.ProjectionMatrix = CMatrix4f::skIdentity; - CGraphics::UpdateMVPBlock(); - - // Draw checkerboard background - CDrawUtil::UseTextureShader(); - glDepthMask(GL_FALSE); - CDrawUtil::LoadCheckerboardTexture(0); - CDrawUtil::DrawSquare(&mCheckerCoords[0].X); - - // Make it darker - CDrawUtil::UseColorShader(CColor::Integral(0.0f, 0.0f, 0.0f, 0.5f)); - glDepthMask(GL_FALSE); - CDrawUtil::DrawSquare(); - - // Leave it at just the checkerboard if there's no texture - if (!mpTexture) return; - - // Draw texture - CDrawUtil::UseTextureShader(); - mpTexture->Bind(0); - CGraphics::sMVPBlock.ModelMatrix = mTexTransform; - CGraphics::UpdateMVPBlock(); - CDrawUtil::DrawSquare(); - - glEnable(GL_DEPTH_TEST); -} - -void WTextureGLWidget::resizeGL(int Width, int Height) -{ - mAspectRatio = (float) Width / (float) Height; - glViewport(0, 0, Width, Height); - - CalcTexTransform(); - CalcCheckerCoords(); - update(); -} - -void WTextureGLWidget::SetTexture(CTexture *pTex) -{ - mpTexture = pTex; - - if (pTex) mTexAspectRatio = (float) pTex->Width() / (float) pTex->Height(); - else mTexAspectRatio = 0.f; - - CalcTexTransform(); - CalcCheckerCoords(); - update(); -} - -void WTextureGLWidget::CalcTexTransform() -{ - // This is a simple scale based on the dimensions of the viewport, in order to - // avoid stretching the texture if it doesn't match the viewport aspect ratio. - mTexTransform = CTransform4f::skIdentity; - float Diff = mTexAspectRatio / mAspectRatio; - - if (mAspectRatio >= mTexAspectRatio) - mTexTransform.Scale(Diff, 1.f, 1.f); - else - mTexTransform.Scale(1.f, 1.f / Diff, 1.f); -} - -void WTextureGLWidget::CalcCheckerCoords() -{ - // The translation vector is set up so the checkerboard stays centered on the screen - // rather than expanding from the bottom-left corner. This makes it look more natural. - CVector2f Trans; - float InvAspect = (mAspectRatio == 0.f) ? 0.f : 1.f / mAspectRatio; - float InvTexAspect = (mTexAspectRatio == 0.f) ? 0.f : 1.f / mTexAspectRatio; - float XBase, YBase, XScale, YScale; - - // Horizontal texture - if ((mpTexture != nullptr) && (mpTexture->Width() > mpTexture->Height())) - { - XBase = 1.f; - YBase = InvTexAspect; - XScale = InvTexAspect; - YScale = 1.f; - } - // Vertical texture - else - { - XBase = mTexAspectRatio; - YBase = 1.f; - XScale = 1.f; - YScale = mTexAspectRatio; - } - - // Space on left/right - if (mAspectRatio > mTexAspectRatio) - { - Trans = CVector2f(mAspectRatio / 2.f, 0.5f) * -XScale; - mCheckerCoords[0] = CVector2f(0.f, YBase); - mCheckerCoords[1] = CVector2f(mAspectRatio * XScale, YBase); - mCheckerCoords[2] = CVector2f(mAspectRatio * XScale, 0.f); - mCheckerCoords[3] = CVector2f(0.f, 0.f); - } - - // Space on top/bottom - else - { - Trans = CVector2f(0.5f, InvAspect / 2.f) * -YScale; - mCheckerCoords[0] = CVector2f(0.f, InvAspect * YScale); - mCheckerCoords[1] = CVector2f(XBase, InvAspect * YScale); - mCheckerCoords[2] = CVector2f(XBase, 0.f); - mCheckerCoords[3] = CVector2f(0.f, 0.f); - } - - // Finally, apply translation/scale - for (uint32 iCoord = 0; iCoord < 4; iCoord++) - { - mCheckerCoords[iCoord] += Trans; - mCheckerCoords[iCoord] *= 10.f; - } - -} diff --git a/src/Editor/Widgets/WTextureGLWidget.h b/src/Editor/Widgets/WTextureGLWidget.h deleted file mode 100644 index 68dd5752..00000000 --- a/src/Editor/Widgets/WTextureGLWidget.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef WTEXTUREGLWIDGET_H -#define WTEXTUREGLWIDGET_H - -#include -#include -#include -#include - -#include -#include -#include - -class WTextureGLWidget : public QOpenGLWidget -{ - Q_OBJECT - - float mAspectRatio; - TResPtr mpTexture; - float mTexAspectRatio; - CTransform4f mTexTransform; - CVector2f mCheckerCoords[4]; - uint32 mContextID; - bool mInitialized; - -public: - explicit WTextureGLWidget(QWidget *pParent = 0, CTexture *pTex = 0); - ~WTextureGLWidget(); - void initializeGL(); - void paintGL(); - void resizeGL(int Width, int Height); - void SetTexture(CTexture *pTex); - -private: - void CalcTexTransform(); - void CalcCheckerCoords(); -}; - -#endif // WTEXTUREGLWIDGET_H diff --git a/src/Editor/Widgets/WTexturePreviewPanel.cpp b/src/Editor/Widgets/WTexturePreviewPanel.cpp deleted file mode 100644 index 2e841eb3..00000000 --- a/src/Editor/Widgets/WTexturePreviewPanel.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "WTexturePreviewPanel.h" -#include "ui_WTexturePreviewPanel.h" -#include "WTextureGLWidget.h" -#include "Editor/UICommon.h" - -WTexturePreviewPanel::WTexturePreviewPanel(QWidget *parent, CTexture *pTexture) - : IPreviewPanel(parent) - , ui(new Ui::WTexturePreviewPanel) -{ - ui->setupUi(this); - SetResource(pTexture); -} - -WTexturePreviewPanel::~WTexturePreviewPanel() -{ - delete ui; -} - -EResourceType WTexturePreviewPanel::ResType() -{ - return EResourceType::Texture; -} - -void WTexturePreviewPanel::SetResource(CResource *pRes) -{ - CTexture *pTexture = (CTexture*) pRes; - ui->TextureGLWidget->SetTexture(pTexture); - - if (pTexture) - { - TString Name = pTexture->Source(); - ui->TextureNameLabel->setText( TO_QSTRING(Name) ); - - QString TexInfo; - TexInfo += QString::number(pTexture->Width()) + "x" + QString::number(pTexture->Height()); - TexInfo += " "; - - switch (pTexture->SourceTexelFormat()) - { - case ETexelFormat::GX_I4: TexInfo += "I4"; break; - case ETexelFormat::GX_I8: TexInfo += "I8"; break; - case ETexelFormat::GX_IA4: TexInfo += "IA4"; break; - case ETexelFormat::GX_IA8: TexInfo += "IA8"; break; - case ETexelFormat::GX_C4: TexInfo += "C4"; break; - case ETexelFormat::GX_C8: TexInfo += "C8"; break; - case ETexelFormat::GX_C14x2: TexInfo += "C14x2"; break; - case ETexelFormat::GX_RGB565: TexInfo += "RGB565"; break; - case ETexelFormat::GX_RGB5A3: TexInfo += "RGB5A3"; break; - case ETexelFormat::GX_RGBA8: TexInfo += "RGBA8"; break; - case ETexelFormat::GX_CMPR: TexInfo += "CMPR"; break; - default: TexInfo += "Invalid Format"; break; - } - - TexInfo += " / "; - TexInfo += QString::number(pTexture->NumMipMaps()) + " mipmaps"; - - ui->TextureInfoLabel->setText(TexInfo); - } - else - { - ui->TextureNameLabel->setText("No texture"); - ui->TextureInfoLabel->setText(""); - } -} diff --git a/src/Editor/Widgets/WTexturePreviewPanel.h b/src/Editor/Widgets/WTexturePreviewPanel.h deleted file mode 100644 index 0cfd0bcc..00000000 --- a/src/Editor/Widgets/WTexturePreviewPanel.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef WTEXTUREPREVIEWPANEL_H -#define WTEXTUREPREVIEWPANEL_H - -#include "IPreviewPanel.h" -#include - -namespace Ui { -class WTexturePreviewPanel; -} - -class WTexturePreviewPanel : public IPreviewPanel -{ - Q_OBJECT - -public: - explicit WTexturePreviewPanel(QWidget *pParent = 0, CTexture *pTexture = 0); - ~WTexturePreviewPanel(); - EResourceType ResType(); - void SetResource(CResource *pRes); - -private: - Ui::WTexturePreviewPanel *ui; -}; - -#endif // WTEXTUREPREVIEWPANEL_H diff --git a/src/Editor/Widgets/WTexturePreviewPanel.ui b/src/Editor/Widgets/WTexturePreviewPanel.ui deleted file mode 100644 index 8e7e25d6..00000000 --- a/src/Editor/Widgets/WTexturePreviewPanel.ui +++ /dev/null @@ -1,77 +0,0 @@ - - - WTexturePreviewPanel - - - - 0 - 0 - 260 - 305 - - - - - 0 - 0 - - - - Form - - - - 2 - - - 2 - - - 2 - - - - - - 0 - 0 - - - - - 256 - 256 - - - - - - - - TextureName - - - true - - - - - - - TextureInfo - - - - - - - - WTextureGLWidget - QWidget -
Editor/Widgets/WTextureGLWidget.h
- 1 -
-
- - -
diff --git a/src/Editor/WorldEditor/CPoiListDialog.h b/src/Editor/WorldEditor/CPoiListDialog.h index a39fd829..84e8586f 100644 --- a/src/Editor/WorldEditor/CPoiListDialog.h +++ b/src/Editor/WorldEditor/CPoiListDialog.h @@ -4,7 +4,7 @@ #include "CPoiMapModel.h" #include "Editor/UICommon.h" -#include +#include #include #include #include @@ -57,7 +57,7 @@ public: { CScriptNode *pNode = mObjList[rkIndex.row()]; CScan *pScan = static_cast(pNode->Extra())->GetScan(); - bool IsImportant = (pScan ? pScan->IsImportant() : false); + bool IsImportant = (pScan ? pScan->IsCriticalPropertyRef() : false); if (IsImportant) return QIcon(":/icons/POI Important.png"); diff --git a/src/Editor/WorldEditor/CPoiMapModel.cpp b/src/Editor/WorldEditor/CPoiMapModel.cpp index 6ebeb872..cb254385 100644 --- a/src/Editor/WorldEditor/CPoiMapModel.cpp +++ b/src/Editor/WorldEditor/CPoiMapModel.cpp @@ -52,7 +52,7 @@ QVariant CPoiMapModel::data(const QModelIndex& rkIndex, int Role) const CScan *pScan = static_cast(pNode->Extra())->GetScan(); if (pScan) - IsImportant = pScan->IsImportant(); + IsImportant = pScan->IsCriticalPropertyRef(); } if (IsImportant) diff --git a/src/Editor/WorldEditor/CPoiMapSidebar.cpp b/src/Editor/WorldEditor/CPoiMapSidebar.cpp index 146a73aa..5aff53bd 100644 --- a/src/Editor/WorldEditor/CPoiMapSidebar.cpp +++ b/src/Editor/WorldEditor/CPoiMapSidebar.cpp @@ -3,8 +3,8 @@ #include "CWorldEditor.h" #include "Editor/UICommon.h" -#include #include +#include #include #include #include @@ -171,7 +171,7 @@ bool CPoiMapSidebar::IsImportant(const QModelIndex& rkIndex) TResPtr pScan = static_cast(pPOI->Extra())->GetScan(); if (pScan) - Important = pScan->IsImportant(); + Important = pScan->IsCriticalPropertyRef(); return Important; } diff --git a/templates/MP1/Enums/ScanImagePane.xml b/templates/MP1/Enums/ScanImagePane.xml index b9cd0d2c..82cd47f0 100644 --- a/templates/MP1/Enums/ScanImagePane.xml +++ b/templates/MP1/Enums/ScanImagePane.xml @@ -23,6 +23,7 @@ + diff --git a/templates/MP1/Misc/ScannableObjectInfo.xml b/templates/MP1/Misc/ScannableObjectInfo.xml index eee5fb64..9cc439b5 100644 --- a/templates/MP1/Misc/ScannableObjectInfo.xml +++ b/templates/MP1/Misc/ScannableObjectInfo.xml @@ -10,7 +10,7 @@ FRME - + String STRG diff --git a/templates/MP2/Misc/ScannableObjectInfo.xml b/templates/MP2/Misc/ScannableObjectInfo.xml index 2e4306b1..7ab82fe4 100644 --- a/templates/MP2/Misc/ScannableObjectInfo.xml +++ b/templates/MP2/Misc/ScannableObjectInfo.xml @@ -24,6 +24,8 @@ CMDL + + diff --git a/templates/MP2/Structs/ScanInfoSecondaryModel.xml b/templates/MP2/Structs/ScanInfoSecondaryModel.xml index 9f10650b..ab051abd 100644 --- a/templates/MP2/Structs/ScanInfoSecondaryModel.xml +++ b/templates/MP2/Structs/ScanInfoSecondaryModel.xml @@ -8,7 +8,7 @@ CMDL - +