Exemple #1
0
        public override void CompleteResolve()
        {
            base.CompleteResolve();

            ActorBone bone = m_Parent as ActorBone;

            bone.m_Jelly = this;

            // Get jellies.
            IList <ActorNode> children = bone.Children;

            if (children == null)
            {
                return;
            }

            m_Bones = new List <ActorJellyBone>();
            foreach (ActorNode child in children)
            {
                if (child is ActorJellyBone)
                {
                    m_Bones.Add(child as ActorJellyBone);
                }
            }
        }
Exemple #2
0
        public override ActorComponent MakeInstance(Actor resetActor)
        {
            ActorBone instanceNode = new ActorBone();

            instanceNode.Copy(this, resetActor);
            return(instanceNode);
        }
Exemple #3
0
        public static ActorBone Read(Actor actor, BinaryReader reader, ActorBone node = null)
        {
            if (node == null)
            {
                node = new ActorBone();
            }

            ActorBoneBase.Read(actor, reader, node);
            return(node);
        }
Exemple #4
0
        private void UpdateJellies()
        {
            if (m_Bones == null)
            {
                return;
            }
            ActorBone bone = m_Parent as ActorBone;
            // We are in local bone space.
            Vec2D tipPosition = new Vec2D(bone.Length, 0.0f);

            if (FuzzyEquals(m_CachedTip, tipPosition) && FuzzyEquals(m_CachedOut, m_OutPoint) && FuzzyEquals(m_CachedIn, m_InPoint) && m_CachedScaleIn == m_ScaleIn && m_CachedScaleOut == m_ScaleOut)
            {
                return;
            }

            Vec2D.Copy(m_CachedTip, tipPosition);
            Vec2D.Copy(m_CachedOut, m_OutPoint);
            Vec2D.Copy(m_CachedIn, m_InPoint);
            m_CachedScaleIn  = m_ScaleIn;
            m_CachedScaleOut = m_ScaleOut;

            Vec2D q0 = new Vec2D();
            Vec2D q1 = m_InPoint;
            Vec2D q2 = m_OutPoint;
            Vec2D q3 = tipPosition;

            ForwardDiffBezier(q0[0], q1[0], q2[0], q3[0], m_JellyPoints, JellyMax, 0);
            ForwardDiffBezier(q0[1], q1[1], q2[1], q3[1], m_JellyPoints, JellyMax, 1);

            IList <Vec2D> normalizedPoints = NormalizeCurve(m_JellyPoints, m_Bones.Count);

            Vec2D lastPoint = m_JellyPoints[0];

            float scale    = m_ScaleIn;
            float scaleInc = (m_ScaleOut - m_ScaleIn) / (m_Bones.Count - 1);

            for (int i = 0; i < normalizedPoints.Count; i++)
            {
                ActorJellyBone jelly = m_Bones[i];
                Vec2D          p     = normalizedPoints[i];

                jelly.Translation = lastPoint;
                jelly.Length      = Vec2D.Distance(p, lastPoint);
                jelly.ScaleY      = scale;
                scale            += scaleInc;

                Vec2D diff = Vec2D.Subtract(new Vec2D(), p, lastPoint);
                jelly.Rotation = (float)Math.Atan2(diff[1], diff[0]);
                lastPoint      = p;
            }
        }
Exemple #5
0
 public override void CompleteResolve()
 {
     base.CompleteResolve();
     if (m_Children == null)
     {
         return;
     }
     foreach (ActorNode node in m_Children)
     {
         if (node is ActorBone)
         {
             m_FirstBone = node as ActorBone;
             return;
         }
     }
 }
Exemple #6
0
        void ConstrainRotation(BoneChain fk, float rotation)
        {
            ActorBone           bone        = fk.m_Bone;
            Mat2D               parentWorld = bone.Parent.WorldTransform;
            Mat2D               transform   = bone.Transform;
            TransformComponents c           = fk.m_TransformComponents;

            if (rotation == 0.0f)
            {
                Mat2D.Identity(transform);
            }
            else
            {
                Mat2D.FromRotation(transform, rotation);
            }
            // Translate
            transform[4] = c.X;
            transform[5] = c.Y;
            // Scale
            float scaleX = c.ScaleX;
            float scaleY = c.ScaleY;

            transform[0] *= scaleX;
            transform[1] *= scaleX;
            transform[2] *= scaleY;
            transform[3] *= scaleY;
            // Skew
            float skew = c.Skew;

            if (skew != 0.0)
            {
                transform[2] = transform[0] * skew + transform[2];
                transform[3] = transform[1] * skew + transform[3];
            }

            Mat2D.Multiply(bone.WorldTransform, parentWorld, transform);
        }
