* This finishes the implementation of AgentCachedTexture. Requires the XBakes Module and service for full functionality. Previous no-cache functionality works without the service and module. In some ways, I would have been happier not putting an AssetBase in WearableCacheItem.. but turns out it was probably unavoidable. No additional locks, yay.

avinationmerge
teravus 2012-12-29 08:53:58 -05:00
parent c961cfe19e
commit 6797ac1474
7 changed files with 374 additions and 36 deletions

View File

@ -27,6 +27,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
@ -50,6 +51,7 @@ namespace OpenSim.Capabilities.Handlers
{ {
public class UploadBakedTextureHandler public class UploadBakedTextureHandler
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Caps m_HostCapsObj; private Caps m_HostCapsObj;
@ -81,7 +83,7 @@ namespace OpenSim.Capabilities.Handlers
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
BakedTextureUploader uploader = BakedTextureUploader uploader =
new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener); new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_HostCapsObj.AgentID);
uploader.OnUpLoad += BakedTextureUploaded; uploader.OnUpLoad += BakedTextureUploaded;
m_HostCapsObj.HttpListener.AddStreamHandler( m_HostCapsObj.HttpListener.AddStreamHandler(
@ -125,6 +127,7 @@ namespace OpenSim.Capabilities.Handlers
asset.Temporary = true; asset.Temporary = true;
asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are
m_assetService.Store(asset); m_assetService.Store(asset);
} }
} }
@ -137,15 +140,19 @@ namespace OpenSim.Capabilities.Handlers
private string uploaderPath = String.Empty; private string uploaderPath = String.Empty;
private UUID newAssetID; private UUID newAssetID;
private IHttpServer httpListener; private IHttpServer httpListener;
private UUID AgentId = UUID.Zero;
public BakedTextureUploader(string path, IHttpServer httpServer) public BakedTextureUploader(string path, IHttpServer httpServer, UUID uUID)
{ {
newAssetID = UUID.Random(); newAssetID = UUID.Random();
uploaderPath = path; uploaderPath = path;
httpListener = httpServer; httpListener = httpServer;
AgentId = uUID;
// m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID); // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID);
} }
/// <summary> /// <summary>
/// Handle raw uploaded baked texture data. /// Handle raw uploaded baked texture data.
/// </summary> /// </summary>

View File

