Renamed and rearranged AvatarFactoryModule to eliminate redundant lookups of scene presence by client ID.

This commit is contained in:
Dan Lake
2011-10-19 14:41:44 -07:00
parent 32c3faedd6
commit da794f34a5
9 changed files with 319 additions and 344 deletions

View File

@@ -42,7 +42,7 @@ using OpenSim.Services.Interfaces;
namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
{
public class AvatarFactoryModule : IAvatarFactory, IRegionModule
public class AvatarFactoryModule : IAvatarFactoryModule, IRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene = null;
@@ -57,12 +57,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
private object m_setAppearanceLock = new object();
#region RegionModule Members
#region IRegionModule
public void Initialise(Scene scene, IConfigSource config)
{
scene.RegisterModuleInterface<IAvatarFactory>(this);
scene.EventManager.OnNewClient += NewClient;
scene.RegisterModuleInterface<IAvatarFactoryModule>(this);
scene.EventManager.OnNewClient += SubscribeToClientEvents;
IConfig sconfig = config.Configs["Startup"];
if (sconfig != null)
@@ -98,44 +98,201 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
get { return false; }
}
public void NewClient(IClientAPI client)
private void SubscribeToClientEvents(IClientAPI client)
{
client.OnRequestWearables += SendWearables;
client.OnSetAppearance += SetAppearanceFromClient;
client.OnAvatarNowWearing += AvatarIsWearing;
client.OnRequestWearables += Client_OnRequestWearables;
client.OnSetAppearance += Client_OnSetAppearance;
client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
}
public void RemoveClient(IClientAPI client)
{
// client.OnAvatarNowWearing -= AvatarIsWearing;
}
#endregion
#endregion
#region IAvatarFactoryModule
/// <summary>
/// Set appearance data (texture asset IDs and slider settings)
/// </summary>
/// <param name="sp"></param>
/// <param name="texture"></param>
/// <param name="visualParam"></param>
public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams)
{
// m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}", client.AgentId);
// TODO: This is probably not necessary any longer, just assume the
// textureEntry set implies that the appearance transaction is complete
bool changed = false;
// Process the texture entry transactionally, this doesn't guarantee that Appearance is
// going to be handled correctly but it does serialize the updates to the appearance
lock (m_setAppearanceLock)
{
// Process the visual params, this may change height as well
if (visualParams != null)
{
// string[] visualParamsStrings = new string[visualParams.Length];
// for (int i = 0; i < visualParams.Length; i++)
// visualParamsStrings[i] = visualParams[i].ToString();
// m_log.DebugFormat(
// "[AVFACTORY]: Setting visual params for {0} to {1}",
// client.Name, string.Join(", ", visualParamsStrings));
float oldHeight = sp.Appearance.AvatarHeight;
changed = sp.Appearance.SetVisualParams(visualParams);
if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
}
// Process the baked texture array
if (textureEntry != null)
{
changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
m_log.InfoFormat("[AVFACTORY]: received texture update for {0}", sp.UUID);
Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(sp, false); });
// This appears to be set only in the final stage of the appearance
// update transaction. In theory, we should be able to do an immediate
// appearance send and save here.
}
// save only if there were changes, send no matter what (doesn't hurt to send twice)
if (changed)
QueueAppearanceSave(sp.ControllingClient.AgentId);
QueueAppearanceSend(sp.ControllingClient.AgentId);
}
// m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString());
}
public bool SendAppearance(UUID agentId)
{
ScenePresence sp = m_scene.GetScenePresence(agentId);
if (sp == null)
{
m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
return false;
}
// Send the appearance to everyone in the scene
sp.SendAppearanceToAllOtherAgents();
// Send animations back to the avatar as well
sp.Animator.SendAnimPack();
return true;
}
public Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(UUID agentId)
{
ScenePresence sp = m_scene.GetScenePresence(agentId);
if (sp == null)
return new Dictionary<BakeType, Primitive.TextureEntryFace>();
return GetBakedTextureFaces(sp);
}
public bool SaveBakedTextures(UUID agentId)
{
ScenePresence sp = m_scene.GetScenePresence(agentId);
if (sp == null)
return false;
m_log.DebugFormat(
"[AV FACTORY]: Permanently saving baked textures for {0} in {1}",
sp.Name, m_scene.RegionInfo.RegionName);
Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp);
if (bakedTextures.Count == 0)
return false;
foreach (BakeType bakeType in bakedTextures.Keys)
{
Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType];
if (bakedTextureFace == null)
{
m_log.WarnFormat(
"[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently",
bakeType, sp.Name, m_scene.RegionInfo.RegionName);
continue;
}
AssetBase asset = m_scene.AssetService.Get(bakedTextureFace.TextureID.ToString());
if (asset != null)
{
asset.Temporary = false;
asset.Local = false;
m_scene.AssetService.Store(asset);
}
else
{
m_log.WarnFormat(
"[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently",
bakedTextureFace.TextureID, bakeType, sp.Name, m_scene.RegionInfo.RegionName);
}
}
return true;
}
/// <summary>
/// Check for the existence of the baked texture assets.
/// </summary>
/// <param name="client"></param>
public bool ValidateBakedTextureCache(IClientAPI client)
/// <param name="sp"></param>
public bool ValidateBakedTextureCache(IScenePresence sp)
{
return ValidateBakedTextureCache(client, true);
}
return ValidateBakedTextureCache(sp, true);
}
/// <summary>
/// Queue up a request to send appearance, makes it possible to
/// accumulate changes without sending out each one separately.
/// </summary>
public void QueueAppearanceSend(UUID agentid)
{
// m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
// 10000 ticks per millisecond, 1000 milliseconds per second
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
lock (m_sendqueue)
{
m_sendqueue[agentid] = timestamp;
m_updateTimer.Start();
}
}
public void QueueAppearanceSave(UUID agentid)
{
// m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid);
// 10000 ticks per millisecond, 1000 milliseconds per second
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
lock (m_savequeue)
{
m_savequeue[agentid] = timestamp;
m_updateTimer.Start();
}
}
#endregion
#region AvatarFactoryModule private methods
/// <summary>
/// Check for the existence of the baked texture assets. Request a rebake
/// unless checkonly is true.
/// </summary>
/// <param name="client"></param>
/// <param name="checkonly"></param>
private bool ValidateBakedTextureCache(IClientAPI client, bool checkonly)
private bool ValidateBakedTextureCache(IScenePresence sp, bool checkonly)
{
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
if (sp == null)
{
m_log.WarnFormat("[AVFACTORY]: SetAppearance unable to find presence for {0}", client.AgentId);
return false;
}
bool defonly = true; // are we only using default textures
// Process the texture entry
@@ -161,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
defonly = false; // found a non-default texture reference
if (!CheckBakedTextureAsset(client, face.TextureID, idx))
if (!CheckBakedTextureAsset(sp, face.TextureID, idx))
{
// the asset didn't exist if we are only checking, then we found a bad
// one and we're done otherwise, ask for a rebake
@@ -170,109 +327,34 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
m_log.InfoFormat("[AVFACTORY]: missing baked texture {0}, requesting rebake", face.TextureID);
client.SendRebakeAvatarTextures(face.TextureID);
sp.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
}
}
m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", client.AgentId);
m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", sp.UUID);
// If we only found default textures, then the appearance is not cached
return (defonly ? false : true);
}
/// <summary>
/// Set appearance data (texture asset IDs and slider settings) received from the client
/// </summary>
/// <param name="client"></param>
/// <param name="texture"></param>
/// <param name="visualParam"></param>
public void SetAppearanceFromClient(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams)
{
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
if (sp == null)
{
m_log.WarnFormat("[AVFACTORY]: SetAppearance unable to find presence for {0}", client.AgentId);
return;
}
// m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}", client.AgentId);
// TODO: This is probably not necessary any longer, just assume the
// textureEntry set implies that the appearance transaction is complete
bool changed = false;
// Process the texture entry transactionally, this doesn't guarantee that Appearance is
// going to be handled correctly but it does serialize the updates to the appearance
lock (m_setAppearanceLock)
{
// Process the visual params, this may change height as well
if (visualParams != null)
{
// string[] visualParamsStrings = new string[visualParams.Length];
// for (int i = 0; i < visualParams.Length; i++)
// visualParamsStrings[i] = visualParams[i].ToString();
// m_log.DebugFormat(
// "[AVFACTORY]: Setting visual params for {0} to {1}",
// client.Name, string.Join(", ", visualParamsStrings));
float oldHeight = sp.Appearance.AvatarHeight;
changed = sp.Appearance.SetVisualParams(visualParams);
if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
sp.SetHeight(sp.Appearance.AvatarHeight);
}
// Process the baked texture array
if (textureEntry != null)
{
changed = sp.Appearance.SetTextureEntries(textureEntry) || changed;
m_log.InfoFormat("[AVFACTORY]: received texture update for {0}", client.AgentId);
Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(client, false); });
// This appears to be set only in the final stage of the appearance
// update transaction. In theory, we should be able to do an immediate
// appearance send and save here.
}
// save only if there were changes, send no matter what (doesn't hurt to send twice)
if (changed)
QueueAppearanceSave(client.AgentId);
QueueAppearanceSend(client.AgentId);
}
// m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString());
}
/// <summary>
/// Checks for the existance of a baked texture asset and
/// requests the viewer rebake if the asset is not found
/// </summary>
/// <param name="client"></param>
/// <param name="sp"></param>
/// <param name="textureID"></param>
/// <param name="idx"></param>
private bool CheckBakedTextureAsset(IClientAPI client, UUID textureID, int idx)
private bool CheckBakedTextureAsset(IScenePresence sp, UUID textureID, int idx)
{
if (m_scene.AssetService.Get(textureID.ToString()) == null)
{
m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",
textureID, idx, client.Name);
textureID, idx, sp.Name);
return false;
}
return true;
}
public Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(UUID agentId)
{
ScenePresence sp = m_scene.GetScenePresence(agentId);
if (sp == null)
return new Dictionary<BakeType, Primitive.TextureEntryFace>();
return GetBakedTextureFaces(sp);
}
private Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(ScenePresence sp)
{
if (sp.IsChildAgent)
@@ -302,136 +384,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
return bakedTextures;
}
public bool SaveBakedTextures(UUID agentId)
{
ScenePresence sp = m_scene.GetScenePresence(agentId);
if (sp == null)
return false;
m_log.DebugFormat(
"[AV FACTORY]: Permanently saving baked textures for {0} in {1}",
sp.Name, m_scene.RegionInfo.RegionName);
Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp);
if (bakedTextures.Count == 0)
return false;
foreach (BakeType bakeType in bakedTextures.Keys)
{
Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType];
if (bakedTextureFace == null)
{
m_log.WarnFormat(
"[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently",
bakeType, sp.Name, m_scene.RegionInfo.RegionName);
continue;
}
AssetBase asset = m_scene.AssetService.Get(bakedTextureFace.TextureID.ToString());
if (asset != null)
{
asset.Temporary = false;
asset.Local = false;
m_scene.AssetService.Store(asset);
}
else
{
m_log.WarnFormat(
"[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently",
bakedTextureFace.TextureID, bakeType, sp.Name, m_scene.RegionInfo.RegionName);
}
}
// for (int i = 0; i < faceTextures.Length; i++)
// {
//// m_log.DebugFormat(
//// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
//// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
//
// if (faceTextures[i] == null)
// continue;
//
// AssetBase asset = m_scene.AssetService.Get(faceTextures[i].TextureID.ToString());
//
// if (asset != null)
// {
// asset.Temporary = false;
// m_scene.AssetService.Store(asset);
// }
// else
// {
// m_log.WarnFormat(
// "[AV FACTORY]: Baked texture {0} for {1} in {2} not found when trying to save permanently",
// faceTextures[i].TextureID, sp.Name, m_scene.RegionInfo.RegionName);
// }
// }
return true;
}
#region UpdateAppearanceTimer
/// <summary>
/// Queue up a request to send appearance, makes it possible to
/// accumulate changes without sending out each one separately.
/// </summary>
public void QueueAppearanceSend(UUID agentid)
{
// m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
// 10000 ticks per millisecond, 1000 milliseconds per second
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
lock (m_sendqueue)
{
m_sendqueue[agentid] = timestamp;
m_updateTimer.Start();
}
}
public void QueueAppearanceSave(UUID agentid)
{
// m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid);
// 10000 ticks per millisecond, 1000 milliseconds per second
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
lock (m_savequeue)
{
m_savequeue[agentid] = timestamp;
m_updateTimer.Start();
}
}
private void SaveAppearance(UUID agentid)
{
// We must set appearance parameters in the en_US culture in order to avoid issues where values are saved
// in a culture where decimal points are commas and then reloaded in a culture which just treats them as
// number seperators.
Culture.SetCurrentCulture();
ScenePresence sp = m_scene.GetScenePresence(agentid);
if (sp == null)
{
m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
return;
}
// m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
// This could take awhile since it needs to pull inventory
// We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
// assets and item asset id changes to complete.
// I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
// multiple save requests.
SetAppearanceAssets(sp.UUID, sp.Appearance);
m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
}
private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
{
long now = DateTime.Now.Ticks;
@@ -464,43 +416,122 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
m_updateTimer.Stop();
}
#endregion
}
private void SaveAppearance(UUID agentid)
{
// We must set appearance parameters in the en_US culture in order to avoid issues where values are saved
// in a culture where decimal points are commas and then reloaded in a culture which just treats them as
// number seperators.
Culture.SetCurrentCulture();
ScenePresence sp = m_scene.GetScenePresence(agentid);
if (sp == null)
{
m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
return;
}
// m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
// This could take awhile since it needs to pull inventory
// We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
// assets and item asset id changes to complete.
// I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
// multiple save requests.
SetAppearanceAssets(sp.UUID, sp.Appearance);
m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
}
private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
{
IInventoryService invService = m_scene.InventoryService;
if (invService.GetRootFolder(userID) != null)
{
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
{
for (int j = 0; j < appearance.Wearables[j].Count; j++)
{
if (appearance.Wearables[i][j].ItemID == UUID.Zero)
continue;
// Ignore ruth's assets
if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
continue;
InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
baseItem = invService.GetItem(baseItem);
if (baseItem != null)
{
appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID);
}
else
{
m_log.ErrorFormat(
"[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default",
appearance.Wearables[i][j].ItemID, (WearableType)i);
appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID);
}
}
}
}
else
{
m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID);
}
}
#endregion
#region Client Event Handlers
/// <summary>
/// Tell the client for this scene presence what items it should be wearing now
/// </summary>
public void SendWearables(IClientAPI client)
{
/// </summary>
/// <param name="client"></param>
private void Client_OnRequestWearables(IClientAPI client)
{
// m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId);
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
if (sp == null)
{
m_log.WarnFormat("[AVFACTORY]: SendWearables unable to find presence for {0}", client.AgentId);
return;
}
// m_log.DebugFormat("[AVFACTORY]: Received request for wearables of {0}", client.Name);
client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++);
if (sp != null)
client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++);
else
m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId);
}
/// <summary>
/// Set appearance data (texture asset IDs and slider settings) received from a client
/// </summary>
/// <param name="client"></param>
/// <param name="texture"></param>
/// <param name="visualParam"></param>
private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams)
{
// m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
if (sp != null)
SetAppearance(sp, textureEntry, visualParams);
else
m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
}
/// <summary>
/// Update what the avatar is wearing using an item from their inventory.
/// </summary>
/// <param name="sender"></param>
/// <param name="client"></param>
/// <param name="e"></param>
public void AvatarIsWearing(IClientAPI client, AvatarWearingArgs e)
{
private void Client_OnAvatarNowWearing(IClientAPI client, AvatarWearingArgs e)
{
// m_log.WarnFormat("[AVFACTORY]: Client_OnAvatarNowWearing called for {0} ({1})", client.Name, client.AgentId);
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
if (sp == null)
{
m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing unable to find presence for {0}", client.AgentId);
m_log.WarnFormat("[AVFACTORY]: Client_OnAvatarNowWearing unable to find presence for {0}", client.AgentId);
return;
}
// m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId);
// we need to clean out the existing textures
sp.Appearance.ResetAppearance();
@@ -527,65 +558,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// of visual param and baked texture changes. When those complete, the new appearance will be sent
QueueAppearanceSave(client.AgentId);
}
}
public bool SendAppearance(UUID agentId)
{
ScenePresence sp = m_scene.GetScenePresence(agentId);
if (sp == null)
{
m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
return false;
}
// Send the appearance to everyone in the scene
sp.SendAppearanceToAllOtherAgents();
// Send animations back to the avatar as well
sp.Animator.SendAnimPack();
return true;
}
private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
{
IInventoryService invService = m_scene.InventoryService;
if (invService.GetRootFolder(userID) != null)
{
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
{
for (int j = 0; j < appearance.Wearables[j].Count; j++)
{
if (appearance.Wearables[i][j].ItemID == UUID.Zero)
continue;
// Ignore ruth's assets
if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
continue;
InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
baseItem = invService.GetItem(baseItem);
if (baseItem != null)
{
appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID);
}
else
{
m_log.ErrorFormat(
"[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default",
appearance.Wearables[i][j].ItemID, (WearableType)i);
appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID);
}
}
}
}
else
{
m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID);
}
}
}
}
#endregion
}
}

View File

@@ -55,15 +55,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
AvatarFactoryModule afm = new AvatarFactoryModule();
TestScene scene = SceneHelpers.SetupScene();
SceneHelpers.SetupSceneModules(scene, afm);
IClientAPI tc = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT];
for (byte i = 0; i < visualParams.Length; i++)
visualParams[i] = i;
afm.SetAppearanceFromClient(tc, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams);
ScenePresence sp = scene.GetScenePresence(userId);
afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams);
// TODO: Check baked texture
Assert.AreEqual(visualParams, sp.Appearance.VisualParams);
@@ -84,8 +82,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
AvatarFactoryModule afm = new AvatarFactoryModule();
TestScene scene = SceneHelpers.SetupScene(assetCache);
SceneHelpers.SetupSceneModules(scene, afm);
IClientAPI tc = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
SceneHelpers.SetupSceneModules(scene, afm);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
// TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules
AssetBase uploadedAsset;
@@ -104,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
eyesFace.TextureID = eyesTextureId;
afm.SetAppearanceFromClient(tc, bakedTextureEntry, visualParams);
afm.SetAppearance(sp, bakedTextureEntry, visualParams);
afm.SaveBakedTextures(userId);
// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);