Avatar Appearance refactoring /changes. Added a AvatarAppearance class, each ScenePresence "has" a AvatarAppearance object. All the ScenePresences in a opensim related to one user (so a user's various ScenePresence's in all the regions in that instance) share the same AvatarAppearance object. This means that a user's avatar should appear correctly (to both that user and other users) no matter what border crossing or teleporting they have done.

Note: this mainly improves Standalone mode, as in grid mode the appearance data isn't passed between region servers. Although people should notice a improvement when moving between regions in the same instance.
afrisby
MW 2007-12-07 17:23:11 +00:00
parent 7f4d033490
commit e23290eff6
6 changed files with 298 additions and 195 deletions

View File

@ -1,10 +1,11 @@
using libsecondlife;
using OpenSim.Framework;
using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Interfaces
{
public interface IAvatarFactory : IRegionModule
{
bool TryGetInitialAvatarAppearance(LLUUID avatarId, out AvatarWearable[] wearables, out byte[] visualParams);
bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance);
}
}

View File

@ -12,26 +12,27 @@ namespace OpenSim.Region.Environment.Modules
public class AvatarFactoryModule : IAvatarFactory
{
private Scene m_scene = null;
private Dictionary<LLUUID, AvatarAppearance> m_avatarsClothes = new Dictionary<LLUUID, AvatarAppearance>();
private Dictionary<LLUUID, AvatarAppearance> m_avatarsAppearance = new Dictionary<LLUUID, AvatarAppearance>();
public bool TryGetInitialAvatarAppearance(LLUUID avatarId, out AvatarWearable[] wearables,
out byte[] visualParams)
public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance)
{
if (m_avatarsClothes.ContainsKey(avatarId))
if (m_avatarsAppearance.ContainsKey(avatarId))
{
visualParams = GetDefaultVisualParams();
wearables = m_avatarsClothes[avatarId].IsWearing;
appearance = m_avatarsAppearance[avatarId];
return true;
}
else
{
AvatarWearable[] wearables;
byte[] visualParams;
GetDefaultAvatarAppearance(out wearables, out visualParams);
AvatarAppearance wearing = new AvatarAppearance(wearables);
m_avatarsClothes[avatarId] = wearing;
appearance = new AvatarAppearance(avatarId, wearables, visualParams);
m_avatarsAppearance[avatarId] = appearance;
return true;
}
}
public void Initialise(Scene scene, IConfigSource source)
{
scene.RegisterModuleInterface<IAvatarFactory>(this);
@ -92,11 +93,12 @@ namespace OpenSim.Region.Environment.Modules
{
assetId = baseItem.assetID;
//temporary dictionary storage. This should be storing to a database
if (m_avatarsClothes.ContainsKey(clientView.AgentId))
if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
{
AvatarAppearance avWearing = m_avatarsClothes[clientView.AgentId];
avWearing.IsWearing[wear.Type].AssetID = assetId;
avWearing.IsWearing[wear.Type].ItemID = wear.ItemID;
AvatarAppearance avatAppearance = m_avatarsAppearance[clientView.AgentId];
avatAppearance.Wearables[wear.Type].AssetID = assetId;
avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
}
}
@ -123,41 +125,6 @@ namespace OpenSim.Region.Environment.Modules
return visualParams;
}
public class AvatarAppearance
{
public AvatarWearable[] IsWearing;
public byte[] VisualParams;
public AvatarAppearance()
{
IsWearing = new AvatarWearable[13];
for (int i = 0; i < 13; i++)
{
IsWearing[i] = new AvatarWearable();
}
}
public AvatarAppearance(AvatarWearable[] wearing)
{
if (wearing.Length == 13)
{
IsWearing = new AvatarWearable[13];
for (int i = 0; i < 13; i++)
{
IsWearing[i] = new AvatarWearable();
IsWearing[i].AssetID = wearing[i].AssetID;
IsWearing[i].ItemID = wearing[i].ItemID;
}
}
else
{
IsWearing = new AvatarWearable[13];
for (int i = 0; i < 13; i++)
{
IsWearing[i] = new AvatarWearable();
}
}
}
}
}
}

View File

