Esempio n. 1
0
        private Dictionary <BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(ScenePresence sp)
        {
            if (sp.IsChildAgent)
            {
                return(new Dictionary <BakeType, Primitive.TextureEntryFace>());
            }

            Dictionary <BakeType, Primitive.TextureEntryFace> bakedTextures
                = new Dictionary <BakeType, Primitive.TextureEntryFace>();

            AvatarAppearance appearance = sp.Appearance;

            Primitive.TextureEntryFace[] faceTextures = appearance.Texture.FaceTextures;

            foreach (int i in Enum.GetValues(typeof(BakeType)))
            {
                BakeType bakeType = (BakeType)i;

                if (bakeType == BakeType.Unknown)
                {
                    continue;
                }

//                m_log.DebugFormat(
//                    "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
//                    acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);

                int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
                Primitive.TextureEntryFace texture = faceTextures[ftIndex];    // this will be null if there's no such baked texture
                bakedTextures[bakeType] = texture;
            }

            return(bakedTextures);
        }
        /// <summary>
        ///     The client wants to know whether we already have baked textures for the given items
        /// </summary>
        /// <param name="client"></param>
        /// <param name="args"></param>
        void AgentCachedTexturesRequest(IClientAPI client, List <CachedAgentArgs> args)
        {
            IScenePresence          sp  = m_scene.GetScenePresence(client.AgentId);
            IAvatarAppearanceModule app = sp.RequestModuleInterface <IAvatarAppearanceModule> ();
            // Look up hashes to make sure that the request is valid

            List <CachedAgentArgs> resp = new List <CachedAgentArgs> ();

            foreach (CachedAgentArgs arg in args)
            {
                CachedAgentArgs r = new CachedAgentArgs();
                r.TextureIndex = arg.TextureIndex;
                //V2 changed to send the actual texture index, and not the baked texture index
                int index = arg.TextureIndex >= 5
                    ? arg.TextureIndex
                    : (int)AppearanceManager.BakeTypeToAgentTextureIndex((BakeType)arg.TextureIndex);

                r.ID = (
                    app.Appearance.Texture.FaceTextures [index] == null ||
                    app.Appearance.WearableCache.Count == 0 ||
                    !app.Appearance.WearableCache.ContainsKey(index.ToString()) ||
                    app.Appearance.WearableCache [index.ToString()] != arg.ID
                        ? UUID.Zero
                        : app.Appearance.Texture.FaceTextures [index].TextureID);

                resp.Add(r);
            }

            client.SendAgentCachedTexture(resp);
        }
        public void TestSetAppearance()
        {
            TestHelpers.InMethod();
//            TestHelpers.EnableLogging();

            UUID userId         = TestHelpers.ParseTail(0x1);
            UUID bakedTextureID = TestHelpers.ParseTail(0x2);

            // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly
            // to the AssetService, which will then store temporary and local assets permanently
            CoreAssetCache assetCache = new CoreAssetCache();

            AvatarFactoryModule afm   = new AvatarFactoryModule();
            TestScene           scene = new SceneHelpers(assetCache).SetupScene();

            SceneHelpers.SetupSceneModules(scene, afm);
            ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);

            // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules
            AssetBase bakedTextureAsset;

            bakedTextureAsset
                = new AssetBase(
                      bakedTextureID, "Test Baked Texture", (sbyte)AssetType.Texture, userId.ToString());
            bakedTextureAsset.Data      = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet
            bakedTextureAsset.Temporary = true;
            bakedTextureAsset.Local     = true;
            scene.AssetService.Store(bakedTextureAsset);

            byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT];
            for (byte i = 0; i < visualParams.Length; i++)
            {
                visualParams[i] = i;
            }

            Primitive.TextureEntry bakedTextureEntry = new Primitive.TextureEntry(TestHelpers.ParseTail(0x10));
            uint eyesFaceIndex = (uint)AppearanceManager.BakeTypeToAgentTextureIndex(BakeType.Eyes);

            Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);

            int rebakeRequestsReceived = 0;

            ((TestClient)sp.ControllingClient).OnReceivedSendRebakeAvatarTextures += id => rebakeRequestsReceived++;

            // This is the alpha texture
            eyesFace.TextureID = bakedTextureID;
            afm.SetAppearance(sp, bakedTextureEntry, visualParams, null);

            Assert.That(rebakeRequestsReceived, Is.EqualTo(0));

            AssetBase eyesBake = scene.AssetService.Get(bakedTextureID.ToString());

            Assert.That(eyesBake, Is.Not.Null);
            Assert.That(eyesBake.Temporary, Is.True);
            Assert.That(eyesBake.Local, Is.True);
        }
        public void TestSaveBakedTextures()
        {
            TestHelpers.InMethod();
//            log4net.Config.XmlConfigurator.Configure();

            UUID userId        = TestHelpers.ParseTail(0x1);
            UUID eyesTextureId = TestHelpers.ParseTail(0x2);

            // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly
            // to the AssetService, which will then store temporary and local assets permanently
            CoreAssetCache assetCache = new CoreAssetCache();

            AvatarFactoryModule afm   = new AvatarFactoryModule();
            TestScene           scene = SceneHelpers.SetupScene(assetCache);

            SceneHelpers.SetupSceneModules(scene, afm);
            ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);

            // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules
            AssetBase uploadedAsset;

            uploadedAsset           = new AssetBase(eyesTextureId, "Baked Texture", (sbyte)AssetType.Texture, userId.ToString());
            uploadedAsset.Data      = new byte[] { 2 };
            uploadedAsset.Temporary = true;
            uploadedAsset.Local     = true; // Local assets aren't persisted, non-local are
            scene.AssetService.Store(uploadedAsset);

            byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT];
            for (byte i = 0; i < visualParams.Length; i++)
            {
                visualParams[i] = i;
            }

            Primitive.TextureEntry bakedTextureEntry = new Primitive.TextureEntry(TestHelpers.ParseTail(0x10));
            uint eyesFaceIndex = (uint)AppearanceManager.BakeTypeToAgentTextureIndex(BakeType.Eyes);

            Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
            eyesFace.TextureID = eyesTextureId;

            afm.SetAppearance(sp, bakedTextureEntry, visualParams);
            afm.SaveBakedTextures(userId);
