Esempio n. 1
0
        [Test] public void SwitchToDuringEnter()
        {
            // Set up some objects
            Scene scene  = new Scene();
            Scene scene2 = new Scene();

            // Switch to the first Scene regularly
            {
                Scene.SwitchTo(scene);
                Assert.AreEqual(Scene.Current, scene);
            }

            // Switch to the second while entering
            {
                Scene.SwitchTo(null);

                GameObject obj             = new GameObject("SwitchObject");
                var        switchComponent = new InitSwitchToSceneComponent {
                    Target = scene2
                };
                obj.AddComponent(switchComponent);
                scene.AddObject(obj);

                Scene.SwitchTo(scene);
                DualityApp.Update();
                Assert.False(switchComponent.Switched);
                Assert.AreEqual(Scene.Current, scene2);
            }

            // Clean up
            scene.Dispose();
            scene2.Dispose();
        }
Esempio n. 2
0
 void INativeWindow.Run()
 {
     while (DualityApp.ExecContext != DualityApp.ExecutionContext.Terminated)
     {
         DualityApp.Update();
         DualityApp.Render(null, new Rect(DualityApp.UserData.WindowSize), DualityApp.UserData.WindowSize);
     }
 }
Esempio n. 3
0
 void INativeWindow.Run()
 {
     while (DualityApp.ExecContext != DualityApp.ExecutionContext.Terminated)
     {
         DualityApp.Update();
         DualityApp.Render(null, new Rect(640, 480), new Vector2(640, 480));
     }
 }
Esempio n. 4
0
 void INativeWindow.Run()
 {
     while (DualityApp.ExecContext != DualityApp.ExecutionContext.Terminated)
     {
         DualityApp.Update();
         DualityApp.Render(new Rect(DualityApp.UserData.GfxWidth, DualityApp.UserData.GfxHeight));
     }
 }
Esempio n. 5
0
        /// <summary>
        /// This test will determine whether a <see cref="Scene"/> can be activated, updated and deactivated
        /// in isolation from the global <see cref="Scene.Current"/> setting.
        /// </summary>
        [Test] public void IsolatedSimulation()
        {
            // Create an isolated new test scene with a ball and a platform
            Scene scene = new Scene();

            GameObject ball          = new GameObject("Ball");
            Transform  ballTransform = ball.AddComponent <Transform>();
            RigidBody  ballBody      = ball.AddComponent <RigidBody>();

            ballBody.AddShape(new CircleShapeInfo(32.0f, new Vector2(0.0f, 0.0f), 1.0f));
            ball.AddComponent <RigidBodyRenderer>();
            scene.AddObject(ball);

            GameObject platform          = new GameObject("Platform");
            Transform  platformTransform = platform.AddComponent <Transform>();

            platformTransform.Pos = new Vector3(0.0f, 128.0f, 0.0f);
            RigidBody platformBody = platform.AddComponent <RigidBody>();

            platformBody.AddShape(new ChainShapeInfo(new[] { new Vector2(-128.0f, 0.0f), new Vector2(128.0f, 0.0f) }));
            platformBody.BodyType = BodyType.Static;
            platform.AddComponent <RigidBodyRenderer>();
            scene.AddObject(platform);

            // Do a single, fixed-step Duality update in order to set up
            // Time.DeltaTime in a predictable way.
            DualityApp.Update(true);

            // Assert that the isolated scene remains unaffected
            Assert.AreEqual(new Vector3(0.0f, 0.0f, 0.0f), ballTransform.Pos);
            Assert.AreEqual(new Vector3(0.0f, 128.0f, 0.0f), platformTransform.Pos);

            // Activate the scene to prepare for simulation
            scene.Activate();

            // Run the simulation for a few fixed-step frames
            for (int i = 0; i < 100; i++)
            {
                scene.Update();
            }

            // Deactivate the scene again
            scene.Deactivate();

            // Assert that the balls position is within expected values
            Assert.IsTrue(ballTransform.Pos.Y > 96.0f);
            Assert.IsTrue(ballTransform.Pos.Y < 128.0f);
            Assert.IsTrue(Math.Abs(ballTransform.Pos.X) < 1.00f);
            Assert.IsTrue(Math.Abs(ballTransform.Pos.Z) < 1.00f);
        }
