Fully implemented delete, added an easy-to-use ID lookup system for undo commands, fixed a bunch of crashes when undoing/redoing after creating/deleting an object

This commit is contained in:
parax0
2016-03-16 19:09:59 -06:00
parent 63812ae4b2
commit c4e05610f3
66 changed files with 992 additions and 569 deletions

View File

@@ -158,16 +158,7 @@ CScriptObject* CGameArea::SpawnInstance(CScriptTemplate *pTemplate,
if (InstanceID == -1)
{
// Determine layer index
u32 LayerIndex = -1;
for (u32 iLyr = 0; iLyr < mScriptLayers.size(); iLyr++)
{
if (mScriptLayers[iLyr] == pLayer)
{
LayerIndex = iLyr;
break;
}
}
u32 LayerIndex = pLayer->AreaIndex();
if (LayerIndex == -1)
{
@@ -202,8 +193,16 @@ CScriptObject* CGameArea::SpawnInstance(CScriptTemplate *pTemplate,
return pInstance;
}
void CGameArea::AddInstanceToArea(CScriptObject *pInstance)
{
// Used for undo after deleting an instance.
// In the future the script loader should go through SpawnInstance to avoid the need for this function.
mObjectMap[pInstance->InstanceID()] = pInstance;
}
void CGameArea::DeleteInstance(CScriptObject *pInstance)
{
pInstance->BreakAllLinks();
pInstance->Layer()->RemoveInstance(pInstance);
pInstance->Template()->RemoveObject(pInstance);
@@ -213,6 +212,5 @@ void CGameArea::DeleteInstance(CScriptObject *pInstance)
if (mpPoiToWorldMap && mpPoiToWorldMap->HasPoiMappings(pInstance->InstanceID()))
mpPoiToWorldMap->RemovePoi(pInstance->InstanceID());
pInstance->BreakAllLinks();
delete pInstance;
}

View File

@@ -74,6 +74,7 @@ public:
const CQuaternion& rkRotation = CQuaternion::skIdentity,
const CVector3f& rkScale = CVector3f::skOne,
u32 SuggestedID = -1, u32 SuggestedLayerIndex = -1);
void AddInstanceToArea(CScriptObject *pInstance);
void DeleteInstance(CScriptObject *pInstance);
// Inline Accessors

View File

@@ -292,3 +292,15 @@ void CScriptCooker::WriteLayer(EGame Game, CScriptLayer *pLayer, IOutputStream&
else
Cooker.WriteLayerMP2(pLayer);
}
void CScriptCooker::CookInstance(EGame Game, CScriptObject *pInstance, IOutputStream& rOut)
{
CScriptCooker Cooker;
Cooker.mpSCLY = &rOut;
Cooker.mVersion = Game;
if (Game <= ePrime)
Cooker.WriteInstanceMP1(pInstance);
else
Cooker.WriteInstanceMP2(pInstance);
}

View File

@@ -20,6 +20,7 @@ class CScriptCooker
public:
static void WriteLayer(EGame Game, CScriptLayer *pLayer, IOutputStream& rOut);
static void CookInstance(EGame Game, CScriptObject *pInstance, IOutputStream& rOut);
};
#endif // CSCRIPTCOOKER_H

View File

@@ -11,7 +11,7 @@ CScriptLoader::CScriptLoader()
mpObj = nullptr;
}
void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY)
{
IPropertyTemplate *pTemp = pProp->Template();
@@ -20,31 +20,31 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
case eBoolProperty: {
TBoolProperty *pBoolCast = static_cast<TBoolProperty*>(pProp);
pBoolCast->Set( (SCLY.ReadByte() != 0) );
pBoolCast->Set( (rSCLY.ReadByte() != 0) );
break;
}
case eByteProperty: {
TByteProperty *pByteCast = static_cast<TByteProperty*>(pProp);
pByteCast->Set(SCLY.ReadByte());
pByteCast->Set(rSCLY.ReadByte());
break;
}
case eShortProperty: {
TShortProperty *pShortCast = static_cast<TShortProperty*>(pProp);
pShortCast->Set(SCLY.ReadShort());
pShortCast->Set(rSCLY.ReadShort());
break;
}
case eLongProperty: {
TLongProperty *pLongCast = static_cast<TLongProperty*>(pProp);
pLongCast->Set(SCLY.ReadLong());
pLongCast->Set(rSCLY.ReadLong());
break;
}
case eBitfieldProperty: {
TBitfieldProperty *pBitfieldCast = static_cast<TBitfieldProperty*>(pProp);
pBitfieldCast->Set(SCLY.ReadLong());
pBitfieldCast->Set(rSCLY.ReadLong());
// Validate
u32 mask = 0;
@@ -54,7 +54,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
u32 check = pBitfieldCast->Get() & ~mask;
if (check != 0)
Log::FileWarning(SCLY.GetSourceString(), SCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has flags set that aren't in the template: " + TString::HexString(check, true, true, 8));
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has flags set that aren't in the template: " + TString::HexString(check, true, true, 8));
break;
}
@@ -62,11 +62,11 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
case eEnumProperty: {
TEnumProperty *pEnumCast = static_cast<TEnumProperty*>(pProp);
CEnumTemplate *pEnumTemp = static_cast<CEnumTemplate*>(pTemp);
u32 ID = SCLY.ReadLong();
u32 ID = rSCLY.ReadLong();
// Validate
u32 Index = pEnumTemp->EnumeratorIndex(ID);
if (Index == -1) Log::FileError(SCLY.GetSourceString(), SCLY.Tell() - 4, "Enum property \"" + pEnumTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has invalid enumerator value: " + TString::HexString(ID, true, true, 8));
if (Index == -1) Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Enum property \"" + pEnumTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has invalid enumerator value: " + TString::HexString(ID, true, true, 8));
pEnumCast->Set(ID);
break;
@@ -74,32 +74,32 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
case eFloatProperty: {
TFloatProperty *pFloatCast = static_cast<TFloatProperty*>(pProp);
pFloatCast->Set(SCLY.ReadFloat());
pFloatCast->Set(rSCLY.ReadFloat());
break;
}
case eStringProperty: {
TStringProperty *pStringCast = static_cast<TStringProperty*>(pProp);
pStringCast->Set(SCLY.ReadString());
pStringCast->Set(rSCLY.ReadString());
break;
}
case eVector3Property: {
TVector3Property *pVector3Cast = static_cast<TVector3Property*>(pProp);
pVector3Cast->Set(CVector3f(SCLY));
pVector3Cast->Set(CVector3f(rSCLY));
break;
}
case eColorProperty: {
TColorProperty *pColorCast = static_cast<TColorProperty*>(pProp);
pColorCast->Set(CColor(SCLY));
pColorCast->Set(CColor(rSCLY));
break;
}
case eFileProperty: {
TFileProperty *pFileCast = static_cast<TFileProperty*>(pProp);
CUniqueID ResID = (mVersion < eCorruptionProto ? SCLY.ReadLong() : SCLY.ReadLongLong());
CUniqueID ResID = (mVersion < eCorruptionProto ? rSCLY.ReadLong() : rSCLY.ReadLongLong());
const TStringList& rkExtensions = static_cast<CFileTemplate*>(pTemp)->Extensions();
CResourceInfo Info(ResID, CFourCC(!rkExtensions.empty() ? rkExtensions.front() : "UNKN"));
@@ -118,38 +118,38 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
CPropertyStruct *pStructCast = static_cast<CPropertyStruct*>(pProp);
if (mVersion < eEchoesDemo)
LoadStructMP1(SCLY, pStructCast, static_cast<CStructTemplate*>(pStructCast->Template()));
LoadStructMP1(rSCLY, pStructCast, static_cast<CStructTemplate*>(pStructCast->Template()));
else
LoadStructMP2(SCLY, pStructCast, static_cast<CStructTemplate*>(pTemp));
LoadStructMP2(rSCLY, pStructCast, static_cast<CStructTemplate*>(pTemp));
break;
}
case eArrayProperty: {
CArrayProperty *pArrayCast = static_cast<CArrayProperty*>(pProp);
int Size = SCLY.ReadLong();
int Count = rSCLY.ReadLong();
pArrayCast->Resize(Size);
pArrayCast->Resize(Count);
for (int iElem = 0; iElem < Size; iElem++)
for (int iElem = 0; iElem < Count; iElem++)
{
if (mVersion < eEchoesDemo)
LoadStructMP1(SCLY, static_cast<CPropertyStruct*>(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate());
LoadStructMP1(rSCLY, static_cast<CPropertyStruct*>(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate());
else
LoadStructMP2(SCLY, static_cast<CPropertyStruct*>(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate());
LoadStructMP2(rSCLY, static_cast<CPropertyStruct*>(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate());
}
break;
}
case eCharacterProperty: {
TCharacterProperty *pAnimCast = static_cast<TCharacterProperty*>(pProp);
pAnimCast->Set(CAnimationParameters(SCLY, mVersion));
pAnimCast->Set(CAnimationParameters(rSCLY, mpMaster->GetGame()));
break;
}
case eMayaSplineProperty: {
TMayaSplineProperty *pSplineCast = static_cast<TMayaSplineProperty*>(pProp);
std::vector<u8> Buffer(Size);
SCLY.ReadBytes(Buffer.data(), Buffer.size());
rSCLY.ReadBytes(Buffer.data(), Buffer.size());
pSplineCast->Set(Buffer);
break;
}
@@ -157,16 +157,16 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
case eUnknownProperty: {
TUnknownProperty *pUnknownCast = static_cast<TUnknownProperty*>(pProp);
std::vector<u8> Buffer(Size);
SCLY.ReadBytes(Buffer.data(), Buffer.size());
rSCLY.ReadBytes(Buffer.data(), Buffer.size());
pUnknownCast->Set(Buffer);
break;
}
}
}
void CScriptLoader::LoadStructMP1(IInputStream& SCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp)
void CScriptLoader::LoadStructMP1(IInputStream& rSCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp)
{
u32 StructStart = SCLY.Tell();
u32 StructStart = rSCLY.Tell();
// Verify property count
u32 PropCount = pTemp->Count();
@@ -174,7 +174,7 @@ void CScriptLoader::LoadStructMP1(IInputStream& SCLY, CPropertyStruct *pStruct,
if (!pTemp->IsSingleProperty())
{
u32 FilePropCount = SCLY.ReadLong();
u32 FilePropCount = rSCLY.ReadLong();
Version = pTemp->VersionForPropertyCount(FilePropCount);
if (Version == -1)
@@ -182,7 +182,7 @@ void CScriptLoader::LoadStructMP1(IInputStream& SCLY, CPropertyStruct *pStruct,
TIDString IDString = pTemp->IDString(true);
if (!IDString.IsEmpty()) IDString = " (" + IDString + ")";
Log::FileWarning(SCLY.GetSourceString(), StructStart, "Struct \"" + pTemp->Name() + "\"" + IDString + " template prop count doesn't match file; template is " + TString::HexString(PropCount, true, true, 2) + ", file is " + TString::HexString(FilePropCount, true, true, 2));
Log::FileWarning(rSCLY.GetSourceString(), StructStart, "Struct \"" + pTemp->Name() + "\"" + IDString + " template prop count doesn't match file; template is " + TString::HexString(PropCount, true, true, 2) + ", file is " + TString::HexString(FilePropCount, true, true, 2));
Version = 0;
}
}
@@ -194,38 +194,38 @@ void CScriptLoader::LoadStructMP1(IInputStream& SCLY, CPropertyStruct *pStruct,
IProperty *pProp = pStruct->PropertyByIndex(iProp);
if (pPropTemp->CookPreference() != eNeverCook && pPropTemp->IsInVersion(Version))
ReadProperty(pProp, 0, SCLY);
ReadProperty(pProp, 0, rSCLY);
}
}
CScriptObject* CScriptLoader::LoadObjectMP1(IInputStream& SCLY)
CScriptObject* CScriptLoader::LoadObjectMP1(IInputStream& rSCLY)
{
u32 ObjStart = SCLY.Tell();
u8 Type = SCLY.ReadByte();
u32 Size = SCLY.ReadLong();
u32 End = SCLY.Tell() + Size;
u32 ObjStart = rSCLY.Tell();
u8 Type = rSCLY.ReadByte();
u32 Size = rSCLY.ReadLong();
u32 End = rSCLY.Tell() + Size;
CScriptTemplate *pTemp = mpMaster->TemplateByID((u32) Type);
if (!pTemp)
{
// No valid template for this object; can't load
Log::FileError(SCLY.GetSourceString(), ObjStart, "Unknown object ID encountered: " + TString::HexString(Type));
SCLY.Seek(End, SEEK_SET);
Log::FileError(rSCLY.GetSourceString(), ObjStart, "Unknown object ID encountered: " + TString::HexString(Type));
rSCLY.Seek(End, SEEK_SET);
return nullptr;
}
u32 InstanceID = SCLY.ReadLong();
u32 InstanceID = rSCLY.ReadLong();
mpObj = new CScriptObject(InstanceID, mpArea, mpLayer, pTemp);
// Load connections
u32 NumLinks = SCLY.ReadLong();
u32 NumLinks = rSCLY.ReadLong();
mpObj->mOutLinks.reserve(NumLinks);
for (u32 iLink = 0; iLink < NumLinks; iLink++)
{
u32 State = SCLY.ReadLong();
u32 Message = SCLY.ReadLong();
u32 ReceiverID = SCLY.ReadLong();
u32 State = rSCLY.ReadLong();
u32 Message = rSCLY.ReadLong();
u32 ReceiverID = rSCLY.ReadLong();
CLink *pLink = new CLink(mpArea, State, Message, mpObj->mInstanceID, ReceiverID);
mpObj->mOutLinks.push_back(pLink);
@@ -233,54 +233,54 @@ CScriptObject* CScriptLoader::LoadObjectMP1(IInputStream& SCLY)
// Load object...
CPropertyStruct *pBase = mpObj->mpProperties;
LoadStructMP1(SCLY, pBase, static_cast<CStructTemplate*>(pBase->Template()));
LoadStructMP1(rSCLY, pBase, static_cast<CStructTemplate*>(pBase->Template()));
// Cleanup and return
SCLY.Seek(End, SEEK_SET);
rSCLY.Seek(End, SEEK_SET);
mpObj->EvaluateProperties();
return mpObj;
}
CScriptLayer* CScriptLoader::LoadLayerMP1(IInputStream &SCLY)
CScriptLayer* CScriptLoader::LoadLayerMP1(IInputStream& rSCLY)
{
u32 LayerStart = SCLY.Tell();
u32 LayerStart = rSCLY.Tell();
SCLY.Seek(0x1, SEEK_CUR); // One unknown byte at the start of each layer
u32 NumObjects = SCLY.ReadLong();
rSCLY.Seek(0x1, SEEK_CUR); // One unknown byte at the start of each layer
u32 NumObjects = rSCLY.ReadLong();
mpLayer = new CScriptLayer(mpArea);
mpLayer->Reserve(NumObjects);
for (u32 iObj = 0; iObj < NumObjects; iObj++)
{
CScriptObject *pObj = LoadObjectMP1(SCLY);
CScriptObject *pObj = LoadObjectMP1(rSCLY);
if (pObj)
mpLayer->AddInstance(pObj);
}
// Layer sizes are always a multiple of 32 - skip end padding before returning
u32 Remaining = 32 - ((SCLY.Tell() - LayerStart) & 0x1F);
SCLY.Seek(Remaining, SEEK_CUR);
u32 Remaining = 32 - ((rSCLY.Tell() - LayerStart) & 0x1F);
rSCLY.Seek(Remaining, SEEK_CUR);
return mpLayer;
}
void CScriptLoader::LoadStructMP2(IInputStream& SCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp)
void CScriptLoader::LoadStructMP2(IInputStream& rSCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp)
{
// Verify property count
u32 StructStart = SCLY.Tell();
u32 StructStart = rSCLY.Tell();
StructStart += 0;
u32 PropCount = pTemp->Count();
if (!pTemp->IsSingleProperty())
PropCount = SCLY.ReadShort();
PropCount = rSCLY.ReadShort();
// Parse properties
for (u32 iProp = 0; iProp < PropCount; iProp++)
{
IProperty *pProp;
IPropertyTemplate *pPropTemp;
u32 PropertyStart = SCLY.Tell();
u32 PropertyStart = rSCLY.Tell();
u32 PropertyID = -1;
u16 PropertyLength = 0;
u32 NextProperty = 0;
@@ -292,79 +292,79 @@ void CScriptLoader::LoadStructMP2(IInputStream& SCLY, CPropertyStruct *pStruct,
}
else
{
PropertyID = SCLY.ReadLong();
PropertyLength = SCLY.ReadShort();
NextProperty = SCLY.Tell() + PropertyLength;
PropertyID = rSCLY.ReadLong();
PropertyLength = rSCLY.ReadShort();
NextProperty = rSCLY.Tell() + PropertyLength;
pProp = pStruct->PropertyByID(PropertyID);
pPropTemp = pTemp->PropertyByID(PropertyID);
}
if (!pPropTemp)
Log::FileError(SCLY.GetSourceString(), PropertyStart, "Can't find template for property " + TString::HexString(PropertyID) + " - skipping");
Log::FileError(rSCLY.GetSourceString(), PropertyStart, "Can't find template for property " + TString::HexString(PropertyID) + " - skipping");
else
ReadProperty(pProp, PropertyLength, SCLY);
ReadProperty(pProp, PropertyLength, rSCLY);
if (NextProperty > 0)
SCLY.Seek(NextProperty, SEEK_SET);
rSCLY.Seek(NextProperty, SEEK_SET);
}
}
CScriptObject* CScriptLoader::LoadObjectMP2(IInputStream& SCLY)
CScriptObject* CScriptLoader::LoadObjectMP2(IInputStream& rSCLY)
{
u32 ObjStart = SCLY.Tell();
u32 ObjectID = SCLY.ReadLong();
u16 ObjectSize = SCLY.ReadShort();
u32 ObjEnd = SCLY.Tell() + ObjectSize;
u32 ObjStart = rSCLY.Tell();
u32 ObjectID = rSCLY.ReadLong();
u16 ObjectSize = rSCLY.ReadShort();
u32 ObjEnd = rSCLY.Tell() + ObjectSize;
CScriptTemplate *pTemplate = mpMaster->TemplateByID(ObjectID);
if (!pTemplate)
{
Log::FileError(SCLY.GetSourceString(), ObjStart, "Unknown object ID encountered: " + CFourCC(ObjectID).ToString());
SCLY.Seek(ObjEnd, SEEK_SET);
Log::FileError(rSCLY.GetSourceString(), ObjStart, "Unknown object ID encountered: " + CFourCC(ObjectID).ToString());
rSCLY.Seek(ObjEnd, SEEK_SET);
return nullptr;
}
u32 InstanceID = SCLY.ReadLong();
u32 InstanceID = rSCLY.ReadLong();
mpObj = new CScriptObject(InstanceID, mpArea, mpLayer, pTemplate);
// Load connections
u32 NumConnections = SCLY.ReadShort();
u32 NumConnections = rSCLY.ReadShort();
mpObj->mOutLinks.reserve(NumConnections);
for (u32 iCon = 0; iCon < NumConnections; iCon++)
{
u32 State = SCLY.ReadLong();
u32 Message = SCLY.ReadLong();
u32 ReceiverID = SCLY.ReadLong();
u32 State = rSCLY.ReadLong();
u32 Message = rSCLY.ReadLong();
u32 ReceiverID = rSCLY.ReadLong();
CLink *pLink = new CLink(mpArea, State, Message, mpObj->mInstanceID, ReceiverID);
mpObj->mOutLinks.push_back(pLink);
}
// Load object
SCLY.Seek(0x6, SEEK_CUR); // Skip base struct ID + size
LoadStructMP2(SCLY, mpObj->mpProperties, mpObj->mpTemplate->BaseStruct());
rSCLY.Seek(0x6, SEEK_CUR); // Skip base struct ID + size
LoadStructMP2(rSCLY, mpObj->mpProperties, mpObj->mpTemplate->BaseStruct());
// Cleanup and return
SCLY.Seek(ObjEnd, SEEK_SET);
rSCLY.Seek(ObjEnd, SEEK_SET);
mpObj->EvaluateProperties();
return mpObj;
}
CScriptLayer* CScriptLoader::LoadLayerMP2(IInputStream& SCLY)
CScriptLayer* CScriptLoader::LoadLayerMP2(IInputStream& rSCLY)
{
SCLY.Seek(0x1, SEEK_CUR); // Skipping version. todo: verify this?
u32 NumObjects = SCLY.ReadLong();
rSCLY.Seek(0x1, SEEK_CUR); // Skipping version. todo: verify this?
u32 NumObjects = rSCLY.ReadLong();
mpLayer = new CScriptLayer(mpArea);
mpLayer->Reserve(NumObjects);
for (u32 iObj = 0; iObj < NumObjects; iObj++)
{
CScriptObject *pObj = LoadObjectMP2(SCLY);
CScriptObject *pObj = LoadObjectMP2(rSCLY);
if (pObj)
mpLayer->AddInstance(pObj);
}
@@ -396,3 +396,28 @@ CScriptLayer* CScriptLoader::LoadLayer(IInputStream& rSCLY, CGameArea *pArea, EG
else
return Loader.LoadLayerMP2(rSCLY);
}
CScriptObject* CScriptLoader::LoadInstance(IInputStream& rSCLY, CGameArea *pArea, CScriptLayer *pLayer, EGame Version, bool ForceReturnsFormat)
{
if (!rSCLY.IsValid()) return nullptr;
CScriptLoader Loader;
Loader.mVersion = (ForceReturnsFormat ? eReturns : Version);
Loader.mpMaster = CMasterTemplate::GetMasterForGame(Version);
Loader.mpArea = pArea;
Loader.mpLayer = pLayer;
if (!Loader.mpMaster)
{
Log::Write("This game doesn't have a master template; couldn't load script instance");
return nullptr;
}
if (!Loader.mpMaster->IsLoadedSuccessfully())
CTemplateLoader::LoadGameTemplates(Version);
if (Loader.mVersion <= ePrime)
return Loader.LoadObjectMP1(rSCLY);
else
return Loader.LoadObjectMP2(rSCLY);
}

View File

@@ -16,18 +16,19 @@ class CScriptLoader
CMasterTemplate *mpMaster;
CScriptLoader();
void ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY);
void ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY);
void LoadStructMP1(IInputStream& SCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp);
CScriptObject* LoadObjectMP1(IInputStream& SCLY);
CScriptLayer* LoadLayerMP1(IInputStream& SCLY);
void LoadStructMP1(IInputStream& rSCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp);
CScriptObject* LoadObjectMP1(IInputStream& rSCLY);
CScriptLayer* LoadLayerMP1(IInputStream& rSCLY);
void LoadStructMP2(IInputStream& SCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp);
CScriptObject* LoadObjectMP2(IInputStream& SCLY);
CScriptLayer* LoadLayerMP2(IInputStream& SCLY);
void LoadStructMP2(IInputStream& rSCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp);
CScriptObject* LoadObjectMP2(IInputStream& rSCLY);
CScriptLayer* LoadLayerMP2(IInputStream& rSCLY);
public:
static CScriptLayer* LoadLayer(IInputStream& SCLY, CGameArea *pArea, EGame version);
static CScriptLayer* LoadLayer(IInputStream& rSCLY, CGameArea *pArea, EGame Version);
static CScriptObject* LoadInstance(IInputStream& rSCLY, CGameArea *pArea, CScriptLayer *pLayer,EGame Version, bool ForceReturnsFormat);
};
#endif // CSCRIPTLOADER_H

View File

@@ -15,7 +15,7 @@ CScriptObject::CScriptObject(u32 InstanceID, CGameArea *pArea, CScriptLayer *pLa
, mIsCheckingNearVisibleActivation(false)
{
mpTemplate->AddObject(this);
mpProperties = (CPropertyStruct*) pTemplate->BaseStruct()->InstantiateProperty(nullptr);
mpProperties = (CPropertyStruct*) pTemplate->BaseStruct()->InstantiateProperty(this, nullptr);
}
CScriptObject::~CScriptObject()
@@ -80,14 +80,16 @@ void CScriptObject::SetLayer(CScriptLayer *pLayer, u32 NewLayerIndex)
{
if (pLayer != mpLayer)
{
mpLayer->RemoveInstance(this);
if (mpLayer) mpLayer->RemoveInstance(this);
mpLayer = pLayer;
mpLayer->AddInstance(this, NewLayerIndex);
if (mpLayer) mpLayer->AddInstance(this, NewLayerIndex);
}
}
u32 CScriptObject::LayerIndex() const
{
if (!mpLayer) return -1;
for (u32 iInst = 0; iInst < mpLayer->NumInstances(); iInst++)
{
if (mpLayer->InstanceByIndex(iInst) == this)

View File

@@ -32,13 +32,44 @@ TString IProperty::Name() const
u32 IProperty::ID() const
{
return mpTemplate->PropertyID();
if (mpParent && mpParent->Type() == eArrayProperty)
return ArrayIndex();
else
return mpTemplate->PropertyID();
}
TIDString IProperty::IDString(bool FullPath) const
{
// todo: since this function just returns the template ID string, it doesn't correctly account for array properties;
return mpTemplate->IDString(FullPath);
TIDString Out;
if (ID() != 0xFFFFFFFF)
{
if (mpParent && FullPath)
{
Out = mpParent->IDString(true);
if (!Out.IsEmpty()) Out += ":";
}
Out += TString::HexString(ID(), true, true, 8);
}
return Out;
}
u32 IProperty::ArrayIndex() const
{
CArrayProperty *pArray = TPropCast<CArrayProperty>(mpParent);
if (pArray)
{
for (u32 iSub = 0; iSub < pArray->Count(); iSub++)
{
if (pArray->PropertyByIndex(iSub) == this)
return iSub;
}
}
return -1;
}
bool IProperty::ShouldCook()
@@ -74,7 +105,7 @@ void CPropertyStruct::Copy(const IProperty *pkProp)
mProperties.resize(pkSource->mProperties.size());
for (u32 iSub = 0; iSub < mProperties.size(); iSub++)
mProperties[iSub] = pkSource->mProperties[iSub]->Clone(this);
mProperties[iSub] = pkSource->mProperties[iSub]->Clone(Instance(), this);
}
bool CPropertyStruct::ShouldCook()
@@ -138,7 +169,7 @@ CPropertyStruct* CPropertyStruct::StructByIndex(u32 index) const
{
IProperty *pProp = PropertyByIndex(index);
if (pProp->Type() == eStructProperty)
if (pProp->Type() == eStructProperty || pProp->Type() == eArrayProperty)
return static_cast<CPropertyStruct*>(pProp);
else
return nullptr;
@@ -148,7 +179,7 @@ CPropertyStruct* CPropertyStruct::StructByID(u32 ID) const
{
IProperty *pProp = PropertyByID(ID);
if (pProp->Type() == eStructProperty)
if (pProp->Type() == eStructProperty || pProp->Type() == eArrayProperty)
return static_cast<CPropertyStruct*>(pProp);
else
return nullptr;
@@ -158,7 +189,7 @@ CPropertyStruct* CPropertyStruct::StructByIDString(const TIDString& rkStr) const
{
IProperty *pProp = PropertyByIDString(rkStr);
if (pProp->Type() == eStructProperty)
if (pProp->Type() == eStructProperty || pProp->Type() == eArrayProperty)
return static_cast<CPropertyStruct*>(pProp);
else
return nullptr;
@@ -186,7 +217,7 @@ void CArrayProperty::Resize(int Size)
if (Size > OldSize)
{
for (int iProp = OldSize; iProp < Size; iProp++)
mProperties[iProp] = static_cast<CArrayTemplate*>(mpTemplate)->CreateSubStruct(this);
mProperties[iProp] = static_cast<CArrayTemplate*>(mpTemplate)->CreateSubStruct(Instance(), this);
}
}

View File

@@ -13,6 +13,7 @@
#include <Math/CVector3f.h>
#include <list>
class CScriptObject;
class CScriptTemplate;
class CStructTemplate;
class IPropertyTemplate;
@@ -28,11 +29,13 @@ class IProperty
protected:
class CPropertyStruct *mpParent;
CScriptObject *mpInstance;
IPropertyTemplate *mpTemplate;
public:
IProperty(IPropertyTemplate *pTemp, CPropertyStruct *pParent)
IProperty(IPropertyTemplate *pTemp, CScriptObject *pInstance, CPropertyStruct *pParent)
: mpParent(pParent)
, mpInstance(pInstance)
, mpTemplate(pTemp)
{
}
@@ -42,12 +45,13 @@ public:
virtual TString ToString() const { return ""; }
virtual IPropertyValue* RawValue() { return nullptr; }
virtual void Copy(const IProperty *pkProp) = 0;
virtual IProperty* Clone(CPropertyStruct *pParent = 0) const = 0;
virtual IProperty* Clone(CScriptObject *pInstance, CPropertyStruct *pParent = 0) const = 0;
virtual bool Matches(const IProperty *pkProp) const = 0;
virtual bool ShouldCook(); // Can't be const because it calls MatchesDefault()
virtual bool MatchesDefault(); // Can't be const because RawValue() isn't const
inline CScriptObject* Instance() const { return mpInstance; }
inline CPropertyStruct* Parent() const { return mpParent; }
inline void SetParent(CPropertyStruct *pParent) { mpParent = pParent; }
@@ -59,6 +63,7 @@ public:
TString Name() const;
u32 ID() const;
TIDString IDString(bool FullPath) const;
u32 ArrayIndex() const;
};
/*
@@ -70,11 +75,11 @@ class TTypedProperty : public IProperty
friend class CScriptLoader;
ValueClass mValue;
public:
TTypedProperty(IPropertyTemplate *pTemp, CPropertyStruct *pParent)
: IProperty(pTemp, pParent) {}
TTypedProperty(IPropertyTemplate *pTemp, CScriptObject *pInstance, CPropertyStruct *pParent)
: IProperty(pTemp, pInstance, pParent) {}
TTypedProperty(IPropertyTemplate *pTemp, CPropertyStruct *pParent, ValueType v)
: IProperty(pTemp, pParent), mValue(v) {}
TTypedProperty(IPropertyTemplate *pTemp, CScriptObject *pInstance, CPropertyStruct *pParent, ValueType v)
: IProperty(pTemp, pInstance, pParent), mValue(v) {}
~TTypedProperty() {}
virtual EPropertyType Type() const { return TypeEnum; }
@@ -89,11 +94,11 @@ public:
mValue.Set(pkCast->mValue.Get());
}
virtual TTypedProperty* Clone(CPropertyStruct *pParent) const
virtual TTypedProperty* Clone(class CScriptObject *pInstance, CPropertyStruct *pParent) const
{
if (!pParent) pParent = mpParent;
TTypedProperty *pOut = new TTypedProperty(mpTemplate, pParent);
TTypedProperty *pOut = new TTypedProperty(mpTemplate, pInstance, pParent);
pOut->Copy(this);
return pOut;
}
@@ -123,11 +128,11 @@ typedef TTypedProperty<std::vector<u8>, eUnknownProperty, CUnknownValue>
* TStringProperty, TFileProperty, and TCharacterProperty get little subclasses in order to override some virtual functions.
*/
#define IMPLEMENT_PROPERTY_CTORS(ClassName, ValueType) \
ClassName(IPropertyTemplate *pTemp, CPropertyStruct *pParent) \
: TTypedProperty(pTemp, pParent) {} \
ClassName(IPropertyTemplate *pTemp, CScriptObject *pInstance, CPropertyStruct *pParent) \
: TTypedProperty(pTemp, pInstance, pParent) {} \
\
ClassName(IPropertyTemplate *pTemp, CPropertyStruct *pParent, ValueType v) \
: TTypedProperty(pTemp, pParent, v) {}
ClassName(IPropertyTemplate *pTemp, CScriptObject *pInstance, CPropertyStruct *pParent, ValueType v) \
: TTypedProperty(pTemp, pInstance, pParent, v) {}
class TStringProperty : public TTypedProperty<TString, eStringProperty, CStringValue>
{
@@ -169,8 +174,8 @@ class CPropertyStruct : public IProperty
protected:
std::vector<IProperty*> mProperties;
public:
CPropertyStruct(IPropertyTemplate *pTemp, CPropertyStruct *pParent)
: IProperty(pTemp, pParent) {}
CPropertyStruct(IPropertyTemplate *pTemp, CScriptObject *pInstance, CPropertyStruct *pParent)
: IProperty(pTemp, pInstance, pParent) {}
~CPropertyStruct()
{
@@ -183,10 +188,10 @@ public:
virtual void Copy(const IProperty *pkProp);
virtual IProperty* Clone(CPropertyStruct *pParent) const
virtual IProperty* Clone(CScriptObject *pInstance, CPropertyStruct *pParent) const
{
if (!pParent) pParent = mpParent;
CPropertyStruct *pOut = new CPropertyStruct(mpTemplate, pParent);
CPropertyStruct *pOut = new CPropertyStruct(mpTemplate, pInstance, pParent);
pOut->Copy(this);
return pOut;
}
@@ -245,16 +250,16 @@ class CArrayProperty : public CPropertyStruct
friend class CScriptLoader;
public:
CArrayProperty(IPropertyTemplate *pTemp, CPropertyStruct *pParent)
: CPropertyStruct(pTemp, pParent) {}
CArrayProperty(IPropertyTemplate *pTemp, CScriptObject *pInstance, CPropertyStruct *pParent)
: CPropertyStruct(pTemp, pInstance, pParent) {}
EPropertyType Type() const { return eArrayProperty; }
static inline EPropertyType StaticType() { return eArrayProperty; }
virtual IProperty* Clone(CPropertyStruct *pParent) const
virtual IProperty* Clone(CScriptObject *pInstance, CPropertyStruct *pParent) const
{
if (!pParent) pParent = mpParent;
CArrayProperty *pOut = new CArrayProperty(mpTemplate, pParent);
CArrayProperty *pOut = new CArrayProperty(mpTemplate, pInstance, pParent);
pOut->Copy(this);
return pOut;
}

View File

@@ -64,7 +64,7 @@ public:
virtual EPropertyType Type() const = 0;
virtual bool CanHaveDefault() const = 0;
virtual bool IsNumerical() const = 0;
virtual IProperty* InstantiateProperty(CPropertyStruct *pParent) = 0;
virtual IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent) = 0;
virtual IPropertyTemplate* Clone(CScriptTemplate *pScript, CStructTemplate *pParent = 0) const = 0;
virtual void Copy(const IPropertyTemplate *pkTemp)
@@ -164,10 +164,10 @@ public:
virtual bool CanHaveDefault() const { return CanHaveDefaultValue; }
virtual bool IsNumerical() const { return false; }
virtual IProperty* InstantiateProperty(CPropertyStruct *pParent)
virtual IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent)
{
typedef TTypedProperty<PropType, PropTypeEnum, ValueClass> TPropertyType;
TPropertyType *pOut = new TPropertyType(this, pParent, GetDefaultValue());
TPropertyType *pOut = new TPropertyType(this, pInstance, pParent, GetDefaultValue());
return pOut;
}
@@ -321,9 +321,9 @@ public:
TCharacterTemplate(u32 ID, const TString& rkName, ECookPreference CookPreference, CScriptTemplate *pScript, CMasterTemplate *pMaster, CStructTemplate *pParent = 0)
: TTypedPropertyTemplate(ID, rkName, CookPreference, pScript, pMaster, pParent) {}
IProperty* InstantiateProperty(CPropertyStruct *pParent)
IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent)
{
return new TCharacterProperty(this, pParent, CAnimationParameters(Game()));
return new TCharacterProperty(this, pInstance, pParent, CAnimationParameters(Game()));
}
};
@@ -339,9 +339,9 @@ public:
TStringTemplate(u32 ID, const TString& rkName, ECookPreference CookPreference, CScriptTemplate *pScript, CMasterTemplate *pMaster, CStructTemplate *pParent = 0)
: TTypedPropertyTemplate(ID, rkName, CookPreference, pScript, pMaster, pParent) {}
IProperty* InstantiateProperty(CPropertyStruct *pParent)
IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent)
{
return new TStringProperty(this, pParent);
return new TStringProperty(this, pInstance, pParent);
}
};
@@ -357,9 +357,9 @@ public:
TMayaSplineTemplate(u32 ID, const TString& rkName, ECookPreference CookPreference, CScriptTemplate *pScript, CMasterTemplate *pMaster, CStructTemplate *pParent = 0)
: TTypedPropertyTemplate(ID, rkName, CookPreference, pScript, pMaster, pParent) {}
IProperty* InstantiateProperty(CPropertyStruct *pParent)
IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent)
{
return new TMayaSplineProperty(this, pParent);
return new TMayaSplineProperty(this, pInstance, pParent);
}
};
@@ -382,9 +382,9 @@ public:
virtual bool CanHaveDefault() const { return false; }
virtual bool IsNumerical() const { return false; }
IProperty* InstantiateProperty(CPropertyStruct *pParent)
IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent)
{
return new TFileProperty(this, pParent);
return new TFileProperty(this, pInstance, pParent);
}
IMPLEMENT_TEMPLATE_CLONE(CFileTemplate)
@@ -451,9 +451,9 @@ public:
virtual bool CanHaveDefault() const { return true; }
virtual bool IsNumerical() const { return false; }
virtual IProperty* InstantiateProperty(CPropertyStruct *pParent)
virtual IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent)
{
TEnumProperty *pEnum = new TEnumProperty(this, pParent);
TEnumProperty *pEnum = new TEnumProperty(this, pInstance, pParent);
pEnum->Set(GetDefaultValue());
return pEnum;
}
@@ -546,9 +546,9 @@ public:
virtual bool CanHaveDefault() const { return true; }
virtual bool IsNumerical() const { return false; }
virtual IProperty* InstantiateProperty(CPropertyStruct *pParent)
virtual IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent)
{
TBitfieldProperty *pBitfield = new TBitfieldProperty(this, pParent);
TBitfieldProperty *pBitfield = new TBitfieldProperty(this, pInstance, pParent);
pBitfield->Set(GetDefaultValue());
return pBitfield;
}
@@ -611,13 +611,13 @@ public:
bool CanHaveDefault() const { return false; }
bool IsNumerical() const { return false; }
IProperty* InstantiateProperty(CPropertyStruct *pParent)
IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent)
{
CPropertyStruct *pStruct = new CPropertyStruct(this, pParent);
CPropertyStruct *pStruct = new CPropertyStruct(this, pInstance, pParent);
for (u32 iSub = 0; iSub < mSubProperties.size(); iSub++)
{
IProperty *pSubProp = mSubProperties[iSub]->InstantiateProperty(pStruct);
IProperty *pSubProp = mSubProperties[iSub]->InstantiateProperty(pInstance, pStruct);
pStruct->AddSubProperty(pSubProp);
}
@@ -708,9 +708,9 @@ public:
EPropertyType Type() const { return eArrayProperty; }
IProperty* InstantiateProperty(CPropertyStruct *pParent)
IProperty* InstantiateProperty(CScriptObject *pInstance, CPropertyStruct *pParent)
{
return new CArrayProperty(this, pParent);
return new CArrayProperty(this, pInstance, pParent);
}
IMPLEMENT_TEMPLATE_CLONE(CArrayTemplate)
@@ -740,9 +740,9 @@ public:
TString ElementName() const { return mElementName; }
void SetElementName(const TString& rkName) { mElementName = rkName; }
CPropertyStruct* CreateSubStruct(CArrayProperty *pArray)
CPropertyStruct* CreateSubStruct(CScriptObject *pInstance, CArrayProperty *pArray)
{
return (CPropertyStruct*) CStructTemplate::InstantiateProperty(pArray);
return (CPropertyStruct*) CStructTemplate::InstantiateProperty(pInstance, pArray);
}
};

