Beispiel #1
0
        /// <summary>
        /// Updates the Scene.
        /// </summary>
        public void Update()
        {
            if (!this.active)
            {
                throw new InvalidOperationException("Cannot update a scene that is not active. Call Activate first.");
            }
            if (this.isUpdating)
            {
                throw new InvalidOperationException("Can't update a Scene while it is already being updated.");
            }
            this.isUpdating = true;
            try
            {
                // Remove disposed objects from managers
                this.CleanupDisposedObjects();

                // Update physics
                this.physicsWorld.Simulate(Time.DeltaTime);

                // Update all GameObjects
                Profile.TimeUpdateScene.BeginMeasure();
                DualityApp.EditorGuard(() =>
                {
                    this.UpdateComponents <ICmpUpdatable>(cmp => cmp.OnUpdate());
                    this.visibilityStrategy.Update();
                });
                Profile.TimeUpdateScene.EndMeasure();
            }
            finally
            {
                this.isUpdating = false;
            }
        }
Beispiel #2
0
        private static void OnLeaving()
        {
            switchLock++;
            if (Leaving != null)
            {
                Leaving(current, null);
            }
            isSwitching = true;
            if (current.ResWeak != null)
            {
                // Deactivate GameObjects
                DualityApp.EditorGuard(() =>
                {
                    GameObject[] activeObj = current.ResWeak.ActiveObjects.ToArray();
                    foreach (GameObject o in activeObj)
                    {
                        o.OnDeactivate();
                    }
                });

                // Clear the physics world of all contents
                physicsWorld.Clear();
                ResetPhysics();
            }
            switchLock--;
        }
Beispiel #3
0
        /// <summary>
        /// Transitions the <see cref="Scene"/> into an inactive state, where it can no
        /// longer be updated or rendered. This is the state of a <see cref="Scene"/>
        /// after it was loaded.
        /// </summary>
        public void Deactivate()
        {
            if (!this.active)
            {
                throw new InvalidOperationException("Cannot deactivate a scene that is not active.");
            }

            // Deactivate GameObjects
            DualityApp.EditorGuard(() =>
            {
                // Create a list of components to deactivate
                List <ICmpInitializable> shutdownList = new List <ICmpInitializable>();
                foreach (Component component in this.FindComponents <ICmpInitializable>())
                {
                    if (!component.Active)
                    {
                        continue;
                    }
                    shutdownList.Add(component as ICmpInitializable);
                }
                // Deactivate all the listed components. Note that they may create or destroy
                // objects, so it's important that we're iterating a copy of the scene objects
                // here, and not the real thing.
                for (int i = shutdownList.Count - 1; i >= 0; i--)
                {
                    shutdownList[i].OnDeactivate();
                }
            });

            // Clear physics world as we're ending simulation
            this.physicsWorld.Native.Clear();
            this.physicsWorld.ResetSimulation();

            this.active = false;
        }
Beispiel #4
0
        /// <summary>
        /// Transitions the <see cref="Scene"/> into an active state, where it can be
        /// updated and rendered. This is the state of a <see cref="Scene"/> while it
        /// is <see cref="Current"/>.
        /// </summary>
        public void Activate()
        {
            if (this.active)
            {
                throw new InvalidOperationException("Cannot activate a scene that is already active.");
            }

            // Set state to active immediately, so the scene will be treated as
            // such when reacting to added objects and similar events.
            this.active = true;

            // Apply physical properties
            this.physicsWorld.ResetSimulation();
            this.physicsWorld.Gravity = this.globalGravity;

            // When in the editor, apply prefab links
            if (DualityApp.ExecEnvironment == DualityApp.ExecutionEnvironment.Editor)
            {
                this.ApplyPrefabLinks();
            }

            // When running the game, break prefab links
            if (DualityApp.ExecContext == DualityApp.ExecutionContext.Game)
            {
                this.BreakPrefabLinks();
            }

            // Activate GameObjects
            DualityApp.EditorGuard(() =>
            {
                // Create a list of components to activate
                List <ICmpInitializable> initList = new List <ICmpInitializable>();
                foreach (Component component in this.FindComponents <ICmpInitializable>())
                {
                    if (!component.Active)
                    {
                        continue;
                    }
                    initList.Add(component as ICmpInitializable);
                }
                // Activate all the listed components. Note that they may create or destroy
                // objects, so it's important that we're iterating a copy of the scene objects
                // here, and not the real thing.
                for (int i = 0; i < initList.Count; i++)
                {
                    initList[i].OnActivate();
                }
            });

            // Update object visibility / culling info, so a scheduled switch at the
            // end of a frame will get up-to-date culling for rendering
            DualityApp.EditorGuard(() =>
            {
                this.visibilityStrategy.Update();
            });
        }
