|
|
@ -431,7 +431,8 @@ hsBool plClothingBase::MsgReceive(plMessage* msg) |
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
plClothingOutfit::plClothingOutfit() :
|
|
|
|
plClothingOutfit::plClothingOutfit() :
|
|
|
|
fTargetLayer(nil), fBase(nil), fGroup(0), fAvatar(nil), fSynchClients(false), fMaterial(nil), fVaultSaveEnabled(true), fMorphsInitDone(false) |
|
|
|
fTargetLayer(nullptr), fBase(nullptr), fGroup(0), fAvatar(nullptr), fSynchClients(false), fMaterial(nullptr), |
|
|
|
|
|
|
|
fVaultSaveEnabled(true), fMorphsInitDone(false) |
|
|
|
{ |
|
|
|
{ |
|
|
|
fSkinTint.Set(1.f, 0.84, 0.71, 1.f); |
|
|
|
fSkinTint.Set(1.f, 0.84, 0.71, 1.f); |
|
|
|
fItems.Reset(); |
|
|
|
fItems.Reset(); |
|
|
@ -802,15 +803,24 @@ void plClothingOutfit::IHandleMorphSDR(plStateDataRecord *sdr) |
|
|
|
morph->SetCurrentStateFrom(sdr); |
|
|
|
morph->SetCurrentStateFrom(sdr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void plClothingOutfit::ReadFromVault() |
|
|
|
bool plClothingOutfit::ReadFromFile() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Have we set a clothing file? If that's the case, load from there.
|
|
|
|
|
|
|
|
if (fClothingFile.IsValid()) |
|
|
|
|
|
|
|
return IReadFromFile(fClothingFile); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
return IReadFromVault(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool plClothingOutfit::IReadFromVault() |
|
|
|
{ |
|
|
|
{ |
|
|
|
SetupMorphSDL(); |
|
|
|
SetupMorphSDL(); |
|
|
|
|
|
|
|
|
|
|
|
WearDefaultClothing(); |
|
|
|
WearDefaultClothing(); |
|
|
|
|
|
|
|
|
|
|
|
RelVaultNode * rvn; |
|
|
|
RelVaultNode * rvn = VaultGetAvatarOutfitFolderIncRef(); |
|
|
|
if (nil == (rvn = VaultGetAvatarOutfitFolderIncRef())) |
|
|
|
if (!rvn) |
|
|
|
return; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
ARRAY(RelVaultNode*) nodes; |
|
|
|
ARRAY(RelVaultNode*) nodes; |
|
|
|
rvn->GetChildNodesIncRef(plVault::kNodeType_SDL, 1, &nodes);
|
|
|
|
rvn->GetChildNodesIncRef(plVault::kNodeType_SDL, 1, &nodes);
|
|
|
@ -845,6 +855,7 @@ void plClothingOutfit::ReadFromVault() |
|
|
|
ForceUpdate(true); |
|
|
|
ForceUpdate(true); |
|
|
|
|
|
|
|
|
|
|
|
rvn->DecRef(); |
|
|
|
rvn->DecRef(); |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void plClothingOutfit::SaveCustomizations(hsBool retry /* = true */) |
|
|
|
void plClothingOutfit::SaveCustomizations(hsBool retry /* = true */) |
|
|
@ -1146,7 +1157,7 @@ void plClothingOutfit::WearMaintainerOutfit() |
|
|
|
|
|
|
|
|
|
|
|
void plClothingOutfit::RemoveMaintainerOutfit() |
|
|
|
void plClothingOutfit::RemoveMaintainerOutfit() |
|
|
|
{ |
|
|
|
{ |
|
|
|
ReadFromVault(); |
|
|
|
ReadFromFile(); |
|
|
|
|
|
|
|
|
|
|
|
fVaultSaveEnabled = true; |
|
|
|
fVaultSaveEnabled = true; |
|
|
|
} |
|
|
|
} |
|
|
@ -1493,6 +1504,90 @@ void plClothingOutfit::SetupMorphSDL() |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool plClothingOutfit::WriteToFile(const plFileName &filename) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!filename.IsValid()) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RelVaultNode* rvn = VaultGetAvatarOutfitFolderIncRef(); |
|
|
|
|
|
|
|
if (!rvn) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hsUNIXStream S; |
|
|
|
|
|
|
|
if (!S.Open(filename, "wb")) { |
|
|
|
|
|
|
|
rvn->DecRef(); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
S.WriteByte(fGroup); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ARRAY(RelVaultNode*) nodes; |
|
|
|
|
|
|
|
rvn->GetChildNodesIncRef(plVault::kNodeType_SDL, 1, &nodes); |
|
|
|
|
|
|
|
S.WriteLE32(nodes.Count()); |
|
|
|
|
|
|
|
for (size_t i = 0; i < nodes.Count(); i++) { |
|
|
|
|
|
|
|
VaultSDLNode sdl(nodes[i]); |
|
|
|
|
|
|
|
S.WriteLE32(sdl.GetSDLDataLength()); |
|
|
|
|
|
|
|
if (sdl.GetSDLDataLength()) |
|
|
|
|
|
|
|
S.Write(sdl.GetSDLDataLength(), sdl.GetSDLData()); |
|
|
|
|
|
|
|
nodes[i]->DecRef(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
rvn->DecRef(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
S.Close(); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool plClothingOutfit::IReadFromFile(const plFileName &filename) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!filename.IsValid()) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hsUNIXStream S; |
|
|
|
|
|
|
|
if (!S.Open(filename)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool isLocalAvatar = plAvatarMgr::GetInstance()->GetLocalAvatar()->GetClothingOutfit() == this; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t gender = S.ReadByte(); |
|
|
|
|
|
|
|
if (gender != fGroup) { |
|
|
|
|
|
|
|
if (isLocalAvatar) { |
|
|
|
|
|
|
|
if (gender == plClothingMgr::kClothingBaseMale) |
|
|
|
|
|
|
|
plClothingMgr::ChangeAvatar("Male", filename); |
|
|
|
|
|
|
|
else if (gender == plClothingMgr::kClothingBaseFemale) |
|
|
|
|
|
|
|
plClothingMgr::ChangeAvatar("Female", filename); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
S.Close(); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StripAccessories(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t nodeCount = S.ReadLE32(); |
|
|
|
|
|
|
|
for (size_t i = 0; i < nodeCount; i++) { |
|
|
|
|
|
|
|
uint32_t dataLen = S.ReadLE32(); |
|
|
|
|
|
|
|
if (dataLen) { |
|
|
|
|
|
|
|
plString sdlRecName; |
|
|
|
|
|
|
|
int sdlRecVersion; |
|
|
|
|
|
|
|
plStateDataRecord::ReadStreamHeader(&S, &sdlRecName, &sdlRecVersion); |
|
|
|
|
|
|
|
plStateDescriptor* desc = plSDLMgr::GetInstance()->FindDescriptor(sdlRecName, sdlRecVersion); |
|
|
|
|
|
|
|
if (desc) { |
|
|
|
|
|
|
|
plStateDataRecord sdlDataRec(desc); |
|
|
|
|
|
|
|
if (sdlDataRec.Read(&S, 0)) { |
|
|
|
|
|
|
|
if (sdlRecName == kSDLMorphSequence) |
|
|
|
|
|
|
|
IHandleMorphSDR(&sdlDataRec); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
plClothingSDLModifier::HandleSingleSDR(&sdlDataRec, this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
S.Close(); |
|
|
|
|
|
|
|
fSynchClients = true; |
|
|
|
|
|
|
|
ForceUpdate(true); |
|
|
|
|
|
|
|
SaveCustomizations(); // Sync with the vault
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|