@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Text;
using libsecondlife;
using libsecondlife.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Communications;
using OpenSim.Region.Environment.Types;
namespace OpenSim.Region.Environment.Scenes
{
public class AvatarAppearance
{
protected LLUUID m_scenePresenceID;
protected int m_wearablesSerial = 1;
protected byte[] m_visualParams;
public byte[] VisualParams
{
get { return m_visualParams; }
set { m_visualParams = value; }
}
protected AvatarWearable[] m_wearables;
public AvatarWearable[] Wearables
{
get { return m_wearables; }
set { m_wearables = value; }
}
protected LLObject.TextureEntry m_textureEntry;
public LLObject.TextureEntry TextureEntry
{
get { return m_textureEntry; }
set { m_textureEntry = value; }
}
protected float m_avatarHeight = 0;
public float AvatarHeight
{
get { return m_avatarHeight; }
set { m_avatarHeight = value; }
}
public AvatarAppearance()
{
}
public AvatarAppearance(LLUUID avatarID, AvatarWearable[] wearables, byte[] visualParams)
{
m_scenePresenceID = avatarID;
m_wearablesSerial = 1;
m_wearables = wearables;
m_visualParams = visualParams;
m_textureEntry = GetDefaultTextureEntry();
}
public void SetID(LLUUID avatarID)
{
m_scenePresenceID = avatarID;
}
/// <summary>
///
/// </summary>
/// <param name="texture"></param>
/// <param name="visualParam"></param>
public void SetAppearance(byte[] texture, AgentSetAppearancePacket.VisualParamBlock[] visualParam)
{
LLObject.TextureEntry textureEnt = new LLObject.TextureEntry(texture, 0, texture.Length);
m_textureEntry = textureEnt;
for (int i = 0; i < visualParam.Length; i++)
{
m_visualParams[i] = visualParam[i].ParamValue;
}
// Teravus : Nifty AV Height Getting Maaaaagical formula. Oh how we love turning 0-255 into meters.
// (float)m_visualParams[25] = Height
// (float)m_visualParams[125] = LegLength
m_avatarHeight = (1.50856f + (((float)m_visualParams[25] / 255.0f) * (2.525506f - 1.50856f)))
+ (((float)m_visualParams[125] / 255.0f) / 1.5f);
}
/// <summary>
///
/// </summary>
/// <param name="avatar"></param>
public void SendAppearanceToOtherAgent(ScenePresence avatar)
{
avatar.ControllingClient.SendAppearance(m_scenePresenceID, m_visualParams,
m_textureEntry.ToBytes());
}
public void SetWearable(IClientAPI client, int wearableId, AvatarWearable wearable)
{
m_wearables[wearableId] = wearable;
SendOwnWearables(client);
}
public void SendOwnWearables(IClientAPI ourClient)
{
ourClient.SendWearables(m_wearables, m_wearablesSerial++);
}
public static LLObject.TextureEntry GetDefaultTextureEntry()
{
LLObject.TextureEntry textu = new LLObject.TextureEntry(new LLUUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97"));
textu.CreateFace(0).TextureID = new LLUUID("00000000-0000-1111-9999-000000000012");
textu.CreateFace(1).TextureID = new LLUUID("5748decc-f629-461c-9a36-a35a221fe21f");
textu.CreateFace(2).TextureID = new LLUUID("5748decc-f629-461c-9a36-a35a221fe21f");
textu.CreateFace(3).TextureID = new LLUUID("6522E74D-1660-4E7F-B601-6F48C1659A77");
textu.CreateFace(4).TextureID = new LLUUID("7CA39B4C-BD19-4699-AFF7-F93FD03D3E7B");
textu.CreateFace(5).TextureID = new LLUUID("00000000-0000-1111-9999-000000000010");
textu.CreateFace(6).TextureID = new LLUUID("00000000-0000-1111-9999-000000000011");
return textu;
}
}
}

View File

@ -161,11 +161,11 @@ namespace OpenSim.Region.Environment.Scenes
}
}
public ScenePresence CreateAndAddScenePresence(IClientAPI client, bool child, AvatarWearable[] wearables, byte[] visualParams)
public ScenePresence CreateAndAddScenePresence(IClientAPI client, bool child, AvatarAppearance appearance)
{
ScenePresence newAvatar = null;
newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, visualParams, wearables);
newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance);
newAvatar.IsChildAgent = child;
if (child)