Beispiel #5
0
        private static void OnEntered()
        {
            switchLock++;
            if (current.ResWeak != null)
            {
                // Apply physical properties
                ResetPhysics();
                physicsWorld.Gravity = PhysicsUnit.ForceToPhysical * current.ResWeak.GlobalGravity;

                // When in the editor, apply prefab links
                if (DualityApp.ExecEnvironment == DualityApp.ExecutionEnvironment.Editor)
                {
                    current.ResWeak.ApplyPrefabLinks();
                }

                // When running the game, break prefab links
                if (DualityApp.ExecContext == DualityApp.ExecutionContext.Game)
                {
                    current.ResWeak.BreakPrefabLinks();
                }

                // Activate GameObjects
                DualityApp.EditorGuard(() =>
                {
                    // Create a list of components to activate
                    List <ICmpInitializable> initList = new List <ICmpInitializable>();
                    foreach (Component component in current.ResWeak.FindComponents <ICmpInitializable>())
                    {
                        if (!component.Active)
                        {
                            continue;
                        }
                        initList.Add(component as ICmpInitializable);
                    }
                    // Activate all the listed components. Note that they may create or destroy
                    // objects, so it's important that we're iterating a copy of the scene objects
                    // here, and not the real thing.
                    for (int i = 0; i < initList.Count; i++)
                    {
                        initList[i].OnInit(Component.InitContext.Activate);
                    }
                });
            }
            isSwitching = false;
            if (Entered != null)
            {
                Entered(current, null);
            }
            switchLock--;
        }
Beispiel #6
0
        /// <summary>
        /// Updates the Scene in the editor.
        /// </summary>
        internal void EditorUpdate()
        {
            if (!this.IsCurrent)
            {
                throw new InvalidOperationException("Can't update non-current Scene!");
            }
            switchLock++;

            Profile.TimeUpdateScene.BeginMeasure();
            DualityApp.EditorGuard(() =>
            {
                this.UpdateComponents <ICmpEditorUpdatable>(cmp => cmp.OnUpdate());
                this.visibilityStrategy.Update();
            });
            Profile.TimeUpdateScene.EndMeasure();

            switchLock--;
        }
Beispiel #7
0
 /// <summary>
 /// Updates the Scene in the editor.
 /// </summary>
 internal void EditorUpdate()
 {
     if (this.isUpdating)
     {
         throw new InvalidOperationException("Can't update a Scene while it is already being updated.");
     }
     this.isUpdating = true;
     try
     {
         Profile.TimeUpdateScene.BeginMeasure();
         DualityApp.EditorGuard(() =>
         {
             this.UpdateComponents <ICmpEditorUpdatable>(cmp => cmp.OnUpdate());
         });
         Profile.TimeUpdateScene.EndMeasure();
     }
     finally
     {
         this.isUpdating = false;
     }
 }
Beispiel #8
0
        /// <summary>
        /// Updates the Scene in the editor.
        /// </summary>
        internal void EditorUpdate()
        {
            if (!this.IsCurrent)
            {
                throw new InvalidOperationException("Can't update non-current Scene!");
            }
            switchLock++;

            Profile.TimeUpdateScene.BeginMeasure();
            DualityApp.EditorGuard(() =>
            {
                // Update all GameObjects
                GameObject[] activeObj = this.objectManager.ActiveObjects.ToArray();
                foreach (GameObject obj in activeObj)
                {
                    obj.EditorUpdate();
                }
            });
            Profile.TimeUpdateScene.EndMeasure();

            switchLock--;
        }
Beispiel #9
0
        private static void OnEntered()
        {
            switchLock++;
            if (current.ResWeak != null)
            {
                // Apply physical properties
                ResetPhysics();
                physicsWorld.Gravity = PhysicsUnit.ForceToPhysical * current.ResWeak.GlobalGravity;

                // When in the editor, apply prefab links
                if (DualityApp.ExecEnvironment == DualityApp.ExecutionEnvironment.Editor)
                {
                    current.ResWeak.ApplyPrefabLinks();
                }

                // When running the game, break prefab links
                if (DualityApp.ExecContext == DualityApp.ExecutionContext.Game)
                {
                    current.ResWeak.BreakPrefabLinks();
                }

                // Activate GameObjects
                DualityApp.EditorGuard(() =>
                {
                    GameObject[] activeObj = current.ResWeak.ActiveObjects.ToArray();
                    foreach (GameObject o in activeObj)
                    {
                        o.OnActivate();
                    }
                });
            }
            isSwitching = false;
            if (Entered != null)
            {
                Entered(current, null);
            }
            switchLock--;
        }
