* BakeLayer.FinalData is public now
* Added baked texture uploading support to Utilities.AppearanceManager git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1004 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
@@ -61,6 +61,8 @@ namespace libsecondlife
|
||||
/// <summary>Maximum number of wearables for any baked layer</summary>
|
||||
public const int WEARABLES_PER_LAYER = 7;
|
||||
|
||||
/// <summary>Final compressed JPEG2000 data</summary>
|
||||
public byte[] FinalData = new byte[0];
|
||||
/// <summary>Whether this bake is complete or not</summary>
|
||||
public bool Finished = false;
|
||||
|
||||
@@ -74,8 +76,6 @@ namespace libsecondlife
|
||||
protected Bitmap Scratchpad;
|
||||
/// <summary>List of textures sorted by their baking order</summary>
|
||||
protected SortedList<BakeOrder, byte[]> Textures = new SortedList<BakeOrder, byte[]>(WEARABLES_PER_LAYER);
|
||||
/// <summary>Final compressed JPEG2000 data</summary>
|
||||
protected byte[] FinalData = new byte[0];
|
||||
/// <summary>Width of the final baked image and scratchpad</summary>
|
||||
protected int BakeWidth = 512;
|
||||
/// <summary>Height of the final baked image and scratchpad</summary>
|
||||
|
||||
@@ -456,14 +456,16 @@ namespace libsecondlife.Utilities.Appearance
|
||||
private AssetManager Assets;
|
||||
private Dictionary<Wearable.WearableType, WearableData> Wearables = new Dictionary<Wearable.WearableType, WearableData>();
|
||||
// As wearable assets are downloaded and decoded, the textures are added to this list
|
||||
private Dictionary<int, LLUUID> AgentTextures = new Dictionary<int, LLUUID>();
|
||||
private Dictionary<TextureIndex, LLUUID> AgentTextures = new Dictionary<TextureIndex, LLUUID>();
|
||||
// Wearable assets are downloaded one at a time, a new request is pulled off the queue
|
||||
// and started when the previous one completes
|
||||
private Queue<KeyValuePair<LLUUID, AssetType>> DownloadQueue = new Queue<KeyValuePair<LLUUID, AssetType>>();
|
||||
// A list of all the images we are currently downloading, prior to baking
|
||||
private Dictionary<LLUUID, TextureIndex> ImageDownloads = new Dictionary<LLUUID, TextureIndex>();
|
||||
// A list of all the bakes we need to complete
|
||||
private List<BakeLayer> PendingBakes = new List<BakeLayer>(BAKED_TEXTURE_COUNT);
|
||||
private Dictionary<BakeType, BakeLayer> PendingBakes = new Dictionary<BakeType, BakeLayer>(BAKED_TEXTURE_COUNT);
|
||||
// A list of all the uploads that are in progress
|
||||
private Dictionary<LLUUID, TextureIndex> PendingUploads = new Dictionary<LLUUID, TextureIndex>(BAKED_TEXTURE_COUNT);
|
||||
// Whether the handler for our current wearable list should automatically start downloading the assets
|
||||
private bool DownloadWearables = false;
|
||||
private int CacheCheckSerialNum = 0;
|
||||
@@ -608,12 +610,12 @@ namespace libsecondlife.Utilities.Appearance
|
||||
DownloadWearables = true;
|
||||
|
||||
// Register an asset download callback to get wearable data
|
||||
AssetManager.AssetReceivedCallback assetCallback =
|
||||
new AssetManager.AssetReceivedCallback(Assets_OnAssetReceived);
|
||||
AssetManager.ImageReceivedCallback imageCallback =
|
||||
new AssetManager.ImageReceivedCallback(Assets_OnImageReceived);
|
||||
AssetManager.AssetReceivedCallback assetCallback = new AssetManager.AssetReceivedCallback(Assets_OnAssetReceived);
|
||||
AssetManager.ImageReceivedCallback imageCallback = new AssetManager.ImageReceivedCallback(Assets_OnImageReceived);
|
||||
AssetManager.AssetUploadedCallback uploadCallback = new AssetManager.AssetUploadedCallback(Assets_OnAssetUploaded);
|
||||
Assets.OnAssetReceived += assetCallback;
|
||||
Assets.OnImageReceived += imageCallback;
|
||||
Assets.OnAssetUploaded += uploadCallback;
|
||||
|
||||
// Ask the server what we are currently wearing
|
||||
RequestAgentWearables();
|
||||
@@ -633,8 +635,9 @@ namespace libsecondlife.Utilities.Appearance
|
||||
|
||||
CachedResponseEvent.WaitOne();
|
||||
|
||||
// Unregister the image download callback
|
||||
// Unregister the image download and asset upload callbacks
|
||||
Assets.OnImageReceived -= imageCallback;
|
||||
Assets.OnAssetUploaded -= uploadCallback;
|
||||
|
||||
Client.DebugLog("CachedResponseEvent completed");
|
||||
|
||||
@@ -690,7 +693,7 @@ namespace libsecondlife.Utilities.Appearance
|
||||
// Put our AgentTextures dictionary in to TextureEntry
|
||||
lock (AgentTextures)
|
||||
{
|
||||
foreach (KeyValuePair<int, LLUUID> texture in AgentTextures)
|
||||
foreach (KeyValuePair<TextureIndex, LLUUID> texture in AgentTextures)
|
||||
{
|
||||
LLObject.TextureEntryFace face = te.CreateFace((uint)texture.Key);
|
||||
face.TextureID = texture.Value;
|
||||
@@ -775,22 +778,22 @@ namespace libsecondlife.Utilities.Appearance
|
||||
Client.Network.SendPacket(wearing);
|
||||
}
|
||||
|
||||
private int BakedIndexToAgentTextureIndex(int index)
|
||||
private TextureIndex BakedIndexToAgentTextureIndex(BakeType index)
|
||||
{
|
||||
switch ((BakeType)index)
|
||||
switch (index)
|
||||
{
|
||||
case BakeType.Head:
|
||||
return 8;
|
||||
return TextureIndex.HeadBaked;
|
||||
case BakeType.UpperBody:
|
||||
return 9;
|
||||
return TextureIndex.UpperBaked;
|
||||
case BakeType.LowerBody:
|
||||
return 10;
|
||||
return TextureIndex.LowerBaked;
|
||||
case BakeType.Eyes:
|
||||
return 11;
|
||||
return TextureIndex.EyesBaked;
|
||||
case BakeType.Skirt:
|
||||
return 19;
|
||||
return TextureIndex.SkirtBaked;
|
||||
default:
|
||||
return (int)TextureIndex.Unknown;
|
||||
return TextureIndex.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -903,7 +906,7 @@ namespace libsecondlife.Utilities.Appearance
|
||||
// Convert the baked index to an AgentTexture index
|
||||
if (block.TextureID != LLUUID.Zero && host.Length == 0)
|
||||
{
|
||||
int index = BakedIndexToAgentTextureIndex(block.TextureIndex);
|
||||
TextureIndex index = BakedIndexToAgentTextureIndex((BakeType)block.TextureIndex);
|
||||
AgentTextures[index] = block.TextureID;
|
||||
}
|
||||
else
|
||||
@@ -915,39 +918,39 @@ namespace libsecondlife.Utilities.Appearance
|
||||
case BakeType.Head:
|
||||
lock (ImageDownloads)
|
||||
{
|
||||
PendingBakes.Add(new BakeLayer(Client, 2, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.HeadBodypaint], TextureIndex.HeadBodypaint);
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.Hair], TextureIndex.Hair);
|
||||
PendingBakes.Add(BakeType.Head, new BakeLayer(Client, 2, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.HeadBodypaint], TextureIndex.HeadBodypaint);
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.Hair], TextureIndex.Hair);
|
||||
}
|
||||
break;
|
||||
case BakeType.UpperBody:
|
||||
lock (ImageDownloads)
|
||||
{
|
||||
PendingBakes.Add(new BakeLayer(Client, 4, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.UpperBodypaint], TextureIndex.UpperBodypaint);
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.UpperUndershirt], TextureIndex.UpperUndershirt);
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.UpperShirt], TextureIndex.UpperShirt);
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.UpperJacket], TextureIndex.UpperJacket);
|
||||
PendingBakes.Add(BakeType.UpperBody, new BakeLayer(Client, 4, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.UpperBodypaint], TextureIndex.UpperBodypaint);
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.UpperUndershirt], TextureIndex.UpperUndershirt);
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.UpperShirt], TextureIndex.UpperShirt);
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.UpperJacket], TextureIndex.UpperJacket);
|
||||
// TODO: Where are the gloves?
|
||||
}
|
||||
break;
|
||||
case BakeType.LowerBody:
|
||||
lock (ImageDownloads)
|
||||
{
|
||||
PendingBakes.Add(new BakeLayer(Client, 6, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.LowerBodypaint], TextureIndex.LowerBodypaint);
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.LowerUnderpants], TextureIndex.LowerUnderpants);
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.LowerSocks], TextureIndex.LowerSocks);
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.LowerShoes], TextureIndex.LowerShoes);
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.LowerPants], TextureIndex.LowerPants);
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.LowerJacket], TextureIndex.LowerJacket);
|
||||
PendingBakes.Add(BakeType.LowerBody, new BakeLayer(Client, 6, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.LowerBodypaint], TextureIndex.LowerBodypaint);
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.LowerUnderpants], TextureIndex.LowerUnderpants);
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.LowerSocks], TextureIndex.LowerSocks);
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.LowerShoes], TextureIndex.LowerShoes);
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.LowerPants], TextureIndex.LowerPants);
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.LowerJacket], TextureIndex.LowerJacket);
|
||||
}
|
||||
break;
|
||||
case BakeType.Eyes:
|
||||
lock (ImageDownloads)
|
||||
{
|
||||
PendingBakes.Add(new BakeLayer(Client, 1, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.EyesIris], TextureIndex.EyesIris);
|
||||
PendingBakes.Add(BakeType.Eyes, new BakeLayer(Client, 1, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.EyesIris], TextureIndex.EyesIris);
|
||||
}
|
||||
break;
|
||||
case BakeType.Skirt:
|
||||
@@ -955,8 +958,8 @@ namespace libsecondlife.Utilities.Appearance
|
||||
{
|
||||
lock (ImageDownloads)
|
||||
{
|
||||
PendingBakes.Add(new BakeLayer(Client, 1, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[(int)TextureIndex.Skirt], TextureIndex.Skirt);
|
||||
PendingBakes.Add(BakeType.Skirt, new BakeLayer(Client, 1, paramValues));
|
||||
ImageDownloads.Add(AgentTextures[TextureIndex.Skirt], TextureIndex.Skirt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1007,7 +1010,7 @@ namespace libsecondlife.Utilities.Appearance
|
||||
lock (AgentTextures)
|
||||
{
|
||||
foreach (KeyValuePair<int, LLUUID> texture in data.Wearable.Textures)
|
||||
AgentTextures[texture.Key] = texture.Value;
|
||||
AgentTextures[(TextureIndex)texture.Key] = texture.Value;
|
||||
}
|
||||
|
||||
Client.DebugLog("Imported wearable asset " + data.Wearable.Type.ToString());
|
||||
@@ -1050,11 +1053,92 @@ namespace libsecondlife.Utilities.Appearance
|
||||
if (ImageDownloads.ContainsKey(image.ID))
|
||||
{
|
||||
TextureIndex index = ImageDownloads[image.ID];
|
||||
BakeType type = BakeType.Head;
|
||||
BakeLayer.BakeOrder order = BakeLayer.BakeOrder.HeadBodypaint;
|
||||
|
||||
if (image.Success)
|
||||
{
|
||||
// FIXME: Add this image to a baking layer
|
||||
// FIXME: If true is returned, the bake is complete and we can fetch the finished jp2 data
|
||||
// Add this image to a baking layer
|
||||
switch (index)
|
||||
{
|
||||
case TextureIndex.HeadBodypaint:
|
||||
type = BakeType.Head;
|
||||
order = BakeLayer.BakeOrder.HeadBodypaint;
|
||||
break;
|
||||
case TextureIndex.Hair:
|
||||
type = BakeType.Head;
|
||||
order = BakeLayer.BakeOrder.Hair;
|
||||
break;
|
||||
case TextureIndex.UpperBodypaint:
|
||||
type = BakeType.UpperBody;
|
||||
order = BakeLayer.BakeOrder.UpperBodypaint;
|
||||
break;
|
||||
case TextureIndex.UpperUndershirt:
|
||||
type = BakeType.UpperBody;
|
||||
order = BakeLayer.BakeOrder.UpperUndershirt;
|
||||
break;
|
||||
case TextureIndex.UpperShirt:
|
||||
type = BakeType.UpperBody;
|
||||
order = BakeLayer.BakeOrder.UpperShirt;
|
||||
break;
|
||||
case TextureIndex.UpperJacket:
|
||||
type = BakeType.UpperBody;
|
||||
order = BakeLayer.BakeOrder.UpperJacket;
|
||||
break;
|
||||
case TextureIndex.LowerBodypaint:
|
||||
type = BakeType.LowerBody;
|
||||
order = BakeLayer.BakeOrder.LowerBodypaint;
|
||||
break;
|
||||
case TextureIndex.LowerUnderpants:
|
||||
type = BakeType.LowerBody;
|
||||
order = BakeLayer.BakeOrder.LowerUnderpants;
|
||||
break;
|
||||
case TextureIndex.LowerSocks:
|
||||
type = BakeType.LowerBody;
|
||||
order = BakeLayer.BakeOrder.LowerSocks;
|
||||
break;
|
||||
case TextureIndex.LowerShoes:
|
||||
type = BakeType.LowerBody;
|
||||
order = BakeLayer.BakeOrder.LowerShoes;
|
||||
break;
|
||||
case TextureIndex.LowerPants:
|
||||
type = BakeType.LowerBody;
|
||||
order = BakeLayer.BakeOrder.LowerPants;
|
||||
break;
|
||||
case TextureIndex.LowerJacket:
|
||||
type = BakeType.LowerBody;
|
||||
order = BakeLayer.BakeOrder.LowerJacket;
|
||||
break;
|
||||
case TextureIndex.EyesIris:
|
||||
type = BakeType.Eyes;
|
||||
order = BakeLayer.BakeOrder.EyesIris;
|
||||
break;
|
||||
case TextureIndex.Skirt:
|
||||
type = BakeType.Skirt;
|
||||
order = BakeLayer.BakeOrder.Skirt;
|
||||
break;
|
||||
default:
|
||||
Client.Log("Image downloaded for unknown TextureIndex " + index.ToString(),
|
||||
Helpers.LogLevel.Warning);
|
||||
break;
|
||||
}
|
||||
|
||||
if (PendingBakes.ContainsKey(type) && PendingBakes[type].AddImage(order, image.AssetData))
|
||||
{
|
||||
// Create a transactionID and assetID for this upload
|
||||
LLUUID transactionID = LLUUID.Random();
|
||||
LLUUID assetID = transactionID.Combine(Client.Network.SecureSessionID);
|
||||
|
||||
// Upload the completed bake data
|
||||
Assets.RequestUpload(transactionID, AssetType.Texture, PendingBakes[type].FinalData,
|
||||
true, true, false);
|
||||
|
||||
// Add it to a pending uploads list
|
||||
lock (PendingUploads) PendingUploads.Add(assetID, index);
|
||||
|
||||
// Remove this bake from the pending list
|
||||
PendingBakes.Remove(type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1064,13 +1148,45 @@ namespace libsecondlife.Utilities.Appearance
|
||||
|
||||
ImageDownloads.Remove(image.ID);
|
||||
|
||||
if (ImageDownloads.Count == 0)
|
||||
if (ImageDownloads.Count == 0 && PendingUploads.Count == 0)
|
||||
{
|
||||
// All the images have been downloaded and the baking is finished
|
||||
// This is a failsafe catch, as the upload completed callback should normally
|
||||
// be triggering the event
|
||||
CachedResponseEvent.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Assets_OnAssetUploaded(AssetUpload upload)
|
||||
{
|
||||
lock (PendingUploads)
|
||||
{
|
||||
if (PendingUploads.ContainsKey(upload.AssetID))
|
||||
{
|
||||
if (upload.Success)
|
||||
{
|
||||
// FIXME: Setup the TextureEntry with the new baked upload
|
||||
}
|
||||
else
|
||||
{
|
||||
Client.Log("Asset upload " + upload.AssetID.ToStringHyphenated() + " failed",
|
||||
Helpers.LogLevel.Warning);
|
||||
}
|
||||
|
||||
PendingUploads.Remove(upload.AssetID);
|
||||
|
||||
if (PendingUploads.Count == 0 && ImageDownloads.Count == 0)
|
||||
{
|
||||
CachedResponseEvent.Set();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TEMP
|
||||
Client.DebugLog("Upload " + upload.AssetID.ToStringHyphenated() + " was not found in PendingUploads");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user