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 HandleUnreferencedTimelinekeys(SpriterDataEntityAnimation animation, SpriterDataEntityAnimationMainline mainline, List<KeyFrame> keyFrameList, IDictionary<int, ScaledSprite> persistentScaledSprites, SpriterObject SpriterObject, IDictionary<string, Texture2D> textures, IDictionary<KeyFrameValues, int> keyFrameValuesParentDictionary, IDictionary<int, SpriterBone> persistentBones, IDictionary<int, ScaledPositionedObject> boneRefDic, IDictionary<string, ObjectInfo> boxes, IDictionary<int, ScaledPolygon> persistentScaledPolygons, IDictionary<int, SpriterPoint> persistentPoints, SpriterDataEntity entity) { foreach (var timeline in animation.Timeline) { foreach (var timelineKey in timeline.Key) { // if timeline key has an object, and no mainline keys for objects reference this key if (timelineKey.Object != null && !mainline.Keys.Where(k => k.ObjectRef != null) .Any(k => k.ObjectRef.Any(r => r.Key == timelineKey.Id && r.Timeline == timeline.Id)) || timelineKey.Bone != null && !mainline.Keys.Where(k => k.BoneRef != null) .Any(k => k.BoneRef.Any(r => r.Key == timelineKey.Id && r.Timeline == timeline.Id))) { int index = keyFrameList.FindLastIndex(kf => Math.Abs(kf.Time - (timelineKey.Time/1000.0f)) < .0001f); if (index > 0) { var keyFrame = new KeyFrame {Time = timelineKey.Time/1000.0f}; var mainlineKey = mainline.Keys.Single(k => k.Time == timelineKey.Time); if (mainlineKey.ObjectRef != null && timelineKey.Object != null) { CreateRuntimeObjectsForSpriterObjectRef(mainlineKey, persistentScaledSprites, SpriterObject, animation, textures, keyFrame, keyFrameValuesParentDictionary, boxes, persistentScaledPolygons, persistentPoints, timelineKeyOverride: timelineKey); } if (mainlineKey.BoneRef != null && timelineKey.Bone != null) { CreateRuntimeObjectsForSpriterBoneRef(mainlineKey, persistentBones, SpriterObject, animation, keyFrame, boneRefDic, keyFrameValuesParentDictionary, entity, timelineKey); } keyFrameList.Insert(index, keyFrame); } } } } }
public SpriterObject Clone() { var so = new SpriterObject(FlatRedBallServices.GlobalContentManager, false) { Animations = new Dictionary<string, SpriterObjectAnimation>() }; var allObjects = Animations.Select(a => a.Value) .SelectMany(v => v.KeyFrames) .SelectMany(kf => kf.Values) .Select(kfv => kfv.Key) .GroupBy(k => k.Name) .Select(g => g.First().Clone<PositionedObject>()) .ToList(); foreach (var animationPair in Animations) { var keyframes = new List<KeyFrame>(); animationPair.Value.KeyFrames.ForEach(kf => { var keyFrame = new KeyFrame { Time = kf.Time, Values = new Dictionary<PositionedObject, KeyFrameValues>(kf.Values.Count) }; foreach (var kfPair in kf.Values) { var parent = kfPair.Value.Parent == null || kfPair.Value.Parent.Name == null ? null : allObjects.First(k => k.Name == kfPair.Value.Parent.Name); var kfv = new KeyFrameValues { Alpha = kfPair.Value.Alpha, Parent = parent, RelativePosition = kfPair.Value.RelativePosition, RelativeRotation = kfPair.Value.RelativeRotation, RelativeScaleX = kfPair.Value.RelativeScaleX, RelativeScaleY = kfPair.Value.RelativeScaleY, Spin = kfPair.Value.Spin, Texture = kfPair.Value.Texture }; keyFrame.Values[allObjects.First(k => k.Name == kfPair.Key.Name)] = kfv; } keyframes.Add(keyFrame); }); so.Animations[animationPair.Key] = new SpriterObjectAnimation(animationPair.Value.Name, animationPair.Value.Looping, animationPair.Value.TotalTime, keyframes); } so.ObjectList = so.Animations.Select(a => a.Value) .SelectMany(v => v.KeyFrames) .SelectMany(kf => kf.Values) .Select(kfv => kfv.Key) .GroupBy(k => k.Name) .Select(g => g.First()) .ToList(); return so; }
private SpriterObject CreateSpriterObjectFromEntity(SpriterDataEntity entity) { var spriterObject = new SpriterObject(FlatRedBallServices.GlobalContentManager, false); IDictionary<string, string> filenames = new Dictionary<string, string>(); IDictionary<int, ScaledSprite> persistentScaledSprites = new Dictionary<int, ScaledSprite>(); IDictionary<int, SpriterBone> persistentBones = new Dictionary<int, SpriterBone>(); IDictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>(); IDictionary<string, ObjectInfo> boxes = new Dictionary<string, ObjectInfo>(); IDictionary<int, ScaledPositionedObject> boneRefDic = new Dictionary<int, ScaledPositionedObject>(); IDictionary<KeyFrameValues, int> keyFrameValuesParentDictionary = new Dictionary<KeyFrameValues, int>(); IDictionary<int, ScaledPolygon> persistentScaledPolygons = new Dictionary<int, ScaledPolygon>(); IDictionary<int, SpriterPoint> persistentPoints = new Dictionary<int, SpriterPoint>(); string oldDir = FileManager.RelativeDirectory; FileManager.RelativeDirectory = this.Directory; foreach (var folder in this.Folder) { foreach (var file in folder.File) { string folderFileId = string.Format("{0}_{1}", folder.Id, file.Id); filenames[folderFileId] = file.Name; textures[folderFileId] = LoadTexture(file); } } FileManager.RelativeDirectory = oldDir; if (entity.ObjectInfos != null) { boxes = entity.ObjectInfos.Where(oi => oi.Type == "box") .ToDictionary(s => s.Name); } foreach (var animation in entity.Animation) { var mainline = animation.Mainline; var keyFrameList = new List<KeyFrame>(); foreach (var key in mainline.Keys) { var keyFrame = new KeyFrame {Time = key.Time/1000.0f}; // If it's a ScaledSprite (not a bone) if (key.ObjectRef != null) { CreateRuntimeObjectsForSpriterObjectRef(key, persistentScaledSprites, spriterObject, animation, textures, keyFrame, keyFrameValuesParentDictionary, boxes, persistentScaledPolygons, persistentPoints); } // If it's a bone (not a ScaledSprite) if (key.BoneRef != null) { CreateRuntimeObjectsForSpriterBoneRef(key, persistentBones, spriterObject, animation, keyFrame, boneRefDic, keyFrameValuesParentDictionary, entity); } keyFrameList.Add(keyFrame); } HandleUnreferencedTimelinekeys(animation, mainline, keyFrameList, persistentScaledSprites, spriterObject, textures, keyFrameValuesParentDictionary, persistentBones, boneRefDic, boxes, persistentScaledPolygons, persistentPoints, entity); // find all the keyframevalues, and look up the bone id, then take that bone id and // set the parent in the keyframevalues variable to the ScaledPositionedObject in the boneRefDic foreach (var pair in keyFrameList.SelectMany(keyFrame => keyFrame.Values)) { if (keyFrameValuesParentDictionary.ContainsKey(pair.Value)) { int boneId = keyFrameValuesParentDictionary[pair.Value]; var parent = boneRefDic[boneId]; pair.Value.Parent = parent; } else if (pair.Key.GetType() != typeof (ScaledSprite) && pair.Key.GetType() != typeof (ScaledPolygon)) { pair.Value.Parent = spriterObject; } } var SpriterObjectAnimation = new SpriterObjectAnimation(animation.Name, animation.Looping, animation.Length/1000.0f, keyFrameList); spriterObject.Animations[animation.Name] = SpriterObjectAnimation; } return spriterObject; }
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; } } }
private static void CreateRuntimeObjectsForSpriterBoneRef(Key key, IDictionary<int, SpriterBone> persistentBones, SpriterObject SpriterObject, SpriterDataEntityAnimation animation, KeyFrame keyFrame, IDictionary<int, ScaledPositionedObject> boneRefDic, IDictionary<KeyFrameValues, int> boneRefParentDic, SpriterDataEntity entity, Key timelineKeyOverride = null) { IDictionary<int, KeyBone> bones = new Dictionary<int, KeyBone>(); foreach (var boneRef in key.BoneRef) { SpriterBone bone; var timeline = animation.Timeline.Single(t => t.Id == boneRef.Timeline); if (persistentBones.ContainsKey(boneRef.Id)) { bone = persistentBones[boneRef.Id]; } else { var objectInfo = entity.ObjectInfos == null ? (ObjectInfo)null : entity.ObjectInfos.FirstOrDefault(o => o.Type == "bone" && o.Name == timeline.Name); bone = new SpriterBone { Name = timeline.Name, Length = objectInfo == null ? 200 : objectInfo.Width }; bone.AttachTo(SpriterObject, true); persistentBones[boneRef.Id] = bone; SpriterObject.ObjectList.Add(bone); } var timelineKey = timelineKeyOverride ?? timeline.Key.Single(k => k.Id == boneRef.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); } var timelineKeyBone = new KeyBone(timelineKey.Bone); bones[boneRef.Id] = timelineKeyBone; keyFrame.Values[bone] = new KeyFrameValues { RelativePosition = new Vector3(timelineKeyBone.X, timelineKeyBone.Y, 0.0f), RelativeRotation = new Vector3(0.0f, 0.0f, timelineKeyBone.Angle), RelativeScaleX = timelineKeyBone.ScaleX, RelativeScaleY = timelineKeyBone.ScaleY, Spin = timelineKey.Spin }; boneRefDic[boneRef.Id] = bone; if (boneRef.Parent.HasValue) { boneRefParentDic[keyFrame.Values[bone]] = boneRef.Parent.Value; } } }
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); }