Beispiel #10
0
        private static void OnLeaving()
        {
            switchLock++;
            if (Leaving != null)
            {
                Leaving(current, null);
            }
            isSwitching = true;
            if (current.ResWeak != null)
            {
                // Deactivate GameObjects
                DualityApp.EditorGuard(() =>
                {
                    // Create a list of components to deactivate
                    List <ICmpInitializable> shutdownList = new List <ICmpInitializable>();
                    foreach (Component component in current.ResWeak.FindComponents <ICmpInitializable>())
                    {
                        if (!component.Active)
                        {
                            continue;
                        }
                        shutdownList.Add(component as ICmpInitializable);
                    }
                    // Deactivate all the listed components. Note that they may create or destroy
                    // objects, so it's important that we're iterating a copy of the scene objects
                    // here, and not the real thing.
                    for (int i = shutdownList.Count - 1; i >= 0; i--)
                    {
                        shutdownList[i].OnShutdown(Component.ShutdownContext.Deactivate);
                    }
                });

                // Clear the physics world of all contents
                physicsWorld.Clear();
                ResetPhysics();
            }
            switchLock--;
        }
Beispiel #11
0
        /// <summary>
        /// Updates the Scene
        /// </summary>
        internal void Update()
        {
            if (!this.IsCurrent)
            {
                throw new InvalidOperationException("Can't update non-current Scene!");
            }
            switchLock++;

            // Update physics
            bool   physUpdate = false;
            double physBegin  = Time.MainTimer.TotalMilliseconds;

            if (Scene.PhysicsFixedTime)
            {
                physicsAcc += Time.MsPFMult * Time.TimeMult;
                int iterations = 0;
                if (physicsAcc >= Time.MsPFMult)
                {
                    Profile.TimeUpdatePhysics.BeginMeasure();
                    DualityApp.EditorGuard(() =>
                    {
                        double timeUpdateBegin = Time.MainTimer.TotalMilliseconds;
                        while (physicsAcc >= Time.MsPFMult)
                        {
                            // Catch up on updating progress
                            FarseerPhysics.Settings.VelocityThreshold = PhysicsUnit.VelocityToPhysical * DualityApp.AppData.PhysicsVelocityThreshold;
                            physicsWorld.Step(Time.SPFMult);
                            physicsAcc -= Time.MsPFMult;
                            iterations++;

                            double timeSpent = Time.MainTimer.TotalMilliseconds - timeUpdateBegin;
                            if (timeSpent >= Time.MsPFMult * 10.0f)
                            {
                                break;                                                                 // Emergency exit
                            }
                        }
                    });
                    physUpdate = true;
                    Profile.TimeUpdatePhysics.EndMeasure();
                }
            }
            else
            {
                Profile.TimeUpdatePhysics.BeginMeasure();
                DualityApp.EditorGuard(() =>
                {
                    FarseerPhysics.Settings.VelocityThreshold = PhysicsUnit.VelocityToPhysical * Time.TimeMult * DualityApp.AppData.PhysicsVelocityThreshold;
                    physicsWorld.Step(Time.TimeMult * Time.SPFMult);
                    if (Time.TimeMult == 0.0f)
                    {
                        physicsWorld.ClearForces();                                            // Complete freeze? Clear forces, so they don't accumulate.
                    }
                    physicsAcc = PhysicsAccStart;
                });
                physUpdate = true;
                Profile.TimeUpdatePhysics.EndMeasure();
            }
            double physTime = Time.MainTimer.TotalMilliseconds - physBegin;

            // Apply Farseers internal measurements to Duality
            if (physUpdate)
            {
                Profile.TimeUpdatePhysicsAddRemove.Set(1000.0f * physicsWorld.AddRemoveTime / System.Diagnostics.Stopwatch.Frequency);
                Profile.TimeUpdatePhysicsContacts.Set(1000.0f * physicsWorld.ContactsUpdateTime / System.Diagnostics.Stopwatch.Frequency);
                Profile.TimeUpdatePhysicsContinous.Set(1000.0f * physicsWorld.ContinuousPhysicsTime / System.Diagnostics.Stopwatch.Frequency);
                Profile.TimeUpdatePhysicsController.Set(1000.0f * physicsWorld.ControllersUpdateTime / System.Diagnostics.Stopwatch.Frequency);
                Profile.TimeUpdatePhysicsSolve.Set(1000.0f * physicsWorld.SolveUpdateTime / System.Diagnostics.Stopwatch.Frequency);
            }

            // Update low fps physics state
            if (!physicsLowFps)
            {
                physicsLowFps = Time.LastDelta > Time.MsPFMult && physTime > Time.LastDelta * 0.85f;
            }
            else
            {
                physicsLowFps = !(Time.LastDelta < Time.MsPFMult * 0.9f || physTime < Time.LastDelta * 0.6f);
            }

            // Update all GameObjects
            Profile.TimeUpdateScene.BeginMeasure();
            DualityApp.EditorGuard(() =>
            {
                this.UpdateComponents <ICmpUpdatable>(cmp => cmp.OnUpdate());
                this.visibilityStrategy.Update();
            });
            Profile.TimeUpdateScene.EndMeasure();

            // Perform a cleanup step to catch all DisposeLater calls from within the Scene update
            DualityApp.RunCleanup();

            // Perform a scheduled Scene switch
            PerformScheduledSwitch();

            switchLock--;
        }
