mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-06-05 22:23:34 +00:00
Rewrote SCAN asset handling + loading
This commit is contained in:
parent
a174548750
commit
a1d94cc58f
@ -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
|
||||
|
@ -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 <Common/Math/MathUtil.h>
|
||||
|
||||
@ -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<SScanParametersMP1*>(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));
|
||||
}
|
||||
|
@ -30,6 +30,70 @@ void IDependencyNode::GetAllResourceReferences(std::set<CAssetID>& 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<CStructProperty>(pProp), pData );
|
||||
|
||||
else if (Type == EPropertyType::Sound)
|
||||
{
|
||||
uint32 SoundID = TPropCast<CSoundProperty>(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<CAssetProperty>(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<CAnimationSetProperty>(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<CStructProperty>(pProp));
|
||||
|
||||
else if (Type == EPropertyType::Sound)
|
||||
{
|
||||
uint32 SoundID = TPropCast<CSoundProperty>(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<CAssetProperty>(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<CAnimationSetProperty>(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
|
||||
{
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
virtual void Serialize(IArchive& rArc) = 0;
|
||||
virtual void GetAllResourceReferences(std::set<CAssetID>& 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.
|
||||
|
@ -2,9 +2,10 @@
|
||||
#define CANIMATIONPARAMETERS_H
|
||||
|
||||
#include "Core/Resource/TResPtr.h"
|
||||
#include "Core/Resource/Model/CModel.h"
|
||||
#include <Common/EGame.h>
|
||||
|
||||
class CModel;
|
||||
|
||||
class CAnimationParameters
|
||||
{
|
||||
EGame mGame;
|
||||
|
@ -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");
|
||||
|
@ -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 <Common/EGame.h>
|
||||
|
||||
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<CStringTable> 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<SScanInfoSecondaryModel> mSecondaryModels;
|
||||
|
||||
// MP3
|
||||
std::vector<CAssetID> 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
|
@ -1,306 +1,83 @@
|
||||
#include "CScanLoader.h"
|
||||
#include "Core/GameProject/CResourceStore.h"
|
||||
#include "CScriptLoader.h"
|
||||
#include <Common/Log.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -7,15 +7,10 @@
|
||||
class CScanLoader
|
||||
{
|
||||
TResPtr<CScan> 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);
|
||||
|
51
src/Core/Resource/Scan/CScan.cpp
Normal file
51
src/Core/Resource/Scan/CScan.cpp
Normal file
@ -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;
|
||||
}
|
34
src/Core/Resource/Scan/CScan.h
Normal file
34
src/Core/Resource/Scan/CScan.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef CSCAN_H
|
||||
#define CSCAN_H
|
||||
|
||||
#include <Common/Common.h>
|
||||
#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<uint8> 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
|
14
src/Core/Resource/Scan/ELogbookCategory.h
Normal file
14
src/Core/Resource/Scan/ELogbookCategory.h
Normal file
@ -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
|
60
src/Core/Resource/Scan/SScanParametersMP1.h
Normal file
60
src/Core/Resource/Scan/SScanParametersMP1.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef SSCANPARAMETERSMP1_H
|
||||
#define SSCANPARAMETERSMP1_H
|
||||
|
||||
#include "ELogbookCategory.h"
|
||||
#include <Common/Common.h>
|
||||
|
||||
/** 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
|
@ -2,6 +2,7 @@
|
||||
#define CANIMATIONSETPROPERTY_H
|
||||
|
||||
#include "IProperty.h"
|
||||
#include "Core/Resource/Animation/CAnimationParameters.h"
|
||||
|
||||
class CAnimationSetProperty : public TSerializeableTypedProperty< CAnimationParameters, EPropertyType::AnimationSet >
|
||||
{
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef IPROPERTY_H
|
||||
#define IPROPERTY_H
|
||||
|
||||
#include "Core/Resource/Animation/CAnimationParameters.h"
|
||||
#include <Common/Common.h>
|
||||
#include <Common/CFourCC.h>
|
||||
#include <Common/Math/CVector3f.h>
|
||||
|
@ -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<CScan>( 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;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define CPOINTOFINTERESTEXTRA_H
|
||||
|
||||
#include "CScriptExtra.h"
|
||||
#include "Core/Resource/CScan.h"
|
||||
#include "Core/Resource/Scan/CScan.h"
|
||||
#include <Common/CColor.h>
|
||||
|
||||
class CPointOfInterestExtra : public CScriptExtra
|
||||
@ -10,6 +10,7 @@ class CPointOfInterestExtra : public CScriptExtra
|
||||
// Tint POI billboard orange/red depending on scan importance
|
||||
CAssetRef mScanProperty;
|
||||
TResPtr<CScan> mpScanData;
|
||||
CBoolRef mScanIsCritical;
|
||||
|
||||
public:
|
||||
explicit CPointOfInterestExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent = 0);
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#ifndef IPREVIEWPANEL_H
|
||||
#define IPREVIEWPANEL_H
|
||||
|
||||
#include <Core/Resource/CResource.h>
|
||||
#include <Core/Resource/EResType.h>
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
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
|
@ -1,99 +0,0 @@
|
||||
#include "WScanPreviewPanel.h"
|
||||
#include "ui_WScanPreviewPanel.h"
|
||||
#include "WStringPreviewPanel.h"
|
||||
#include <Core/Resource/CScan.h>
|
||||
|
||||
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<CScan*>(pRes);
|
||||
|
||||
// Scan type
|
||||
if (pScan->IsImportant())
|
||||
ui->ScanTypeLabel->setText("<b><font color=\"red\">Important</font></b>");
|
||||
else
|
||||
{
|
||||
if (pScan->Game() <= EGame::Prime)
|
||||
ui->ScanTypeLabel->setText("<b><font color=\"#FF9030\">Normal</font></b>");
|
||||
else
|
||||
ui->ScanTypeLabel->setText("<b><font color=\"#A0A0FF\">Normal</font></b>");
|
||||
}
|
||||
|
||||
// Scan speed
|
||||
if (pScan->IsSlow())
|
||||
ui->ScanSpeedLabel->setText("<b><font color=\"blue\">Slow</font></b>");
|
||||
else
|
||||
ui->ScanSpeedLabel->setText("<b><font color=\"green\">Fast</font></b>");
|
||||
|
||||
// Scan category
|
||||
switch (pScan->LogbookCategory())
|
||||
{
|
||||
case CScan::ELogbookCategory::None:
|
||||
ui->ScanCategoryLabel->setText("<b>None</b>");
|
||||
break;
|
||||
case CScan::ELogbookCategory::ChozoLore:
|
||||
ui->ScanCategoryLabel->setText("<b>Chozo Lore</b>");
|
||||
break;
|
||||
case CScan::ELogbookCategory::PirateData:
|
||||
ui->ScanCategoryLabel->setText("<b>Pirate Data</b>");
|
||||
break;
|
||||
case CScan::ELogbookCategory::Creatures:
|
||||
ui->ScanCategoryLabel->setText("<b>Creatures</b>");
|
||||
break;
|
||||
case CScan::ELogbookCategory::Research:
|
||||
ui->ScanCategoryLabel->setText("<b>Research</b>");
|
||||
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);
|
||||
}
|
@ -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
|
@ -1,159 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>WScanPreviewPanel</class>
|
||||
<widget class="QWidget" name="WScanPreviewPanel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>38</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ScanInfoLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ScanTypeInfoLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="TypeInfoLabel">
|
||||
<property name="text">
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="ScanTypeLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="HorizSpacer1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ScanCategoryInfoLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="CategoryInfoLabel">
|
||||
<property name="text">
|
||||
<string>Logbook:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="ScanCategoryLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="HorizSpacer2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ScanSpeedInfoLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="SpeedInfoLabel">
|
||||
<property name="text">
|
||||
<string>Speed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="ScanSpeedLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="WStringPreviewPanel" name="ScanTextWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>WStringPreviewPanel</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Editor/Widgets/WStringPreviewPanel.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,53 +0,0 @@
|
||||
#include "WStringPreviewPanel.h"
|
||||
#include "Editor/UICommon.h"
|
||||
#include <Core/Resource/StringTable/CStringTable.h>
|
||||
|
||||
#include <QFontMetrics>
|
||||
#include <QTextLayout>
|
||||
|
||||
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<CStringTable*>(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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
#ifndef WSTRINGPREVIEWPANEL_H
|
||||
#define WSTRINGPREVIEWPANEL_H
|
||||
|
||||
#include "IPreviewPanel.h"
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QVector>
|
||||
|
||||
class WStringPreviewPanel : public IPreviewPanel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QVector<QLabel*> mLabels;
|
||||
QVBoxLayout *mpLayout;
|
||||
|
||||
public:
|
||||
explicit WStringPreviewPanel(QWidget *pParent = 0);
|
||||
~WStringPreviewPanel();
|
||||
QSize sizeHint() const;
|
||||
EResourceType ResType();
|
||||
void SetResource(CResource *pRes);
|
||||
};
|
||||
|
||||
#endif // WSTRINGPREVIEWPANEL_H
|
@ -1,155 +0,0 @@
|
||||
#include "WTextureGLWidget.h"
|
||||
#include <Common/Math/CTransform4f.h>
|
||||
#include <Core/GameProject/CResourceStore.h>
|
||||
#include <Core/Render/CDrawUtil.h>
|
||||
#include <Core/Render/CGraphics.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
#ifndef WTEXTUREGLWIDGET_H
|
||||
#define WTEXTUREGLWIDGET_H
|
||||
|
||||
#include <Common/Math/CTransform4f.h>
|
||||
#include <Common/Math/CVector2f.h>
|
||||
#include <Core/Resource/TResPtr.h>
|
||||
#include <Core/Resource/CTexture.h>
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
#include <QTimer>
|
||||
#include <GL/glew.h>
|
||||
|
||||
class WTextureGLWidget : public QOpenGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
float mAspectRatio;
|
||||
TResPtr<CTexture> 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
|
@ -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("");
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
#ifndef WTEXTUREPREVIEWPANEL_H
|
||||
#define WTEXTUREPREVIEWPANEL_H
|
||||
|
||||
#include "IPreviewPanel.h"
|
||||
#include <Core/Resource/CTexture.h>
|
||||
|
||||
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
|
@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>WTexturePreviewPanel</class>
|
||||
<widget class="QWidget" name="WTexturePreviewPanel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>260</width>
|
||||
<height>305</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="WTextureGLWidget" name="TextureGLWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>256</width>
|
||||
<height>256</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="TextureNameLabel">
|
||||
<property name="text">
|
||||
<string>TextureName</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="TextureInfoLabel">
|
||||
<property name="text">
|
||||
<string>TextureInfo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>WTextureGLWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Editor/Widgets/WTextureGLWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -4,7 +4,7 @@
|
||||
#include "CPoiMapModel.h"
|
||||
#include "Editor/UICommon.h"
|
||||
|
||||
#include <Core/Resource/CScan.h>
|
||||
#include <Core/Resource/Scan/CScan.h>
|
||||
#include <Core/Resource/Script/CScriptTemplate.h>
|
||||
#include <Core/Scene/CScene.h>
|
||||
#include <Core/ScriptExtra/CPointOfInterestExtra.h>
|
||||
@ -57,7 +57,7 @@ public:
|
||||
{
|
||||
CScriptNode *pNode = mObjList[rkIndex.row()];
|
||||
CScan *pScan = static_cast<CPointOfInterestExtra*>(pNode->Extra())->GetScan();
|
||||
bool IsImportant = (pScan ? pScan->IsImportant() : false);
|
||||
bool IsImportant = (pScan ? pScan->IsCriticalPropertyRef() : false);
|
||||
|
||||
if (IsImportant)
|
||||
return QIcon(":/icons/POI Important.png");
|
||||
|
@ -52,7 +52,7 @@ QVariant CPoiMapModel::data(const QModelIndex& rkIndex, int Role) const
|
||||
CScan *pScan = static_cast<CPointOfInterestExtra*>(pNode->Extra())->GetScan();
|
||||
|
||||
if (pScan)
|
||||
IsImportant = pScan->IsImportant();
|
||||
IsImportant = pScan->IsCriticalPropertyRef();
|
||||
}
|
||||
|
||||
if (IsImportant)
|
||||
|
@ -3,8 +3,8 @@
|
||||
#include "CWorldEditor.h"
|
||||
#include "Editor/UICommon.h"
|
||||
|
||||
#include <Core/Resource/CScan.h>
|
||||
#include <Core/Resource/Cooker/CPoiToWorldCooker.h>
|
||||
#include <Core/Resource/Scan/CScan.h>
|
||||
#include <Core/Resource/Script/CGameTemplate.h>
|
||||
#include <Core/Resource/Script/NGameList.h>
|
||||
#include <Core/ScriptExtra/CPointOfInterestExtra.h>
|
||||
@ -171,7 +171,7 @@ bool CPoiMapSidebar::IsImportant(const QModelIndex& rkIndex)
|
||||
TResPtr<CScan> pScan = static_cast<CPointOfInterestExtra*>(pPOI->Extra())->GetScan();
|
||||
|
||||
if (pScan)
|
||||
Important = pScan->IsImportant();
|
||||
Important = pScan->IsCriticalPropertyRef();
|
||||
|
||||
return Important;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
<Element Name="Pane456" ID="0x11"/>
|
||||
<Element Name="Pane567" ID="0x12"/>
|
||||
<Element Name="Pane4567" ID="0x13"/>
|
||||
<Element Name="None" ID="0xFFFFFFFF"/>
|
||||
</Values>
|
||||
</PropertyArchetype>
|
||||
</PropertyTemplate>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<Element>FRME</Element>
|
||||
</TypeFilter>
|
||||
</Element>
|
||||
<Element Type="Asset" ID="0x0">
|
||||
<Element Type="Asset" ID="0x1">
|
||||
<Name>String</Name>
|
||||
<TypeFilter>
|
||||
<Element>STRG</Element>
|
||||
|
@ -24,6 +24,8 @@
|
||||
<Element>CMDL</Element>
|
||||
</TypeFilter>
|
||||
</Element>
|
||||
<Element Type="AnimationSet" ID="0x15694EE1"/>
|
||||
<Element Type="AnimationSet" ID="0x58F9FE99"/>
|
||||
<Element Type="Struct" ID="0x1C5B4A3A" Archetype="ScanInfoSecondaryModel"/>
|
||||
<Element Type="Struct" ID="0x8728A0EE" Archetype="ScanInfoSecondaryModel"/>
|
||||
<Element Type="Struct" ID="0xF1CD99D3" Archetype="ScanInfoSecondaryModel"/>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<Element>CMDL</Element>
|
||||
</TypeFilter>
|
||||
</Element>
|
||||
<Element Type="AnimationSet" ID="0x48B192CF"/>
|
||||
<Element Type="AnimationSet" ID="0xCDD202D1"/>
|
||||
<Element Type="String" ID="0x3EA2BED8"/>
|
||||
</SubProperties>
|
||||
</PropertyArchetype>
|
||||
|
Loading…
x
Reference in New Issue
Block a user