public AvatarAppearance BakeAppearance(UUID agentID, int cof_version) { AvatarAppearance appearance = m_avatarService.GetAppearance(agentID); List<BakeType> pendingBakes = new List<BakeType>(); InventoryFolderBase cof = m_inventoryService.GetFolderForType(agentID, InventoryType.Unknown, AssetType.CurrentOutfitFolder); if (cof.Version < cof_version) { int i = 0; while (i < 10) { cof = m_inventoryService.GetFolderForType(agentID, InventoryType.Unknown, AssetType.CurrentOutfitFolder); 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.Warn("[ServerSideAppearance]: 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) { wearable.Asset = new AssetClothing(assetID, asset.Data); 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); } } } else { } } } /*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) { Textures[i].Texture = new AssetTexture(Textures[i].TextureID, asset.Data); 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 = OpenMetaverse.AppearanceManager.BakeTypeToTextures(bakeType); Baker oven = new Baker(bakeType); for (int i = 0; i < textureIndices.Count; i++) { int textureIndex = (int)textureIndices[i]; TextureData texture = Textures[(int)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; if (appearance.Texture.FaceTextures[(int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType)].TextureID != UUID.Zero) m_assetService.Delete(appearance.Texture.FaceTextures[(int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType)].TextureID); assetID = m_assetService.Store(newBakedAsset); bake_complete: newBakeIDs.Add(assetID); MainConsole.Instance.WarnFormat("[ServerSideAppearance]: Baked {0}", assetID); int place = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); appearance.Texture.FaceTextures[place].TextureID = assetID; } MainConsole.Instance.ErrorFormat("[ServerSideAppearance]: Baking took {0} ms", (Environment.TickCount - start)); appearance.Serial = cof_version + 1; cof = m_inventoryService.GetFolderForType(agentID, InventoryType.Unknown, AssetType.CurrentOutfitFolder); if (cof.Version > cof_version) { //it changed during the baking... kill it with fire! return null; } m_avatarService.SetAppearance(agentID, appearance); return appearance; }
/// <summary> /// Blocking method to create and upload a baked texture for a single /// bake layer /// </summary> /// <param name="bakeType">Layer to bake</param> /// <returns>True on success, otherwise false</returns> private bool CreateBake(BakeType bakeType) { List<AvatarTextureIndex> textureIndices = BakeTypeToTextures(bakeType); Baker oven = new Baker(bakeType); for (int i = 0; i < textureIndices.Count; i++) { AvatarTextureIndex textureIndex = textureIndices[i]; TextureData texture = Textures[(int)textureIndex]; texture.TextureIndex = textureIndex; oven.AddTexture(texture); } int start = Environment.TickCount; oven.Bake(); Logger.DebugLog("Baking " + bakeType + " took " + (Environment.TickCount - start) + "ms"); UUID newAssetID = UUID.Zero; int retries = UPLOAD_RETRIES; while (newAssetID == UUID.Zero && retries > 0) { newAssetID = UploadBake(oven.BakedTexture.AssetData); --retries; } Textures[(int)BakeTypeToAgentTextureIndex(bakeType)].TextureID = newAssetID; if (newAssetID == UUID.Zero) { Logger.Log("Failed uploading bake " + bakeType, Helpers.LogLevel.Warning); return false; } return true; }
private void UploadBake(Baker bake) { lock (PendingUploads) { if(PendingUploads.ContainsKey(bake.BakedTexture.AssetID)) { Log.Log("UploadBake(): Skipping Asset id "+bake.BakedTexture.AssetID.ToString()+" Already in progress",Helpers.LogLevel.Info); return; } // Upload the completed layer data and Add it to a pending uploads list UUID id=Assets.RequestUpload(bake.BakedTexture, true); PendingUploads.Add(UUID.Combine(id, Network.SecureSessionID), BakeTypeToAgentTextureIndex(bake.BakeType)); } Log.DebugLog(String.Format("Bake {0} completed. Uploading asset {1}", bake.BakeType, bake.BakedTexture.AssetID.ToString())); }
private void AgentCachedTextureResponseHandler(Packet packet, Simulator simulator) { Log.DebugLog("AgentCachedTextureResponseHandler()"); AgentCachedTextureResponsePacket response = (AgentCachedTextureResponsePacket)packet; lock (AgentTextures) { //If we are here then the user has tried to wear stuff or we are at login // In either case the existing uploads of this class are very shortly going to be no good PendingUploads.Clear(); foreach (AgentCachedTextureResponsePacket.WearableDataBlock block in response.WearableData) { //UUID hash=new UUID(); // For each missing element we need to bake our own texture Log.DebugLog("Cache response, index: " + block.TextureIndex + ", ID: " + block.TextureID.ToString()); // FIXME: Use this. Right now we treat baked images on other sims as if they were missing string host = Utils.BytesToString(block.HostName); if (host.Length > 0) Log.DebugLog("Cached bake exists on foreign host " + host); BakeType bakeType = (BakeType)block.TextureIndex; // Note, still should handle block.TextureID != UUID.Zero && host.Length == 0 // Not sure what we should do as yet with that. // Convert the baked index to an AgentTexture index if (block.TextureID != UUID.Zero && host.Length != 0) { TextureIndex index = BakeTypeToAgentTextureIndex(bakeType); AgentTextures[(int)index] = block.TextureID; AddImagesToDownload(bakeType); // We need to do this bit regardless for rebaking purposes later } else { int imageCount=AddImagesToDownload(bakeType); if (!PendingBakes.ContainsKey(bakeType)) { Log.DebugLog("Initializing " + bakeType.ToString() + " bake with " + imageCount + " textures"); Dictionary<int, float> paramValues=MakeParamValues(); // Build a dictionary of appearance parameter indices and values from the wearables if (imageCount == 0) { // if there are no textures to download, we can bake right away and start the upload Baker bake = new Baker(Log, bakeType, 0, paramValues); UploadBake(bake); } else { lock (PendingBakes) { Baker bake=new Baker(Log, bakeType, imageCount,paramValues); PendingBakes.Add(bakeType,bake); } } } else if (!PendingBakes.ContainsKey(bakeType)) { Log.Log("No cached bake for " + bakeType.ToString() + " and no textures for that " + "layer, this is an unhandled case", Helpers.LogLevel.Error); } } } } if (ImageDownloads.Count > 0) { lock (ImageDownloads) { List<UUID> imgKeys = new List<UUID>(ImageDownloads.Keys); foreach (UUID image in imgKeys) { // Download all the images we need for baking Assets.RequestImage(image, ImageType.Normal, Assets_OnImageReceived); } } } else { CachedResponseEvent.Set(); } }
private void RebakeLayer(BakeType bakeType) { Dictionary<int, float> paramValues; // Build a dictionary of appearance parameter indices and values from the wearables paramValues=MakeParamValues(); Baker bake = new Baker(Log, bakeType, 0, paramValues); for (int ii = 0; ii < AVATAR_TEXTURE_COUNT; ii++) { if(bakeType==Baker.BakeTypeFor((TextureIndex)ii) && AgentAssets[ii]!=null) { Log.Log("Adding asset "+AgentAssets[ii].AssetID.ToString()+" to baker",Helpers.LogLevel.Debug); bake.AddTexture((TextureIndex)ii,(AssetTexture)AgentAssets[ii],true); } } UploadBake(bake); }
private void pic_MouseClick(object sender, MouseEventArgs e) { PictureBox control = (PictureBox)sender; OpenFileDialog dialog = new OpenFileDialog(); // TODO: Setup a dialog.Filter for supported image types if (dialog.ShowDialog() == DialogResult.OK) { try { System.Drawing.Image image = System.Drawing.Image.FromFile(dialog.FileName); #region Dimensions Check if (control == picEyesBake) { // Eyes texture is 128x128 if (Width != 128 || Height != 128) { Bitmap resized = new Bitmap(128, 128, image.PixelFormat); Graphics graphics = Graphics.FromImage(resized); graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; graphics.DrawImage(image, 0, 0, 128, 128); image.Dispose(); image = resized; } } else { // Other textures are 512x512 if (Width != 128 || Height != 128) { Bitmap resized = new Bitmap(512, 512, image.PixelFormat); Graphics graphics = Graphics.FromImage(resized); graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; graphics.DrawImage(image, 0, 0, 512, 512); image.Dispose(); image = resized; } } #endregion Dimensions Check // Set the control image control.Image = image; } catch (Exception ex) { MessageBox.Show("Failed to load image: " + ex.Message); } } else { control.Image = null; } #region Baking Dictionary<int, float> paramValues = GetParamValues(); Dictionary<AppearanceManager.TextureIndex, AssetTexture> layers = new Dictionary<AppearanceManager.TextureIndex, AssetTexture>(); int textureCount = 0; if ((string)control.Tag == "Head") { if (picHair.Image != null) { layers.Add(AppearanceManager.TextureIndex.Hair, new AssetTexture(new ManagedImage((Bitmap)picHair.Image))); ++textureCount; } if (picHeadBodypaint.Image != null) { layers.Add(AppearanceManager.TextureIndex.HeadBodypaint, new AssetTexture(new ManagedImage((Bitmap)picHeadBodypaint.Image))); ++textureCount; } // Compute the head bake Baker baker = new Baker( _client, AppearanceManager.BakeType.Head, textureCount, paramValues); foreach (KeyValuePair<AppearanceManager.TextureIndex, AssetTexture> kvp in layers) baker.AddTexture(kvp.Key, kvp.Value, false); if (baker.BakedTexture != null) { AssetTexture bakeAsset = baker.BakedTexture; // Baked textures use the alpha layer for other purposes, so we need to not use it bakeAsset.Image.Channels = ManagedImage.ImageChannels.Color; picHeadBake.Image = LoadTGAClass.LoadTGA(new MemoryStream(bakeAsset.Image.ExportTGA())); } else { MessageBox.Show("Failed to create the bake layer, unknown error"); } } else if ((string)control.Tag == "Upper") { if (picUpperBodypaint.Image != null) { layers.Add(AppearanceManager.TextureIndex.UpperBodypaint, new AssetTexture(new ManagedImage((Bitmap)picUpperBodypaint.Image))); ++textureCount; } if (picUpperGloves.Image != null) { layers.Add(AppearanceManager.TextureIndex.UpperGloves, new AssetTexture(new ManagedImage((Bitmap)picUpperGloves.Image))); ++textureCount; } if (picUpperUndershirt.Image != null) { layers.Add(AppearanceManager.TextureIndex.UpperUndershirt, new AssetTexture(new ManagedImage((Bitmap)picUpperUndershirt.Image))); ++textureCount; } if (picUpperShirt.Image != null) { layers.Add(AppearanceManager.TextureIndex.UpperShirt, new AssetTexture(new ManagedImage((Bitmap)picUpperShirt.Image))); ++textureCount; } if (picUpperJacket.Image != null) { layers.Add(AppearanceManager.TextureIndex.UpperJacket, new AssetTexture(new ManagedImage((Bitmap)picUpperJacket.Image))); ++textureCount; } // Compute the upper body bake Baker baker = new Baker( _client, AppearanceManager.BakeType.UpperBody, textureCount, paramValues); foreach (KeyValuePair<AppearanceManager.TextureIndex, AssetTexture> kvp in layers) baker.AddTexture(kvp.Key, kvp.Value, false); if (baker.BakedTexture != null) { AssetTexture bakeAsset = baker.BakedTexture; // Baked textures use the alpha layer for other purposes, so we need to not use it bakeAsset.Image.Channels = ManagedImage.ImageChannels.Color; picUpperBodyBake.Image = LoadTGAClass.LoadTGA(new MemoryStream(bakeAsset.Image.ExportTGA())); } else { MessageBox.Show("Failed to create the bake layer, unknown error"); } } else if ((string)control.Tag == "Lower") { if (picLowerBodypaint.Image != null) { layers.Add(AppearanceManager.TextureIndex.LowerBodypaint, new AssetTexture(new ManagedImage((Bitmap)picLowerBodypaint.Image))); ++textureCount; } if (picLowerUnderpants.Image != null) { layers.Add(AppearanceManager.TextureIndex.LowerUnderpants, new AssetTexture(new ManagedImage((Bitmap)picLowerUnderpants.Image))); ++textureCount; } if (picLowerSocks.Image != null) { layers.Add(AppearanceManager.TextureIndex.LowerSocks, new AssetTexture(new ManagedImage((Bitmap)picLowerSocks.Image))); ++textureCount; } if (picLowerShoes.Image != null) { layers.Add(AppearanceManager.TextureIndex.LowerShoes, new AssetTexture(new ManagedImage((Bitmap)picLowerShoes.Image))); ++textureCount; } if (picLowerPants.Image != null) { layers.Add(AppearanceManager.TextureIndex.LowerPants, new AssetTexture(new ManagedImage((Bitmap)picLowerPants.Image))); ++textureCount; } // Compute the lower body bake Baker baker = new Baker( _client, AppearanceManager.BakeType.LowerBody, textureCount, paramValues); foreach (KeyValuePair<AppearanceManager.TextureIndex, AssetTexture> kvp in layers) baker.AddTexture(kvp.Key, kvp.Value, false); if (baker.BakedTexture != null) { AssetTexture bakeAsset = baker.BakedTexture; // Baked textures use the alpha layer for other purposes, so we need to not use it bakeAsset.Image.Channels = ManagedImage.ImageChannels.Color; picLowerBodyBake.Image = LoadTGAClass.LoadTGA(new MemoryStream(bakeAsset.Image.ExportTGA())); } else { MessageBox.Show("Failed to create the bake layer, unknown error"); } } else if ((string)control.Tag == "Bake") { // Bake image has been set manually, no need to manually calculate a bake // FIXME: } #endregion Baking }
private void AgentCachedTextureResponseHandler(Packet packet, Simulator simulator) { Logger.DebugLog("AgentCachedTextureResponseHandler()", Client); AgentCachedTextureResponsePacket response = (AgentCachedTextureResponsePacket)packet; Dictionary<int, float> paramValues = new Dictionary<int, float>(VisualParams.Params.Count); // Build a dictionary of appearance parameter indices and values from the wearables foreach (KeyValuePair<int,VisualParam> kvp in VisualParams.Params) { // Only Group-0 parameters are sent in AgentSetAppearance packets if (kvp.Value.Group == 0) { bool found = false; VisualParam vp = kvp.Value; // Try and find this value in our collection of downloaded wearables foreach (WearableData data in Wearables.Dictionary.Values) { if (data.Asset.Params.ContainsKey(vp.ParamID)) { paramValues.Add(vp.ParamID, data.Asset.Params[vp.ParamID]); found = true; break; } } // Use a default value if we don't have one set for it if (!found) paramValues.Add(vp.ParamID, vp.DefaultValue); } } lock (AgentTextures) { foreach (AgentCachedTextureResponsePacket.WearableDataBlock block in response.WearableData) { // For each missing element we need to bake our own texture Logger.DebugLog("Cache response, index: " + block.TextureIndex + ", ID: " + block.TextureID.ToString(), Client); // FIXME: Use this. Right now we treat baked images on other sims as if they were missing string host = Utils.BytesToString(block.HostName); if (host.Length > 0) Logger.DebugLog("Cached bake exists on foreign host " + host, Client); BakeType bakeType = (BakeType)block.TextureIndex; // Convert the baked index to an AgentTexture index if (block.TextureID != Guid.Empty && host.Length == 0) { TextureIndex index = BakeTypeToAgentTextureIndex(bakeType); AgentTextures[(int)index] = block.TextureID; } else { int imageCount = 0; // Download all of the images in this layer switch (bakeType) { case BakeType.Head: lock (ImageDownloads) { imageCount += AddImageDownload(TextureIndex.HeadBodypaint); //imageCount += AddImageDownload(TextureIndex.Hair); } break; case BakeType.UpperBody: lock (ImageDownloads) { imageCount += AddImageDownload(TextureIndex.UpperBodypaint); imageCount += AddImageDownload(TextureIndex.UpperGloves); imageCount += AddImageDownload(TextureIndex.UpperUndershirt); imageCount += AddImageDownload(TextureIndex.UpperShirt); imageCount += AddImageDownload(TextureIndex.UpperJacket); } break; case BakeType.LowerBody: lock (ImageDownloads) { imageCount += AddImageDownload(TextureIndex.LowerBodypaint); imageCount += AddImageDownload(TextureIndex.LowerUnderpants); imageCount += AddImageDownload(TextureIndex.LowerSocks); imageCount += AddImageDownload(TextureIndex.LowerShoes); imageCount += AddImageDownload(TextureIndex.LowerPants); imageCount += AddImageDownload(TextureIndex.LowerJacket); } break; case BakeType.Eyes: lock (ImageDownloads) { imageCount += AddImageDownload(TextureIndex.EyesIris); } break; case BakeType.Skirt: if (Wearables.ContainsKey(WearableType.Skirt)) { lock (ImageDownloads) { imageCount += AddImageDownload(TextureIndex.Skirt); } } break; default: Logger.Log("Unknown BakeType " + block.TextureIndex, Helpers.LogLevel.Warning, Client); break; } if (!PendingBakes.ContainsKey(bakeType)) { Logger.DebugLog("Initializing " + bakeType.ToString() + " bake with " + imageCount + " textures", Client); if (imageCount == 0) { // if there are no textures to download, we can bake right away and start the upload Baker bake = new Baker(Client, bakeType, 0, paramValues); UploadBake(bake); } else { lock (PendingBakes) PendingBakes.Add(bakeType, new Baker(Client, bakeType, imageCount, paramValues)); } } else if (!PendingBakes.ContainsKey(bakeType)) { Logger.Log("No cached bake for " + bakeType.ToString() + " and no textures for that " + "layer, this is an unhandled case", Helpers.LogLevel.Error, Client); } } } } if (ImageDownloads.Count == 0) { // No pending downloads for baking, we're done CachedResponseEvent.Set(); } else { lock (ImageDownloads) { List<Guid> imgKeys = new List<Guid>(ImageDownloads.Keys); foreach (Guid image in imgKeys) { // Download all the images we need for baking Assets.RequestImage(image, ImageType.Normal, 1013000.0f, 0, 0); } } } }
private void UploadBake(Baker bake) { // Upload the completed layer data Assets.RequestUpload(bake.BakedTexture, true); Logger.DebugLog(String.Format("Bake {0} completed. Uploading asset {1}", bake.BakeType, bake.BakedTexture.AssetID.ToString()), Client); // Add it to a pending uploads list lock (PendingUploads) PendingUploads.Add(bake.BakedTexture.AssetID, BakeTypeToAgentTextureIndex(bake.BakeType)); }
public byte[] UpdateAvatarAppearance(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { try { OSDMap rm = (OSDMap) OSDParser.DeserializeLLSDXml(request); int cof_version = rm["cof_version"].AsInteger(); bool success = false; string error = ""; AvatarAppearance appearance = m_avatarService.GetAppearance(m_agentID); List<BakeType> pendingBakes = new List<BakeType>(); List<InventoryItemBase> items = m_inventoryService.GetFolderItems(m_agentID, m_inventoryService.GetFolderForType(m_agentID, InventoryType.Unknown, AssetType.CurrentOutfitFolder).ID); foreach (InventoryItemBase itm in items) MainConsole.Instance.Warn("[SSB]: Baking " + itm.Name); //for (int i = 0; i < Textures.Length; i++) // Textures[i] = new AppearanceManager.TextureData(); List<UUID> currentItemIDs = new List<UUID>(); foreach (InventoryItemBase itm in items) { if (itm.AssetType == (int)AssetType.Link) { UUID assetID = m_inventoryService.GetItemAssetID(m_agentID, itm.AssetID); currentItemIDs.Add(assetID); if (m_lastInventoryItemIDs.Contains(assetID)) continue; OpenMetaverse.AppearanceManager.WearableData wearable = new OpenMetaverse.AppearanceManager.WearableData(); AssetBase asset = m_assetService.Get(assetID.ToString()); if (asset != null && asset.TypeAsset != AssetType.Object) { wearable.Asset = new AssetClothing(assetID, asset.Data); if (wearable.Asset.Decode()) { wearable.AssetID = assetID; wearable.AssetType = wearable.Asset.AssetType; wearable.WearableType = wearable.Asset.WearableType; wearable.ItemID = itm.AssetID; DecodeWearableParams(wearable); } } } } m_lastInventoryItemIDs = currentItemIDs; for (int i = 0; i < Textures.Length; i++) { if (Textures[i].TextureID == UUID.Zero) continue; AssetBase asset = m_assetService.Get(Textures[i].TextureID.ToString()); if (asset != null) { Textures[i].Texture = new AssetTexture(Textures[i].TextureID, asset.Data); 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) { List<AvatarTextureIndex> textureIndices = OpenMetaverse.AppearanceManager.BakeTypeToTextures(bakeType); Baker oven = new Baker(bakeType); for (int i = 0; i < textureIndices.Count; i++) { int textureIndex = (int)textureIndices[i]; OpenMetaverse.AppearanceManager.TextureData texture = Textures[(int)textureIndex]; texture.TextureIndex = (AvatarTextureIndex)textureIndex; 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 = "SSB Texture"; newBakedAsset.Flags = AssetFlags.Deletable | AssetFlags.Collectable | AssetFlags.Rewritable | AssetFlags.Temporary; if (appearance.Texture.FaceTextures[(int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType)].TextureID != UUID.Zero) m_assetService.Delete(appearance.Texture.FaceTextures[(int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType)].TextureID); UUID assetID = m_assetService.Store(newBakedAsset); newBakeIDs.Add(assetID); MainConsole.Instance.WarnFormat("[SSB]: Baked {0}", assetID); int place = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); appearance.Texture.FaceTextures[place].TextureID = assetID; } MainConsole.Instance.ErrorFormat("[SSB]: Baking took {0} ms", (Environment.TickCount - start)); appearance.Serial = cof_version+1; m_avatarService.SetAppearance(m_agentID, appearance); OSDMap uaamap = new OSDMap(); uaamap["Method"] = "UpdateAvatarAppearance"; uaamap["AgentID"] = m_agentID; uaamap["Appearance"] = appearance.ToOSD(); m_syncMessage.Post(m_region.ServerURI, uaamap); success = true; OSDMap map = new OSDMap(); map["success"] = success; map["error"] = error; map["agent_id"] = m_agentID; /*map["avatar_scale"] = appearance.AvatarHeight; map["textures"] = newBakeIDs.ToOSDArray(); OSDArray visualParams = new OSDArray(); foreach(byte b in appearance.VisualParams) visualParams.Add((int)b); map["visual_params"] = visualParams;*/ return OSDParser.SerializeLLSDXmlBytes(map); } catch (Exception e) { MainConsole.Instance.Error("[CAPS]: " + e); } return null; }