public AvatarAppearance(WearableData wearableData) : base() // Note: indra has a protected constructor since it subclasses this in VOAvatar { IsDummy = false; TexSkinColor = null; //TODO: Not implemented TexHairColor = null; //TODO: Not implemented TexEyeColor = null; //TODO: Not implemented PelvisToFoot = 0f; HeadOffset = Vector3.zero; Root = null; WearableData = wearableData; NumBones = 0; NumCollisionVolumes = 0; IsBuilt = false; InitFlags = 0; if (WearableData == null) { throw new Exception("AvatarAppearance.constructor: Can't create an avatar with a null wearableData."); } for (int i = 0; i < (int)AvatarAppearanceDictionary.BakedTextureIndex.NumIndices; i++) { BakedTextureDatas.Add(new BakedTextureData() { LastTextureID = IndraConstants.IMG_DEFAULT_AVATAR, TexLayerSet = null, IsLoaded = false, IsUsed = false, MaskTexName = 0, TextureIndex = AvatarAppearanceDictionary.BakedToLocalTextureIndex((AvatarAppearanceDictionary.BakedTextureIndex)i) }); } }
/// <summary> /// Replaces the Wearables collection with a list of new wearable items /// </summary> /// <param name="wearableItems">Wearable items to replace the Wearables collection with</param> private void ReplaceOutfit(List<InventoryWearable> wearableItems) { Dictionary<WearableType, WearableData> newWearables = new Dictionary<WearableType, WearableData>(); lock (Wearables) { // Preserve body parts from the previous set of wearables. They may be overwritten, // but cannot be missing in the new set foreach (KeyValuePair<WearableType, WearableData> entry in Wearables) { if (entry.Value.AssetType == AssetType.Bodypart) newWearables[entry.Key] = entry.Value; } // Add the given wearables to the new wearables collection for (int i = 0; i < wearableItems.Count; i++) { InventoryWearable wearableItem = wearableItems[i]; WearableData wd = new WearableData(); wd.AssetID = wearableItem.AssetUUID; wd.AssetType = wearableItem.AssetType; wd.ItemID = wearableItem.UUID; wd.WearableType = wearableItem.WearableType; newWearables[wearableItem.WearableType] = wd; } // Replace the Wearables collection Wearables = newWearables; } }
/// <summary> /// Add a list of wearables to the current outfit and set appearance /// </summary> /// <param name="wearableItems">List of wearable inventory items to /// be added to the outfit</param> public void AddToOutfit(List<InventoryItem> wearableItems) { List<InventoryWearable> wearables = new List<InventoryWearable>(); List<InventoryItem> attachments = new List<InventoryItem>(); for (int i = 0; i < wearableItems.Count; i++) { InventoryItem item = wearableItems[i]; if (item is InventoryWearable) wearables.Add((InventoryWearable)item); else if (item is InventoryAttachment || item is InventoryObject) attachments.Add(item); } lock (Wearables) { // Add the given wearables to the wearables collection for (int i = 0; i < wearables.Count; i++) { InventoryWearable wearableItem = wearables[i]; WearableData wd = new WearableData(); wd.AssetID = wearableItem.AssetUUID; wd.AssetType = wearableItem.AssetType; wd.ItemID = wearableItem.UUID; wd.WearableType = wearableItem.WearableType; Wearables[wearableItem.WearableType] = wd; } } if (attachments.Count > 0) { AddAttachments(attachments, false, false); } if (wearables.Count > 0) { SendAgentIsNowWearing(); DelayedRequestSetAppearance(); } }
/// <summary> /// Populates textures and visual params from a decoded asset /// </summary> /// <param name="wearable">Wearable to decode</param> private void DecodeWearableParams(WearableData wearable) { Dictionary<VisualAlphaParam, float> alphaMasks = new Dictionary<VisualAlphaParam, float>(); List<ColorParamInfo> colorParams = new List<ColorParamInfo>(); // Populate collection of alpha masks from visual params // also add color tinting information foreach (KeyValuePair<int, float> kvp in wearable.Asset.Params) { if (!VisualParams.Params.ContainsKey(kvp.Key)) continue; VisualParam p = VisualParams.Params[kvp.Key]; ColorParamInfo colorInfo = new ColorParamInfo(); colorInfo.WearableType = wearable.WearableType; colorInfo.VisualParam = p; colorInfo.Value = kvp.Value; // Color params if (p.ColorParams.HasValue) { colorInfo.VisualColorParam = p.ColorParams.Value; // If this is not skin, just add params directly if (wearable.WearableType != WearableType.Skin) { colorParams.Add(colorInfo); } else { // For skin we skip makeup params for now and use only the 3 // that are used to determine base skin tone // Param 108 - Rainbow Color // Param 110 - Red Skin (Ruddiness) // Param 111 - Pigment if (kvp.Key == 108 || kvp.Key == 110 || kvp.Key == 111) { colorParams.Add(colorInfo); } } } // Add alpha mask if (p.AlphaParams.HasValue && p.AlphaParams.Value.TGAFile != string.Empty && !p.IsBumpAttribute && !alphaMasks.ContainsKey(p.AlphaParams.Value)) { alphaMasks.Add(p.AlphaParams.Value, kvp.Value); } // Alhpa masks can also be specified in sub "driver" params if (p.Drivers != null) { for (int i = 0; i < p.Drivers.Length; i++) { if (VisualParams.Params.ContainsKey(p.Drivers[i])) { VisualParam driver = VisualParams.Params[p.Drivers[i]]; if (driver.AlphaParams.HasValue && driver.AlphaParams.Value.TGAFile != string.Empty && !driver.IsBumpAttribute && !alphaMasks.ContainsKey(driver.AlphaParams.Value)) { alphaMasks.Add(driver.AlphaParams.Value, kvp.Value); } } } } } Color4 wearableColor = Color4.White; // Never actually used if (colorParams.Count > 0) { wearableColor = GetColorFromParams(colorParams); Logger.DebugLog("Setting tint " + wearableColor + " for " + wearable.WearableType); } // Loop through all of the texture IDs in this decoded asset and put them in our cache of worn textures foreach (KeyValuePair<AvatarTextureIndex, UUID> entry in wearable.Asset.Textures) { int i = (int)entry.Key; // Update information about color and alpha masks for this texture Textures[i].AlphaMasks = alphaMasks; Textures[i].Color = wearableColor; // If this texture changed, update the TextureID and clear out the old cached texture asset if (Textures[i].TextureID != entry.Value) { // Treat DEFAULT_AVATAR_TEXTURE as null if (entry.Value != DEFAULT_AVATAR_TEXTURE) Textures[i].TextureID = entry.Value; else Textures[i].TextureID = UUID.Zero; Logger.DebugLog("Set " + entry.Key + " to " + Textures[i].TextureID, Client); Textures[i].Texture = null; } } }
protected void AgentWearablesUpdateHandler(object sender, PacketReceivedEventArgs e) { bool changed = false; AgentWearablesUpdatePacket update = (AgentWearablesUpdatePacket)e.Packet; lock (Wearables) { #region Test if anything changed in this update for (int i = 0; i < update.WearableData.Length; i++) { AgentWearablesUpdatePacket.WearableDataBlock block = update.WearableData[i]; if (block.AssetID != UUID.Zero) { WearableData wearable; if (Wearables.TryGetValue((WearableType)block.WearableType, out wearable)) { if (wearable.AssetID != block.AssetID || wearable.ItemID != block.ItemID) { // A different wearable is now set for this index changed = true; break; } } else { // A wearable is now set for this index changed = true; break; } } else if (Wearables.ContainsKey((WearableType)block.WearableType)) { // This index is now empty changed = true; break; } } #endregion Test if anything changed in this update if (changed) { Logger.DebugLog("New wearables received in AgentWearablesUpdate"); Wearables.Clear(); for (int i = 0; i < update.WearableData.Length; i++) { AgentWearablesUpdatePacket.WearableDataBlock block = update.WearableData[i]; if (block.AssetID != UUID.Zero) { WearableType type = (WearableType)block.WearableType; WearableData data = new WearableData(); data.Asset = null; data.AssetID = block.AssetID; data.AssetType = WearableTypeToAssetType(type); data.ItemID = block.ItemID; data.WearableType = type; // Add this wearable to our collection Wearables[type] = data; } } } else { Logger.DebugLog("Duplicate AgentWearablesUpdate received, discarding"); } } if (changed) { // Fire the callback OnAgentWearables(new AgentWearablesReplyEventArgs()); } }
private void AgentWearablesUpdateHandler(Packet packet, Simulator simulator) { // Lock to prevent a race condition with multiple AgentWearables packets lock (WearablesRequestEvent) { AgentWearablesUpdatePacket update = (AgentWearablesUpdatePacket)packet; // Reset the Wearables collection lock (Wearables.Dictionary) Wearables.Dictionary.Clear(); for (int i = 0; i < update.WearableData.Length; i++) { if (update.WearableData[i].AssetID != UUID.Zero) { WearableType type = (WearableType)update.WearableData[i].WearableType; WearableData data = new WearableData(); data.Item = new InventoryWearable(update.WearableData[i].ItemID); data.Item.WearableType = type; data.Item.AssetType = WearableTypeToAssetType(type); data.Item.AssetUUID = update.WearableData[i].AssetID; // Add this wearable to our collection lock (Wearables.Dictionary) Wearables.Dictionary[type] = data; } } } WearablesRequestEvent.Set(); }
// this method will download the assets for all inventory items in iws private void ReplaceOutfitWearables(List<InventoryWearable> iws) { lock (Wearables.Dictionary) { Dictionary<WearableType, WearableData> preserve = new Dictionary<WearableType,WearableData>(); foreach (KeyValuePair<WearableType,WearableData> kvp in Wearables.Dictionary) { if (kvp.Value.Item.AssetType == AssetType.Bodypart) preserve.Add(kvp.Key, kvp.Value); } Wearables.Dictionary = preserve; foreach (InventoryWearable iw in iws) { WearableData wd = new WearableData(); wd.Item = iw; Wearables.Dictionary[wd.Item.WearableType] = wd; } } }
private void AgentWearablesUpdateHandler(Packet packet, Simulator simulator) { bool changed = false; AgentWearablesUpdatePacket update = (AgentWearablesUpdatePacket)packet; lock (Wearables) { #region Test if anything changed in this update for (int i = 0; i < update.WearableData.Length; i++) { AgentWearablesUpdatePacket.WearableDataBlock block = update.WearableData[i]; if (block.AssetID != UUID.Zero) { WearableData wearable; if (Wearables.TryGetValue((WearableType)block.WearableType, out wearable)) { if (wearable.AssetID != block.AssetID || wearable.ItemID != block.ItemID) { // A different wearable is now set for this index changed = true; break; } } else { // A wearable is now set for this index changed = true; break; } } else if (Wearables.ContainsKey((WearableType)block.WearableType)) { // This index is now empty changed = true; break; } } #endregion Test if anything changed in this update if (changed) { Logger.DebugLog("New wearables received in AgentWearablesUpdate"); Wearables.Clear(); for (int i = 0; i < update.WearableData.Length; i++) { AgentWearablesUpdatePacket.WearableDataBlock block = update.WearableData[i]; if (block.AssetID != UUID.Zero) { WearableType type = (WearableType)block.WearableType; WearableData data = new WearableData(); data.Asset = null; data.AssetID = block.AssetID; data.AssetType = WearableTypeToAssetType(type); data.ItemID = block.ItemID; data.WearableType = type; // Add this wearable to our collection Wearables[type] = data; } } } else { Logger.DebugLog("Duplicate AgentWearablesUpdate received, discarding"); } } if (changed) { // Fire the callback AgentWearablesCallback callback = OnAgentWearables; if (callback != null) { try { callback(); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex); } } } }