Esempio n. 6
0
        [Test] public void FallingBallOnPlatform()
        {
            Scene scene = new Scene();

            Scene.SwitchTo(scene);

            // Create the ball
            GameObject ball          = new GameObject("Ball");
            Transform  ballTransform = ball.AddComponent <Transform>();
            RigidBody  ballBody      = ball.AddComponent <RigidBody>();

            ballBody.Restitution = 0f;
            CollisionEventReceiver listener = ball.AddComponent <CollisionEventReceiver>();

            ballBody.AddShape(new CircleShapeInfo(1, new Vector2(0, 0), 1));
            scene.AddObject(ball);

            // Create the platform
            GameObject platform      = new GameObject("Platform");
            Transform  platformTrans = platform.AddComponent <Transform>();

            platformTrans.Pos = new Vector3(0, 5, 0);
            RigidBody platformBody = platform.AddComponent <RigidBody>();

            platformBody.Restitution = 0f;
            platformBody.AddShape(new ChainShapeInfo(new[] { new Vector2(-1, 0), new Vector2(1, 0), }));
            platformBody.BodyType = BodyType.Static;
            scene.AddObject(platform);

            // Simulate some update steps
            for (int i = 0; i < 10; i++)
            {
                DualityApp.Update(true);
            }

            // Check if the position is within expected values
            Assert.IsTrue(ballTransform.Pos.Y > 3f);
            Assert.IsTrue(ballTransform.Pos.Y < 5f);
            Assert.IsTrue(Math.Abs(ballTransform.Pos.X) < 0.01f);
            Assert.IsTrue(Math.Abs(ballTransform.Pos.Z) < 0.01f);

            // Check if the collision events were triggered
            // First one should always be a begin
            Assert.IsTrue(listener.Collisions[0].Type == CollisionEventReceiver.CollisionType.Begin);
            // The ones after that should all be of type Solve. There should be no event of type End since there is no bouncing.
            Assert.IsTrue(listener.Collisions.Skip(1).All(x => x.Type == CollisionEventReceiver.CollisionType.Solve));
        }
Esempio n. 7
0
        [Test] public void SwitchReloadDeferredDispose()
        {
            // Inject some pseudo loading code for our Scene.
            const string TestSceneName = "TestScene";
            EventHandler <ResourceResolveEventArgs> resolveHandler = delegate(object sender, ResourceResolveEventArgs e)
            {
                if (e.RequestedContent == TestSceneName)
                {
                    e.Resolve(new Scene());
                }
            };

            ContentProvider.ResourceResolve += resolveHandler;

            // Retrieve the Scene and make sure it's always the same
            Scene scene = ContentProvider.RequestContent <Scene>(TestSceneName).Res;

            Assert.IsNotNull(scene);
            {
                Scene scene2 = ContentProvider.RequestContent <Scene>(TestSceneName).Res;
                Assert.AreSame(scene, scene2);
            }

            // Switch to the Scene regularly
            {
                Scene.SwitchTo(scene);
                Assert.AreSame(Scene.Current, scene);
            }

            // Reload the Scene during update while using deferred disposal
            {
                GameObject obj = new GameObject("SwitchObject");
                obj.AddComponent <UpdateReloadSceneComponent>();
                scene.AddObject(obj);

                Assert.AreSame(Scene.Current, scene);
                DualityApp.Update();
                Assert.AreNotSame(Scene.Current, scene);
                Assert.AreEqual(TestSceneName, Scene.Current.Path);
            }

            // Clean up
            ContentProvider.ResourceResolve -= resolveHandler;
            scene.Dispose();
        }
Esempio n. 8
0
        private void OnUpdate(double milliseconds)
        {
            if (DualityApp.ExecContext == DualityApp.ExecutionContext.Terminated)
            {
                return;
            }

            DualityApp.Update();

            Vector2 imageSize;
            Rect    viewportRect;

            DualityApp.CalculateGameViewport(this.Size, out viewportRect, out imageSize);

            DualityApp.Render(null, viewportRect, imageSize);

            window.Invoke("requestAnimationFrame", updateDelegate);
        }
Esempio n. 9
0
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            //base.OnUpdateFrame(e);

            if (DualityApp.ExecContext == DualityApp.ExecutionContext.Terminated)
            {
                if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
                {
                    (Context as Activity).FinishAndRemoveTask();
                }
                else
                {
                    (Context as Activity).Finish();
                }
                System.Environment.Exit(0);
                return;
            }

            DualityApp.Update();
        }
