Пример #1
0
        public static OSDArray BakedToOSD(WearableCacheItem[] pcacheItems)
        {
            if (pcacheItems.Length < AvatarAppearance.BAKE_INDICES[AvatarAppearance.BAKE_INDICES.Length - 1])
            {
                return(null);
            }

            OSDArray arr = new OSDArray();

            for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
            {
                int idx = AvatarAppearance.BAKE_INDICES[i];

                WearableCacheItem item = pcacheItems[idx];

                OSDMap itemmap = new OSDMap();
                itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
                itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
                itemmap.Add("textureid", OSD.FromUUID(item.TextureID));

/*
 *              if (item.TextureAsset != null)
 *              {
 *                  itemmap.Add("assetdata", OSD.FromBinary(item.TextureAsset.Data));
 *                  itemmap.Add("assetcreator", OSD.FromString(item.TextureAsset.CreatorID));
 *                  itemmap.Add("assetname", OSD.FromString(item.TextureAsset.Name));
 *              }
 */
                arr.Add(itemmap);
            }
            return(arr);
        }
Пример #2
0
        public static OSDArray BakedToOSD(WearableCacheItem[] pcacheItems, int start, int end)
        {
            OSDArray arr = new OSDArray();

            if (start < 0)
            {
                start = 0;
            }
            if (end < 0 || end > AvatarAppearance.BAKE_INDICES.Length)
            {
                end = AvatarAppearance.BAKE_INDICES.Length;
            }
            if (start > end)
            {
                return(null);
            }

            for (int i = start; i < end; i++)
            {
                int idx = AvatarAppearance.BAKE_INDICES[i];
                if (idx >= pcacheItems.Length)
                {
                    continue;
                }
                WearableCacheItem item = pcacheItems[idx];

                OSDMap itemmap = new OSDMap();
                itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
                itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
                itemmap.Add("textureid", OSD.FromUUID(item.TextureID));
                arr.Add(itemmap);
            }
            return(arr);
        }
Пример #3
0
        public static WearableCacheItem[] BakedFromOSD(OSD pInput)
        {
            WearableCacheItem[] pcache = WearableCacheItem.GetDefaultCacheItem();

            if (pInput.Type == OSDType.Array)
            {
                OSDArray itemarray = (OSDArray)pInput;
                foreach (OSDMap item in itemarray)
                {
                    int idx = (int)item["textureindex"].AsUInteger();
                    if (idx < 0 || idx > pcache.Length)
                    {
                        continue;
                    }
                    pcache[idx].CacheId   = item["cacheid"].AsUUID();
                    pcache[idx].TextureID = item["textureid"].AsUUID();

/*
 *                  if (item.ContainsKey("assetdata"))
 *                  {
 *                      AssetBase asset = new AssetBase(item["textureid"].AsUUID(), "BakedTexture", (sbyte)AssetType.Texture, UUID.Zero.ToString());
 *                      asset.Temporary = true;
 *                      asset.Local = true;
 *                      asset.Data = item["assetdata"].AsBinary();
 *                      pcache[idx].TextureAsset = asset;
 *                  }
 *                  else
 */
                    pcache[idx].TextureAsset = null;
                }
            }
            return(pcache);
        }
Пример #4
0
 public static WearableCacheItem[] GetDefaultCacheItem()
 {
     int itemmax = 21;
     WearableCacheItem[] retitems = new WearableCacheItem[itemmax];
     for (uint i=0;i<itemmax;i++)
         retitems[i] = new WearableCacheItem() {CacheId = UUID.Zero, TextureID = UUID.Zero, TextureIndex = i + 1};
     return retitems;
 }
Пример #5
0
 public static WearableCacheItem[] GetDefaultCacheItem()
 {
     int itemmax = AvatarAppearance.TEXTURE_COUNT;
     WearableCacheItem[] retitems = new WearableCacheItem[itemmax];
     for (uint i=0;i<itemmax;i++)
         retitems[i] = new WearableCacheItem() {CacheId = UUID.Zero, TextureID = UUID.Zero, TextureIndex = i};
     return retitems;          
 }
