public static ActorImage Read(Actor actor, BinaryReader reader, ActorImage node = null) { if (node == null) { node = new ActorImage(); } ActorNode.Read(actor, reader, node); bool isVisible = reader.ReadByte() != 0; if (isVisible) { node.m_BlendMode = (BlendModes)reader.ReadByte(); node.m_DrawOrder = (int)reader.ReadUInt16(); node.m_TextureIndex = (int)reader.ReadByte(); int numConnectedBones = (int)reader.ReadByte(); if (numConnectedBones != 0) { node.m_BoneConnections = new BoneConnection[numConnectedBones]; for (int i = 0; i < numConnectedBones; i++) { BoneConnection bc = new BoneConnection(); bc.m_BoneIdx = reader.ReadUInt16(); Actor.ReadFloat32Array(reader, bc.m_Bind.Values); Mat2D.Invert(bc.m_InverseBind, bc.m_Bind); node.m_BoneConnections[i] = bc; } Mat2D worldOverride = new Mat2D(); Actor.ReadFloat32Array(reader, worldOverride.Values); node.WorldTransformOverride = worldOverride; } uint numVertices = reader.ReadUInt32(); int vertexStride = numConnectedBones > 0 ? 12 : 4; node.m_VertexCount = (int)numVertices; node.m_Vertices = new float[numVertices * vertexStride]; Actor.ReadFloat32Array(reader, node.m_Vertices); uint numTris = reader.ReadUInt32(); node.m_Triangles = new ushort[numTris * 3]; node.m_TriangleCount = (int)numTris; Actor.ReadUInt16Array(reader, node.m_Triangles); } return(node); }
public bool LoadFrom(Stream stream) { BlockReader reader = new BlockReader(stream); byte N = reader.ReadByte(); byte I = reader.ReadByte(); byte M = reader.ReadByte(); byte A = reader.ReadByte(); uint version = reader.ReadUInt32(); if (N != 78 || I != 73 || M != 77 || A != 65) { return(false); } if (version < 12) { return(false); } m_Version = version; //version == 1.0 //Debugger.Log("NIMA confirmed. " + reader.BaseStream.Length); //byte[] data = new byte[reader.BaseStream.Length]; m_MaxTextureIndex = 0; m_Root = new ActorNode(this); BlockReader block = null; while ((block = reader.ReadNextBlock()) != null) { switch (block.BlockType) { case (int)BlockTypes.Components: ReadComponentsBlock(block); break; case (int)BlockTypes.Animations: ReadAnimationsBlock(block); break; } } return(true); }
public virtual void ResolveComponentIndices(ActorComponent[] components) { ActorNode node = components[m_ParentIdx] as ActorNode; if (node != null) { if (this is ActorNode) { node.AddChild(this as ActorNode); } else { m_Parent = node; } m_Actor.AddDependency(this, node); } }
public override void Constrain(ActorNode node) { ActorNode target = m_Target as ActorNode; if (target == null) { return; } Vec2D targetTranslation = target.GetWorldTranslation(new Vec2D()); Vec2D ourTranslation = m_Parent.GetWorldTranslation(new Vec2D()); Vec2D toTarget = Vec2D.Subtract(new Vec2D(), ourTranslation, targetTranslation); float currentDistance = Vec2D.Length(toTarget); switch (m_Mode) { case Mode.Closer: if (currentDistance < m_Distance) { return; } break; case Mode.Further: if (currentDistance > m_Distance) { return; } break; } if (currentDistance < 0.001) { return; } Vec2D.Scale(toTarget, toTarget, 1.0f / currentDistance); Vec2D.Scale(toTarget, toTarget, m_Distance); Mat2D world = m_Parent.WorldTransform; Vec2D position = Vec2D.Lerp(new Vec2D(), ourTranslation, Vec2D.Add(new Vec2D(), targetTranslation, toTarget), m_Strength); world[4] = position[0]; world[5] = position[1]; }
public static ActorNode Read(Actor actor, BinaryReader reader, ActorNode node = null) { if (node == null) { node = new ActorNode(); } ActorComponent.Read(actor, reader, node); Actor.ReadFloat32Array(reader, node.m_Translation.Values); node.m_Rotation = reader.ReadSingle(); Actor.ReadFloat32Array(reader, node.m_Scale.Values); node.m_Opacity = reader.ReadSingle(); if (actor.Version >= 13) { node.m_IsCollapsedVisibility = reader.ReadByte() == 1; } return(node); }
public void Copy(Actor actor) { m_Animations = actor.m_Animations; m_Flags = actor.m_Flags; m_MaxTextureIndex = actor.m_MaxTextureIndex; m_ImageNodeCount = actor.m_ImageNodeCount; m_NodeCount = actor.m_NodeCount; if (actor.ComponentCount != 0) { m_Components = new ActorComponent[actor.ComponentCount]; } if (m_NodeCount != 0) // This will always be at least 1. { m_Nodes = new ActorNode[m_NodeCount]; } if (m_ImageNodeCount != 0) { m_ImageNodes = new ActorImage[m_ImageNodeCount]; } if (actor.ComponentCount != 0) { int idx = 0; int imgIdx = 0; int ndIdx = 0; foreach (ActorComponent component in actor.Components) { if (component == null) { m_Components[idx++] = null; continue; } ActorComponent instanceComponent = component.MakeInstance(this); m_Components[idx++] = instanceComponent; ActorNode nodeInstance = instanceComponent as ActorNode; if (nodeInstance != null) { m_Nodes[ndIdx++] = nodeInstance; } ActorImage imageInstance = instanceComponent as ActorImage; if (imageInstance != null) { m_ImageNodes[imgIdx++] = imageInstance; } } } m_Root = m_Components[0] as ActorNode; foreach (ActorComponent component in m_Components) { if (m_Root == component || component == null) { continue; } component.ResolveComponentIndices(m_Components); } foreach (ActorComponent component in m_Components) { if (m_Root == component || component == null) { continue; } component.CompleteResolve(); } SortDependencies(); }
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(); }
public void Start() { m_Actor = gameObject.GetComponent <Nima.Unity.ActorBaseComponent>(); if (m_Actor != null) { // Get a game object from the actor, use this to mount items or query for other components. // GameObject headColliderGameObject = m_Actor.GetActorGameObject("HeadCollider"); // if(headColliderGameObject != null) // { // Collider2D collider = headColliderGameObject.GetComponent<Collider2D>(); // if(collider != null) // { // // Set it to a trigger, or do something else with it... // // collider.isTrigger = true; // } // } if (m_Actor.ActorInstance != null) { m_Idle = m_Actor.ActorInstance.GetAnimation("Idle"); m_Aim = m_Actor.ActorInstance.GetAnimation("Aim2"); m_Walk = m_Actor.ActorInstance.GetAnimationInstance("Walk"); m_Run = m_Actor.ActorInstance.GetAnimation("Run"); m_WalkToIdle = m_Actor.ActorInstance.GetAnimation("WalkToIdle"); // We made walk an animation instance so it has it's own sense of time which lets it do things like track events. m_Walk.AnimationEvent += delegate(object animationInstance, Nima.Animation.AnimationEventArgs args) { // Event triggered from animation. }; Nima.ActorNode characterNode = m_Actor.ActorInstance.GetNode("Character"); if (characterNode != null) { m_GroundSpeedProperty = characterNode.GetCustomFloatProperty("GroundSpeed"); m_IsRunningProperty = characterNode.GetCustomBooleanProperty("IsRunning"); } // Calculate aim slices. if (m_Aim != null) { Nima.ActorNode muzzle = m_Actor.ActorInstance.GetNode("Muzzle"); if (muzzle != null) { for (int i = 0; i < AimSliceCount; i++) { float position = i / (float)(AimSliceCount - 1) * m_Aim.Duration; m_Aim.Apply(position, m_Actor.ActorInstance, 1.0f); m_Actor.ActorInstance.Advance(0.0f); Nima.Math2D.Mat2D worldTransform = muzzle.WorldTransform; AimSlice slice = m_AimLookup[i]; // Extract forward vector and position. slice.dir = new Nima.Math2D.Vec2D(); Nima.Math2D.Vec2D.Normalize(slice.dir, new Nima.Math2D.Vec2D(worldTransform[0], worldTransform[1])); slice.point = new Nima.Math2D.Vec2D(worldTransform[4] * Nima.Unity.ActorAsset.NimaToUnityScale, worldTransform[5] * Nima.Unity.ActorAsset.NimaToUnityScale); m_AimLookup[i] = slice; } } if (m_Walk != null) { m_Walk.Time = 0.0f; m_Walk.Apply(1.0f); for (int i = 0; i < AimSliceCount; i++) { float position = i / (float)(AimSliceCount - 1) * m_Aim.Duration; m_Aim.Apply(position, m_Actor.ActorInstance, 1.0f); m_Actor.ActorInstance.Advance(0.0f); Nima.Math2D.Mat2D worldTransform = muzzle.WorldTransform; AimSlice slice = m_AimWalkingLookup[i]; // Extract forward vector and position. slice.dir = new Nima.Math2D.Vec2D(); Nima.Math2D.Vec2D.Normalize(slice.dir, new Nima.Math2D.Vec2D(worldTransform[0], worldTransform[1])); slice.point = new Nima.Math2D.Vec2D(worldTransform[4] * Nima.Unity.ActorAsset.NimaToUnityScale, worldTransform[5] * Nima.Unity.ActorAsset.NimaToUnityScale); m_AimWalkingLookup[i] = slice; } } } } } m_IdleTime = 0.0f; }
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 static ActorCollider Read(Actor actor, BinaryReader reader, ActorCollider property) { ActorNode.Read(actor, reader, property); property.IsCollisionEnabled = reader.ReadByte() == 1; return(property); }
public abstract void Constrain(ActorNode node);
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); } } }
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; }