/Aurora/Modules/World/PhysicsState/PhysicsStateModule.cs
C# | 235 lines | 203 code | 31 blank | 1 comment | 14 complexity | e7c8efcad713dd99b282c122fe792d50 MD5 | raw file
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Timers; 5using Aurora.Framework.Modules; 6using Aurora.Framework.Physics; 7using Aurora.Framework.PresenceInfo; 8using Aurora.Framework.SceneInfo; 9using Nini.Config; 10using OpenMetaverse; 11using Aurora.Framework; 12 13namespace Aurora.Modules.PhysicsState 14{ 15 public class PhysicsStateModule : INonSharedRegionModule, IPhysicsStateModule 16 { 17 private readonly List<WorldPhysicsState> m_timeReversal = new List<WorldPhysicsState>(); 18 private bool m_isReversing; 19 private bool m_isSavingRevertStates; 20 private int m_lastRevertedTo = -100; 21 private WorldPhysicsState m_lastWorldPhysicsState; 22 private IScene m_scene; 23 24 #region INonSharedRegionModule Members 25 26 public void Initialise(IConfigSource source) 27 { 28 } 29 30 public void AddRegion(IScene scene) 31 { 32 scene.RegisterModuleInterface<IPhysicsStateModule>(this); 33 m_scene = scene; 34 Timer timeReversal = new Timer(250); 35 timeReversal.Elapsed += timeReversal_Elapsed; 36 timeReversal.Start(); 37 } 38 39 public void RegionLoaded(IScene scene) 40 { 41 } 42 43 public void RemoveRegion(IScene scene) 44 { 45 } 46 47 public void Close() 48 { 49 } 50 51 public string Name 52 { 53 get { return "PhysicsState"; } 54 } 55 56 public Type ReplaceableInterface 57 { 58 get { return null; } 59 } 60 61 #endregion 62 63 #region IPhysicsStateModule Members 64 65 public void SavePhysicsState() 66 { 67 m_lastWorldPhysicsState = m_isReversing ? null : MakePhysicsState(); 68 } 69 70 public void ResetToLastSavedState() 71 { 72 if (m_lastWorldPhysicsState != null) 73 m_lastWorldPhysicsState.Reload(m_scene, 1); 74 m_lastWorldPhysicsState = null; 75 } 76 77 public void StartSavingPhysicsTimeReversalStates() 78 { 79 m_isSavingRevertStates = true; 80 } 81 82 public void StopSavingPhysicsTimeReversalStates() 83 { 84 m_isSavingRevertStates = false; 85 m_timeReversal.Clear(); 86 } 87 88 public void StartPhysicsTimeReversal() 89 { 90 m_lastRevertedTo = -100; 91 m_isReversing = true; 92 m_scene.RegionInfo.RegionSettings.DisablePhysics = true; 93 } 94 95 public void StopPhysicsTimeReversal() 96 { 97 m_lastRevertedTo = -100; 98 m_scene.RegionInfo.RegionSettings.DisablePhysics = false; 99 m_isReversing = false; 100 } 101 102 #endregion 103 104 private WorldPhysicsState MakePhysicsState() 105 { 106 WorldPhysicsState state = new WorldPhysicsState(); 107 //Add all active objects in the scene 108 foreach (PhysicsObject prm in m_scene.PhysicsScene.ActiveObjects) 109 { 110 state.AddPrim(prm); 111 } 112#if (!ISWIN) 113 foreach (IScenePresence sp in m_scene.GetScenePresences()) 114 { 115 if (!sp.IsChildAgent) 116 { 117 state.AddAvatar(sp.PhysicsActor); 118 } 119 } 120#else 121 foreach (IScenePresence sp in m_scene.GetScenePresences().Where(sp => !sp.IsChildAgent)) 122 { 123 state.AddAvatar(sp.PhysicsActor); 124 } 125#endif 126 return state; 127 } 128 129 private void timeReversal_Elapsed(object sender, ElapsedEventArgs e) 130 { 131 if (!m_isSavingRevertStates) 132 return; //Only save if we are running this 133 if (!m_isReversing) //Only save new states if we are going forward 134 m_timeReversal.Add(MakePhysicsState()); 135 else 136 { 137 if (m_lastRevertedTo == -100) 138 m_lastRevertedTo = m_timeReversal.Count - 1; 139 m_timeReversal[m_lastRevertedTo].Reload(m_scene, -1f); //Do the velocity in reverse with -1 140 m_lastRevertedTo--; 141 if (m_lastRevertedTo < 0) 142 { 143 m_isSavingRevertStates = false; 144 m_lastRevertedTo = -100; 145 m_isReversing = false; 146 m_scene.StopPhysicsScene(); //Stop physics from moving too 147 m_scene.RegionInfo.RegionSettings.DisablePhysics = true; //Freeze the scene 148 m_timeReversal.Clear(); //Remove the states we have as well, we've played them 149 } 150 } 151 } 152 153 #region Nested type: WorldPhysicsState 154 155 public class WorldPhysicsState 156 { 157 private readonly Dictionary<UUID, PhysicsState> m_activePrims = new Dictionary<UUID, PhysicsState>(); 158 159 public void AddPrim(PhysicsObject prm) 160 { 161 PhysicsState state = new PhysicsState 162 { 163 Position = prm.Position, 164 AngularVelocity = prm.RotationalVelocity, 165 LinearVelocity = prm.Velocity, 166 Rotation = prm.Orientation 167 }; 168 m_activePrims[prm.UUID] = state; 169 } 170 171 public void AddAvatar(PhysicsCharacter prm) 172 { 173 PhysicsState state = new PhysicsState 174 { 175 Position = prm.Position, 176 AngularVelocity = prm.RotationalVelocity, 177 LinearVelocity = prm.Velocity, 178 Rotation = prm.Orientation 179 }; 180 m_activePrims[prm.UUID] = state; 181 } 182 183 public void Reload(IScene scene, float direction) 184 { 185 foreach (KeyValuePair<UUID, PhysicsState> kvp in m_activePrims) 186 { 187 ISceneChildEntity childPrim = scene.GetSceneObjectPart(kvp.Key); 188 if (childPrim != null && childPrim.PhysActor != null) 189 ResetPrim(childPrim.PhysActor, kvp.Value, direction); 190 else 191 { 192 IScenePresence sp = scene.GetScenePresence(kvp.Key); 193 if (sp != null) 194 ResetAvatar(sp.PhysicsActor, kvp.Value, direction); 195 } 196 } 197 } 198 199 private void ResetPrim(PhysicsObject physicsObject, PhysicsState physicsState, float direction) 200 { 201 physicsObject.Position = physicsState.Position; 202 physicsObject.Orientation = physicsState.Rotation; 203 physicsObject.RotationalVelocity = physicsState.AngularVelocity*direction; 204 physicsObject.Velocity = physicsState.LinearVelocity*direction; 205 physicsObject.ForceSetVelocity(physicsState.LinearVelocity*direction); 206 physicsObject.RequestPhysicsterseUpdate(); 207 } 208 209 private void ResetAvatar(PhysicsCharacter physicsObject, PhysicsState physicsState, float direction) 210 { 211 physicsObject.Position = physicsState.Position; 212 physicsObject.ForceSetPosition(physicsState.Position); 213 physicsObject.Orientation = physicsState.Rotation; 214 physicsObject.RotationalVelocity = physicsState.AngularVelocity*direction; 215 physicsObject.Velocity = physicsState.LinearVelocity*direction; 216 physicsObject.ForceSetVelocity(physicsState.LinearVelocity*direction); 217 physicsObject.RequestPhysicsterseUpdate(); 218 } 219 220 #region Nested type: PhysicsState 221 222 public class PhysicsState 223 { 224 public Vector3 AngularVelocity; 225 public Vector3 LinearVelocity; 226 public Vector3 Position; 227 public Quaternion Rotation; 228 } 229 230 #endregion 231 } 232 233 #endregion 234 } 235}