Inheritance: FlatRedBall.PositionedObject, IRelativeScalable
        public void RelativeRotationScaledPositionTest()
        {
            var parent1 = new ScaledPositionedObject
            {
                Position = new Vector3(100f, 100f, 100f)
            };

            var parent2 = new ScaledPositionedObject
            {
                RelativeScaleX = .5f,
                Position = new Vector3(100f, 100f, 100f)
            };

            var spo = new ScaledPositionedObject();
            parent2.AttachTo(parent1, true);
            spo.AttachTo(parent2, true);

            spo.RelativePosition = new Vector3(10f, 10f, 0f);
            parent2.RelativeRotationZ = MathHelper.ToRadians(90f);
            parent1.RotationZ += MathHelper.ToRadians(90f);

            spo.UpdateDependencies(1);

            var rotationZ = MathHelper.ToDegrees(spo.RotationZ);
            Assert.IsTrue(Math.Abs(rotationZ - 180f) < .0001f);
            Assert.IsTrue(Math.Abs(spo.Position.X - 95f) < .0001f);
            Assert.IsTrue(Math.Abs(spo.Position.Y - 90f) < .0001f);
        }
        public void ChangingScale()
        {
            var parent = new ScaledPositionedObject { ScaleX = .5f, ScaleY = .5f };
            var polygon = new ScaledPolygon
            {
                X = 10,
                Y = 10,
                Points = new List<Point>
                {
                    new Point(0, 0),
                    new Point(32, 0),
                    new Point(32, 32),
                    new Point(0, 32),
                    new Point(0, 0)
                }
            };

            polygon.AttachTo(parent, true);

            polygon.UpdateDependencies(1.0);
            polygon.RelativeScaleX = .5f;
            polygon.RelativeScaleY = .5f;
            polygon.UpdateDependencies(2.0);

            Assert.IsTrue(Math.Abs(polygon.Points[0].X) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Points[1].X - 8f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Points[2].X - 8f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Points[3].X) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Points[4].X) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Points[0].Y) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Points[1].Y) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Points[2].Y - 8f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Points[3].Y - 8f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Points[4].Y) < Single.Epsilon);
        }
        public void RelativePositionAffectedByParentScale()
        {
            var spo = new ScaledPositionedObject { Position = new Vector3(100, 200, 300) };
            var parent = new ScaledPositionedObject();

            spo.AttachTo(parent, true);

            parent.ScaleX = .5f;
            parent.ScaleY = .5f;
            parent.ScaleZ = .5f;

            spo.UpdateDependencies(0);

            Assert.IsTrue(Math.Abs(spo.Position.X - 50f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(spo.Position.Y - 100f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(spo.Position.Z - 150f) < Single.Epsilon);
        }
        public void ParentScaleAffectsSpriteScale()
        {
            var spo = new ScaledPositionedObject
            {
                ScaleX = .5f,
                ScaleY = .25f
            };

            var sprite = new ScaledSprite
            {
                RelativeScaleX = .5f,
                RelativeScaleY = 1.0f
            };

            sprite.AttachTo(spo, true);

            sprite.UpdateDependencies(0);

            Assert.IsTrue(Math.Abs(sprite.Width - .25f * ScaledSprite.DefaultTextureWidth) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(sprite.Height - .25f * ScaledSprite.DefaultTextureHeight) < Single.Epsilon);
        }
        public void RelativeScalingDoesNotBreakPositioning()
        {
            var parent = new ScaledPositionedObject
            {
                Position = new Vector3
                {
                    X = 100f,
                    Y = 200f,
                    Z = 300f
                },
                ScaleX = .5f,
                ScaleY = .5f,
                ScaleZ = .5f
            };

            var spo = new ScaledPositionedObject();
            spo.AttachTo(parent, true);
            spo.RelativePosition = new Vector3(10f, 20f, 30f);

            spo.UpdateDependencies(0);

            Assert.IsTrue(Math.Abs(spo.Position.X - 105f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(spo.Position.Y - 210f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(spo.Position.Z - 315f) < Single.Epsilon);
        }
        public void ScaledRotationPositionOffOrigin()
        {
            var parent = new ScaledPositionedObject
            {
                Position = new Vector3(100f, 100f, 100f),
                ScaleX = .5f,
                ScaleY = 1.0f,
                ScaleZ = 1f
            };

            var spo = new ScaledPositionedObject();
            spo.AttachTo(parent, true);
            spo.RelativePosition = new Vector3(10f, 0f, 0f);

            parent.RotationZ += MathHelper.ToRadians(90f);

            spo.UpdateDependencies(0);

            Assert.IsTrue(Math.Abs(spo.Position.X - 105f) >= Single.Epsilon);
            Assert.IsTrue(Math.Abs(spo.Position.Y - 105f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(spo.Position.Z - 100f) < Single.Epsilon);
        }
 public void ScaleDefaultsTo1()
 {
     var spo = new ScaledPositionedObject();
     Assert.AreEqual(1.0f, spo.ScaleX);
     Assert.AreEqual(1.0f, spo.ScaleY);
     Assert.AreEqual(1.0f, spo.ScaleZ);
     Assert.AreEqual(1.0f, spo.RelativeScaleX);
     Assert.AreEqual(1.0f, spo.RelativeScaleY);
     Assert.AreEqual(1.0f, spo.RelativeScaleZ);
 }
        private static SpriterObject GetSimpleSpriterObject(bool loops = false)
        {
            var so = new SpriterObject("Global", false);

            var sprite = new ScaledSprite();
            var pivot = new ScaledPositionedObject();
            pivot.AttachTo(so, true);
            sprite.AttachTo(pivot, true);
            sprite.Name = "sprite";
            pivot.Name = "pivot";

            so.Animations.Add("", new SpriterObjectAnimation("", loops, 2.0f, new List<KeyFrame>()));

            // first keyframe (0ms)
            var keyFrame = new KeyFrame
            {
                Time = 0
            };

            // The pivot is at 30,30
            keyFrame.Values[pivot] = new KeyFrameValues
            {
                RelativePosition = new Vector3(30f, 30f, 0f)
            };
            // Sprite is just there to connect to the pivot
            keyFrame.Values[sprite] = new KeyFrameValues
            {
                Alpha = 1.0f,
                Parent = pivot,
                RelativeScaleX = 1.0f,
                RelativeScaleY = 1.0f
            };

            so.Animations[""].KeyFrames.Add(keyFrame);

            keyFrame = new KeyFrame
            {
                Time = 1.0f
            };
            keyFrame.Values[pivot] = new KeyFrameValues
            {
                RelativePosition = Vector3.Zero
            };

            keyFrame.Values[sprite] = new KeyFrameValues
            {
                Alpha = 1.0f,
                Parent = pivot,
                RelativeScaleX = 1.0f,
                RelativeScaleY = 1.0f,
                RelativePosition = Vector3.Zero
            };

            so.Animations[""].KeyFrames.Add(keyFrame);

            so.ObjectList.Add(sprite);
            so.ObjectList.Add(pivot);

            //so.AddToManagers(null);
            return so;
        }
        private void CreateRuntimeObjectsForSpriterObjectRef(Key key, IDictionary<int, ScaledSprite> persistentScaledSprites, SpriterObject SpriterObject, SpriterDataEntityAnimation animation, IDictionary<string, Texture2D> textures, KeyFrame keyFrame, IDictionary<KeyFrameValues, int> SpriterefParentDic, IDictionary<string, ObjectInfo> boxes, IDictionary<int, ScaledPolygon> persistentScaledPolygons, IDictionary<int, SpriterPoint> persistentPoints, Key timelineKeyOverride = null)
        {
            foreach (var objectRef in key.ObjectRef)
            {
                var timeline = animation.Timeline.Single(t => t.Id == objectRef.Timeline);
                Key timelineKey = timelineKeyOverride ?? timeline.Key.Single(k => k.Id == objectRef.Key);
                if (timelineKeyOverride == null && key.Time != timelineKey.Time)
                {
                    var nextTimelineKey = timeline.Key.FirstOrDefault(k => k.Time > key.Time) ??
                                          new Key(timeline.Key.First()) { Time = animation.Length };

                    timelineKey = InterpolateToNewTimelineKey(key, timelineKey, nextTimelineKey);
                }

                if (timeline.ObjectType == "box")
                {
                    ScaledPolygon scaledPolygon;
                    ScaledPositionedObject pivot;
                    var box = boxes[timeline.Name];

                    if (persistentScaledPolygons.ContainsKey(objectRef.Id))
                    {
                        scaledPolygon = persistentScaledPolygons[objectRef.Id];
                        pivot = (ScaledPositionedObject)scaledPolygon.Parent;
                    }
                    else
                    {
                        scaledPolygon = ScaledPolygon.CreateRectangle(timelineKey.Object.X, timelineKey.Object.Y, (int)box.Width, (int)box.Height);
                        scaledPolygon.ParentScaleChangesPosition = false;
                        scaledPolygon.Visible = false;

                        var name = objectRef.Name ?? objectRef.Id.ToString(CultureInfo.InvariantCulture);
                        pivot = new ScaledPositionedObject { Name = string.Format("{0}_pivot", name) };

                        scaledPolygon.Name = timeline.Name;

                        scaledPolygon.AttachTo(pivot, true);
                        pivot.AttachTo(SpriterObject, true);

                        persistentScaledPolygons[objectRef.Id] = scaledPolygon;
                        SpriterObject.ObjectList.Add(scaledPolygon);
                        SpriterObject.ObjectList.Add(pivot);
                    }

                    var values = GetKeyFrameValues(timelineKey, box, objectRef);

                    values.ScaledPolygon.Parent = pivot;
                    if (objectRef.Parent.HasValue)
                    {
                        SpriterefParentDic[values.Pivot] = objectRef.Parent.Value;
                    }
                    else
                    {
                        values.Pivot.Parent = SpriterObject;
                    }

                    keyFrame.Values[pivot] = values.Pivot;
                    keyFrame.Values[scaledPolygon] = values.ScaledPolygon;
                }
                else if (timeline.ObjectType == "point")
                {
                    SpriterPoint point;

                    if (persistentPoints.ContainsKey(objectRef.Id))
                    {
                        point = persistentPoints[objectRef.Id];
                    }
                    else
                    {
                        point = new SpriterPoint
                        {
                            X = timelineKey.Object.X,
                            Y = timelineKey.Object.Y,
                            Name = timeline.Name
                        };
                        SpriterObject.ObjectList.Add(point);
                        persistentPoints[objectRef.Id] = point;
                    }

                    KeyFrameValues values = GetKeyFrameValuesForPoint(timelineKey, objectRef);

                    if (objectRef.Parent.HasValue)
                    {
                        SpriterefParentDic[values] = objectRef.Parent.Value;
                    }
                    else
                    {
                        values.Parent = SpriterObject;
                    }

                    keyFrame.Values[point] = values;
                }
                else if (string.IsNullOrEmpty(timeline.ObjectType))
                {
                    var folderFileId = string.Format("{0}_{1}", timelineKey.Object.Folder,
                        timelineKey.Object.File);
                    var file =
                        this.Folder.First(f => f.Id == timelineKey.Object.Folder)
                            .File.First(f => f.Id == timelineKey.Object.File);

                    ScaledSprite scaledSprite;
                    ScaledPositionedObject pivot;
                    if (persistentScaledSprites.ContainsKey(objectRef.Id))
                    {
                        scaledSprite = persistentScaledSprites[objectRef.Id];
                        pivot = (ScaledPositionedObject) scaledSprite.Parent;
                    }
                    else
                    {
                        var name = objectRef.Name ?? objectRef.Id.ToString(CultureInfo.InvariantCulture);
                        pivot = new ScaledPositionedObject {Name = string.Format("{0}_pivot", name)};

                        scaledSprite = new ScaledSprite
                        {
                            Name = string.Format("{0}_sprite", name),
                            Width = file.Width,
                            Height = file.Height,
                            ParentScaleChangesPosition = false
                        };

                        scaledSprite.AttachTo(pivot, true);
                        pivot.AttachTo(SpriterObject, true);

                        persistentScaledSprites[objectRef.Id] = scaledSprite;
                        SpriterObject.ObjectList.Add(scaledSprite);
                        SpriterObject.ObjectList.Add(pivot);
                    }

                    var values = GetKeyFrameValues(timelineKey, file, textures, folderFileId, objectRef);

                    values.ScaledSprite.Parent = pivot;
                    if (objectRef.Parent.HasValue)
                    {
                        SpriterefParentDic[values.Pivot] = objectRef.Parent.Value;
                    }
                    else
                    {
                        values.Pivot.Parent = SpriterObject;
                    }

                    keyFrame.Values[pivot] = values.Pivot;
                    keyFrame.Values[scaledSprite] = values.ScaledSprite;
                }
            }
        }
        public void ParentScaleAffectsPosition()
        {
            var parent = new ScaledPositionedObject { ScaleX = .5f, ScaleY = .5f };
            var polygon = new ScaledPolygon
            {
                X = 10,
                Y = 15,
                Points = new List<Point>
                {
                    new Point(0, 0),
                    new Point(32, 0),
                    new Point(32, 32),
                    new Point(0, 32),
                    new Point(0, 0)
                }
            };

            polygon.AttachTo(parent, true);

            polygon.UpdateDependencies(1.0);
            polygon.UpdateDependencies(2.0);

            Assert.IsTrue(Math.Abs(polygon.X - 5f) < Single.Epsilon);
            Assert.IsTrue(Math.Abs(polygon.Y - 7.5f) < Single.Epsilon);
        }
        public void Test2Objects()
        {
            var so = new SpriterObject("Global", false);

            var sprite = new ScaledSprite();
            var pivot = new ScaledPositionedObject();
            var sprite2 = new ScaledSprite();
            var pivot2 = new ScaledPositionedObject();

            pivot.AttachTo(so, true);
            sprite.AttachTo(pivot, true);

            pivot2.AttachTo(so, true);
            sprite2.AttachTo(pivot2, true);
            so.Animations.Add("", new SpriterObjectAnimation("", true, 2.0f, new List<KeyFrame>()));

            var keyFrame = new KeyFrame
            {
                Time = 0
            };
            keyFrame.Values[pivot] = new KeyFrameValues
            {
                RelativePosition = Vector3.Zero
            };
            keyFrame.Values[pivot2] = new KeyFrameValues
            {
                RelativePosition = Vector3.Zero
            };

            so.Animations[""].KeyFrames.Add(keyFrame);

            keyFrame = new KeyFrame
            {
                Time = 1.0f
            };
            keyFrame.Values[pivot] = new KeyFrameValues
            {
                RelativePosition = new Vector3(0f, 10f, 0f)
            };
            keyFrame.Values[pivot2] = new KeyFrameValues
            {
                RelativePosition = new Vector3(10f, 0f, 0f)
            };

            so.Animations[""].KeyFrames.Add(keyFrame);

            so.ObjectList.Add(sprite);
            so.ObjectList.Add(pivot);
            so.ObjectList.Add(sprite2);
            so.ObjectList.Add(pivot2);

            so.StartAnimation();
            TimeManager.CurrentTime += .5;
            so.TimedActivity(.5f, 0f, 0f);

            Assert.AreEqual(5f, so.ObjectList[1].Position.Y);
            Assert.AreEqual(5f, so.ObjectList[3].Position.X);

            TimeManager.CurrentTime += .25;
            so.TimedActivity(.25f, 0f, 0f);
            Assert.AreEqual(7.5f, so.ObjectList[1].Position.Y);
            Assert.AreEqual(7.5f, so.ObjectList[3].Position.X);
        }
        public void BoneReparenting()
        {
            var so = new SpriterObject("Global", false);
            var bone1 = new ScaledPositionedObject();
            var bone2 = new ScaledPositionedObject();

            so.Animations.Add("", new SpriterObjectAnimation("", false, 2.0f, new List<KeyFrame>()));

            var keyFrame = new KeyFrame
            {
                Time = 0f
            };

            keyFrame.Values[bone1] = new KeyFrameValues
            {
                Parent = so
            };

            keyFrame.Values[bone2] = new KeyFrameValues { Parent = bone1 };
            so.Animations[""].KeyFrames.Add(keyFrame);

            keyFrame = new KeyFrame
            {
                Time = 1.0f
            };

            keyFrame.Values[bone1] = new KeyFrameValues { RelativePosition = new Vector3(100f, 0f, 0f), Parent = so };
            keyFrame.Values[bone2] = new KeyFrameValues
            {
                Parent = so
            };

            so.Animations[""].KeyFrames.Add(keyFrame);

            so.ObjectList.Add(bone1);
            so.ObjectList.Add(bone2);

            so.StartAnimation();

            so.TimedActivity(.5f, 0f, 0f);
            Assert.AreSame(so.ObjectList[0], so.ObjectList[1].Parent);
            Assert.AreSame(so, so.ObjectList[0].Parent);

            so.TimedActivity(.5f, 0f, 0f);
            Assert.AreSame(so, so.ObjectList[1].Parent);
            Assert.AreSame(so, so.ObjectList[0].Parent);
        }