View File

@ -991,11 +991,10 @@ namespace OpenSim.Region.Environment.Scenes
{
ScenePresence avatar = null;
byte[] visualParams;
AvatarWearable[] wearables;
LoadAvatarAppearance(client, out visualParams, out wearables);
AvatarAppearance appearance;
LoadAvatarAppearance(client, out appearance);
avatar = m_innerScene.CreateAndAddScenePresence(client, child, wearables, visualParams);
avatar = m_innerScene.CreateAndAddScenePresence(client, child, appearance);
if (avatar.IsChildAgent)
{
@ -1005,12 +1004,16 @@ namespace OpenSim.Region.Environment.Scenes
return avatar;
}
protected void LoadAvatarAppearance(IClientAPI client, out byte[] visualParams, out AvatarWearable[] wearables)
protected void LoadAvatarAppearance(IClientAPI client, out AvatarAppearance appearance)
{
if (m_AvatarFactory == null ||
!m_AvatarFactory.TryGetInitialAvatarAppearance(client.AgentId, out wearables, out visualParams))
!m_AvatarFactory.TryGetAvatarAppearance(client.AgentId, out appearance))
{
//not found Appearance
byte[] visualParams;
AvatarWearable[] wearables;
AvatarFactoryModule.GetDefaultAvatarAppearance(out wearables, out visualParams);
appearance = new AvatarAppearance(client.AgentId, wearables, visualParams);
}
}

View File

