private GameObject MakeGameObject(Ref childRef, GameObject parent, string spriteFolder) { TimelineKey key = childRef.Referenced; GameObject go = new GameObject(key.Timeline.Name); if (parent != null) { go.transform.parent = parent.transform; } //Any objects that show up only after t=0 begin inactive if (key.Time_Ms > 0) { go.SetActive(false); } var spriteKey = key as SpriteTimelineKey; if (spriteKey != null) { //Set initial sprite information var sprite = go.AddComponent <SpriteRenderer>(); //Hack to be able to animate the sortingOrder property go.AddComponent <SortingOrderUpdate>(); sprite.sprite = AssetUtils.GetSpriteAtPath(spriteKey.File.Name, spriteFolder); } SetTransform(childRef, go.transform); return(go); }
public void SetCurve(Transform root, Transform current, float time, TimelineKey lastTimelineKey, int zIndex = -1) { var path = AnimationUtility.CalculateTransformPath(current, root); var curves = GetOrCreateAnimationCurves(path); UpdateTransformCurve(curves, current, time, lastTimelineKey, zIndex); }
public void DrawBones(SpriterAnimationPlayer player) { SetColor(Color.Red); IEnumerator <Bone> it = player.BoneIterator(); while (it.MoveNext()) { Bone bone = it.Current; TimelineKey key = player.GetKeyFor(bone); if (!key.Active) { continue; } Entity.ObjectInfo info = player.GetObjectInfoFor(bone); Dimension size = info.Size; DrawBone(bone, size); } }
private void LoadTimelineKeys(ContentReader input, Timeline timeline, int count) { for (int id = 0; id < count; id++) { int spin = input.ReadInt32(); int time = input.ReadInt32(); string curveType = input.ReadString(); float[] c = new[] { input.ReadSingle(), input.ReadSingle(), input.ReadSingle(), input.ReadSingle() }; Curve curve = new Curve(); curve.Type = SpriterUtils.GetType(curveType); curve.Constraints.Set(c[0], c[1], c[2], c[3]); TimelineKey key = new TimelineKey(id, time, spin, curve); LoadObjectOrBone(input, key, timeline); } }
private void LoadObjectOrBone(ContentReader input, TimelineKey key, Timeline timeline) { string name = input.ReadString(); Point pivot = new Point(input.ReadSingle(), input.ReadSingle()); Point scale = new Point(input.ReadSingle(), input.ReadSingle()); Point position = new Point(input.ReadSingle(), input.ReadSingle()); float angle = input.ReadSingle(); int folder = -1, file = -1; float alpha = 1f; if (name == "object") { if (timeline.ObjectInfo.Type == Entity.ObjectType.Sprite) { folder = input.ReadInt32(); file = input.ReadInt32(); alpha = input.ReadSingle(); File f = data.GetFolder(folder).GetFile(file); // TODO objectilla voi olla kans pivot, pitäs kirjottaa? pivot = new Point(f.Pivot.X, f.Pivot.Y); timeline.ObjectInfo.Size.Set(f.Size); } } SpriterObject obj; if (name == "bone") { obj = new SpriterObject(position, scale, pivot, angle, alpha, new FileReference(folder, file)); } else { obj = new SpriterObject(position, scale, pivot, angle, alpha, new FileReference(folder, file)); } key.Object = obj; timeline.AddKey(key); }
private void SetGameObjectForRef(GameObject root, Ref childRef, float time) { TimelineKey key = childRef.Referenced; if (time < 0) { time = key.Time; } TimelineKey lastKey; lastKeyframeCache.TryGetValue(key.Timeline, out lastKey); //Get the relative path based on the current hierarchy var relativePath = childRef.RelativePath; //If this is the root, skip it if (string.IsNullOrEmpty(relativePath)) { Debug.Log("Skipping root node in SetGameObjectForRef (SHOULD NEVER HAPPEN)"); return; } //Find the gameObject based on relative path var transform = root.transform.Find(relativePath); if (transform == null) { Debug.LogError("ERROR: Unable to find GameObject at relative path " + relativePath); return; } var gameObject = transform.gameObject; gameObject.SetActive(true); //Get transform data from ref Vector3 localPosition; Vector3 localScale; Vector3 localEulerAngles; childRef.BakeTransforms(out localPosition, out localEulerAngles, out localScale); //Set the current GameObject's transform data transform.localPosition = localPosition; transform.localScale = localScale; //Spin the object in the correct direction var oldEulerAngles = transform.localEulerAngles; if (oldEulerAngles.z - localEulerAngles.z > 180) { localEulerAngles.z += 360; } else if (localEulerAngles.z - oldEulerAngles.z > 180) { localEulerAngles.z -= 360; } /* * switch(childRef.Unmapped.Spin) * { * case SpinDirection.Clockwise: * while (oldEulerAngles.z > localEulerAngles.z) localEulerAngles.z += 360; * break; * case SpinDirection.CounterClockwise: * while (oldEulerAngles.z < localEulerAngles.z) localEulerAngles.z -= 360; * break; * }*/ transform.localEulerAngles = localEulerAngles; int zIndex = -1; var spriteKey = key as SpriteTimelineKey; if (spriteKey != null) { zIndex = ((ObjectRef)childRef).ZIndex; //transform.GetComponent<SpriteRenderer>().sortingOrder = zIndex; } acb.SetCurve(root.transform, transform, time, lastKey, zIndex); //Get last-used game object for this Timeline - needed to clean up reparenting GameObject lastGameObject; if (lastGameObjectCache.TryGetValue(key.Timeline, out lastGameObject) && gameObject != lastGameObject) { //Let Unity handle the global->local position cruft for us lastGameObject.transform.position = transform.position; lastGameObject.transform.eulerAngles = transform.eulerAngles; //TODO: Also need to do something about scale - this is a little more tricky lastGameObject.transform.localScale = localScale; //Deactivate the old object lastGameObject.SetActive(false); acb.SetCurve(root.transform, lastGameObject.transform, time, lastKey); } //Set cached value for last keyframe lastKeyframeCache[key.Timeline] = key; }
public void Update(GameTime p_gameTime) { m_renderList.Clear(); m_boneTransforms.Clear(); m_elapsedTime += p_gameTime.ElapsedGameTime.Milliseconds; if (m_elapsedTime > m_current.Length) { if (AnimationEnded != null) { AnimationEnded(); } if (m_current.Looping) { m_elapsedTime -= m_current.Length; } else { m_elapsedTime = m_current.Length; } } int l_frame = 0; for (int l_i = 0; (l_i < m_current.MainLine.Count); l_i++) { if (m_elapsedTime >= m_current.MainLine[l_i].Time) { l_frame = l_i; } } Vector2 l_flip = new Vector2(m_flipX ? -1.0f : 1.0f, m_flipY ? -1.0f : 1.0f); MainlineKey l_mainline = m_current.MainLine[l_frame]; for (int l_i = 0; l_i < l_mainline.Body.Count; l_i++) { TimelineKey l_key = m_current.TimeLines[l_mainline.Body[l_i].Timeline].Keys[l_mainline.Body[l_i].Key]; // check if file for this object is missing, and if so skip calculating transforms if (m_rect[l_key.Folder][l_key.File].Width == 0) { continue; } RenderMatrix l_render = new RenderMatrix(ApplyBoneTransforms(l_mainline, l_mainline.Body[l_i])); FindMapChar(l_key.Folder, l_key.File, out l_render.Folder, out l_render.File); if (l_render.Folder == -1 || l_render.File == -1) { continue; } l_render.Location = Location + Vector2.Multiply(l_render.Location, l_flip); if (m_flipX) { l_render.Effects |= SpriteEffects.FlipHorizontally; l_render.Pivot.X = m_rect[l_key.Folder][l_render.File].Width - l_render.Pivot.X; } if (m_flipY) { l_render.Effects |= SpriteEffects.FlipVertically; l_render.Pivot.Y = m_rect[l_key.Folder][l_render.File].Height - l_render.Pivot.Y; } if (m_flipX != m_flipY) { l_render.Rotation *= -1.0f; } l_render.ZOrder = l_mainline.Body[l_i].ZOrder; m_renderList.Add(l_render); } }
protected AnimationTransform GetFrameTransition(Reference p_ref) { Timeline l_timeline = m_current.TimeLines[p_ref.Timeline]; // Find the current frame. // The one referenced by mainline is not neccesarily the correct one // I guess the Spriter editor sometimes messes things up // I'm not sure how to reproduce this problem but better safe than sorry? For the reference XSpriter does something similar int l_keyCur = l_timeline.KeyAtOrBefore(m_elapsedTime), l_keyNext = 0; int l_thisTime = m_elapsedTime - l_timeline.Keys[l_keyCur].Time, l_nextTime = 0; // Find the next frame. if ((l_keyCur + 1) < l_timeline.Keys.Count) { l_keyNext = l_keyCur + 1; l_nextTime = l_timeline.Keys[l_keyNext].Time; } else if (m_current.Looping) { // Assume that there is a frame at time = 0 l_keyNext = 0; l_nextTime = m_current.Length; } else { l_keyNext = l_keyCur; l_nextTime = m_current.Length; } // Figure out where we are in the timeline... l_nextTime = l_nextTime - l_timeline.Keys[l_keyCur].Time; TimelineKey l_now = l_timeline.Keys[l_keyCur], l_next = l_timeline.Keys[l_keyNext]; float l_timeRatio = MathHelper.Clamp((float)l_thisTime / (float)l_nextTime, 0.0f, 1.0f); /// Tween EVERYTHING... Gonna have to add an option for it not to... /// Rotations are handled differently depending on which way they're supposed to spin AnimationTransform l_render = new AnimationTransform(); float l_angleA = l_now.Rotation, l_angleB = l_next.Rotation; if (l_now.Spin == SpinDirection.None) { l_angleA = l_angleB = l_now.Rotation; } else if (l_now.Spin == SpinDirection.Clockwise) { if ((l_angleB - l_angleA) < 0.0f) { l_angleB += MathHelper.TwoPi; } else { l_angleA %= MathHelper.TwoPi; l_angleB %= MathHelper.TwoPi; } } else if (l_now.Spin == SpinDirection.CounterClockwise) { if ((l_angleB - l_angleA) > 0.0f) { l_angleB -= MathHelper.TwoPi; } else { l_angleA %= MathHelper.TwoPi; l_angleB %= MathHelper.TwoPi; } } l_render.Rotation = MathHelper.Lerp(l_angleA, l_angleB, l_timeRatio); l_render.Scale = Vector2.Lerp(l_now.Scale, l_next.Scale, l_timeRatio); l_render.Location = Vector2.Lerp(l_now.Location, l_next.Location, l_timeRatio); l_render.Pivot = Vector2.Lerp(l_now.Pivot, l_next.Pivot, l_timeRatio); l_render.Alpha = MathHelper.Lerp(l_now.Alpha, l_next.Alpha, l_timeRatio); // So, how far are we between frames? return(l_render); }
protected override CharacterModel Read(ContentReader p_input, CharacterModel p_character) { p_character = new CharacterModel(); Int32 l_textureCount = p_input.ReadInt32();///Number of Textures for (int l_tIter = 0; l_tIter < l_textureCount; l_tIter++) { Texture2D l_texture = p_input.ReadRawObject <Texture2D>(); p_character.Textures.Add(l_texture); } Int32 l_rectCount1 = p_input.ReadInt32();///Number of RectangleLists for (int l_rIter1 = 0; l_rIter1 < l_rectCount1; l_rIter1++) { List <Rectangle> l_list = new List <Rectangle>(); Int32 l_rectCount2 = p_input.ReadInt32();///Number of Rectangles in that list for (int l_rIter2 = 0; l_rIter2 < l_rectCount2; l_rIter2++) { l_list.Add(p_input.ReadRawObject <Rectangle>()); } p_character.Rectangles.Add(l_list); } /// ------------------- Entities ------------------------------- Int32 l_entityCount = p_input.ReadInt32();///Number of Entities for (int l_eIter = 0; l_eIter < l_entityCount; l_eIter++) { Entity l_entity = new Entity(); l_entity.Name = p_input.ReadString();///Name /// ------------------- Animations ------------------------------- Int32 l_animationCount = p_input.ReadInt32();///Number of Animations for (int l_aIter = 0; l_aIter < l_animationCount; l_aIter++) { Animation l_animation = new Animation(); l_animation.Name = p_input.ReadString(); ///Name l_animation.Length = p_input.ReadInt32(); //length l_animation.Looping = p_input.ReadBoolean(); //looping l_animation.MainLine = new List <MainlineKey>(); l_animation.TimeLines = new TimelineList(); /// ------------------- Mainline ------------------------------- Int32 l_keyCount = p_input.ReadInt32();///Number of Keyframes for (int l_kIter = 0; l_kIter < l_keyCount; l_kIter++) { MainlineKey l_key = new MainlineKey(); l_key.Time = p_input.ReadInt32();///Time l_key.Body = new List <Reference>(); l_key.Bones = new List <Reference>(); /// ------------------- Object_refs ------------------------------- Int32 l_objectCount = p_input.ReadInt32();///Number of Objects for (int l_oIter = 0; l_oIter < l_objectCount; l_oIter++) { Reference l_body = new Reference(); l_body.Parent = p_input.ReadInt32(); //parent l_body.Timeline = p_input.ReadInt32(); //timeline l_body.Key = p_input.ReadInt32(); //key l_body.ZOrder = p_input.ReadInt32(); //z_index l_body.BoneId = -1; l_key.Body.Add(l_body); } /// ------------------- bone_ref ------------------------------- Int32 l_boneCount = p_input.ReadInt32();///Number of Objects for (int l_bIter = 0; l_bIter < l_boneCount; l_bIter++) { Reference l_bone = new Reference(); l_bone.Parent = p_input.ReadInt32(); //parent l_bone.Timeline = p_input.ReadInt32(); //timeline l_bone.Key = p_input.ReadInt32(); //key l_bone.BoneId = l_bIter; l_key.Bones.Add(l_bone); } l_animation.MainLine.Add(l_key); } /// ------------------- Timelines ------------------------------- Int32 l_timelineCount = p_input.ReadInt32();///Number of Timelines for (int l_tIter = 0; l_tIter < l_timelineCount; l_tIter++) { Timeline l_timeline = new Timeline(); l_timeline.Keys = new List <TimelineKey>(); l_timeline.Name = p_input.ReadString();///Name /// ------------------- Frame ------------------------------- l_keyCount = p_input.ReadInt32();///Number of Keyframes for (int l_kIter = 0; l_kIter < l_keyCount; l_kIter++) { TimelineKey l_key = new TimelineKey(); l_key.Time = p_input.ReadInt32(); //time int l_spin = p_input.ReadInt32(); //spin if (l_spin == 0) { l_key.Spin = SpinDirection.None; } else if (l_spin == 1) { l_key.Spin = SpinDirection.CounterClockwise; } else if (l_spin == -1) { l_key.Spin = SpinDirection.Clockwise; } l_key.Type = (TimelineType)p_input.ReadInt32();//type if (l_key.Type == TimelineType.Body) { l_key.Folder = p_input.ReadInt32(); //folder l_key.File = p_input.ReadInt32(); //file // Sprite Location (Spriter saves the rotations backwards.) float l_locationX = p_input.ReadSingle(), l_locationY = p_input.ReadSingle();//location l_key.Location = new Vector2(l_locationX, -l_locationY); // Sprite Pivot Point (Spriter saves the "Y" backwards. We need to flip it.) float l_pivotX = p_input.ReadSingle(), l_pivotY = p_input.ReadSingle();//pivot l_key.Pivot = new Vector2(l_pivotX * p_character.Rectangles[l_key.Folder][l_key.File].Width, (1.0f - l_pivotY) * p_character.Rectangles[l_key.Folder][l_key.File].Height); l_key.Rotation = -MathHelper.ToRadians(p_input.ReadSingle()); //rotation float l_scaleX = p_input.ReadSingle(), l_scaleY = p_input.ReadSingle(); //scale l_key.Scale = new Vector2(l_scaleX, l_scaleY); l_key.Alpha = p_input.ReadSingle();//alpha } else { l_key.Folder = l_key.File = -1; //File & folder are useless. float l_locationX = p_input.ReadSingle(), l_locationY = p_input.ReadSingle(); //location l_key.Location = new Vector2(l_locationX, -l_locationY); float l_pivotX = p_input.ReadSingle(), l_pivotY = p_input.ReadSingle();//pivot l_key.Pivot = new Vector2(l_pivotX, l_pivotY); // Rotation (Spriter saves the rotations backwards. l_key.Rotation = -MathHelper.ToRadians(p_input.ReadSingle()); //rotation float l_scaleX = p_input.ReadSingle(), l_scaleY = p_input.ReadSingle(); //scale l_key.Scale = new Vector2(l_scaleX, l_scaleY); l_key.Alpha = 1.0f; // Useless alpha } l_timeline.Keys.Add(l_key); } l_animation.TimeLines.Add(l_timeline); } l_entity.Add(l_animation); } p_character.Add(l_entity); } p_character.CharacterMaps = p_input.ReadObject <List <CharacterMap> >(); return(p_character); }
private void UpdateTransformCurve(ObjectCurves obj, Transform current, float time, TimelineKey lastTimelineKey, int zIndex = -1) { float val; //IsActive curve val = (current.gameObject.activeSelf) ? 1.0f : 0.0f; obj.Curves[(int)AnimationCurveIndex.IsActive].AddKey(new Keyframe(time, val, float.PositiveInfinity, float.PositiveInfinity) { tangentMode = 0 }); //Position curves obj.Curves[(int)AnimationCurveIndex.LocalPositionX].AddKey(new Keyframe(time, current.localPosition.x) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.LocalPositionY].AddKey(new Keyframe(time, current.localPosition.y) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.LocalPositionZ].AddKey(new Keyframe(time, current.localPosition.z, float.PositiveInfinity, float.PositiveInfinity)); //Z value always has instant transition //Rotation curves var quat = Quaternion.Euler(current.localEulerAngles); obj.Curves[(int)AnimationCurveIndex.LocalRotationX].AddKey(new Keyframe(time, quat.x) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.LocalRotationY].AddKey(new Keyframe(time, quat.y) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.LocalRotationZ].AddKey(new Keyframe(time, quat.z) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.LocalRotationW].AddKey(new Keyframe(time, quat.w) { tangentMode = 0 }, lastTimelineKey); //Scale curves obj.Curves[(int)AnimationCurveIndex.LocalScaleX].AddKey(new Keyframe(time, current.localScale.x) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.LocalScaleY].AddKey(new Keyframe(time, current.localScale.y) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.LocalScaleZ].AddKey(new Keyframe(time, current.localScale.z) { tangentMode = 0 }, lastTimelineKey); //Sprite Curves var spriteTimelineKey = lastTimelineKey as SpriteTimelineKey; if (spriteTimelineKey != null) { obj.IsSpriteKey = true; obj.Curves[(int)AnimationCurveIndex.ColorR].AddKey(new Keyframe(time, spriteTimelineKey.Tint.r) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.ColorG].AddKey(new Keyframe(time, spriteTimelineKey.Tint.g) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.ColorB].AddKey(new Keyframe(time, spriteTimelineKey.Tint.b) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.ColorA].AddKey(new Keyframe(time, spriteTimelineKey.Tint.a) { tangentMode = 0 }, lastTimelineKey); obj.Curves[(int)AnimationCurveIndex.ZIndex].AddKey(new Keyframe(time, zIndex, float.PositiveInfinity, float.PositiveInfinity)); } }
public virtual void Update(GameTime p_gameTime) { m_renderList.Clear(); m_boneTransforms.Clear(); m_elapsedTime += p_gameTime.ElapsedGameTime.Milliseconds; if (m_elapsedTime > m_current.Length) { // pitää ottaa talteen että nähdään vaihtaako eventti animaatiota Animation current = m_current; if (AnimationEnded != null) { AnimationEnded(m_current); } // jos animaatioi vaihtui niin alotetaan taas aika nollasta if (!Equals(current, m_current)) { m_elapsedTime = 0; } else if (m_current.Looping) { m_elapsedTime -= m_current.Length; } else { m_elapsedTime = m_current.Length; } } int l_frame = 0; for (int l_i = 0; (l_i < m_current.MainLine.Count); l_i++) { if (m_elapsedTime >= m_current.MainLine[l_i].Time) { l_frame = l_i; } } Vector2 l_flip = new Vector2(m_flipX ? -1.0f : 1.0f, m_flipY ? -1.0f : 1.0f); MainlineKey l_mainline = m_current.MainLine[l_frame]; for (int l_i = 0; l_i < l_mainline.Body.Count; l_i++) { TimelineKey l_key = m_current.TimeLines[l_mainline.Body[l_i].Timeline].Keys[l_mainline.Body[l_i].Key]; // check if file for this object is missing, and if so skip calculating transforms if (m_rect[l_key.Folder][l_key.File].Width == 0) { continue; } RenderMatrix l_render = new RenderMatrix(ApplyBoneTransforms(l_mainline, l_mainline.Body[l_i])); l_render.File = l_key.File; l_render.Folder = l_key.Folder; l_render.Location = Location + Vector2.Multiply(l_render.Location, l_flip); if (m_flipX) { l_render.Effects |= SpriteEffects.FlipHorizontally; l_render.Pivot.X = m_rect[l_key.Folder][l_render.File].Width - l_render.Pivot.X; } if (m_flipY) { l_render.Effects |= SpriteEffects.FlipVertically; l_render.Pivot.Y = m_rect[l_key.Folder][l_render.File].Height - l_render.Pivot.Y; } if (m_flipX != m_flipY) { l_render.Rotation *= -1.0f; } l_render.ZOrder = l_mainline.Body[l_i].ZOrder; m_renderList.Add(l_render); } }
private TimelineKey ParseTimelineKey(CharacterModel model, XElement xTimelineKey, Dictionary <int, Dictionary <int, Vector2> > defaultPivots) { TimelineKey key = new TimelineKey(); key.Time = ReadInt(xTimelineKey, "time", 0); // alkaa alusta default int spin = ReadInt(xTimelineKey, "spin", 1); // counter clock switch (spin) { case 0: key.Spin = SpinDirection.None; break; case 1: key.Spin = SpinDirection.CounterClockwise; break; case -1: key.Spin = SpinDirection.Clockwise; break; } if (xTimelineKey.Descendants("object").Count() > 0) { var xObject = xTimelineKey.Element("object"); key.Type = TimelineType.Body; key.Folder = Convert.ToInt32(xObject.Attribute("folder").Value); key.File = Convert.ToInt32(xObject.Attribute("file").Value); float locationX = ReadFloat(xObject, "x", 0); // x 0 float locationY = ReadFloat(xObject, "y", 0); // y 0 key.Location = new Vector2(locationX, -locationY); float pivotX = ReadFloat(xObject, "pivot_x", 0); if (pivotX == 0) { pivotX = defaultPivots[key.Folder][key.File].X; } float pivotY = ReadFloat(xObject, "pivot_y", 1); if (pivotY == 1) { pivotY = defaultPivots[key.Folder][key.File].Y;//ReadFloat(xObject, "pivot_x", 1); // pivot_y 1 } key.Pivot = new Vector2( pivotX * model.Rectangles[key.Folder][key.File].Width, (1.0f - pivotY) * model.Rectangles[key.Folder][key.File].Height ); key.Rotation = -MathHelper.ToRadians(ReadFloat(xObject, "angle", 0)); // kulma 0 float scaleX = ReadFloat(xObject, "scale_x", 1); // scale x 1 float scaleY = ReadFloat(xObject, "scale_y", 1); // scale y 1 key.Scale = new Vector2(scaleX, scaleY); float alpha = ReadFloat(xObject, "a", 1); // alpha 1 key.Alpha = alpha; } else { var xBone = xTimelineKey.Element("bone"); key.Type = TimelineType.Bone; key.Folder = key.File = -1; key.Alpha = 1f; float locationX = ReadFloat(xBone, "x", 0); // x 0 float locationY = ReadFloat(xBone, "y", 0); // y 0 key.Location = new Vector2(locationX, -locationY); float pivotX = ReadFloat(xBone, "pivot_x", 0); // pivot_x 0 float pivotY = ReadFloat(xBone, "pivot_y", 1); // pivot_y 1 key.Pivot = new Vector2( pivotX, pivotY ); key.Rotation = -MathHelper.ToRadians(ReadFloat(xBone, "angle", 0)); // kulma 0 float scaleX = ReadFloat(xBone, "scale_x", 1); // scale x 1 float scaleY = ReadFloat(xBone, "scale_y", 1); // scale y 1 key.Scale = new Vector2(scaleX, scaleY); } return(key); }