/// <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 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<AvatarTextureIndex, AssetTexture> layers = new Dictionary<AvatarTextureIndex, AssetTexture>(); int textureCount = 0; if ((string)control.Tag == "Head") { if (picHair.Image != null) { layers.Add(AvatarTextureIndex.Hair, new AssetTexture(new ManagedImage((Bitmap)picHair.Image))); ++textureCount; } if (picHeadBodypaint.Image != null) { layers.Add(AvatarTextureIndex.HeadBodypaint, new AssetTexture(new ManagedImage((Bitmap)picHeadBodypaint.Image))); ++textureCount; } // Compute the head bake Baker baker = new Baker(BakeType.Head); foreach (KeyValuePair<AvatarTextureIndex, AssetTexture> kvp in layers) { AppearanceManager.TextureData tdata = new AppearanceManager.TextureData(); tdata.Texture = kvp.Value; baker.AddTexture(tdata); } baker.Bake(); 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(AvatarTextureIndex.UpperBodypaint, new AssetTexture(new ManagedImage((Bitmap)picUpperBodypaint.Image))); ++textureCount; } if (picUpperGloves.Image != null) { layers.Add(AvatarTextureIndex.UpperGloves, new AssetTexture(new ManagedImage((Bitmap)picUpperGloves.Image))); ++textureCount; } if (picUpperUndershirt.Image != null) { layers.Add(AvatarTextureIndex.UpperUndershirt, new AssetTexture(new ManagedImage((Bitmap)picUpperUndershirt.Image))); ++textureCount; } if (picUpperShirt.Image != null) { layers.Add(AvatarTextureIndex.UpperShirt, new AssetTexture(new ManagedImage((Bitmap)picUpperShirt.Image))); ++textureCount; } if (picUpperJacket.Image != null) { layers.Add(AvatarTextureIndex.UpperJacket, new AssetTexture(new ManagedImage((Bitmap)picUpperJacket.Image))); ++textureCount; } // Compute the upper body bake Baker baker = new Baker(BakeType.UpperBody); foreach (KeyValuePair<AvatarTextureIndex, AssetTexture> kvp in layers) { AppearanceManager.TextureData tdata = new AppearanceManager.TextureData(); tdata.Texture = kvp.Value; baker.AddTexture(tdata); } baker.Bake(); 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(AvatarTextureIndex.LowerBodypaint, new AssetTexture(new ManagedImage((Bitmap)picLowerBodypaint.Image))); ++textureCount; } if (picLowerUnderpants.Image != null) { layers.Add(AvatarTextureIndex.LowerUnderpants, new AssetTexture(new ManagedImage((Bitmap)picLowerUnderpants.Image))); ++textureCount; } if (picLowerSocks.Image != null) { layers.Add(AvatarTextureIndex.LowerSocks, new AssetTexture(new ManagedImage((Bitmap)picLowerSocks.Image))); ++textureCount; } if (picLowerShoes.Image != null) { layers.Add(AvatarTextureIndex.LowerShoes, new AssetTexture(new ManagedImage((Bitmap)picLowerShoes.Image))); ++textureCount; } if (picLowerPants.Image != null) { layers.Add(AvatarTextureIndex.LowerPants, new AssetTexture(new ManagedImage((Bitmap)picLowerPants.Image))); ++textureCount; } // Compute the lower body bake Baker baker = new Baker(BakeType.LowerBody); foreach (KeyValuePair<AvatarTextureIndex, AssetTexture> kvp in layers) { AppearanceManager.TextureData tdata = new AppearanceManager.TextureData(); tdata.Texture = kvp.Value; baker.AddTexture(tdata); } baker.Bake(); 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 }
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; }
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; }