View File

@@ -3,8 +3,8 @@
#include "Core/Render/CGraphics.h"
#include "Core/Render/CRenderer.h"
CCollisionNode::CCollisionNode(CScene *pScene, CSceneNode *pParent, CCollisionMeshGroup *pCollision)
: CSceneNode(pScene, pParent)
CCollisionNode::CCollisionNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CCollisionMeshGroup *pCollision)
: CSceneNode(pScene, NodeID, pParent)
{
SetCollision(pCollision);
SetName("Collision");

View File

@@ -9,7 +9,7 @@ class CCollisionNode : public CSceneNode
TResPtr<CCollisionMeshGroup> mpCollision;
public:
CCollisionNode(CScene *pScene, CSceneNode *pParent = 0, CCollisionMeshGroup *pCollision = 0);
CCollisionNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CCollisionMeshGroup *pCollision = 0);
ENodeType NodeType();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);

View File

@@ -4,8 +4,8 @@
#include "Core/Render/CRenderer.h"
#include <Math/MathUtil.h>
CLightNode::CLightNode(CScene *pScene, CSceneNode *pParent, CLight *Light)
: CSceneNode(pScene, pParent)
CLightNode::CLightNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CLight *Light)
: CSceneNode(pScene, NodeID, pParent)
{
mpLight = Light;
mLocalAABox = CAABox::skOne;

View File

@@ -8,7 +8,7 @@ class CLightNode : public CSceneNode
{
CLight *mpLight;
public:
CLightNode(CScene *pScene, CSceneNode *pParent = 0, CLight *Light = 0);
CLightNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CLight *Light = 0);
ENodeType NodeType();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);

