mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 14:37:41 +00:00
Add read and write file functions for clothing
(cherry picked from commit 4f13d37905
)
This commit is contained in:
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -193,8 +193,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();
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user