Compare commits

...

2 Commits

Author SHA1 Message Date
Justin Clark-Casey (justincc)
05c51222e5 Merge branch 'master' into multiple-attachments 2012-06-29 20:21:39 +01:00
Justin Clark-Casey (justincc)
7033b4a0fc Experimental multiple prims on a single attachment point support.
It's difficult to extend the existing "_ap_" attachment format to support multiple attachments
So this commit creates _ap2_ entries.  It currently also still creates _ap_ entries as well.
_ap_ format will still be used if no _ap2_ entries are found, _ap2_ will be ignored by earlier version of opensim
This code appears to work with viewer 3 but it not yet well tested with other viewers.
The data formats are not final - do not use in any context where you value your appearance until arrangements become final.
2012-06-16 02:55:16 +01:00
4 changed files with 130 additions and 44 deletions

View File

@@ -140,7 +140,7 @@ namespace OpenSim.Framework
public AvatarAppearance(AvatarAppearance appearance, bool copyWearables)
{
// m_log.WarnFormat("[AVATAR APPEARANCE] create from an existing appearance");
m_log.DebugFormat("[AVATAR APPEARANCE]: Creating from an existing appearance");
if (appearance == null)
{
@@ -404,11 +404,30 @@ namespace OpenSim.Framework
return alist;
}
/// <summary>
/// Get attachments listed by attach point.
/// </summary>
/// <returns>
/// A dictionary that can be altered by the caller. This will have no impact on the original dictionary.
/// </returns>
public Dictionary<int, List<AvatarAttachment>> GetAttachmentsByAttachPoint()
{
Dictionary<int, List<AvatarAttachment>> returnDict = new Dictionary<int, List<AvatarAttachment>>();
lock (m_attachments)
{
foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
returnDict[kvp.Key] = new List<AvatarAttachment>(kvp.Value);
}
return returnDict;
}
internal void AppendAttachment(AvatarAttachment attach)
{
// m_log.DebugFormat(
// "[AVATAR APPEARNCE]: Appending itemID={0}, assetID={1} at {2}",
// attach.ItemID, attach.AssetID, attach.AttachPoint);
m_log.DebugFormat(
"[AVATAR APPEARNCE]: Appending itemID={0}, assetID={1} at {2}",
attach.ItemID, attach.AssetID, attach.AttachPoint);
lock (m_attachments)
{
@@ -421,9 +440,9 @@ namespace OpenSim.Framework
internal void ReplaceAttachment(AvatarAttachment attach)
{
// m_log.DebugFormat(
// "[AVATAR APPEARANCE]: Replacing itemID={0}, assetID={1} at {2}",
// attach.ItemID, attach.AssetID, attach.AttachPoint);
m_log.DebugFormat(
"[AVATAR APPEARANCE]: Replacing itemID={0}, assetID={1} at {2}",
attach.ItemID, attach.AssetID, attach.AttachPoint);
lock (m_attachments)
{
@@ -449,9 +468,9 @@ namespace OpenSim.Framework
/// </returns>
public bool SetAttachment(int attachpoint, UUID item, UUID asset)
{
// m_log.DebugFormat(
// "[AVATAR APPEARANCE]: Setting attachment at {0} with item ID {1}, asset ID {2}",
// attachpoint, item, asset);
m_log.DebugFormat(
"[AVATAR APPEARANCE]: Setting attachment at {0} with item ID {1}, asset ID {2}",
attachpoint, item, asset);
if (attachpoint == 0)
return false;
@@ -490,11 +509,18 @@ namespace OpenSim.Framework
{
// strip the append bit
int point = attachpoint & 0x7F;
AppendAttachment(new AvatarAttachment(point, item, asset));
// We must check if we already have the item attached. If we do then we must replace since we may
// need to set the asset ID
// FIXME: This needs to become more straightforward.
if (GetAttachmentForItem(item) == null)
AppendAttachment(new AvatarAttachment(point, item, asset));
else
ReplaceAttachment(new AvatarAttachment(point, item, asset));
}
else
{
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
ReplaceAttachment(new AvatarAttachment(attachpoint, item, asset));
}
return true;
@@ -614,6 +640,8 @@ namespace OpenSim.Framework
/// </summary>
public void Unpack(OSDMap data)
{
m_log.DebugFormat("[AVATAR APPEARANCE]: Unpacking OSDMap appearance data");
if ((data != null) && (data["serial"] != null))
m_serial = data["serial"].AsInteger();
if ((data != null) && (data["height"] != null))

View File

@@ -265,7 +265,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim
attachmentPt &= 0x7f;
// attachmentPt &= 0x7f;
// If the attachment point isn't the same as the one previously used
// set it's offset position = 0 so that it appears on the attachment point
@@ -300,15 +300,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
// At the moment we can only deal with a single attachment
if (attachments.Count != 0)
{
if (attachments[0].FromItemID != UUID.Zero)
DetachSingleAttachmentToInvInternal(sp, attachments[0]);
else
m_log.WarnFormat(
"[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
}
// if (attachments.Count != 0)
// {
// if (attachments[0].FromItemID != UUID.Zero)
// DetachSingleAttachmentToInvInternal(sp, attachments[0]);
// else
// m_log.WarnFormat(
// "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
// attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
// }
// Add the new attachment to inventory if we don't already have it.
UUID newAttachmentItemID = group.FromItemID;
@@ -335,7 +335,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim
AttachmentPt &= 0x7f;
// AttachmentPt &= 0x7f;
// Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such).
// This often happens during login - not sure the exact reason.
@@ -860,7 +860,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim
AttachmentPt &= 0x7f;
// AttachmentPt &= 0x7f;
// Calls attach with a Zero position
if (AttachObject(sp, part.ParentGroup, AttachmentPt, false))

View File

@@ -28,10 +28,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
using OpenSim.Framework;
using System.Reflection;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
namespace OpenSim.Services.Interfaces
{
@@ -91,6 +91,8 @@ namespace OpenSim.Services.Interfaces
/// </summary>
public class AvatarData
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// This pretty much determines which name/value pairs will be
// present below. The name/value pair describe a part of
// the avatar. For SL avatars, these would be "shape", "texture1",
@@ -172,11 +174,21 @@ namespace OpenSim.Services.Interfaces
Data["VisualParams"] = String.Join(",", vps);
// Attachments
List<AvatarAttachment> attachments = appearance.GetAttachments();
foreach (AvatarAttachment attach in attachments)
Dictionary<int, List<AvatarAttachment>> attachments = appearance.GetAttachmentsByAttachPoint();
foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in attachments)
{
Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString();
for (int i = 0; i < kvp.Value.Count; i++)
{
AvatarAttachment attachment = kvp.Value[i];
// Attachments old single point 'ap' style for compatibility
// The last attachment will effectively be the one chosen if there is more than one on a point.
Data["_ap_" + attachment.AttachPoint] = attachment.ItemID.ToString();
// Multi point 'ap2' style
Data[string.Format("_ap2_{0}_{1}", attachment.AttachPoint, i)] = attachment.ItemID.ToString();
}
}
}
@@ -291,22 +303,68 @@ namespace OpenSim.Services.Interfaces
}
// Attachments
Dictionary<string, string> attchs = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> _kvp in Data)
if (_kvp.Key.StartsWith("_ap_"))
attchs[_kvp.Key] = _kvp.Value;
Dictionary<int, UUID> attchsAp1 = new Dictionary<int, UUID>();
Dictionary<int, List<UUID>> attchsAp2 = new Dictionary<int, List<UUID>>();
foreach (KeyValuePair<string, string> _kvp in attchs)
foreach (KeyValuePair<string, string> kvp in Data)
{
string pointStr = _kvp.Key.Substring(4);
int point = 0;
if (!Int32.TryParse(pointStr, out point))
continue;
if (kvp.Key.StartsWith("_ap_"))
{
string pointStr = kvp.Key.Substring(4);
int point = 0;
if (!Int32.TryParse(pointStr, out point))
continue;
UUID itemUuid = UUID.Zero;
if (!UUID.TryParse(kvp.Value, out itemUuid))
continue;
UUID uuid = UUID.Zero;
UUID.TryParse(_kvp.Value, out uuid);
attchsAp1[point] = itemUuid;
}
else if (kvp.Key.StartsWith("_ap2_"))
{
string[] parts = kvp.Key.Split(new char[] { '_' });
string rawAttachPoint = parts[2];
int attachPoint;
appearance.SetAttachment(point, uuid, UUID.Zero);
if (!int.TryParse(rawAttachPoint, out attachPoint))
{
m_log.WarnFormat("[AVATAR DATA]: Received bad attachment key {0} in {1}", parts[1], kvp.Key);
continue;
}
UUID itemUuid = UUID.Zero;
if (!UUID.TryParse(kvp.Value, out itemUuid))
{
m_log.WarnFormat("[AVATAR DATA]: Received bad attachment item UUID {0}", kvp.Value);
continue;
}
if (!attchsAp2.ContainsKey(attachPoint))
attchsAp2[attachPoint] = new List<UUID>();
attchsAp2[attachPoint].Add(itemUuid);
}
}
if (attchsAp2.Count > 0)
{
m_log.DebugFormat("[AVATAR DATA]: Using ap2 format attachments");
foreach (KeyValuePair<int, List<UUID>> kvp in attchsAp2)
{
foreach (UUID itemUuid in kvp.Value)
{
// | 0x80 is a temporary hack to signal that this is an attachment append (this is what
// the viewer uses to indicate this, but ultimately we will want to do something different
appearance.SetAttachment(kvp.Key | 0x80, itemUuid, UUID.Zero);
}
}
}
else
{
m_log.DebugFormat("[AVATAR DATA]: Using ap1 format attachments");
foreach (KeyValuePair<int, UUID> kvp in attchsAp1)
appearance.SetAttachment(kvp.Key, kvp.Value, UUID.Zero);
}
if (appearance.Wearables[AvatarWearable.BODY].Count == 0)

View File

@@ -12,7 +12,7 @@
<log4net>
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{HH:mm:ss} - %message" />
<conversionPattern value="%date{HH:mm:ss.fff} - %message" />
<!-- console log with milliseconds. Useful for debugging -->
<!-- <conversionPattern value="%date{HH:mm:ss.fff} - %message" /> -->
</layout>