/// <summary> /// Serializes the slots contents to be stored in the SaveGame /// </summary> /// <param name="tree"></param> /// <param name="forClient"></param> public virtual void ToAttributes(ITreeAttribute tree, bool forClient) { foreach (var val in ActiveAnimationsByAnimCode) { if (val.Value.Code == null) { val.Value.Code = val.Key; // ah wtf. } if (!forClient && val.Value.Code != "die") { continue; } RunningAnimation anim = Animator.GetAnimationState(val.Value.Animation); if (anim != null) { val.Value.StartFrameOnce = anim.CurrentFrame; } using (MemoryStream ms = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(ms)) { val.Value.ToBytes(writer); } tree[val.Key] = new ByteArrayAttribute(ms.ToArray()); } val.Value.StartFrameOnce = 0; } }
public AnimatorBase(WalkSpeedSupplierDelegate WalkSpeedSupplier, Animation[] Animations, Action <string> onAnimationStoppedListener = null) { this.WalkSpeedSupplier = WalkSpeedSupplier; this.onAnimationStoppedListener = onAnimationStoppedListener; anims = new RunningAnimation[Animations == null ? 0 : Animations.Length]; for (int i = 0; i < anims.Length; i++) { Animations[i].Code = Animations[i].Code.ToLower(); anims[i] = new RunningAnimation() { Active = false, Running = false, Animation = Animations[i], CurrentFrame = 0 }; } float[] identMat = Mat4f.Create(); for (int i = 0; i < TransformationMatricesDefaultPose.Length; i++) { TransformationMatricesDefaultPose[i] = identMat[i % 16]; } }
protected virtual void AnimNowActive(RunningAnimation anim, AnimationMetaData animData) { anim.Running = true; anim.Active = true; anim.meta = animData; anim.ShouldRewind = false; anim.ShouldPlayTillEnd = false; anim.CurrentFrame = animData.StartFrameOnce; animData.StartFrameOnce = 0; }
protected override void AnimNowActive(RunningAnimation anim, AnimationMetaData animData) { base.AnimNowActive(anim, animData); if (anim.Animation.PrevNextKeyFrameByFrame == null) { anim.Animation.GenerateAllFrames(rootElements, jointsById); } anim.LoadWeights(rootElements); }
void updateLocalEyePosImmersiveFpMode() { AttachmentPointAndPose apap = AnimManager.Animator.GetAttachmentPointPose("Eyes"); AttachmentPoint ap = apap.AttachPoint; float[] ModelMat = Mat4f.Create(); Matrixf tmpModelMat = new Matrixf(); float bodyYaw = BodyYaw; float rotX = Properties.Client.Shape != null ? Properties.Client.Shape.rotateX : 0; float rotY = Properties.Client.Shape != null ? Properties.Client.Shape.rotateY : 0; float rotZ = Properties.Client.Shape != null ? Properties.Client.Shape.rotateZ : 0; float bodyPitch = WalkPitch; float lookOffset = (SidedPos.Pitch - GameMath.PI) / 9f; bool wasHoldPos = holdPosition; holdPosition = false; for (int i = 0; i < AnimManager.Animator.RunningAnimations.Length; i++) { RunningAnimation anim = AnimManager.Animator.RunningAnimations[i]; if (anim.Running && anim.EasingFactor > anim.meta.HoldEyePosAfterEasein) { if (!wasHoldPos) { prevAnimModelMatrix = (float[])apap.AnimModelMatrix.Clone(); } holdPosition = true; break; } } tmpModelMat .Set(ModelMat) .RotateX(SidedPos.Roll + rotX * GameMath.DEG2RAD) .RotateY(bodyYaw + (180 + rotY) * GameMath.DEG2RAD) .RotateZ(bodyPitch + rotZ * GameMath.DEG2RAD) .Mul(holdPosition ? prevAnimModelMatrix : apap.AnimModelMatrix) .Scale(Properties.Client.Size, Properties.Client.Size, Properties.Client.Size) .Translate(-0.5f, 0, -0.5f) .Translate(ap.PosX / 16f - lookOffset, ap.PosY / 16f - lookOffset / 1.3f, ap.PosZ / 16f) ; float[] pos = new float[4] { 0, 0, 0, 1 }; float[] endVec = Mat4f.MulWithVec4(tmpModelMat.Values, pos); LocalEyePos.Set(endVec[0], endVec[1], endVec[2]); }
public RunningAnimation GetAnimationState(string code) { for (int i = 0; i < anims.Length; i++) { RunningAnimation anim = anims[i]; if (anim.Animation.Code == code) { return(anim); } } return(null); }
public virtual void OnFrame(Dictionary <string, AnimationMetaData> activeAnimationsByAnimCode, float dt) { curAnimCount = 0; accum += dt; if (accum > 0.25f) { walkSpeed = WalkSpeedSupplier == null ? 1f : WalkSpeedSupplier(); accum = 0; } //string debug = ""; for (int i = 0; i < anims.Length; i++) { RunningAnimation anim = anims[i]; AnimationMetaData animData; activeAnimationsByAnimCode.TryGetValue(anim.Animation.Code, out animData); bool wasActive = anim.Active; anim.Active = animData != null; // Animation got started if (!wasActive && anim.Active) { AnimNowActive(anim, animData); } // Animation got stopped if (wasActive && !anim.Active) { if (anim.Animation.OnActivityStopped == EnumEntityActivityStoppedHandling.Rewind) { anim.ShouldRewind = true; } if (anim.Animation.OnActivityStopped == EnumEntityActivityStoppedHandling.Stop) { anim.Stop(); activeAnimationsByAnimCode.Remove(anim.Animation.Code); onAnimationStoppedListener?.Invoke(anim.Animation.Code); } if (anim.Animation.OnActivityStopped == EnumEntityActivityStoppedHandling.PlayTillEnd) { anim.ShouldPlayTillEnd = true; } } if (!anim.Running) { continue; } bool shouldStop = (anim.Iterations > 0 && anim.Animation.OnAnimationEnd == EnumEntityAnimationEndHandling.Stop) || (anim.Iterations > 0 && !anim.Active && (anim.Animation.OnActivityStopped == EnumEntityActivityStoppedHandling.PlayTillEnd || anim.Animation.OnActivityStopped == EnumEntityActivityStoppedHandling.EaseOut) && anim.EasingFactor < 0.002f) || (anim.Iterations < 0 && !anim.Active && anim.Animation.OnActivityStopped == EnumEntityActivityStoppedHandling.Rewind && anim.EasingFactor < 0.002f) ; if (shouldStop) { anim.Stop(); if (anim.Animation.OnAnimationEnd == EnumEntityAnimationEndHandling.Stop) { activeAnimationsByAnimCode.Remove(anim.Animation.Code); onAnimationStoppedListener?.Invoke(anim.Animation.Code); } continue; } // debug += anim.Animation.Code + "("+anim.BlendedWeight.ToString("#.##")+"),"; CurAnims[curAnimCount] = anim; if (anim.Animation.OnAnimationEnd == EnumEntityAnimationEndHandling.Hold && anim.Iterations != 0 && !anim.Active) { anim.EaseOut(dt); } anim.Progress(dt, (float)walkSpeed); curAnimCount++; } calculateMatrices(dt); }
// Careful when changing around stuff in here, this is a recursively called method private void calculateMatrices( float dt, List <ElementPose> currentPoses, ShapeElementWeights[][] weightsByAnimationAndElement, float[] modelMatrix, List <ElementPose>[] transformsByAnimation, List <ElementPose>[] nextFrameTransformsByAnimation, int depth ) { depth++; List <ElementPose>[] childTransformsByAnimation = this.transformsByAnimation[depth]; List <ElementPose>[] nextFrameChildTransformsByAnimation = this.nextFrameTransformsByAnimation[depth]; ShapeElementWeights[][] childWeightsByAnimationAndElement = this.weightsByAnimationAndElement[depth]; for (int i = 0; i < currentPoses.Count; i++) { ElementPose currentPose = currentPoses[i]; ShapeElement elem = currentPose.ForElement; currentPose.SetMat(modelMatrix); Mat4f.Identity(localTransformMatrix); currentPose.Clear(); float weightSum = 0f; for (int j = 0; j < curAnimCount; j++) { RunningAnimation anim = CurAnims[j]; ShapeElementWeights sew = weightsByAnimationAndElement[j][i]; if (sew.BlendMode != EnumAnimationBlendMode.Add) { weightSum += sew.Weight * anim.EasingFactor; } } for (int j = 0; j < curAnimCount; j++) { RunningAnimation anim = CurAnims[j]; ShapeElementWeights sew = weightsByAnimationAndElement[j][i]; //anim.CalcBlendedWeight(sew.Weight weightSum, sew.BlendMode); - that makes no sense for element weights != 1 anim.CalcBlendedWeight(weightSum / sew.Weight, sew.BlendMode); ElementPose prevFramePose = transformsByAnimation[j][i]; ElementPose nextFramePose = nextFrameTransformsByAnimation[j][i]; int prevFrame = this.prevFrame[j]; int nextFrame = this.nextFrame[j]; // May loop around, so nextFrame can be smaller than prevFrame float keyFrameDist = nextFrame > prevFrame ? (nextFrame - prevFrame) : (anim.Animation.QuantityFrames - prevFrame + nextFrame); float curFrameDist = anim.CurrentFrame >= prevFrame ? (anim.CurrentFrame - prevFrame) : (anim.Animation.QuantityFrames - prevFrame + anim.CurrentFrame); float lerp = curFrameDist / keyFrameDist; currentPose.Add(prevFramePose, nextFramePose, lerp, anim.BlendedWeight); childTransformsByAnimation[j] = prevFramePose.ChildElementPoses; childWeightsByAnimationAndElement[j] = sew.ChildElements; nextFrameChildTransformsByAnimation[j] = nextFramePose.ChildElementPoses; } elem.GetLocalTransformMatrix(localTransformMatrix, currentPose); Mat4f.Mul(currentPose.AnimModelMatrix, currentPose.AnimModelMatrix, localTransformMatrix); if (elem.JointId > 0 && !jointsDone.Contains(elem.JointId)) { Mat4f.Mul(tmpMatrix, currentPose.AnimModelMatrix, elem.inverseModelTransform); for (int l = 0; l < 16; l++) { TransformationMatrices[16 * elem.JointId + l] = tmpMatrix[l]; } jointsDone.Add(elem.JointId); } if (currentPose.ChildElementPoses != null) { calculateMatrices( dt, currentPose.ChildElementPoses, childWeightsByAnimationAndElement, currentPose.AnimModelMatrix, childTransformsByAnimation, nextFrameChildTransformsByAnimation, depth ); } } }
protected override void calculateMatrices(float dt) { if (!CalculateMatrices) { return; } try { jointsDone.Clear(); for (int j = 0; j < curAnimCount; j++) { RunningAnimation anim = CurAnims[j]; weightsByAnimationAndElement[0][j] = anim.ElementWeights; AnimationFrame[] prevNextFrame = anim.Animation.PrevNextKeyFrameByFrame[(int)anim.CurrentFrame % anim.Animation.QuantityFrames]; transformsByAnimation[0][j] = prevNextFrame[0].RootElementTransforms; prevFrame[j] = prevNextFrame[0].FrameNumber; if (anim.Animation.OnAnimationEnd == EnumEntityAnimationEndHandling.Hold && (int)anim.CurrentFrame + 1 == anim.Animation.QuantityFrames) { nextFrameTransformsByAnimation[0][j] = prevNextFrame[0].RootElementTransforms; nextFrame[j] = prevNextFrame[0].FrameNumber; } else { nextFrameTransformsByAnimation[0][j] = prevNextFrame[1].RootElementTransforms; nextFrame[j] = prevNextFrame[1].FrameNumber; } } calculateMatrices( dt, RootPoses, weightsByAnimationAndElement[0], Mat4f.Create(), transformsByAnimation[0], nextFrameTransformsByAnimation[0], 0 ); for (int jointid = 0; jointid < GlobalConstants.MaxAnimatedElements; jointid++) { if (jointsById.ContainsKey(jointid)) { continue; } for (int j = 0; j < 16; j++) { TransformationMatrices[jointid * 16 + j] = identMat[j]; } } foreach (var val in AttachmentPointByCode) { for (int i = 0; i < 16; i++) { val.Value.AnimModelMatrix[i] = val.Value.CachedPose.AnimModelMatrix[i]; } } } catch (Exception) { //entity.World.Logger.Fatal("Animation system crash. Please report this bug. curanimcount: {3}, tm-l:{0}, jbi-c: {1}, abc-c: {2}\nException: {4}", TransformationMatrices.Length, jointsById.Count, AttachmentPointByCode.Count, curAnimCount, e); } }
protected override void AnimNowActive(RunningAnimation anim, AnimationMetaData animData) { base.AnimNowActive(anim, animData); anim.LoadWeights(rootElements); }