* Moved OpenMetaverse/Resources to bin/openmetaverse_data until we have a working xbuild and reorganize SVN
* Complete rewrite of AppearanceManager. Appearance editing has not been (re)implemented yet, but the normal appearance setting is much more reliable * Added a setting (defaulted to true) for automatically setting appearance * Various baking hacks to get slightly less ugly avatars * Added baked texture uploading through CAPS in AssetManager.RequestUploadBakedTexture(). UDP fallback is not implemented yet * Added Parallel.Invoke() and overloads for all three methods that take a threadCount git-svn-id: http://libopenmetaverse.googlecode.com/svn/libopenmetaverse/trunk@3038 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,9 @@ using System.IO;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenMetaverse.Assets;
|
||||
using OpenMetaverse.Http;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse.Messages.Linden;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
@@ -312,6 +315,11 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="newAssetID"></param>
|
||||
public delegate void BakedTextureUploadedCallback(UUID newAssetID);
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="upload"></param>
|
||||
public delegate void UploadProgressCallback(AssetUpload upload);
|
||||
/// <summary>
|
||||
@@ -709,6 +717,70 @@ namespace OpenMetaverse
|
||||
}
|
||||
}
|
||||
|
||||
public void RequestUploadBakedTexture(byte[] textureData, BakedTextureUploadedCallback callback)
|
||||
{
|
||||
Uri url = null;
|
||||
|
||||
Caps caps = Client.Network.CurrentSim.Caps;
|
||||
if (caps != null)
|
||||
url = caps.CapabilityURI("UploadBakedTexture");
|
||||
|
||||
if (url != null)
|
||||
{
|
||||
// Fetch the uploader capability
|
||||
CapsClient request = new CapsClient(url);
|
||||
request.OnComplete +=
|
||||
delegate(CapsClient client, OSD result, Exception error)
|
||||
{
|
||||
if (error == null && result is OSDMap)
|
||||
{
|
||||
UploadBakedTextureMessage message = new UploadBakedTextureMessage();
|
||||
message.Deserialize((OSDMap)result);
|
||||
|
||||
if (message.Request.State == "upload")
|
||||
{
|
||||
Uri uploadUrl = ((UploaderRequestUpload)message.Request).Url;
|
||||
|
||||
if (uploadUrl != null)
|
||||
{
|
||||
// POST the asset data
|
||||
CapsClient upload = new CapsClient(uploadUrl);
|
||||
upload.OnComplete +=
|
||||
delegate(CapsClient client2, OSD result2, Exception error2)
|
||||
{
|
||||
if (error2 == null && result2 is OSDMap)
|
||||
{
|
||||
UploadBakedTextureMessage message2 = new UploadBakedTextureMessage();
|
||||
message2.Deserialize((OSDMap)result2);
|
||||
|
||||
if (message2.Request.State == "complete")
|
||||
{
|
||||
callback(((UploaderRequestComplete)message2.Request).AssetID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Log("Bake upload failed during asset upload", Helpers.LogLevel.Warning, Client);
|
||||
callback(UUID.Zero);
|
||||
};
|
||||
upload.BeginGetResponse(textureData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Log("Bake upload failed during uploader retrieval", Helpers.LogLevel.Warning, Client);
|
||||
callback(UUID.Zero);
|
||||
};
|
||||
request.BeginGetResponse(new OSDMap(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("UploadBakedTexture not available, falling back to UDP method", Helpers.LogLevel.Info, Client);
|
||||
// FIXME:
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request a texture asset from the simulator using the <see cref="TexturePipeline"/> system to
|
||||
/// manage the requests and re-assemble the image from the packets received from the simulator
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace OpenMetaverse.Assets
|
||||
/// <summary>A Dictionary containing Key/Value pairs of the objects parameters</summary>
|
||||
public Dictionary<int, float> Params = new Dictionary<int, float>();
|
||||
/// <summary>A Dictionary containing Key/Value pairs where the Key is the textures Index and the Value is the Textures <seealso cref="UUID"/></summary>
|
||||
public Dictionary<AppearanceManager.TextureIndex, UUID> Textures = new Dictionary<AppearanceManager.TextureIndex, UUID>();
|
||||
public Dictionary<AvatarTextureIndex, UUID> Textures = new Dictionary<AvatarTextureIndex, UUID>();
|
||||
|
||||
/// <summary>Initializes a new instance of an AssetWearable object</summary>
|
||||
public AssetWearable() { }
|
||||
@@ -145,7 +145,7 @@ namespace OpenMetaverse.Assets
|
||||
line = lines[stri].Trim();
|
||||
fields = line.Split(' ');
|
||||
|
||||
AppearanceManager.TextureIndex id = (AppearanceManager.TextureIndex)Int32.Parse(fields[0]);
|
||||
AvatarTextureIndex id = (AvatarTextureIndex)Int32.Parse(fields[0]);
|
||||
UUID texture = new UUID(fields[1]);
|
||||
|
||||
Textures[id] = texture;
|
||||
@@ -249,7 +249,7 @@ namespace OpenMetaverse.Assets
|
||||
}
|
||||
|
||||
data.Append("textures "); data.Append(Textures.Count); data.Append(NL);
|
||||
foreach (KeyValuePair<AppearanceManager.TextureIndex, UUID> texture in Textures)
|
||||
foreach (KeyValuePair<AvatarTextureIndex, UUID> texture in Textures)
|
||||
{
|
||||
data.Append((byte)texture.Key); data.Append(" "); data.Append(texture.Value.ToString()); data.Append(NL);
|
||||
}
|
||||
|
||||
@@ -42,11 +42,11 @@ namespace OpenMetaverse.Imaging
|
||||
{
|
||||
public AssetTexture BakedTexture { get { return _bakedTexture; } }
|
||||
public Dictionary<int, float> ParamValues { get { return _paramValues; } }
|
||||
public Dictionary<AppearanceManager.TextureIndex, AssetTexture> Textures { get { return _textures; } }
|
||||
public Dictionary<AvatarTextureIndex, AssetTexture> Textures { get { return _textures; } }
|
||||
public int TextureCount { get { return _textureCount; } }
|
||||
public int BakeWidth { get { return _bakeWidth; } }
|
||||
public int BakeHeight { get { return _bakeHeight; } }
|
||||
public AppearanceManager.BakeType BakeType { get { return _bakeType; } }
|
||||
public BakeType BakeType { get { return _bakeType; } }
|
||||
|
||||
/// <summary>Reference to the GridClient object</summary>
|
||||
protected GridClient _client;
|
||||
@@ -55,7 +55,7 @@ namespace OpenMetaverse.Imaging
|
||||
/// <summary>Appearance parameters the drive the baking process</summary>
|
||||
protected Dictionary<int, float> _paramValues;
|
||||
/// <summary>Wearable textures</summary>
|
||||
protected Dictionary<AppearanceManager.TextureIndex, AssetTexture> _textures = new Dictionary<AppearanceManager.TextureIndex, AssetTexture>();
|
||||
protected Dictionary<AvatarTextureIndex, AssetTexture> _textures = new Dictionary<AvatarTextureIndex, AssetTexture>();
|
||||
/// <summary>Total number of textures in the bake</summary>
|
||||
protected int _textureCount;
|
||||
/// <summary>Width of the final baked image and scratchpad</summary>
|
||||
@@ -63,7 +63,7 @@ namespace OpenMetaverse.Imaging
|
||||
/// <summary>Height of the final baked image and scratchpad</summary>
|
||||
protected int _bakeHeight;
|
||||
/// <summary>Bake type</summary>
|
||||
protected AppearanceManager.BakeType _bakeType;
|
||||
protected BakeType _bakeType;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
@@ -74,13 +74,13 @@ namespace OpenMetaverse.Imaging
|
||||
/// composed of</param>
|
||||
/// <param name="paramValues">Appearance parameters the drive the
|
||||
/// baking process</param>
|
||||
public Baker(GridClient client, AppearanceManager.BakeType bakeType, int textureCount, Dictionary<int, float> paramValues)
|
||||
public Baker(GridClient client, BakeType bakeType, int textureCount, Dictionary<int, float> paramValues)
|
||||
{
|
||||
_client = client;
|
||||
_bakeType = bakeType;
|
||||
_textureCount = textureCount;
|
||||
|
||||
if (bakeType == AppearanceManager.BakeType.Eyes)
|
||||
if (bakeType == BakeType.Eyes)
|
||||
{
|
||||
_bakeWidth = 128;
|
||||
_bakeHeight = 128;
|
||||
@@ -108,7 +108,7 @@ namespace OpenMetaverse.Imaging
|
||||
/// called for the texture, otherwise false</param>
|
||||
/// <returns>True if this texture is completely baked and JPEG2000 data
|
||||
/// is available, otherwise false</returns>
|
||||
public bool AddTexture(AppearanceManager.TextureIndex index, AssetTexture texture, bool needsDecode)
|
||||
public bool AddTexture(AvatarTextureIndex index, AssetTexture texture, bool needsDecode)
|
||||
{
|
||||
lock (_textures)
|
||||
{
|
||||
@@ -140,7 +140,7 @@ namespace OpenMetaverse.Imaging
|
||||
}
|
||||
}
|
||||
|
||||
public bool MissingTexture(AppearanceManager.TextureIndex index)
|
||||
public bool MissingTexture(AvatarTextureIndex index)
|
||||
{
|
||||
Logger.DebugLog(String.Format("Missing texture {0} in bake {1}", index, _bakeType), _client);
|
||||
_textureCount--;
|
||||
@@ -161,18 +161,18 @@ namespace OpenMetaverse.Imaging
|
||||
_bakedTexture = new AssetTexture(new ManagedImage(_bakeWidth, _bakeHeight,
|
||||
ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump));
|
||||
|
||||
if (_bakeType == AppearanceManager.BakeType.Eyes)
|
||||
if (_bakeType == BakeType.Eyes)
|
||||
{
|
||||
InitBakedLayerColor(255, 255, 255);
|
||||
DrawLayer(AppearanceManager.TextureIndex.EyesIris);
|
||||
DrawLayer(AvatarTextureIndex.EyesIris);
|
||||
}
|
||||
else if (_bakeType == AppearanceManager.BakeType.Head)
|
||||
else if (_bakeType == BakeType.Head)
|
||||
{
|
||||
// FIXME: Need to use the visual parameters to determine the base skin color in RGB but
|
||||
// it's not apparent how to define RGB levels from the skin color parameters, so
|
||||
// for now use a grey foundation for the skin
|
||||
InitBakedLayerColor(128, 128, 128);
|
||||
DrawLayer(AppearanceManager.TextureIndex.HeadBodypaint);
|
||||
// for now use default color for the skin
|
||||
InitBakedLayerColor(226, 160, 125);
|
||||
DrawLayer(AvatarTextureIndex.HeadBodypaint);
|
||||
|
||||
// HACK: Bake the eyelashes in if we have them
|
||||
ManagedImage eyelashes = LoadAlphaLayer("head_alpha.tga");
|
||||
@@ -187,7 +187,7 @@ namespace OpenMetaverse.Imaging
|
||||
Logger.Log("head_alpha.tga resource not found, skipping eyelashes", Helpers.LogLevel.Info);
|
||||
}
|
||||
}
|
||||
else if (_bakeType == AppearanceManager.BakeType.Skirt)
|
||||
else if (_bakeType == BakeType.Skirt)
|
||||
{
|
||||
float skirtRed = 1.0f, skirtGreen = 1.0f, skirtBlue = 1.0f;
|
||||
|
||||
@@ -202,43 +202,44 @@ namespace OpenMetaverse.Imaging
|
||||
Logger.Log("Unable to determine skirt color from visual params", Helpers.LogLevel.Warning, _client);
|
||||
}
|
||||
|
||||
InitBakedLayerColor((byte)(skirtRed * 255.0f), (byte)(skirtGreen * 255.0f), (byte)(skirtBlue * 255.0f));
|
||||
DrawLayer(AppearanceManager.TextureIndex.Skirt);
|
||||
// FIXME: We should be drawing the skirt first, then tinting with the skirt color
|
||||
//InitBakedLayerColor((byte)(skirtRed * 255.0f), (byte)(skirtGreen * 255.0f), (byte)(skirtBlue * 255.0f));
|
||||
DrawLayer(AvatarTextureIndex.Skirt);
|
||||
}
|
||||
else if (_bakeType == AppearanceManager.BakeType.UpperBody)
|
||||
else if (_bakeType == BakeType.UpperBody)
|
||||
{
|
||||
InitBakedLayerColor(128, 128, 128);
|
||||
DrawLayer(AppearanceManager.TextureIndex.UpperBodypaint);
|
||||
DrawLayer(AppearanceManager.TextureIndex.UpperUndershirt);
|
||||
DrawLayer(AppearanceManager.TextureIndex.UpperGloves);
|
||||
DrawLayer(AppearanceManager.TextureIndex.UpperShirt);
|
||||
DrawLayer(AppearanceManager.TextureIndex.UpperJacket);
|
||||
InitBakedLayerColor(226, 160, 125);
|
||||
DrawLayer(AvatarTextureIndex.UpperBodypaint);
|
||||
DrawLayer(AvatarTextureIndex.UpperUndershirt);
|
||||
DrawLayer(AvatarTextureIndex.UpperGloves);
|
||||
DrawLayer(AvatarTextureIndex.UpperShirt);
|
||||
DrawLayer(AvatarTextureIndex.UpperJacket);
|
||||
}
|
||||
else if (_bakeType == AppearanceManager.BakeType.LowerBody)
|
||||
else if (_bakeType == BakeType.LowerBody)
|
||||
{
|
||||
InitBakedLayerColor(128, 128, 128);
|
||||
DrawLayer(AppearanceManager.TextureIndex.LowerBodypaint);
|
||||
DrawLayer(AppearanceManager.TextureIndex.LowerUnderpants);
|
||||
DrawLayer(AppearanceManager.TextureIndex.LowerSocks);
|
||||
DrawLayer(AppearanceManager.TextureIndex.LowerShoes);
|
||||
DrawLayer(AppearanceManager.TextureIndex.LowerPants);
|
||||
DrawLayer(AppearanceManager.TextureIndex.LowerJacket);
|
||||
InitBakedLayerColor(226, 160, 125);
|
||||
DrawLayer(AvatarTextureIndex.LowerBodypaint);
|
||||
DrawLayer(AvatarTextureIndex.LowerUnderpants);
|
||||
DrawLayer(AvatarTextureIndex.LowerSocks);
|
||||
DrawLayer(AvatarTextureIndex.LowerShoes);
|
||||
DrawLayer(AvatarTextureIndex.LowerPants);
|
||||
DrawLayer(AvatarTextureIndex.LowerJacket);
|
||||
}
|
||||
else if (_bakeType == AppearanceManager.BakeType.Hair)
|
||||
else if (_bakeType == BakeType.Hair)
|
||||
{
|
||||
InitBakedLayerColor(255, 255, 255);
|
||||
DrawLayer(AppearanceManager.TextureIndex.Hair);
|
||||
DrawLayer(AvatarTextureIndex.Hair);
|
||||
}
|
||||
|
||||
_bakedTexture.Encode();
|
||||
}
|
||||
|
||||
private bool DrawLayer(AppearanceManager.TextureIndex textureIndex)
|
||||
private bool DrawLayer(AvatarTextureIndex textureIndex)
|
||||
{
|
||||
AssetTexture texture;
|
||||
bool useSourceAlpha =
|
||||
(textureIndex == AppearanceManager.TextureIndex.HeadBodypaint ||
|
||||
textureIndex == AppearanceManager.TextureIndex.Skirt);
|
||||
(textureIndex == AvatarTextureIndex.HeadBodypaint ||
|
||||
textureIndex == AvatarTextureIndex.Skirt);
|
||||
|
||||
if (_textures.TryGetValue(textureIndex, out texture))
|
||||
return DrawLayer(texture.Image, useSourceAlpha);
|
||||
@@ -266,9 +267,8 @@ namespace OpenMetaverse.Imaging
|
||||
catch { return false; }
|
||||
}
|
||||
|
||||
int alpha = 255;
|
||||
//int alphaInv = 255 - alpha;
|
||||
int alphaInv = 256 - alpha;
|
||||
byte alpha = Byte.MaxValue;
|
||||
byte alphaInv = (byte)(Byte.MaxValue - alpha);
|
||||
|
||||
byte[] bakedRed = _bakedTexture.Image.Red;
|
||||
byte[] bakedGreen = _bakedTexture.Image.Green;
|
||||
@@ -279,14 +279,8 @@ namespace OpenMetaverse.Imaging
|
||||
byte[] sourceRed = source.Red;
|
||||
byte[] sourceGreen = source.Green;
|
||||
byte[] sourceBlue = source.Blue;
|
||||
byte[] sourceAlpha = null;
|
||||
byte[] sourceBump = null;
|
||||
|
||||
if (sourceHasAlpha)
|
||||
sourceAlpha = source.Alpha;
|
||||
|
||||
if (sourceHasBump)
|
||||
sourceBump = source.Bump;
|
||||
byte[] sourceAlpha = sourceHasAlpha ? source.Alpha : null;
|
||||
byte[] sourceBump = sourceHasBump ? source.Bump : null;
|
||||
|
||||
for (int y = 0; y < _bakeHeight; y++)
|
||||
{
|
||||
@@ -295,8 +289,7 @@ namespace OpenMetaverse.Imaging
|
||||
if (sourceHasAlpha)
|
||||
{
|
||||
alpha = sourceAlpha[i];
|
||||
//alphaInv = 255 - alpha;
|
||||
alphaInv = 256 - alpha;
|
||||
alphaInv = (byte)(Byte.MaxValue - alpha);
|
||||
}
|
||||
|
||||
if (sourceHasColor)
|
||||
@@ -340,15 +333,15 @@ namespace OpenMetaverse.Imaging
|
||||
gAlt = gByte;
|
||||
bAlt = bByte;
|
||||
|
||||
if (rByte < byte.MaxValue)
|
||||
if (rByte < Byte.MaxValue)
|
||||
rAlt++;
|
||||
else rAlt--;
|
||||
|
||||
if (gByte < byte.MaxValue)
|
||||
if (gByte < Byte.MaxValue)
|
||||
gAlt++;
|
||||
else gAlt--;
|
||||
|
||||
if (bByte < byte.MaxValue)
|
||||
if (bByte < Byte.MaxValue)
|
||||
bAlt++;
|
||||
else bAlt--;
|
||||
|
||||
@@ -369,7 +362,7 @@ namespace OpenMetaverse.Imaging
|
||||
red[i] = rAlt;
|
||||
green[i] = gByte;
|
||||
blue[i] = bByte;
|
||||
alpha[i] = 128;
|
||||
alpha[i] = Byte.MaxValue;
|
||||
bump[i] = 0;
|
||||
}
|
||||
else
|
||||
@@ -377,7 +370,7 @@ namespace OpenMetaverse.Imaging
|
||||
red[i] = rByte;
|
||||
green[i] = gAlt;
|
||||
blue[i] = bAlt;
|
||||
alpha[i] = 128;
|
||||
alpha[i] = Byte.MaxValue;
|
||||
bump[i] = 0;
|
||||
}
|
||||
|
||||
@@ -426,39 +419,39 @@ namespace OpenMetaverse.Imaging
|
||||
|
||||
}
|
||||
|
||||
public static AppearanceManager.BakeType BakeTypeFor(AppearanceManager.TextureIndex index)
|
||||
public static BakeType BakeTypeFor(AvatarTextureIndex index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case AppearanceManager.TextureIndex.HeadBodypaint:
|
||||
return AppearanceManager.BakeType.Head;
|
||||
case AvatarTextureIndex.HeadBodypaint:
|
||||
return BakeType.Head;
|
||||
|
||||
case AppearanceManager.TextureIndex.UpperBodypaint:
|
||||
case AppearanceManager.TextureIndex.UpperGloves:
|
||||
case AppearanceManager.TextureIndex.UpperUndershirt:
|
||||
case AppearanceManager.TextureIndex.UpperShirt:
|
||||
case AppearanceManager.TextureIndex.UpperJacket:
|
||||
return AppearanceManager.BakeType.UpperBody;
|
||||
case AvatarTextureIndex.UpperBodypaint:
|
||||
case AvatarTextureIndex.UpperGloves:
|
||||
case AvatarTextureIndex.UpperUndershirt:
|
||||
case AvatarTextureIndex.UpperShirt:
|
||||
case AvatarTextureIndex.UpperJacket:
|
||||
return BakeType.UpperBody;
|
||||
|
||||
case AppearanceManager.TextureIndex.LowerBodypaint:
|
||||
case AppearanceManager.TextureIndex.LowerUnderpants:
|
||||
case AppearanceManager.TextureIndex.LowerSocks:
|
||||
case AppearanceManager.TextureIndex.LowerShoes:
|
||||
case AppearanceManager.TextureIndex.LowerPants:
|
||||
case AppearanceManager.TextureIndex.LowerJacket:
|
||||
return AppearanceManager.BakeType.LowerBody;
|
||||
case AvatarTextureIndex.LowerBodypaint:
|
||||
case AvatarTextureIndex.LowerUnderpants:
|
||||
case AvatarTextureIndex.LowerSocks:
|
||||
case AvatarTextureIndex.LowerShoes:
|
||||
case AvatarTextureIndex.LowerPants:
|
||||
case AvatarTextureIndex.LowerJacket:
|
||||
return BakeType.LowerBody;
|
||||
|
||||
case AppearanceManager.TextureIndex.EyesIris:
|
||||
return AppearanceManager.BakeType.Eyes;
|
||||
case AvatarTextureIndex.EyesIris:
|
||||
return BakeType.Eyes;
|
||||
|
||||
case AppearanceManager.TextureIndex.Skirt:
|
||||
return AppearanceManager.BakeType.Skirt;
|
||||
case AvatarTextureIndex.Skirt:
|
||||
return BakeType.Skirt;
|
||||
|
||||
case AppearanceManager.TextureIndex.Hair:
|
||||
return AppearanceManager.BakeType.Hair;
|
||||
case AvatarTextureIndex.Hair:
|
||||
return BakeType.Hair;
|
||||
|
||||
default:
|
||||
return AppearanceManager.BakeType.Unknown;
|
||||
return BakeType.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1387,6 +1387,11 @@ namespace OpenMetaverse.Messages.Linden
|
||||
/// <summary>Base class for Asset uploads/results via Capabilities</summary>
|
||||
public abstract class AssetUploaderBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// The request state
|
||||
/// </summary>
|
||||
public string State;
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the object
|
||||
/// </summary>
|
||||
@@ -1406,23 +1411,26 @@ namespace OpenMetaverse.Messages.Linden
|
||||
/// </summary>
|
||||
public class UploaderRequestUpload : AssetUploaderBlock
|
||||
{
|
||||
/// <summary>The request state (Always "upload")</summary>
|
||||
public string State = "upload";
|
||||
/// <summary>The Capability URL sent by the simulator to upload the baked texture to</summary>
|
||||
public string Url;
|
||||
public Uri Url;
|
||||
|
||||
public UploaderRequestUpload()
|
||||
{
|
||||
State = "upload";
|
||||
}
|
||||
|
||||
public override OSDMap Serialize()
|
||||
{
|
||||
OSDMap map = new OSDMap(2);
|
||||
map["state"] = OSD.FromString(State);
|
||||
map["uploader"] = OSD.FromString(Url);
|
||||
map["uploader"] = OSD.FromUri(Url);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public override void Deserialize(OSDMap map)
|
||||
{
|
||||
Url = map["uploader"].AsString();
|
||||
Url = map["uploader"].AsUri();
|
||||
State = map["state"].AsString();
|
||||
}
|
||||
}
|
||||
@@ -1433,11 +1441,14 @@ namespace OpenMetaverse.Messages.Linden
|
||||
/// </summary>
|
||||
public class UploaderRequestComplete : AssetUploaderBlock
|
||||
{
|
||||
/// <summary>The request state (Always "complete")</summary>
|
||||
public string State = "complete";
|
||||
/// <summary>The uploaded texture asset ID</summary>
|
||||
public UUID AssetID;
|
||||
|
||||
public UploaderRequestComplete()
|
||||
{
|
||||
State = "complete";
|
||||
}
|
||||
|
||||
public override OSDMap Serialize()
|
||||
{
|
||||
OSDMap map = new OSDMap(2);
|
||||
@@ -1483,11 +1494,8 @@ namespace OpenMetaverse.Messages.Linden
|
||||
else if (map.ContainsKey("state") && map["state"].AsString().Equals("complete"))
|
||||
Request = new UploaderRequestComplete();
|
||||
else
|
||||
{
|
||||
Logger.Log("Unable to deserialize UploadBakedTexture: No message handler exists for state " + map["state"].AsString(), Helpers.LogLevel.Warning);
|
||||
|
||||
}
|
||||
|
||||
if (Request != null)
|
||||
Request.Deserialize(map);
|
||||
}
|
||||
|
||||
@@ -158,6 +158,10 @@ namespace OpenMetaverse
|
||||
/// <summary>Enable/disable sending periodic camera updates</summary>
|
||||
public bool SEND_AGENT_UPDATES = true;
|
||||
|
||||
/// <summary>Enable/disable automatically setting agent appearance at
|
||||
/// login and after sim crossing</summary>
|
||||
public bool SEND_AGENT_APPEARANCE = true;
|
||||
|
||||
/// <summary>Enable/disable automatically setting the bandwidth throttle
|
||||
/// after connecting to each simulator</summary>
|
||||
/// <remarks>The default throttle uses the equivalent of the maximum
|
||||
|
||||
@@ -35,15 +35,7 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
public static class Parallel
|
||||
{
|
||||
private static int threadCount = System.Environment.ProcessorCount;
|
||||
|
||||
/// <summary>The number of parallel threads to run tasks on. Defaults
|
||||
/// to the number of system processors</summary>
|
||||
public static int ThreadCount
|
||||
{
|
||||
get { return threadCount; }
|
||||
set { threadCount = Math.Max(1, value); }
|
||||
}
|
||||
private static readonly int processorCount = System.Environment.ProcessorCount;
|
||||
|
||||
/// <summary>
|
||||
/// Executes a for loop in which iterations may run in parallel
|
||||
@@ -52,6 +44,18 @@ namespace OpenMetaverse
|
||||
/// <param name="toExclusive">The loop will be terminated before this index is reached</param>
|
||||
/// <param name="body">Method body to run for each iteration of the loop</param>
|
||||
public static void For(int fromInclusive, int toExclusive, Action<int> body)
|
||||
{
|
||||
For(processorCount, fromInclusive, toExclusive, body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a for loop in which iterations may run in parallel
|
||||
/// </summary>
|
||||
/// <param name="threadCount">The number of concurrent execution threads to run</param>
|
||||
/// <param name="fromInclusive">The loop will be started at this index</param>
|
||||
/// <param name="toExclusive">The loop will be terminated before this index is reached</param>
|
||||
/// <param name="body">Method body to run for each iteration of the loop</param>
|
||||
public static void For(int threadCount, int fromInclusive, int toExclusive, Action<int> body)
|
||||
{
|
||||
AutoResetEvent[] threadFinishEvent = new AutoResetEvent[threadCount];
|
||||
--fromInclusive;
|
||||
@@ -67,12 +71,12 @@ namespace OpenMetaverse
|
||||
|
||||
while (true)
|
||||
{
|
||||
int index = Interlocked.Increment(ref fromInclusive);
|
||||
int currentIndex = Interlocked.Increment(ref fromInclusive);
|
||||
|
||||
if (index >= toExclusive)
|
||||
if (currentIndex >= toExclusive)
|
||||
break;
|
||||
|
||||
body(index);
|
||||
body(currentIndex);
|
||||
}
|
||||
|
||||
threadFinishEvent[threadIndex].Set();
|
||||
@@ -91,6 +95,18 @@ namespace OpenMetaverse
|
||||
/// <param name="enumerable">An enumerable collection to iterate over</param>
|
||||
/// <param name="body">Method body to run for each object in the collection</param>
|
||||
public static void ForEach<T>(IEnumerable<T> enumerable, Action<T> body)
|
||||
{
|
||||
ForEach<T>(processorCount, enumerable, body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a foreach loop in which iterations may run in parallel
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Object type that the collection wraps</typeparam>
|
||||
/// <param name="threadCount">The number of concurrent execution threads to run</param>
|
||||
/// <param name="enumerable">An enumerable collection to iterate over</param>
|
||||
/// <param name="body">Method body to run for each object in the collection</param>
|
||||
public static void ForEach<T>(int threadCount, IEnumerable<T> enumerable, Action<T> body)
|
||||
{
|
||||
AutoResetEvent[] threadFinishEvent = new AutoResetEvent[threadCount];
|
||||
IEnumerator<T> enumerator = enumerable.GetEnumerator();
|
||||
@@ -113,7 +129,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
if (!enumerator.MoveNext())
|
||||
break;
|
||||
entry = enumerator.Current;
|
||||
entry = (T)enumerator.Current; // Explicit typecast for Mono's sake
|
||||
}
|
||||
|
||||
body(entry);
|
||||
@@ -127,5 +143,52 @@ namespace OpenMetaverse
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
threadFinishEvent[i].WaitOne();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a series of tasks in parallel
|
||||
/// </summary>
|
||||
/// <param name="actions">A series of method bodies to execute</param>
|
||||
public static void Invoke(params Action[] actions)
|
||||
{
|
||||
Invoke(processorCount, actions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a series of tasks in parallel
|
||||
/// </summary>
|
||||
/// <param name="threadCount">The number of concurrent execution threads to run</param>
|
||||
/// <param name="actions">A series of method bodies to execute</param>
|
||||
public static void Invoke(int threadCount, params Action[] actions)
|
||||
{
|
||||
AutoResetEvent[] threadFinishEvent = new AutoResetEvent[threadCount];
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
{
|
||||
threadFinishEvent[i] = new AutoResetEvent(false);
|
||||
|
||||
ThreadPool.QueueUserWorkItem(
|
||||
delegate(object o)
|
||||
{
|
||||
int threadIndex = (int)o;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int currentIndex = Interlocked.Increment(ref index);
|
||||
|
||||
if (currentIndex >= actions.Length)
|
||||
break;
|
||||
|
||||
actions[currentIndex]();
|
||||
}
|
||||
|
||||
threadFinishEvent[threadIndex].Set();
|
||||
}, i
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
threadFinishEvent[i].WaitOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,30 +282,30 @@ namespace AvatarPreview
|
||||
#region Baking
|
||||
|
||||
Dictionary<int, float> paramValues = GetParamValues();
|
||||
Dictionary<AppearanceManager.TextureIndex, AssetTexture> layers =
|
||||
new Dictionary<AppearanceManager.TextureIndex, AssetTexture>();
|
||||
Dictionary<AvatarTextureIndex, AssetTexture> layers =
|
||||
new Dictionary<AvatarTextureIndex, AssetTexture>();
|
||||
int textureCount = 0;
|
||||
|
||||
if ((string)control.Tag == "Head")
|
||||
{
|
||||
if (picHair.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.Hair,
|
||||
layers.Add(AvatarTextureIndex.Hair,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picHair.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
if (picHeadBodypaint.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.HeadBodypaint,
|
||||
layers.Add(AvatarTextureIndex.HeadBodypaint,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picHeadBodypaint.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
|
||||
// Compute the head bake
|
||||
Baker baker = new Baker(
|
||||
_client, AppearanceManager.BakeType.Head, textureCount, paramValues);
|
||||
_client, BakeType.Head, textureCount, paramValues);
|
||||
|
||||
foreach (KeyValuePair<AppearanceManager.TextureIndex, AssetTexture> kvp in layers)
|
||||
foreach (KeyValuePair<AvatarTextureIndex, AssetTexture> kvp in layers)
|
||||
baker.AddTexture(kvp.Key, kvp.Value, false);
|
||||
|
||||
if (baker.BakedTexture != null)
|
||||
@@ -324,40 +324,40 @@ namespace AvatarPreview
|
||||
{
|
||||
if (picUpperBodypaint.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.UpperBodypaint,
|
||||
layers.Add(AvatarTextureIndex.UpperBodypaint,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picUpperBodypaint.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
if (picUpperGloves.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.UpperGloves,
|
||||
layers.Add(AvatarTextureIndex.UpperGloves,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picUpperGloves.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
if (picUpperUndershirt.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.UpperUndershirt,
|
||||
layers.Add(AvatarTextureIndex.UpperUndershirt,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picUpperUndershirt.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
if (picUpperShirt.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.UpperShirt,
|
||||
layers.Add(AvatarTextureIndex.UpperShirt,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picUpperShirt.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
if (picUpperJacket.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.UpperJacket,
|
||||
layers.Add(AvatarTextureIndex.UpperJacket,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picUpperJacket.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
|
||||
// Compute the upper body bake
|
||||
Baker baker = new Baker(
|
||||
_client, AppearanceManager.BakeType.UpperBody, textureCount, paramValues);
|
||||
_client, BakeType.UpperBody, textureCount, paramValues);
|
||||
|
||||
foreach (KeyValuePair<AppearanceManager.TextureIndex, AssetTexture> kvp in layers)
|
||||
foreach (KeyValuePair<AvatarTextureIndex, AssetTexture> kvp in layers)
|
||||
baker.AddTexture(kvp.Key, kvp.Value, false);
|
||||
|
||||
if (baker.BakedTexture != null)
|
||||
@@ -376,40 +376,40 @@ namespace AvatarPreview
|
||||
{
|
||||
if (picLowerBodypaint.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.LowerBodypaint,
|
||||
layers.Add(AvatarTextureIndex.LowerBodypaint,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picLowerBodypaint.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
if (picLowerUnderpants.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.LowerUnderpants,
|
||||
layers.Add(AvatarTextureIndex.LowerUnderpants,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picLowerUnderpants.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
if (picLowerSocks.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.LowerSocks,
|
||||
layers.Add(AvatarTextureIndex.LowerSocks,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picLowerSocks.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
if (picLowerShoes.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.LowerShoes,
|
||||
layers.Add(AvatarTextureIndex.LowerShoes,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picLowerShoes.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
if (picLowerPants.Image != null)
|
||||
{
|
||||
layers.Add(AppearanceManager.TextureIndex.LowerPants,
|
||||
layers.Add(AvatarTextureIndex.LowerPants,
|
||||
new AssetTexture(new ManagedImage((Bitmap)picLowerPants.Image)));
|
||||
++textureCount;
|
||||
}
|
||||
|
||||
// Compute the lower body bake
|
||||
Baker baker = new Baker(
|
||||
_client, AppearanceManager.BakeType.LowerBody, textureCount, paramValues);
|
||||
_client, BakeType.LowerBody, textureCount, paramValues);
|
||||
|
||||
foreach (KeyValuePair<AppearanceManager.TextureIndex, AssetTexture> kvp in layers)
|
||||
foreach (KeyValuePair<AvatarTextureIndex, AssetTexture> kvp in layers)
|
||||
baker.AddTexture(kvp.Key, kvp.Value, false);
|
||||
|
||||
if (baker.BakedTexture != null)
|
||||
|
||||
@@ -63,7 +63,6 @@ namespace Dashboard
|
||||
Client.Settings.USE_LLSD_LOGIN = true;
|
||||
Client.Settings.USE_ASSET_CACHE = true;
|
||||
|
||||
Client.Network.OnCurrentSimChanged += new NetworkManager.CurrentSimChangedCallback(Network_OnCurrentSimChanged);
|
||||
Client.Network.OnDisconnected += new NetworkManager.DisconnectedCallback(Network_OnDisconnected);
|
||||
Client.Self.OnInstantMessage += new AgentManager.InstantMessageCallback(Self_OnInstantMessage);
|
||||
|
||||
@@ -101,11 +100,6 @@ namespace Dashboard
|
||||
MessageBox.Show(group.Name + " = " + group.ID);
|
||||
}
|
||||
|
||||
void Network_OnCurrentSimChanged(Simulator PreviousSimulator)
|
||||
{
|
||||
Client.Appearance.SetPreviousAppearance(false);
|
||||
}
|
||||
|
||||
void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message)
|
||||
{
|
||||
InitializeClient(!ShuttingDown);
|
||||
|
||||
@@ -12,35 +12,14 @@ namespace OpenMetaverse.TestClient
|
||||
public AppearanceCommand(TestClient testClient)
|
||||
{
|
||||
Name = "appearance";
|
||||
Description = "Set your current appearance to your last saved appearance";
|
||||
Description = "Set your current appearance to your last saved appearance. Usage: appearance [rebake]";
|
||||
Category = CommandCategory.Appearance;
|
||||
}
|
||||
|
||||
public override string Execute(string[] args, UUID fromAgentID)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
// Register a handler for the appearance event
|
||||
AutoResetEvent appearanceEvent = new AutoResetEvent(false);
|
||||
AppearanceManager.AppearanceUpdatedCallback callback =
|
||||
delegate(Primitive.TextureEntry te) { appearanceEvent.Set(); };
|
||||
Client.Appearance.OnAppearanceUpdated += callback;
|
||||
|
||||
// Start the appearance setting process (with baking enabled or disabled)
|
||||
Client.Appearance.SetPreviousAppearance(!(args.Length > 0 && args[0].Equals("nobake")));
|
||||
|
||||
// Wait for the process to complete or time out
|
||||
if (appearanceEvent.WaitOne(1000 * 120, false))
|
||||
success = true;
|
||||
|
||||
// Unregister the handler
|
||||
Client.Appearance.OnAppearanceUpdated -= callback;
|
||||
|
||||
// Return success or failure message
|
||||
if (success)
|
||||
return "Successfully set appearance";
|
||||
else
|
||||
return "Timed out while setting appearance";
|
||||
Client.Appearance.RequestSetAppearance((args.Length > 0 && args[0].Equals("rebake")));
|
||||
return "Appearance sequence started";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace OpenMetaverse.TestClient.Commands.Appearance
|
||||
if (foundAv.Textures.FaceTextures[i] != null)
|
||||
{
|
||||
Primitive.TextureEntryFace face = foundAv.Textures.FaceTextures[i];
|
||||
AppearanceManager.TextureIndex type = (AppearanceManager.TextureIndex)i;
|
||||
AvatarTextureIndex type = (AvatarTextureIndex)i;
|
||||
|
||||
output.AppendFormat("{0}: {1}", type, face.TextureID);
|
||||
output.AppendLine();
|
||||
|
||||
@@ -31,16 +31,9 @@ namespace OpenMetaverse.TestClient
|
||||
|
||||
target = target.TrimEnd();
|
||||
|
||||
try
|
||||
{
|
||||
Client.Appearance.WearOutfit(target.Split('/'), bake);
|
||||
}
|
||||
catch (InvalidOutfitException ex)
|
||||
{
|
||||
return "Invalid outfit (" + ex.Message + ")";
|
||||
}
|
||||
//Client.Appearance.WearOutfit(target.Split('/'), bake);
|
||||
|
||||
return String.Empty;
|
||||
return "FIXME: Implement this";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,22 +31,19 @@ namespace OpenMetaverse.TestClient
|
||||
|
||||
// initialize results list
|
||||
List<InventoryBase> found = new List<InventoryBase>();
|
||||
try
|
||||
|
||||
// find the folder
|
||||
found = Client.Inventory.LocalFind(Client.Inventory.Store.RootFolder.UUID, target.Split('/'), 0, true);
|
||||
|
||||
if (found.Count.Equals(1))
|
||||
{
|
||||
// find the folder
|
||||
found = Client.Inventory.LocalFind(Client.Inventory.Store.RootFolder.UUID, target.Split('/'), 0, true);
|
||||
if (found.Count.Equals(1))
|
||||
{
|
||||
// move the folder to the trash folder
|
||||
Client.Inventory.MoveFolder(found[0].UUID, Client.Inventory.FindFolderForType(AssetType.TrashFolder));
|
||||
return String.Format("Moved folder {0} to Trash", found[0].Name);
|
||||
}
|
||||
// move the folder to the trash folder
|
||||
Client.Inventory.MoveFolder(found[0].UUID, Client.Inventory.FindFolderForType(AssetType.TrashFolder));
|
||||
|
||||
return String.Format("Moved folder {0} to Trash", found[0].Name);
|
||||
}
|
||||
catch (InvalidOutfitException ex)
|
||||
{
|
||||
return "Folder Not Found: (" + ex.Message + ")";
|
||||
}
|
||||
return string.Empty;
|
||||
|
||||
return String.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,20 +55,20 @@ namespace OpenMetaverse.TestClient
|
||||
{
|
||||
ImageType type = ImageType.Normal;
|
||||
|
||||
switch ((AppearanceManager.TextureIndex)j)
|
||||
switch ((AvatarTextureIndex)j)
|
||||
{
|
||||
case AppearanceManager.TextureIndex.HeadBaked:
|
||||
case AppearanceManager.TextureIndex.EyesBaked:
|
||||
case AppearanceManager.TextureIndex.UpperBaked:
|
||||
case AppearanceManager.TextureIndex.LowerBaked:
|
||||
case AppearanceManager.TextureIndex.SkirtBaked:
|
||||
case AvatarTextureIndex.HeadBaked:
|
||||
case AvatarTextureIndex.EyesBaked:
|
||||
case AvatarTextureIndex.UpperBaked:
|
||||
case AvatarTextureIndex.LowerBaked:
|
||||
case AvatarTextureIndex.SkirtBaked:
|
||||
type = ImageType.Baked;
|
||||
break;
|
||||
}
|
||||
|
||||
OutfitAssets.Add(face.TextureID);
|
||||
Client.Assets.RequestImage(face.TextureID, type, Assets_OnImageReceived);
|
||||
output.Append(((AppearanceManager.TextureIndex)j).ToString());
|
||||
output.Append(((AvatarTextureIndex)j).ToString());
|
||||
output.Append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,14 +60,14 @@ namespace OpenMetaverse.TestClient
|
||||
|
||||
// Determine if this is a baked outfit texture or a normal texture
|
||||
ImageType type = ImageType.Normal;
|
||||
AppearanceManager.TextureIndex index = (AppearanceManager.TextureIndex)i;
|
||||
AvatarTextureIndex index = (AvatarTextureIndex)i;
|
||||
switch (index)
|
||||
{
|
||||
case AppearanceManager.TextureIndex.EyesBaked:
|
||||
case AppearanceManager.TextureIndex.HeadBaked:
|
||||
case AppearanceManager.TextureIndex.LowerBaked:
|
||||
case AppearanceManager.TextureIndex.SkirtBaked:
|
||||
case AppearanceManager.TextureIndex.UpperBaked:
|
||||
case AvatarTextureIndex.EyesBaked:
|
||||
case AvatarTextureIndex.HeadBaked:
|
||||
case AvatarTextureIndex.LowerBaked:
|
||||
case AvatarTextureIndex.SkirtBaked:
|
||||
case AvatarTextureIndex.UpperBaked:
|
||||
type = ImageType.Baked;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user