opensim-development – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 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  
28 using System;
29 using System.Collections.Generic;
30 using System.Security;
31 using OpenMetaverse;
32 using OpenMetaverse.Packets;
33 using OpenSim.Framework;
34 using OpenSim.Region.Framework.Interfaces;
35 using OpenSim.Region.Framework.Scenes;
36 using OpenSim.Region.OptionalModules.Scripting.Minimodule.Object;
37 using OpenSim.Region.Physics.Manager;
38 using PrimType=OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.PrimType;
39 using SculptType=OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.SculptType;
40  
41 namespace 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 }