Пример #6
0
        public static WearableCacheItem[] GetDefaultCacheItem()
        {
            int itemmax = AvatarAppearance.TEXTURE_COUNT;

            WearableCacheItem[] retitems = new WearableCacheItem[itemmax];
            for (uint i = 0; i < itemmax; i++)
            {
                retitems[i] = new WearableCacheItem()
                {
                    CacheId = UUID.Zero, TextureID = UUID.Zero, TextureIndex = i
                }
            }
            ;
            return(retitems);
        }
        public static WearableCacheItem[] GetDefaultCacheItem()
        {
            int itemmax = 21;

            WearableCacheItem[] retitems = new WearableCacheItem[itemmax];
            for (uint i = 0; i < itemmax; i++)
            {
                retitems[i] = new WearableCacheItem()
                {
                    CacheId = UUID.Zero, TextureID = UUID.Zero, TextureIndex = i + 1
                }
            }
            ;
            return(retitems);
        }
Пример #8
0
 public static WearableCacheItem[] BakedFromOSD(OSD pInput)
 {
     WearableCacheItem[] pcache = WearableCacheItem.GetDefaultCacheItem();
     if (pInput.Type == OSDType.Array)
     {
         OSDArray itemarray = (OSDArray)pInput;
         foreach (OSDMap item in itemarray)
         {
             int idx = item["textureindex"].AsInteger();
             if (idx < 0 || idx >= pcache.Length)
             {
                 continue;
             }
             pcache[idx].CacheId      = item["cacheid"].AsUUID();
             pcache[idx].TextureID    = item["textureid"].AsUUID();
             pcache[idx].TextureAsset = null;
         }
     }
     return(pcache);
 }
Пример #9
0
        public void Store(UUID agentId, WearableCacheItem[] data)
        {
            if (m_URL == String.Empty)
                return;

            MemoryStream reqStream;

            using (MemoryStream bakeStream = new MemoryStream())
            using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null))
            {
                bakeWriter.WriteStartElement(String.Empty, "BakedAppearance", String.Empty);

                for (int i = 0; i < data.Length; i++)
                {
                    if (data[i] != null)
                    {
                        bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
                        bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
                        bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
                        if (data[i].TextureAsset != null)
                            m_serializer.Serialize(bakeWriter, data[i].TextureAsset);

                        bakeWriter.WriteEndElement();
                    }
                }

                bakeWriter.WriteEndElement();
                bakeWriter.Flush();

                reqStream = new MemoryStream(bakeStream.ToArray());
            }

            RestClient rc = new RestClient(m_URL);
            rc.AddResourcePath("bakes");
            rc.AddResourcePath(agentId.ToString());

            rc.RequestMethod = "POST";

            Util.FireAndForget(
                delegate
                {
                    rc.Request(reqStream, m_Auth);
                    m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", data.Length, agentId);
                }, null, "XBakesModule.Store"
            );
        }
Пример #10
0
 public static WearableCacheItem SearchTextureTextureId(UUID pTextureId, WearableCacheItem[] pcacheItems)
 {
     for (int i = 0; i < pcacheItems.Length; i++)
     {
         if (pcacheItems[i].TextureID == pTextureId)
             return pcacheItems[i];
     }
     return null;
 }
Пример #11
0
 public static WearableCacheItem SearchTextureIndex(uint pTextureIndex,WearableCacheItem[] pcacheItems)
 {
     for (int i = 0; i < pcacheItems.Length; i++)
     {
         if (pcacheItems[i].TextureIndex == pTextureIndex)
             return pcacheItems[i];
     }
     return null;
 }
Пример #12
0
        public static OSDArray BakedToOSD(WearableCacheItem[] pcacheItems)
        {
            if (pcacheItems.Length < AvatarAppearance.BAKE_INDICES[AvatarAppearance.BAKE_INDICES.Length - 1])
                return null;

            OSDArray arr = new OSDArray();

            for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
            {
                int idx = AvatarAppearance.BAKE_INDICES[i];

                WearableCacheItem item = pcacheItems[idx];

                OSDMap itemmap = new OSDMap();
                itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
                itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
                itemmap.Add("textureid", OSD.FromUUID(item.TextureID));
/*
                if (item.TextureAsset != null)
                {
                    itemmap.Add("assetdata", OSD.FromBinary(item.TextureAsset.Data));
                    itemmap.Add("assetcreator", OSD.FromString(item.TextureAsset.CreatorID));
                    itemmap.Add("assetname", OSD.FromString(item.TextureAsset.Name));
                }
 */
                arr.Add(itemmap);
            }
            return arr;
        }
