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); }