View File

@@ -4,7 +4,8 @@
#include "Core/Render/CGraphics.h"
#include <Math/MathUtil.h>
CModelNode::CModelNode(CScene *pScene, CSceneNode *pParent, CModel *pModel) : CSceneNode(pScene, pParent)
CModelNode::CModelNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CModel *pModel)
: CSceneNode(pScene, NodeID, pParent)
{
SetModel(pModel);
mScale = CVector3f(1.f);

View File

@@ -15,7 +15,7 @@ class CModelNode : public CSceneNode
CColor mScanOverlayColor;
public:
explicit CModelNode(CScene *pScene, CSceneNode *pParent = 0, CModel *pModel = 0);
explicit CModelNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CModel *pModel = 0);
virtual ENodeType NodeType();
virtual void PostLoad();

View File

@@ -8,7 +8,8 @@
class CRootNode : public CSceneNode
{
public:
explicit CRootNode(CScene *pScene, CSceneNode *pParent = 0) : CSceneNode(pScene, pParent) {}
explicit CRootNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0)
: CSceneNode(pScene, NodeID, pParent) {}
~CRootNode() {}
ENodeType NodeType() {

View File

@@ -17,7 +17,7 @@ CScene::CScene()
: mSplitTerrain(true)
, mRanPostLoad(false)
, mNumNodes(0)
, mpSceneRootNode(new CRootNode(this, nullptr))
, mpSceneRootNode(new CRootNode(this, -1, nullptr))
, mpArea(nullptr)
, mpWorld(nullptr)
, mpAreaRootNode(nullptr)
@@ -29,43 +29,76 @@ CScene::~CScene()
ClearScene();
}
CModelNode* CScene::CreateModelNode(CModel *pModel)
bool CScene::IsNodeIDUsed(u32 ID) const
{
return (mNodeMap.find(ID) != mNodeMap.end());
}
u32 CScene::CreateNodeID(u32 SuggestedID /*= -1*/) const
{
if (SuggestedID != -1)
{
if (IsNodeIDUsed(SuggestedID))
Log::Error("Suggested node ID is already being used! New ID will be created.");
else
return SuggestedID;
}
u32 ID = 0;
while (IsNodeIDUsed(ID))
ID++;
return ID;
}
CModelNode* CScene::CreateModelNode(CModel *pModel, u32 NodeID /*= -1*/)
{
if (pModel == nullptr) return nullptr;
CModelNode *pNode = new CModelNode(this, mpAreaRootNode, pModel);
u32 ID = CreateNodeID(NodeID);
CModelNode *pNode = new CModelNode(this, ID, mpAreaRootNode, pModel);
mNodes[eModelNode].push_back(pNode);
mNodeMap[ID] = pNode;
mNumNodes++;
return pNode;
}
CStaticNode* CScene::CreateStaticNode(CStaticModel *pModel)
CStaticNode* CScene::CreateStaticNode(CStaticModel *pModel, u32 NodeID /*= -1*/)
{
if (pModel == nullptr) return nullptr;
CStaticNode *pNode = new CStaticNode(this, mpAreaRootNode, pModel);
u32 ID = CreateNodeID(NodeID);
CStaticNode *pNode = new CStaticNode(this, ID, mpAreaRootNode, pModel);
mNodes[eStaticNode].push_back(pNode);
mNodeMap[ID] = pNode;
mNumNodes++;
return pNode;
}
CCollisionNode* CScene::CreateCollisionNode(CCollisionMeshGroup *pMesh)
CCollisionNode* CScene::CreateCollisionNode(CCollisionMeshGroup *pMesh, u32 NodeID /*= -1*/)
{
if (pMesh == nullptr) return nullptr;
CCollisionNode *pNode = new CCollisionNode(this, mpAreaRootNode, pMesh);
u32 ID = CreateNodeID(NodeID);
CCollisionNode *pNode = new CCollisionNode(this, ID, mpAreaRootNode, pMesh);
mNodes[eCollisionNode].push_back(pNode);
mNodeMap[ID] = pNode;
mNumNodes++;
return pNode;
}
CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj)
CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj, u32 NodeID /*= -1*/)
{
if (pObj == nullptr) return nullptr;
CScriptNode *pNode = new CScriptNode(this, mpAreaRootNode, pObj);
u32 ID = CreateNodeID(NodeID);
u32 InstanceID = pObj->InstanceID();
CScriptNode *pNode = new CScriptNode(this, ID, mpAreaRootNode, pObj);
mNodes[eScriptNode].push_back(pNode);
mScriptNodeMap[pObj->InstanceID()] = pNode;
mNodeMap[ID] = pNode;
mScriptMap[InstanceID] = pNode;
pNode->BuildLightList(mpArea);
// AreaAttributes check
@@ -81,12 +114,14 @@ CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj)
return pNode;
}
CLightNode* CScene::CreateLightNode(CLight *pLight)
CLightNode* CScene::CreateLightNode(CLight *pLight, u32 NodeID /*= -1*/)
{
if (pLight == nullptr) return nullptr;
CLightNode *pNode = new CLightNode(this, mpAreaRootNode, pLight);
u32 ID = CreateNodeID(NodeID);
CLightNode *pNode = new CLightNode(this, ID, mpAreaRootNode, pLight);
mNodes[eLightNode].push_back(pNode);
mNodeMap[ID] = pNode;
mNumNodes++;
return pNode;
}
@@ -104,13 +139,17 @@ void CScene::DeleteNode(CSceneNode *pNode)
}
}
auto MapIt = mNodeMap.find(pNode->ID());
if (MapIt != mNodeMap.end())
mNodeMap.erase(MapIt);
if (Type == eScriptNode)
{
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
auto ScriptMapIt = mScriptNodeMap.find(pScript->Object()->InstanceID());
if (ScriptMapIt != mScriptNodeMap.end())
mScriptNodeMap.erase(ScriptMapIt);
auto it = mScriptMap.find(pScript->Object()->InstanceID());
if (it != mScriptMap.end())
mScriptMap.erase(it);
switch (pScript->Object()->ObjectTypeID())
{
@@ -140,7 +179,7 @@ void CScene::SetActiveArea(CGameArea *pArea)
// Create nodes for new area
mpArea = pArea;
mpAreaRootNode = new CRootNode(this, mpSceneRootNode);
mpAreaRootNode = new CRootNode(this, -1, mpSceneRootNode);
// Create static nodes
u32 Count = mpArea->GetStaticModelCount();
@@ -190,10 +229,11 @@ void CScene::SetActiveArea(CGameArea *pArea)
}
// Ensure script nodes have valid positions + build light lists
for (auto it = mScriptNodeMap.begin(); it != mScriptNodeMap.end(); it++)
for (CSceneIterator It(this, eScriptNode, true); It; ++It)
{
it->second->GeneratePosition();
it->second->BuildLightList(mpArea);
CScriptNode *pScript = static_cast<CScriptNode*>(*It);
pScript->GeneratePosition();
pScript->BuildLightList(mpArea);
}
u32 NumLightLayers = mpArea->GetLightLayerCount();
@@ -239,7 +279,7 @@ void CScene::ClearScene()
mNodes.clear();
mAreaAttributesObjects.clear();
mScriptNodeMap.clear();
mNodeMap.clear();
mNumNodes = 0;
mpArea = nullptr;
@@ -277,17 +317,25 @@ SRayIntersection CScene::SceneRayCast(const CRay& Ray, const SViewInfo& ViewInfo
return Tester.TestNodes(ViewInfo);
}
CScriptNode* CScene::ScriptNodeByID(u32 InstanceID)
CSceneNode* CScene::NodeByID(u32 NodeID)
{
auto it = mScriptNodeMap.find(InstanceID);
auto it = mNodeMap.find(NodeID);
if (it != mScriptNodeMap.end()) return it->second;
if (it != mNodeMap.end()) return it->second;
else return nullptr;
}
CScriptNode* CScene::NodeForInstanceID(u32 InstanceID)
{
auto it = mScriptMap.find(InstanceID);
if (it != mScriptMap.end()) return it->second;
else return nullptr;
}
CScriptNode* CScene::NodeForObject(CScriptObject *pObj)
{
return ScriptNodeByID(pObj->InstanceID());
return NodeForInstanceID(pObj->InstanceID());
}
CLightNode* CScene::NodeForLight(CLight *pLight)

View File

@@ -38,19 +38,23 @@ class CScene
// Environment
std::vector<CAreaAttributes> mAreaAttributesObjects;
// Objects
std::unordered_map<u32, CScriptNode*> mScriptNodeMap;
// Node Management
std::unordered_map<u32, CSceneNode*> mNodeMap;
std::unordered_map<u32, CScriptNode*> mScriptMap;
public:
CScene();
~CScene();
// Scene Management
CModelNode* CreateModelNode(CModel *pModel);
CStaticNode* CreateStaticNode(CStaticModel *pModel);
CCollisionNode* CreateCollisionNode(CCollisionMeshGroup *pMesh);
CScriptNode* CreateScriptNode(CScriptObject *pObj);
CLightNode* CreateLightNode(CLight *pLight);
bool IsNodeIDUsed(u32 ID) const;
u32 CreateNodeID(u32 SuggestedID = -1) const;
CModelNode* CreateModelNode(CModel *pModel, u32 NodeID = -1);
CStaticNode* CreateStaticNode(CStaticModel *pModel, u32 NodeID = -1);
CCollisionNode* CreateCollisionNode(CCollisionMeshGroup *pMesh, u32 NodeID = -1);
CScriptNode* CreateScriptNode(CScriptObject *pObj, u32 NodeID = -1);
CLightNode* CreateLightNode(CLight *pLight, u32 NodeID = -1);
void DeleteNode(CSceneNode *pNode);
void SetActiveArea(CGameArea *pArea);
void SetActiveWorld(CWorld *pWorld);
@@ -58,7 +62,8 @@ public:
void ClearScene();
void AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo);
SRayIntersection SceneRayCast(const CRay& rkRay, const SViewInfo& rkViewInfo);
CScriptNode* ScriptNodeByID(u32 InstanceID);
CSceneNode* NodeByID(u32 NodeID);
CScriptNode* NodeForInstanceID(u32 InstanceID);
CScriptNode* NodeForObject(CScriptObject *pObj);
CLightNode* NodeForLight(CLight *pLight);