@ -66,7 +66,9 @@ namespace OpenSim.Framework
protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f); protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f);
protected float m_avatarFeetOffset = 0; protected float m_avatarFeetOffset = 0;
protected float m_avatarAnimOffset = 0; protected float m_avatarAnimOffset = 0;
protected WearableCacheItem[] cacheitems; protected WearableCacheItem[] m_cacheitems;
protected bool m_cacheItemsDirty = true;
public virtual int Serial public virtual int Serial
{ {
get { return m_serial; } get { return m_serial; }
@ -118,8 +120,14 @@ namespace OpenSim.Framework
public virtual WearableCacheItem[] WearableCacheItems public virtual WearableCacheItem[] WearableCacheItems
{ {
get { return cacheitems; } get { return m_cacheitems; }
set { cacheitems = value; } set { m_cacheitems = value; }
}
public virtual bool WearableCacheItemsDirty
{
get { return m_cacheItemsDirty; }
set { m_cacheItemsDirty = value; }
} }
public AvatarAppearance() public AvatarAppearance()

View File

@ -26,14 +26,132 @@
*/ */
using System; using System;
using System.Collections.Generic;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
[Serializable]
public class WearableCacheItem public class WearableCacheItem
{ {
public uint TextureIndex { get; set; } public uint TextureIndex { get; set; }
public UUID CacheId { get; set; } public UUID CacheId { get; set; }
public UUID TextureID { get; set; } public UUID TextureID { get; set; }
public AssetBase TextureAsset { get; set; }
public static WearableCacheItem[] GetDefaultCacheItem()
{
int itemmax = 21;
WearableCacheItem[] retitems = new WearableCacheItem[itemmax];
for (uint i=0;i<itemmax;i++)
retitems[i] = new WearableCacheItem() {CacheId = UUID.Zero, TextureID = UUID.Zero, TextureIndex = i + 1};
return retitems;
}
public static WearableCacheItem[] FromOSD(OSD pInput, IImprovedAssetCache dataCache)
{
List<WearableCacheItem> ret = new List<WearableCacheItem>();
if (pInput.Type == OSDType.Array)
{
OSDArray itemarray = (OSDArray) pInput;
foreach (OSDMap item in itemarray)
{
ret.Add(new WearableCacheItem()
{
TextureIndex = item["textureindex"].AsUInteger(),
CacheId = item["cacheid"].AsUUID(),
TextureID = item["textureid"].AsUUID()
});
if (dataCache != null && item.ContainsKey("assetdata"))
{
AssetBase asset = new AssetBase(item["textureid"].AsUUID(),"BakedTexture",(sbyte)AssetType.Texture,UUID.Zero.ToString());
asset.Temporary = true;
asset.Data = item["assetdata"].AsBinary();
dataCache.Cache(asset);
}
}
}
else if (pInput.Type == OSDType.Map)
{
OSDMap item = (OSDMap) pInput;
ret.Add(new WearableCacheItem(){
TextureIndex = item["textureindex"].AsUInteger(),
CacheId = item["cacheid"].AsUUID(),
TextureID = item["textureid"].AsUUID()
});
if (dataCache != null && item.ContainsKey("assetdata"))
{
string assetCreator = item["assetcreator"].AsString();
string assetName = item["assetname"].AsString();
AssetBase asset = new AssetBase(item["textureid"].AsUUID(), assetName, (sbyte)AssetType.Texture, assetCreator);
asset.Temporary = true;
asset.Data = item["assetdata"].AsBinary();
dataCache.Cache(asset);
}
}
else
{
return new WearableCacheItem[0];
}
return ret.ToArray();
}
public static OSD ToOSD(WearableCacheItem[] pcacheItems, IImprovedAssetCache dataCache)
{
OSDArray arr = new OSDArray();
foreach (WearableCacheItem item in pcacheItems)
{
OSDMap itemmap = new OSDMap();
itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
itemmap.Add("textureid", OSD.FromUUID(item.TextureID));
if (dataCache != null)
{
if (dataCache.Check(item.TextureID.ToString()))
{
AssetBase assetItem = dataCache.Get(item.TextureID.ToString());
if (assetItem != null)
{
itemmap.Add("assetdata", OSD.FromBinary(assetItem.Data));
itemmap.Add("assetcreator", OSD.FromString(assetItem.CreatorID));
itemmap.Add("assetname", OSD.FromString(assetItem.Name));
}
}
}
arr.Add(itemmap);
}
return arr;
}
public static WearableCacheItem SearchTextureIndex(uint pTextureIndex,WearableCacheItem[] pcacheItems)
{
for (int i = 0; i < pcacheItems.Length; i++)
{
if (pcacheItems[i].TextureIndex == pTextureIndex)
return pcacheItems[i];
}
return null;
}
public static WearableCacheItem SearchTextureCacheId(UUID pCacheId, WearableCacheItem[] pcacheItems)
{
for (int i = 0; i < pcacheItems.Length; i++)
{
if (pcacheItems[i].CacheId == pCacheId)
return pcacheItems[i];
}
return null;
}
public static WearableCacheItem SearchTextureTextureId(UUID pTextureId, WearableCacheItem[] pcacheItems)
{
for (int i = 0; i < pcacheItems.Length; i++)
{
if (pcacheItems[i].TextureID == pTextureId)
return pcacheItems[i];
}
return null;
}
} }
} }

View File

