diff options
First part of Scene refactoring:
Started the move of some of the methods from scene into a inner class (currently called InnerScene.cs), the idea being that the code related to the 3d scene (primitive/entities/Avatars etc) will be in this inner class, then what is now Scene.cs will be left as a kind of wrapper class around it. And once the spilt is complete can be renamed to something like RegionInstance (or any name that sounds good and ids it as the Region layer class that "has" a scene).
Added SceneCommunicationService which at the moment is a kind of high level wrapper around commsManager. The idea being that it has a higher level API for the Region/Scene to send messages to the other regions on the grid. a Example of the API is that instead of having sendXmessage methods, it has more functional level method like PassAvatarToNeighbour. Hopefully this will allow more freedom to do changes in communications that doesn't break other things.
Diffstat (limited to 'OpenSim/Region/Environment/Scenes/InnerScene.cs')
-rw-r--r-- | OpenSim/Region/Environment/Scenes/InnerScene.cs | 657 |
1 files changed, 657 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs new file mode 100644 index 0000000..325153f --- /dev/null +++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs | |||
@@ -0,0 +1,657 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | using OpenSim.Framework; | ||
7 | using OpenSim.Framework.Console; | ||
8 | using OpenSim.Region.Environment.Types; | ||
9 | using OpenSim.Region.Physics.Manager; | ||
10 | |||
11 | namespace OpenSim.Region.Environment.Scenes | ||
12 | { | ||
13 | public class InnerScene | ||
14 | { | ||
15 | public Dictionary<LLUUID, ScenePresence> ScenePresences; | ||
16 | public Dictionary<LLUUID, SceneObjectGroup> SceneObjects; | ||
17 | public Dictionary<LLUUID, EntityBase> Entities; | ||
18 | |||
19 | public BasicQuadTreeNode QuadTree; | ||
20 | |||
21 | protected RegionInfo m_regInfo; | ||
22 | |||
23 | protected Scene m_parentScene; | ||
24 | public PhysicsScene PhyScene; | ||
25 | |||
26 | private PermissionManager PermissionsMngr; | ||
27 | |||
28 | public InnerScene(Scene parent, RegionInfo regInfo, PermissionManager permissionsMngr) | ||
29 | { | ||
30 | m_parentScene = parent; | ||
31 | m_regInfo = regInfo; | ||
32 | PermissionsMngr = permissionsMngr; | ||
33 | QuadTree = new BasicQuadTreeNode(null, "/0/", 0, 0, 256, 256); | ||
34 | QuadTree.Subdivide(); | ||
35 | QuadTree.Subdivide(); | ||
36 | } | ||
37 | |||
38 | public void Close() | ||
39 | { | ||
40 | ScenePresences.Clear(); | ||
41 | SceneObjects.Clear(); | ||
42 | Entities.Clear(); | ||
43 | } | ||
44 | |||
45 | public void AddEntityFromStorage(SceneObjectGroup sceneObject) | ||
46 | { | ||
47 | sceneObject.RegionHandle = m_regInfo.RegionHandle; | ||
48 | sceneObject.SetScene(m_parentScene); | ||
49 | foreach (SceneObjectPart part in sceneObject.Children.Values) | ||
50 | { | ||
51 | part.LocalID = m_parentScene.PrimIDAllocate(); | ||
52 | } | ||
53 | sceneObject.UpdateParentIDs(); | ||
54 | AddEntity(sceneObject); | ||
55 | } | ||
56 | |||
57 | public void AddEntity(SceneObjectGroup sceneObject) | ||
58 | { | ||
59 | if (!Entities.ContainsKey(sceneObject.UUID)) | ||
60 | { | ||
61 | // QuadTree.AddObject(sceneObject); | ||
62 | Entities.Add(sceneObject.UUID, sceneObject); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | public void RemovePrim(uint localID, LLUUID avatar_deleter) | ||
67 | { | ||
68 | foreach (EntityBase obj in Entities.Values) | ||
69 | { | ||
70 | if (obj is SceneObjectGroup) | ||
71 | { | ||
72 | if (((SceneObjectGroup)obj).LocalId == localID) | ||
73 | { | ||
74 | m_parentScene.RemoveEntity((SceneObjectGroup)obj); | ||
75 | return; | ||
76 | } | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | |||
81 | public ScenePresence CreateAndAddScenePresence(IClientAPI client, bool child, AvatarWearable[] wearables, byte[] visualParams) | ||
82 | { | ||
83 | ScenePresence newAvatar = null; | ||
84 | |||
85 | newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, visualParams, wearables); | ||
86 | newAvatar.IsChildAgent = child; | ||
87 | |||
88 | if (child) | ||
89 | { | ||
90 | MainLog.Instance.Verbose("SCENE", m_regInfo.RegionName + ": Creating new child agent."); | ||
91 | } | ||
92 | else | ||
93 | { | ||
94 | //newAvatar.OnSignificantClientMovement += m_LandManager.handleSignificantClientMovement; | ||
95 | |||
96 | MainLog.Instance.Verbose("SCENE", m_regInfo.RegionName + ": Creating new root agent."); | ||
97 | MainLog.Instance.Verbose("SCENE", m_regInfo.RegionName + ": Adding Physical agent."); | ||
98 | |||
99 | newAvatar.AddToPhysicalScene(); | ||
100 | } | ||
101 | |||
102 | lock (Entities) | ||
103 | { | ||
104 | if (!Entities.ContainsKey(client.AgentId)) | ||
105 | { | ||
106 | Entities.Add(client.AgentId, newAvatar); | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | Entities[client.AgentId] = newAvatar; | ||
111 | } | ||
112 | } | ||
113 | lock (ScenePresences) | ||
114 | { | ||
115 | if (ScenePresences.ContainsKey(client.AgentId)) | ||
116 | { | ||
117 | ScenePresences[client.AgentId] = newAvatar; | ||
118 | } | ||
119 | else | ||
120 | { | ||
121 | ScenePresences.Add(client.AgentId, newAvatar); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | return newAvatar; | ||
126 | } | ||
127 | |||
128 | /// <summary> | ||
129 | /// Request a List of all m_scenePresences in this World | ||
130 | /// </summary> | ||
131 | /// <returns></returns> | ||
132 | public List<ScenePresence> GetScenePresences() | ||
133 | { | ||
134 | List<ScenePresence> result = new List<ScenePresence>(ScenePresences.Values); | ||
135 | |||
136 | return result; | ||
137 | } | ||
138 | |||
139 | public List<ScenePresence> GetAvatars() | ||
140 | { | ||
141 | List<ScenePresence> result = | ||
142 | GetScenePresences(delegate(ScenePresence scenePresence) { return !scenePresence.IsChildAgent; }); | ||
143 | |||
144 | return result; | ||
145 | } | ||
146 | |||
147 | /// <summary> | ||
148 | /// Request a filtered list of m_scenePresences in this World | ||
149 | /// </summary> | ||
150 | /// <returns></returns> | ||
151 | public List<ScenePresence> GetScenePresences(FilterAvatarList filter) | ||
152 | { | ||
153 | List<ScenePresence> result = new List<ScenePresence>(); | ||
154 | |||
155 | foreach (ScenePresence avatar in ScenePresences.Values) | ||
156 | { | ||
157 | if (filter(avatar)) | ||
158 | { | ||
159 | result.Add(avatar); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return result; | ||
164 | } | ||
165 | |||
166 | /// <summary> | ||
167 | /// Request a Avatar by UUID | ||
168 | /// </summary> | ||
169 | /// <param name="avatarID"></param> | ||
170 | /// <returns></returns> | ||
171 | public ScenePresence GetScenePresence(LLUUID avatarID) | ||
172 | { | ||
173 | if (ScenePresences.ContainsKey(avatarID)) | ||
174 | { | ||
175 | return ScenePresences[avatarID]; | ||
176 | } | ||
177 | return null; | ||
178 | } | ||
179 | |||
180 | |||
181 | public LLUUID ConvertLocalIDToFullID(uint localID) | ||
182 | { | ||
183 | bool hasPrim = false; | ||
184 | foreach (EntityBase ent in Entities.Values) | ||
185 | { | ||
186 | if (ent is SceneObjectGroup) | ||
187 | { | ||
188 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
189 | if (hasPrim != false) | ||
190 | { | ||
191 | return ((SceneObjectGroup)ent).GetPartsFullID(localID); | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | return LLUUID.Zero; | ||
196 | } | ||
197 | |||
198 | public void SendAllSceneObjectsToClient(ScenePresence presence) | ||
199 | { | ||
200 | foreach (EntityBase ent in Entities.Values) | ||
201 | { | ||
202 | if (ent is SceneObjectGroup) | ||
203 | { | ||
204 | ((SceneObjectGroup)ent).ScheduleFullUpdateToAvatar(presence); | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | public SceneObjectPart GetSceneObjectPart(uint localID) | ||
210 | { | ||
211 | bool hasPrim = false; | ||
212 | foreach (EntityBase ent in Entities.Values) | ||
213 | { | ||
214 | if (ent is SceneObjectGroup) | ||
215 | { | ||
216 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
217 | if (hasPrim != false) | ||
218 | { | ||
219 | return ((SceneObjectGroup)ent).GetChildPart(localID); | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | return null; | ||
224 | } | ||
225 | |||
226 | public SceneObjectPart GetSceneObjectPart(LLUUID fullID) | ||
227 | { | ||
228 | bool hasPrim = false; | ||
229 | foreach (EntityBase ent in Entities.Values) | ||
230 | { | ||
231 | if (ent is SceneObjectGroup) | ||
232 | { | ||
233 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(fullID); | ||
234 | if (hasPrim != false) | ||
235 | { | ||
236 | return ((SceneObjectGroup)ent).GetChildPart(fullID); | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | return null; | ||
241 | } | ||
242 | |||
243 | internal bool TryGetAvatar(LLUUID avatarId, out ScenePresence avatar) | ||
244 | { | ||
245 | ScenePresence presence; | ||
246 | if (ScenePresences.TryGetValue(avatarId, out presence)) | ||
247 | { | ||
248 | if (!presence.IsChildAgent) | ||
249 | { | ||
250 | avatar = presence; | ||
251 | return true; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | avatar = null; | ||
256 | return false; | ||
257 | } | ||
258 | |||
259 | internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) | ||
260 | { | ||
261 | foreach (ScenePresence presence in ScenePresences.Values) | ||
262 | { | ||
263 | if (!presence.IsChildAgent) | ||
264 | { | ||
265 | string name = presence.ControllingClient.FirstName + " " + presence.ControllingClient.LastName; | ||
266 | |||
267 | if (String.Compare(avatarName, name, true) == 0) | ||
268 | { | ||
269 | avatar = presence; | ||
270 | return true; | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | avatar = null; | ||
276 | return false; | ||
277 | } | ||
278 | |||
279 | |||
280 | internal void ForEachClient(Action<IClientAPI> action) | ||
281 | { | ||
282 | foreach (ScenePresence presence in ScenePresences.Values) | ||
283 | { | ||
284 | action(presence.ControllingClient); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | #region Client Event handlers | ||
289 | /// <summary> | ||
290 | /// | ||
291 | /// </summary> | ||
292 | /// <param name="localID"></param> | ||
293 | /// <param name="scale"></param> | ||
294 | /// <param name="remoteClient"></param> | ||
295 | public void UpdatePrimScale(uint localID, LLVector3 scale, IClientAPI remoteClient) | ||
296 | { | ||
297 | bool hasPrim = false; | ||
298 | foreach (EntityBase ent in Entities.Values) | ||
299 | { | ||
300 | if (ent is SceneObjectGroup) | ||
301 | { | ||
302 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
303 | if (hasPrim != false) | ||
304 | { | ||
305 | ((SceneObjectGroup)ent).Resize(scale, localID); | ||
306 | break; | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | |||
312 | |||
313 | /// <summary> | ||
314 | /// | ||
315 | /// </summary> | ||
316 | /// <param name="localID"></param> | ||
317 | /// <param name="rot"></param> | ||
318 | /// <param name="remoteClient"></param> | ||
319 | public void UpdatePrimSingleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) | ||
320 | { | ||
321 | bool hasPrim = false; | ||
322 | foreach (EntityBase ent in Entities.Values) | ||
323 | { | ||
324 | if (ent is SceneObjectGroup) | ||
325 | { | ||
326 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
327 | if (hasPrim != false) | ||
328 | { | ||
329 | ((SceneObjectGroup)ent).UpdateSingleRotation(rot, localID); | ||
330 | break; | ||
331 | } | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | |||
336 | /// <summary> | ||
337 | /// | ||
338 | /// </summary> | ||
339 | /// <param name="localID"></param> | ||
340 | /// <param name="rot"></param> | ||
341 | /// <param name="remoteClient"></param> | ||
342 | public void UpdatePrimRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) | ||
343 | { | ||
344 | bool hasPrim = false; | ||
345 | foreach (EntityBase ent in Entities.Values) | ||
346 | { | ||
347 | if (ent is SceneObjectGroup) | ||
348 | { | ||
349 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
350 | if (hasPrim != false) | ||
351 | { | ||
352 | ((SceneObjectGroup)ent).UpdateGroupRotation(rot); | ||
353 | break; | ||
354 | } | ||
355 | } | ||
356 | } | ||
357 | } | ||
358 | |||
359 | /// <summary> | ||
360 | /// | ||
361 | /// </summary> | ||
362 | /// <param name="localID"></param> | ||
363 | /// <param name="pos"></param> | ||
364 | /// <param name="rot"></param> | ||
365 | /// <param name="remoteClient"></param> | ||
366 | public void UpdatePrimRotation(uint localID, LLVector3 pos, LLQuaternion rot, IClientAPI remoteClient) | ||
367 | { | ||
368 | bool hasPrim = false; | ||
369 | foreach (EntityBase ent in Entities.Values) | ||
370 | { | ||
371 | if (ent is SceneObjectGroup) | ||
372 | { | ||
373 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
374 | if (hasPrim != false) | ||
375 | { | ||
376 | ((SceneObjectGroup)ent).UpdateGroupRotation(pos, rot); | ||
377 | break; | ||
378 | } | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | public void UpdatePrimSinglePosition(uint localID, LLVector3 pos, IClientAPI remoteClient) | ||
384 | { | ||
385 | bool hasPrim = false; | ||
386 | foreach (EntityBase ent in Entities.Values) | ||
387 | { | ||
388 | if (ent is SceneObjectGroup) | ||
389 | { | ||
390 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
391 | if (hasPrim != false) | ||
392 | { | ||
393 | ((SceneObjectGroup)ent).UpdateSinglePosition(pos, localID); | ||
394 | break; | ||
395 | } | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | |||
400 | |||
401 | /// <summary> | ||
402 | /// | ||
403 | /// </summary> | ||
404 | /// <param name="localID"></param> | ||
405 | /// <param name="pos"></param> | ||
406 | /// <param name="remoteClient"></param> | ||
407 | public void UpdatePrimPosition(uint localID, LLVector3 pos, IClientAPI remoteClient) | ||
408 | { | ||
409 | bool hasPrim = false; | ||
410 | foreach (EntityBase ent in Entities.Values) | ||
411 | { | ||
412 | if (ent is SceneObjectGroup) | ||
413 | { | ||
414 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
415 | if (hasPrim != false) | ||
416 | { | ||
417 | ((SceneObjectGroup)ent).UpdateGroupPosition(pos); | ||
418 | break; | ||
419 | } | ||
420 | } | ||
421 | } | ||
422 | } | ||
423 | |||
424 | /// <summary> | ||
425 | /// | ||
426 | /// </summary> | ||
427 | /// <param name="localID"></param> | ||
428 | /// <param name="texture"></param> | ||
429 | /// <param name="remoteClient"></param> | ||
430 | public void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient) | ||
431 | { | ||
432 | bool hasPrim = false; | ||
433 | foreach (EntityBase ent in Entities.Values) | ||
434 | { | ||
435 | if (ent is SceneObjectGroup) | ||
436 | { | ||
437 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
438 | if (hasPrim != false) | ||
439 | { | ||
440 | ((SceneObjectGroup)ent).UpdateTextureEntry(localID, texture); | ||
441 | break; | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /// <summary> | ||
448 | /// | ||
449 | /// </summary> | ||
450 | /// <param name="localID"></param> | ||
451 | /// <param name="packet"></param> | ||
452 | /// <param name="remoteClient"></param> | ||
453 | public void UpdatePrimFlags(uint localID, Packet packet, IClientAPI remoteClient) | ||
454 | { | ||
455 | bool hasprim = false; | ||
456 | foreach (EntityBase ent in Entities.Values) | ||
457 | { | ||
458 | if (ent is SceneObjectGroup) | ||
459 | { | ||
460 | hasprim = ((SceneObjectGroup)ent).HasChildPrim(localID); | ||
461 | if (hasprim != false) | ||
462 | { | ||
463 | ((SceneObjectGroup)ent).UpdatePrimFlags(localID, (ushort)packet.Type, true, packet.ToBytes()); | ||
464 | } | ||
465 | } | ||
466 | } | ||
467 | |||
468 | //System.Console.WriteLine("Got primupdate packet: " + packet.UsePhysics.ToString()); | ||
469 | } | ||
470 | |||
471 | public void MoveObject(LLUUID objectID, LLVector3 offset, LLVector3 pos, IClientAPI remoteClient) | ||
472 | { | ||
473 | if (PermissionsMngr.CanEditObject(remoteClient.AgentId, objectID)) | ||
474 | { | ||
475 | bool hasPrim = false; | ||
476 | foreach (EntityBase ent in Entities.Values) | ||
477 | { | ||
478 | if (ent is SceneObjectGroup) | ||
479 | { | ||
480 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(objectID); | ||
481 | if (hasPrim != false) | ||
482 | { | ||
483 | ((SceneObjectGroup)ent).GrabMovement(offset, pos, remoteClient); | ||
484 | break; | ||
485 | } | ||
486 | } | ||
487 | } | ||
488 | } | ||
489 | } | ||
490 | |||
491 | /// <summary> | ||
492 | /// | ||
493 | /// </summary> | ||
494 | /// <param name="primLocalID"></param> | ||
495 | /// <param name="description"></param> | ||
496 | public void PrimName(uint primLocalID, string name) | ||
497 | { | ||
498 | bool hasPrim = false; | ||
499 | foreach (EntityBase ent in Entities.Values) | ||
500 | { | ||
501 | if (ent is SceneObjectGroup) | ||
502 | { | ||
503 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(primLocalID); | ||
504 | if (hasPrim != false) | ||
505 | { | ||
506 | ((SceneObjectGroup)ent).SetPartName(name, primLocalID); | ||
507 | break; | ||
508 | } | ||
509 | } | ||
510 | } | ||
511 | } | ||
512 | |||
513 | /// <summary> | ||
514 | /// | ||
515 | /// </summary> | ||
516 | /// <param name="primLocalID"></param> | ||
517 | /// <param name="description"></param> | ||
518 | public void PrimDescription(uint primLocalID, string description) | ||
519 | { | ||
520 | bool hasPrim = false; | ||
521 | foreach (EntityBase ent in Entities.Values) | ||
522 | { | ||
523 | if (ent is SceneObjectGroup) | ||
524 | { | ||
525 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(primLocalID); | ||
526 | if (hasPrim != false) | ||
527 | { | ||
528 | ((SceneObjectGroup)ent).SetPartDescription(description, primLocalID); | ||
529 | break; | ||
530 | } | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | |||
535 | public void UpdateExtraParam(uint primLocalID, ushort type, bool inUse, byte[] data) | ||
536 | { | ||
537 | bool hasPrim = false; | ||
538 | foreach (EntityBase ent in Entities.Values) | ||
539 | { | ||
540 | if (ent is SceneObjectGroup) | ||
541 | { | ||
542 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(primLocalID); | ||
543 | if (hasPrim != false) | ||
544 | { | ||
545 | ((SceneObjectGroup)ent).UpdateExtraParam(primLocalID, type, inUse, data); | ||
546 | break; | ||
547 | } | ||
548 | } | ||
549 | } | ||
550 | } | ||
551 | |||
552 | /// <summary> | ||
553 | /// | ||
554 | /// </summary> | ||
555 | /// <param name="primLocalID"></param> | ||
556 | /// <param name="shapeBlock"></param> | ||
557 | public void UpdatePrimShape(uint primLocalID, ObjectShapePacket.ObjectDataBlock shapeBlock) | ||
558 | { | ||
559 | bool hasPrim = false; | ||
560 | foreach (EntityBase ent in Entities.Values) | ||
561 | { | ||
562 | if (ent is SceneObjectGroup) | ||
563 | { | ||
564 | hasPrim = ((SceneObjectGroup)ent).HasChildPrim(primLocalID); | ||
565 | if (hasPrim != false) | ||
566 | { | ||
567 | ((SceneObjectGroup)ent).UpdateShape(shapeBlock, primLocalID); | ||
568 | break; | ||
569 | } | ||
570 | } | ||
571 | } | ||
572 | } | ||
573 | |||
574 | /// <summary> | ||
575 | /// | ||
576 | /// </summary> | ||
577 | /// <param name="parentPrim"></param> | ||
578 | /// <param name="childPrims"></param> | ||
579 | public void LinkObjects(uint parentPrim, List<uint> childPrims) | ||
580 | { | ||
581 | SceneObjectGroup parenPrim = null; | ||
582 | foreach (EntityBase ent in Entities.Values) | ||
583 | { | ||
584 | if (ent is SceneObjectGroup) | ||
585 | { | ||
586 | if (((SceneObjectGroup)ent).LocalId == parentPrim) | ||
587 | { | ||
588 | parenPrim = (SceneObjectGroup)ent; | ||
589 | break; | ||
590 | } | ||
591 | } | ||
592 | } | ||
593 | |||
594 | List<SceneObjectGroup> children = new List<SceneObjectGroup>(); | ||
595 | if (parenPrim != null) | ||
596 | { | ||
597 | for (int i = 0; i < childPrims.Count; i++) | ||
598 | { | ||
599 | foreach (EntityBase ent in Entities.Values) | ||
600 | { | ||
601 | if (ent is SceneObjectGroup) | ||
602 | { | ||
603 | if (((SceneObjectGroup)ent).LocalId == childPrims[i]) | ||
604 | { | ||
605 | children.Add((SceneObjectGroup)ent); | ||
606 | } | ||
607 | } | ||
608 | } | ||
609 | } | ||
610 | } | ||
611 | |||
612 | foreach (SceneObjectGroup sceneObj in children) | ||
613 | { | ||
614 | parenPrim.LinkToGroup(sceneObj); | ||
615 | } | ||
616 | } | ||
617 | |||
618 | /// <summary> | ||
619 | /// | ||
620 | /// </summary> | ||
621 | /// <param name="originalPrim"></param> | ||
622 | /// <param name="offset"></param> | ||
623 | /// <param name="flags"></param> | ||
624 | public void DuplicateObject(uint originalPrim, LLVector3 offset, uint flags) | ||
625 | { | ||
626 | SceneObjectGroup originPrim = null; | ||
627 | foreach (EntityBase ent in Entities.Values) | ||
628 | { | ||
629 | if (ent is SceneObjectGroup) | ||
630 | { | ||
631 | if (((SceneObjectGroup)ent).LocalId == originalPrim) | ||
632 | { | ||
633 | originPrim = (SceneObjectGroup)ent; | ||
634 | break; | ||
635 | } | ||
636 | } | ||
637 | } | ||
638 | |||
639 | if (originPrim != null) | ||
640 | { | ||
641 | SceneObjectGroup copy = originPrim.Copy(); | ||
642 | copy.AbsolutePosition = copy.AbsolutePosition + offset; | ||
643 | Entities.Add(copy.UUID, copy); | ||
644 | |||
645 | copy.ScheduleGroupForFullUpdate(); | ||
646 | |||
647 | } | ||
648 | else | ||
649 | { | ||
650 | MainLog.Instance.Warn("client", "Attempted to duplicate nonexistant prim"); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | |||
655 | #endregion | ||
656 | } | ||
657 | } | ||