OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
SOPObject.cs
Go to the documentation of this file.
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.PhysicsModules.SharedBase;
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 
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 
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 }
SOPObject(Scene rootScene, uint localID, ISecurityCredential credential)
Definition: SOPObject.cs:56
void Dialog(UUID avatar, string message, string[] buttons, int chat_channel)
Opens a Dialog Panel in the Users Viewer, equivilent to LSL/OSSL llDialog
Definition: SOPObject.cs:410
OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.SculptType SculptType
Definition: SOPObject.cs:39
void AddAngularForce(Vector3 force, bool pushforce)
Definition: SOPObject.cs:721
OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.PrimType PrimType
Definition: SOPObject.cs:38
This implements an interface similar to that provided by physics engines to OpenSim internally...
delegate void OnTouchDelegate(IObject sender, TouchEventArgs e)
This implements the methods neccesary to operate on the inventory of an object
void Say(string msg)
Causes the object to speak to its surroundings, equivilent to LSL/OSSL llSay
Definition: SOPObject.cs:392
void Say(string msg, int channel)
Causes the object to speak to on a specific channel, equivilent to LSL/OSSL llSay ...
Definition: SOPObject.cs:401