corrade-vassal – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | using System; |
2 | using System.Collections.Generic; |
||
3 | using System.IO; |
||
4 | using System.Threading; |
||
5 | using OpenMetaverse; |
||
6 | using OpenMetaverse.StructuredData; |
||
7 | using OpenMetaverse.Assets; |
||
8 | |||
9 | namespace OpenMetaverse.TestClient |
||
10 | { |
||
11 | public class ExportCommand : Command |
||
12 | { |
||
13 | List<UUID> Textures = new List<UUID>(); |
||
14 | AutoResetEvent GotPermissionsEvent = new AutoResetEvent(false); |
||
15 | Primitive.ObjectProperties Properties; |
||
16 | bool GotPermissions = false; |
||
17 | UUID SelectedObject = UUID.Zero; |
||
18 | |||
19 | Dictionary<UUID, Primitive> PrimsWaiting = new Dictionary<UUID, Primitive>(); |
||
20 | AutoResetEvent AllPropertiesReceived = new AutoResetEvent(false); |
||
21 | |||
22 | public ExportCommand(TestClient testClient) |
||
23 | { |
||
24 | testClient.Objects.ObjectPropertiesFamily += new EventHandler<ObjectPropertiesFamilyEventArgs>(Objects_OnObjectPropertiesFamily); |
||
25 | |||
26 | testClient.Objects.ObjectProperties += new EventHandler<ObjectPropertiesEventArgs>(Objects_OnObjectProperties); |
||
27 | testClient.Avatars.ViewerEffectPointAt += new EventHandler<ViewerEffectPointAtEventArgs>(Avatars_ViewerEffectPointAt); |
||
28 | |||
29 | Name = "export"; |
||
30 | Description = "Exports an object to an xml file. Usage: export uuid outputfile.xml"; |
||
31 | Category = CommandCategory.Objects; |
||
32 | } |
||
33 | |||
34 | void Avatars_ViewerEffectPointAt(object sender, ViewerEffectPointAtEventArgs e) |
||
35 | { |
||
36 | if (e.SourceID == Client.MasterKey) |
||
37 | { |
||
38 | //Client.DebugLog("Master is now selecting " + targetID.ToString()); |
||
39 | SelectedObject = e.TargetID; |
||
40 | } |
||
41 | } |
||
42 | |||
43 | public override string Execute(string[] args, UUID fromAgentID) |
||
44 | { |
||
45 | if (args.Length != 2 && !(args.Length == 1 && SelectedObject != UUID.Zero)) |
||
46 | return "Usage: export uuid outputfile.xml"; |
||
47 | |||
48 | UUID id; |
||
49 | uint localid; |
||
50 | string file; |
||
51 | |||
52 | if (args.Length == 2) |
||
53 | { |
||
54 | file = args[1]; |
||
55 | if (!UUID.TryParse(args[0], out id)) |
||
56 | return "Usage: export uuid outputfile.xml"; |
||
57 | } |
||
58 | else |
||
59 | { |
||
60 | file = args[0]; |
||
61 | id = SelectedObject; |
||
62 | } |
||
63 | |||
64 | Primitive exportPrim; |
||
65 | |||
66 | exportPrim = Client.Network.CurrentSim.ObjectsPrimitives.Find( |
||
67 | delegate(Primitive prim) { return prim.ID == id; } |
||
68 | ); |
||
69 | |||
70 | if (exportPrim != null) |
||
71 | { |
||
72 | if (exportPrim.ParentID != 0) |
||
73 | localid = exportPrim.ParentID; |
||
74 | else |
||
75 | localid = exportPrim.LocalID; |
||
76 | |||
77 | // Check for export permission first |
||
78 | Client.Objects.RequestObjectPropertiesFamily(Client.Network.CurrentSim, id); |
||
79 | GotPermissionsEvent.WaitOne(1000 * 10, false); |
||
80 | |||
81 | if (!GotPermissions) |
||
82 | { |
||
83 | return "Couldn't fetch permissions for the requested object, try again"; |
||
84 | } |
||
85 | else |
||
86 | { |
||
87 | GotPermissions = false; |
||
88 | if (Properties.OwnerID != Client.Self.AgentID && |
||
89 | Properties.OwnerID != Client.MasterKey && |
||
90 | Client.Self.AgentID != Client.Self.AgentID) |
||
91 | { |
||
92 | return "That object is owned by " + Properties.OwnerID + ", we don't have permission " + |
||
93 | "to export it"; |
||
94 | } |
||
95 | } |
||
96 | |||
97 | List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( |
||
98 | delegate(Primitive prim) |
||
99 | { |
||
100 | return (prim.LocalID == localid || prim.ParentID == localid); |
||
101 | } |
||
102 | ); |
||
103 | |||
104 | bool complete = RequestObjectProperties(prims, 250); |
||
105 | |||
106 | if (!complete) |
||
107 | { |
||
108 | Logger.Log("Warning: Unable to retrieve full properties for:", Helpers.LogLevel.Warning, Client); |
||
109 | foreach (UUID uuid in PrimsWaiting.Keys) |
||
110 | Logger.Log(uuid.ToString(), Helpers.LogLevel.Warning, Client); |
||
111 | } |
||
112 | |||
113 | string output = OSDParser.SerializeLLSDXmlString(Helpers.PrimListToOSD(prims)); |
||
114 | try { File.WriteAllText(file, output); } |
||
115 | catch (Exception e) { return e.Message; } |
||
116 | |||
117 | Logger.Log("Exported " + prims.Count + " prims to " + file, Helpers.LogLevel.Info, Client); |
||
118 | |||
119 | // Create a list of all of the textures to download |
||
120 | List<ImageRequest> textureRequests = new List<ImageRequest>(); |
||
121 | |||
122 | lock (Textures) |
||
123 | { |
||
124 | for (int i = 0; i < prims.Count; i++) |
||
125 | { |
||
126 | Primitive prim = prims[i]; |
||
127 | |||
128 | if (prim.Textures.DefaultTexture.TextureID != Primitive.TextureEntry.WHITE_TEXTURE && |
||
129 | !Textures.Contains(prim.Textures.DefaultTexture.TextureID)) |
||
130 | { |
||
131 | Textures.Add(prim.Textures.DefaultTexture.TextureID); |
||
132 | } |
||
133 | |||
134 | for (int j = 0; j < prim.Textures.FaceTextures.Length; j++) |
||
135 | { |
||
136 | if (prim.Textures.FaceTextures[j] != null && |
||
137 | prim.Textures.FaceTextures[j].TextureID != Primitive.TextureEntry.WHITE_TEXTURE && |
||
138 | !Textures.Contains(prim.Textures.FaceTextures[j].TextureID)) |
||
139 | { |
||
140 | Textures.Add(prim.Textures.FaceTextures[j].TextureID); |
||
141 | } |
||
142 | } |
||
143 | |||
144 | if (prim.Sculpt != null && prim.Sculpt.SculptTexture != UUID.Zero && !Textures.Contains(prim.Sculpt.SculptTexture)) |
||
145 | { |
||
146 | Textures.Add(prim.Sculpt.SculptTexture); |
||
147 | } |
||
148 | } |
||
149 | |||
150 | // Create a request list from all of the images |
||
151 | for (int i = 0; i < Textures.Count; i++) |
||
152 | textureRequests.Add(new ImageRequest(Textures[i], ImageType.Normal, 1013000.0f, 0)); |
||
153 | } |
||
154 | |||
155 | // Download all of the textures in the export list |
||
156 | foreach (ImageRequest request in textureRequests) |
||
157 | { |
||
158 | Client.Assets.RequestImage(request.ImageID, request.Type, Assets_OnImageReceived); |
||
159 | } |
||
160 | |||
161 | return "XML exported, began downloading " + Textures.Count + " textures"; |
||
162 | } |
||
163 | else |
||
164 | { |
||
165 | return "Couldn't find UUID " + id.ToString() + " in the " + |
||
166 | Client.Network.CurrentSim.ObjectsPrimitives.Count + |
||
167 | "objects currently indexed in the current simulator"; |
||
168 | } |
||
169 | } |
||
170 | |||
171 | private bool RequestObjectProperties(List<Primitive> objects, int msPerRequest) |
||
172 | { |
||
173 | // Create an array of the local IDs of all the prims we are requesting properties for |
||
174 | uint[] localids = new uint[objects.Count]; |
||
175 | |||
176 | lock (PrimsWaiting) |
||
177 | { |
||
178 | PrimsWaiting.Clear(); |
||
179 | |||
180 | for (int i = 0; i < objects.Count; ++i) |
||
181 | { |
||
182 | localids[i] = objects[i].LocalID; |
||
183 | PrimsWaiting.Add(objects[i].ID, objects[i]); |
||
184 | } |
||
185 | } |
||
186 | |||
187 | Client.Objects.SelectObjects(Client.Network.CurrentSim, localids); |
||
188 | |||
189 | return AllPropertiesReceived.WaitOne(2000 + msPerRequest * objects.Count, false); |
||
190 | } |
||
191 | |||
192 | private void Assets_OnImageReceived(TextureRequestState state, AssetTexture asset) |
||
193 | { |
||
194 | |||
195 | if (state == TextureRequestState.Finished && Textures.Contains(asset.AssetID)) |
||
196 | { |
||
197 | lock (Textures) |
||
198 | Textures.Remove(asset.AssetID); |
||
199 | |||
200 | if (state == TextureRequestState.Finished) |
||
201 | { |
||
202 | try { File.WriteAllBytes(asset.AssetID + ".jp2", asset.AssetData); } |
||
203 | catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); } |
||
204 | |||
205 | if (asset.Decode()) |
||
206 | { |
||
207 | try { File.WriteAllBytes(asset.AssetID + ".tga", asset.Image.ExportTGA()); } |
||
208 | catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); } |
||
209 | } |
||
210 | else |
||
211 | { |
||
212 | Logger.Log("Failed to decode image " + asset.AssetID, Helpers.LogLevel.Error, Client); |
||
213 | } |
||
214 | |||
215 | Logger.Log("Finished downloading image " + asset.AssetID, Helpers.LogLevel.Info, Client); |
||
216 | } |
||
217 | else |
||
218 | { |
||
219 | Logger.Log("Failed to download image " + asset.AssetID + ":" + state, Helpers.LogLevel.Warning, Client); |
||
220 | } |
||
221 | } |
||
222 | } |
||
223 | |||
224 | void Objects_OnObjectPropertiesFamily(object sender, ObjectPropertiesFamilyEventArgs e) |
||
225 | { |
||
226 | Properties = new Primitive.ObjectProperties(); |
||
227 | Properties.SetFamilyProperties(e.Properties); |
||
228 | GotPermissions = true; |
||
229 | GotPermissionsEvent.Set(); |
||
230 | } |
||
231 | |||
232 | void Objects_OnObjectProperties(object sender, ObjectPropertiesEventArgs e) |
||
233 | { |
||
234 | lock (PrimsWaiting) |
||
235 | { |
||
236 | PrimsWaiting.Remove(e.Properties.ObjectID); |
||
237 | |||
238 | if (PrimsWaiting.Count == 0) |
||
239 | AllPropertiesReceived.Set(); |
||
240 | } |
||
241 | } |
||
242 | } |
||
243 | } |