@ -58,9 +58,6 @@ namespace OpenSim.Region.Environment.Scenes
private bool m_setAlwaysRun = false;
private Quaternion m_bodyRot;
private byte[] m_visualParams;
private AvatarWearable[] m_wearables;
private LLObject.TextureEntry m_textureEntry;
public bool IsRestrictedToRegion = false;
@ -75,7 +72,7 @@ namespace OpenSim.Region.Environment.Scenes
private readonly Vector3[] Dir_Vectors = new Vector3[6];
private LLVector3 lastPhysPos = new LLVector3();
private int m_wearablesSerial = 1;
// Position of agent's camera in world
protected Vector3 m_CameraCenter = new Vector3(0, 0, 0);
@ -89,6 +86,8 @@ namespace OpenSim.Region.Environment.Scenes
// Agent's Draw distance.
protected float m_DrawDistance = 0f;
protected AvatarAppearance m_appearance;
private readonly List<ulong> m_knownChildRegions = new List<ulong>(); //neighbouring regions we have enabled a child agent in
private enum Dir_ControlFlags
@ -110,13 +109,6 @@ namespace OpenSim.Region.Environment.Scenes
public event SignificantClientMovement OnSignificantClientMovement;
//public List<SceneObjectGroup> InterestList = new List<SceneObjectGroup>();
// private string m_currentQuadNode = " ";
// private Queue<SceneObjectPart> m_fullPartUpdates = new Queue<SceneObjectPart>();
//private Queue<SceneObjectPart> m_tersePartUpdates = new Queue<SceneObjectPart>();
private UpdateQueue m_partsUpdateQueue = new UpdateQueue();
private Dictionary<LLUUID, ScenePartUpdate> m_updateTimes = new Dictionary<LLUUID, ScenePartUpdate>();
@ -280,23 +272,74 @@ namespace OpenSim.Region.Environment.Scenes
public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams,
AvatarWearable[] wearables)
{
m_scene = world;
m_uuid = client.AgentId;
m_regionInfo = reginfo;
//couldn't move the following into SetInitialValues as they are readonly
m_regionHandle = reginfo.RegionHandle;
m_controllingClient = client;
m_firstname = m_controllingClient.FirstName;
m_lastname = m_controllingClient.LastName;
m_localId = m_scene.NextLocalId;
AbsolutePosition = m_controllingClient.StartPos;
m_visualParams = visualParams;
m_wearables = wearables;
SetInitialValues(client, world, reginfo);
m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
Animations = new AvatarAnimations();
Animations.LoadAnims();
RegisterToEvents();
SetDirectionVectors();
//m_textureEntry = new LLObject.TextureEntry(DefaultTexture, 0, DefaultTexture.Length);
// m_textureEntry = GetDefaultTextureEntry();
//temporary until we move some code into the body classes
if (m_newAvatar)
{
//do we need to use newAvatar? not sure so have added this to kill the compile warning
}
m_scene.LandManager.sendLandUpdate(this);
}
public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
{
//couldn't move the following into SetInitialValues as they are readonly
m_regionHandle = reginfo.RegionHandle;
m_controllingClient = client;
m_firstname = m_controllingClient.FirstName;
m_lastname = m_controllingClient.LastName;
SetInitialValues(client, world, reginfo);
m_appearance = appearance;
Animations = new AvatarAnimations();
Animations.LoadAnims();
RegisterToEvents();
SetDirectionVectors();
if (m_newAvatar)
{
//do we need to use newAvatar? not sure so have added this to kill the compile warning
}
m_scene.LandManager.sendLandUpdate(this);
}
private void SetInitialValues(IClientAPI client, Scene world, RegionInfo reginfo)
{
m_scene = world;
m_uuid = client.AgentId;
m_regionInfo = reginfo;
m_localId = m_scene.NextLocalId;
AbsolutePosition = m_controllingClient.StartPos;
}
private void RegisterToEvents()
{
//register for events
m_controllingClient.OnRequestWearables += SendOwnAppearance;
m_controllingClient.OnSetAppearance += SetAppearance;
@ -310,26 +353,17 @@ namespace OpenSim.Region.Environment.Scenes
// ControllingClient.OnStartAnim += new StartAnim(this.SendAnimPack);
// ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
//ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
}
private void SetDirectionVectors()
{
Dir_Vectors[0] = new Vector3(1, 0, 0); //FOWARD
Dir_Vectors[1] = new Vector3(-1, 0, 0); //BACK
Dir_Vectors[2] = new Vector3(0, 1, 0); //LEFT
Dir_Vectors[3] = new Vector3(0, -1, 0); //RIGHT
Dir_Vectors[4] = new Vector3(0, 0, 1); //UP
Dir_Vectors[5] = new Vector3(0, 0, -1); //DOWN
m_textureEntry = new LLObject.TextureEntry(DefaultTexture, 0, DefaultTexture.Length);
//temporary until we move some code into the body classes
if (m_newAvatar)
{
//do we need to use newAvatar? not sure so have added this to kill the compile warning
}
m_scene.LandManager.sendLandUpdate(this);
}
#endregion
public void QueuePartForUpdate(SceneObjectPart part)
@ -500,34 +534,14 @@ namespace OpenSim.Region.Environment.Scenes
#region Event Handlers
/// <summary>
///
/// </summary>
/// <param name="texture"></param>
/// <param name="visualParam"></param>
public void SetAppearance(byte[] texture, AgentSetAppearancePacket.VisualParamBlock[] visualParam)
internal void SetHeight(float height)
{
LLObject.TextureEntry textureEnt = new LLObject.TextureEntry(texture, 0, texture.Length);
m_textureEntry = textureEnt;
for (int i = 0; i < visualParam.Length; i++)
{
m_visualParams[i] = visualParam[i].ParamValue;
//MainLog.Instance.Verbose("CLIENT", "VisualData[" + i.ToString() + "]: " + visualParam[i].ParamValue.ToString() + "m");
}
// Teravus : Nifty AV Height Getting Maaaaagical formula. Oh how we love turning 0-255 into meters.
// (float)m_visualParams[25] = Height
// (float)m_visualParams[125] = LegLength
m_avHeight = (1.50856f + (((float)m_visualParams[25] / 255.0f) * (2.525506f - 1.50856f)))
+ (((float)m_visualParams[125] / 255.0f) / 1.5f);
m_avHeight = height;
if (PhysicsActor != null)
{
PhysicsVector SetSize = new PhysicsVector(0.45f, 0.6f, m_avHeight);
PhysicsActor.Size = SetSize;
}
//MainLog.Instance.Verbose("CLIENT", "Set Avatar Height to: " + (1.50856f + (((float)m_visualParams[25] / 255.0f) * (2.525506f - 1.50856f))).ToString() + "m" + " Leglength: " + ((float)m_visualParams[125]).ToString() + ":" + (((float)m_visualParams[125] / 255.0f)).ToString() + "m");
SendAppearanceToAllOtherAgents();
}
/// <summary>
@ -1022,7 +1036,7 @@ namespace OpenSim.Region.Environment.Scenes
public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar)
{
remoteAvatar.m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_uuid,
LocalId, m_pos, m_textureEntry.ToBytes(), m_parentID);
LocalId, m_pos, m_appearance.TextureEntry.ToBytes(), m_parentID);
}
public void SendFullUpdateToAllClients()
@ -1048,7 +1062,7 @@ namespace OpenSim.Region.Environment.Scenes
public void SendInitialData()
{
m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_uuid, LocalId,
m_pos, m_textureEntry.ToBytes(), m_parentID);
m_pos, m_appearance.TextureEntry.ToBytes(), m_parentID);
if (!m_isChildAgent)
{
m_scene.InformClientOfNeighbours(this);
@ -1065,7 +1079,7 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="client"></param>
public void SendOwnAppearance()
{
SendOwnWearables();
m_appearance.SendOwnWearables(ControllingClient);
// TODO: remove this once the SunModule is slightly more tested
// m_controllingClient.SendViewerTime(m_scene.TimePhase);
@ -1078,23 +1092,32 @@ namespace OpenSim.Region.Environment.Scenes
{
m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
{
// if (scenePresence != this)
// {
SendAppearanceToOtherAgent(scenePresence);
// }
if (scenePresence.UUID != UUID)
{
m_appearance.SendAppearanceToOtherAgent(scenePresence);
}
});
}
/// <summary>
///
/// </summary>
/// <param name="avatarInfo"></param>
public void SendAppearanceToOtherAgent(ScenePresence avatarInfo)
public void SendAppearanceToOtherAgent(ScenePresence avatar)
{
avatarInfo.m_controllingClient.SendAppearance(m_controllingClient.AgentId, m_visualParams,
m_textureEntry.ToBytes());
m_appearance.SendAppearanceToOtherAgent(avatar);
}
public void SetAppearance(byte[] texture, AgentSetAppearancePacket.VisualParamBlock[] visualParam)
{
m_appearance.SetAppearance(texture, visualParam);
SetHeight(m_appearance.AvatarHeight);
SendAppearanceToAllOtherAgents();
}
public void SetWearable(int wearableId, AvatarWearable wearable)
{
m_appearance.SetWearable(ControllingClient, wearableId, wearable);
}
/// <summary>
///
/// </summary>
@ -1269,14 +1292,7 @@ namespace OpenSim.Region.Environment.Scenes
static ScenePresence()
{
LLObject.TextureEntry textu = new LLObject.TextureEntry(new LLUUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97"));
textu.CreateFace(0).TextureID = new LLUUID("00000000-0000-1111-9999-000000000012");
textu.CreateFace(1).TextureID = new LLUUID("5748decc-f629-461c-9a36-a35a221fe21f");
textu.CreateFace(2).TextureID = new LLUUID("5748decc-f629-461c-9a36-a35a221fe21f");
textu.CreateFace(3).TextureID = new LLUUID("6522E74D-1660-4E7F-B601-6F48C1659A77");
textu.CreateFace(4).TextureID = new LLUUID("7CA39B4C-BD19-4699-AFF7-F93FD03D3E7B");
textu.CreateFace(5).TextureID = new LLUUID("00000000-0000-1111-9999-000000000010");
textu.CreateFace(6).TextureID = new LLUUID("00000000-0000-1111-9999-000000000011");
LLObject.TextureEntry textu = AvatarAppearance.GetDefaultTextureEntry();
DefaultTexture = textu.ToBytes();
}
@ -1334,15 +1350,5 @@ namespace OpenSim.Region.Environment.Scenes
RemoveFromPhysicalScene();
}
public void SetWearable(int wearableId, AvatarWearable wearable)
{
m_wearables[wearableId] = wearable;
SendOwnWearables();
}
private void SendOwnWearables()
{
m_controllingClient.SendWearables(m_wearables, m_wearablesSerial++);
}
}
}