/// <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> /// 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 bool AttachObject( IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool append) { if (!Enabled) return false; group.DetachFromBackup(); bool success = AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append); if (!success) group.AttachToBackup(); return success; }
/// <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> /// 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> /// <returns>true if the object was added, false if an object with the same uuid was already in the scene /// </returns> public bool AddGroupToSceneGraph(SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool fromStorage, bool fromCrossing) { if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) { m_log.ErrorFormat("[SceneGraph]: {0} AddGroupToSceneGraph failed, invalid or null object.", m_parentScene.RegionInfo.RegionName); return false; } foreach (SceneObjectPart part in sceneObject.Children.Values) { Vector3 scale = part.Shape.Scale; if (scale.X < SceneObjectPart.MIN_PART_SCALE) { scale.X = SceneObjectPart.MIN_PART_SCALE; sceneObject.HasGroupChanged = true; } if (scale.Y < SceneObjectPart.MIN_PART_SCALE) { scale.Y = SceneObjectPart.MIN_PART_SCALE; sceneObject.HasGroupChanged = true; } if (scale.Z < SceneObjectPart.MIN_PART_SCALE) { scale.Z = SceneObjectPart.MIN_PART_SCALE; sceneObject.HasGroupChanged = true; } if (m_parentScene.m_clampPrimSize) { 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; } // if physical, make sure we're above the ground by at least 10 cm if ((sceneObject.RootPart.Flags & PrimFlags.Physics) != 0) { OpenSim.Framework.Geom.Box bbox = sceneObject.BoundingBox(); float groundHeight = m_parentScene.Heightmap.CalculateHeightAt(sceneObject.AbsolutePosition.X, sceneObject.AbsolutePosition.Y); if (sceneObject.AbsolutePosition.Z + bbox.Size.Z <= groundHeight) { Vector3 newPos = sceneObject.AbsolutePosition; newPos.Z = (bbox.Size.Z / 2.0f) + groundHeight + 0.1f; sceneObject.RootPart.SetGroupPositionDirect(newPos); } AddPhysicalObject(); } // rationalize the group: fix any inconsistency in locked bits, and // clear the default touch action of BUY for any objects not actually for sale, etc sceneObject.Rationalize(sceneObject.OwnerID, fromCrossing); sceneObject.AttachToScene(m_parentScene, fromStorage); // allocates the localIds for the prims if (!alreadyPersisted) { sceneObject.HasGroupChanged = true; } sceneObject.IsPersisted = alreadyPersisted; lock (sceneObject) { bool entityAdded = false; lock (m_dictionary_lock) { if (!Entities.ContainsKey(sceneObject.LocalId)) { Entities.Add(sceneObject); foreach (SceneObjectPart part in sceneObject.Children.Values) { SceneObjectPartsByFullID[part.UUID] = part; SceneObjectPartsByLocalID[part.LocalId] = part; } entityAdded = true; } } if (entityAdded) { m_numPrim += sceneObject.Children.Count; m_parentScene.EventManager.TriggerParcelPrimCountTainted(); if (attachToBackup) { sceneObject.AttachToBackup(); //this gets the new object on the taint list if (!alreadyPersisted) { sceneObject.HasGroupChanged = true; } m_parentScene.InspectForAutoReturn(sceneObject); } //This property doesn't work on rezzing, only on crossings or restarts if ((fromStorage || fromCrossing) && sceneObject.RootPart.KeyframeAnimation != null) { if (sceneObject.RootPart.KeyframeAnimation.CurrentCommand == KeyframeAnimation.Commands.Play) { if (!fromStorage) { //Offset the initial position so that it is in the new region's coordinates // (only if we are actually crossing from a different region) Vector3 regionOffset = sceneObject.AbsolutePosition - sceneObject.OriginalEnteringScenePosition; sceneObject.RootPart.KeyframeAnimation.InitialPosition += regionOffset; } sceneObject.AddKeyframedMotion(null, KeyframeAnimation.Commands.Play); } } if (OnObjectCreate != null) OnObjectCreate(sceneObject); return true; } } return false; }
/// <summary> /// Detach the given scene object to the ground. /// </summary> /// <remarks> /// The caller has to take care of all the other work in updating avatar appearance, inventory, etc. /// </remarks> /// <param name="so">The scene object to detach.</param> /// <param name="sp">The scene presence from which the scene object is being detached.</param> private void DetachSceneObjectToGround(SceneObjectGroup so, ScenePresence sp) { SceneObjectPart rootPart = so.RootPart; rootPart.FromItemID = UUID.Zero; so.AbsolutePosition = sp.AbsolutePosition; so.AttachedAvatar = UUID.Zero; rootPart.SetParentLocalId(0); so.ClearPartAttachmentData(); rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive, m_scene.m_physicalPrim); so.HasGroupChanged = true; rootPart.Rezzed = DateTime.Now; rootPart.RemFlag(PrimFlags.TemporaryOnRez); so.AttachToBackup(); m_scene.EventManager.TriggerParcelPrimCountTainted(); rootPart.ScheduleFullUpdate(); rootPart.ClearUndoState(); }
/// <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; }