//            Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);

            // We should also inpsect the asset data store layer directly, but this is difficult to get at right now.
            assetCache.Clear();

            AssetBase eyesBake = scene.AssetService.Get(eyesTextureId.ToString());

            Assert.That(eyesBake, Is.Not.Null);
            Assert.That(eyesBake.Temporary, Is.False);
            Assert.That(eyesBake.Local, Is.False);
        }
        public void TestSetAppearanceAlphaBakedTextures()
        {
            TestHelpers.InMethod();
//            TestHelpers.EnableLogging();

            UUID userId         = TestHelpers.ParseTail(0x1);
            UUID alphaTextureID = new UUID("3a367d1c-bef1-6d43-7595-e88c1e3aadb3");

            // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly
            // to the AssetService, which will then store temporary and local assets permanently
            CoreAssetCache assetCache = new CoreAssetCache();

            AvatarFactoryModule afm   = new AvatarFactoryModule();
            TestScene           scene = new SceneHelpers(assetCache).SetupScene();

            SceneHelpers.SetupSceneModules(scene, afm);
            ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);

            AssetBase libraryAsset;

            libraryAsset
                = new AssetBase(
                      alphaTextureID, "Default Alpha Layer Texture", (sbyte)AssetType.Texture, userId.ToString());
            libraryAsset.Data      = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet
            libraryAsset.Temporary = false;
            libraryAsset.Local     = false;
            scene.AssetService.Store(libraryAsset);

            byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT];
            for (byte i = 0; i < visualParams.Length; i++)
            {
                visualParams[i] = i;
            }

            Primitive.TextureEntry bakedTextureEntry = new Primitive.TextureEntry(TestHelpers.ParseTail(0x10));
            uint eyesFaceIndex = (uint)AppearanceManager.BakeTypeToAgentTextureIndex(BakeType.Eyes);

            Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);

            int rebakeRequestsReceived = 0;

            ((TestClient)sp.ControllingClient).OnReceivedSendRebakeAvatarTextures += id => rebakeRequestsReceived++;

            // This is the alpha texture
            eyesFace.TextureID = alphaTextureID;
            afm.SetAppearance(sp, bakedTextureEntry, visualParams, null);

            Assert.That(rebakeRequestsReceived, Is.EqualTo(0));
        }
        // List<UUID> m_lastInventoryItemIDs = new List<UUID>();


        public AvatarAppearance BakeAppearance(UUID agentID, int cof_version)
        {
            AvatarAppearance appearance = m_avatarService.GetAppearance(agentID);

            if (appearance == null)
            {
                MainConsole.Instance.Error("[ServerSide appearance]: Unable to retrieve avatar appearance for bake!");
                return(new AvatarAppearance());
            }

            List <BakeType>     pendingBakes = new List <BakeType> ();
            InventoryFolderBase cof          = m_inventoryService.GetFolderForType(agentID, InventoryType.Unknown, FolderType.CurrentOutfit);

            if (cof.Version < cof_version)
            {
                int i = 0;
                while (i < 10)
                {
                    cof = m_inventoryService.GetFolderForType(agentID, InventoryType.Unknown, FolderType.CurrentOutfit);
                    System.Threading.Thread.Sleep(100);
                    if (cof.Version >= cof_version)
                    {
                        break;
                    }
                    i++;
                }
            }

            List <InventoryItemBase> items = m_inventoryService.GetFolderItems(agentID, cof.ID);

            foreach (InventoryItemBase itm in items)
            {
                MainConsole.Instance.Info("[ServerSide appearance]: Baking " + itm.Name);
            }

            for (int i = 0; i < Textures.Length; i++)
            {
                Textures [i] = new TextureData();
            }

            WearableData alphaWearable  = null;
            List <UUID>  currentItemIDs = new List <UUID> ();

            foreach (InventoryItemBase itm in items)
            {
                if (itm.AssetType == (int)AssetType.Link)
                {
                    UUID assetID = m_inventoryService.GetItemAssetID(agentID, itm.AssetID);
                    if (appearance.Wearables.Any((w) => w.GetItem(assetID) != UUID.Zero))
                    {
                        currentItemIDs.Add(assetID);
                        //if (m_lastInventoryItemIDs.Contains(assetID))
                        //    continue;
                        WearableData wearable = new WearableData();
                        AssetBase    asset    = m_assetService.Get(assetID.ToString());
                        if (asset != null && asset.TypeAsset != AssetType.Object)
                        {
                            var assetData = new byte [asset.Data.Length];
                            asset.Data.CopyTo(assetData, 0);
                            asset.Dispose();
                            wearable.Asset = new AssetClothing(assetID, assetData);
                            if (wearable.Asset.Decode())
                            {
                                wearable.AssetID      = assetID;
                                wearable.AssetType    = wearable.Asset.AssetType;
                                wearable.WearableType = wearable.Asset.WearableType;
                                wearable.ItemID       = itm.AssetID;
                                if (wearable.WearableType == WearableType.Alpha)
                                {
                                    alphaWearable = wearable;
                                    continue;
                                }
                                AppearanceManager.DecodeWearableParams(wearable, ref Textures);
                            }
                        }
                        if (asset != null)  // have asset but not an object
                        {
                            asset.Dispose();
                        }
                    }
                }
            }

            /*foreach (UUID id in m_lastInventoryItemIDs)
             * {
             *  if (!currentItemIDs.Contains(id))
             *  {
             *      OpenMetaverse.AppearanceManager.WearableData wearable = new OpenMetaverse.AppearanceManager.WearableData();
             *      AssetBase asset = m_assetService.Get(id.ToString());
             *      if (asset != null && asset.TypeAsset != AssetType.Object)
             *      {
             *          wearable.Asset = new AssetClothing(id, asset.Data);
             *          if (wearable.Asset.Decode())
             *          {
             *              foreach (KeyValuePair<AvatarTextureIndex, UUID> entry in wearable.Asset.Textures)
             *              {
             *                  int i = (int)entry.Key;
             *
             *                  Textures[i].Texture = null;
             *                  Textures[i].TextureID = UUID.Zero;
             *              }
             *          }
             *      }
             *  }
             * }*/
            //m_lastInventoryItemIDs = currentItemIDs;
            for (int i = 0; i < Textures.Length; i++)
            {
                /*if (Textures[i].TextureID == UUID.Zero)
                 *  continue;
                 * if (Textures[i].Texture != null)
                 *  continue;*/
                AssetBase asset = m_assetService.Get(Textures [i].TextureID.ToString());
                if (asset != null)
                {
                    var assetData = new byte [asset.Data.Length];
                    asset.Data.CopyTo(assetData, 0);
                    asset.Dispose();
                    Textures [i].Texture = new AssetTexture(Textures [i].TextureID, assetData);
                    Textures [i].Texture.Decode();
                }
            }

            for (int bakedIndex = 0; bakedIndex < AppearanceManager.BAKED_TEXTURE_COUNT; bakedIndex++)
            {
                AvatarTextureIndex textureIndex = AppearanceManager.BakeTypeToAgentTextureIndex((BakeType)bakedIndex);

                if (Textures [(int)textureIndex].TextureID == UUID.Zero)
                {
                    // If this is the skirt layer and we're not wearing a skirt then skip it
                    if (bakedIndex == (int)BakeType.Skirt && appearance.Wearables [(int)WearableType.Skirt].Count == 0)
                    {
                        continue;
                    }

                    pendingBakes.Add((BakeType)bakedIndex);
                }
            }

            int         start      = Environment.TickCount;
            List <UUID> newBakeIDs = new List <UUID> ();

            foreach (BakeType bakeType in pendingBakes)
            {
                UUID assetID = UUID.Zero;
                List <AvatarTextureIndex> textureIndices = AppearanceManager.BakeTypeToTextures(bakeType);
                Baker oven = new Baker(bakeType);

                for (int i = 0; i < textureIndices.Count; i++)
                {
                    int         textureIndex = (int)textureIndices [i];
                    TextureData texture      = Textures [textureIndex];
                    texture.TextureIndex = (AvatarTextureIndex)textureIndex;
                    if (alphaWearable != null)
                    {
                        if (alphaWearable.Asset.Textures.ContainsKey(texture.TextureIndex) &&
                            alphaWearable.Asset.Textures [texture.TextureIndex] != UUID.Parse("5748decc-f629-461c-9a36-a35a221fe21f"))
                        {
                            assetID = alphaWearable.Asset.Textures [texture.TextureIndex];
                            goto bake_complete;
                        }
                    }

                    oven.AddTexture(texture);
                }

                oven.Bake();
                byte []   assetData     = oven.BakedTexture.AssetData;
                AssetBase newBakedAsset = new AssetBase(UUID.Random());
                newBakedAsset.Data      = assetData;
                newBakedAsset.TypeAsset = AssetType.Texture;
                newBakedAsset.Name      = "ServerSideAppearance Texture";
                newBakedAsset.Flags     = AssetFlags.Deletable | AssetFlags.Collectable | AssetFlags.Rewritable | AssetFlags.Temporary;

                var faceTextureID = appearance.Texture.FaceTextures [(int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType)].TextureID;
                if (faceTextureID != UUID.Zero)
                {
                    try {
                        m_assetService.Delete(faceTextureID);
                    } catch {
                        MainConsole.Instance.ErrorFormat("[Serverside apperance]: Unable to delete asset {0} during bake", faceTextureID);
                    }
                }
                assetID = m_assetService.Store(newBakedAsset);
bake_complete:
                newBakeIDs.Add(assetID);
                MainConsole.Instance.WarnFormat("[ServerSide appearance]: Baked {0}", assetID);
                int place = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
                appearance.Texture.FaceTextures [place].TextureID = assetID;
            }

            MainConsole.Instance.ErrorFormat("[ServerSide appearance]: Baking took {0} ms", (Environment.TickCount - start));

            appearance.Serial = cof_version + 1;
            cof = m_inventoryService.GetFolderForType(agentID, InventoryType.Unknown, FolderType.CurrentOutfit);
            if (cof.Version > cof_version)
            {
                //it changed during the baking... kill it with fire!
                return(null);
            }
            m_avatarService.SetAppearance(agentID, appearance);
            return(appearance);
        }