@ -27,6 +27,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
@ -53,8 +54,8 @@ namespace OpenSim.Region.ClientStack.Linden
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UploadBakedTextureModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UploadBakedTextureModule")]
public class UploadBakedTextureModule : INonSharedRegionModule public class UploadBakedTextureModule : INonSharedRegionModule
{ {
// private static readonly ILog m_log = private static readonly ILog m_log =
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary> /// <summary>
/// For historical reasons this is fixed, but there /// For historical reasons this is fixed, but there
@ -64,31 +65,154 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_scene; private Scene m_scene;
private bool m_persistBakedTextures; private bool m_persistBakedTextures;
private IBakedTextureModule m_BakedTextureModule;
public void Initialise(IConfigSource source) public void Initialise(IConfigSource source)
{ {
IConfig appearanceConfig = source.Configs["Appearance"]; IConfig appearanceConfig = source.Configs["Appearance"];
if (appearanceConfig != null) if (appearanceConfig != null)
m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
} }
public void AddRegion(Scene s) public void AddRegion(Scene s)
{ {
m_scene = s; m_scene = s;
} }
public void RemoveRegion(Scene s) public void RemoveRegion(Scene s)
{ {
s.EventManager.OnRegisterCaps -= RegisterCaps;
s.EventManager.OnNewPresence -= RegisterNewPresence;
s.EventManager.OnRemovePresence -= DeRegisterPresence;
m_BakedTextureModule = null;
m_scene = null;
} }
public void RegionLoaded(Scene s) public void RegionLoaded(Scene s)
{ {
m_scene.EventManager.OnRegisterCaps += RegisterCaps; m_scene.EventManager.OnRegisterCaps += RegisterCaps;
m_scene.EventManager.OnNewPresence += RegisterNewPresence;
m_scene.EventManager.OnRemovePresence += DeRegisterPresence;
}
private void DeRegisterPresence(UUID agentId)
{
ScenePresence presence = null;
if (m_scene.TryGetScenePresence(agentId, out presence))
{
presence.ControllingClient.OnSetAppearance -= CaptureAppearanceSettings;
}
}
private void RegisterNewPresence(ScenePresence presence)
{
presence.ControllingClient.OnSetAppearance += CaptureAppearanceSettings;
}
private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
{
m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
if (cacheItems.Length > 0)
{
m_log.Info("[Cacheitems]: " + cacheItems.Length);
for (int iter = 0; iter < cacheItems.Length; iter++)
{
m_log.Info("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
cacheItems[iter].TextureID);
}
ScenePresence p = null;
if (m_scene.TryGetScenePresence(remoteClient.AgentId, out p))
{
WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems;
if (existingitems == null)
{
if (m_BakedTextureModule != null)
{
WearableCacheItem[] savedcache = null;
try
{
if (p.Appearance.WearableCacheItemsDirty)
{
savedcache = m_BakedTextureModule.Get(p.UUID);
p.Appearance.WearableCacheItems = savedcache;
p.Appearance.WearableCacheItemsDirty = false;
}
}
catch (InvalidOperationException)
{
}
if (savedcache != null)
existingitems = savedcache;
}
}
// Existing items null means it's a fully new appearance
if (existingitems == null)
{
for (int iter = 0; iter < cacheItems.Length; iter++)
{
cacheItems[iter].TextureID = textureEntry.FaceTextures[cacheItems[iter].TextureIndex].TextureID;
if (m_scene.AssetService != null)
cacheItems[iter].TextureAsset = m_scene.AssetService.GetCached(cacheItems[iter].TextureID.ToString());
}
}
else
{
// for each uploaded baked texture
for (int i = 0; i < cacheItems.Length; i++)
{
cacheItems[i].TextureID =
textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID;
}
for (int i = 0; i < cacheItems.Length; i++)
{
if (cacheItems[i].TextureAsset == null)
{
cacheItems[i].TextureAsset = m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
}
}
}
p.Appearance.WearableCacheItems = cacheItems;
if (m_BakedTextureModule != null)
{
m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems);
p.Appearance.WearableCacheItemsDirty = true;
}
}
}
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() { } public void Close() { }
public string Name { get { return "UploadBakedTextureModule"; } } public string Name { get { return "UploadBakedTextureModule"; } }
@ -100,15 +224,23 @@ namespace OpenSim.Region.ClientStack.Linden
public void RegisterCaps(UUID agentID, Caps caps) public void RegisterCaps(UUID agentID, Caps caps)
{ {
UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler(
caps, m_scene.AssetService, m_persistBakedTextures);
caps.RegisterHandler( caps.RegisterHandler(
"UploadBakedTexture", "UploadBakedTexture",
new RestStreamHandler( new RestStreamHandler(
"POST", "POST",
"/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath, "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
new UploadBakedTextureHandler( avatarhandler.UploadBakedTexture,
caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture,
"UploadBakedTexture", "UploadBakedTexture",
agentID.ToString())); agentID.ToString()));
} }
} }
} }

View File

