diff --git a/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs index 7c0cd77f28..c3934795b3 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs @@ -104,11 +104,16 @@ namespace OpenSim.Region.Environment.Scenes { if (ent is SceneObjectGroup) { + if (((SceneObjectGroup) ent).LocalId == primLocalID) { - ((SceneObjectGroup) ent).GetProperties(remoteClient); - ((SceneObjectGroup) ent).IsSelected = true; - LandManager.setPrimsTainted(); + // A prim is only tainted if it's allowed to be edited by the person clicking it. + if (m_permissionManager.CanEditObjectPosition(remoteClient.AgentId, ((SceneObjectGroup)ent).UUID) || m_permissionManager.CanEditObject(remoteClient.AgentId, ((SceneObjectGroup)ent).UUID)) + { + ((SceneObjectGroup) ent).GetProperties(remoteClient); + ((SceneObjectGroup) ent).IsSelected = true; + LandManager.setPrimsTainted(); + } break; } } @@ -130,9 +135,12 @@ namespace OpenSim.Region.Environment.Scenes { if (((SceneObjectGroup) ent).LocalId == primLocalID) { - ((SceneObjectGroup) ent).IsSelected = false; - LandManager.setPrimsTainted(); - break; + if (m_permissionManager.CanEditObjectPosition(remoteClient.AgentId, ((SceneObjectGroup)ent).UUID) || m_permissionManager.CanEditObject(remoteClient.AgentId, ((SceneObjectGroup)ent).UUID)) + { + ((SceneObjectGroup) ent).IsSelected = false; + LandManager.setPrimsTainted(); + break; + } } } } diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs index 8fd9edb831..801e61408c 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs @@ -203,6 +203,14 @@ namespace OpenSim.Region.Environment.Scenes if (m_rootPart.PhysActor != null) { m_rootPart.PhysActor.Selected = value; + // Pass it on to the children. + foreach (SceneObjectPart child in Children.Values) + { + if (child.PhysActor != null) + { + child.PhysActor.Selected = value; + } + } } } } diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs index 4e96ce0bfe..e3b9ef341a 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs @@ -228,6 +228,11 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin set { return; } } + public override uint LocalID + { + set { return; } + } + public override bool Grabbed { set { return; } diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs index 180e14c368..8a4e4f4e52 100644 --- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs +++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs @@ -895,6 +895,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin set { return; } } + public override uint LocalID + { + set { return; } + } + public override bool Grabbed { set { return; } diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 7e88479a55..aa6cf43869 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -124,6 +124,8 @@ namespace OpenSim.Region.Physics.Manager public abstract PrimitiveBaseShape Shape { set; } + public abstract uint LocalID { set; } + public abstract bool Grabbed { set; } public abstract bool Selected { set; } @@ -228,6 +230,11 @@ namespace OpenSim.Region.Physics.Manager set { return; } } + public override uint LocalID + { + set { return; } + } + public override bool Grabbed { set { return; } diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index 499422f3d1..2efca3b278 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -87,6 +87,8 @@ namespace OpenSim.Region.Physics.OdePlugin private bool m_hackSentFall = false; private bool m_hackSentFly = false; private bool m_foundDebian = false; + public uint m_localID = 0; + private CollisionLocker ode; private string m_name = String.Empty; @@ -94,6 +96,15 @@ namespace OpenSim.Region.Physics.OdePlugin private bool[] m_colliderarr = new bool[11]; private bool[] m_colliderGroundarr = new bool[11]; + // Default we're a Character + private CollisionCategories m_collisionCategories = (CollisionCategories.Character); + + // Default, Collide with Other Geometries, spaces, bodies and characters. + private CollisionCategories m_collisionFlags = (CollisionCategories.Geom + | CollisionCategories.Space + | CollisionCategories.Body + | CollisionCategories.Character + | CollisionCategories.Land); private bool jumping = false; //private float gravityAccel; @@ -157,6 +168,11 @@ namespace OpenSim.Region.Physics.OdePlugin set { m_alwaysRun = value; } } + public override uint LocalID + { + set { m_localID = value; } + } + public override bool Grabbed { set { return; } @@ -404,6 +420,10 @@ namespace OpenSim.Region.Physics.OdePlugin int dAMotorEuler = 1; _parent_scene.waitForSpaceUnlock(_parent_scene.space); Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); + + d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); + d.GeomSetCollideBits(Shell, (int)m_collisionFlags); + d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH); Body = d.BodyCreate(_parent_scene.world); d.BodySetPosition(Body, npositionX, npositionY, npositionZ); diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 50087a5dac..6da22969bc 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -52,12 +52,30 @@ namespace OpenSim.Region.Physics.OdePlugin private PhysicsVector m_taintsize; private PhysicsVector m_taintVelocity = PhysicsVector.Zero; private Quaternion m_taintrot; + private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom + | CollisionCategories.Space + | CollisionCategories.Body + | CollisionCategories.Character); private bool m_taintshape = false; private bool m_taintPhysics = false; + private bool m_collidesLand = true; + private bool m_collidesWater = false; + + // Default we're a Geometry + private CollisionCategories m_collisionCategories = (CollisionCategories.Geom ); + + // Default, Collide with Other Geometries, spaces and Bodies + private CollisionCategories m_collisionFlags = m_default_collisionFlags; + public bool m_taintremove = false; public bool m_taintdisable = false; public bool m_disabled = false; public bool m_taintadd = false; + public bool m_taintselected = false; + + + public uint m_localID = 0; + public GCHandle gc; private CollisionLocker ode; @@ -74,6 +92,8 @@ namespace OpenSim.Region.Physics.OdePlugin private bool iscolliding = false; private bool m_isphysical = false; + private bool m_isSelected = false; + private bool m_throttleUpdates = false; private int throttleCounter = 0; public int m_interpenetrationcount = 0; @@ -172,6 +192,11 @@ namespace OpenSim.Region.Physics.OdePlugin set { return; } } + public override uint LocalID + { + set { m_localID = value; } + } + public override bool Grabbed { set { return; } @@ -179,17 +204,59 @@ namespace OpenSim.Region.Physics.OdePlugin public override bool Selected { - set { return; } + set { + // This only makes the object not collidable if the object + // is physical or the object is modified somehow *IN THE FUTURE* + // without this, if an avatar selects prim, they can walk right + // through it while it's selected + + if (m_isphysical || !value) + { + m_taintselected = value; + _parent_scene.AddPhysicsActorTaint(this); + } + else + { + + m_taintselected = value; + m_isSelected = value; + } + + } } public void SetGeom(IntPtr geom) { prev_geom = prim_geom; prim_geom = geom; + if (prim_geom != (IntPtr)0) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } //m_log.Warn("Setting Geom to: " + prim_geom); } + public void enableBodySoft() + { + if (m_isphysical) + if (Body != (IntPtr)0) + d.BodyEnable(Body); + + m_disabled = false; + } + + public void disableBodySoft() + { + m_disabled = true; + + if (m_isphysical) + if (Body != (IntPtr)0) + d.BodyDisable(Body); + } + + public void enableBody() { // Sets the geom to a body @@ -204,6 +271,13 @@ namespace OpenSim.Region.Physics.OdePlugin myrot.Z = _orientation.z; d.BodySetQuaternion(Body, ref myrot); d.GeomSetBody(prim_geom, Body); + m_collisionCategories |= CollisionCategories.Body; + m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + + d.BodySetAutoDisableFlag(Body, true); d.BodySetAutoDisableSteps(Body, 20); @@ -332,6 +406,15 @@ namespace OpenSim.Region.Physics.OdePlugin //this kills the body so things like 'mesh' can re-create it. if (Body != (IntPtr) 0) { + m_collisionCategories &= ~CollisionCategories.Body; + m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); + + if (prim_geom != (IntPtr)0) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + _parent_scene.remActivePrim(this); d.BodyDestroy(Body); Body = (IntPtr) 0; @@ -425,10 +508,81 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_taintdisable) changedisable(timestep); + if (m_taintselected != m_isSelected) + changeSelectedStatus(timestep); + if (m_taintVelocity != PhysicsVector.Zero) changevelocity(timestep); } + private void changeSelectedStatus(float timestep) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + if (m_taintselected) + { + + + m_collisionCategories = CollisionCategories.Selected; + m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); + + // We do the body disable soft twice because 'in theory' a collision could have happened + // in between the disabling and the collision properties setting + // which would wake the physical body up from a soft disabling and potentially cause it to fall + // through the ground. + + if (m_isphysical) + { + disableBodySoft(); + } + + if (prim_geom != (IntPtr)0) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + + if (m_isphysical) + { + disableBodySoft(); + } + + } + else + { + + m_collisionCategories = CollisionCategories.Geom; + + if (m_isphysical) + m_collisionCategories |= CollisionCategories.Body; + + + m_collisionFlags = m_default_collisionFlags; + + if (m_collidesLand) + m_collisionFlags |= CollisionCategories.Land; + if (m_collidesWater) + m_collisionFlags |= CollisionCategories.Water; + + if (prim_geom != (IntPtr)0) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + if (m_isphysical) + enableBodySoft(); + + + } + + ode.dunlock(_parent_scene.world); + resetCollisionAccounting(); + m_isSelected = m_taintselected; + } + public void ResetTaints() { @@ -438,6 +592,8 @@ namespace OpenSim.Region.Physics.OdePlugin m_taintPhysics = m_isphysical; + m_taintselected = m_isSelected; + m_taintsize = _size; @@ -586,6 +742,9 @@ namespace OpenSim.Region.Physics.OdePlugin ode.dunlock(_parent_scene.world); _parent_scene.geom_name_map[prim_geom] = this.m_primName; _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this; + + changeSelectedStatus(timestep); + m_taintadd = false; @@ -630,6 +789,8 @@ namespace OpenSim.Region.Physics.OdePlugin } ode.dunlock(_parent_scene.world); + changeSelectedStatus(timestep); + resetCollisionAccounting(); m_taintposition = _position; } @@ -682,7 +843,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_taintdisable = false; } - public void changePhysicsStatus(float timestap) + public void changePhysicsStatus(float timestep) { lock (ode) { @@ -709,6 +870,8 @@ namespace OpenSim.Region.Physics.OdePlugin ode.dunlock(_parent_scene.world); } + changeSelectedStatus(timestep); + resetCollisionAccounting(); m_taintPhysics = m_isphysical; } @@ -880,6 +1043,8 @@ namespace OpenSim.Region.Physics.OdePlugin ode.dunlock(_parent_scene.world); + changeSelectedStatus(timestamp); + resetCollisionAccounting(); m_taintsize = _size; } @@ -927,7 +1092,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Re creates body on size. // EnableBody also does setMass() enableBody(); - d.BodyEnable(Body); + } } else @@ -1032,66 +1197,76 @@ namespace OpenSim.Region.Physics.OdePlugin d.BodyEnable(Body); } } + + _parent_scene.geom_name_map[prim_geom] = oldname; ode.dunlock(_parent_scene.world); + changeSelectedStatus(timestamp); + resetCollisionAccounting(); m_taintshape = false; } public void changeAddForce(float timestamp) { - while (ode.lockquery()) - { - } - ode.dlock(_parent_scene.world); - - - lock (m_forcelist) - { - //m_log.Info("[PHYSICS]: dequeing forcelist"); - if (IsPhysical) - { - PhysicsVector iforce = new PhysicsVector(); - for (int i = 0; i < m_forcelist.Count; i++) - { - iforce = iforce + (m_forcelist[i]*100); - } - d.BodyEnable(Body); - d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); - } - m_forcelist.Clear(); - } - - ode.dunlock(_parent_scene.world); - - m_collisionscore = 0; - m_interpenetrationcount = 0; - m_taintforce = false; - - } - private void changevelocity(float timestep) - { - lock (ode) + if (!m_isSelected) { while (ode.lockquery()) { } ode.dlock(_parent_scene.world); - System.Threading.Thread.Sleep(20); - if (IsPhysical) + + lock (m_forcelist) { - if (Body != (IntPtr)0) + //m_log.Info("[PHYSICS]: dequeing forcelist"); + if (IsPhysical) { - d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); + PhysicsVector iforce = new PhysicsVector(); + for (int i = 0; i < m_forcelist.Count; i++) + { + iforce = iforce + (m_forcelist[i] * 100); + } + d.BodyEnable(Body); + d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); } + m_forcelist.Clear(); } ode.dunlock(_parent_scene.world); + + m_collisionscore = 0; + m_interpenetrationcount = 0; + } + m_taintforce = false; + + } + private void changevelocity(float timestep) + { + if (!m_isSelected) + { + lock (ode) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + System.Threading.Thread.Sleep(20); + if (IsPhysical) + { + if (Body != (IntPtr)0) + { + d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); + } + } + + ode.dunlock(_parent_scene.world); + } + //resetCollisionAccounting(); } - //resetCollisionAccounting(); m_taintVelocity = PhysicsVector.Zero; } public override bool IsPhysical diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index b3780fd36d..76bd3f2f76 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -78,6 +78,21 @@ namespace OpenSim.Region.Physics.OdePlugin } } + [Flags] + public enum CollisionCategories : int + { + Disabled = 0, + Geom = 0x00000001, + Body = 0x00000002, + Space = 0x00000004, + Character = 0x00000008, + Land = 0x00000010, + Water = 0x00000020, + Wind = 0x00000040, + Sensor = 0x00000080, + Selected = 0x00000100 + } + public class OdeScene : PhysicsScene { private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); @@ -997,6 +1012,7 @@ namespace OpenSim.Region.Physics.OdePlugin { // creating a new space for prim and inserting it into main space. staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); + d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space); waitForSpaceUnlock(space); d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; @@ -1656,6 +1672,12 @@ namespace OpenSim.Region.Physics.OdePlugin offset, thickness, wrap); d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); LandGeom = d.CreateHeightfield(space, HeightmapData, 1); + if (LandGeom != (IntPtr)0) + { + d.GeomSetCategoryBits(LandGeom, (int)(CollisionCategories.Land)); + d.GeomSetCollideBits(LandGeom, (int)(CollisionCategories.Space)); + + } geom_name_map[LandGeom] = "Terrain"; d.Matrix3 R = new d.Matrix3(); diff --git a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs b/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs index 6d1bec707a..9d70ac8b38 100644 --- a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs +++ b/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs @@ -357,6 +357,11 @@ namespace OpenSim.Region.Physics.POSPlugin set { return; } } + public override uint LocalID + { + set { return; } + } + public override bool Grabbed { set { return; } @@ -645,6 +650,11 @@ namespace OpenSim.Region.Physics.POSPlugin set { return; } } + public override uint LocalID + { + set { return; } + } + public override bool Grabbed { set { return; } diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs index 970f6fb642..83930c3d24 100644 --- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs +++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs @@ -227,6 +227,11 @@ namespace OpenSim.Region.Physics.PhysXPlugin set { return; } } + public override uint LocalID + { + set { return; } + } + public override bool Grabbed { set { return; } @@ -437,6 +442,11 @@ namespace OpenSim.Region.Physics.PhysXPlugin set { return; } } + public override uint LocalID + { + set { return; } + } + public override bool Grabbed { set { return; }