Browse Source

Add read and write file functions for clothing

tickets/35/35/2
Mystler 3 years ago committed by Patrick Dulebohn
parent
commit
4f13d37905
  1. 13
      Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp
  2. 6
      Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp
  3. 107
      Sources/Plasma/PubUtilLib/plAvatar/plAvatarClothing.cpp
  4. 26
      Sources/Plasma/PubUtilLib/plAvatar/plAvatarClothing.h

13
Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp

@ -84,6 +84,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plMessage/plListenerMsg.h" #include "../plMessage/plListenerMsg.h"
#include "../plMessage/plAgeLoadedMsg.h" #include "../plMessage/plAgeLoadedMsg.h"
#include "../plMessage/plParticleUpdateMsg.h" #include "../plMessage/plParticleUpdateMsg.h"
#include "plMessage/plLoadClothingMsg.h"
#include "../plParticleSystem/plParticleSystem.h" #include "../plParticleSystem/plParticleSystem.h"
#include "../plParticleSystem/plParticleSDLMod.h" #include "../plParticleSystem/plParticleSDLMod.h"
@ -1309,6 +1310,9 @@ hsBool plArmatureMod::MsgReceive(plMessage* msg)
} }
} }
// We also want to use the trigger msg when loading an avatar
MsgReceive(avLoadMsg->GetTriggerMsg());
// copy the user string over // copy the user string over
const char* userStr = avLoadMsg->GetUserStr(); const char* userStr = avLoadMsg->GetUserStr();
if (userStr) if (userStr)
@ -1356,6 +1360,15 @@ hsBool plArmatureMod::MsgReceive(plMessage* msg)
} }
} }
plLoadClothingMsg *clothingMsg = plLoadClothingMsg::ConvertNoRef(msg);
if (clothingMsg)
{
// We got a clothing file and are supposed to load our avatar from it.
// Let's tell our outfit to do so!
fClothingOutfit->SetClothingFile(clothingMsg->GetClothingFile());
return true;
}
plLinkEffectBCMsg *linkBCMsg = plLinkEffectBCMsg::ConvertNoRef(msg); plLinkEffectBCMsg *linkBCMsg = plLinkEffectBCMsg::ConvertNoRef(msg);
if (linkBCMsg) if (linkBCMsg)
{ {

6
Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp

@ -192,8 +192,10 @@ void plAvBrainHuman::Activate(plArmatureModBase *avMod)
if (fAvMod->GetClothingOutfit() && fAvMod->GetClothingOutfit()->fGroup != plClothingMgr::kClothingBaseNoOptions) if (fAvMod->GetClothingOutfit() && fAvMod->GetClothingOutfit()->fGroup != plClothingMgr::kClothingBaseNoOptions)
{ {
if (fAvMod->IsLocalAvatar()) if (fAvMod->IsLocalAvatar())
fAvMod->GetClothingOutfit()->ReadFromVault(); {
fAvMod->GetClothingOutfit()->ReadFromFile();
}
else else
{ {
fAvMod->GetClothingOutfit()->WearDefaultClothing(); fAvMod->GetClothingOutfit()->WearDefaultClothing();

107
Sources/Plasma/PubUtilLib/plAvatar/plAvatarClothing.cpp

@ -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;
}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

26
Sources/Plasma/PubUtilLib/plAvatar/plAvatarClothing.h

@ -215,26 +215,48 @@ public:
void IInstanceSharedMeshes(plClothingItem *item); void IInstanceSharedMeshes(plClothingItem *item);
void IRemoveSharedMeshes(plClothingItem *item); void IRemoveSharedMeshes(plClothingItem *item);
void ReadFromVault(); //** This will load the avatar clothing. If a clothing file is set,
* we will load from the file, otherwise from the vault.
*//
bool ReadFromFile();
void WriteToVault(); void WriteToVault();
void WriteToVault(const ARRAY(plStateDataRecord*) & SDRs); void WriteToVault(const ARRAY(plStateDataRecord*) & SDRs);
//** Write the avatar clothing to a file *//
bool WriteToFile(const plFileName &filename);
void SetupMorphSDL(); void SetupMorphSDL();
// XXX Don't use this. Temp function for a temp HACK console command. // XXX Don't use this. Temp function for a temp HACK console command.
void DirtyTileset(int tileset); void DirtyTileset(int tileset);
//** Instruct this plClothingOutfit to read clothing from the given file *//
void SetClothingFile(const plFileName &file) { fClothingFile = file; }
//** Returns the clothing file of this outfit. If there is none, an empty string will be returned.//
plFileName GetClothingFile() const { return fClothingFile; }
protected: protected:
hsBitVector fDirtyItems; hsBitVector fDirtyItems;
hsBool fVaultSaveEnabled; hsBool fVaultSaveEnabled;
bool fMorphsInitDone; bool fMorphsInitDone;
plFileName fClothingFile;
void IAddItem(plClothingItem *item); void IAddItem(plClothingItem *item);
void IRemoveItem(plClothingItem *item); void IRemoveItem(plClothingItem *item);
hsBool ITintItem(plClothingItem *item, hsColorRGBA color, UInt8 layer); hsBool ITintItem(plClothingItem *item, hsColorRGBA color, UInt8 layer);
hsBool IMorphItem(plClothingItem *item, UInt8 layer, UInt8 delta, hsScalar weight); hsBool IMorphItem(plClothingItem *item, UInt8 layer, UInt8 delta, hsScalar weight);
void IHandleMorphSDR(plStateDataRecord *sdr); void IHandleMorphSDR(plStateDataRecord *sdr);
bool IReadFromVault();
//** Read the avatar clothing from a file.//
// * A local avatar will change the clothing group to the one in the file.//
// * A local avatar will be invisible if the file does not exist. (used in the Startup age)//
bool IReadFromFile(const plFileName &filename);
void IUpdate(); void IUpdate();
}; };

Loading…
Cancel
Save