aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs')
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs647
1 files changed, 647 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
new file mode 100644
index 0000000..b7bc229
--- /dev/null
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -0,0 +1,647 @@
1using System.Collections.Generic;
2using System.Text;
3using Axiom.Math;
4using libsecondlife;
5using libsecondlife.Packets;
6using OpenSim.Framework.Interfaces;
7using OpenSim.Framework.Types;
8using OpenSim.Physics.Manager;
9
10namespace OpenSim.Region.Environment.Scenes
11{
12 // public delegate void PrimCountTaintedDelegate();
13
14 public class SceneObjectGroup : EntityBase
15 {
16 private Encoding enc = Encoding.ASCII;
17
18 protected SceneObjectPart m_rootPart;
19 protected Dictionary<LLUUID, SceneObjectPart> m_parts = new Dictionary<LLUUID, SceneObjectPart>();
20
21 protected ulong m_regionHandle;
22
23 public event PrimCountTaintedDelegate OnPrimCountTainted;
24
25 /// <summary>
26 ///
27 /// </summary>
28 public int PrimCount
29 {
30 get { return 1; }
31 }
32
33 /// <summary>
34 ///
35 /// </summary>
36 public LLVector3 GroupCentrePoint
37 {
38 get { return new LLVector3(0, 0, 0); }
39 }
40
41 public Dictionary<LLUUID, SceneObjectPart> Children
42 {
43 get { return this.m_parts; }
44 set { m_parts = value; }
45 }
46
47 public override LLVector3 Pos
48 {
49 get { return m_rootPart.GroupPosition; }
50 set
51 {
52 lock (this.m_parts)
53 {
54 foreach (SceneObjectPart part in this.m_parts.Values)
55 {
56 part.GroupPosition = value;
57 }
58 }
59 }
60 }
61
62 public override uint LocalId
63 {
64 get { return m_rootPart.LocalID; }
65 set { m_rootPart.LocalID = value; }
66 }
67
68 public override LLUUID UUID
69 {
70 get { return m_rootPart.UUID; }
71 set { m_rootPart.UUID = value; }
72 }
73
74 public LLUUID OwnerID
75 {
76 get { return m_rootPart.OwnerID; }
77 }
78
79 /// <summary>
80 /// Added because the Parcel code seems to use it
81 /// but not sure a object should have this
82 /// as what does it tell us? that some avatar has selected it
83 /// think really there should be a list (or whatever) in each scenepresence
84 /// saying what prim(s) that user has selected at any time.
85 /// </summary>
86 protected bool m_isSelected = false;
87 public bool IsSelected
88 {
89 get{ return m_isSelected;}
90 set { m_isSelected = value; }
91 }
92
93 /// <summary>
94 ///
95 /// </summary>
96 public SceneObjectGroup()
97 {
98
99 }
100
101 /// <summary>
102 ///
103 /// </summary>
104 public SceneObjectGroup(byte[] data)
105 {
106
107 }
108
109 /// <summary>
110 ///
111 /// </summary>
112 public SceneObjectGroup(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos, PrimitiveBaseShape shape)
113 {
114 m_regionHandle = regionHandle;
115 m_scene = scene;
116
117 this.Pos = pos;
118 LLVector3 rootOffset = new LLVector3(0, 0, 0);
119 SceneObjectPart newPart = new SceneObjectPart(m_regionHandle, this, ownerID, localID, shape, pos, rootOffset);
120 this.m_parts.Add(newPart.UUID, newPart);
121 this.SetPartAsRoot(newPart);
122 }
123
124
125 #region Copying
126 /// <summary>
127 ///
128 /// </summary>
129 /// <returns></returns>
130 public new SceneObjectGroup Copy()
131 {
132 SceneObjectGroup dupe = (SceneObjectGroup)this.MemberwiseClone();
133 dupe.Pos = new LLVector3(Pos.X, Pos.Y, Pos.Z);
134 dupe.m_scene = m_scene;
135 dupe.m_regionHandle = this.m_regionHandle;
136
137 dupe.CopyRootPart(this.m_rootPart);
138
139 foreach (SceneObjectPart part in this.m_parts.Values)
140 {
141 if (part.UUID != this.m_rootPart.UUID)
142 {
143 dupe.CopyPart(part);
144 }
145 }
146 return dupe;
147 }
148
149 /// <summary>
150 ///
151 /// </summary>
152 /// <param name="part"></param>
153 public void CopyRootPart(SceneObjectPart part)
154 {
155 SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate());
156 this.m_parts.Add(newPart.UUID, newPart);
157 this.SetPartAsRoot(newPart);
158 }
159
160 /// <summary>
161 ///
162 /// </summary>
163 /// <param name="part"></param>
164 public void CopyPart(SceneObjectPart part)
165 {
166 SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate());
167 this.m_parts.Add(newPart.UUID, newPart);
168 this.SetPartAsNonRoot(newPart);
169 }
170 #endregion
171
172 /// <summary>
173 ///
174 /// </summary>
175 public override void Update()
176 {
177 foreach (SceneObjectPart part in this.m_parts.Values)
178 {
179 part.SendScheduledUpdates();
180 }
181 }
182
183 /// <summary>
184 ///
185 /// </summary>
186 public void ScheduleGroupForFullUpdate()
187 {
188 foreach (SceneObjectPart part in this.m_parts.Values)
189 {
190 part.ScheduleFullUpdate();
191 }
192 }
193
194 /// <summary>
195 ///
196 /// </summary>
197 public void ScheduleGroupForTerseUpdate()
198 {
199 foreach (SceneObjectPart part in this.m_parts.Values)
200 {
201 part.ScheduleTerseUpdate();
202 }
203 }
204
205 /// <summary>
206 ///
207 /// </summary>
208 public void SendGroupFullUpdate()
209 {
210 foreach (SceneObjectPart part in this.m_parts.Values)
211 {
212 part.SendFullUpdateToAllClients();
213 }
214 }
215
216 /// <summary>
217 ///
218 /// </summary>
219 public void SendGroupTerseUpdate()
220 {
221 foreach (SceneObjectPart part in this.m_parts.Values)
222 {
223 part.SendTerseUpdateToAllClients();
224 }
225 }
226
227 /// <summary>
228 ///
229 /// </summary>
230 /// <param name="objectGroup"></param>
231 public void LinkToGroup(SceneObjectGroup objectGroup)
232 {
233
234 }
235
236 /// <summary>
237 ///
238 /// </summary>
239 /// <param name="primID"></param>
240 /// <returns></returns>
241 private SceneObjectPart GetChildPrim(LLUUID primID)
242 {
243 SceneObjectPart childPart = null;
244 if (this.m_parts.ContainsKey(primID))
245 {
246 childPart = this.m_parts[primID];
247 }
248 return childPart;
249 }
250
251 /// <summary>
252 ///
253 /// </summary>
254 /// <param name="localID"></param>
255 /// <returns></returns>
256 private SceneObjectPart GetChildPrim(uint localID)
257 {
258 foreach (SceneObjectPart part in this.m_parts.Values)
259 {
260 if (part.LocalID == localID)
261 {
262 return part;
263 }
264 }
265 return null;
266 }
267
268 /// <summary>
269 /// Does this group contain the child prim
270 /// should be able to remove these methods once we have a entity index in scene
271 /// </summary>
272 /// <param name="primID"></param>
273 /// <returns></returns>
274 public bool HasChildPrim(LLUUID primID)
275 {
276 SceneObjectPart childPart = null;
277 if (this.m_parts.ContainsKey(primID))
278 {
279 childPart = this.m_parts[primID];
280 return true;
281 }
282 return false;
283 }
284
285 /// <summary>
286 /// Does this group contain the child prim
287 /// should be able to remove these methods once we have a entity index in scene
288 /// </summary>
289 /// <param name="localID"></param>
290 /// <returns></returns>
291 public bool HasChildPrim(uint localID)
292 {
293 foreach (SceneObjectPart part in this.m_parts.Values)
294 {
295 if (part.LocalID == localID)
296 {
297 return true;
298 }
299 }
300 return false;
301 }
302
303 /// <summary>
304 ///
305 /// </summary>
306 public void TriggerTainted()
307 {
308 if (OnPrimCountTainted != null)
309 {
310 this.OnPrimCountTainted();
311 }
312 }
313
314 /// <summary>
315 ///
316 /// </summary>
317 /// <param name="offset"></param>
318 /// <param name="pos"></param>
319 /// <param name="remoteClient"></param>
320 public void GrapMovement(LLVector3 offset, LLVector3 pos, IClientAPI remoteClient)
321 {
322 this.Pos = pos;
323 this.m_rootPart.SendTerseUpdateToAllClients();
324 }
325
326 /// <summary>
327 ///
328 /// </summary>
329 /// <param name="client"></param>
330 public void GetProperites(IClientAPI client)
331 {
332 ObjectPropertiesPacket proper = new ObjectPropertiesPacket();
333 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1];
334 proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock();
335 proper.ObjectData[0].ItemID = LLUUID.Zero;
336 proper.ObjectData[0].CreationDate = (ulong)this.m_rootPart.CreationDate;
337 proper.ObjectData[0].CreatorID = this.m_rootPart.CreatorID;
338 proper.ObjectData[0].FolderID = LLUUID.Zero;
339 proper.ObjectData[0].FromTaskID = LLUUID.Zero;
340 proper.ObjectData[0].GroupID = LLUUID.Zero;
341 proper.ObjectData[0].InventorySerial = 0;
342 proper.ObjectData[0].LastOwnerID = this.m_rootPart.LastOwnerID;
343 proper.ObjectData[0].ObjectID = this.UUID;
344 proper.ObjectData[0].OwnerID = this.m_rootPart.OwnerID;
345 proper.ObjectData[0].TouchName = enc.GetBytes(this.m_rootPart.TouchName + "\0");
346 proper.ObjectData[0].TextureID = new byte[0];
347 proper.ObjectData[0].SitName = enc.GetBytes(this.m_rootPart.SitName + "\0");
348 proper.ObjectData[0].Name = enc.GetBytes(this.m_rootPart.PartName + "\0");
349 proper.ObjectData[0].Description = enc.GetBytes(this.m_rootPart.Description + "\0");
350 proper.ObjectData[0].OwnerMask = this.m_rootPart.OwnerMask;
351 proper.ObjectData[0].NextOwnerMask = this.m_rootPart.NextOwnerMask;
352 proper.ObjectData[0].GroupMask = this.m_rootPart.GroupMask;
353 proper.ObjectData[0].EveryoneMask = this.m_rootPart.EveryoneMask;
354 proper.ObjectData[0].BaseMask = this.m_rootPart.BaseMask;
355
356 client.OutPacket(proper);
357 }
358
359 /// <summary>
360 ///
361 /// </summary>
362 /// <param name="name"></param>
363 public void SetPartName(string name, uint localID)
364 {
365 SceneObjectPart part = this.GetChildPrim(localID);
366 if (part != null)
367 {
368 part.PartName = name;
369 }
370 }
371
372 public void SetPartDescription(string des, uint localID)
373 {
374 SceneObjectPart part = this.GetChildPrim(localID);
375 if (part != null)
376 {
377 part.Description = des;
378 }
379 }
380
381 /// <summary>
382 ///
383 /// </summary>
384 /// <param name="remoteClient"></param>
385 /// <param name="localID"></param>
386 public void GetPartInventory(IClientAPI remoteClient, uint localID)
387 {
388 SceneObjectPart part = this.GetChildPrim(localID);
389 if (part != null)
390 {
391 part.GetInventory(remoteClient, localID);
392 }
393 }
394
395 /// <summary>
396 ///
397 /// </summary>
398 /// <param name="localID"></param>
399 /// <param name="type"></param>
400 /// <param name="inUse"></param>
401 /// <param name="data"></param>
402 public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data)
403 {
404 SceneObjectPart part = this.GetChildPrim(localID);
405 if (part != null)
406 {
407 part.UpdateExtraParam(type, inUse, data);
408 }
409 }
410
411 /// <summary>
412 ///
413 /// </summary>
414 /// <param name="localID"></param>
415 /// <param name="textureEntry"></param>
416 public void UpdateTextureEntry(uint localID, byte[] textureEntry)
417 {
418 SceneObjectPart part = this.GetChildPrim(localID);
419 if (part != null)
420 {
421 part.UpdateTextureEntry(textureEntry);
422 }
423 }
424
425 #region Shape
426 /// <summary>
427 ///
428 /// </summary>
429 /// <param name="shapeBlock"></param>
430 public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, uint localID)
431 {
432 SceneObjectPart part = this.GetChildPrim(localID);
433 if (part != null)
434 {
435 part.UpdateShape(shapeBlock);
436 }
437 }
438 #endregion
439
440 /// <summary>
441 ///
442 /// </summary>
443 /// <param name="scale"></param>
444 /// <param name="localID"></param>
445 public void Resize(LLVector3 scale, uint localID)
446 {
447 SceneObjectPart part = this.GetChildPrim(localID);
448 if (part != null)
449 {
450 part.Resize(scale);
451 }
452 }
453
454 #region Position
455 /// <summary>
456 ///
457 /// </summary>
458 /// <param name="pos"></param>
459 public void UpdateGroupPosition(LLVector3 pos)
460 {
461 this.Pos = pos;
462 }
463
464 /// <summary>
465 ///
466 /// </summary>
467 /// <param name="pos"></param>
468 /// <param name="localID"></param>
469 public void UpdateSinglePosition(LLVector3 pos, uint localID)
470 {
471 SceneObjectPart part = this.GetChildPrim(localID);
472 if (part != null)
473 {
474 if (part.UUID == this.m_rootPart.UUID)
475 {
476 this.UpdateRootPosition(pos);
477 }
478 else
479 {
480 part.UpdateOffSet(pos);
481 }
482 }
483 }
484
485 /// <summary>
486 ///
487 /// </summary>
488 /// <param name="pos"></param>
489 private void UpdateRootPosition(LLVector3 pos)
490 {
491 LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
492 LLVector3 oldPos = new LLVector3(this.Pos.X + this.m_rootPart.OffsetPosition.X, this.Pos.Y + this.m_rootPart.OffsetPosition.Y, this.Pos.Z + this.m_rootPart.OffsetPosition.Z);
493 LLVector3 diff = oldPos - newPos;
494 Axiom.Math.Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
495 Axiom.Math.Quaternion partRotation = new Quaternion(this.m_rootPart.RotationOffset.W, this.m_rootPart.RotationOffset.X, this.m_rootPart.RotationOffset.Y, this.m_rootPart.RotationOffset.Z);
496 axDiff = partRotation.Inverse() * axDiff;
497 diff.X = axDiff.x;
498 diff.Y = axDiff.y;
499 diff.Z = axDiff.z;
500
501 foreach (SceneObjectPart obPart in this.m_parts.Values)
502 {
503 if (obPart.UUID != this.m_rootPart.UUID)
504 {
505 obPart.OffsetPosition = obPart.OffsetPosition + diff;
506 }
507 }
508 this.Pos = newPos;
509 pos.X = newPos.X;
510 pos.Y = newPos.Y;
511 pos.Z = newPos.Z;
512 }
513 #endregion
514
515 #region Roation
516 /// <summary>
517 ///
518 /// </summary>
519 /// <param name="rot"></param>
520 public void UpdateGroupRotation(LLQuaternion rot)
521 {
522 this.m_rootPart.UpdateRotation(rot);
523 }
524
525 /// <summary>
526 ///
527 /// </summary>
528 /// <param name="pos"></param>
529 /// <param name="rot"></param>
530 public void UpdateGroupRotation(LLVector3 pos, LLQuaternion rot)
531 {
532 this.m_rootPart.UpdateRotation(rot);
533 this.Pos = pos;
534 }
535
536 /// <summary>
537 ///
538 /// </summary>
539 /// <param name="rot"></param>
540 /// <param name="localID"></param>
541 public void UpdateSingleRotation(LLQuaternion rot, uint localID)
542 {
543 SceneObjectPart part = this.GetChildPrim(localID);
544 if (part != null)
545 {
546 if (part.UUID == this.m_rootPart.UUID)
547 {
548 this.UpdateRootRotation(rot);
549 }
550 else
551 {
552 part.UpdateRotation(rot);
553 }
554 }
555 }
556
557 /// <summary>
558 ///
559 /// </summary>
560 /// <param name="rot"></param>
561 private void UpdateRootRotation(LLQuaternion rot)
562 {
563 this.m_rootPart.UpdateRotation(rot);
564 Axiom.Math.Quaternion axRot = new Quaternion(rot.W, rot.X, rot.Y, rot.Z);
565 Axiom.Math.Quaternion oldParentRot = new Quaternion(this.m_rootPart.RotationOffset.W, this.m_rootPart.RotationOffset.X, this.m_rootPart.RotationOffset.Y, this.m_rootPart.RotationOffset.Z);
566
567 foreach (SceneObjectPart prim in this.m_parts.Values)
568 {
569 if (prim.UUID != this.m_rootPart.UUID)
570 {
571 Vector3 axPos = new Vector3(prim.OffsetPosition.X, prim.OffsetPosition.Y, prim.OffsetPosition.Z);
572 axPos = oldParentRot * axPos;
573 axPos = axRot.Inverse() * axPos;
574 prim.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
575 Axiom.Math.Quaternion primsRot = new Quaternion(prim.RotationOffset.W, prim.RotationOffset.X, prim.RotationOffset.Y, prim.RotationOffset.Z);
576 Axiom.Math.Quaternion newRot = oldParentRot * primsRot;
577 newRot = axRot.Inverse() * newRot;
578 prim.RotationOffset = new LLQuaternion(newRot.w, newRot.x, newRot.y, newRot.z);
579 }
580 }
581 }
582
583 #endregion
584 /// <summary>
585 ///
586 /// </summary>
587 /// <param name="part"></param>
588 private void SetPartAsRoot(SceneObjectPart part)
589 {
590 this.m_rootPart = part;
591 //this.m_uuid= part.UUID;
592 // this.m_localId = part.LocalID;
593 }
594
595 /// <summary>
596 ///
597 /// </summary>
598 /// <param name="part"></param>
599 private void SetPartAsNonRoot(SceneObjectPart part)
600 {
601 part.ParentID = this.m_rootPart.LocalID;
602 }
603
604 /// <summary>
605 ///
606 /// </summary>
607 /// <returns></returns>
608 public List<ScenePresence> RequestSceneAvatars()
609 {
610 return m_scene.RequestAvatarList();
611 }
612
613 /// <summary>
614 ///
615 /// </summary>
616 /// <param name="remoteClient"></param>
617 /// <param name="part"></param>
618 internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part)
619 {
620 if( m_rootPart == part )
621 {
622 part.SendFullUpdateToClient( remoteClient, Pos );
623 }
624 else
625 {
626 part.SendFullUpdateToClient( remoteClient );
627 }
628 }
629
630 /// <summary>
631 ///
632 /// </summary>
633 /// <param name="remoteClient"></param>
634 /// <param name="part"></param>
635 internal void SendPartTerseUpdate(IClientAPI remoteClient, SceneObjectPart part)
636 {
637 if (m_rootPart == part)
638 {
639 part.SendTerseUpdateToClient(remoteClient, Pos);
640 }
641 else
642 {
643 part.SendTerseUpdateToClient(remoteClient);
644 }
645 }
646 }
647}