Esempio n. 10
0
		[Test] public void EnforceOrderSceneUpdate()
		{
			EventOrderLog eventLog = new EventOrderLog();
			eventLog.EventFilter = EventType.Update;

			Scene scene = this.GenerateSampleScene(10,
				typeof(TestComponentA1), 
				typeof(TestComponentA2), 
				typeof(TestComponentA3), 
				typeof(TestComponentA4), 
				typeof(TestComponentA5));

			Scene.SwitchTo(scene, true);

			this.AssignEventLog(scene, eventLog);
			DualityApp.Update();
			this.AssertEventOrder(eventLog, 5 * 10, Component.ExecOrder, false);

			Scene.SwitchTo(null, true);
		}
Esempio n. 11
0
        private void OnUpdateFrame(FrameEventArgs e)
        {
            if (DualityApp.ExecContext == DualityApp.ExecutionContext.Terminated)
            {
                this.internalWindow.Close();
                return;
            }

            // Give the processor a rest if we have the time, don't use 100% CPU even without VSync
            if (this.frameLimiterWatch.IsRunning && this.refreshMode == RefreshMode.ManualSync)
            {
                while (this.frameLimiterWatch.Elapsed.TotalMilliseconds < Time.MsPFMult)
                {
                    // Enough leftover time? Risk a millisecond sleep.
                    //if (this.frameLimiterWatch.Elapsed.TotalMilliseconds < Time.MsPFMult * 0.75f)
                    //	System.Threading.Thread.Sleep(1);
                }
            }
            this.frameLimiterWatch.Restart();
            DualityApp.Update();
        }
Esempio n. 12
0
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            if (DualityApp.ExecContext == DualityApp.ExecutionContext.Terminated)
            {
                this.Close();
                return;
            }

            if (!isDebugging && !isProfiling)             // Don't limit frame rate when debugging or profiling.
            {
                //// Assure we'll at least wait 16 ms until updating again.
                //if (this.frameLimiterWatch.IsRunning)
                //{
                //    while (this.frameLimiterWatch.Elapsed.TotalSeconds < 0.016d)
                //    {
                //        // Go to sleep if we'd have to wait too long
                //        if (this.frameLimiterWatch.Elapsed.TotalSeconds < 0.01d)
                //            System.Threading.Thread.Sleep(1);
                //    }
                //}

                // Give the processor a rest if we have the time, don't use 100% CPU even without VSync
                if (this.frameLimiterWatch.IsRunning && this.VSync == VSyncMode.Off)
                {
                    while (this.frameLimiterWatch.Elapsed.TotalMilliseconds < Time.MsPFMult)
                    {
                        // Enough leftover time? Risk a millisecond sleep.
                        if (this.frameLimiterWatch.Elapsed.TotalMilliseconds < Time.MsPFMult * 0.75f)
                        {
                            System.Threading.Thread.Sleep(1);
                        }
                    }
                }
                this.frameLimiterWatch.Restart();
            }
            this.mainJoystickDriver.Poll();
            DualityApp.Update();
        }
Esempio n. 13
0
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);

            if (!_isDebugging && !_isProfiling)             // Don't limit frame rate when debugging or profiling.
            {
                //// Assure we'll at least wait 16 ms until updating again.
                //if (this.frameLimiterWatch.IsRunning)
                //{
                //    while (this.frameLimiterWatch.Elapsed.TotalSeconds < 0.016d)
                //    {
                //        // Go to sleep if we'd have to wait too long
                //        if (this.frameLimiterWatch.Elapsed.TotalSeconds < 0.01d)
                //            System.Threading.Thread.Sleep(1);
                //    }
                //}

                // Give the processor a rest if we have the time, don't use 100% CPU even without VSync

                /* DEBT: waiting for VSync no control for VSync on android
                 */
                if (_frameLimiterWatch.IsRunning)                 // && this.VSync == VSyncMode.Off)
                {
                    while (_frameLimiterWatch.Elapsed.TotalMilliseconds < Time.MsPFMult)
                    {
                        // Enough leftover time? Risk a millisecond sleep.
                        if (_frameLimiterWatch.Elapsed.TotalMilliseconds < Time.MsPFMult * 0.75f)
                        {
                            System.Threading.Thread.Sleep(1);
                        }
                    }
                }
                _frameLimiterWatch.Restart();
            }
            DualityApp.Update();
        }
