From 2e7e871c07e4f6f91f567de18314f02f96409c19 Mon Sep 17 00:00:00 2001 From: Luigi Rosso Date: Sun, 14 Jan 2018 14:46:43 -0800 Subject: [PATCH] Adding Translation, Scale, Rotation, and Transform constraints. --- Actor.cs | 16 +++ ActorAxisConstraint.cs | 113 ++++++++++++++++++ ActorRotationConstraint.cs | 214 ++++++++++++++++++++++++++++++++++ ActorScaleConstraint.cs | 162 +++++++++++++++++++++++++ ActorTransformConstraint.cs | 117 +++++++++++++++++++ ActorTranslationConstraint.cs | 137 ++++++++++++++++++++++ Animation/ActorAnimation.cs | 4 +- Animation/KeyFrame.cs | 15 ++- Animation/PropertyTypes.cs | 2 +- TransformSpace.cs | 8 ++ 10 files changed, 780 insertions(+), 8 deletions(-) create mode 100644 ActorAxisConstraint.cs create mode 100644 ActorRotationConstraint.cs create mode 100644 ActorScaleConstraint.cs create mode 100644 ActorTransformConstraint.cs create mode 100644 ActorTranslationConstraint.cs create mode 100644 TransformSpace.cs diff --git a/Actor.cs b/Actor.cs index 5168820..22aa432 100644 --- a/Actor.cs +++ b/Actor.cs @@ -399,6 +399,22 @@ private void ReadComponentsBlock(BlockReader block) case BlockTypes.ActorDistanceConstraint: component = ActorDistanceConstraint.Read(this, nodeBlock); break; + + case BlockTypes.ActorTranslationConstraint: + component = ActorTranslationConstraint.Read(this, nodeBlock); + break; + + case BlockTypes.ActorScaleConstraint: + component = ActorScaleConstraint.Read(this, nodeBlock); + break; + + case BlockTypes.ActorRotationConstraint: + component = ActorRotationConstraint.Read(this, nodeBlock); + break; + + case BlockTypes.ActorTransformConstraint: + component = ActorTransformConstraint.Read(this, nodeBlock); + break; } } if(component is ActorNode) diff --git a/ActorAxisConstraint.cs b/ActorAxisConstraint.cs new file mode 100644 index 0000000..550ab9a --- /dev/null +++ b/ActorAxisConstraint.cs @@ -0,0 +1,113 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Nima.Math2D; + +namespace Nima +{ + public abstract class ActorAxisConstraint : ActorTargetedConstraint + { + protected bool m_CopyX; + protected bool m_CopyY; + protected float m_ScaleX; + protected float m_ScaleY; + protected bool m_EnableMinX; + protected bool m_EnableMinY; + protected bool m_EnableMaxX; + protected bool m_EnableMaxY; + protected float m_MaxX; + protected float m_MaxY; + protected float m_MinX; + protected float m_MinY; + protected bool m_Offset; + protected TransformSpace m_SourceSpace; + protected TransformSpace m_DestSpace; + protected TransformSpace m_MinMaxSpace; + + public ActorAxisConstraint() + { + m_CopyX = false; + m_CopyY = false; + m_ScaleX = 1.0f; + m_ScaleY = 1.0f; + m_EnableMinX = false; + m_EnableMinY = false; + m_EnableMaxX = false; + m_EnableMaxY = false; + m_MinX = 0.0f; + m_MinY = 0.0f; + m_MaxX = 0.0f; + m_MaxY = 0.0f; + m_Offset = false; + m_SourceSpace = TransformSpace.World; + m_DestSpace = TransformSpace.World; + m_MinMaxSpace = TransformSpace.World; + } + + public override void OnDirty(byte dirt) + { + MarkDirty(); + } + + public static ActorAxisConstraint Read(Actor actor, BinaryReader reader, ActorAxisConstraint component) + { + ActorTargetedConstraint.Read(actor, reader, component); + + if((component.m_CopyX = reader.ReadByte() == 1)) + { + component.m_ScaleX = reader.ReadSingle(); + } + if((component.m_EnableMinX = reader.ReadByte() == 1)) + { + component.m_MinX = reader.ReadSingle(); + } + if((component.m_EnableMaxX = reader.ReadByte() == 1)) + { + component.m_MaxX = reader.ReadSingle(); + } + + // Y Axis + if((component.m_CopyY = reader.ReadByte() == 1)) + { + component.m_ScaleY = reader.ReadSingle(); + } + if((component.m_EnableMinY = reader.ReadByte() == 1)) + { + component.m_MinY = reader.ReadSingle(); + } + if((component.m_EnableMaxY = reader.ReadByte() == 1)) + { + component.m_MaxY = reader.ReadSingle(); + } + + component.m_Offset = reader.ReadByte() == 1; + component.m_SourceSpace = (TransformSpace)reader.ReadByte(); + component.m_DestSpace = (TransformSpace)reader.ReadByte(); + component.m_MinMaxSpace = (TransformSpace)reader.ReadByte(); + + return component; + } + + public void Copy(ActorAxisConstraint node, Actor resetActor) + { + base.Copy(node, resetActor); + + m_CopyX = node.m_CopyX; + m_CopyY = node.m_CopyY; + m_ScaleX = node.m_ScaleX; + m_ScaleY = node.m_ScaleY; + m_EnableMinX = node.m_EnableMinX; + m_EnableMinY = node.m_EnableMinY; + m_EnableMaxX = node.m_EnableMaxX; + m_EnableMaxY = node.m_EnableMaxY; + m_MinX = node.m_MinX; + m_MinY = node.m_MinY; + m_MaxX = node.m_MaxX; + m_MaxY = node.m_MaxY; + m_Offset = node.m_Offset; + m_SourceSpace = node.m_SourceSpace; + m_DestSpace = node.m_DestSpace; + m_MinMaxSpace = node.m_MinMaxSpace; + } + } +} \ No newline at end of file diff --git a/ActorRotationConstraint.cs b/ActorRotationConstraint.cs new file mode 100644 index 0000000..96bdcd2 --- /dev/null +++ b/ActorRotationConstraint.cs @@ -0,0 +1,214 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Nima.Math2D; + +namespace Nima +{ + public class ActorRotationConstraint : ActorTargetedConstraint + { + const float PI2 = (float)(Math.PI*2.0); + + protected bool m_Copy; + protected float m_Scale; + protected bool m_EnableMin; + protected bool m_EnableMax; + protected float m_Max; + protected float m_Min; + protected bool m_Offset; + protected TransformSpace m_SourceSpace; + protected TransformSpace m_DestSpace; + protected TransformSpace m_MinMaxSpace; + TransformComponents m_ComponentsA; + TransformComponents m_ComponentsB; + + public ActorRotationConstraint() + { + m_Copy = false; + m_Scale = 1.0f; + m_EnableMin = false; + m_EnableMax = false; + m_Min = 0.0f; + m_Max = 0.0f; + m_Offset = false; + m_SourceSpace = TransformSpace.World; + m_DestSpace = TransformSpace.World; + m_MinMaxSpace = TransformSpace.World; + m_ComponentsA = new TransformComponents(); + m_ComponentsB = new TransformComponents(); + } + + public override void OnDirty(byte dirt) + { + MarkDirty(); + } + + public static ActorRotationConstraint Read(Actor actor, BinaryReader reader, ActorRotationConstraint component = null) + { + if(component == null) + { + component = new ActorRotationConstraint(); + } + ActorTargetedConstraint.Read(actor, reader, component); + + if((component.m_Copy = reader.ReadByte() == 1)) + { + component.m_Scale = reader.ReadSingle(); + } + if((component.m_EnableMin = reader.ReadByte() == 1)) + { + component.m_Min = reader.ReadSingle(); + } + if((component.m_EnableMax = reader.ReadByte() == 1)) + { + component.m_Max = reader.ReadSingle(); + } + + component.m_Offset = reader.ReadByte() == 1; + component.m_SourceSpace = (TransformSpace)reader.ReadByte(); + component.m_DestSpace = (TransformSpace)reader.ReadByte(); + component.m_MinMaxSpace = (TransformSpace)reader.ReadByte(); + + return component; + } + + public void Copy(ActorRotationConstraint node, Actor resetActor) + { + base.Copy(node, resetActor); + + m_Copy = node.m_Copy; + m_Scale = node.m_Scale; + m_EnableMin = node.m_EnableMin; + m_EnableMax = node.m_EnableMax; + m_Min = node.m_Min; + m_Max = node.m_Max; + + m_Offset = node.m_Offset; + m_SourceSpace = node.m_SourceSpace; + m_DestSpace = node.m_DestSpace; + m_MinMaxSpace = node.m_MinMaxSpace; + } + + public override void Constrain(ActorNode node) + { + ActorNode target = m_Target as ActorNode; + ActorNode grandParent = m_Parent.Parent; + + Mat2D transformA = m_Parent.WorldTransform; + Mat2D transformB = new Mat2D(); + Mat2D.Decompose(transformA, m_ComponentsA); + if(target == null) + { + Mat2D.Copy(transformB, transformA); + m_ComponentsB[0] = m_ComponentsA[0]; + m_ComponentsB[1] = m_ComponentsA[1]; + m_ComponentsB[2] = m_ComponentsA[2]; + m_ComponentsB[3] = m_ComponentsA[3]; + m_ComponentsB[4] = m_ComponentsA[4]; + m_ComponentsB[5] = m_ComponentsA[5]; + } + else + { + Mat2D.Copy(transformB, target.WorldTransform); + if(m_SourceSpace == TransformSpace.Local) + { + ActorNode sourceGrandParent = target.Parent; + if(sourceGrandParent != null) + { + Mat2D inverse = new Mat2D(); + if(!Mat2D.Invert(inverse, sourceGrandParent.WorldTransform)) + { + return; + } + Mat2D.Multiply(transformB, inverse, transformB); + } + } + Mat2D.Decompose(transformB, m_ComponentsB); + + if(!m_Copy) + { + m_ComponentsB.Rotation = m_DestSpace == TransformSpace.Local ? 1.0f : m_ComponentsA.Rotation; + } + else + { + m_ComponentsB.Rotation *= m_Scale; + if(m_Offset) + { + m_ComponentsB.Rotation += m_Parent.Rotation; + } + } + + if(m_DestSpace == TransformSpace.Local) + { + // Destination space is in parent transform coordinates. + // Recompose the parent local transform and get it in world, then decompose the world for interpolation. + if(grandParent != null) + { + Mat2D.Compose(transformB, m_ComponentsB); + Mat2D.Multiply(transformB, grandParent.WorldTransform, transformB); + Mat2D.Decompose(transformB, m_ComponentsB); + } + } + } + + bool clampLocal = m_MinMaxSpace == TransformSpace.Local && grandParent != null; + if(clampLocal) + { + // Apply min max in local space, so transform to local coordinates first. + Mat2D.Compose(transformB, m_ComponentsB); + Mat2D inverse = new Mat2D(); + if(!Mat2D.Invert(inverse, grandParent.WorldTransform)) + { + return; + } + Mat2D.Multiply(transformB, inverse, transformB); + Mat2D.Decompose(transformB, m_ComponentsB); + } + if(m_EnableMax && m_ComponentsB.Rotation > m_Max) + { + m_ComponentsB.Rotation = m_Max; + } + if(m_EnableMin && m_ComponentsB.Rotation < m_Min) + { + m_ComponentsB.Rotation = m_Min; + } + if(clampLocal) + { + // Transform back to world. + Mat2D.Compose(transformB, m_ComponentsB); + Mat2D.Multiply(transformB, grandParent.WorldTransform, transformB); + Mat2D.Decompose(transformB, m_ComponentsB); + } + + float angleA = m_ComponentsA.Rotation%PI2; + float angleB = m_ComponentsB.Rotation%PI2; + float diff = angleB - angleA; + + if(diff > Math.PI) + { + diff -= PI2; + } + else if(diff < -Math.PI) + { + diff += PI2; + } + float ti = 1.0f-m_Strength; + + m_ComponentsB.Rotation = m_ComponentsA.Rotation + diff * m_Strength; + m_ComponentsB.X = m_ComponentsA.X; + m_ComponentsB.Y = m_ComponentsA.Y; + m_ComponentsB.ScaleX = m_ComponentsA.ScaleX; + m_ComponentsB.ScaleY = m_ComponentsA.ScaleY; + m_ComponentsB.Skew = m_ComponentsA.Skew; + + Mat2D.Compose(m_Parent.WorldTransform, m_ComponentsB); + } + + public override ActorComponent MakeInstance(Actor resetActor) + { + ActorRotationConstraint instance = new ActorRotationConstraint(); + instance.Copy(this, resetActor); + return instance; + } + } +} \ No newline at end of file diff --git a/ActorScaleConstraint.cs b/ActorScaleConstraint.cs new file mode 100644 index 0000000..22cc1c8 --- /dev/null +++ b/ActorScaleConstraint.cs @@ -0,0 +1,162 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Nima.Math2D; + +namespace Nima +{ + public class ActorScaleConstraint : ActorAxisConstraint + { + TransformComponents m_ComponentsA; + TransformComponents m_ComponentsB; + + ActorScaleConstraint() + { + m_ComponentsA = new TransformComponents(); + m_ComponentsB = new TransformComponents(); + } + + public static ActorScaleConstraint Read(Actor actor, BinaryReader reader, ActorScaleConstraint component = null) + { + if(component == null) + { + component = new ActorScaleConstraint(); + } + ActorAxisConstraint.Read(actor, reader, component); + + return component; + } + + public override void Constrain(ActorNode node) + { + ActorNode target = m_Target as ActorNode; + ActorNode grandParent = m_Parent.Parent; + + Mat2D transformA = m_Parent.WorldTransform; + Mat2D transformB = new Mat2D(); + Mat2D.Decompose(transformA, m_ComponentsA); + if(target == null) + { + Mat2D.Copy(transformB, transformA); + m_ComponentsB[0] = m_ComponentsA[0]; + m_ComponentsB[1] = m_ComponentsA[1]; + m_ComponentsB[2] = m_ComponentsA[2]; + m_ComponentsB[3] = m_ComponentsA[3]; + m_ComponentsB[4] = m_ComponentsA[4]; + m_ComponentsB[5] = m_ComponentsA[5]; + } + else + { + Mat2D.Copy(transformB, target.WorldTransform); + if(m_SourceSpace == TransformSpace.Local) + { + ActorNode sourceGrandParent = target.Parent; + if(sourceGrandParent != null) + { + Mat2D inverse = new Mat2D(); + if(!Mat2D.Invert(inverse, sourceGrandParent.WorldTransform)) + { + return; + } + Mat2D.Multiply(transformB, inverse, transformB); + } + } + Mat2D.Decompose(transformB, m_ComponentsB); + + if(!m_CopyX) + { + m_ComponentsB[2] = m_DestSpace == TransformSpace.Local ? 1.0f : m_ComponentsA[2]; + } + else + { + m_ComponentsB[2] *= m_ScaleX; + if(m_Offset) + { + m_ComponentsB[2] *= m_Parent.ScaleX; + } + } + + if(!m_CopyY) + { + m_ComponentsB[3] = m_DestSpace == TransformSpace.Local ? 0.0f : m_ComponentsA[3]; + } + else + { + m_ComponentsB[3] *= m_ScaleY; + + if(m_Offset) + { + m_ComponentsB[3] *= m_Parent.ScaleY; + } + } + + if(m_DestSpace == TransformSpace.Local) + { + // Destination space is in parent transform coordinates. + // Recompose the parent local transform and get it in world, then decompose the world for interpolation. + if(grandParent != null) + { + Mat2D.Compose(transformB, m_ComponentsB); + Mat2D.Multiply(transformB, grandParent.WorldTransform, transformB); + Mat2D.Decompose(transformB, m_ComponentsB); + } + } + } + + bool clampLocal = m_MinMaxSpace == TransformSpace.Local && grandParent != null; + if(clampLocal) + { + // Apply min max in local space, so transform to local coordinates first. + Mat2D.Compose(transformB, m_ComponentsB); + Mat2D inverse = new Mat2D(); + if(!Mat2D.Invert(inverse, grandParent.WorldTransform)) + { + return; + } + Mat2D.Multiply(transformB, inverse, transformB); + Mat2D.Decompose(transformB, m_ComponentsB); + } + if(m_EnableMaxX && m_ComponentsB.ScaleX > m_MaxX) + { + m_ComponentsB.ScaleX = m_MaxX; + } + if(m_EnableMinX && m_ComponentsB.ScaleX < m_MinX) + { + m_ComponentsB.ScaleX = m_MinX; + } + if(m_EnableMaxY && m_ComponentsB.ScaleY > m_MaxY) + { + m_ComponentsB.ScaleY = m_MaxY; + } + if(m_EnableMinY && m_ComponentsB.ScaleY < m_MinY) + { + m_ComponentsB.ScaleY = m_MinY; + } + if(clampLocal) + { + // Transform back to world. + Mat2D.Compose(transformB, m_ComponentsB); + Mat2D.Multiply(transformB, grandParent.WorldTransform, transformB); + Mat2D.Decompose(transformB, m_ComponentsB); + } + + float ti = 1.0f-m_Strength; + + m_ComponentsB.Rotation = m_ComponentsA.Rotation; + m_ComponentsB.X = m_ComponentsA.X; + m_ComponentsB.Y = m_ComponentsA.Y; + m_ComponentsB.ScaleX = m_ComponentsA.ScaleX * ti + m_ComponentsB.ScaleX * m_Strength; + m_ComponentsB.ScaleY = m_ComponentsA.ScaleY * ti + m_ComponentsB.ScaleY * m_Strength; + m_ComponentsB.Skew = m_ComponentsA.Skew; + + Mat2D.Compose(m_Parent.WorldTransform, m_ComponentsB); + } + + public override ActorComponent MakeInstance(Actor resetActor) + { + ActorScaleConstraint instance = new ActorScaleConstraint(); + instance.Copy(this, resetActor); + return instance; + } + } +} \ No newline at end of file diff --git a/ActorTransformConstraint.cs b/ActorTransformConstraint.cs new file mode 100644 index 0000000..c4dcffb --- /dev/null +++ b/ActorTransformConstraint.cs @@ -0,0 +1,117 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Nima.Math2D; + +namespace Nima +{ + public class ActorTransformConstraint : ActorTargetedConstraint + { + const float PI2 = (float)(Math.PI*2.0); + + protected TransformSpace m_SourceSpace; + protected TransformSpace m_DestSpace; + TransformComponents m_ComponentsA; + TransformComponents m_ComponentsB; + + public ActorTransformConstraint() + { + m_SourceSpace = TransformSpace.World; + m_DestSpace = TransformSpace.World; + m_ComponentsA = new TransformComponents(); + m_ComponentsB = new TransformComponents(); + } + + public override void OnDirty(byte dirt) + { + MarkDirty(); + } + + public static ActorTransformConstraint Read(Actor actor, BinaryReader reader, ActorTransformConstraint component = null) + { + if(component == null) + { + component = new ActorTransformConstraint(); + } + ActorTargetedConstraint.Read(actor, reader, component); + + component.m_SourceSpace = (TransformSpace)reader.ReadByte(); + component.m_DestSpace = (TransformSpace)reader.ReadByte(); + + return component; + } + + public void Copy(ActorTransformConstraint node, Actor resetActor) + { + base.Copy(node, resetActor); + + m_SourceSpace = node.m_SourceSpace; + m_DestSpace = node.m_DestSpace; + } + + public override void Constrain(ActorNode node) + { + ActorNode target = m_Target as ActorNode; + if(target == null) + { + return; + } + + Mat2D transformA = m_Parent.WorldTransform; + Mat2D transformB = new Mat2D(target.WorldTransform); + if(m_SourceSpace == TransformSpace.Local) + { + ActorNode grandParent = target.Parent; + if(grandParent != null) + { + Mat2D inverse = new Mat2D(); + if(!Mat2D.Invert(inverse, grandParent.WorldTransform)) + { + return; + } + Mat2D.Multiply(transformB, inverse, transformB); + } + } + if(m_DestSpace == TransformSpace.Local) + { + ActorNode grandParent = m_Parent.Parent; + if(grandParent != null) + { + Mat2D.Multiply(transformB, grandParent.WorldTransform, transformB); + } + } + Mat2D.Decompose(transformA, m_ComponentsA); + Mat2D.Decompose(transformB, m_ComponentsB); + + float angleA = m_ComponentsA.Rotation%PI2; + float angleB = m_ComponentsB.Rotation%PI2; + float diff = angleB - angleA; + if(diff > Math.PI) + { + diff -= PI2; + } + else if(diff < -Math.PI) + { + diff += PI2; + } + + float ti = 1.0f-m_Strength; + + m_ComponentsB.Rotation = angleA + diff * m_Strength; + m_ComponentsB.X = m_ComponentsA.X * ti + m_ComponentsB.X * m_Strength; + m_ComponentsB.Y = m_ComponentsA.Y * ti + m_ComponentsB.Y * m_Strength; + m_ComponentsB.ScaleX = m_ComponentsA.ScaleX * ti + m_ComponentsB.ScaleX * m_Strength; + m_ComponentsB.ScaleY = m_ComponentsA.ScaleY * ti + m_ComponentsB.ScaleY * m_Strength; + m_ComponentsB.Skew = m_ComponentsA.Skew * ti + m_ComponentsB.Skew * m_Strength; + + Mat2D.Compose(m_Parent.WorldTransform, m_ComponentsB); + } + + public override ActorComponent MakeInstance(Actor resetActor) + { + ActorTransformConstraint instance = new ActorTransformConstraint(); + instance.Copy(this, resetActor); + return instance; + } + } +} \ No newline at end of file diff --git a/ActorTranslationConstraint.cs b/ActorTranslationConstraint.cs new file mode 100644 index 0000000..bd45134 --- /dev/null +++ b/ActorTranslationConstraint.cs @@ -0,0 +1,137 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Nima.Math2D; + +namespace Nima +{ + public class ActorTranslationConstraint : ActorAxisConstraint + { + public static ActorTranslationConstraint Read(Actor actor, BinaryReader reader, ActorTranslationConstraint component = null) + { + if(component == null) + { + component = new ActorTranslationConstraint(); + } + ActorAxisConstraint.Read(actor, reader, component); + + return component; + } + + public override void Constrain(ActorNode node) + { + ActorNode target = m_Target as ActorNode; + ActorNode grandParent = m_Parent.Parent; + + Mat2D transformA = m_Parent.WorldTransform; + Vec2D translationA = new Vec2D(transformA[4], transformA[5]); + Vec2D translationB = new Vec2D(); + if(target == null) + { + Vec2D.Copy(translationB, translationA); + } + else + { + Mat2D transformB = new Mat2D(target.WorldTransform); + if(m_SourceSpace == TransformSpace.Local) + { + ActorNode sourceGrandParent = target.Parent; + if(sourceGrandParent != null) + { + Mat2D inverse = new Mat2D(); + if(!Mat2D.Invert(inverse, sourceGrandParent.WorldTransform)) + { + return; + } + Mat2D.Multiply(transformB, inverse, transformB); + } + } + translationB[0] = transformB[4]; + translationB[1] = transformB[5]; + + if(!m_CopyX) + { + translationB[0] = m_DestSpace == TransformSpace.Local ? 0.0f : translationA[0]; + } + else + { + translationB[0] *= m_ScaleX; + if(m_Offset) + { + translationB[0] += m_Parent.X; + } + } + + if(!m_CopyY) + { + translationB[1] = m_DestSpace == TransformSpace.Local ? 0.0f : translationA[1]; + } + else + { + translationB[1] *= m_ScaleY; + + if(m_Offset) + { + translationB[1] += m_Parent.Y; + } + } + + if(m_DestSpace == TransformSpace.Local) + { + // Destination space is in parent transform coordinates. + if(grandParent != null) + { + Vec2D.TransformMat2D(translationB, translationB, grandParent.WorldTransform); + } + } + } + + bool clampLocal = m_MinMaxSpace == TransformSpace.Local && grandParent != null; + if(clampLocal) + { + // Apply min max in local space, so transform to local coordinates first. + Mat2D invert = new Mat2D(); + if(!Mat2D.Invert(invert, grandParent.WorldTransform)) + { + return; + } + // Get our target world coordinates in parent local. + Vec2D.TransformMat2D(translationB, translationB, invert); + } + if(m_EnableMaxX && translationB[0] > m_MaxX) + { + translationB[0] = m_MaxX; + } + if(m_EnableMinX && translationB[0] < m_MinX) + { + translationB[0] = m_MinX; + } + if(m_EnableMaxY && translationB[1] > m_MaxY) + { + translationB[1] = m_MaxY; + } + if(m_EnableMinY && translationB[1] < m_MinY) + { + translationB[1] = m_MinY; + } + if(clampLocal) + { + // Transform back to world. + Vec2D.TransformMat2D(translationB, translationB, grandParent.WorldTransform); + } + + float ti = 1.0f-m_Strength; + + // Just interpolate world translation + transformA[4] = translationA[0] * ti + translationB[0] * m_Strength; + transformA[5] = translationA[1] * ti + translationB[1] * m_Strength; + } + + public override ActorComponent MakeInstance(Actor resetActor) + { + ActorTranslationConstraint instance = new ActorTranslationConstraint(); + instance.Copy(this, resetActor); + return instance; + } + } +} \ No newline at end of file diff --git a/Animation/ActorAnimation.cs b/Animation/ActorAnimation.cs index 62f0900..2989e41 100644 --- a/Animation/ActorAnimation.cs +++ b/Animation/ActorAnimation.cs @@ -75,8 +75,8 @@ public static PropertyAnimation Read(BlockReader reader, ActorComponent componen case PropertyTypes.VertexDeform: keyFrameReader = KeyFrameVertexDeform.Read; break; - case PropertyTypes.IKStrength: - keyFrameReader = KeyFrameIKStrength.Read; + case PropertyTypes.ConstraintStrength: + keyFrameReader = KeyFrameConstraintStrength.Read; break; case PropertyTypes.Trigger: keyFrameReader = KeyFrameTrigger.Read; diff --git a/Animation/KeyFrame.cs b/Animation/KeyFrame.cs index e005647..52b8b0a 100644 --- a/Animation/KeyFrame.cs +++ b/Animation/KeyFrame.cs @@ -519,11 +519,11 @@ protected override void SetValue(ActorComponent component, float value, float mi } } - public class KeyFrameIKStrength : KeyFrameNumeric + public class KeyFrameConstraintStrength : KeyFrameNumeric { public static KeyFrame Read(BinaryReader reader, ActorComponent component) { - KeyFrameIKStrength frame = new KeyFrameIKStrength(); + KeyFrameConstraintStrength frame = new KeyFrameConstraintStrength(); if(KeyFrameNumeric.Read(reader, frame)) { return frame; @@ -533,12 +533,17 @@ public static KeyFrame Read(BinaryReader reader, ActorComponent component) protected override void SetValue(ActorComponent component, float value, float mix) { - ActorIKTarget target = component as ActorIKTarget; - if(target == null) + ActorConstraint constraint = component as ActorConstraint; + if(constraint != null) { + constraint.Strength = constraint.Strength * (1.0f - mix) + value * mix; return; } - target.Strength = target.Strength * (1.0f - mix) + value * mix; + ActorIKTarget target = component as ActorIKTarget; + if(target != null) + { + target.Strength = target.Strength * (1.0f - mix) + value * mix; + } } } diff --git a/Animation/PropertyTypes.cs b/Animation/PropertyTypes.cs index 4427734..f1edf73 100644 --- a/Animation/PropertyTypes.cs +++ b/Animation/PropertyTypes.cs @@ -14,7 +14,7 @@ public enum PropertyTypes DrawOrder = 7, Length = 8, VertexDeform = 9, - IKStrength = 10, + ConstraintStrength = 10, Trigger = 11, IntProperty = 12, FloatProperty = 13, diff --git a/TransformSpace.cs b/TransformSpace.cs new file mode 100644 index 0000000..4e6d726 --- /dev/null +++ b/TransformSpace.cs @@ -0,0 +1,8 @@ +namespace Nima +{ + public enum TransformSpace + { + Local = 0, + World = 1 + } +} \ No newline at end of file