2007-04-28 20:54:02 +00:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Threading;
|
2008-07-21 21:12:59 +00:00
|
|
|
using OpenMetaverse;
|
|
|
|
|
using OpenMetaverse.StructuredData;
|
2009-05-12 00:07:35 +00:00
|
|
|
using OpenMetaverse.Assets;
|
2007-04-28 20:54:02 +00:00
|
|
|
|
2008-07-21 21:12:59 +00:00
|
|
|
namespace OpenMetaverse.TestClient
|
2007-04-28 20:54:02 +00:00
|
|
|
{
|
|
|
|
|
public class ExportCommand : Command
|
|
|
|
|
{
|
2008-07-25 05:15:05 +00:00
|
|
|
List<UUID> Textures = new List<UUID>();
|
2007-04-28 20:54:02 +00:00
|
|
|
AutoResetEvent GotPermissionsEvent = new AutoResetEvent(false);
|
2008-08-24 05:06:51 +00:00
|
|
|
Primitive.ObjectProperties Properties;
|
2007-04-28 20:54:02 +00:00
|
|
|
bool GotPermissions = false;
|
2008-07-25 05:15:05 +00:00
|
|
|
UUID SelectedObject = UUID.Zero;
|
2007-04-28 20:54:02 +00:00
|
|
|
|
2008-07-25 05:15:05 +00:00
|
|
|
Dictionary<UUID, Primitive> PrimsWaiting = new Dictionary<UUID, Primitive>();
|
2007-04-28 20:54:02 +00:00
|
|
|
AutoResetEvent AllPropertiesReceived = new AutoResetEvent(false);
|
|
|
|
|
|
|
|
|
|
public ExportCommand(TestClient testClient)
|
|
|
|
|
{
|
|
|
|
|
testClient.Objects.OnObjectPropertiesFamily += new ObjectManager.ObjectPropertiesFamilyCallback(Objects_OnObjectPropertiesFamily);
|
|
|
|
|
testClient.Objects.OnObjectProperties += new ObjectManager.ObjectPropertiesCallback(Objects_OnObjectProperties);
|
2009-10-22 04:29:25 +00:00
|
|
|
testClient.Avatars.ViewerEffectPointAt += new EventHandler<ViewerEffectPointAtEventArgs>(Avatars_ViewerEffectPointAt);
|
2007-04-28 20:54:02 +00:00
|
|
|
|
|
|
|
|
Name = "export";
|
|
|
|
|
Description = "Exports an object to an xml file. Usage: export uuid outputfile.xml";
|
2008-07-25 08:55:36 +00:00
|
|
|
Category = CommandCategory.Objects;
|
2007-04-28 20:54:02 +00:00
|
|
|
}
|
|
|
|
|
|
2009-10-22 04:29:25 +00:00
|
|
|
void Avatars_ViewerEffectPointAt(object sender, ViewerEffectPointAtEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (e.SourceID == Client.MasterKey)
|
|
|
|
|
{
|
|
|
|
|
//Client.DebugLog("Master is now selecting " + targetID.ToString());
|
|
|
|
|
SelectedObject = e.TargetID;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-25 05:15:05 +00:00
|
|
|
public override string Execute(string[] args, UUID fromAgentID)
|
2007-04-28 20:54:02 +00:00
|
|
|
{
|
2008-07-25 05:15:05 +00:00
|
|
|
if (args.Length != 2 && !(args.Length == 1 && SelectedObject != UUID.Zero))
|
2007-04-28 20:54:02 +00:00
|
|
|
return "Usage: export uuid outputfile.xml";
|
|
|
|
|
|
2008-07-25 05:15:05 +00:00
|
|
|
UUID id;
|
2007-08-29 08:55:53 +00:00
|
|
|
uint localid;
|
2007-04-28 20:54:02 +00:00
|
|
|
string file;
|
|
|
|
|
|
|
|
|
|
if (args.Length == 2)
|
|
|
|
|
{
|
|
|
|
|
file = args[1];
|
2008-07-25 05:15:05 +00:00
|
|
|
if (!UUID.TryParse(args[0], out id))
|
2007-04-28 20:54:02 +00:00
|
|
|
return "Usage: export uuid outputfile.xml";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
file = args[0];
|
|
|
|
|
id = SelectedObject;
|
|
|
|
|
}
|
2007-08-20 09:26:21 +00:00
|
|
|
|
2007-08-29 08:55:53 +00:00
|
|
|
Primitive exportPrim;
|
2007-04-28 20:54:02 +00:00
|
|
|
|
2008-01-03 21:55:49 +00:00
|
|
|
exportPrim = Client.Network.CurrentSim.ObjectsPrimitives.Find(
|
2007-11-30 03:55:08 +00:00
|
|
|
delegate(Primitive prim) { return prim.ID == id; }
|
2007-08-29 08:55:53 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (exportPrim != null)
|
2007-04-28 20:54:02 +00:00
|
|
|
{
|
2007-08-29 08:55:53 +00:00
|
|
|
if (exportPrim.ParentID != 0)
|
|
|
|
|
localid = exportPrim.ParentID;
|
|
|
|
|
else
|
|
|
|
|
localid = exportPrim.LocalID;
|
|
|
|
|
|
2007-04-28 20:54:02 +00:00
|
|
|
// Check for export permission first
|
|
|
|
|
Client.Objects.RequestObjectPropertiesFamily(Client.Network.CurrentSim, id);
|
2007-08-29 08:55:53 +00:00
|
|
|
GotPermissionsEvent.WaitOne(1000 * 10, false);
|
2007-04-28 20:54:02 +00:00
|
|
|
|
|
|
|
|
if (!GotPermissions)
|
|
|
|
|
{
|
|
|
|
|
return "Couldn't fetch permissions for the requested object, try again";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GotPermissions = false;
|
2007-11-06 09:26:10 +00:00
|
|
|
if (Properties.OwnerID != Client.Self.AgentID &&
|
2007-04-28 20:54:02 +00:00
|
|
|
Properties.OwnerID != Client.MasterKey &&
|
2007-11-06 09:26:10 +00:00
|
|
|
Client.Self.AgentID != Client.Self.AgentID)
|
2007-04-28 20:54:02 +00:00
|
|
|
{
|
|
|
|
|
return "That object is owned by " + Properties.OwnerID + ", we don't have permission " +
|
|
|
|
|
"to export it";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-03 21:55:49 +00:00
|
|
|
List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll(
|
2007-11-30 03:55:08 +00:00
|
|
|
delegate(Primitive prim)
|
2007-04-28 20:54:02 +00:00
|
|
|
{
|
2007-11-30 03:55:08 +00:00
|
|
|
return (prim.LocalID == localid || prim.ParentID == localid);
|
2007-04-28 20:54:02 +00:00
|
|
|
}
|
2007-11-30 03:55:08 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
bool complete = RequestObjectProperties(prims, 250);
|
|
|
|
|
|
|
|
|
|
if (!complete)
|
|
|
|
|
{
|
2008-05-06 23:57:26 +00:00
|
|
|
Logger.Log("Warning: Unable to retrieve full properties for:", Helpers.LogLevel.Warning, Client);
|
2008-07-25 05:15:05 +00:00
|
|
|
foreach (UUID uuid in PrimsWaiting.Keys)
|
2008-05-06 23:57:26 +00:00
|
|
|
Logger.Log(uuid.ToString(), Helpers.LogLevel.Warning, Client);
|
2007-04-28 20:54:02 +00:00
|
|
|
}
|
2007-11-30 03:55:08 +00:00
|
|
|
|
2009-10-07 03:47:02 +00:00
|
|
|
string output = OSDParser.SerializeLLSDXmlString(Helpers.PrimListToOSD(prims));
|
2007-11-30 03:55:08 +00:00
|
|
|
try { File.WriteAllText(file, output); }
|
|
|
|
|
catch (Exception e) { return e.Message; }
|
|
|
|
|
|
2008-05-06 23:57:26 +00:00
|
|
|
Logger.Log("Exported " + prims.Count + " prims to " + file, Helpers.LogLevel.Info, Client);
|
2008-01-03 21:55:49 +00:00
|
|
|
|
|
|
|
|
// Create a list of all of the textures to download
|
2008-01-17 08:08:54 +00:00
|
|
|
List<ImageRequest> textureRequests = new List<ImageRequest>();
|
|
|
|
|
|
|
|
|
|
lock (Textures)
|
2008-01-03 21:55:49 +00:00
|
|
|
{
|
2008-01-17 08:08:54 +00:00
|
|
|
for (int i = 0; i < prims.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
Primitive prim = prims[i];
|
2008-01-03 21:55:49 +00:00
|
|
|
|
2008-08-24 05:06:51 +00:00
|
|
|
if (prim.Textures.DefaultTexture.TextureID != Primitive.TextureEntry.WHITE_TEXTURE &&
|
2008-04-10 19:57:27 +00:00
|
|
|
!Textures.Contains(prim.Textures.DefaultTexture.TextureID))
|
|
|
|
|
{
|
2008-01-17 08:08:54 +00:00
|
|
|
Textures.Add(prim.Textures.DefaultTexture.TextureID);
|
2008-04-10 19:57:27 +00:00
|
|
|
}
|
2008-01-03 21:55:49 +00:00
|
|
|
|
2008-01-17 08:08:54 +00:00
|
|
|
for (int j = 0; j < prim.Textures.FaceTextures.Length; j++)
|
|
|
|
|
{
|
2008-04-10 19:57:27 +00:00
|
|
|
if (prim.Textures.FaceTextures[j] != null &&
|
2008-08-24 05:06:51 +00:00
|
|
|
prim.Textures.FaceTextures[j].TextureID != Primitive.TextureEntry.WHITE_TEXTURE &&
|
2008-04-10 19:57:27 +00:00
|
|
|
!Textures.Contains(prim.Textures.FaceTextures[j].TextureID))
|
|
|
|
|
{
|
2008-01-17 08:08:54 +00:00
|
|
|
Textures.Add(prim.Textures.FaceTextures[j].TextureID);
|
2008-04-10 19:57:27 +00:00
|
|
|
}
|
2008-01-17 08:08:54 +00:00
|
|
|
}
|
2008-04-07 14:37:18 +00:00
|
|
|
|
2009-01-05 18:01:37 +00:00
|
|
|
if (prim.Sculpt != null && prim.Sculpt.SculptTexture != UUID.Zero && !Textures.Contains(prim.Sculpt.SculptTexture))
|
|
|
|
|
{
|
2008-04-07 14:37:18 +00:00
|
|
|
Textures.Add(prim.Sculpt.SculptTexture);
|
|
|
|
|
}
|
2008-01-03 21:55:49 +00:00
|
|
|
}
|
2008-01-17 08:08:54 +00:00
|
|
|
|
|
|
|
|
// Create a request list from all of the images
|
|
|
|
|
for (int i = 0; i < Textures.Count; i++)
|
|
|
|
|
textureRequests.Add(new ImageRequest(Textures[i], ImageType.Normal, 1013000.0f, 0));
|
2008-01-03 21:55:49 +00:00
|
|
|
}
|
|
|
|
|
|
2008-01-17 08:08:54 +00:00
|
|
|
// Download all of the textures in the export list
|
2009-05-07 16:10:52 +00:00
|
|
|
foreach (ImageRequest request in textureRequests)
|
|
|
|
|
{
|
|
|
|
|
Client.Assets.RequestImage(request.ImageID, request.Type, Assets_OnImageReceived);
|
|
|
|
|
}
|
2008-01-17 08:08:54 +00:00
|
|
|
|
|
|
|
|
return "XML exported, began downloading " + Textures.Count + " textures";
|
2007-04-28 20:54:02 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return "Couldn't find UUID " + id.ToString() + " in the " +
|
2008-01-03 21:55:49 +00:00
|
|
|
Client.Network.CurrentSim.ObjectsPrimitives.Count +
|
2007-04-28 20:54:02 +00:00
|
|
|
"objects currently indexed in the current simulator";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool RequestObjectProperties(List<Primitive> objects, int msPerRequest)
|
|
|
|
|
{
|
|
|
|
|
// Create an array of the local IDs of all the prims we are requesting properties for
|
|
|
|
|
uint[] localids = new uint[objects.Count];
|
|
|
|
|
|
|
|
|
|
lock (PrimsWaiting)
|
|
|
|
|
{
|
|
|
|
|
PrimsWaiting.Clear();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < objects.Count; ++i)
|
|
|
|
|
{
|
|
|
|
|
localids[i] = objects[i].LocalID;
|
|
|
|
|
PrimsWaiting.Add(objects[i].ID, objects[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Client.Objects.SelectObjects(Client.Network.CurrentSim, localids);
|
|
|
|
|
|
|
|
|
|
return AllPropertiesReceived.WaitOne(2000 + msPerRequest * objects.Count, false);
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-07 16:10:52 +00:00
|
|
|
private void Assets_OnImageReceived(TextureRequestState state, AssetTexture asset)
|
2008-01-17 08:08:54 +00:00
|
|
|
{
|
2009-05-07 16:10:52 +00:00
|
|
|
|
|
|
|
|
if (state == TextureRequestState.Finished && Textures.Contains(asset.AssetID))
|
2008-01-17 08:08:54 +00:00
|
|
|
{
|
|
|
|
|
lock (Textures)
|
2009-05-07 16:10:52 +00:00
|
|
|
Textures.Remove(asset.AssetID);
|
2008-01-17 08:08:54 +00:00
|
|
|
|
2009-05-07 16:10:52 +00:00
|
|
|
if (state == TextureRequestState.Finished)
|
2008-01-17 08:08:54 +00:00
|
|
|
{
|
2009-05-07 16:10:52 +00:00
|
|
|
try { File.WriteAllBytes(asset.AssetID + ".jp2", asset.AssetData); }
|
2008-05-06 23:57:26 +00:00
|
|
|
catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); }
|
2008-01-17 08:08:54 +00:00
|
|
|
|
|
|
|
|
if (asset.Decode())
|
|
|
|
|
{
|
2009-05-07 16:10:52 +00:00
|
|
|
try { File.WriteAllBytes(asset.AssetID + ".tga", asset.Image.ExportTGA()); }
|
2008-05-06 23:57:26 +00:00
|
|
|
catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); }
|
2008-01-17 08:08:54 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-05-07 16:10:52 +00:00
|
|
|
Logger.Log("Failed to decode image " + asset.AssetID, Helpers.LogLevel.Error, Client);
|
2008-01-17 08:08:54 +00:00
|
|
|
}
|
|
|
|
|
|
2009-05-07 16:10:52 +00:00
|
|
|
Logger.Log("Finished downloading image " + asset.AssetID, Helpers.LogLevel.Info, Client);
|
2008-01-17 08:08:54 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-05-07 16:10:52 +00:00
|
|
|
Logger.Log("Failed to download image " + asset.AssetID + ":" + state, Helpers.LogLevel.Warning, Client);
|
2008-01-17 08:08:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-24 05:06:51 +00:00
|
|
|
void Objects_OnObjectPropertiesFamily(Simulator simulator, Primitive.ObjectProperties properties,
|
2008-08-28 02:38:32 +00:00
|
|
|
ReportType type)
|
2007-04-28 20:54:02 +00:00
|
|
|
{
|
2009-01-05 18:01:37 +00:00
|
|
|
Properties = new Primitive.ObjectProperties();
|
2008-08-24 05:06:51 +00:00
|
|
|
Properties.SetFamilyProperties(properties);
|
2007-04-28 20:54:02 +00:00
|
|
|
GotPermissions = true;
|
|
|
|
|
GotPermissionsEvent.Set();
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-24 05:06:51 +00:00
|
|
|
void Objects_OnObjectProperties(Simulator simulator, Primitive.ObjectProperties properties)
|
2007-04-28 20:54:02 +00:00
|
|
|
{
|
|
|
|
|
lock (PrimsWaiting)
|
|
|
|
|
{
|
|
|
|
|
PrimsWaiting.Remove(properties.ObjectID);
|
|
|
|
|
|
|
|
|
|
if (PrimsWaiting.Count == 0)
|
|
|
|
|
AllPropertiesReceived.Set();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|