Esempio n. 14
0
        [Test] public void VelocityInHierarchy()
        {
            // In this test case, we'll set up a parent and a child transform
            // to see if changes to the parent affect the child transforms velocity value
            GameObject      parentObj       = new GameObject("Parent");
            GameObject      obj             = new GameObject("Child", parentObj);
            Transform       parentTransform = parentObj.AddComponent <Transform>();
            Transform       transform       = obj.AddComponent <Transform>();
            VelocityTracker tracker         = obj.AddComponent <VelocityTracker>();

            // Since velocity values are only updated after the frame ends, we need
            // a full scene setup to simulate an update cycle
            using (Scene testScene = new Scene())
            {
                // Setup and enter the scene
                testScene.AddObject(parentObj);
                Scene.SwitchTo(testScene, true);
                DualityApp.Update(true);

                // Identity parent and a moving child
                parentTransform.Pos   = Vector3.Zero;
                parentTransform.Angle = 0.0f;
                parentTransform.Scale = 1.0f;
                transform.Pos         = Vector3.Zero;
                transform.Angle       = 0.0f;
                transform.Scale       = 1.0f;

                transform.MoveByLocal(new Vector3(1.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.DegToRad(90.0f));
                DualityApp.Update(true);

                AssertEqual(new Vector3(1.0f, 0.0f, 0.0f), tracker.LastMovement, "Absolute child velocity");
                AssertEqual(MathF.DegToRad(90.0f), tracker.LastAngleMovement, "Absolute child angle velocity");

                // Transformed parent and a moving child
                parentTransform.Pos   = new Vector3(1.0f, 2.0f, 3.0f);
                parentTransform.Angle = MathF.DegToRad(90.0f);
                parentTransform.Scale = 2.0f;
                transform.Pos         = Vector3.Zero;
                transform.Angle       = 0.0f;
                transform.Scale       = 1.0f;

                transform.MoveByLocal(new Vector3(1.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.DegToRad(90.0f));
                DualityApp.Update(true);

                AssertEqual(new Vector3(0.0f, 2.0f, 0.0f), tracker.LastMovement, "Absolute child velocity");
                AssertEqual(MathF.DegToRad(90.0f), tracker.LastAngleMovement, "Absolute child angle velocity");

                // Moving parent and a transformed child
                parentTransform.Pos   = Vector3.Zero;
                parentTransform.Angle = 0.0f;
                parentTransform.Scale = 1.0f;
                transform.Pos         = new Vector3(1.0f, 0.0f, 0.0f);
                transform.Angle       = 0.0f;
                transform.Scale       = 1.0f;

                parentTransform.MoveByLocal(new Vector3(1.0f, 0.0f, 0.0f));
                DualityApp.Update(true);

                AssertEqual(new Vector3(1.0f, 0.0f, 0.0f), tracker.LastMovement, "Absolute child velocity");

                // Moving parent and a transformed, moving child
                parentTransform.Pos   = Vector3.Zero;
                parentTransform.Angle = 0.0f;
                parentTransform.Scale = 1.0f;
                transform.Pos         = new Vector3(1.0f, 0.0f, 0.0f);
                transform.Angle       = 0.0f;
                transform.Scale       = 1.0f;

                transform.MoveByLocal(new Vector3(1.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.DegToRad(90.0f));
                parentTransform.MoveByLocal(new Vector3(1.0f, 0.0f, 0.0f));
                DualityApp.Update(true);

                AssertEqual(new Vector3(2.0f, 0.0f, 0.0f), tracker.LastMovement, "Absolute child velocity");
                AssertEqual(MathF.DegToRad(90.0f), tracker.LastAngleMovement, "Absolute child angle velocity");
            }
        }
Esempio n. 15
0
        [Test] public void VelocityTeleportAndMove()
        {
            GameObject      obj       = new GameObject("TestObject");
            Transform       transform = obj.AddComponent <Transform>();
            VelocityTracker tracker   = obj.AddComponent <VelocityTracker>();

            // Since velocity values are only updated after the frame ends, we need
            // a full scene setup to simulate an update cycle
            using (Scene testScene = new Scene())
            {
                // Setup and enter the scene
                testScene.AddObject(obj);
                Scene.SwitchTo(testScene, true);
                DualityApp.Update(true);

                // The object is at rest
                transform.Pos   = Vector3.Zero;
                transform.Angle = 0.0f;
                DualityApp.Update(true);
                AssertEqual(Vector3.Zero, tracker.LastMovement, "Velocity at rest");
                AssertEqual(0.0f, tracker.LastAngleMovement, "Angle velocity at rest");

                // The object is teleported
                transform.Pos   = new Vector3(1.0f, 0.0f, 0.0f);
                transform.Angle = MathF.RadAngle90;
                DualityApp.Update(true);
                AssertEqual(Vector3.Zero, tracker.LastMovement, "Velocity after teleport");
                AssertEqual(0.0f, tracker.LastAngleMovement, "Angle velocity after teleport");

                // The object is moved
                transform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.RadAngle90);
                DualityApp.Update(true);
                AssertEqual(new Vector3(1.0f, 0.0f, 0.0f), tracker.LastMovement, "Velocity after move");
                AssertEqual(MathF.RadAngle90, tracker.LastAngleMovement, "Angle velocity after teleport");

                // The object rests for a frame
                DualityApp.Update(true);
                AssertEqual(Vector3.Zero, tracker.LastMovement, "Velocity after one frame rest");
                AssertEqual(0.0f, tracker.LastAngleMovement, "Angle velocity after one frame rest");

                // The object is moved, then teleported
                transform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.RadAngle90);
                transform.Pos   = new Vector3(1.0f, 0.0f, 0.0f);
                transform.Angle = MathF.RadAngle90;
                DualityApp.Update(true);
                AssertEqual(Vector3.Zero, tracker.LastMovement, "Velocity after move, then teleport");
                AssertEqual(0.0f, tracker.LastAngleMovement, "Angle velocity after move, then teleport");

                // The object is moved, then teleported, then moved again
                transform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.RadAngle90);
                transform.Pos   = new Vector3(1.0f, 0.0f, 0.0f);
                transform.Angle = MathF.RadAngle90;
                transform.MoveBy(new Vector3(2.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.RadAngle45);
                DualityApp.Update(true);
                AssertEqual(new Vector3(2.0f, 0.0f, 0.0f), tracker.LastMovement, "Velocity after move, then teleport, then move");
                AssertEqual(MathF.RadAngle45, tracker.LastAngleMovement, "Angle velocity after move, then teleport, then move");
            }
        }
Esempio n. 16
0
        [Test] public void TransformHierarchyVelocity()
        {
            // In this test case, we'll set up a parent and a child transform
            // to see if changes to the parent affect the child transforms velocity value
            GameObject parentObj       = new GameObject("Parent");
            GameObject obj             = new GameObject("Child", parentObj);
            Transform  parentTransform = parentObj.AddComponent <Transform>();
            Transform  transform       = obj.AddComponent <Transform>();

            // Since velocity values are only updated after the frame ends, we need
            // a full scene setup to simulate an update cycle
            using (Scene testScene = new Scene())
            {
                // Setup and enter the scene
                testScene.AddObject(parentObj);
                Scene.SwitchTo(testScene, true);
                DualityApp.Update(true);

                // Identity parent and a moving child
                parentTransform.Pos   = Vector3.Zero;
                parentTransform.Angle = 0.0f;
                parentTransform.Scale = 1.0f;
                transform.Pos         = Vector3.Zero;
                transform.Angle       = 0.0f;
                transform.Scale       = 1.0f;

                transform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.DegToRad(90.0f));
                DualityApp.Update(true);

                AssertEqual(new Vector3(1.0f, 0.0f, 0.0f), transform.RelativeVel, "Relative child velocity");
                AssertEqual(new Vector3(1.0f, 0.0f, 0.0f), transform.Vel, "Absolute child velocity");
                AssertEqual(MathF.DegToRad(90.0f), transform.RelativeAngleVel, "Relative child angle velocity");
                AssertEqual(MathF.DegToRad(90.0f), transform.AngleVel, "Absolute child angle velocity");

                // Transformed parent and a moving child
                parentTransform.Pos   = new Vector3(1.0f, 2.0f, 3.0f);
                parentTransform.Angle = MathF.DegToRad(90.0f);
                parentTransform.Scale = 2.0f;
                transform.Pos         = Vector3.Zero;
                transform.Angle       = 0.0f;
                transform.Scale       = 1.0f;

                transform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.DegToRad(90.0f));
                DualityApp.Update(true);

                AssertEqual(new Vector3(1.0f, 0.0f, 0.0f), transform.RelativeVel, "Relative child velocity");
                AssertEqual(new Vector3(0.0f, 2.0f, 0.0f), transform.Vel, "Absolute child velocity");
                AssertEqual(MathF.DegToRad(90.0f), transform.RelativeAngleVel, "Relative child angle velocity");
                AssertEqual(MathF.DegToRad(90.0f), transform.AngleVel, "Absolute child angle velocity");

                // Moving parent and a transformed child
                parentTransform.Pos   = Vector3.Zero;
                parentTransform.Angle = 0.0f;
                parentTransform.Scale = 1.0f;
                transform.Pos         = new Vector3(1.0f, 0.0f, 0.0f);
                transform.Angle       = 0.0f;
                transform.Scale       = 1.0f;

                parentTransform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                DualityApp.Update(true);

                AssertEqual(new Vector3(0.0f, 0.0f, 0.0f), transform.RelativeVel, "Relative child velocity");
                AssertEqual(new Vector3(1.0f, 0.0f, 0.0f), transform.Vel, "Absolute child velocity");

                // Moving parent and a transformed, moving child
                parentTransform.Pos   = Vector3.Zero;
                parentTransform.Angle = 0.0f;
                parentTransform.Scale = 1.0f;
                transform.Pos         = new Vector3(1.0f, 0.0f, 0.0f);
                transform.Angle       = 0.0f;
                transform.Scale       = 1.0f;

                transform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                transform.TurnBy(MathF.DegToRad(90.0f));
                parentTransform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                DualityApp.Update(true);

                AssertEqual(new Vector3(1.0f, 0.0f, 0.0f), transform.RelativeVel, "Relative child velocity");
                AssertEqual(new Vector3(2.0f, 0.0f, 0.0f), transform.Vel, "Absolute child velocity");
                AssertEqual(MathF.DegToRad(90.0f), transform.RelativeAngleVel, "Relative child angle velocity");
                AssertEqual(MathF.DegToRad(90.0f), transform.AngleVel, "Absolute child angle velocity");

                // ToDo: Fix how Transform adds up velocity due to parent transform
                // rotation in order to make the test cases below work. The current
                // implementation only works with small per-frame rotations, not big,
                // sudden ones.

                // Moving parent and a transformed child
                //parentTransform.Pos = Vector3.Zero;
                //parentTransform.Angle = 0.0f;
                //parentTransform.Scale = 1.0f;
                //transform.Pos = new Vector3(1.0f, 0.0f, 0.0f);
                //transform.Angle = 0.0f;
                //transform.Scale = 1.0f;
                //
                //parentTransform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                //parentTransform.TurnBy(MathF.DegToRad(90.0f));
                //DualityApp.Update(true);
                //
                //AssertEqual(new Vector3(0.0f, 0.0f, 0.0f), transform.RelativeVel, "Relative child velocity");
                //AssertEqual(new Vector3(0.0f, 1.0f, 0.0f), transform.Vel, "Absolute child velocity");
                //AssertEqual(MathF.DegToRad(0.0f), transform.RelativeAngleVel, "Relative child angle velocity");
                //AssertEqual(MathF.DegToRad(90.0f), transform.AngleVel, "Absolute child angle velocity");

                // Moving parent and a transformed, moving child
                //parentTransform.Pos = Vector3.Zero;
                //parentTransform.Angle = 0.0f;
                //parentTransform.Scale = 1.0f;
                //transform.Pos = new Vector3(1.0f, 0.0f, 0.0f);
                //transform.Angle = 0.0f;
                //transform.Scale = 1.0f;
                //
                //transform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                //transform.TurnBy(MathF.DegToRad(90.0f));
                //parentTransform.MoveBy(new Vector3(1.0f, 0.0f, 0.0f));
                //parentTransform.TurnBy(MathF.DegToRad(90.0f));
                //DualityApp.Update(true);
                //
                //AssertEqual(new Vector3(1.0f, 0.0f, 0.0f), transform.RelativeVel, "Relative child velocity");
                //AssertEqual(new Vector3(-1.0f, 3.0f, 0.0f), transform.Vel, "Absolute child velocity");
                //AssertEqual(MathF.DegToRad(90.0f), transform.RelativeAngleVel, "Relative child angle velocity");
                //AssertEqual(MathF.DegToRad(180.0f), transform.AngleVel, "Absolute child angle velocity");
            }
        }