diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 5e156f1772..1bd4749713 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -130,6 +130,8 @@ namespace OpenSim.Framework public delegate void UpdateVector(uint localID, Vector3 pos, IClientAPI remoteClient); + public delegate void ClientChangeObject(uint localID, object data ,IClientAPI remoteClient); + public delegate void UpdatePrimRotation(uint localID, Quaternion rot, IClientAPI remoteClient); public delegate void UpdatePrimSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient); @@ -838,6 +840,7 @@ namespace OpenSim.Framework event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; event UpdatePrimFlags OnUpdatePrimFlags; event UpdatePrimTexture OnUpdatePrimTexture; + event ClientChangeObject onClientChangeObject; event UpdateVector OnUpdatePrimGroupPosition; event UpdateVector OnUpdatePrimSinglePosition; event UpdatePrimRotation OnUpdatePrimGroupRotation; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 051c4fa8e3..7d51323456 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -125,6 +125,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; public event UpdatePrimFlags OnUpdatePrimFlags; public event UpdatePrimTexture OnUpdatePrimTexture; + public event ClientChangeObject onClientChangeObject; public event UpdateVector OnUpdatePrimGroupPosition; public event UpdateVector OnUpdatePrimSinglePosition; public event UpdatePrimRotation OnUpdatePrimGroupRotation; @@ -11517,22 +11518,151 @@ namespace OpenSim.Region.ClientStack.LindenUDP // parts[j].IgnoreUndoUpdate = true; // } - UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; - UpdateVector handlerUpdatePrimGroupScale; +// UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; +// UpdateVector handlerUpdatePrimGroupScale; - Quaternion arot; - Vector3 ascale; - Vector3 apos; -/*ubit from ll JIRA: - * 0x01 position - * 0x02 rotation - * 0x04 scale + ClientChangeObject updatehandler = onClientChangeObject; + + if (updatehandler != null) + { + ObjectChangeData udata = new ObjectChangeData(); + + /*ubit from ll JIRA: + * 0x01 position + * 0x02 rotation + * 0x04 scale - * 0x08 LINK_SET - * 0x10 UNIFORM for scale - */ + * 0x08 LINK_SET + * 0x10 UNIFORM for scale + */ + // translate to internal changes + // not all cases .. just the ones older code did + switch (block.Type) + { + case 1: //change position sp + udata.position = new Vector3(block.Data, 0); + + udata.what = ObjectChangeWhat.primP; + updatehandler(localId, udata, this); + break; + + case 2: // rotation sp + udata.rotation = new Quaternion(block.Data, 0, true); + + udata.what = ObjectChangeWhat.primR; + updatehandler(localId, udata, this); + break; + + case 3: // position plus rotation + udata.position = new Vector3(block.Data, 0); + udata.rotation = new Quaternion(block.Data, 12, true); + + udata.what = ObjectChangeWhat.primPR; + updatehandler(localId, udata, this); + + break; + + case 4: // scale sp + udata.scale = new Vector3(block.Data, 0); + udata.what = ObjectChangeWhat.primS; + + updatehandler(localId, udata, this); + break; + + case 0x14: // uniform scale sp + udata.scale = new Vector3(block.Data, 0); + + udata.what = ObjectChangeWhat.primUS; + updatehandler(localId, udata, this); + break; + + case 5: // scale and position sp + udata.position = new Vector3(block.Data, 0); + udata.scale = new Vector3(block.Data, 12); + + udata.what = ObjectChangeWhat.primPS; + updatehandler(localId, udata, this); + break; + + case 0x15: //uniform scale and position + udata.position = new Vector3(block.Data, 0); + udata.scale = new Vector3(block.Data, 12); + + udata.what = ObjectChangeWhat.primPUS; + updatehandler(localId, udata, this); + break; + + // now group related (bit 4) + case 9: //( 8 + 1 )group position + udata.position = new Vector3(block.Data, 0); + + udata.what = ObjectChangeWhat.groupP; + updatehandler(localId, udata, this); + break; + + case 0x0A: // (8 + 2) group rotation + udata.rotation = new Quaternion(block.Data, 0, true); + + udata.what = ObjectChangeWhat.groupR; + updatehandler(localId, udata, this); + break; + + case 0x0B: //( 8 + 2 + 1) group rotation and position + udata.position = new Vector3(block.Data, 0); + udata.rotation = new Quaternion(block.Data, 12, true); + + udata.what = ObjectChangeWhat.groupPR; + updatehandler(localId, udata, this); + break; + + case 0x0C: // (8 + 4) group scale + // only afects root prim and only sent by viewer editor object tab scaling + // mouse edition only allows uniform scaling + // SL MAY CHANGE THIS in viewers + + udata.scale = new Vector3(block.Data, 0); + + // udata.what = ObjectChangeWhat.groupS; + udata.what = ObjectChangeWhat.primS; // to conform to current SL + updatehandler(localId, udata, this); + + break; + + case 0x0D: //(8 + 4 + 1) group scale and position + // exception as above + + udata.position = new Vector3(block.Data, 0); + udata.scale = new Vector3(block.Data, 12); + + // udata.what = ObjectChangeWhat.groupPS; + udata.what = ObjectChangeWhat.primPS; // to conform to current SL + updatehandler(localId, udata, this); + break; + + case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM + udata.scale = new Vector3(block.Data, 0); + + udata.what = ObjectChangeWhat.groupUS; + updatehandler(localId, udata, this); + break; + + case 0x1D: // (UNIFORM + GROUP + SCALE + POS) + udata.position = new Vector3(block.Data, 0); + udata.scale = new Vector3(block.Data, 12); + + udata.what = ObjectChangeWhat.groupPUS; + updatehandler(localId, udata, this); + break; + + default: + m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); + break; + } + } + +/* switch (block.Type) { case 1: //change position sp @@ -11788,7 +11918,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); break; } - +*/ // for (int j = 0; j < parts.Length; j++) // parts[j].IgnoreUndoUpdate = false; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 68c05f85d6..a3358a597d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2811,6 +2811,8 @@ namespace OpenSim.Region.Framework.Scenes client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; + client.onClientChangeObject += m_sceneGraph.ClientChangeObject; + client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; @@ -2940,6 +2942,8 @@ namespace OpenSim.Region.Framework.Scenes client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; + client.onClientChangeObject -= m_sceneGraph.ClientChangeObject; + client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 3cd4a10e6c..5e770ba1fd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -47,6 +47,57 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ChangedBackupDelegate(SceneObjectGroup sog); + + public enum ObjectChangeWhat : uint + { + // bits definitions + Position = 0x01, + Rotation = 0x02, + Scale = 0x04, + Group = 0x08, + UniformScale = 0x10, + + // macros from above + // single prim + primP = 0x01, + primR = 0x02, + primPR = 0x03, + primS = 0x04, + primPS = 0x05, + primRS = 0x06, + primPSR = 0x07, + + primUS = 0x14, + primPUS = 0x15, + primRUS = 0x16, + primPUSR = 0x17, + + // group + groupP = 0x09, + groupR = 0x0A, + groupPR = 0x0B, + groupS = 0x0C, + groupPS = 0x0D, + groupRS = 0x0E, + groupPSR = 0x0F, + + groupUS = 0x1C, + groupPUS = 0x1D, + groupRUS = 0x1E, + groupPUSR = 0x1F, + + PRSmask = 0x07 + } + + public struct ObjectChangeData + { + public Quaternion rotation; + public Vector3 position; + public Vector3 scale; + public ObjectChangeWhat what; + } + + /// /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components /// should be migrated out over time. @@ -1289,6 +1340,87 @@ namespace OpenSim.Region.Framework.Scenes #region Client Event handlers + protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient) + { + SceneObjectPart part = GetSceneObjectPart(localID); + ObjectChangeData data = (ObjectChangeData)odata; + + if (part != null) + { + SceneObjectGroup grp = part.ParentGroup; + if (grp != null) + { + if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId)) + { +// part.StoreUndoState(data.what | ObjectChangeWhat.PRSmask); // for now save all to keep previus behavour ??? + part.StoreUndoState(data.what); // lets test only saving what we changed + grp.doChangeObject(part, (ObjectChangeData)data); + } + } + } + } + +/* moved to SOG + protected internal void doChangeObject(SceneObjectPart part, ObjectChangeData data) + { + if (part != null && part.ParentGroup != null) + { + ObjectChangeWhat what = data.what; + bool togroup = ((what & ObjectChangeWhat.Group) != 0); +// bool uniform = ((what & ObjectChangeWhat.UniformScale) != 0); not in use + + SceneObjectGroup group = part.ParentGroup; + PhysicsActor pha = group.RootPart.PhysActor; + + if (togroup) + { + // related to group + if ((what & ObjectChangeWhat.Position) != 0) + group.AbsolutePosition = data.position; + if ((what & ObjectChangeWhat.Rotation) != 0) + group.RootPart.UpdateRotation(data.rotation); + if ((what & ObjectChangeWhat.Scale) != 0) + { + if (pha != null) + pha.Building = true; + group.GroupResize(data.scale); + if (pha != null) + pha.Building = false; + } + } + else + { + // related to single prim in a link-set ( ie group) + if (pha != null) + pha.Building = true; + + // must deal with root part specially for position and rotation + // so parts offset positions or rotations are fixed + + if (part == group.RootPart) + { + if ((what & ObjectChangeWhat.Position) != 0) + group.UpdateRootPosition(data.position); + if ((what & ObjectChangeWhat.Rotation) != 0) + group.UpdateRootRotation(data.rotation); + } + else + { + if ((what & ObjectChangeWhat.Position) != 0) + part.OffsetPosition = data.position; + if ((what & ObjectChangeWhat.Rotation) != 0) + part.UpdateRotation(data.rotation); + } + + if ((what & ObjectChangeWhat.Scale) != 0) + part.Resize(data.scale); + + if (pha != null) + pha.Building = false; + } + } + } +*/ /// /// Update the scale of an individual prim. /// @@ -1303,7 +1435,17 @@ namespace OpenSim.Region.Framework.Scenes { if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) { + bool physbuild = false; + if (part.ParentGroup.RootPart.PhysActor != null) + { + part.ParentGroup.RootPart.PhysActor.Building = true; + physbuild = true; + } + part.Resize(scale); + + if (physbuild) + part.ParentGroup.RootPart.PhysActor.Building = false; } } } @@ -1315,7 +1457,17 @@ namespace OpenSim.Region.Framework.Scenes { if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) { + bool physbuild = false; + if (group.RootPart.PhysActor != null) + { + group.RootPart.PhysActor.Building = true; + physbuild = true; + } + group.GroupResize(scale); + + if (physbuild) + group.RootPart.PhysActor.Building = false; } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 2d71372011..92f2d54f52 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2499,6 +2499,11 @@ namespace OpenSim.Region.Framework.Scenes if (linkPart.PhysActor != null) linkPart.PhysActor.Building = true; + // physics flags from group to be applied to linked parts + bool grpusephys = UsesPhysics; + bool grptemporary = IsTemporary; + bool gprphantom = IsPhantom; + Vector3 oldGroupPosition = linkPart.GroupPosition; Quaternion oldRootRotation = linkPart.RotationOffset; @@ -2542,7 +2547,8 @@ namespace OpenSim.Region.Framework.Scenes linkPart.SetParent(this); linkPart.CreateSelected = true; - // let physics know + // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now + linkPart.UpdatePrimFlags(grpusephys, grptemporary, gprphantom, linkPart.VolumeDetectActive, true); if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) { linkPart.PhysActor.link(m_rootPart.PhysActor); @@ -2564,6 +2570,7 @@ namespace OpenSim.Region.Framework.Scenes { LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); // let physics know + part.UpdatePrimFlags(grpusephys, grptemporary, gprphantom, part.VolumeDetectActive, true); if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) { part.PhysActor.link(m_rootPart.PhysActor); @@ -3117,10 +3124,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void GroupResize(Vector3 scale) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); -// RootPart.StoreUndoState(true); - scale.X = Math.Min(scale.X, Scene.m_maxNonphys); scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); @@ -3145,7 +3148,6 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart obPart = parts[i]; if (obPart.UUID != m_rootPart.UUID) { -// obPart.IgnoreUndoUpdate = true; Vector3 oldSize = new Vector3(obPart.Scale); float f = 1.0f; @@ -3209,8 +3211,6 @@ namespace OpenSim.Region.Framework.Scenes z *= a; } } - -// obPart.IgnoreUndoUpdate = false; } } } @@ -3219,9 +3219,8 @@ namespace OpenSim.Region.Framework.Scenes prevScale.X *= x; prevScale.Y *= y; prevScale.Z *= z; -// RootPart.IgnoreUndoUpdate = true; + RootPart.Resize(prevScale); -// RootPart.IgnoreUndoUpdate = false; parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) @@ -3230,8 +3229,6 @@ namespace OpenSim.Region.Framework.Scenes if (obPart.UUID != m_rootPart.UUID) { -// obPart.IgnoreUndoUpdate = true; - Vector3 currentpos = new Vector3(obPart.OffsetPosition); currentpos.X *= x; currentpos.Y *= y; @@ -3244,18 +3241,12 @@ namespace OpenSim.Region.Framework.Scenes obPart.Resize(newSize); obPart.UpdateOffSet(currentpos); - -// obPart.IgnoreUndoUpdate = false; } -// obPart.IgnoreUndoUpdate = false; HasGroupChanged = true; m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); ScheduleGroupForTerseUpdate(); } - -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale); } #endregion @@ -3268,14 +3259,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupPosition(Vector3 pos) { -// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos); - -// RootPart.StoreUndoState(true); - -// SceneObjectPart[] parts = m_parts.GetArray(); -// for (int i = 0; i < parts.Length; i++) -// parts[i].StoreUndoState(); - if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) { if (IsAttachment) @@ -3307,22 +3290,14 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// + /// + public void UpdateSinglePosition(Vector3 pos, uint localID) { SceneObjectPart part = GetChildPart(localID); -// SceneObjectPart[] parts = m_parts.GetArray(); -// for (int i = 0; i < parts.Length; i++) -// parts[i].StoreUndoState(); - if (part != null) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); - -// part.StoreUndoState(false); -// part.IgnoreUndoUpdate = true; - // unlock parts position change if (m_rootPart.PhysActor != null) m_rootPart.PhysActor.Building = true; @@ -3340,7 +3315,6 @@ namespace OpenSim.Region.Framework.Scenes m_rootPart.PhysActor.Building = false; HasGroupChanged = true; -// part.IgnoreUndoUpdate = false; } } @@ -3350,13 +3324,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateRootPosition(Vector3 pos) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos); - -// SceneObjectPart[] parts = m_parts.GetArray(); -// for (int i = 0; i < parts.Length; i++) -// parts[i].StoreUndoState(); - + // needs to be called with phys building true Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); Vector3 oldPos = new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, @@ -3376,17 +3344,7 @@ namespace OpenSim.Region.Framework.Scenes obPart.OffsetPosition = obPart.OffsetPosition + diff; } - //We have to set undoing here because otherwise an undo state will be saved -// if (!m_rootPart.Undoing) -// { -// m_rootPart.Undoing = true; - AbsolutePosition = newPos; -// m_rootPart.Undoing = false; -// } -// else -// { -// AbsolutePosition = newPos; -// } + AbsolutePosition = newPos; HasGroupChanged = true; if (m_rootPart.Undoing) @@ -3409,17 +3367,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupRotationR(Quaternion rot) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot); - -// SceneObjectPart[] parts = m_parts.GetArray(); -// for (int i = 0; i < parts.Length; i++) -// parts[i].StoreUndoState(); - -// m_rootPart.StoreUndoState(true); - -// m_rootPart.UpdateRotation(rot); - PhysicsActor actor = m_rootPart.PhysActor; if (actor != null) { @@ -3438,16 +3385,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot); - -// SceneObjectPart[] parts = m_parts.GetArray(); -// for (int i = 0; i < parts.Length; i++) -// parts[i].StoreUndoState(); - -// RootPart.StoreUndoState(true); -// RootPart.IgnoreUndoUpdate = true; - m_rootPart.UpdateRotation(rot); PhysicsActor actor = m_rootPart.PhysActor; @@ -3461,8 +3398,6 @@ namespace OpenSim.Region.Framework.Scenes HasGroupChanged = true; ScheduleGroupForTerseUpdate(); - -// RootPart.IgnoreUndoUpdate = false; } /// @@ -3477,9 +3412,6 @@ namespace OpenSim.Region.Framework.Scenes if (part != null) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); - if (m_rootPart.PhysActor != null) m_rootPart.PhysActor.Building = true; @@ -3507,30 +3439,13 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = GetChildPart(localID); if (part != null) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", -// part.Name, part.LocalId, rot); - -// part.StoreUndoState(); -// part.IgnoreUndoUpdate = true; - if (m_rootPart.PhysActor != null) m_rootPart.PhysActor.Building = true; if (part.UUID == m_rootPart.UUID) { UpdateRootRotation(rot); -/* if (!m_rootPart.Undoing) - { - m_rootPart.Undoing = true; - AbsolutePosition = pos; - m_rootPart.Undoing = false; - } - else - { - */ - AbsolutePosition = pos; -// } + AbsolutePosition = pos; } else { @@ -3540,8 +3455,6 @@ namespace OpenSim.Region.Framework.Scenes if (m_rootPart.PhysActor != null) m_rootPart.PhysActor.Building = false; - -// part.IgnoreUndoUpdate = false; } } @@ -3551,13 +3464,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateRootRotation(Quaternion rot) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}", -// Name, LocalId, rot); - + // needs to be called with phys building true Quaternion axRot = rot; Quaternion oldParentRot = m_rootPart.RotationOffset; -// m_rootPart.StoreUndoState(); //Don't use UpdateRotation because it schedules an update prematurely m_rootPart.RotationOffset = rot; @@ -3573,8 +3482,6 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart prim = parts[i]; if (prim.UUID != m_rootPart.UUID) { -// prim.IgnoreUndoUpdate = true; - Quaternion NewRot = oldParentRot * prim.RotationOffset; NewRot = Quaternion.Inverse(axRot) * NewRot; prim.RotationOffset = NewRot; @@ -3584,26 +3491,88 @@ namespace OpenSim.Region.Framework.Scenes axPos *= oldParentRot; axPos *= Quaternion.Inverse(axRot); prim.OffsetPosition = axPos; - -// prim.IgnoreUndoUpdate = false; } } -// for (int i = 0; i < parts.Length; i++) -// { -// SceneObjectPart childpart = parts[i]; -// if (childpart != m_rootPart) -// { -//// childpart.IgnoreUndoUpdate = false; -//// childpart.StoreUndoState(); -// } -// } HasGroupChanged = true; ScheduleGroupForFullUpdate(); + } -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", -// Name, LocalId, rot); + public void doChangeObject(SceneObjectPart part, ObjectChangeData data) + { + // TODO this still as excessive ScheduleGroupForTerseUpdate()s + + if (part != null && part.ParentGroup != null) + { + ObjectChangeWhat what = data.what; + bool togroup = ((what & ObjectChangeWhat.Group) != 0); + // bool uniform = ((what & ObjectChangeWhat.UniformScale) != 0); not in use + + SceneObjectGroup group = part.ParentGroup; + PhysicsActor pha = group.RootPart.PhysActor; + + bool needgrpUpdate = false; + + if (togroup) + { + // related to group + if ((what & ObjectChangeWhat.Position) != 0) + { + group.AbsolutePosition = data.position; + needgrpUpdate = true; + } + if ((what & ObjectChangeWhat.Rotation) != 0) + group.RootPart.UpdateRotation(data.rotation); + if ((what & ObjectChangeWhat.Scale) != 0) + { + if (pha != null) + pha.Building = true; + group.GroupResize(data.scale); + if (pha != null) + pha.Building = false; + } + } + else + { + // related to single prim in a link-set ( ie group) + if (pha != null) + pha.Building = true; + + // must deal with root part specially for position and rotation + // so parts offset positions or rotations are fixed + + if (part == group.RootPart) + { + if ((what & ObjectChangeWhat.Position) != 0) + group.UpdateRootPosition(data.position); + if ((what & ObjectChangeWhat.Rotation) != 0) + group.UpdateRootRotation(data.rotation); + } + else + { + + if ((what & ObjectChangeWhat.Position) != 0) + { + part.OffsetPosition = data.position; + needgrpUpdate = true; + } + if ((what & ObjectChangeWhat.Rotation) != 0) + part.UpdateRotation(data.rotation); + } + + if ((what & ObjectChangeWhat.Scale) != 0) + part.Resize(data.scale); + + if (pha != null) + pha.Building = false; + } + + if (needgrpUpdate) + { + HasGroupChanged = true; + ScheduleGroupForTerseUpdate(); + } + } } #endregion diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 662249597a..f70b2597c6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -263,8 +263,7 @@ namespace OpenSim.Region.Framework.Scenes private bool m_occupied; // KF if any av is sitting on this prim private string m_text = String.Empty; private string m_touchName = String.Empty; - private Stack m_undo = new Stack(5); - private Stack m_redo = new Stack(5); + private UndoRedoState m_UndoRedo = new UndoRedoState(5); private bool m_passTouches; @@ -1709,8 +1708,8 @@ namespace OpenSim.Region.Framework.Scenes dupe.Category = Category; dupe.m_rezzed = m_rezzed; - dupe.m_undo = new Stack(5); - dupe.m_redo = new Stack(5); + dupe.m_UndoRedo = new UndoRedoState(5); + dupe.IgnoreUndoUpdate = false; dupe.Undoing = false; @@ -1944,6 +1943,7 @@ namespace OpenSim.Region.Framework.Scenes PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; PhysActor.OnOutOfBounds += PhysicsOutOfBounds; + if (ParentID != 0 && ParentID != LocalId) { if (ParentGroup.RootPart.PhysActor != null) @@ -3657,43 +3657,13 @@ namespace OpenSim.Region.Framework.Scenes //ParentGroup.ScheduleGroupForFullUpdate(); } - public void StoreUndoState() + public void StoreUndoState(ObjectChangeWhat what) { - StoreUndoState(false); - } - - public void StoreUndoState(bool forGroup) - { - if (!Undoing && !IgnoreUndoUpdate) // just to read better - undo is in progress, or suspended + lock (m_UndoRedo) { - if (ParentGroup != null) + if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended { - lock (m_undo) - { - if (m_undo.Count > 0) - { - // see if we had a change - - UndoState last = m_undo.Peek(); - if (last != null) - { - if (last.Compare(this, forGroup)) - { - return; - } - } - } - - if (ParentGroup.GetSceneMaxUndo() > 0) - { - UndoState nUndo = new UndoState(this, forGroup); - - m_undo.Push(nUndo); - - if (m_redo.Count > 0) - m_redo.Clear(); - } - } + m_UndoRedo.StoreUndo(this, what); } } } @@ -3705,84 +3675,42 @@ namespace OpenSim.Region.Framework.Scenes { get { - lock (m_undo) - return m_undo.Count; + lock (m_UndoRedo) + return m_UndoRedo.Count; } } public void Undo() { - lock (m_undo) + lock (m_UndoRedo) { -// m_log.DebugFormat( -// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}", -// Name, LocalId, m_undo.Count); + if (Undoing || ParentGroup == null) + return; - if (m_undo.Count > 0) - { - UndoState goback = m_undo.Pop(); - - if (goback != null) - { - UndoState nUndo = null; - - if (ParentGroup.GetSceneMaxUndo() > 0) - { - nUndo = new UndoState(this, goback.ForGroup); - } - - goback.PlayState(this); - - if (nUndo != null) - m_redo.Push(nUndo); - } - } - -// m_log.DebugFormat( -// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", -// Name, LocalId, m_undo.Count); + Undoing = true; + m_UndoRedo.Undo(this); + Undoing = false; } } public void Redo() { - lock (m_undo) + lock (m_UndoRedo) { -// m_log.DebugFormat( -// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}", -// Name, LocalId, m_redo.Count); + if (Undoing || ParentGroup == null) + return; - if (m_redo.Count > 0) - { - UndoState gofwd = m_redo.Pop(); - - if (gofwd != null) - { - if (ParentGroup.GetSceneMaxUndo() > 0) - { - UndoState nUndo = new UndoState(this, gofwd.ForGroup); - - m_undo.Push(nUndo); - } - - gofwd.PlayState(this); - } - -// m_log.DebugFormat( -// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", -// Name, LocalId, m_redo.Count); - } + Undoing = true; + m_UndoRedo.Redo(this); + Undoing = false; } } public void ClearUndoState() { -// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); - - lock (m_undo) + lock (m_UndoRedo) { - m_undo.Clear(); - m_redo.Clear(); + m_UndoRedo.Clear(); } } diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index 38474def84..668b53b5bb 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs @@ -27,6 +27,7 @@ using System; using System.Reflection; +using System.Collections.Generic; using log4net; using OpenMetaverse; using OpenSim.Region.Framework.Interfaces; @@ -34,6 +35,8 @@ using System; namespace OpenSim.Region.Framework.Scenes { + +/* [Flags] public enum UndoType { @@ -48,6 +51,7 @@ namespace OpenSim.Region.Framework.Scenes STATE_ALL = 63 } + public class UndoState { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -121,9 +125,16 @@ namespace OpenSim.Region.Framework.Scenes public void PlayState(SceneObjectPart part) { part.Undoing = true; - + bool physbuilding = false; + if (part.ParentID == 0) { + if (!ForGroup && part.PhysActor != null) + { + part.PhysActor.Building = true; + physbuilding = true; + } + if (Position != Vector3.Zero) { if (ForGroup) @@ -139,17 +150,34 @@ namespace OpenSim.Region.Framework.Scenes if (Scale != Vector3.Zero) { + if (!physbuilding && part.PhysActor != null) + { + part.PhysActor.Building = true; + physbuilding = true; + } + if (ForGroup) part.ParentGroup.GroupResize(Scale); else part.Resize(Scale); } + + if (physbuilding) + part.PhysActor.Building = false; + part.ParentGroup.ScheduleGroupForTerseUpdate(); } else { if (ForGroup) // trap for group since seems parts can't do it return; + + // changing a part invalidates entire object physical rep + if (part.ParentGroup != null && part.ParentGroup.RootPart != null && part.ParentGroup.RootPart.PhysActor != null) + { + part.ParentGroup.RootPart.PhysActor.Building = true; + physbuilding = true; + } // Note: Updating these properties on sop automatically schedules an update if needed part.OffsetPosition = Position; @@ -158,11 +186,264 @@ namespace OpenSim.Region.Framework.Scenes { part.Resize(Scale); } + + if (physbuilding) + part.ParentGroup.RootPart.PhysActor.Building = false; } part.Undoing = false; } } +*/ + public class UndoState + { + const int UNDOEXPIRESECONDS = 300; // undo expire time (nice to have it came from a ini later) + + public ObjectChangeData data; + public DateTime creationtime; + /// + /// Constructor. + /// + /// + /// True if the undo is for an entire group + /// only for root parts ???? + public UndoState(SceneObjectPart part, ObjectChangeWhat what) + { + data = new ObjectChangeData(); + data.what = what; + creationtime = DateTime.UtcNow; + + if (part.ParentGroup.RootPart == part) + { + if ((what & ObjectChangeWhat.Position) != 0) + data.position = part.ParentGroup.AbsolutePosition; + if ((what & ObjectChangeWhat.Rotation) != 0) + data.rotation = part.RotationOffset; + if ((what & ObjectChangeWhat.Scale) != 0) + data.scale = part.Shape.Scale; + } + else + { + if ((what & ObjectChangeWhat.Position) != 0) + data.position = part.OffsetPosition; + if ((what & ObjectChangeWhat.Rotation) != 0) + data.rotation = part.RotationOffset; + if ((what & ObjectChangeWhat.Scale) != 0) + data.scale = part.Shape.Scale; + } + } + + public bool checkExpire() + { + TimeSpan t = DateTime.UtcNow - creationtime; + if (t.Seconds > UNDOEXPIRESECONDS) + return true; + return false; + } + + public void updateExpire() + { + creationtime = DateTime.UtcNow; + } + + /// + /// Compare the relevant state in the given part to this state. + /// + /// + /// true if both the part's position, rotation and scale match those in this undo state. False otherwise. + public bool Compare(SceneObjectPart part, ObjectChangeWhat what) + { + if (data.what != what) // if diferent targets, then they are diferent + return false; + + if (part != null) + { + if (part.ParentID == 0) + { + if ((what & ObjectChangeWhat.Position) != 0 && data.position != part.ParentGroup.AbsolutePosition) + return false; + } + else + { + if ((what & ObjectChangeWhat.Position) != 0 && data.position != part.OffsetPosition) + return false; + } + + if ((what & ObjectChangeWhat.Rotation) != 0 && data.rotation != part.RotationOffset) + return false; + if ((what & ObjectChangeWhat.Rotation) != 0 && data.scale == part.Shape.Scale) + return false; + return true; + + } + return false; + } + + public void PlayState(SceneObjectPart part) + { + part.Undoing = true; + + SceneObjectGroup grp = part.ParentGroup; + + if (grp != null) + { + grp.doChangeObject(part, data); + } + part.Undoing = false; + } + } + + public class UndoRedoState + { + int size; + public LinkedList m_redo = new LinkedList(); + public LinkedList m_undo = new LinkedList(); + + public UndoRedoState() + { + size = 5; + } + + public UndoRedoState(int _size) + { + if (_size < 3) + size = 3; + else + size = _size; + } + + public int Count + { + get { return m_undo.Count; } + } + + public void Clear() + { + m_undo.Clear(); + m_redo.Clear(); + } + + public void StoreUndo(SceneObjectPart part, ObjectChangeWhat what) + { + lock (m_undo) + { + UndoState last; + + if (m_redo.Count > 0) // last code seems to clear redo on every new undo + { + m_redo.Clear(); + } + + if (m_undo.Count > 0) + { + // check expired entry + last = m_undo.First.Value; + if (last != null && last.checkExpire()) + m_undo.Clear(); + else + { + // see if we actually have a change + if (last != null) + { + if (last.Compare(part, what)) + return; + } + } + } + + // limite size + while (m_undo.Count >= size) + m_undo.RemoveLast(); + + UndoState nUndo = new UndoState(part, what); + m_undo.AddFirst(nUndo); + } + } + + public void Undo(SceneObjectPart part) + { + lock (m_undo) + { + UndoState nUndo; + + // expire redo + if (m_redo.Count > 0) + { + nUndo = m_redo.First.Value; + if (nUndo != null && nUndo.checkExpire()) + m_redo.Clear(); + } + + if (m_undo.Count > 0) + { + UndoState goback = m_undo.First.Value; + // check expired + if (goback != null && goback.checkExpire()) + { + m_undo.Clear(); + return; + } + + if (goback != null) + { + m_undo.RemoveFirst(); + + // redo limite size + while (m_redo.Count >= size) + m_redo.RemoveLast(); + + nUndo = new UndoState(part, goback.data.what); // new value in part should it be full goback copy? + m_redo.AddFirst(nUndo); + + goback.PlayState(part); + } + } + } + } + + public void Redo(SceneObjectPart part) + { + lock (m_undo) + { + UndoState nUndo; + + // expire undo + if (m_undo.Count > 0) + { + nUndo = m_undo.First.Value; + if (nUndo != null && nUndo.checkExpire()) + m_undo.Clear(); + } + + if (m_redo.Count > 0) + { + UndoState gofwd = m_redo.First.Value; + // check expired + if (gofwd != null && gofwd.checkExpire()) + { + m_redo.Clear(); + return; + } + + if (gofwd != null) + { + m_redo.RemoveFirst(); + + // limite undo size + while (m_undo.Count >= size) + m_undo.RemoveLast(); + + nUndo = new UndoState(part, gofwd.data.what); // new value in part should it be full gofwd copy? + m_undo.AddFirst(nUndo); + + gofwd.PlayState(part); + } + } + } + } + + + } public class LandUndoState { diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 0f62b2a1a7..18f8f34002 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -714,6 +714,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; public event UpdatePrimFlags OnUpdatePrimFlags; public event UpdatePrimTexture OnUpdatePrimTexture; + public event ClientChangeObject onClientChangeObject; public event UpdateVector OnUpdatePrimGroupPosition; public event UpdateVector OnUpdatePrimSinglePosition; public event UpdatePrimRotation OnUpdatePrimGroupRotation; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index cbc38135ff..cdb6efec71 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -275,6 +275,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event UpdatePrimTexture OnUpdatePrimTexture; public event UpdateVector OnUpdatePrimGroupPosition; public event UpdateVector OnUpdatePrimSinglePosition; + public event ClientChangeObject onClientChangeObject; public event UpdatePrimRotation OnUpdatePrimGroupRotation; public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition; public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index b105f77da7..563d527dcd 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs @@ -1524,17 +1524,19 @@ namespace OpenSim.Region.Physics.OdePlugin { prm.m_collisionCategories |= CollisionCategories.Body; prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + d.GeomEnable(prm.prim_geom); } if (prm.m_NoColide) { d.GeomSetCategoryBits(prm.prim_geom, 0); d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land); + d.GeomEnable(prm.prim_geom); } else { - d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags); + d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); + d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); } prm.m_collisionscore = 0; diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index fa750aba1b..be6b81b5ac 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -135,6 +135,7 @@ namespace OpenSim.Tests.Common.Mock public event GenericCall7 OnObjectMaterial; public event UpdatePrimFlags OnUpdatePrimFlags; public event UpdatePrimTexture OnUpdatePrimTexture; + public event ClientChangeObject onClientChangeObject; public event UpdateVector OnUpdatePrimGroupPosition; public event UpdateVector OnUpdatePrimSinglePosition; public event UpdatePrimRotation OnUpdatePrimGroupRotation;