Пример #13
0
 public static OSD ToOSD(WearableCacheItem[] pcacheItems, IImprovedAssetCache dataCache)
 {
     OSDArray arr = new OSDArray();
     foreach (WearableCacheItem item in pcacheItems)
     {
         OSDMap itemmap = new OSDMap();
         itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
         itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
         itemmap.Add("textureid", OSD.FromUUID(item.TextureID));
         if (dataCache != null)
         {
             if (dataCache.Check(item.TextureID.ToString()))
             {
                 AssetBase assetItem = dataCache.Get(item.TextureID.ToString());
                 if (assetItem != null)
                 {
                     itemmap.Add("assetdata", OSD.FromBinary(assetItem.Data));
                     itemmap.Add("assetcreator", OSD.FromString(assetItem.CreatorID));
                     itemmap.Add("assetname", OSD.FromString(assetItem.Name));
                 }
             }
         }
         arr.Add(itemmap);
     }
     return arr;
 }
        /// <summary>
        /// Set appearance data (texture asset IDs and slider settings) 
        /// </summary>
        /// <param name="sp"></param>
        /// <param name="texture"></param>
        /// <param name="visualParam"></param>
        public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems)
        {
//            m_log.DebugFormat(
//                "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
//                sp.Name, textureEntry, visualParams);

            // 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)
                {
                    //                    string[] visualParamsStrings = new string[visualParams.Length];
                    //                    for (int i = 0; i < visualParams.Length; i++)
                    //                        visualParamsStrings[i] = visualParams[i].ToString();
                    //                    m_log.DebugFormat(
                    //                        "[AVFACTORY]: Setting visual params for {0} to {1}",
                    //                        client.Name, string.Join(", ", visualParamsStrings));
/*
                    float oldHeight = sp.Appearance.AvatarHeight;
                    changed = sp.Appearance.SetVisualParams(visualParams);

                    if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
                        ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
 */
//                    float oldoff = sp.Appearance.AvatarFeetOffset;
//                    Vector3 oldbox = sp.Appearance.AvatarBoxSize;
                    changed = sp.Appearance.SetVisualParams(visualParams);
//                    float off = sp.Appearance.AvatarFeetOffset;
//                    Vector3 box = sp.Appearance.AvatarBoxSize;
//                    if(oldoff != off || oldbox != box)
//                        ((ScenePresence)sp).SetSize(box,off);

                }
            
                // Process the baked texture array
                if (textureEntry != null)
                {
                    m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID);

//                    WriteBakedTexturesReport(sp, m_log.DebugFormat);

                    changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;

//                    WriteBakedTexturesReport(sp, m_log.DebugFormat);

                    // If bake textures are missing and this is not an NPC, request a rebake from client
                    if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
                        RequestRebake(sp, true);

                    // 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.
                }

                // NPC should send to clients immediately and skip saving appearance
                if (((ScenePresence)sp).PresenceType == PresenceType.Npc)
                {
                    SendAppearance((ScenePresence)sp);
                    return;
                }

                // save only if there were changes, send no matter what (doesn't hurt to send twice)
                if (changed)
                    QueueAppearanceSave(sp.ControllingClient.AgentId);

                QueueAppearanceSend(sp.ControllingClient.AgentId);
            }

            // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString());
        }
        private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
        {
            int maxCacheitemsLoop = cacheItems.Length;
            if (maxCacheitemsLoop > AvatarWearable.MAX_WEARABLES)
            {
                maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES;
                m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}.  Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES);
            }

            m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
            if (cacheItems.Length > 0)
            {
//                m_log.Debug("[Cacheitems]: " + cacheItems.Length);
//                for (int iter = 0; iter < maxCacheitemsLoop; iter++)
//                {
//                    m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
//                                      cacheItems[iter].TextureID);
//                }
               
                ScenePresence p = null;
                if (m_scene.TryGetScenePresence(remoteClient.AgentId, out p))
                {

                    WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems;
                    if (existingitems == null)
                    {
                        if (m_BakedTextureModule != null)
                        {
                            WearableCacheItem[] savedcache = null;
                            try
                            {
                                if (p.Appearance.WearableCacheItemsDirty)
                                {
                                    savedcache = m_BakedTextureModule.Get(p.UUID);
                                    p.Appearance.WearableCacheItems = savedcache;
                                    p.Appearance.WearableCacheItemsDirty = false;
                                }

                            }
                            /*
                             * The following Catch types DO NOT WORK with m_BakedTextureModule.Get
                             * it jumps to the General Packet Exception Handler if you don't catch Exception!
                             * 
                            catch (System.Net.Sockets.SocketException)
                            {
                                cacheItems = null;
                            }
                            catch (WebException)
                            {
                                cacheItems = null;
                            }
                            catch (InvalidOperationException)
                            {
                                cacheItems = null;
                            } */
                            catch (Exception)
                            {
                               // The service logs a sufficient error message.
                            }
                            

                            if (savedcache != null)
                                existingitems = savedcache;
                        }
                    }
                    // Existing items null means it's a fully new appearance
                    if (existingitems == null)
                    {

                        for (int i = 0; i < maxCacheitemsLoop; i++)
                        {
                            if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
                            {
                                Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
                                if (face == null)
                                {
                                    textureEntry.CreateFace(cacheItems[i].TextureIndex);
                                    textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
                                        AppearanceManager.DEFAULT_AVATAR_TEXTURE;
                                    continue;
                                }
                                cacheItems[i].TextureID =face.TextureID;
                                if (m_scene.AssetService != null)
                                    cacheItems[i].TextureAsset =
                                        m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
                            }
                            else
                            {
                                m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}.  Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length);
                            }


                        }
                    }
                    else


                    {
                        // for each uploaded baked texture
                        for (int i = 0; i < maxCacheitemsLoop; i++)
                        {
                            if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
                            {
                                Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
                                if (face == null)
                                {
                                    textureEntry.CreateFace(cacheItems[i].TextureIndex);
                                    textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
                                        AppearanceManager.DEFAULT_AVATAR_TEXTURE;
                                    continue;
                                }
                                cacheItems[i].TextureID =
                                    face.TextureID;
                            }
                            else
                            {
                                m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}.  Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length);
                            }
                        }

                        for (int i = 0; i < maxCacheitemsLoop; i++)
                        {
                            if (cacheItems[i].TextureAsset == null)
                            {
                                cacheItems[i].TextureAsset =
                                    m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
                            }
                        }
                    }



                    p.Appearance.WearableCacheItems = cacheItems;
                    
                   

                    if (m_BakedTextureModule != null)
                    {
                        m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems);
                        p.Appearance.WearableCacheItemsDirty = true;
                        
                    }
                }
            }
        }
        // called on textures update
        public bool UpdateBakedTextureCache(IScenePresence sp, WearableCacheItem[] cacheItems)
        {
            if(cacheItems == null)
                return false;

            // npcs dont have baked cache
            if (((ScenePresence)sp).isNPC)
                return true;

            // uploaded baked textures will be in assets local cache
            IAssetService cache = m_scene.AssetService;
            IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();

            int validDirtyBakes = 0;
            int hits = 0;

            // our main cacheIDs mapper is p.Appearance.WearableCacheItems
            WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;

            if (wearableCache == null)
            {
                wearableCache = WearableCacheItem.GetDefaultCacheItem();
            }

            List<UUID> missing = new List<UUID>();

            bool haveSkirt = (wearableCache[19].TextureAsset != null);
            bool haveNewSkirt = false;

            // Process received baked textures
            for (int i = 0; i < cacheItems.Length; i++)
            {
                int idx = (int)cacheItems[i].TextureIndex;
                Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];

                // No face
                if (face == null)
                {
                    // for some reason viewer is cleaning this
                    if(idx != 19) // skirt is optional
                        {
                        sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
                        sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
                        }
                    wearableCache[idx].CacheId = UUID.Zero;
                    wearableCache[idx].TextureID = UUID.Zero;
                    wearableCache[idx].TextureAsset = null;
                    continue;
                }
                else
                {
                    if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
                    {
                        wearableCache[idx].CacheId = UUID.Zero;
                        wearableCache[idx].TextureID = UUID.Zero;
                        wearableCache[idx].TextureAsset = null;
                        continue;
                    }

                    if(idx == 19)
                        haveNewSkirt = true;
/*
                    if (face.TextureID == wearableCache[idx].TextureID && m_BakedTextureModule != null)
                    {
                        if (wearableCache[idx].CacheId != cacheItems[i].CacheId)
                        {
                            wearableCache[idx].CacheId = cacheItems[i].CacheId;
                            validDirtyBakes++;

                            //assuming this can only happen if asset is in cache
                        }
                        hits++;
                        continue;
                    }
*/
                    wearableCache[idx].TextureAsset = null;
                    if (cache != null)
                       wearableCache[idx].TextureAsset = cache.GetCached(face.TextureID.ToString());

                    if (wearableCache[idx].TextureAsset != null)
                    {
                        if ( wearableCache[idx].TextureID != face.TextureID ||
                                wearableCache[idx].CacheId != cacheItems[i].CacheId)
                            validDirtyBakes++;

                        wearableCache[idx].TextureID = face.TextureID;
                        wearableCache[idx].CacheId = cacheItems[i].CacheId;
                        hits++;
                    }
                    else
                    {
                        wearableCache[idx].CacheId = UUID.Zero;
                        wearableCache[idx].TextureID = UUID.Zero;
                        wearableCache[idx].TextureAsset = null;
                        missing.Add(face.TextureID);
                        continue;
                    }
                }
            }

            // handle optional skirt case
            if(!haveNewSkirt && haveSkirt)
            {
                wearableCache[19].CacheId = UUID.Zero;
                wearableCache[19].TextureID = UUID.Zero;
                wearableCache[19].TextureAsset = null;
                validDirtyBakes++;
            }

            sp.Appearance.WearableCacheItems = wearableCache;
           
            if (missing.Count > 0)
            {
                foreach (UUID id in missing)
                    sp.ControllingClient.SendRebakeAvatarTextures(id);
            }

            if (validDirtyBakes > 0 && hits == cacheItems.Length)
            {
                // if we got a full set of baked textures save all in BakedTextureModule
                if (m_BakedTextureModule != null)
                {
                    m_log.Debug("[UpdateBakedCache] start async uploading to bakedModule cache");

                    m_BakedTextureModule.Store(sp.UUID, wearableCache);
                }
            }


            // debug
            m_log.Debug("[UpdateBakedCache] cache hits: " + hits.ToString() + " changed entries: " + validDirtyBakes.ToString() + " rebakes " + missing.Count);
