aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ExportBot/Commands/ImportCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ExportBot/Commands/ImportCommand.cs246
1 files changed, 246 insertions, 0 deletions
diff --git a/ExportBot/Commands/ImportCommand.cs b/ExportBot/Commands/ImportCommand.cs
new file mode 100644
index 0000000..4cdcaee
--- /dev/null
+++ b/ExportBot/Commands/ImportCommand.cs
@@ -0,0 +1,246 @@
1using System;
2using System.Collections.Generic;
3using System.Xml;
4using System.Xml.Serialization;
5using System.Threading;
6using System.IO;
7using libsecondlife;
8
9namespace libsecondlife.TestClient
10{
11 enum ImporterState
12 {
13 RezzingParent,
14 RezzingChildren,
15 Linking,
16 Idle
17 }
18
19 public class Linkset
20 {
21 public Primitive RootPrim;
22 public List<Primitive> Children = new List<Primitive>();
23
24 public Linkset()
25 {
26 RootPrim = new Primitive();
27 }
28
29 public Linkset(Primitive rootPrim)
30 {
31 RootPrim = rootPrim;
32 }
33 }
34
35 public class ImportCommand : Command
36 {
37 Primitive currentPrim;
38 LLVector3 currentPosition;
39 SecondLife currentClient;
40 AutoResetEvent primDone;
41 List<Primitive> primsCreated;
42 List<uint> linkQueue;
43 uint rootLocalID = 0;
44 bool registeredCreateEvent = false;
45
46 ImporterState state = ImporterState.Idle;
47
48 public ImportCommand(TestClient testClient)
49 {
50 Name = "import";
51 Description = "Import prims from an exported xml file. Usage: import inputfile.xml";
52 primDone = new AutoResetEvent(false);
53 registeredCreateEvent = false;
54 }
55
56 public override string Execute(string[] args, LLUUID fromAgentID)
57 {
58 if (args.Length != 1)
59 return "Usage: import inputfile.xml";
60
61 string filename = args[0];
62 Dictionary<uint, Primitive> prims;
63
64 currentClient = Client;
65
66 try
67 {
68 XmlReader reader = XmlReader.Create(filename);
69 List<Primitive> listprims = Helpers.PrimListFromXml(reader);
70 reader.Close();
71
72 // Create a dictionary indexed by the old local ID of the prims
73 prims = new Dictionary<uint, Primitive>();
74 foreach (Primitive prim in listprims)
75 {
76 prims.Add(prim.LocalID, prim);
77 }
78 }
79 catch (Exception)
80 {
81 return "Failed to import the object XML file, maybe it doesn't exist or is in the wrong format?";
82 }
83
84 if (!registeredCreateEvent)
85 {
86 Client.OnPrimCreated += new TestClient.PrimCreatedCallback(TestClient_OnPrimCreated);
87 registeredCreateEvent = true;
88 }
89
90 // Build an organized structure from the imported prims
91 Dictionary<uint, Linkset> linksets = new Dictionary<uint, Linkset>();
92 foreach (Primitive prim in prims.Values)
93 {
94 if (prim.ParentID == 0)
95 {
96 if (linksets.ContainsKey(prim.LocalID))
97 linksets[prim.LocalID].RootPrim = prim;
98 else
99 linksets[prim.LocalID] = new Linkset(prim);
100 }
101 else
102 {
103 if (!linksets.ContainsKey(prim.ParentID))
104 linksets[prim.ParentID] = new Linkset();
105
106 linksets[prim.ParentID].Children.Add(prim);
107 }
108 }
109
110 primsCreated = new List<Primitive>();
111 Console.WriteLine("Importing " + linksets.Count + " structures.");
112
113 foreach (Linkset linkset in linksets.Values)
114 {
115 if (linkset.RootPrim.LocalID != 0)
116 {
117 state = ImporterState.RezzingParent;
118 currentPrim = linkset.RootPrim;
119 // HACK: Offset the root prim position so it's not lying on top of the original
120 // We need a more elaborate solution for importing with relative or absolute offsets
121 linkset.RootPrim.Position = Client.Self.Position;
122 linkset.RootPrim.Position.Z += 3.0f;
123 currentPosition = linkset.RootPrim.Position;
124 // A better solution would move the bot to the desired position.
125 // or to check if we are within a certain distance of the desired position.
126
127 // Rez the root prim with no rotation
128 LLQuaternion rootRotation = linkset.RootPrim.Rotation;
129 linkset.RootPrim.Rotation = LLQuaternion.Identity;
130
131 Client.Objects.AddPrim(Client.Network.CurrentSim, linkset.RootPrim.Data, LLUUID.Zero,
132 linkset.RootPrim.Position, linkset.RootPrim.Scale, linkset.RootPrim.Rotation);
133
134 if (!primDone.WaitOne(10000, false))
135 return "Rez failed, timed out while creating the root prim.";
136
137 state = ImporterState.RezzingChildren;
138
139 // Rez the child prims
140 foreach (Primitive prim in linkset.Children)
141 {
142 currentPrim = prim;
143 currentPosition = prim.Position + linkset.RootPrim.Position;
144
145 Client.Objects.AddPrim(Client.Network.CurrentSim, prim.Data, LLUUID.Zero, currentPosition,
146 prim.Scale, prim.Rotation);
147
148 if (!primDone.WaitOne(10000, false))
149 return "Rez failed, timed out while creating child prim.";
150 }
151
152 if (linkset.Children.Count != 0)
153 {
154 // Create a list of the local IDs of the newly created prims
155 List<uint> primIDs = new List<uint>(primsCreated.Count);
156 primIDs.Add(rootLocalID); // Root prim is first in list.
157 foreach (Primitive prim in primsCreated)
158 {
159 if (prim.LocalID != rootLocalID)
160 primIDs.Add(prim.LocalID);
161 }
162 linkQueue = new List<uint>(primIDs.Count);
163 linkQueue.AddRange(primIDs);
164
165 // Link and set the permissions + rotation
166 state = ImporterState.Linking;
167 Client.Objects.LinkPrims(Client.Network.CurrentSim, linkQueue);
168 if (primDone.WaitOne(100000 * linkset.Children.Count, false))
169 {
170 Client.Objects.SetPermissions(Client.Network.CurrentSim, primIDs,
171 Helpers.PermissionWho.Everyone | Helpers.PermissionWho.Group | Helpers.PermissionWho.NextOwner,
172 Helpers.PermissionType.Copy | Helpers.PermissionType.Modify | Helpers.PermissionType.Move |
173 Helpers.PermissionType.Transfer, true);
174
175 Client.Objects.SetRotation(Client.Network.CurrentSim, rootLocalID, rootRotation);
176 }
177 else
178 {
179 Console.WriteLine("Warning: Failed to link {0} prims", linkQueue.Count);
180 }
181 }
182 else
183 {
184 Client.Objects.SetRotation(Client.Network.CurrentSim, rootLocalID, rootRotation);
185 }
186 state = ImporterState.Idle;
187 }
188 else
189 {
190 // Skip linksets with a missing root prim
191 Console.WriteLine("WARNING: Skipping a linkset with a missing root prim");
192 }
193
194 // Reset everything for the next linkset
195 primsCreated.Clear();
196 }
197
198 return "Import complete.";
199 }
200
201 void TestClient_OnPrimCreated(Simulator simulator, Primitive prim)
202 {
203 if ((prim.Flags & LLObject.ObjectFlags.CreateSelected) == 0)
204 return; // We received an update for an object we didn't create
205
206 switch (state)
207 {
208 case ImporterState.RezzingParent:
209 rootLocalID = prim.LocalID;
210 goto case ImporterState.RezzingChildren;
211 case ImporterState.RezzingChildren:
212 if (!primsCreated.Contains(prim))
213 {
214 Console.WriteLine("Setting properties for " + prim.LocalID);
215 // TODO: Is there a way to set all of this at once, and update more ObjectProperties stuff?
216 currentClient.Objects.SetPosition(simulator, prim.LocalID, currentPosition);
217 currentClient.Objects.SetTextures(simulator, prim.LocalID, currentPrim.Textures);
218 currentClient.Objects.SetLight(simulator, prim.LocalID, currentPrim.Light);
219 currentClient.Objects.SetFlexible(simulator, prim.LocalID, currentPrim.Flexible);
220
221 if (!String.IsNullOrEmpty(currentPrim.Properties.Name))
222 currentClient.Objects.SetName(simulator, prim.LocalID, currentPrim.Properties.Name);
223 if (!String.IsNullOrEmpty(currentPrim.Properties.Description))
224 currentClient.Objects.SetDescription(simulator, prim.LocalID,
225 currentPrim.Properties.Description);
226
227 primsCreated.Add(prim);
228 primDone.Set();
229 }
230 break;
231 case ImporterState.Linking:
232 lock (linkQueue)
233 {
234 int index = linkQueue.IndexOf(prim.LocalID);
235 if (index != -1)
236 {
237 linkQueue.RemoveAt(index);
238 if (linkQueue.Count == 0)
239 primDone.Set();
240 }
241 }
242 break;
243 }
244 }
245 }
246}