View File

@@ -12,11 +12,12 @@
u32 CSceneNode::smNumNodes = 0;
CColor CSceneNode::skSelectionTint = CColor::Integral(39, 154, 167);
CSceneNode::CSceneNode(CScene *pScene, CSceneNode *pParent)
CSceneNode::CSceneNode(CScene *pScene, u32 NodeID, CSceneNode *pParent)
{
smNumNodes++;
mpScene = pScene;
mpParent = pParent;
_mID = NodeID;
mPosition = CVector3f::skZero;
mRotation = CQuaternion::skIdentity;
@@ -341,6 +342,11 @@ CScene* CSceneNode::Scene() const
return mpScene;
}
u32 CSceneNode::ID() const
{
return _mID;
}
CVector3f CSceneNode::LocalPosition() const
{
return mPosition;

View File

@@ -29,6 +29,8 @@ private:
bool _mInheritsRotation;
bool _mInheritsScale;
u32 _mID;
protected:
static u32 smNumNodes;
TString mName;
@@ -51,7 +53,7 @@ protected:
CColor mAmbientColor;
public:
explicit CSceneNode(CScene *pScene, CSceneNode *pParent = 0);
explicit CSceneNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0);
virtual ~CSceneNode();
virtual ENodeType NodeType() = 0;
virtual void PostLoad() {}
@@ -94,6 +96,7 @@ public:
TString Name() const;
CSceneNode* Parent() const;
CScene* Scene() const;
u32 ID() const;
CVector3f LocalPosition() const;
CVector3f AbsolutePosition() const;
CQuaternion LocalRotation() const;