@ -3629,7 +3629,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
avp.Sender.IsTrial = false; avp.Sender.IsTrial = false;
avp.Sender.ID = agentID; avp.Sender.ID = agentID;
//m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
OutPacket(avp, ThrottleOutPacketType.State); OutPacket(avp, ThrottleOutPacketType.State);
} }
@ -11725,32 +11725,110 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// var item = fac.GetBakedTextureFaces(AgentId); // var item = fac.GetBakedTextureFaces(AgentId);
//WearableCacheItem[] items = fac.GetCachedItems(AgentId); //WearableCacheItem[] items = fac.GetCachedItems(AgentId);
IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); IAssetService cache = m_scene.AssetService;
if (cache == null) IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
if (bakedTextureModule != null && cache != null)
{ {
for (int i = 0; i < cachedtex.WearableData.Length; i++) // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid
WearableCacheItem[] cacheItems = null;
ScenePresence p = m_scene.GetScenePresence(AgentId);
if (p.Appearance != null)
if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty)
{
try
{
cacheItems = bakedTextureModule.Get(AgentId);
p.Appearance.WearableCacheItems = cacheItems;
p.Appearance.WearableCacheItemsDirty = false;
}
catch (InvalidOperationException)
{
cacheItems = null;
}
}
else if (p.Appearance.WearableCacheItems != null)
{
cacheItems = p.Appearance.WearableCacheItems;
}
if (cache != null && cacheItems != null)
{ {
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); foreach (WearableCacheItem item in cacheItems)
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; {
cachedresp.WearableData[i].TextureID = UUID.Zero; //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
cachedresp.WearableData[i].HostName = new byte[0]; if (cache.GetCached(item.TextureID.ToString()) == null)
{
item.TextureAsset.Temporary = true;
cache.Store(item.TextureAsset);
}
}
}
if (cacheItems != null)
{
for (int i = 0; i < cachedtex.WearableData.Length; i++)
{
WearableCacheItem item =
WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems);
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex;
cachedresp.WearableData[i].HostName = new byte[0];
if (item != null)
{
cachedresp.WearableData[i].TextureID = item.TextureID;
}
else
{
cachedresp.WearableData[i].TextureID = UUID.Zero;
}
}
}
else
{
for (int i = 0; i < cachedtex.WearableData.Length; i++)
{
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
cachedresp.WearableData[i].TextureID = UUID.Zero;
//UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
cachedresp.WearableData[i].HostName = new byte[0];
}
} }
} }
else else
{ {
for (int i = 0; i < cachedtex.WearableData.Length; i++) if (cache == null)
{ {
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); for (int i = 0; i < cachedtex.WearableData.Length; i++)
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; {
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
if (cache.Check(cachedtex.WearableData[i].ID.ToString()))
cachedresp.WearableData[i].TextureID = UUID.Zero; cachedresp.WearableData[i].TextureID = UUID.Zero;
//UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
else cachedresp.WearableData[i].HostName = new byte[0];
cachedresp.WearableData[i].TextureID = UUID.Zero; // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46"); }
cachedresp.WearableData[i].HostName = new byte[0]; }
else
{
for (int i = 0; i < cachedtex.WearableData.Length; i++)
{
cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
if (cache.GetCached(cachedresp.WearableData[i].TextureID.ToString()) == null)
cachedresp.WearableData[i].TextureID = UUID.Zero;
//UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
else
cachedresp.WearableData[i].TextureID = UUID.Zero;
// UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
cachedresp.WearableData[i].HostName = new byte[0];
}
} }
} }
cachedresp.Header.Zerocoded = true; cachedresp.Header.Zerocoded = true;

View File

@ -205,10 +205,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// ((ScenePresence)sp).SetSize(box,off); // ((ScenePresence)sp).SetSize(box,off);
} }
//if (cacheItems.Length > 0)
//{
sp.Appearance.WearableCacheItems = cacheItems;
//}
// Process the baked texture array // Process the baked texture array
if (textureEntry != null) if (textureEntry != null)
{ {
@ -284,8 +281,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
public WearableCacheItem[] GetCachedItems(UUID agentId) public WearableCacheItem[] GetCachedItems(UUID agentId)
{ {
ScenePresence sp = m_scene.GetScenePresence(agentId); ScenePresence sp = m_scene.GetScenePresence(agentId);
Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp);
WearableCacheItem[] items = sp.Appearance.WearableCacheItems; WearableCacheItem[] items = sp.Appearance.WearableCacheItems;
//foreach (WearableCacheItem item in items) //foreach (WearableCacheItem item in items)
//{ //{

View File

@ -13,7 +13,7 @@ namespace OpenSim.Services.Interfaces
{ {
public interface IBakedTextureModule public interface IBakedTextureModule
{ {
AssetBase[] Get(UUID id); WearableCacheItem[] Get(UUID id);
void Store(UUID id, AssetBase[] data); void Store(UUID id, WearableCacheItem[] data);
} }
} }