From df860516bf4fa4e4196be4d5fc26db71d98334f4 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Fri, 3 Dec 2010 16:17:50 -0800 Subject: Various bug fixes for appearance handling: more aggressive reset of textures and vparams when appearance is not cached and when wearables change. Send appearance to the viewer with initial data. Cleaned up (and added) debugging. --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 99 ++++++++++++++-------- 1 file changed, 63 insertions(+), 36 deletions(-) (limited to 'OpenSim/Region/CoreModules/Avatar') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index ab1c206..7d6d191 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -115,8 +115,19 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory #endregion + /// + /// Check for the existence of the baked texture assets. Request a rebake + /// unless checkonly is true. + /// + /// + /// public bool ValidateBakedTextureCache(IClientAPI client) { + return ValidateBakedTextureCache(client, true); + } + + private bool ValidateBakedTextureCache(IClientAPI client, bool checkonly) + { ScenePresence sp = m_scene.GetScenePresence(client.AgentId); if (sp == null) { @@ -131,15 +142,33 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory { int idx = AvatarAppearance.BAKE_INDICES[i]; Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; - if (face == null || face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) + + // if there is no texture entry, skip it + if (face == null) continue; + // if the texture is one of the "defaults" then skip it + // this should probably be more intelligent (skirt texture doesnt matter + // if the avatar isnt wearing a skirt) but if any of the main baked + // textures is default then the rest should be as well + if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) + continue; + defonly = false; // found a non-default texture reference if (! CheckBakedTextureAsset(client,face.TextureID,idx)) - return false; + { + // the asset didn't exist if we are only checking, then we found a bad + // one and we're done otherwise, ask for a rebake + if (checkonly) return false; + + m_log.InfoFormat("[AVFACTORY] missing baked texture {0}, request rebake",face.TextureID); + client.SendRebakeAvatarTextures(face.TextureID); + } } + m_log.InfoFormat("[AVFACTORY]: complete texture check for {0}",client.AgentId); + // If we only found default textures, then the appearance is not cached return (defonly ? false : true); } @@ -158,55 +187,43 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return; } - // m_log.WarnFormat("[AVFACTORY]: Start SetAppearance for {0}",client.AgentId); + m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}",client.AgentId); + // TODO: This is probably not necessary any longer, just assume the + // textureEntry set implies that the appearance transaction is complete bool changed = false; // Process the texture entry transactionally, this doesn't guarantee that Appearance is // going to be handled correctly but it does serialize the updates to the appearance lock (m_setAppearanceLock) { + // Process the visual params, this may change height as well + if (visualParams != null) + { + changed = sp.Appearance.SetVisualParams(visualParams); + if (sp.Appearance.AvatarHeight > 0) + sp.SetHeight(sp.Appearance.AvatarHeight); + } + + // Process the baked texture array if (textureEntry != null) { - changed = sp.Appearance.SetTextureEntries(textureEntry); + changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; - // m_log.WarnFormat("[AVFACTORY]: Prepare to check textures for {0}",client.AgentId); + m_log.InfoFormat("[AVFACTORY]: received texture update for {0}",client.AgentId); + Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(client,false); }); - for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) - { - int idx = AvatarAppearance.BAKE_INDICES[i]; - Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; - if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) - Util.FireAndForget(delegate(object o) { - if (! CheckBakedTextureAsset(client,face.TextureID,idx)) - client.SendRebakeAvatarTextures(face.TextureID); - }); - } + // This appears to be set only in the final stage of the appearance + // update transaction. In theory, we should be able to do an immediate + // appearance send and save here. - m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); + QueueAppearanceSave(client.AgentId); + QueueAppearanceSend(client.AgentId); } - // Process the visual params, this may change height as well - if (visualParams != null) - { - if (sp.Appearance.SetVisualParams(visualParams)) - { - changed = true; - if (sp.Appearance.AvatarHeight > 0) - sp.SetHeight(sp.Appearance.AvatarHeight); - } - } } - - // If something changed in the appearance then queue an appearance save - if (changed) - QueueAppearanceSave(client.AgentId); - - // And always queue up an appearance update to send out - QueueAppearanceSend(client.AgentId); - - // m_log.WarnFormat("[AVFACTORY]: Complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); + // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); } /// @@ -229,6 +246,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory #region UpdateAppearanceTimer + /// + /// Queue up a request to send appearance, makes it possible to + /// accumulate changes without sending out each one separately. + /// public void QueueAppearanceSend(UUID agentid) { // m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); @@ -268,6 +289,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Send the appearance to everyone in the scene sp.SendAppearanceToAllOtherAgents(); + + // Send animations back to the avatar as well + sp.Animator.SendAnimPack(); } private void HandleAppearanceSave(UUID agentid) @@ -353,9 +377,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId); + // we need to clean out the existing textures + sp.Appearance.ResetAppearance(); + // operate on a copy of the appearance so we don't have to lock anything AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); - + foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) { if (wear.Type < AvatarWearable.MAX_WEARABLES) -- cgit v1.1