View File

@@ -10,8 +10,8 @@
#include <Common/AnimUtil.h>
#include <Math/MathUtil.h>
CScriptNode::CScriptNode(CScene *pScene, CSceneNode *pParent, CScriptObject *pObject)
: CSceneNode(pScene, pParent)
CScriptNode::CScriptNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CScriptObject *pObject)
: CSceneNode(pScene, NodeID, pParent)
, mGameModeVisibility(eUntested)
{
mpVolumePreviewNode = nullptr;
@@ -21,7 +21,7 @@ CScriptNode::CScriptNode(CScene *pScene, CSceneNode *pParent, CScriptObject *pOb
mpInstance = pObject;
SetActiveModel(nullptr);
mpBillboard = nullptr;
mpCollisionNode = new CCollisionNode(pScene, this);
mpCollisionNode = new CCollisionNode(pScene, -1, this);
mpCollisionNode->SetInheritance(true, true, false);
if (mpInstance)
@@ -43,7 +43,7 @@ CScriptNode::CScriptNode(CScene *pScene, CSceneNode *pParent, CScriptObject *pOb
mpCollisionNode->SetCollision(mpInstance->GetCollision());
// Create preview volume node
mpVolumePreviewNode = new CModelNode(pScene, this, nullptr);
mpVolumePreviewNode = new CModelNode(pScene, -1, this, nullptr);
if (pTemp->ScaleType() == CScriptTemplate::eScaleVolume)
{
@@ -259,14 +259,14 @@ void CScriptNode::DrawSelection()
{
// Don't draw in links if the other object is selected.
CLink *pLink = mpInstance->Link(eIncoming, iIn);
CScriptNode *pLinkNode = mpScene->ScriptNodeByID(pLink->SenderID());
CScriptNode *pLinkNode = mpScene->NodeForInstanceID(pLink->SenderID());
if (pLinkNode && !pLinkNode->IsSelected()) CDrawUtil::DrawLine(CenterPoint(), pLinkNode->CenterPoint(), CColor::skTransparentRed);
}
for (u32 iOut = 0; iOut < mpInstance->NumLinks(eOutgoing); iOut++)
{
CLink *pLink = mpInstance->Link(eOutgoing, iOut);
CScriptNode *pLinkNode = mpScene->ScriptNodeByID(pLink->ReceiverID());
CScriptNode *pLinkNode = mpScene->NodeForInstanceID(pLink->ReceiverID());
if (pLinkNode) CDrawUtil::DrawLine(CenterPoint(), pLinkNode->CenterPoint(), CColor::skTransparentGreen);
}
}
@@ -549,7 +549,7 @@ void CScriptNode::GeneratePosition()
if (NumLinks == 1)
{
u32 LinkedID = (mpInstance->NumLinks(eIncoming) > 0 ? mpInstance->Link(eIncoming, 0)->SenderID() : mpInstance->Link(eOutgoing, 0)->ReceiverID());
CScriptNode *pNode = mpScene->ScriptNodeByID(LinkedID);
CScriptNode *pNode = mpScene->NodeForInstanceID(LinkedID);
pNode->GeneratePosition();
mPosition = pNode->AbsolutePosition();
mPosition.z += (pNode->AABox().Size().z / 2.f);
@@ -564,7 +564,7 @@ void CScriptNode::GeneratePosition()
for (u32 iIn = 0; iIn < mpInstance->NumLinks(eIncoming); iIn++)
{
CScriptNode *pNode = mpScene->ScriptNodeByID(mpInstance->Link(eIncoming, iIn)->SenderID());
CScriptNode *pNode = mpScene->NodeForInstanceID(mpInstance->Link(eIncoming, iIn)->SenderID());
if (pNode)
{
@@ -575,7 +575,7 @@ void CScriptNode::GeneratePosition()
for (u32 iOut = 0; iOut < mpInstance->NumLinks(eOutgoing); iOut++)
{
CScriptNode *pNode = mpScene->ScriptNodeByID(mpInstance->Link(eOutgoing, iOut)->ReceiverID());
CScriptNode *pNode = mpScene->NodeForInstanceID(mpInstance->Link(eOutgoing, iOut)->ReceiverID());
if (pNode)
{

View File

@@ -30,7 +30,7 @@ class CScriptNode : public CSceneNode
} mGameModeVisibility;
public:
CScriptNode(CScene *pScene, CSceneNode *pParent = 0, CScriptObject *pObject = 0);
CScriptNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CScriptObject *pObject = 0);
ENodeType NodeType();
void PostLoad();
void OnTransformed();

View File

@@ -5,8 +5,8 @@
#include <Common/AnimUtil.h>
#include <Math/MathUtil.h>
CStaticNode::CStaticNode(CScene *pScene, CSceneNode *pParent, CStaticModel *pModel)
: CSceneNode(pScene, pParent)
CStaticNode::CStaticNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CStaticModel *pModel)
: CSceneNode(pScene, NodeID, pParent)
{
mpModel = pModel;
mLocalAABox = mpModel->AABox();

View File

@@ -9,7 +9,7 @@ class CStaticNode : public CSceneNode
CStaticModel *mpModel;
public:
CStaticNode(CScene *pScene, CSceneNode *pParent = 0, CStaticModel *pModel = 0);
CStaticNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CStaticModel *pModel = 0);
ENodeType NodeType();
void PostLoad();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);

View File

@@ -20,7 +20,7 @@ protected:
public:
explicit CScriptExtra(CScriptObject *pInstance, CScene *pScene, CSceneNode *pParent = 0)
: CSceneNode(pScene, pParent),
: CSceneNode(pScene, -1, pParent),
mpInstance(pInstance),
mGame(pInstance->Template()->Game())
{

View File

@@ -53,7 +53,7 @@ void CSplinePathExtra::AddWaypoints()
if ( (pLink->State() == 0x49533030 && pLink->Message() == 0x41544348) || // InternalState00/Attach
(pLink->State() == 0x4D4F5450 && pLink->Message() == 0x41544348) ) // MotionPath/Attach
{
CScriptNode *pNode = mpScene->ScriptNodeByID(pLink->ReceiverID());
CScriptNode *pNode = mpScene->NodeForInstanceID(pLink->ReceiverID());
if (pNode && pNode->Object()->ObjectTypeID() == 0x57415950) // Waypoint
{

View File

@@ -85,7 +85,7 @@ void CWaypointExtra::BuildLinks()
if (IsPathLink(pLink))
{
CScriptNode *pNode = mpScene->ScriptNodeByID(pLink->ReceiverID());
CScriptNode *pNode = mpScene->NodeForInstanceID(pLink->ReceiverID());
SWaypointLink Link;
Link.pWaypoint = pNode;
@@ -117,7 +117,7 @@ bool CWaypointExtra::IsPathLink(CLink *pLink)
if (Valid)
{
CScriptNode *pNode = mpScene->ScriptNodeByID(pLink->ReceiverID());
CScriptNode *pNode = mpScene->NodeForInstanceID(pLink->ReceiverID());
if (pNode)
return pNode->Object()->ObjectTypeID() == mpInstance->ObjectTypeID();