Exemple #7
0
        private void ReadComponentsBlock(BlockReader block)
        {
            int componentCount = block.ReadUInt16();

            m_Components    = new ActorComponent[componentCount + 1];
            m_Components[0] = m_Root;

            // Guaranteed from the exporter to be in index order.
            BlockReader nodeBlock = null;

            int componentIndex = 1;

            m_NodeCount = 1;
            while ((nodeBlock = block.ReadNextBlock()) != null)
            {
                ActorComponent component = null;
                if (Enum.IsDefined(typeof(BlockTypes), nodeBlock.BlockType))
                {
                    BlockTypes type = (BlockTypes)nodeBlock.BlockType;
                    switch (type)
                    {
                    case BlockTypes.ActorNode:
                        component = ActorNode.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorBone:
                        component = ActorBone.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorRootBone:
                        component = ActorRootBone.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorImage:
                        m_ImageNodeCount++;
                        component = ActorImage.Read(this, nodeBlock, makeImageNode());
                        if ((component as ActorImage).TextureIndex > m_MaxTextureIndex)
                        {
                            m_MaxTextureIndex = (component as ActorImage).TextureIndex;
                        }
                        break;

                    case BlockTypes.ActorIKTarget:
                        component = ActorIKTarget.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorEvent:
                        component = ActorEvent.Read(this, nodeBlock);
                        break;

                    case BlockTypes.CustomIntProperty:
                        component = CustomIntProperty.Read(this, nodeBlock);
                        break;

                    case BlockTypes.CustomFloatProperty:
                        component = CustomFloatProperty.Read(this, nodeBlock);
                        break;

                    case BlockTypes.CustomStringProperty:
                        component = CustomStringProperty.Read(this, nodeBlock);
                        break;

                    case BlockTypes.CustomBooleanProperty:
                        component = CustomBooleanProperty.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorColliderRectangle:
                        component = ActorColliderRectangle.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorColliderTriangle:
                        component = ActorColliderTriangle.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorColliderCircle:
                        component = ActorColliderCircle.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorColliderPolygon:
                        component = ActorColliderPolygon.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorColliderLine:
                        component = ActorColliderLine.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorNodeSolo:
                        component = ActorNodeSolo.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorJellyBone:
                        component = ActorJellyBone.Read(this, nodeBlock);
                        break;

                    case BlockTypes.JellyComponent:
                        component = JellyComponent.Read(this, nodeBlock);
                        break;

                    case BlockTypes.ActorIKConstraint:
                        component = ActorIKConstraint.Read(this, nodeBlock);
                        break;

                    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)
                {
                    m_NodeCount++;
                }

                m_Components[componentIndex] = component;
                if (component != null)
                {
                    component.Idx = (ushort)(componentIndex);
                }
                componentIndex++;
            }

            m_ImageNodes = new ActorImage[m_ImageNodeCount];
            m_Nodes      = new ActorNode[m_NodeCount];
            m_Nodes[0]   = m_Root;

            // Resolve nodes.
            int imgIdx = 0;
            int anIdx  = 0;

            ActorComponent[] components = m_Components;
            for (int i = 1; i <= componentCount; i++)
            {
                ActorComponent c = components[i];
                // Nodes can be null if we read from a file version that contained nodes that we don't interpret in this runtime.
                if (c != null)
                {
                    c.ResolveComponentIndices(components);
                }

                ActorImage ain = c as ActorImage;
                if (ain != null)
                {
                    m_ImageNodes[imgIdx++] = ain;
                }

                ActorNode an = c as ActorNode;
                if (an != null)
                {
                    m_Nodes[anIdx++] = an;
                }
            }

            for (int i = 1; i <= componentCount; i++)
            {
                ActorComponent c = components[i];
                if (c != null)
                {
                    c.CompleteResolve();
                }
            }

            SortDependencies();
        }
Exemple #8
0
        public override void Update(byte dirt)
        {
            ActorBone      bone            = m_Parent as ActorBone;
            ActorBone      parentBone      = bone.Parent as ActorBone;
            JellyComponent parentBoneJelly = parentBone == null ? null : parentBone.m_Jelly;

            Mat2D inverseWorld = new Mat2D();

            if (!Mat2D.Invert(inverseWorld, bone.WorldTransform))
            {
                return;
            }

            if (m_InTarget != null)
            {
                Vec2D translation = m_InTarget.GetWorldTranslation(new Vec2D());
                Vec2D.TransformMat2D(m_InPoint, translation, inverseWorld);
                Vec2D.Normalize(m_InDirection, m_InPoint);
            }
            else if (parentBone != null)
            {
                if (parentBone.FirstBone == bone && parentBoneJelly != null && parentBoneJelly.m_OutTarget != null)
                {
                    Vec2D translation    = parentBoneJelly.m_OutTarget.GetWorldTranslation(new Vec2D());
                    Vec2D localParentOut = Vec2D.TransformMat2D(new Vec2D(), translation, inverseWorld);
                    Vec2D.Normalize(localParentOut, localParentOut);
                    Vec2D.Negate(m_InDirection, localParentOut);
                }
                else
                {
                    Vec2D d1 = new Vec2D(1.0f, 0.0f);
                    Vec2D d2 = new Vec2D(1.0f, 0.0f);

                    Vec2D.TransformMat2(d1, d1, parentBone.WorldTransform);
                    Vec2D.TransformMat2(d2, d2, bone.WorldTransform);

                    Vec2D sum = Vec2D.Add(new Vec2D(), d1, d2);
                    Vec2D.TransformMat2(m_InDirection, sum, inverseWorld);
                    Vec2D.Normalize(m_InDirection, m_InDirection);
                }
                m_InPoint[0] = m_InDirection[0] * m_EaseIn * bone.Length * CurveConstant;
                m_InPoint[1] = m_InDirection[1] * m_EaseIn * bone.Length * CurveConstant;
            }
            else
            {
                m_InDirection[0] = 1.0f;
                m_InDirection[1] = 0.0f;
                m_InPoint[0]     = m_InDirection[0] * m_EaseIn * bone.Length * CurveConstant;
            }

            if (m_OutTarget != null)
            {
                Vec2D translation = m_OutTarget.GetWorldTranslation(new Vec2D());
                Vec2D.TransformMat2D(m_OutPoint, translation, inverseWorld);
                Vec2D tip = new Vec2D(bone.Length, 0.0f);
                Vec2D.Subtract(m_OutDirection, m_OutPoint, tip);
                Vec2D.Normalize(m_OutDirection, m_OutDirection);
            }
            else if (bone.FirstBone != null)
            {
                ActorBone      firstBone      = bone.FirstBone;
                JellyComponent firstBoneJelly = firstBone.m_Jelly;
                if (firstBoneJelly != null && firstBoneJelly.m_InTarget != null)
                {
                    Vec2D translation     = firstBoneJelly.m_InTarget.GetWorldTranslation(new Vec2D());
                    Vec2D worldChildInDir = Vec2D.Subtract(new Vec2D(), firstBone.GetWorldTranslation(new Vec2D()), translation);
                    Vec2D.TransformMat2(m_OutDirection, worldChildInDir, inverseWorld);
                }
                else
                {
                    Vec2D d1 = new Vec2D(1.0f, 0.0f);
                    Vec2D d2 = new Vec2D(1.0f, 0.0f);

                    Vec2D.TransformMat2(d1, d1, firstBone.WorldTransform);
                    Vec2D.TransformMat2(d2, d2, bone.WorldTransform);

                    Vec2D sum = Vec2D.Add(new Vec2D(), d1, d2);
                    Vec2D.Negate(sum, sum);
                    Vec2D.TransformMat2(m_OutDirection, sum, inverseWorld);
                    Vec2D.Normalize(m_OutDirection, m_OutDirection);
                }
                Vec2D.Normalize(m_OutDirection, m_OutDirection);
                Vec2D scaledOut = Vec2D.Scale(new Vec2D(), m_OutDirection, m_EaseOut * bone.Length * CurveConstant);
                m_OutPoint[0] = bone.Length;
                m_OutPoint[1] = 0.0f;
                Vec2D.Add(m_OutPoint, m_OutPoint, scaledOut);
            }
            else
            {
                m_OutDirection[0] = -1.0f;
                m_OutDirection[1] = 0.0f;

                Vec2D scaledOut = Vec2D.Scale(new Vec2D(), m_OutDirection, m_EaseOut * bone.Length * CurveConstant);
                m_OutPoint[0] = bone.Length;
                m_OutPoint[1] = 0.0f;
                Vec2D.Add(m_OutPoint, m_OutPoint, scaledOut);
            }

            UpdateJellies();
        }
Exemple #9
0
        public override void CompleteResolve()
        {
            base.CompleteResolve();
            if (m_InfluencedBones == null || m_InfluencedBones.Length == 0)
            {
                return;
            }

            // Initialize solver.
            ActorBone start = m_InfluencedBones[0].m_Bone;
            ActorBone end   = m_InfluencedBones[m_InfluencedBones.Length - 1].m_Bone;
            int       count = 0;

            while (end != null && end != start.Parent)
            {
                count++;
                end = end.Parent as ActorBone;
            }

            bool allIn = count < 3;

            end       = m_InfluencedBones[m_InfluencedBones.Length - 1].m_Bone;
            m_FKChain = new BoneChain[count];
            int idx = count - 1;

            while (end != null && end != start.Parent)
            {
                BoneChain bc = new BoneChain();
                bc.m_Bone                = end;
                bc.m_Angle               = 0.0f;
                bc.m_Included            = allIn;
                bc.m_TransformComponents = new TransformComponents();
                bc.m_ParentWorldInverse  = new Mat2D();
                bc.m_Index               = idx;
                m_FKChain[idx--]         = bc;
                end = end.Parent as ActorBone;
            }

            // Make sure bones are good.
            m_BoneData = new List <BoneChain>();
            foreach (InfluencedBone bone in m_InfluencedBones)
            {
                BoneChain item = Array.Find(m_FKChain, chainItem => chainItem.m_Bone == bone.m_Bone);
                if (item == null)
                {
                    Console.WriteLine("Bone not in chain: " + bone.m_Bone.Name);
                    continue;
                }
                m_BoneData.Add(item);
            }
            if (!allIn)
            {
                // Influenced bones are in the IK chain.
                for (int i = 0; i < m_BoneData.Count - 1; i++)
                {
                    BoneChain item = m_BoneData[i];
                    item.m_Included = true;
                    m_FKChain[item.m_Index + 1].m_Included = true;
                }
            }

            // Finally mark dependencies.
            foreach (InfluencedBone bone in m_InfluencedBones)
            {
                // Don't mark dependency on parent as ActorComponent already does this.
                if (bone.m_Bone == m_Parent)
                {
                    continue;
                }

                m_Actor.AddDependency(this, bone.m_Bone);
            }

            if (m_Target != null)
            {
                m_Actor.AddDependency(this, m_Target);
            }

            // All the first level children of the influenced bones should depend on the final bone.
            BoneChain tip = m_FKChain[m_FKChain.Length - 1];

            foreach (BoneChain fk in m_FKChain)
            {
                if (fk == tip)
                {
                    continue;
                }

                ActorBone bone = fk.m_Bone;
                foreach (ActorNode node in bone.Children)
                {
                    BoneChain item = Array.Find(m_FKChain, chainItem => chainItem.m_Bone == node);
                    if (item != null)
                    {
                        // node is in the FK chain.
                        continue;
                    }
                    m_Actor.AddDependency(node, tip.m_Bone);
                }
            }
        }
Exemple #10
0
        void Solve2(BoneChain fk1, BoneChain fk2, Vec2D worldTargetTranslation)
        {
            ActorBone b1         = fk1.m_Bone;
            ActorBone b2         = fk2.m_Bone;
            BoneChain firstChild = m_FKChain[fk1.m_Index + 1];

            Mat2D iworld = fk1.m_ParentWorldInverse;

            Vec2D pA  = b1.GetWorldTranslation(new Vec2D());
            Vec2D pC  = firstChild.m_Bone.GetWorldTranslation(new Vec2D());
            Vec2D pB  = b2.GetTipWorldTranslation(new Vec2D());;
            Vec2D pBT = new Vec2D(worldTargetTranslation);

            pA  = Vec2D.TransformMat2D(pA, pA, iworld);
            pC  = Vec2D.TransformMat2D(pC, pC, iworld);
            pB  = Vec2D.TransformMat2D(pB, pB, iworld);
            pBT = Vec2D.TransformMat2D(pBT, pBT, iworld);

            // http://mathworld.wolfram.com/LawofCosines.html
            Vec2D av = Vec2D.Subtract(new Vec2D(), pB, pC);
            float a  = Vec2D.Length(av);

            Vec2D bv = Vec2D.Subtract(new Vec2D(), pC, pA);
            float b  = Vec2D.Length(bv);

            Vec2D cv = Vec2D.Subtract(new Vec2D(), pBT, pA);
            float c  = Vec2D.Length(cv);

            float A = (float)Math.Acos(Math.Max(-1, Math.Min(1, (-a * a + b * b + c * c) / (2 * b * c))));
            float C = (float)Math.Acos(Math.Max(-1, Math.Min(1, (a * a + b * b - c * c) / (2 * a * b))));

            float r1, r2;

            if (b2.Parent != b1)
            {
                BoneChain secondChild = m_FKChain[fk1.m_Index + 2];

                Mat2D secondChildWorldInverse = secondChild.m_ParentWorldInverse;

                pC = firstChild.m_Bone.GetWorldTranslation(new Vec2D());
                pB = b2.GetTipWorldTranslation(new Vec2D());

                Vec2D avec            = Vec2D.Subtract(new Vec2D(), pB, pC);
                Vec2D avLocal         = Vec2D.TransformMat2(new Vec2D(), avec, secondChildWorldInverse);
                float angleCorrection = (float)-Math.Atan2(avLocal[1], avLocal[0]);

                if (m_InvertDirection)
                {
                    r1 = (float)Math.Atan2(cv[1], cv[0]) - A;
                    r2 = -C + PI + angleCorrection;
                }
                else
                {
                    r1 = A + (float)Math.Atan2(cv[1], cv[0]);
                    r2 = C - PI + angleCorrection;
                }
            }
            else if (m_InvertDirection)
            {
                r1 = (float)Math.Atan2(cv[1], cv[0]) - A;
                r2 = -C + PI;
            }
            else
            {
                r1 = A + (float)Math.Atan2(cv[1], cv[0]);
                r2 = C - PI;
            }

            ConstrainRotation(fk1, r1);
            ConstrainRotation(firstChild, r2);
            if (firstChild != fk2)
            {
                ActorBone bone = fk2.m_Bone;
                Mat2D.Multiply(bone.WorldTransform, bone.Parent.WorldTransform, bone.Transform);
            }

            // Simple storage, need this for interpolation.
            fk1.m_Angle        = r1;
            firstChild.m_Angle = r2;
        }
Exemple #11
0
        public override void Constrain(ActorNode node)
        {
            ActorNode target = m_Target as ActorNode;

            if (target == null)
            {
                return;
            }
            Vec2D worldTargetTranslation = new Vec2D();

            target.GetWorldTranslation(worldTargetTranslation);

            if (m_InfluencedBones.Length == 0)
            {
                return;
            }

            // Decompose the chain.
            foreach (BoneChain item in m_FKChain)
            {
                ActorBone bone        = item.m_Bone;
                Mat2D     parentWorld = bone.Parent.WorldTransform;
                Mat2D.Invert(item.m_ParentWorldInverse, parentWorld);
                Mat2D.Multiply(bone.Transform, item.m_ParentWorldInverse, bone.WorldTransform);
                Mat2D.Decompose(bone.Transform, item.m_TransformComponents);
            }

            int count = m_BoneData.Count;

            if (count == 1)
            {
                Solve1(m_BoneData[0], worldTargetTranslation);
            }
            else if (count == 2)
            {
                Solve2(m_BoneData[0], m_BoneData[1], worldTargetTranslation);
            }
            else
            {
                BoneChain tip = m_BoneData[count - 1];
                for (int i = 0; i < count - 1; i++)
                {
                    BoneChain item = m_BoneData[i];
                    Solve2(item, tip, worldTargetTranslation);
                    for (int j = item.m_Index + 1; j < m_FKChain.Length - 1; j++)
                    {
                        BoneChain fk = m_FKChain[j];
                        Mat2D.Invert(fk.m_ParentWorldInverse, fk.m_Bone.Parent.WorldTransform);
                    }
                }
            }

            // At the end, mix the FK angle with the IK angle by strength
            if (m_Strength != 1.0)
            {
                foreach (BoneChain fk in m_FKChain)
                {
                    if (!fk.m_Included)
                    {
                        ActorBone bone = fk.m_Bone;
                        Mat2D.Multiply(bone.WorldTransform, bone.Parent.WorldTransform, bone.Transform);
                        continue;
                    }
                    float fromAngle = fk.m_TransformComponents.Rotation % PI2;
                    float toAngle   = fk.m_Angle % PI2;
                    float diff      = toAngle - fromAngle;
                    if (diff > PI)
                    {
                        diff -= PI2;
                    }
                    else if (diff < -PI)
                    {
                        diff += PI2;
                    }
                    float angle = fromAngle + diff * m_Strength;
                    ConstrainRotation(fk, angle);
                }
            }
        }