Beispiel #12
0
        /// <summary>
        /// Advances this physics world simulation by <paramref name="timestep"/> seconds.
        ///
        /// If <see cref="IsFixedTimestep"/> is true, this may actually simulate multiple smaller
        /// steps, or none at all while accumulating the internal fixed step timer. Otherwise,
        /// it will perform exactly one physics stept with the specified <paramref name="timestep"/>.
        /// </summary>
        /// <param name="timestep"></param>
        public void Simulate(float timestep)
        {
            bool   physUpdate = false;
            double physBegin  = Time.MainTimer.TotalSeconds;

            if (this.IsFixedTimestep)
            {
                this.fixedStepTimer += timestep;
                int iterations = 0;
                if (this.fixedStepTimer >= this.fixedStepPeriod)
                {
                    Profile.TimeUpdatePhysics.BeginMeasure();
                    DualityApp.EditorGuard(() =>
                    {
                        double timeUpdateBegin = Time.MainTimer.TotalSeconds;
                        while (this.fixedStepTimer >= this.fixedStepPeriod)
                        {
                            // Catch up on updating progress
                            this.UpdateNativeSettings();
                            this.native.Step(this.fixedStepPeriod);
                            this.fixedStepTimer -= this.fixedStepPeriod;
                            iterations++;

                            double timeSpent = Time.MainTimer.TotalSeconds - timeUpdateBegin;
                            if (timeSpent >= Time.SecondsPerFrame * 10.0f)
                            {
                                break;                                                                        // Emergency exit
                            }
                        }
                    });
                    physUpdate = true;
                    Profile.TimeUpdatePhysics.EndMeasure();
                }
            }
            else
            {
                Profile.TimeUpdatePhysics.BeginMeasure();
                DualityApp.EditorGuard(() =>
                {
                    this.UpdateNativeSettings();
                    this.native.Step(timestep);
                    if (timestep == 0.0f)
                    {
                        this.native.ClearForces();                                       // Complete freeze? Clear forces, so they don't accumulate.
                    }
                    this.fixedStepTimer = this.fixedStepPeriod;
                });
                physUpdate = true;
                Profile.TimeUpdatePhysics.EndMeasure();
            }
            double physTime = Time.MainTimer.TotalSeconds - physBegin;

            // Apply Farseers internal measurements to Duality
            if (physUpdate)
            {
                Profile.TimeUpdatePhysicsAddRemove.Set(1000.0f * this.native.AddRemoveTime / Stopwatch.Frequency);
                Profile.TimeUpdatePhysicsContacts.Set(1000.0f * this.native.ContactsUpdateTime / Stopwatch.Frequency);
                Profile.TimeUpdatePhysicsContinous.Set(1000.0f * this.native.ContinuousPhysicsTime / Stopwatch.Frequency);
                Profile.TimeUpdatePhysicsController.Set(1000.0f * this.native.ControllersUpdateTime / Stopwatch.Frequency);
                Profile.TimeUpdatePhysicsSolve.Set(1000.0f * this.native.SolveUpdateTime / Stopwatch.Frequency);
            }

            // Update low fps physics state
            if (!this.lowFramerateMode)
            {
                this.lowFramerateMode = Time.UnscaledDeltaTime > Time.SecondsPerFrame && physTime > Time.UnscaledDeltaTime * 0.85f;
            }
            else
            {
                this.lowFramerateMode = !(Time.UnscaledDeltaTime < Time.SecondsPerFrame * 0.9f || physTime < Time.UnscaledDeltaTime * 0.6f);
            }
        }