Merge commit 'da794f34a56f7c88904315ae538de8f3790e6891' into bigmerge
commit
04678836c3
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -31,8 +31,11 @@ using OpenSim.Framework;
|
|||
|
||||
namespace OpenSim.Region.Framework.Interfaces
|
||||
{
|
||||
public interface IAvatarFactory
|
||||
{
|
||||
public interface IAvatarFactoryModule
|
||||
{
|
||||
|
||||
void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams);
|
||||
|
||||
/// <summary>
|
||||
/// Send the appearance of an avatar to others in the scene.
|
||||
/// </summary>
|
||||
|
@ -57,7 +60,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
/// <returns>true if a valid agent was found, false otherwise</returns>
|
||||
bool SaveBakedTextures(UUID agentId);
|
||||
|
||||
bool ValidateBakedTextureCache(IClientAPI client);
|
||||
bool ValidateBakedTextureCache(IScenePresence sp);
|
||||
void QueueAppearanceSend(UUID agentid);
|
||||
void QueueAppearanceSave(UUID agentid);
|
||||
}
|
|
@ -138,7 +138,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
protected IXMLRPC m_xmlrpcModule;
|
||||
protected IWorldComm m_worldCommModule;
|
||||
protected IAvatarFactory m_AvatarFactory;
|
||||
protected IAvatarFactoryModule m_AvatarFactory;
|
||||
protected IConfigSource m_config;
|
||||
protected IRegionSerialiserModule m_serialiser;
|
||||
protected IDialogModule m_dialogModule;
|
||||
|
@ -463,7 +463,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
public IAttachmentsModule AttachmentsModule { get; set; }
|
||||
|
||||
public IAvatarFactory AvatarFactory
|
||||
public IAvatarFactoryModule AvatarFactory
|
||||
{
|
||||
get { return m_AvatarFactory; }
|
||||
}
|
||||
|
@ -1183,7 +1183,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_xmlrpcModule = RequestModuleInterface<IXMLRPC>();
|
||||
m_worldCommModule = RequestModuleInterface<IWorldComm>();
|
||||
XferManager = RequestModuleInterface<IXfer>();
|
||||
m_AvatarFactory = RequestModuleInterface<IAvatarFactory>();
|
||||
m_AvatarFactory = RequestModuleInterface<IAvatarFactoryModule>();
|
||||
AttachmentsModule = RequestModuleInterface<IAttachmentsModule>();
|
||||
m_serialiser = RequestModuleInterface<IRegionSerialiserModule>();
|
||||
m_dialogModule = RequestModuleInterface<IDialogModule>();
|
||||
|
|
|
@ -2890,7 +2890,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// We have an appearance but we may not have the baked textures. Check the asset cache
|
||||
// to see if all the baked textures are already here.
|
||||
if (m_scene.AvatarFactory != null)
|
||||
cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(ControllingClient);
|
||||
cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
|
||||
|
||||
// If we aren't using a cached appearance, then clear out the baked textures
|
||||
if (!cachedappearance)
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
|
|||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
|
||||
protected IAvatarFactory m_avatarFactory;
|
||||
protected IAvatarFactoryModule m_avatarFactory;
|
||||
|
||||
public string Name { get { return "Appearance Information Module"; } }
|
||||
|
||||
|
@ -106,14 +106,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
|
|||
{
|
||||
foreach (Scene scene in m_scenes.Values)
|
||||
{
|
||||
scene.ForEachClient(
|
||||
delegate(IClientAPI client)
|
||||
scene.ForEachScenePresence(
|
||||
delegate(ScenePresence sp)
|
||||
{
|
||||
if (client is LLClientView && !((LLClientView)client).ChildAgentStatus())
|
||||
if (sp.ControllingClient is LLClientView && !((LLClientView)sp.ControllingClient).ChildAgentStatus())
|
||||
{
|
||||
bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(client);
|
||||
bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp);
|
||||
MainConsole.Instance.OutputFormat(
|
||||
"{0} baked appearance texture is {1}", client.Name, bakedTextureValid ? "OK" : "corrupt");
|
||||
"{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
|||
sp.Appearance = npcAppearance;
|
||||
scene.AttachmentsModule.RezAttachments(sp);
|
||||
|
||||
IAvatarFactory module = scene.RequestModuleInterface<IAvatarFactory>();
|
||||
IAvatarFactoryModule module = scene.RequestModuleInterface<IAvatarFactoryModule>();
|
||||
module.SendAppearance(sp.UUID);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -106,7 +106,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
|
|||
// ScenePresence.SendInitialData() to reset our entire appearance.
|
||||
scene.AssetService.Store(AssetHelpers.CreateAsset(originalFace8TextureId));
|
||||
|
||||
afm.SetAppearanceFromClient(sp.ControllingClient, originalTe, null);
|
||||
afm.SetAppearance(sp, originalTe, null);
|
||||
|
||||
INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
|
||||
UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, sp.Appearance);
|
||||
|
|
|
@ -2413,7 +2413,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
|
||||
protected LSL_Key SaveAppearanceToNotecard(ScenePresence sp, string notecard)
|
||||
{
|
||||
IAvatarFactory appearanceModule = World.RequestModuleInterface<IAvatarFactory>();
|
||||
IAvatarFactoryModule appearanceModule = World.RequestModuleInterface<IAvatarFactoryModule>();
|
||||
|
||||
if (appearanceModule != null)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue