/// <summary> /// Add an object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. /// </summary> /// <param name="sceneObject"></param> /// <param name="attachToBackup"> /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// </param> /// <param name="sendClientUpdates"> /// If true, updates for the new scene object are sent to all viewers in range. /// If false, it is left to the caller to schedule the update /// </param> /// <returns> /// true if the object was added, false if an object with the same uuid was already in the scene /// </returns> protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) return false; bool alreadyExisted = false; if (m_parentScene.m_clampPrimSize) { foreach (SceneObjectPart part in sceneObject.Children.Values) { Vector3 scale = part.Shape.Scale; if (scale.X > m_parentScene.m_maxNonphys) scale.X = m_parentScene.m_maxNonphys; if (scale.Y > m_parentScene.m_maxNonphys) scale.Y = m_parentScene.m_maxNonphys; if (scale.Z > m_parentScene.m_maxNonphys) scale.Z = m_parentScene.m_maxNonphys; part.Shape.Scale = scale; } } sceneObject.AttachToScene(m_parentScene); if (sendClientUpdates) sceneObject.ScheduleGroupForFullUpdate(); lock (sceneObject) { if (!Entities.ContainsKey(sceneObject.UUID)) { Entities.Add(sceneObject); m_numPrim += sceneObject.Children.Count; if (attachToBackup) sceneObject.AttachToBackup(); if (OnObjectCreate != null) OnObjectCreate(sceneObject); lock (m_dictionary_lock) { SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; foreach (SceneObjectPart part in sceneObject.Children.Values) { SceneObjectGroupsByFullID[part.UUID] = sceneObject; SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; } } } else { alreadyExisted = true; } } return alreadyExisted; }
public SceneObjectGroup CreateEntity( UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) { if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0) { m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name); return null; } SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape, m_scene); SceneObjectPart rootPart = sceneObject.GetChildPart(sceneObject.UUID); rootPart.AddFlag(PrimFlags.Phantom); if (rootPart.Shape.PCode != (byte)PCode.Grass) { // Tree size has to be adapted depending on its type switch ((Tree)rootPart.Shape.State) { case Tree.Cypress1: case Tree.Cypress2: case Tree.Palm1: case Tree.Palm2: case Tree.WinterAspen: rootPart.Scale = new Vector3(4, 4, 10); break; case Tree.WinterPine1: case Tree.WinterPine2: rootPart.Scale = new Vector3(4, 4, 20); break; case Tree.Dogwood: rootPart.Scale = new Vector3(6.5f, 6.5f, 6.5f); break; // case... other tree types // tree.Scale = new Vector3(?, ?, ?); // break; default: rootPart.Scale = new Vector3(4, 4, 4); break; } } m_scene.AddPrimToScene(sceneObject); sceneObject.ScheduleGroupForFullUpdate(PrimUpdateFlags.FullUpdate); sceneObject.SetGroup(groupID, null); return sceneObject; }
/// <summary> /// Add an object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. /// </summary> /// <remarks> /// The object's stored position, rotation and velocity are used. /// </remarks> /// <param name="sceneObject"></param> /// <param name="attachToBackup"> /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// </param> /// <param name="sendClientUpdates"> /// If true, updates for the new scene object are sent to all viewers in range. /// If false, it is left to the caller to schedule the update /// </param> /// <returns> /// true if the object was added, false if an object with the same uuid was already in the scene /// </returns> protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (sceneObject.UUID == UUID.Zero) { m_log.ErrorFormat( "[SCENEGRAPH]: Tried to add scene object {0} to {1} with illegal UUID of {2}", sceneObject.Name, m_parentScene.RegionInfo.RegionName, UUID.Zero); return false; } if (Entities.ContainsKey(sceneObject.UUID)) { m_log.DebugFormat( "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()", m_parentScene.RegionInfo.RegionName, sceneObject.UUID); return false; } // m_log.DebugFormat( // "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}", // sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName); SceneObjectPart[] parts = sceneObject.Parts; // Clamp child prim sizes and add child prims to the m_numPrim count if (m_parentScene.m_clampPrimSize) { foreach (SceneObjectPart part in parts) { Vector3 scale = part.Shape.Scale; scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); part.Shape.Scale = scale; } } m_numPrim += parts.Length; sceneObject.AttachToScene(m_parentScene); if (sendClientUpdates) sceneObject.ScheduleGroupForFullUpdate(); Entities.Add(sceneObject); if (attachToBackup) sceneObject.AttachToBackup(); lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; lock (SceneObjectGroupsByFullPartID) { foreach (SceneObjectPart part in parts) SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; } lock (SceneObjectGroupsByLocalPartID) { // m_log.DebugFormat( // "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}", // sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName); foreach (SceneObjectPart part in parts) SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; } return true; }
/// <summary> /// Attach this scene object to the given avatar. /// </summary> /// <remarks> /// This isn't publicly available since attachments should always perform the corresponding inventory /// operation (to show the attach in user inventory and update the asset with positional information). /// </remarks> /// <param name="sp"></param> /// <param name="so"></param> /// <param name="attachmentpoint"></param> /// <param name="attachOffset"></param> /// <param name="silent"></param> private void AttachToAgent( IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) { if (DebugLevel > 0) m_log.DebugFormat( "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); so.DetachFromBackup(); // Remove from database and parcel prim count m_scene.DeleteFromStorage(so.UUID); m_scene.EventManager.TriggerParcelPrimCountTainted(); so.AttachedAvatar = sp.UUID; if (so.RootPart.PhysActor != null) so.RootPart.RemoveFromPhysics(); so.AbsolutePosition = attachOffset; so.RootPart.AttachedPos = attachOffset; so.IsAttachment = true; so.RootPart.SetParentLocalId(sp.LocalId); so.AttachmentPoint = attachmentpoint; sp.AddAttachment(so); if (!silent) { if (so.HasPrivateAttachmentPoint) { if (DebugLevel > 0) m_log.DebugFormat( "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}", so.Name, sp.Name, so.AttachmentPoint); // As this scene object can now only be seen by the attaching avatar, tell everybody else in the // scene that it's no longer in their awareness. m_scene.ForEachClient( client => { if (client.AgentId != so.AttachedAvatar) client.SendKillObject(new List<uint>() { so.LocalId }); }); } // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update // will succeed, as that will not update if an attachment is selected. so.IsSelected = false; // fudge.... so.ScheduleGroupForFullUpdate(); } // In case it is later dropped again, don't let // it get cleaned up so.RootPart.RemFlag(PrimFlags.TemporaryOnRez); }
/// <summary> /// Add an object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. /// </summary> /// <param name="sceneObject"></param> /// <param name="attachToBackup"> /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// </param> /// <param name="sendClientUpdates"> /// If true, updates for the new scene object are sent to all viewers in range. /// If false, it is left to the caller to schedule the update /// </param> /// <returns> /// true if the object was added, false if an object with the same uuid was already in the scene /// </returns> protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) return false; //if (Entities.ContainsKey(sceneObject.UUID)) //{ // m_log.WarnFormat( // "[SCENE GRAPH]: Scene object {0} {1} was already in region {2} on add request", // sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); // return false; //} IOpenRegionSettingsModule WSModule = sceneObject.Scene.RequestModuleInterface<IOpenRegionSettingsModule>(); if (WSModule != null) { foreach (SceneObjectPart part in sceneObject.ChildrenList) { if (part.Shape == null) continue; Vector3 scale = part.Shape.Scale; if (WSModule.MinimumPrimScale != -1) { if (scale.X < WSModule.MinimumPrimScale) scale.X = WSModule.MinimumPrimScale; if (scale.Y < WSModule.MinimumPrimScale) scale.Y = WSModule.MinimumPrimScale; if (scale.Z < WSModule.MinimumPrimScale) scale.Z = WSModule.MinimumPrimScale; } if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical && WSModule.MaximumPhysPrimScale != -1) { if (scale.X > WSModule.MaximumPhysPrimScale) scale.X = WSModule.MaximumPhysPrimScale; if (scale.Y > WSModule.MaximumPhysPrimScale) scale.Y = WSModule.MaximumPhysPrimScale; if (scale.Z > WSModule.MaximumPhysPrimScale) scale.Z = WSModule.MaximumPhysPrimScale; } if (WSModule.MaximumPrimScale != -1) { if (scale.X > WSModule.MaximumPrimScale) scale.X = WSModule.MaximumPrimScale; if (scale.Y > WSModule.MaximumPrimScale) scale.Y = WSModule.MaximumPrimScale; if (scale.Z > WSModule.MaximumPrimScale) scale.Z = WSModule.MaximumPrimScale; } part.Shape.Scale = scale; } } sceneObject.AttachToScene(m_parentScene); Entities.Add(sceneObject); if (sendClientUpdates) sceneObject.ScheduleGroupForFullUpdate(PrimUpdateFlags.FullUpdate); m_numPrim += sceneObject.ChildrenList.Count; return true; }
/// <summary> /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. /// /// Using the objects new world location, ask the grid service for a the new region and adjust the prim /// position to be relative to the new region. /// </summary> /// <param name="grp">the scene object that we're crossing</param> /// <param name="attemptedPosition">the attempted out of region position of the scene object. This position is /// relative to the region the object currently is in.</param> /// <param name="silent">if 'true', the deletion of the client from the region is not broadcast to the clients</param> public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) { if (grp == null) return; if (grp.IsDeleted) return; Scene scene = grp.Scene; if (scene == null) return; if (grp.RootPart.DIE_AT_EDGE) { // We remove the object here try { scene.DeleteSceneObject(grp, false); } catch (Exception) { m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); } return; } // Remember the old group position in case the region lookup fails so position can be restored. Vector3 oldGroupPosition = grp.RootPart.GroupPosition; // Compute the absolute position of the object. double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X; double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y; // Ask the grid service for the region that contains the passed address GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID, objectWorldLocX, objectWorldLocY); Vector3 pos = Vector3.Zero; if (destination != null) { // Adjust the object's relative position from the old region (attemptedPosition) // to be relative to the new region (pos). pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX), (float)(objectWorldLocY - (double)destination.RegionLocY), attemptedPosition.Z); } if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) { m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID); // We are going to move the object back to the old position so long as the old position // is in the region oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1)); oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1)); oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 1.0f, Constants.RegionHeight); grp.AbsolutePosition = oldGroupPosition; grp.Velocity = Vector3.Zero; if (grp.RootPart.PhysActor != null) grp.RootPart.PhysActor.CrossingFailure(); if (grp.RootPart.KeyframeMotion != null) grp.RootPart.KeyframeMotion.CrossingFailure(); grp.ScheduleGroupForFullUpdate(); } }
/// <summary> /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. /// /// This method locates the new region handle and offsets the prim position for the new region /// </summary> /// <param name="attemptedPosition">the attempted out of region position of the scene object</param> /// <param name="grp">the scene object that we're crossing</param> public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) { if (grp == null) return; if (grp.IsDeleted) return; Scene scene = grp.Scene; if (scene == null) return; if (grp.RootPart.DIE_AT_EDGE) { // We remove the object here try { scene.DeleteSceneObject(grp, false, true); } catch (Exception) { m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); } return; } int thisx = (int)scene.RegionInfo.RegionLocX; int thisy = (int)scene.RegionInfo.RegionLocY; Vector3 EastCross = new Vector3(0.1f, 0, 0); Vector3 WestCross = new Vector3(-0.1f, 0, 0); Vector3 NorthCross = new Vector3(0, 0.1f, 0); Vector3 SouthCross = new Vector3(0, -0.1f, 0); // use this if no borders were crossed! ulong newRegionHandle = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize), (uint)((thisy) * Constants.RegionSize)); Vector3 pos = attemptedPosition; int changeX = 1; int changeY = 1; if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W)) { if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x - 1 // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x - 1 // y + 1 } else { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x - 1 } } else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E)) { if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { pos.X = ((pos.X - Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x + 1 // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.X = ((pos.X - Constants.RegionSize)); pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x + 1 // y + 1 } else { pos.X = ((pos.X - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x + 1 } } else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // y + 1 } // Offset the positions for the new region across the border Vector3 oldGroupPosition = grp.RootPart.GroupPosition; grp.OffsetForNewRegion(pos); // If we fail to cross the border, then reset the position of the scene object on that border. uint x = 0, y = 0; Utils.LongToUInts(newRegionHandle, out x, out y); GridRegion destination = scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); if (destination != null && !CrossPrimGroupIntoNewRegion(destination, grp, silent)) { grp.OffsetForNewRegion(oldGroupPosition); grp.ScheduleGroupForFullUpdate(PrimUpdateFlags.FullUpdate); } }
void DoSierpinski(SceneObjectGroup sog, Vector3 scale) { //replace the original prim with 5 new prims Vector3 newsize = new Vector3(scale.X / 2, scale.Y / 2, scale.Z / 2); Vector3 offset = new Vector3(scale.X / 4, scale.Y / 4, scale.Z / 4); Vector3 pos = sog.AbsolutePosition; //Move and resize the existing prim to become the new prim#1 //This is much faster than creating a new one and deleting the old Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z + offset.Z); sog.AbsolutePosition = newpos; sog.RootPart.Scale = newsize; sog.ScheduleGroupForFullUpdate(); m_newprims.Add(sog); // Add new prim#2 PrimitiveBaseShape prim2 = PrimitiveBaseShape.CreateBox(); prim2.Textures = new Primitive.TextureEntry(new UUID("5748decc-f629-461c-9a36-a35a236fe36f")); newpos = new Vector3(pos.X - offset.X, pos.Y - offset.Y, pos.Z - offset.Z); SceneObjectGroup newsog2 = new SceneObjectGroup(UUID.Zero, newpos, prim2); newsog2.RootPart.Scale = newsize; m_newprims.Add(newsog2); //add it to our list of managed objects m_scene.AddNewSceneObject(newsog2, false); //add it to the scene (not backed up to the db) Primitive.TextureEntry tex = newsog2.RootPart.Shape.Textures; tex.DefaultTexture.RGBA = RandomColor(); newsog2.RootPart.UpdateTexture(tex); // Add new prim#3 PrimitiveBaseShape prim3 = PrimitiveBaseShape.CreateBox(); prim3.Textures = new Primitive.TextureEntry(new UUID("5748decc-f629-461c-9a36-a35a236fe36f")); newpos = new Vector3(pos.X - offset.X, pos.Y + offset.Y, pos.Z - offset.Z); SceneObjectGroup newsog3 = new SceneObjectGroup(UUID.Zero, newpos, prim3); newsog3.RootPart.Scale = newsize; m_newprims.Add(newsog3); //add it to our list of managed objects m_scene.AddNewSceneObject(newsog3, false); //add it to the scene (not backed up to the db) tex = newsog3.RootPart.Shape.Textures; tex.DefaultTexture.RGBA = RandomColor(); newsog3.RootPart.UpdateTexture(tex); // Add new prim#4 PrimitiveBaseShape prim4 = PrimitiveBaseShape.CreateBox(); prim4.Textures = new Primitive.TextureEntry(new UUID("5748decc-f629-461c-9a36-a35a236fe36f")); newpos = new Vector3(pos.X + offset.X, pos.Y - offset.Y, pos.Z - offset.Z); SceneObjectGroup newsog4 = new SceneObjectGroup(UUID.Zero, newpos, prim4); newsog4.RootPart.Scale = newsize; m_newprims.Add(newsog4); //add it to our list of managed objects m_scene.AddNewSceneObject(newsog4, false); //add it to the scene (not backed up to the db) tex = newsog4.RootPart.Shape.Textures; tex.DefaultTexture.RGBA = RandomColor(); newsog4.RootPart.UpdateTexture(tex); // Add new prim#5 PrimitiveBaseShape prim5 = PrimitiveBaseShape.CreateBox(); prim5.Textures = new Primitive.TextureEntry(new UUID("5748decc-f629-461c-9a36-a35a236fe36f")); newpos = new Vector3(pos.X + offset.X, pos.Y + offset.Y, pos.Z - offset.Z); SceneObjectGroup newsog5 = new SceneObjectGroup(UUID.Zero, newpos, prim5); newsog5.RootPart.Scale = newsize; m_newprims.Add(newsog5); //add it to our list of managed objects m_scene.AddNewSceneObject(newsog5, false); //add it to the scene (not backed up to the db) tex = newsog5.RootPart.Shape.Textures; tex.DefaultTexture.RGBA = RandomColor(); newsog5.RootPart.UpdateTexture(tex); }
/// <summary> /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. /// /// This method locates the new region handle and offsets the prim position for the new region /// </summary> /// <param name="attemptedPosition">the attempted out of region position of the scene object</param> /// <param name="grp">the scene object that we're crossing</param> public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) { if (grp == null) return; if (grp.IsDeleted) return; Scene scene = grp.Scene; if (scene == null) return; if (grp.RootPart.DIE_AT_EDGE) { // We remove the object here try { scene.DeleteSceneObject(grp, false); } catch (Exception) { m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); } return; } int thisx = (int)scene.RegionInfo.RegionLocX; int thisy = (int)scene.RegionInfo.RegionLocY; Vector3 EastCross = new Vector3(0.1f, 0, 0); Vector3 WestCross = new Vector3(-0.1f, 0, 0); Vector3 NorthCross = new Vector3(0, 0.1f, 0); Vector3 SouthCross = new Vector3(0, -0.1f, 0); // use this if no borders were crossed! ulong newRegionHandle = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize), (uint)((thisy) * Constants.RegionSize)); Vector3 pos = attemptedPosition; int changeX = 1; int changeY = 1; if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W)) { if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x - 1 // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x - 1 // y + 1 } else { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x - 1 } } else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E)) { if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { pos.X = ((pos.X - Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x + 1 // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.X = ((pos.X - Constants.RegionSize)); pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x + 1 // y + 1 } else { pos.X = ((pos.X - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x + 1 } } else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // y + 1 } // Offset the positions for the new region across the border Vector3 oldGroupPosition = grp.RootPart.GroupPosition; // If we fail to cross the border, then reset the position of the scene object on that border. uint x = 0, y = 0; Utils.LongToUInts(newRegionHandle, out x, out y); GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) { m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}",grp.UUID); // We are going to move the object back to the old position so long as the old position // is in the region oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X,1.0f,(float)Constants.RegionSize-1); oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y,1.0f,(float)Constants.RegionSize-1); oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z,1.0f,4096.0f); grp.RootPart.GroupPosition = oldGroupPosition; // Need to turn off the physics flags, otherwise the object will continue to attempt to // move out of the region creating an infinite loop of failed attempts to cross grp.UpdatePrimFlags(grp.RootPart.LocalId,false,grp.IsTemporary,grp.IsPhantom,false); grp.ScheduleGroupForFullUpdate(); } }
/// <summary> /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. /// /// This method locates the new region handle and offsets the prim position for the new region /// </summary> /// <param name="attemptedPosition">the attempted out of region position of the scene object</param> /// <param name="grp">the scene object that we're crossing</param> public void CrossPrimGroupIntoNewRegion(Vector3 attemptedPosition, SceneObjectGroup grp, bool silent) { if (grp == null) return; if (grp.IsDeleted) return; if (grp.RootPart.DIE_AT_EDGE) { // We remove the object here try { DeleteSceneObject(grp, false); } catch (Exception) { m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); } return; } if (grp.RootPart.RETURN_AT_EDGE) { // We remove the object here try { List<SceneObjectGroup> objects = new List<SceneObjectGroup>(); objects.Add(grp); SceneObjectGroup[] objectsArray = objects.ToArray(); returnObjects(objectsArray, UUID.Zero); } catch (Exception) { m_log.Warn("[DATABASE]: exception when trying to return the prim that crossed the border."); } return; } int thisx = (int)RegionInfo.RegionLocX; int thisy = (int)RegionInfo.RegionLocY; Vector3 EastCross = new Vector3(0.1f,0,0); Vector3 WestCross = new Vector3(-0.1f, 0, 0); Vector3 NorthCross = new Vector3(0, 0.1f, 0); Vector3 SouthCross = new Vector3(0, -0.1f, 0); // use this if no borders were crossed! ulong newRegionHandle = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize), (uint)((thisy) * Constants.RegionSize)); Vector3 pos = attemptedPosition; int changeX = 1; int changeY = 1; if (TestBorderCross(attemptedPosition + WestCross, Cardinals.W)) { if (TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBorderx = GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z /(int) Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x - 1 // y - 1 } else if (TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { Border crossedBorderx = GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) try { if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x - 1 // y + 1 } catch (Exception ex) { } } else { Border crossedBorderx = GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint) (thisy*Constants.RegionSize)); // x - 1 } } else if (TestBorderCross(attemptedPosition + EastCross, Cardinals.E)) { if (TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { pos.X = ((pos.X - Constants.RegionSize)); Border crossedBordery = GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x + 1 // y - 1 } else if (TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.X = ((pos.X - Constants.RegionSize)); pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x + 1 // y + 1 } else { pos.X = ((pos.X - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint) (thisy*Constants.RegionSize)); // x + 1 } } else if (TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBordery = GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // y - 1 } else if (TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // y + 1 } // Offset the positions for the new region across the border Vector3 oldGroupPosition = grp.RootPart.GroupPosition; grp.OffsetForNewRegion(pos); // If we fail to cross the border, then reset the position of the scene object on that border. if (!CrossPrimGroupIntoNewRegion(newRegionHandle, grp, silent)) { grp.OffsetForNewRegion(oldGroupPosition); grp.ScheduleGroupForFullUpdate(); } }
/// <summary> /// Add an object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. /// </summary> /// <remarks> /// The object's stored position, rotation and velocity are used. /// </remarks> /// <param name="sceneObject"></param> /// <param name="attachToBackup"> /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// </param> /// <param name="sendClientUpdates"> /// If true, updates for the new scene object are sent to all viewers in range. /// If false, it is left to the caller to schedule the update /// </param> /// <returns> /// true if the object was added, false if an object with the same uuid was already in the scene /// </returns> protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (sceneObject == null || sceneObject.RootPart.UUID == UUID.Zero) return false; if (Entities.ContainsKey(sceneObject.UUID)) return false; // m_log.DebugFormat( // "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}", // sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName); SceneObjectPart[] parts = sceneObject.Parts; // Clamp child prim sizes and add child prims to the m_numPrim count if (m_parentScene.m_clampPrimSize) { foreach (SceneObjectPart part in parts) { Vector3 scale = part.Shape.Scale; if (scale.X > m_parentScene.m_maxNonphys) scale.X = m_parentScene.m_maxNonphys; if (scale.Y > m_parentScene.m_maxNonphys) scale.Y = m_parentScene.m_maxNonphys; if (scale.Z > m_parentScene.m_maxNonphys) scale.Z = m_parentScene.m_maxNonphys; part.Shape.Scale = scale; } } m_numPrim += parts.Length; sceneObject.AttachToScene(m_parentScene); if (sendClientUpdates) sceneObject.ScheduleGroupForFullUpdate(); Entities.Add(sceneObject); if (attachToBackup) sceneObject.AttachToBackup(); if (OnObjectCreate != null) OnObjectCreate(sceneObject); lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; lock (SceneObjectGroupsByFullPartID) { foreach (SceneObjectPart part in parts) SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; } lock (SceneObjectGroupsByLocalPartID) { // m_log.DebugFormat( // "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}", // sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName); foreach (SceneObjectPart part in parts) SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; } return true; }
/// <summary> /// Add an object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. /// </summary> /// <param name="sceneObject"></param> /// <param name="attachToBackup"> /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// </param> /// <param name="sendClientUpdates"> /// If true, updates for the new scene object are sent to all viewers in range. /// If false, it is left to the caller to schedule the update /// </param> /// <returns> /// true if the object was added, false if an object with the same uuid was already in the scene /// </returns> protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) return false; if (Entities.ContainsKey(sceneObject.UUID)) return false; SceneObjectPart[] children = sceneObject.Parts; // Clamp child prim sizes and add child prims to the m_numPrim count if (m_parentScene.m_clampPrimSize) { foreach (SceneObjectPart part in children) { Vector3 scale = part.Shape.Scale; if (scale.X > m_parentScene.m_maxNonphys) scale.X = m_parentScene.m_maxNonphys; if (scale.Y > m_parentScene.m_maxNonphys) scale.Y = m_parentScene.m_maxNonphys; if (scale.Z > m_parentScene.m_maxNonphys) scale.Z = m_parentScene.m_maxNonphys; part.Shape.Scale = scale; } } m_numPrim += children.Length; sceneObject.AttachToScene(m_parentScene); if (sendClientUpdates) sceneObject.ScheduleGroupForFullUpdate(); Entities.Add(sceneObject); if (attachToBackup) sceneObject.AttachToBackup(); if (OnObjectCreate != null) OnObjectCreate(sceneObject); lock (SceneObjectGroupsByFullID) { SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; foreach (SceneObjectPart part in children) SceneObjectGroupsByFullID[part.UUID] = sceneObject; } lock (SceneObjectGroupsByLocalID) { SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; foreach (SceneObjectPart part in children) SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; } return true; }
/// <summary> /// Add an object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. /// </summary> /// <param name="sceneObject"></param> /// <param name="attachToBackup"> /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// </param> /// <param name="sendClientUpdates"> /// If true, updates for the new scene object are sent to all viewers in range. /// If false, it is left to the caller to schedule the update /// </param> /// <returns> /// true if the object was added, false if an object with the same uuid was already in the scene /// </returns> protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) return false; lock (sceneObject) { if (Entities.ContainsKey(sceneObject.UUID)) { // m_log.WarnFormat( // "[SCENE GRAPH]: Scene object {0} {1} was already in region {2} on add request", // sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); return false; } // m_log.DebugFormat( // "[SCENE GRAPH]: Adding object {0} {1} to region {2}", // sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); if (m_parentScene.m_clampPrimSize) { foreach (SceneObjectPart part in sceneObject.Children.Values) { Vector3 scale = part.Shape.Scale; if (scale.X > m_parentScene.m_maxNonphys) scale.X = m_parentScene.m_maxNonphys; if (scale.Y > m_parentScene.m_maxNonphys) scale.Y = m_parentScene.m_maxNonphys; if (scale.Z > m_parentScene.m_maxNonphys) scale.Z = m_parentScene.m_maxNonphys; part.Shape.Scale = scale; } } sceneObject.AttachToScene(m_parentScene); if (sendClientUpdates) sceneObject.ScheduleGroupForFullUpdate(); Entities.Add(sceneObject); m_numPrim += sceneObject.Children.Count; if (attachToBackup) sceneObject.AttachToBackup(); if (OnObjectCreate != null) OnObjectCreate(sceneObject); lock (m_dictionary_lock) { SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; foreach (SceneObjectPart part in sceneObject.Children.Values) { SceneObjectGroupsByFullID[part.UUID] = sceneObject; SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; } } } return true; }
/// <summary> /// Add a given object to the world. If you prefer argument to use default value, when pass it as null. /// *There is 1 compulsory fields which is position of the object. The rest are optionals. /// By Thanakorn Tuanwachat 07/2013 /// </summary> /// <param name="name">Name of this object. Use default value "primative" if null is given</param> /// <param name="position">"Vector(x y z) where x, y, and z represent the coordinates in the world"</param> /// <param name="dimension">"Vector(x, y, z) where x, y, and z represent the size of the object"</param> /// <param name="rotation">double(x, y, z) where x, y, and z represent angle of rotation from its axis in radian</param> /// <param name="primType">There are only 3 types which are Box, </param> /// <param name="script"> The LSL script which will be attached to this object</param> public void addObjectToTheWorld(string name, Vector3 position, Vector3 dimension, Quaternion rotation, int primType, string script) { //Generate a new UUID for this ray UUID rayUUID = UUID.Random(); //Place an object into the world. It can either be Box, Sphere, or Cylinder. according to the given PrimType SceneObjectGroup sog; switch (primType) { case PrimType.Box: sog = new SceneObjectGroup(new UUID(rayUUID), position, OpenSim.Framework.PrimitiveBaseShape.CreateBox()); break; case PrimType.Sphere: sog = new SceneObjectGroup(new UUID(rayUUID), position, OpenSim.Framework.PrimitiveBaseShape.CreateSphere()); break; case PrimType.Cylinder: sog = new SceneObjectGroup(new UUID(rayUUID), position, OpenSim.Framework.PrimitiveBaseShape.CreateCylinder()); break; default: sog = new SceneObjectGroup(new UUID(rayUUID), position, OpenSim.Framework.PrimitiveBaseShape.CreateBox()); break; }//switch //Check if it is possible to set thses parameters. If not then use default value if(dimension != null) { sog.RootPart.Scale = dimension; } if(rotation != null) { sog.RootPart.UpdateRotation(rotation); }//if if(name != null) { sog.Name = name; }//if else { sog.Name = "Primative"; }//else if (script != null) { addScript(sog.RootPart, script); } //Add this object to the scene. m_scene.AddNewSceneObject(sog, false); sog.ScheduleGroupForFullUpdate(); sog.HasGroupChanged = true; addedSog.Add(sog); }
/// <summary> /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. /// /// This method locates the new region handle and offsets the prim position for the new region /// </summary> /// <param name="attemptedPosition">the attempted out of region position of the scene object</param> /// <param name="grp">the scene object that we're crossing</param> public void CrossPrimGroupIntoNewRegion(Vector3 attemptedPosition, SceneObjectGroup grp, bool silent) { if (grp == null) return; if (grp.IsDeleted) return; if (grp.RootPart.DIE_AT_EDGE) { // We remove the object here try { DeleteSceneObject(grp, false); } catch (Exception) { m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); } return; } int thisx = (int)RegionInfo.RegionLocX; int thisy = (int)RegionInfo.RegionLocY; ulong newRegionHandle = 0; Vector3 pos = attemptedPosition; if (attemptedPosition.X > Constants.RegionSize + 0.1f) { pos.X = ((pos.X - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + 1) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x + 1 } else if (attemptedPosition.X < -0.1f) { pos.X = ((pos.X + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - 1) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x - 1 } if (attemptedPosition.Y > Constants.RegionSize + 0.1f) { pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + 1) * Constants.RegionSize)); // y + 1 } else if (attemptedPosition.Y < -0.1f) { pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - 1) * Constants.RegionSize)); // y - 1 } // Offset the positions for the new region across the border Vector3 oldGroupPosition = grp.RootPart.GroupPosition; grp.OffsetForNewRegion(pos); // If we fail to cross the border, then reset the position of the scene object on that border. if (!CrossPrimGroupIntoNewRegion(newRegionHandle, grp, silent)) { grp.OffsetForNewRegion(oldGroupPosition); grp.ScheduleGroupForFullUpdate(); } }
/// <summary> /// Attach this scene object to the given avatar. /// </summary> /// <remarks> /// This isn't publicly available since attachments should always perform the corresponding inventory /// operation (to show the attach in user inventory and update the asset with positional information). /// </remarks> /// <param name="sp"></param> /// <param name="so"></param> /// <param name="attachmentpoint"></param> /// <param name="attachOffset"></param> /// <param name="silent"></param> private void AttachToAgent( IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) { // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); so.DetachFromBackup(); // Remove from database and parcel prim count m_scene.DeleteFromStorage(so.UUID); m_scene.EventManager.TriggerParcelPrimCountTainted(); so.AttachedAvatar = sp.UUID; if (so.RootPart.PhysActor != null) so.RootPart.RemoveFromPhysics(); so.AbsolutePosition = attachOffset; so.RootPart.AttachedPos = attachOffset; so.IsAttachment = true; so.RootPart.SetParentLocalId(sp.LocalId); so.AttachmentPoint = attachmentpoint; sp.AddAttachment(so); if (!silent) { // Killing it here will cause the client to deselect it // It then reappears on the avatar, deselected // through the full update below // if (so.IsSelected) { m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId }); } so.IsSelected = false; // fudge.... so.ScheduleGroupForFullUpdate(); } // In case it is later dropped again, don't let // it get cleaned up so.RootPart.RemFlag(PrimFlags.TemporaryOnRez); }
/// <summary> /// Attach this scene object to the given avatar. /// </summary> /// <remarks> /// This isn't publicly available since attachments should always perform the corresponding inventory /// operation (to show the attach in user inventory and update the asset with positional information). /// </remarks> /// <param name="sp"></param> /// <param name="so"></param> /// <param name="attachmentpoint"></param> /// <param name="attachOffset"></param> /// <param name="silent"></param> private void AttachToAgent( IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) { // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", // so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); so.DetachFromBackup(); // Remove from database and parcel prim count m_scene.DeleteFromStorage(so.UUID); m_scene.EventManager.TriggerParcelPrimCountTainted(); so.AttachedAvatar = sp.UUID; if (so.RootPart.PhysActor != null) so.RootPart.RemoveFromPhysics(); so.AbsolutePosition = attachOffset; so.RootPart.AttachedPos = attachOffset; so.IsAttachment = true; so.RootPart.SetParentLocalId(sp.LocalId); so.AttachmentPoint = attachmentpoint; sp.AddAttachment(so); if (!silent) { // Killing it here will cause the client to deselect it // It then reappears on the avatar, deselected // through the full update below // if (so.IsSelected) { m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId }); } else if (so.HasPrivateAttachmentPoint) { // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}", // so.Name, sp.Name, so.AttachmentPoint); // As this scene object can now only be seen by the attaching avatar, tell everybody else in the // scene that it's no longer in their awareness. m_scene.ForEachClient( client => { if (client.AgentId != so.AttachedAvatar) client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId }); }); } so.IsSelected = false; // fudge.... so.ScheduleGroupForFullUpdate(); } // In case it is later dropped again, don't let // it get cleaned up so.RootPart.RemFlag(PrimFlags.TemporaryOnRez); }
/// <summary> /// Add an object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. /// </summary> /// <remarks> /// The object's stored position, rotation and velocity are used. /// </remarks> /// <param name="sceneObject"></param> /// <param name="attachToBackup"> /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// </param> /// <param name="sendClientUpdates"> /// If true, updates for the new scene object are sent to all viewers in range. /// If false, it is left to the caller to schedule the update /// </param> /// <returns> /// true if the object was added, false if an object with the same uuid was already in the scene /// </returns> protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (sceneObject == null) { m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object"); return false; } if (sceneObject.UUID == UUID.Zero) { m_log.ErrorFormat( "[SCENEGRAPH]: Tried to add scene object {0} to {1} with illegal UUID of {2}", sceneObject.Name, m_parentScene.RegionInfo.RegionName, UUID.Zero); return false; } if (Entities.ContainsKey(sceneObject.UUID)) { m_log.DebugFormat( "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()", m_parentScene.RegionInfo.RegionName, sceneObject.UUID); return false; } // m_log.DebugFormat( // "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}", // sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName); SceneObjectPart[] parts = sceneObject.Parts; // Clamp the sizes (scales) of the child prims and add the child prims to the count of all primitives // (meshes and geometric primitives) in the scene; add child prims to m_numTotalPrim count if (m_parentScene.m_clampPrimSize) { foreach (SceneObjectPart part in parts) { Vector3 scale = part.Shape.Scale; scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); part.Shape.Scale = scale; } } m_numTotalPrim += parts.Length; // Go through all parts (geometric primitives and meshes) of this Scene Object foreach (SceneObjectPart part in parts) { // Keep track of the total number of meshes or geometric primitives now in the scene; // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives if (part.GetPrimType() == PrimType.SCULPT) m_numMesh++; else m_numPrim++; } sceneObject.AttachToScene(m_parentScene); Entities.Add(sceneObject); lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; foreach (SceneObjectPart part in parts) { lock (SceneObjectGroupsByFullPartID) SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; lock (SceneObjectGroupsByLocalPartID) SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; } if (sendClientUpdates) sceneObject.ScheduleGroupForFullUpdate(); if (attachToBackup) sceneObject.AttachToBackup(); return true; }
/// <summary> /// Attach this scene object to the given avatar. /// </summary> /// /// This isn't publicly available since attachments should always perform the corresponding inventory /// operation (to show the attach in user inventory and update the asset with positional information). /// /// <param name="sp"></param> /// <param name="so"></param> /// <param name="attachmentpoint"></param> /// <param name="AttachOffset"></param> /// <param name="silent"></param> protected void AttachToAgent(ScenePresence avatar, SceneObjectGroup so, int attachmentpoint, Vector3 AttachOffset, bool silent) { // don't attach attachments to child agents if (avatar.IsChildAgent) return; // m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1}", Name, avatar.Name); so.DetachFromBackup(); // Remove from database and parcel prim count m_scene.DeleteFromStorage(so.UUID); m_scene.EventManager.TriggerParcelPrimCountTainted(); so.RootPart.AttachedAvatar = avatar.UUID; //Anakin Lohner bug #3839 SceneObjectPart[] parts = so.Parts; for (int i = 0; i < parts.Length; i++) parts[i].AttachedAvatar = avatar.UUID; if (so.RootPart.PhysActor != null) { m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor); so.RootPart.PhysActor = null; } so.AbsolutePosition = AttachOffset; so.RootPart.AttachedPos = AttachOffset; so.RootPart.IsAttachment = true; so.RootPart.SetParentLocalId(avatar.LocalId); so.SetAttachmentPoint(Convert.ToByte(attachmentpoint)); avatar.AddAttachment(so); if (!silent) { // Killing it here will cause the client to deselect it // It then reappears on the avatar, deselected // through the full update below // if (so.IsSelected) { m_scene.SendKillObject(so.RootPart.LocalId); } so.IsSelected = false; // fudge.... so.ScheduleGroupForFullUpdate(PrimUpdateFlags.FullUpdate); } // In case it is later dropped again, don't let // it get cleaned up so.RootPart.RemFlag(PrimFlags.TemporaryOnRez); so.HasGroupChanged = false; }
/// <summary> /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. /// /// This method locates the new region handle and offsets the prim position for the new region /// </summary> /// <param name="attemptedPosition">the attempted out of region position of the scene object</param> /// <param name="grp">the scene object that we're crossing</param> public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) { if (grp == null) return; if (grp.IsDeleted) return; Scene scene = grp.Scene; if (scene == null) return; if (grp.RootPart.DIE_AT_EDGE) { // We remove the object here try { scene.DeleteSceneObject(grp, false); } catch (Exception) { m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); } return; } int thisx = (int)scene.RegionInfo.RegionLocX; int thisy = (int)scene.RegionInfo.RegionLocY; Vector3 EastCross = new Vector3(0.1f, 0, 0); Vector3 WestCross = new Vector3(-0.1f, 0, 0); Vector3 NorthCross = new Vector3(0, 0.1f, 0); Vector3 SouthCross = new Vector3(0, -0.1f, 0); // use this if no borders were crossed! ulong newRegionHandle = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize), (uint)((thisy) * Constants.RegionSize)); Vector3 pos = attemptedPosition; int changeX = 1; int changeY = 1; if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W)) { if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x - 1 // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x - 1 // y + 1 } else { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x - 1 } } else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E)) { if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { pos.X = ((pos.X - Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x + 1 // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.X = ((pos.X - Constants.RegionSize)); pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x + 1 // y + 1 } else { pos.X = ((pos.X - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x + 1 } } else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // y + 1 } // Offset the positions for the new region across the border Vector3 oldGroupPosition = grp.RootPart.GroupPosition; // If we fail to cross the border, then reset the position of the scene object on that border. uint x = 0, y = 0; Utils.LongToUInts(newRegionHandle, out x, out y); GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); if (destination != null) { if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) return; // we did it } // no one or failed lets go back and tell physics to go on oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f); oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f); oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 0.5f, 4096.0f); grp.AbsolutePosition = oldGroupPosition; grp.Velocity = Vector3.Zero; if (grp.RootPart.PhysActor != null) grp.RootPart.PhysActor.CrossingFailure(); if (grp.RootPart.KeyframeMotion != null) grp.RootPart.KeyframeMotion.CrossingFailure(); grp.ScheduleGroupForFullUpdate(); }
public UUID tsuccirRezLinkset(UUID host, UUID script, int numberOfChildPrims) { numberOfChildPrims = Math.Max(0, numberOfChildPrims); SceneObjectPart part = m_scene.GetSceneObjectPart(host); if (part == null || !m_scene.Permissions.CanRezObject(1 + numberOfChildPrims, part.OwnerID, Vector3.Zero)) return UUID.Zero; SceneObjectGroup newGroup = new SceneObjectGroup(part.OwnerID, part.AbsolutePosition, Quaternion.Identity, PrimitiveBaseShape.Default); for (int i = 0; i < numberOfChildPrims; ++i) { newGroup.AddPart(new SceneObjectPart(part.OwnerID, PrimitiveBaseShape.Default, part.AbsolutePosition, Quaternion.Identity, Vector3.Zero)); } if (!m_scene.SceneGraph.AddNewSceneObject(newGroup, true, part.AbsolutePosition, Quaternion.Identity, Vector3.Zero)) { ScriptError(part, "Failed to add linkset to scene graph."); return UUID.Zero; } else { newGroup.FromPartID = host; newGroup.ScheduleGroupForFullUpdate(); IScriptModule[] modules = m_scene.RequestModuleInterfaces<IScriptModule>(); foreach (IScriptModule module in modules) { module.PostObjectEvent(host, "object_rez", new object[] { new LSL_String(newGroup.UUID.ToString()) }); } return newGroup.UUID; } }
public void DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents, bool sendGroupUpdate) { linkPart.ClearUndoState(); // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object lock (m_parts) { m_parts.Remove(linkPart.UUID); _partsByLocalId.Remove(linkPart.LocalId); if (m_parts.Count == 1 && RootPart != null) //Single prim is left { RootPart.LinkNum = 0; } else { foreach (SceneObjectPart p in m_parts.Values) { if (p.LinkNum > linkPart.LinkNum) p.LinkNum--; } } } linkPart.ParentID = 0; linkPart.LinkNum = 0; // We need to reset the child part's position // ready for life as a separate object after being a part of another object Quaternion parentRot = m_rootPart.RotationOffset; Vector3 axPos = linkPart.OffsetPosition; axPos *= parentRot; Vector3 groupPosition = AbsolutePosition + axPos; linkPart.SetGroupPositionDirect(groupPosition); linkPart.SetOffsetPositionDirect(Vector3.Zero); linkPart.SetRotationOffsetDirect(worldRot); SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); PhysicsActor partActor = linkPart.PhysActor; if (partActor != null) { partActor.DelinkFromParent(groupPosition, worldRot); } m_scene.AddNewSceneObject(objectGroup, true); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); linkPart.Rezzed = RootPart.Rezzed; //Rebuild the bounding box ClearBoundingBoxCache(); // Update the ServerWeight/LandImpact and StreamingCost RecalcPrimWeights(); if (sendGroupUpdate) { HasGroupChanged = true; ScheduleGroupForFullUpdate(); objectGroup.ScheduleGroupForFullUpdate(); } }
/// <summary> /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. /// /// This method locates the new region handle and offsets the prim position for the new region /// </summary> /// <param name="attemptedPosition">the attempted out of region position of the scene object</param> /// <param name="grp">the scene object that we're crossing</param> public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) { if (grp == null) return; if (grp.IsDeleted) return; Scene scene = grp.Scene; if (scene == null) return; if (grp.RootPart.DIE_AT_EDGE) { // We remove the object here try { scene.DeleteSceneObject(grp, false); } catch (Exception) { m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); } return; } int thisx = (int)scene.RegionInfo.RegionLocX; int thisy = (int)scene.RegionInfo.RegionLocY; /* Vector3 EastCross = new Vector3(0.1f, 0, 0); Vector3 WestCross = new Vector3(-0.1f, 0, 0); Vector3 NorthCross = new Vector3(0, 0.1f, 0); Vector3 SouthCross = new Vector3(0, -0.1f, 0); // use this if no borders were crossed! ulong newRegionHandle = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize), (uint)((thisy) * Constants.RegionSize)); Vector3 pos = attemptedPosition; int changeX = 1; int changeY = 1; if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W)) { if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x - 1 // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x - 1 // y + 1 } else { Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W); if (crossedBorderx.BorderLine.Z > 0) { pos.X = ((pos.X + crossedBorderx.BorderLine.Z)); changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize); } else pos.X = ((pos.X + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x - 1 } } else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E)) { if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { pos.X = ((pos.X - Constants.RegionSize)); Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // x + 1 // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.X = ((pos.X - Constants.RegionSize)); pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // x + 1 // y + 1 } else { pos.X = ((pos.X - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); // x + 1 } } else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) { Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) if (crossedBordery.BorderLine.Z > 0) { pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize); } else pos.Y = ((pos.Y + Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize)); // y - 1 } else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N)) { pos.Y = ((pos.Y - Constants.RegionSize)); newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); // y + 1 } */ // If we fail to cross the border, then reset the position of the scene object on that border. // Utils.LongToUInts(newRegionHandle, out x, out y); int x, y; Vector3 pos = attemptedPosition; Vector3 newpos = pos; float boundaryDistance = 1.0f; if (scene.RegionInfo.CombinedRegionHandle != 0) // we are a slave region send to main region { uint tmp1; uint tmp2; Utils.LongToUInts(scene.RegionInfo.CombinedRegionHandle, out tmp1, out tmp2); x = (int)tmp1; y = (int)tmp2; newpos.X += ((int)scene.RegionInfo.RegionLocX * Constants.RegionSize - x); newpos.Y += ((int)scene.RegionInfo.RegionLocY * Constants.RegionSize - y); } else { if (pos.X - boundaryDistance < 0) // going W { x = -1; newpos.X = Constants.RegionSize + pos.X - boundaryDistance; } else // assume we are going E { x = ((int)(pos.X + boundaryDistance) / (int)Constants.RegionSize); newpos.X = pos.X - x * (int)Constants.RegionSize; } x += (int)scene.RegionInfo.RegionLocX; x *= (int)Constants.RegionSize; if (pos.Y - boundaryDistance < 0) // going S SW or SE { y = -1; newpos.Y = Constants.RegionSize + pos.Y - boundaryDistance; } else // assume we are going N NW or NE { y = ((int)(pos.Y + boundaryDistance) / (int)Constants.RegionSize); newpos.Y = pos.Y - y * (int)Constants.RegionSize; } y += (int)scene.RegionInfo.RegionLocY; y *= (int)Constants.RegionSize; } // int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize); ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y); GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); if (destination == null) { // let physics know (for now ode needs this) if (!grp.IsDeleted) { if (grp.RootPart.PhysActor != null) { grp.RootPart.PhysActor.CrossingFailure(); } } } else { // Offset the positions for the new region across the border Vector3 oldGroupPosition = grp.RootPart.GroupPosition; grp.RootPart.GroupPosition = newpos; if (!CrossPrimGroupIntoNewRegion(destination, grp, silent)) { if (!grp.IsDeleted) { grp.RootPart.GroupPosition = oldGroupPosition; if (grp.RootPart.PhysActor != null) { grp.RootPart.PhysActor.CrossingFailure(); } grp.ScheduleGroupForFullUpdate(); } } } }
public virtual SceneObjectGroup AddNewPrim( UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) { //m_log.DebugFormat( // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName); SceneObjectGroup sceneObject = null; // If an entity creator has been registered for this prim type then use that if (m_entityCreators.ContainsKey((PCode)shape.PCode)) { sceneObject = m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape); } else { // Otherwise, use this default creation code; sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape, this); //This has to be set, otherwise it will break things like rezzing objects in an area where crossing is disabled, but rez isn't sceneObject.m_lastSignificantPosition = pos; AddPrimToScene(sceneObject); sceneObject.ScheduleGroupForFullUpdate(PrimUpdateFlags.FullUpdate); sceneObject.SetGroup(groupID, null); } return sceneObject; }