aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs')
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs833
1 files changed, 833 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
new file mode 100644
index 0000000..5ed1514
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
@@ -0,0 +1,833 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Security;
31using OpenMetaverse;
32using OpenMetaverse.Packets;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.OptionalModules.Scripting.Minimodule.Object;
37using OpenSim.Region.Physics.Manager;
38using PrimType=OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.PrimType;
39using SculptType=OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.SculptType;
40
41namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
42{
43 class SOPObject : MarshalByRefObject, IObject, IObjectPhysics, IObjectShape, IObjectSound
44 {
45 private readonly Scene m_rootScene;
46 private readonly uint m_localID;
47 private readonly ISecurityCredential m_security;
48
49 [Obsolete("Replace with 'credential' constructor [security]")]
50 public SOPObject(Scene rootScene, uint localID)
51 {
52 m_rootScene = rootScene;
53 m_localID = localID;
54 }
55
56 public SOPObject(Scene rootScene, uint localID, ISecurityCredential credential)
57 {
58 m_rootScene = rootScene;
59 m_localID = localID;
60 m_security = credential;
61 }
62
63 /// <summary>
64 /// This needs to run very, very quickly.
65 /// It is utilized in nearly every property and method.
66 /// </summary>
67 /// <returns></returns>
68 private SceneObjectPart GetSOP()
69 {
70 return m_rootScene.GetSceneObjectPart(m_localID);
71 }
72
73 private bool CanEdit()
74 {
75 if (!m_security.CanEditObject(this))
76 {
77 throw new SecurityException("Insufficient Permission to edit object with UUID [" + GetSOP().UUID + "]");
78 }
79 return true;
80 }
81
82 #region OnTouch
83
84 private event OnTouchDelegate _OnTouch;
85 private bool _OnTouchActive = false;
86
87 public event OnTouchDelegate OnTouch
88 {
89 add
90 {
91 if (CanEdit())
92 {
93 if (!_OnTouchActive)
94 {
95 GetSOP().Flags |= PrimFlags.Touch;
96 _OnTouchActive = true;
97 m_rootScene.EventManager.OnObjectGrab += EventManager_OnObjectGrab;
98 }
99
100 _OnTouch += value;
101 }
102 }
103 remove
104 {
105 _OnTouch -= value;
106
107 if (_OnTouch == null)
108 {
109 GetSOP().Flags &= ~PrimFlags.Touch;
110 _OnTouchActive = false;
111 m_rootScene.EventManager.OnObjectGrab -= EventManager_OnObjectGrab;
112 }
113 }
114 }
115
116 void EventManager_OnObjectGrab(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
117 {
118 if (_OnTouchActive && m_localID == localID)
119 {
120 TouchEventArgs e = new TouchEventArgs();
121 e.Avatar = new SPAvatar(m_rootScene, remoteClient.AgentId, m_security);
122 e.TouchBiNormal = surfaceArgs.Binormal;
123 e.TouchMaterialIndex = surfaceArgs.FaceIndex;
124 e.TouchNormal = surfaceArgs.Normal;
125 e.TouchPosition = surfaceArgs.Position;
126 e.TouchST = new Vector2(surfaceArgs.STCoord.X, surfaceArgs.STCoord.Y);
127 e.TouchUV = new Vector2(surfaceArgs.UVCoord.X, surfaceArgs.UVCoord.Y);
128
129 IObject sender = this;
130
131 if (_OnTouch != null)
132 _OnTouch(sender, e);
133 }
134 }
135
136 #endregion
137
138 public bool Exists
139 {
140 get { return GetSOP() != null; }
141 }
142
143 public uint LocalID
144 {
145 get { return m_localID; }
146 }
147
148 public UUID GlobalID
149 {
150 get { return GetSOP().UUID; }
151 }
152
153 public string Name
154 {
155 get { return GetSOP().Name; }
156 set
157 {
158 if (CanEdit())
159 GetSOP().Name = value;
160 }
161 }
162
163 public string Description
164 {
165 get { return GetSOP().Description; }
166 set
167 {
168 if (CanEdit())
169 GetSOP().Description = value;
170 }
171 }
172
173 public UUID OwnerId
174 {
175 get { return GetSOP().OwnerID;}
176 }
177
178 public UUID CreatorId
179 {
180 get { return GetSOP().CreatorID;}
181 }
182
183 public IObject[] Children
184 {
185 get
186 {
187 SceneObjectPart my = GetSOP();
188 IObject[] rets = null;
189
190 int total = my.ParentGroup.PrimCount;
191
192 rets = new IObject[total];
193
194 int i = 0;
195
196 foreach (SceneObjectPart part in my.ParentGroup.Parts)
197 {
198 rets[i++] = new SOPObject(m_rootScene, part.LocalId, m_security);
199 }
200
201 return rets;
202 }
203 }
204
205 public IObject Root
206 {
207 get { return new SOPObject(m_rootScene, GetSOP().ParentGroup.RootPart.LocalId, m_security); }
208 }
209
210 public IObjectMaterial[] Materials
211 {
212 get
213 {
214 SceneObjectPart sop = GetSOP();
215 IObjectMaterial[] rets = new IObjectMaterial[getNumberOfSides(sop)];
216
217 for (int i = 0; i < rets.Length; i++)
218 {
219 rets[i] = new SOPObjectMaterial(i, sop);
220 }
221
222 return rets;
223 }
224 }
225
226 public Vector3 Scale
227 {
228 get { return GetSOP().Scale; }
229 set
230 {
231 if (CanEdit())
232 GetSOP().Scale = value;
233 }
234 }
235
236 public Quaternion WorldRotation
237 {
238 get { throw new System.NotImplementedException(); }
239 set { throw new System.NotImplementedException(); }
240 }
241
242 public Quaternion OffsetRotation
243 {
244 get { throw new System.NotImplementedException(); }
245 set { throw new System.NotImplementedException(); }
246 }
247
248 public Vector3 WorldPosition
249 {
250 get { return GetSOP().AbsolutePosition; }
251 set
252 {
253 if (CanEdit())
254 {
255 SceneObjectPart pos = GetSOP();
256 pos.UpdateOffSet(value - pos.AbsolutePosition);
257 }
258 }
259 }
260
261 public Vector3 OffsetPosition
262 {
263 get { return GetSOP().OffsetPosition; }
264 set
265 {
266 if (CanEdit())
267 {
268 GetSOP().OffsetPosition = value;
269 }
270 }
271 }
272
273 public Vector3 SitTarget
274 {
275 get { return GetSOP().SitTargetPosition; }
276 set
277 {
278 if (CanEdit())
279 {
280 GetSOP().SitTargetPosition = value;
281 }
282 }
283 }
284
285 public string SitTargetText
286 {
287 get { return GetSOP().SitName; }
288 set
289 {
290 if (CanEdit())
291 {
292 GetSOP().SitName = value;
293 }
294 }
295 }
296
297 public string TouchText
298 {
299 get { return GetSOP().TouchName; }
300 set
301 {
302 if (CanEdit())
303 {
304 GetSOP().TouchName = value;
305 }
306 }
307 }
308
309 public string Text
310 {
311 get { return GetSOP().Text; }
312 set
313 {
314 if (CanEdit())
315 {
316 GetSOP().SetText(value,new Vector3(1.0f,1.0f,1.0f),1.0f);
317 }
318 }
319 }
320
321 public bool IsRotationLockedX
322 {
323 get { throw new System.NotImplementedException(); }
324 set { throw new System.NotImplementedException(); }
325 }
326
327 public bool IsRotationLockedY
328 {
329 get { throw new System.NotImplementedException(); }
330 set { throw new System.NotImplementedException(); }
331 }
332
333 public bool IsRotationLockedZ
334 {
335 get { throw new System.NotImplementedException(); }
336 set { throw new System.NotImplementedException(); }
337 }
338
339 public bool IsSandboxed
340 {
341 get { throw new System.NotImplementedException(); }
342 set { throw new System.NotImplementedException(); }
343 }
344
345 public bool IsImmotile
346 {
347 get { throw new System.NotImplementedException(); }
348 set { throw new System.NotImplementedException(); }
349 }
350
351 public bool IsAlwaysReturned
352 {
353 get { throw new System.NotImplementedException(); }
354 set { throw new System.NotImplementedException(); }
355 }
356
357 public bool IsTemporary
358 {
359 get { throw new System.NotImplementedException(); }
360 set { throw new System.NotImplementedException(); }
361 }
362
363 public bool IsFlexible
364 {
365 get { throw new System.NotImplementedException(); }
366 set { throw new System.NotImplementedException(); }
367 }
368
369 public PhysicsMaterial PhysicsMaterial
370 {
371 get { throw new System.NotImplementedException(); }
372 set { throw new System.NotImplementedException(); }
373 }
374
375 public IObjectPhysics Physics
376 {
377 get { return this; }
378 }
379
380 public IObjectShape Shape
381 {
382 get { return this; }
383 }
384
385 public IObjectInventory Inventory
386 {
387 get { return new SOPObjectInventory(m_rootScene, GetSOP().TaskInventory); }
388 }
389
390 #region Public Functions
391
392 public void Say(string msg)
393 {
394 if (!CanEdit())
395 return;
396
397 SceneObjectPart sop = GetSOP();
398 m_rootScene.SimChat(msg, ChatTypeEnum.Say, sop.AbsolutePosition, sop.Name, sop.UUID, false);
399 }
400
401 public void Say(string msg,int channel)
402 {
403 if (!CanEdit())
404 return;
405
406 SceneObjectPart sop = GetSOP();
407 m_rootScene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,channel, sop.AbsolutePosition, sop.Name, sop.UUID, false);
408 }
409
410 public void Dialog(UUID avatar, string message, string[] buttons, int chat_channel)
411 {
412 if (!CanEdit())
413 return;
414
415 IDialogModule dm = m_rootScene.RequestModuleInterface<IDialogModule>();
416
417 if (dm == null)
418 return;
419
420 if (buttons.Length < 1)
421 {
422 Say("ERROR: No less than 1 button can be shown",2147483647);
423 return;
424 }
425 if (buttons.Length > 12)
426 {
427 Say("ERROR: No more than 12 buttons can be shown",2147483647);
428 return;
429 }
430
431 foreach (string button in buttons)
432 {
433 if (button == String.Empty)
434 {
435 Say("ERROR: button label cannot be blank",2147483647);
436 return;
437 }
438 if (button.Length > 24)
439 {
440 Say("ERROR: button label cannot be longer than 24 characters",2147483647);
441 return;
442 }
443 }
444
445 dm.SendDialogToUser(
446 avatar, GetSOP().Name, GetSOP().UUID, GetSOP().OwnerID,
447 message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buttons);
448
449 }
450
451 #endregion
452
453
454 #region Supporting Functions
455
456 // Helper functions to understand if object has cut, hollow, dimple, and other affecting number of faces
457 private static void hasCutHollowDimpleProfileCut(int primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow,
458 out bool hasDimple, out bool hasProfileCut)
459 {
460 if (primType == (int)PrimType.Box
461 ||
462 primType == (int)PrimType.Cylinder
463 ||
464 primType == (int)PrimType.Prism)
465
466 hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
467 else
468 hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
469
470 hasHollow = shape.ProfileHollow > 0;
471 hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
472 hasProfileCut = hasDimple; // is it the same thing?
473
474 }
475
476 private static int getScriptPrimType(PrimitiveBaseShape primShape)
477 {
478 if (primShape.SculptEntry)
479 return (int) PrimType.Sculpt;
480 if ((primShape.ProfileCurve & 0x07) == (byte) ProfileShape.Square)
481 {
482 if (primShape.PathCurve == (byte) Extrusion.Straight)
483 return (int) PrimType.Box;
484 if (primShape.PathCurve == (byte) Extrusion.Curve1)
485 return (int) PrimType.Tube;
486 }
487 else if ((primShape.ProfileCurve & 0x07) == (byte) ProfileShape.Circle)
488 {
489 if (primShape.PathCurve == (byte) Extrusion.Straight)
490 return (int) PrimType.Cylinder;
491 if (primShape.PathCurve == (byte) Extrusion.Curve1)
492 return (int) PrimType.Torus;
493 }
494 else if ((primShape.ProfileCurve & 0x07) == (byte) ProfileShape.HalfCircle)
495 {
496 if (primShape.PathCurve == (byte) Extrusion.Curve1 || primShape.PathCurve == (byte) Extrusion.Curve2)
497 return (int) PrimType.Sphere;
498 }
499 else if ((primShape.ProfileCurve & 0x07) == (byte) ProfileShape.EquilateralTriangle)
500 {
501 if (primShape.PathCurve == (byte) Extrusion.Straight)
502 return (int) PrimType.Prism;
503 if (primShape.PathCurve == (byte) Extrusion.Curve1)
504 return (int) PrimType.Ring;
505 }
506 return (int) PrimType.NotPrimitive;
507 }
508
509 private static int getNumberOfSides(SceneObjectPart part)
510 {
511 int ret;
512 bool hasCut;
513 bool hasHollow;
514 bool hasDimple;
515 bool hasProfileCut;
516
517 int primType = getScriptPrimType(part.Shape);
518 hasCutHollowDimpleProfileCut(primType, part.Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut);
519
520 switch (primType)
521 {
522 default:
523 case (int) PrimType.Box:
524 ret = 6;
525 if (hasCut) ret += 2;
526 if (hasHollow) ret += 1;
527 break;
528 case (int) PrimType.Cylinder:
529 ret = 3;
530 if (hasCut) ret += 2;
531 if (hasHollow) ret += 1;
532 break;
533 case (int) PrimType.Prism:
534 ret = 5;
535 if (hasCut) ret += 2;
536 if (hasHollow) ret += 1;
537 break;
538 case (int) PrimType.Sphere:
539 ret = 1;
540 if (hasCut) ret += 2;
541 if (hasDimple) ret += 2;
542 if (hasHollow)
543 ret += 1; // GOTCHA: LSL shows 2 additional sides here.
544 // This has been fixed, but may cause porting issues.
545 break;
546 case (int) PrimType.Torus:
547 ret = 1;
548 if (hasCut) ret += 2;
549 if (hasProfileCut) ret += 2;
550 if (hasHollow) ret += 1;
551 break;
552 case (int) PrimType.Tube:
553 ret = 4;
554 if (hasCut) ret += 2;
555 if (hasProfileCut) ret += 2;
556 if (hasHollow) ret += 1;
557 break;
558 case (int) PrimType.Ring:
559 ret = 3;
560 if (hasCut) ret += 2;
561 if (hasProfileCut) ret += 2;
562 if (hasHollow) ret += 1;
563 break;
564 case (int) PrimType.Sculpt:
565 ret = 1;
566 break;
567 }
568 return ret;
569 }
570
571
572 #endregion
573
574 #region IObjectPhysics
575
576 public bool Enabled
577 {
578 get { throw new System.NotImplementedException(); }
579 set { throw new System.NotImplementedException(); }
580 }
581
582 public bool Phantom
583 {
584 get { throw new System.NotImplementedException(); }
585 set { throw new System.NotImplementedException(); }
586 }
587
588 public bool PhantomCollisions
589 {
590 get { throw new System.NotImplementedException(); }
591 set { throw new System.NotImplementedException(); }
592 }
593
594 public double Density
595 {
596 get { return (GetSOP().PhysActor.Mass/Scale.X*Scale.Y/Scale.Z); }
597 set { throw new NotImplementedException(); }
598 }
599
600 public double Mass
601 {
602 get { return GetSOP().PhysActor.Mass; }
603 set { throw new NotImplementedException(); }
604 }
605
606 public double Buoyancy
607 {
608 get { return GetSOP().PhysActor.Buoyancy; }
609 set { GetSOP().PhysActor.Buoyancy = (float)value; }
610 }
611
612 public Vector3 GeometricCenter
613 {
614 get
615 {
616 Vector3 tmp = GetSOP().PhysActor.GeometricCenter;
617 return tmp;
618 }
619 }
620
621 public Vector3 CenterOfMass
622 {
623 get
624 {
625 Vector3 tmp = GetSOP().PhysActor.CenterOfMass;
626 return tmp;
627 }
628 }
629
630 public Vector3 RotationalVelocity
631 {
632 get
633 {
634 Vector3 tmp = GetSOP().PhysActor.RotationalVelocity;
635 return tmp;
636 }
637 set
638 {
639 if (!CanEdit())
640 return;
641
642 GetSOP().PhysActor.RotationalVelocity = value;
643 }
644 }
645
646 public Vector3 Velocity
647 {
648 get
649 {
650 Vector3 tmp = GetSOP().PhysActor.Velocity;
651 return tmp;
652 }
653 set
654 {
655 if (!CanEdit())
656 return;
657
658 GetSOP().PhysActor.Velocity = value;
659 }
660 }
661
662 public Vector3 Torque
663 {
664 get
665 {
666 Vector3 tmp = GetSOP().PhysActor.Torque;
667 return tmp;
668 }
669 set
670 {
671 if (!CanEdit())
672 return;
673
674 GetSOP().PhysActor.Torque = value;
675 }
676 }
677
678 public Vector3 Acceleration
679 {
680 get
681 {
682 Vector3 tmp = GetSOP().PhysActor.Acceleration;
683 return tmp;
684 }
685 }
686
687 public Vector3 Force
688 {
689 get
690 {
691 Vector3 tmp = GetSOP().PhysActor.Force;
692 return tmp;
693 }
694 set
695 {
696 if (!CanEdit())
697 return;
698
699 GetSOP().PhysActor.Force = value;
700 }
701 }
702
703 public bool FloatOnWater
704 {
705 set
706 {
707 if (!CanEdit())
708 return;
709 GetSOP().PhysActor.FloatOnWater = value;
710 }
711 }
712
713 public void AddForce(Vector3 force, bool pushforce)
714 {
715 if (!CanEdit())
716 return;
717
718 GetSOP().PhysActor.AddForce(force, pushforce);
719 }
720
721 public void AddAngularForce(Vector3 force, bool pushforce)
722 {
723 if (!CanEdit())
724 return;
725
726 GetSOP().PhysActor.AddAngularForce(force, pushforce);
727 }
728
729 public void SetMomentum(Vector3 momentum)
730 {
731 if (!CanEdit())
732 return;
733
734 GetSOP().PhysActor.SetMomentum(momentum);
735 }
736
737 #endregion
738
739 #region Implementation of IObjectShape
740
741 private UUID m_sculptMap = UUID.Zero;
742
743 public UUID SculptMap
744 {
745 get { return m_sculptMap; }
746 set
747 {
748 if (!CanEdit())
749 return;
750
751 m_sculptMap = value;
752 SetPrimitiveSculpted(SculptMap, (byte) SculptType);
753 }
754 }
755
756 private SculptType m_sculptType = Object.SculptType.Default;
757
758 public SculptType SculptType
759 {
760 get { return m_sculptType; }
761 set
762 {
763 if (!CanEdit())
764 return;
765
766 m_sculptType = value;
767 SetPrimitiveSculpted(SculptMap, (byte) SculptType);
768 }
769 }
770
771 public HoleShape HoleType
772 {
773 get { throw new System.NotImplementedException(); }
774 set { throw new System.NotImplementedException(); }
775 }
776
777 public double HoleSize
778 {
779 get { throw new System.NotImplementedException(); }
780 set { throw new System.NotImplementedException(); }
781 }
782
783 public PrimType PrimType
784 {
785 get { return (PrimType)getScriptPrimType(GetSOP().Shape); }
786 set { throw new System.NotImplementedException(); }
787 }
788
789 private void SetPrimitiveSculpted(UUID map, byte type)
790 {
791 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
792
793 SceneObjectPart part = GetSOP();
794
795 UUID sculptId = map;
796
797 shapeBlock.ObjectLocalID = part.LocalId;
798 shapeBlock.PathScaleX = 100;
799 shapeBlock.PathScaleY = 150;
800
801 // retain pathcurve
802 shapeBlock.PathCurve = part.Shape.PathCurve;
803
804 part.Shape.SetSculptProperties((byte)type, sculptId);
805 part.Shape.SculptEntry = true;
806 part.UpdateShape(shapeBlock);
807 }
808
809
810 #endregion
811
812
813 #region Implementation of IObjectSound
814
815 public IObjectSound Sound
816 {
817 get { return this; }
818 }
819
820 public void Play(UUID asset, double volume)
821 {
822 if (!CanEdit())
823 return;
824 ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>();
825 if (module != null)
826 {
827 module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false);
828 }
829 }
830
831 #endregion
832 }
833}