/*
            for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
            {
                int j = AvatarAppearance.BAKE_INDICES[iter];
                m_log.Debug("[UpdateBCache] {" + iter + "/" + 
                                    sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
                                    sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
                                    sp.Appearance.WearableCacheItems[j].TextureID);
            }
*/
            return (hits == cacheItems.Length);
        }
        /// <summary>
        /// Set appearance data (texture asset IDs and slider settings) 
        /// </summary>
        /// <param name="sp"></param>
        /// <param name="texture"></param>
        /// <param name="visualParam"></param>
        public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems)
        {
//            m_log.DebugFormat(
//                "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
//                sp.Name, textureEntry, visualParams);

            // 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);
                }
            
                // Process the baked texture array
                if (textureEntry != null)
                {
                    m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID);

//                    WriteBakedTexturesReport(sp, m_log.DebugFormat);

                    changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;

//                    WriteBakedTexturesReport(sp, m_log.DebugFormat);

                    UpdateBakedTextureCache(sp, cacheItems);

                    // 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.
                }

                // NPC should send to clients immediately and skip saving appearance
                if (((ScenePresence)sp).PresenceType == PresenceType.Npc)
                {
                    SendAppearance((ScenePresence)sp);
                    return;
                }

                // save only if there were changes, send no matter what (doesn't hurt to send twice)
                if (changed)
                    QueueAppearanceSave(sp.ControllingClient.AgentId);

                QueueAppearanceSend(sp.ControllingClient.AgentId);
            }

            // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString());
        }
        public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
        {
            float oldoff = sp.Appearance.AvatarFeetOffset;
            Vector3 oldbox = sp.Appearance.AvatarBoxSize;

            SetAppearance(sp, textureEntry, visualParams, cacheItems);
            sp.Appearance.SetSize(avSize);

            float off = sp.Appearance.AvatarFeetOffset;
            Vector3 box = sp.Appearance.AvatarBoxSize;
            if (oldoff != off || oldbox != box)
                ((ScenePresence)sp).SetSize(box, off);
        }
 /// </summary>
 /// <param name="sp"></param>
 /// <param name="texture"></param>
 /// <param name="visualParam"></param>
 public void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems)
 {
     SetAppearance(sp, appearance.Texture, appearance.VisualParams, cacheItems);
 }
 /// <summary>
 /// Set appearance data (texture asset IDs and slider settings) received from a client
 /// </summary>
 /// <param name="client"></param>
 /// <param name="texture"></param>
 /// <param name="visualParam"></param>
 private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
 {
     // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
     ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
     if (sp != null)
         SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems);
     else
         m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
 }