public static AnimationCurve CreateCurve( float[] values, float[] times, bool smooth = true) { D.Assert( values != null && times != null, "Param == null" ); D.Assert( values.Length == times.Length, "Size not same" ); if ( values.Length != times.Length ){ D.Log("values.Length: {0} times.Length: {1}", values.Length, times.Length); } AnimationCurve result; Keyframe[] ks = new Keyframe[values.Length]; for( int i = 0; i < values.Length; i ++ ) { ks[ i ] = new Keyframe( times[ i ], values[ i ] ); } result = new AnimationCurve( ks ); if ( smooth){ for( int i = 0; i < result.length; i++ ) { result.SmoothTangents( i, 0 ); } } return result; }
/// <summary> /// Create drift orbit /// </summary> public void Drift(Vector3 origin, float speed, out AnimationCurve[] ac) { Keyframe[][] kf = new Keyframe[2][]; kf[X] = new Keyframe[driftPoints + 2]; kf[Y] = new Keyframe[driftPoints + 2]; kf[X][0] = new Keyframe(0, origin.x, inTangent, outTangent); kf[Y][0] = new Keyframe(0, origin.y, inTangent, outTangent); for (int i = 1; i <= driftPoints; i++) { kf[X][i] = new Keyframe(i / speed, origin.x + (driftX * Random.value), inTangent, outTangent); kf[Y][i] = new Keyframe(i / speed, origin.y + (driftY * Random.value), inTangent, outTangent); } kf[X][driftPoints + 1] = new Keyframe((driftPoints + 1) / speed, origin.x, inTangent, outTangent); kf[Y][driftPoints + 1] = new Keyframe((driftPoints + 1) / speed, origin.y, inTangent, outTangent); // Curves ac = new AnimationCurve[2]; ac[X] = new AnimationCurve(kf[X]); ac[Y] = new AnimationCurve(kf[Y]); // Smooth curves for (int i = 0; i < ac[X].keys.Length; ++i) { ac[X].SmoothTangents(i, 0); ac[Y].SmoothTangents(i, 0); } }
void Start() { GameObject.Find("GUI Text").guiText.text = "AnimationClip sample"; AnimationClip clipA = new AnimationClip(); AnimationCurve curveA = AnimationCurve.Linear(0f, 3f, 3f, 3f); Keyframe keyA = new Keyframe(1.5f, 10f); curveA.AddKey(keyA); clipA.SetCurve("", typeof(Transform), "localPosition.z", curveA); clipA.wrapMode = WrapMode.Loop; animation.AddClip(clipA, "anim1"); AnimationClip clipB = new AnimationClip(); AnimationCurve curveB = AnimationCurve.Linear(0f, 3f, 3f, 3f); Keyframe key1 = new Keyframe(0.75f, 7f); curveB.AddKey(key1); Keyframe key2 = new Keyframe(1.5f, 3f); curveB.AddKey(key2); Keyframe key3 = new Keyframe(2.25f,7f); curveB.AddKey (key3); clipB.SetCurve("", typeof(Transform), "localPosition.z", curveB); clipB.wrapMode = WrapMode.Loop; animation.AddClip(clipB, "anim2"); animation.Play ("anim1"); }
// Use this for initialization void Start() { GameObject[] ob_cubes; ob_cubes = GameObject.FindGameObjectsWithTag("ob_cube"); foreach (GameObject obj in ob_cubes) { Vector3 move = obj.transform.position; AnimationClip clip = new AnimationClip(); clip.legacy = true; Keyframe[] keysX = new Keyframe[2]; keysX[0] = new Keyframe(0f, move.x - 5); keysX[1] = new Keyframe(1f, move.x + 3); AnimationCurve curveX = new AnimationCurve(keysX); clip.SetCurve("", typeof(Transform), "localPosition.x", curveX); clip.wrapMode = WrapMode.PingPong; Keyframe[] keysY = new Keyframe[2]; keysY[0] = new Keyframe(0f, move.y); keysY[1] = new Keyframe(1f, move.y); AnimationCurve curveY = new AnimationCurve(keysY); clip.SetCurve("", typeof(Transform), "localPosition.y", curveY); Keyframe[] keysZ = new Keyframe[2]; keysZ[0] = new Keyframe(0f, move.z); keysZ[1] = new Keyframe(1f, move.z); AnimationCurve curveZ = new AnimationCurve(keysZ); clip.SetCurve("", typeof(Transform), "localPosition.z", curveZ); Animation animation = obj.GetComponent<Animation>(); animation.AddClip(clip, "clip1"); animation.Play("clip1"); } }
public void Test_New2() { var frame = new Keyframe (1, new Vector3(1,2,3)); Assert.AreEqual (1, frame.Time); Assert.AreEqual (new Vector3(1,2,3), frame.Value); }
void SetLoupiotteAproach() { AnimationClip clip = new AnimationClip(); Keyframe[] xValues = new Keyframe[5]; Keyframe[] yValues = new Keyframe[5]; Keyframe[] zValues = new Keyframe[5]; Keyframe[] stateValues = new Keyframe[5]; for (int i = 0; i<5; i++) { xValues[i] = new Keyframe(i * 3.0f, i < 4 ? Random.Range(-20.0f / (2 * i + 1), 20.0f / (2 * i + 1)) : xReference); zValues[i] = new Keyframe(i * 3.0f, i < 4 ? Random.Range(-20.0f / (2 * i + 1), 20.0f / (2 * i + 1)) : zReference); stateValues[i] = new Keyframe(i * 3.0f, i < 4 ? 0.0f : 1.0f); } yValues[0] = new Keyframe(0.0f, 50.0f); yValues[1] = new Keyframe(3.0f, 35.0f); yValues[2] = new Keyframe(6.0f, 25.0f); yValues[3] = new Keyframe(9.0f, 15.0f); yValues[4] = new Keyframe(12.0f, yReference); AnimationCurve xCurve = new AnimationCurve(xValues); AnimationCurve yCurve = new AnimationCurve(yValues); AnimationCurve zCurve = new AnimationCurve(zValues); AnimationCurve stateCurve = new AnimationCurve(stateValues); clip.legacy = true; clip.SetCurve("", typeof(Loupiotte), "positionToPlayer.x", xCurve); clip.SetCurve("", typeof(Loupiotte), "positionToPlayer.y", yCurve); clip.SetCurve("", typeof(Loupiotte), "positionToPlayer.z", zCurve); clip.SetCurve("", typeof(Loupiotte), "state", stateCurve); anim.AddClip(clip, "Approche"); }
public static AnimationCurve CreateLineraCurve( float[] values, float[] times ) { D.Assert( values != null && times != null, "Param == null" ); D.Assert( values.Length == times.Length, "Size not same" ); AnimationCurve result; Keyframe[] ks = new Keyframe[values.Length]; for( int i = 0; i < values.Length; i ++ ) { float inTgt; float outTgt; if ( i == 0){ inTgt = 0; }else{ inTgt = (values[ i ] - values[i-1])/(times[i] - times[i-1]); } if ( i == values.Length -1){ outTgt = 0; }else{ outTgt = (values[ i+1 ] - values[i])/(times[i+1] - times[i]); } ks[ i ] = new Keyframe( times[ i ], values[ i ], inTgt, outTgt ); } result = new AnimationCurve( ks ); return result; }
void CreateAnimationClip() { CameraShakeTool tool = target as CameraShakeTool; List<Keyframe> keyframeList = new List<Keyframe>(); foreach (Vector2 v in tool.value) { Keyframe k = new Keyframe(v.x, v.y); keyframeList.Add(k); } AnimationClip clip = new AnimationClip(); #if UNITY_5 clip.legacy = true; #endif clip.wrapMode = WrapMode.Once; clip.SetCurve("", typeof(Transform), "localPosition.x", new AnimationCurve(keyframeList.ToArray())); string activePath = AssetDatabase.GetAssetPath(Selection.activeObject); string directory = Path.GetDirectoryName(activePath); string filename = Path.GetFileNameWithoutExtension(activePath); string path = directory + "/" + filename + ".anim"; string clipPath = AssetDatabase.GenerateUniqueAssetPath(path); AssetDatabase.CreateAsset(clip, clipPath); }
public static float CalculateCurvesPoint(Keyframe[] aCurve, long nFrame) { if (null == aCurve || 1> aCurve.Length) throw new Exception("curve is empty"); Keyframe[] aInterval=FindInterval(aCurve, nFrame); if (1 == aInterval.Length) { if (aCurve[0] == aInterval[0]) ; // в идеале расчитать экстрапол¤цию за границы диапазона (касательна¤ в ту же сторону) if (aCurve[aCurve.Length - 1] == aInterval[0]) ; // в идеале расчитать экстрапол¤цию за границы диапазона (касательна¤ в ту же сторону) return aInterval[0].nPosition; // но пока просто остаЄмс¤ на этой точке } float nRetVal = 0; switch (aInterval[0].eType) { case Keyframe.Type.hold: // формула y=A при M<=x<N nRetVal = aInterval[0].nPosition; break; case Keyframe.Type.linear: // формула y=kx+h, где y-пиксели, x-фреймы. M, N - точки на х; A, B - точки на y, то люба¤ точка (PX, FR) <= PX=((B-A)/(N-M))*(FR-M)+A nRetVal = ((aInterval[1].nPosition - aInterval[0].nPosition) / (aInterval[1].nFrame - aInterval[0].nFrame)) * (nFrame - aInterval[0].nFrame) + aInterval[0].nPosition; break; case Keyframe.Type.besier: break; default: break; } return nRetVal; }
void Start() { moves[0] = new Vector3( 0f, 1f, 0f); moves[1] = new Vector3(-3f, 1f, 5f); moves[2] = new Vector3( 3f, 1f, 5f); moves[3] = new Vector3(-3f, 1f, -3f); moves[4] = new Vector3( 3f, 1f, -3f); for(int i=0;i<5;i++){ cubes[i] = GameObject.Find ("BoardCube"+i); Vector3 move = cubes[i].transform.position; AnimationClip clip = new AnimationClip(); Keyframe[] keysX = new Keyframe[2]; keysX[0] = new Keyframe( 0f, move.x-3); keysX[1] = new Keyframe(i+1f, move.x+3); AnimationCurve curveX = new AnimationCurve(keysX); clip.SetCurve("", typeof(Transform), "localPosition.x", curveX); clip.wrapMode = WrapMode.PingPong; Keyframe[] keysY = new Keyframe[2]; keysY[0] = new Keyframe( 0f, move.y); keysY[1] = new Keyframe(i+1f, move.y); AnimationCurve curveY = new AnimationCurve(keysY); clip.SetCurve("", typeof(Transform), "localPosition.y", curveY); Keyframe[] keysZ = new Keyframe[2]; keysZ[0] = new Keyframe( 0f, move.z); keysZ[1] = new Keyframe(i+1f, move.z); AnimationCurve curveZ = new AnimationCurve(keysZ); clip.SetCurve("", typeof(Transform), "localPosition.z", curveZ); cubes[i].animation.AddClip(clip, "clip1"); cubes[i].animation.Play("clip1"); } }
public static bool CurveIsWrong(Keyframe[] aCurve) { if (null == aCurve || 1 > aCurve.Length) return true; else return false; }
public void Test_New1() { var frame = new Keyframe (1, 2); Assert.AreEqual (1, frame.Time); Assert.AreEqual (2, frame.Value); }
public void ApplyPose(Keyframe pose) { currentPose = pose; SetLocalTranslation(pose.GetTranslation()); poseRot = pose.GetRotation(); UpdateTransform(); }
// public AnimationInstance(Animation anim) { animation_ = anim; frameRate_ = anim.FrameRate; // The time of the last frame is less than the duration of the animation, // as the last frame has some duration itself. lastFrameTime_ = (anim.NumFrames - 1) / frameRate_; invFrameRate_ = 1.0f / frameRate_; duration_ = anim.NumFrames * invFrameRate_; int max = 0; // calculate max bone index // todo: do in content pipeline foreach (KeyValuePair<int, AnimationTrack> kvp in anim.Tracks) { if (kvp.Key >= max) max = kvp.Key + 1; } // Allocate animation keyframes (for lerping between times). keyframes_ = new Keyframe[max]; // Load all the tracks (one track per bone). tracks_ = new AnimationTrack[max]; foreach (int i in anim.Tracks.Keys) { keyframes_[i] = new Keyframe(); tracks_[i] = anim.Tracks[i]; } }
public static AnimationCurve CreateCurve( Keyframe[] keyFrames){ AnimationCurve result; result = new AnimationCurve( keyFrames ); for( int i = 0; i < result.length; i++ ) { result.SmoothTangents( i, 0 ); } return result; }
// UnityEditor.CurveUtility.cs (c) Unity Technologies public static TangentMode GetKeyTangentMode(Keyframe keyframe, int leftRight) { Type t = typeof(UnityEngine.Keyframe); FieldInfo field = t.GetField("m_TangentMode", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); int tangentMode = (int)field.GetValue(keyframe); if(leftRight == 0) return (TangentMode)((tangentMode & 6) >> 1); else return (TangentMode)((tangentMode & 24) >> 3); }
public override void Init() { SceneManager.RC = RC; var stativ = new SceneEntity("stativ", new ActionCode()); var dir = new DirectionalLight(new float3(0, 10, -1), new float4(1, 1, 1, 1), new float4(1, 1, 1, 1), new float4(1, 1, 1, 1), new float3(0, 0, 0), 0); stativ.AddComponent(dir); _camera = new Camera(stativ); stativ.transform.GlobalPosition = new float3(0, 0, 100); SceneManager.Manager.AddSceneEntity(stativ); _camera.Resize(Width, Height); Geometry wuerfelGeo = MeshReader.ReadWavefrontObj(new StreamReader(@"Assets/Sphere.obj.model")); _wuerfel = new SceneEntity("wuerfel", new Material(MoreShaders.GetSpecularShader(RC)), new Renderer(wuerfelGeo)); SceneManager.Manager.AddSceneEntity(_wuerfel); _channel2 = new Channel<float3>(Lerp.Float3Lerp); _channel1 = new Channel<float4>(Lerp.Float4Lerp, new float4(0.5f, 0.5f, 0.5f, 0.5f)); var key0 = new Keyframe<float4>(0, new float4(1, 0, 1, 1)); var key1 = new Keyframe<float4>(2, new float4(0.125f, 1, 0.125f, 1)); var key2 = new Keyframe<float4>(4, new float4(0.250f, 0.75f, 0.250f, 1)); var key3 = new Keyframe<float4>(6, new float4(0.5f, 0.5f, 0.5f, 1)); var key4 = new Keyframe<float4>(8, new float4(0.75f, 0.25f, 0.75f, 1)); var key5 = new Keyframe<float4>(10, new float4(1, 25, 0.125f, 1)); var key6 = new Keyframe<float4>(0, new float4(0, 1, 0, 1)); _channel1.AddKeyframe(key0); _channel1.AddKeyframe(key1); _channel1.AddKeyframe(key2); _channel1.AddKeyframe(key3); _channel1.AddKeyframe(key4); _channel1.AddKeyframe(key5); _channel1.AddKeyframe(key6); var key40 = new Keyframe<float3>(8, new float3(8, 0, 80)); var key00 = new Keyframe<float3>(0, new float3(0, 0, 0)); var key10 = new Keyframe<float3>(2, new float3(1, 2, 20)); var key20 = new Keyframe<float3>(4, new float3(2, 4, 40)); var key30 = new Keyframe<float3>(6, new float3(4, 4, 60)); var key50 = new Keyframe<float3>(12, new float3(0, 4, 60)); var key60 = new Keyframe<float3>(0, new float3(8, 8, 8)); _channel2.AddKeyframe(key00); _channel2.AddKeyframe(key10); _channel2.AddKeyframe(key20); _channel2.AddKeyframe(key30); _channel2.AddKeyframe(key40); _channel2.AddKeyframe(key50); _channel2.AddKeyframe(key60); _myAnim.AddAnimation(_channel1, RC, "ClearColor"); _myAnim.AddAnimation(_channel2, _wuerfel, "transform.GlobalPosition"); }
void Start() { GameObject.Find ("GUI Text").guiText.text = "AnimationClip sample"; AnimationClip clip = new AnimationClip (); AnimationCurve curve = AnimationCurve.Linear (0f, 3f, 3f, 3f); Keyframe key = new Keyframe (1.5f, 7f); curve.AddKey (key); clip.SetCurve ("", typeof(Transform), "localPosition.z", curve); clip.wrapMode = WrapMode.Loop; animation.AddClip (clip, "clip1"); animation.Play ("clip1"); }
public void SetStartPosition() { if (XPositionCurve.keys.Length < 2) XPositionCurve = AnimationCurve.Linear(0,0,1,0); if (YPositionCurve.keys.Length < 2) YPositionCurve = AnimationCurve.Linear(0,0,1,0); StartPostion = transform.position; Keyframe keyx = new Keyframe(0, StartPostion.x); XPositionCurve.MoveKey(0, keyx); Keyframe keyy = new Keyframe(0, StartPostion.y); YPositionCurve.MoveKey(0, keyy); }
public void TestTimelineData() { Keyframe<KeyframeParams>[] keyframes = new Keyframe<KeyframeParams>[] { new Keyframe<KeyframeParams>() { time=0, value=new KeyframeParams() { a=0,b=10 } }, new Keyframe<KeyframeParams>() { time=0.5f, value=new KeyframeParams() { a=1,b=5 } }, new Keyframe<KeyframeParams>() { time=0.1f, value=new KeyframeParams() { a=3,b=1 } } }; KeyframeObject keyframeObject = new KeyframeObject(); Func<int,float,string> formatMsg = (a,b)=>string.Format( "{0}-{1}", a, b ); Timeline<KeyframeParams,KeyframeObject> timeline = new Timeline<KeyframeParams, KeyframeObject>() { timelineEntity=keyframeObject, keyframes=keyframes, tweenFunction=(p1,p2,t)=>{ return new KeyframeParams() { a=(int)Lerp(p1.a,p2.a,t), b=Lerp(p1.b,p2.b,t) }; }, applyKeyframeParameters=(kfo,p)=>kfo.msg = formatMsg(p.a,p.b) }; Assert.AreEqual( -1, timeline.CurrentKeyframeIndex ); timeline.Update(0); Assert.AreEqual( 0, timeline.CurrentKeyframeIndex ); Assert.AreEqual( formatMsg(0,10), keyframeObject.msg ); timeline.Update(0.1f); Assert.AreEqual( 0, timeline.CurrentKeyframeIndex ); Assert.AreEqual( formatMsg(0,9f), keyframeObject.msg ); timeline.Update(0.4f); Assert.AreEqual( 0, timeline.CurrentKeyframeIndex ); Assert.AreEqual( formatMsg(1,5f), keyframeObject.msg ); timeline.Update(0.1f); Assert.AreEqual( 1, timeline.CurrentKeyframeIndex ); Assert.AreEqual( formatMsg(3,0.999999f), keyframeObject.msg ); timeline.Update(0.1f); Assert.AreEqual( 2, timeline.CurrentKeyframeIndex ); Assert.AreEqual( formatMsg(0,10f), keyframeObject.msg ); // this frame has no length timeline.Update(0.1f); Assert.AreEqual( 0, timeline.CurrentKeyframeIndex ); // loop around Assert.AreEqual( formatMsg(0,8f), keyframeObject.msg ); }
public static Keyframe[] FindInterval(Keyframe[] aCurve, long nFrame) { if (aCurve[0].nFrame >= nFrame) return new Keyframe[1] { aCurve[0]}; if (aCurve[aCurve.Length - 1].nFrame <= nFrame) return new Keyframe[1] { aCurve[aCurve.Length - 1] }; for (int ni = 0; ni < aCurve.Length - 1; ni++) { if (aCurve[ni].nFrame == nFrame) return new Keyframe[1] { aCurve[ni] }; if (aCurve[ni].nFrame > nFrame || aCurve[ni].nFrame < nFrame && aCurve[ni + 1].nFrame > nFrame) return new Keyframe[2] { aCurve[ni], aCurve[ni + 1] }; } throw new Exception("impossible to find interval"); }
private static void WriteKeyframe(BinaryWriter writer, Keyframe keyframe) { writer.Write(keyframe.Time); writer.Write(keyframe.ModelPartAnimStates.Count); foreach (var modelPartAnimState in keyframe.ModelPartAnimStates) { WriteModelPartAnimState(writer, modelPartAnimState); } writer.Write(keyframe.AnchorAnimStates.Count); foreach (var anchorAnimState in keyframe.AnchorAnimStates) { WriteAnchorAnimState(writer, anchorAnimState); } }
public static Keyframe GetNewKey(float time, float value, TangentMode left, TangentMode right) { object boxed = new Keyframe(time, value); // cant use struct in reflection SetKeyBroken(boxed, true); SetKeyTangentMode(boxed, 0, left); SetKeyTangentMode(boxed, 1, right); Keyframe keyframe = (Keyframe)boxed; if(left == TangentMode.Stepped) keyframe.inTangent = float.PositiveInfinity; if(right == TangentMode.Stepped) keyframe.outTangent = float.PositiveInfinity; return keyframe; }
void Start() { //カーブを設定 if(Application.platform == RuntimePlatform.WindowsEditor && generateCurveOnStartEditor) { Keyframe[] keys = new Keyframe[envelopeKeys.Length]; for(int i = 0; i < envelopeKeys.Length; i++) { EnvelopeKey envKey = envelopeKeys[i]; keys[i] = AnimationCurveUtil.GetNewKey(envKey.time, envKey.value, envKey.leftTangent, envKey.rightTangent); } envelopeCurve = new AnimationCurve(keys); envelopeCurve.preWrapMode = preWrapMode; envelopeCurve.postWrapMode = postWrapMode; AnimationCurveUtil.UpdateAllLinearTangents(envelopeCurve); } }
public void ResampleKeys() { keysCount = Mathf.Max (keysCount, 2); Keyframe[] keys = new Keyframe[keysCount]; float inv = 1f / (keysCount - 1); for (int i = 0; i < keysCount; i++) { keys[i] = new Keyframe(i * inv, Random.Range(randMin, randMax)); } float firstVal = keys [0].value; float lastVal = keys [keys.Length - 1].value; float middle = (firstVal + lastVal) * .5f; keys [0].value = middle; keys [keys.Length - 1].value = middle; curve = new AnimationCurve (keys); }
public static AnimationCurve FromXMLtoAnimationCurve(XmlNode node) { AnimationCurve output = new AnimationCurve(); if(node == null || !node.HasChildNodes) { output.AddKey(0, 1); output.AddKey(1, 1); return output; } foreach(XmlNode keyframeNode in node.SelectNodes("keyframe")) { Keyframe keyFrame = new Keyframe(); keyFrame.inTangent = float.Parse(keyframeNode["inTangent"].FirstChild.Value); keyFrame.outTangent = float.Parse(keyframeNode["outTangent"].FirstChild.Value); keyFrame.time = float.Parse(keyframeNode["time"].FirstChild.Value); keyFrame.value = float.Parse(keyframeNode["value"].FirstChild.Value); output.AddKey(keyFrame); } return output; }
// Can be called from outside if you want a different seed public void ResampleKeys() { // Make sure there is at least 2 keys keysCount = Mathf.Max( keysCount, 2 ); // Generate the keys randomly Keyframe[] keys = new Keyframe[keysCount]; float inv = 1f / (keysCount-1); for( int i = 0; i < keysCount; i++ ) keys[i] = new Keyframe( i * inv, Random.Range(randMin, randMax) ); // Make sure the first and last value matches to have a proper loop float firstVal = keys[0].value; float lastVal = keys[ keys.Length-1 ].value; float middle = (firstVal + lastVal) * .5f; keys[0].value = middle; keys[ keys.Length-1 ].value = middle; // Commit curve = new AnimationCurve( keys ); }
private Explosion(Texture2D tex, Rectangle position, Rectangle cut) { if (tex == null) { Position = position; return; } Sheet = new AnimatedSpriteSheet(tex) { Rectangle = new Rectangle(0, 0, 32, 32), AutoUpdate = true }; Position = position; for (var i = 0; i < 12; i++) { cut.X = 134 * i; var kf = new Keyframe(cut, 60f); Sheet.Add(kf); } }
private void DoOnTimer(double tickDuration) { if (m_skipLoops > 0) { m_skipLoops--; return; } if (m_group == null) { return; } bool update = false; if (m_selected) { if (m_group.RootPart.Velocity != Vector3.Zero) { m_group.RootPart.Velocity = Vector3.Zero; m_skippedUpdates = 1000; // m_group.SendGroupRootTerseUpdate(); m_group.RootPart.ScheduleTerseUpdate(); } return; } if (m_isCrossing) { // if crossing and timer running then cross failed // wait some time then // retry to set the position that evtually caused the outbound // if still outside region this will call startCrossing below m_isCrossing = false; m_skippedUpdates = 1000; m_group.AbsolutePosition = m_nextPosition; if (!m_isCrossing) { StopTimer(); StartTimer(); } return; } double nowMS = Util.GetTimeStampMS(); if (m_frames.Count == 0) { lock (m_frames) { GetNextList(); if (m_frames.Count == 0) { Done(); m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId); return; } m_currentFrame = m_frames[0]; } m_nextPosition = m_group.AbsolutePosition; m_currentVel = (Vector3)m_currentFrame.Position - m_nextPosition; m_currentVel /= (m_currentFrame.TimeMS * 0.001f); m_currentFrame.TimeMS += (int)tickDuration; m_lasttickMS = nowMS - 50f; update = true; } int elapsed = (int)(nowMS - m_lasttickMS); if (elapsed > 3 * tickDuration) { elapsed = (int)tickDuration; } m_currentFrame.TimeMS -= elapsed; m_lasttickMS = nowMS; // Do the frame processing double remainingSteps = (double)m_currentFrame.TimeMS / tickDuration; if (remainingSteps <= 1.0) { m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.AngularVelocity = Vector3.Zero; m_nextPosition = (Vector3)m_currentFrame.Position; m_group.AbsolutePosition = m_nextPosition; m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; lock (m_frames) { m_frames.RemoveAt(0); if (m_frames.Count > 0) { m_currentFrame = m_frames[0]; m_currentVel = (Vector3)m_currentFrame.Position - m_nextPosition; m_currentVel /= (m_currentFrame.TimeMS * 0.001f); m_group.RootPart.Velocity = m_currentVel; m_currentFrame.TimeMS += (int)tickDuration; } else { m_group.RootPart.Velocity = Vector3.Zero; } } update = true; } else { // bool lastSteps = remainingSteps < 4; Vector3 currentPosition = m_group.AbsolutePosition; Vector3 motionThisFrame = (Vector3)m_currentFrame.Position - currentPosition; motionThisFrame /= (float)remainingSteps; m_nextPosition = currentPosition + motionThisFrame; Quaternion currentRotation = m_group.GroupRotation; if ((Quaternion)m_currentFrame.Rotation != currentRotation) { float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); step.Normalize(); m_group.RootPart.RotationOffset = step; /* * if (Math.Abs(step.X - m_lastRotationUpdate.X) > 0.001f || Math.Abs(step.Y - m_lastRotationUpdate.Y) > 0.001f || Math.Abs(step.Z - m_lastRotationUpdate.Z) > 0.001f) || update = true; */ } m_group.AbsolutePosition = m_nextPosition; // if(lastSteps) // m_group.RootPart.Velocity = Vector3.Zero; // else m_group.RootPart.Velocity = m_currentVel; /* * if(!update && ( * // lastSteps || * m_skippedUpdates * tickDuration > 0.5 || * Math.Abs(m_nextPosition.X - currentPosition.X) > 5f || * Math.Abs(m_nextPosition.Y - currentPosition.Y) > 5f || * Math.Abs(m_nextPosition.Z - currentPosition.Z) > 5f * )) * { * update = true; * } * else * m_skippedUpdates++; */ } // if(update) // { // m_lastPosUpdate = m_nextPosition; // m_lastRotationUpdate = m_group.GroupRotation; // m_skippedUpdates = 0; // m_group.SendGroupRootTerseUpdate(); m_group.RootPart.ScheduleTerseUpdate(); // } }
void Start() { int j = 0; while (queryBlock(j, 0)) { List <UnityAudioBlock> blocks = new List <UnityAudioBlock>(); int k = 0; GameObject audioObjectInstance = Instantiate(objectInstance) as GameObject; audioObjects.Add(audioObjectInstance); while (queryBlock(j, k)) { UnityAudioBlock nextBlock = getBlock(j, k); blocks.Add(nextBlock); GameObject objectPosition = Instantiate(objectPositionInstance) as GameObject; objectPosition.transform.position = new Vector3(nextBlock.x, nextBlock.y, nextBlock.z); k++; } channelFormats.Add(blocks); j++; } for (int y = 0; y < channelFormats.Count; y++) { GameObject audioObject = audioObjects[y]; audioObject.AddComponent <Animation>(); Animation objectAnimation = audioObject.GetComponent <Animation>(); AnimationClip clip = new AnimationClip(); clip.name = Encoding.ASCII.GetString(channelFormats[y][0].name); clip.legacy = true; Keyframe[] xKeys = new Keyframe[channelFormats[y].Count]; Keyframe[] yKeys = new Keyframe[channelFormats[y].Count]; Keyframe[] zKeys = new Keyframe[channelFormats[y].Count]; for (int i = 0; i < channelFormats[y].Count; i++) { xKeys[i] = new Keyframe(channelFormats[y][i].rTime, channelFormats[y][i].x); yKeys[i] = new Keyframe(channelFormats[y][i].rTime, channelFormats[y][i].y); zKeys[i] = new Keyframe(channelFormats[y][i].rTime, channelFormats[y][i].z); } AnimationCurve xCurve = new AnimationCurve(xKeys); clip.SetCurve("", typeof(Transform), "localPosition.x", xCurve); AnimationCurve yCurve = new AnimationCurve(yKeys); clip.SetCurve("", typeof(Transform), "localPosition.y", yCurve); AnimationCurve zCurve = new AnimationCurve(zKeys); clip.SetCurve("", typeof(Transform), "localPosition.z", zCurve); objectAnimation.AddClip(clip, clip.name); objectAnimation.Play(clip.name, PlayMode.StopSameLayer); xCurve.AddKey(new Keyframe(21.0f, 0.0f)); yCurve.AddKey(new Keyframe(21.0f, 10.0f)); zCurve.AddKey(new Keyframe(21.0f, 10.0f)); clip.SetCurve("", typeof(Transform), "localPosition.x", xCurve); clip.SetCurve("", typeof(Transform), "localPosition.y", yCurve); clip.SetCurve("", typeof(Transform), "localPosition.z", zCurve); objectAnimation.PlayQueued(clip.name, QueueMode.PlayNow, PlayMode.StopAll); xCurve.AddKey(new Keyframe(22.0f, 0.0f)); yCurve.AddKey(new Keyframe(22.0f, 0.0f)); zCurve.AddKey(new Keyframe(22.0f, 0.0f)); clip.SetCurve("", typeof(Transform), "localPosition.x", xCurve); clip.SetCurve("", typeof(Transform), "localPosition.y", yCurve); clip.SetCurve("", typeof(Transform), "localPosition.z", zCurve); objectAnimation.PlayQueued(clip.name, QueueMode.PlayNow, PlayMode.StopAll); } }
public void LoadLogToExportAnim() { if (DisplayName == "") { Debug.LogWarning("DisplayName is null"); return; } if (animator == null) { animator = GetComponent <Animator>(); } string humrPath = @"Assets/HUMR"; CreateDirectoryIfNotExist(humrPath); ControllerSetUp(humrPath); string[] files = Directory.GetFiles(OutputLogPath, "*.txt"); string[] strOutputLogLines = File.ReadAllLines(files[index]); int nTargetCounter = 0; List <int> newTargetLines = new List <int>();//ファイルの中での新しく始まった対象の行を格納する newTargetLines.Add(0); List <int> newLogLines = new List <int>();//抽出したログの中で新しく始まった行を格納する newLogLines.Add(0); float beforetime = 0; for (int j = 0; j < strOutputLogLines.Length; j++) { //対象のログの行を抽出 if (strOutputLogLines[j].Contains(strKeyWord + DisplayName)) { if (strOutputLogLines[j].Length > nHeaderStrNum + (strKeyWord + DisplayName).Length) { //記録終わりを検知 string strTmpOLL = strOutputLogLines[j].Substring(nHeaderStrNum + (strKeyWord + DisplayName).Length); for (int k = 0; k < strTmpOLL.Length; k++) { if (strTmpOLL[k] == ',') { float currenttime = float.Parse(strTmpOLL.Substring(0, k)); if (currenttime < beforetime) { newLogLines.Add(nTargetCounter); newTargetLines.Add(j); } beforetime = currenttime; break; } } nTargetCounter++;//目的の行が何行あるか。 } else { Debug.LogWarning("Length is not correct"); } } } newLogLines.Add(nTargetCounter); newTargetLines.Add(strOutputLogLines.Length); // Keyframeの生成 if (nTargetCounter == 0) { Debug.LogWarning("Not exist Motion Data with [" + DisplayName + "] (Did you enter correct DisplayName ? or select correct log ?)"); return; } for (int i = 0; i < newLogLines.Count - 1; i++) { int nLineNum = newLogLines[i + 1] - newLogLines[i]; int nTargetLineNum = newTargetLines[i + 1] - newTargetLines[i]; Keyframe[][] Keyframes = new Keyframe[4 * (HumanTrait.BoneName.Length + 1 /*time + hip position*/) - 1 /*time*/][];//[要素数] for (int j = 0; j < Keyframes.Length; j++) { Keyframes[j] = new Keyframe[nLineNum];//[行数] } //Keyframeにログの値を入れていく { string[] strDisplayNameOutputLogLines = new string[nLineNum];//目的の行の配列 int nTargetLineCounter = 0; beforetime = 0; for (int j = newTargetLines[i]; j < newTargetLines[i + 1]; j++) { //対象のログの行を抽出 if (strOutputLogLines[j].Contains(strKeyWord + DisplayName)) { if (strOutputLogLines[j].Length > nHeaderStrNum + (strKeyWord + DisplayName).Length) { strDisplayNameOutputLogLines[nTargetLineCounter] = strOutputLogLines[j].Substring(nHeaderStrNum + (strKeyWord + DisplayName).Length);//時間,position,rotation,rotation,… for (int k = 0; k < strDisplayNameOutputLogLines[nTargetLineCounter].Length; k++) { if (strDisplayNameOutputLogLines[nTargetLineCounter][k] == ',') { float currenttime = float.Parse(strDisplayNameOutputLogLines[nTargetLineCounter].Substring(0, k)); if (currenttime < beforetime) { Debug.LogAssertion("new record line is contained"); } beforetime = currenttime; break; } } } else { Debug.LogWarning("Log Length is not correct"); } //Debug.Log(DisplayNameOutputLogLines[nTargetLineCounter]); string[] strSplitedOutPutLog = strDisplayNameOutputLogLines[nTargetLineCounter].Split(','); if (strSplitedOutPutLog.Length == 4 * (HumanTrait.BoneName.Length + 1 /*time + hip position*/)) { float key_time = float.Parse(strSplitedOutPutLog[0]); Vector3 rootScale = animator.transform.localScale; Vector3 armatureScale = animator.GetBoneTransform((HumanBodyBones)0).parent.localScale; Vector3 hippos = new Vector3(float.Parse(strSplitedOutPutLog[1]), float.Parse(strSplitedOutPutLog[2]), float.Parse(strSplitedOutPutLog[3])); transform.rotation = Quaternion.identity; //Avatarがrotation(0,0,0)でない可能性があるため hippos = Quaternion.Inverse(animator.GetBoneTransform((HumanBodyBones)0).parent.localRotation) * hippos; //armatureがrotation(0,0,0)でない可能性があるため hippos = new Vector3(hippos.x / rootScale.x / armatureScale.x, hippos.y / rootScale.y / armatureScale.y, hippos.z / rootScale.z / armatureScale.z); //いる Keyframes[0][nTargetLineCounter] = new Keyframe(key_time, hippos.x); Keyframes[1][nTargetLineCounter] = new Keyframe(key_time, hippos.y); Keyframes[2][nTargetLineCounter] = new Keyframe(key_time, hippos.z); Quaternion[] boneWorldRotation = new Quaternion[HumanTrait.BoneName.Length]; for (int k = 0; k < HumanTrait.BoneName.Length; k++) { boneWorldRotation[k] = new Quaternion(float.Parse(strSplitedOutPutLog[k * 4 + 4]), float.Parse(strSplitedOutPutLog[k * 4 + 5]), float.Parse(strSplitedOutPutLog[k * 4 + 6]), float.Parse(strSplitedOutPutLog[k * 4 + 7])); } for (int k = 0; k < HumanTrait.BoneName.Length; k++) { if (animator.GetBoneTransform((HumanBodyBones)k) == null) { continue; } animator.GetBoneTransform((HumanBodyBones)k).rotation = boneWorldRotation[k]; } for (int k = 0; k < HumanTrait.BoneName.Length; k++) { if (animator.GetBoneTransform((HumanBodyBones)k) == null) { continue; } Quaternion localrot = animator.GetBoneTransform((HumanBodyBones)k).localRotation; Keyframes[k * 4 + 3][nTargetLineCounter] = new Keyframe(key_time, localrot.x); Keyframes[k * 4 + 4][nTargetLineCounter] = new Keyframe(key_time, localrot.y); Keyframes[k * 4 + 5][nTargetLineCounter] = new Keyframe(key_time, localrot.z); Keyframes[k * 4 + 6][nTargetLineCounter] = new Keyframe(key_time, localrot.w); } } else { Debug.Log(strSplitedOutPutLog.Length);//228 Debug.LogAssertion("Key value length is not correct"); } nTargetLineCounter++; } } } //AnimationClipにAnimationCurveを設定 AnimationClip clip = new AnimationClip(); { // AnimationCurveの生成 AnimationCurve[] AnimCurves = new AnimationCurve[Keyframes.Length]; for (int l = 0; l < AnimCurves.Length; l++)//[行数-1] { AnimCurves[l] = new AnimationCurve(Keyframes[l]); } // AnimationCurveの追加 clip.SetCurve(GetHierarchyPath(animator.GetBoneTransform((HumanBodyBones)0)), typeof(Transform), "localPosition.x", AnimCurves[0]); clip.SetCurve(GetHierarchyPath(animator.GetBoneTransform((HumanBodyBones)0)), typeof(Transform), "localPosition.y", AnimCurves[1]); clip.SetCurve(GetHierarchyPath(animator.GetBoneTransform((HumanBodyBones)0)), typeof(Transform), "localPosition.z", AnimCurves[2]); for (int m = 0; m < (AnimCurves.Length - 3) / 4; m++)//[骨数] { if (animator.GetBoneTransform((HumanBodyBones)m) == null) { continue; } clip.SetCurve(GetHierarchyPath(animator.GetBoneTransform((HumanBodyBones)m)), typeof(Transform), "localRotation.x", AnimCurves[m * 4 + 3]); clip.SetCurve(GetHierarchyPath(animator.GetBoneTransform((HumanBodyBones)m)), typeof(Transform), "localRotation.y", AnimCurves[m * 4 + 4]); clip.SetCurve(GetHierarchyPath(animator.GetBoneTransform((HumanBodyBones)m)), typeof(Transform), "localRotation.z", AnimCurves[m * 4 + 5]); clip.SetCurve(GetHierarchyPath(animator.GetBoneTransform((HumanBodyBones)m)), typeof(Transform), "localRotation.w", AnimCurves[m * 4 + 6]); } clip.EnsureQuaternionContinuity();//これをしないとQuaternion補間してくれない } //GenericAnimation出力 { string animFolderPath = humrPath + @"/GenericAnimations"; CreateDirectoryIfNotExist(animFolderPath); string displaynameFolderPath = animFolderPath + "/" + DisplayName; CreateDirectoryIfNotExist(displaynameFolderPath); string animationName = files[index].Substring(files[index].Length - 13).Remove(9) + "_" + i.ToString(); string animPath = displaynameFolderPath + "/" + animationName + ".anim"; Debug.Log(animPath); if (ExportGenericAnimation) { if (File.Exists(animPath)) { AssetDatabase.DeleteAsset(animPath); Debug.LogWarning("Same Name Generic Animation is existing. Overwritten!!"); foreach (var layer in controller.layers)//アニメーションを消したことにより空のアニメーションステートが出来てたら削除 { foreach (var state in layer.stateMachine.states) { if (state.state.motion == null) { layer.stateMachine.RemoveState(state.state); } } } } AssetDatabase.CreateAsset(clip, AssetDatabase.GenerateUniqueAssetPath(animPath)); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } } //アニメーションをアバターのアニメーターに入れる { controller.layers[0].stateMachine.AddState(clip.name).motion = clip; } } //FBXとして出力 { animator.runtimeAnimatorController = controller; string exportFolderPath = humrPath + @"/FBXs"; CreateDirectoryIfNotExist(exportFolderPath); string displaynameFBXFolderPath = exportFolderPath + "/" + ValidName(DisplayName); CreateDirectoryIfNotExist(displaynameFBXFolderPath); UnityEditor.Formats.Fbx.Exporter.ModelExporter.ExportObject(displaynameFBXFolderPath + "/" + files[index].Substring(files[index].Length - 13).Remove(9), this.gameObject); } }
public static string Assemble(KeyframeSequence sequence, List <Bone> rig) { StudioMdlWriter animWriter = new StudioMdlWriter(); List <Keyframe> keyframes = new List <Keyframe>(); var boneLookup = new Dictionary <string, Bone>(); var nodes = animWriter.Nodes; foreach (Bone bone in rig) { Node node = bone.Node; if (node != null) { string boneName = node.Name; if (!boneLookup.ContainsKey(boneName)) { boneLookup.Add(boneName, bone); } nodes.Add(node); } } foreach (Keyframe kf in sequence.GetChildrenOfClass <Keyframe>()) { Pose rootPart = kf.FindFirstChild <Pose>("HumanoidRootPart"); if (rootPart != null) { // We don't need the rootpart for this. foreach (Pose subPose in rootPart.GetChildrenOfClass <Pose>()) { subPose.Parent = kf; } rootPart.Destroy(); } kf.Time /= sequence.TimeScale; keyframes.Add(kf); } keyframes.Sort(0, keyframes.Count, sorter); Keyframe lastKeyframe = keyframes[keyframes.Count - 1]; float fLength = lastKeyframe.Time; int frameCount = ToFrameRate(fLength); // As far as I can tell, models in Source require you to store poses for every // single frame, so I need to fill in the gaps with interpolated pose CFrames. var keyframeMap = new Dictionary <int, Dictionary <string, Pose> >(); foreach (Keyframe kf in keyframes) { int frame = ToFrameRate(kf.Time); var poses = GatherPoses(kf); var poseMap = poses.ToDictionary(pose => pose.Name); keyframeMap[frame] = poseMap; } // Make sure there are no holes in the data. for (int i = 0; i < frameCount; i++) { if (!keyframeMap.ContainsKey(i)) { var emptyState = new Dictionary <string, Pose>(); keyframeMap.Add(i, emptyState); } } List <BoneKeyframe> boneKeyframes = animWriter.Skeleton; for (int i = 0; i < frameCount; i++) { BoneKeyframe frame = new BoneKeyframe(i); List <Bone> bones = frame.Bones; if (sequence.AvatarType == AvatarType.R15) { frame.BaseRig = rig; frame.DeltaSequence = true; } foreach (Node node in nodes) { PosePair closestPoses = GetClosestPoses(keyframeMap, i, node.Name); float min = closestPoses.Min.Frame; float max = closestPoses.Max.Frame; float alpha = (min == max ? 0 : (i - min) / (max - min)); Pose pose0 = closestPoses.Min.Pose; Pose pose1 = closestPoses.Max.Pose; CFrame lastCFrame = pose0.CFrame; CFrame nextCFrame = pose1.CFrame; Bone baseBone = boneLookup[node.Name]; CFrame interp = lastCFrame.Lerp(nextCFrame, alpha); // Make some patches to the interpolation offsets. Unfortunately I can't // identify any single fix that I can apply to each joint, so I have to get crafty. // At some point in the future, I want to find a more practical solution for this problem, // but it is extremely difficult to isolate if any single solution exists. if (sequence.AvatarType == AvatarType.R6) { Vector3 pos = interp.Position; CFrame rot = interp - pos; if (node.Name == "Torso") { // Flip the YZ axis of the Torso. float[] ang = interp.ToEulerAnglesXYZ(); rot = CFrame.Angles(ang[0], ang[2], ang[1]); pos = new Vector3(pos.X, pos.Z, pos.Y); } else if (node.Name.StartsWith("Right")) { // X-axis is inverted for the right arm/leg. pos *= new Vector3(-1, 1, 1); } if (node.Name.EndsWith("Arm") || node.Name.EndsWith("Leg")) { // Rotate position offset of the arms & legs 90* counter-clockwise. pos = new Vector3(-pos.Z, pos.Y, pos.X); } if (node.Name != "Head") { rot = rot.Inverse(); } interp = new CFrame(pos) * rot; } else if (sequence.AvatarType == AvatarType.R15) { float[] ang = interp.ToEulerAnglesXYZ(); // Cancel out the rotations interp *= CFrame.Angles(-ang[0], -ang[1], -ang[2]); // Patch the Y-axis PatchAngles(ref interp, 1, ang); // Patch the Z-axis PatchAngles(ref interp, 2, ang); // Patch the X-axis PatchAngles(ref interp, 0, ang); } Bone bone = new Bone(node, interp); bones.Add(bone); } boneKeyframes.Add(frame); } return(animWriter.BuildFile()); }
int KeyframeTimeSort(Keyframe a, Keyframe b) => a.time.CompareTo(b.time);
public override void OnInspectorGUI() { Undo.RecordObject(target, "Look Animator Inspector"); // Update component from last changes serializedObject.Update(); FLookAnimator lookT = (FLookAnimator)target; #region Default Inspector if (drawDefaultInspector) { GUILayout.Space(10f); EditorGUILayout.BeginVertical(FEditor_Styles.GrayBackground); drawDefaultInspector = GUILayout.Toggle(drawDefaultInspector, "Draw default inspector"); #region Exluding from view not needed properties List <string> excludedVars = new List <string>(); if (lookT.BackBonesCount < 1) { excludedVars.Add("BackBonesTransforms"); excludedVars.Add("BackBonesFalloff"); } if (!lookT.AnimateWithSource) { excludedVars.Add("MonitorAnimator"); } if (lookT.CompensationBones == null || lookT.CompensationBones.Count < 1) { excludedVars.Add("CompensationWeight"); } #endregion GUILayout.Space(5f); if (GUILayout.Button("Auto Find Head Bone")) { FindHeadBone(lookT); } EditorGUILayout.EndVertical(); GUILayout.Space(10f); if (lookT.BackBonesCount < 0) { lookT.BackBonesCount = 0; } // Draw default inspector without not needed properties DrawPropertiesExcluding(serializedObject, excludedVars.ToArray()); } else #endregion { EditorGUILayout.BeginVertical(FEditor_Styles.GrayBackground); EditorGUILayout.BeginHorizontal(); drawDefaultInspector = GUILayout.Toggle(drawDefaultInspector, "Default inspector"); GUILayout.FlexibleSpace(); EditorGUIUtility.labelWidth = 80; lookT.drawGizmos = GUILayout.Toggle(lookT.drawGizmos, "Draw Gizmos"); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); GUILayout.Space(5f); EditorGUILayout.BeginVertical(FEditor_Styles.GrayBackground); EditorGUI.indentLevel++; drawMain = EditorGUILayout.Foldout(drawMain, "Main Animation Parameters", true); #region Main tab if (drawMain) { EditorGUILayout.BeginVertical(EditorStyles.helpBox); if (!lookT.ObjectToFollow) { GUILayout.BeginHorizontal(FEditor_Styles.YellowBackground); } else { GUILayout.Space(5f); GUILayout.BeginHorizontal(); } EditorGUIUtility.labelWidth = 133f; EditorGUILayout.PropertyField(sp_tofollow); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (!lookT.LeadBone) { GUILayout.BeginHorizontal(FEditor_Styles.RedBackground); } else { GUILayout.BeginHorizontal(); } EditorGUILayout.PropertyField(sp_leadbone); if (lookT.LeadBone != previousHead) { previousHead = lookT.LeadBone; lookT.UpdateForCustomInspector(); } if (GUILayout.Button(new GUIContent("Auto Find", "By pressing this button, algorithm will go trough hierarchy and try to find object which name includes 'head' or 'neck', be aware, this bone can not be correct but sure it will help you find right one quicker"), new GUILayoutOption[2] { GUILayout.MaxWidth(90), GUILayout.MaxHeight(15) })) { FindHeadBone(lookT); EditorUtility.SetDirty(target); } GUILayout.EndHorizontal(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (lookT.BaseTransform != lookT.transform || !lookT.BaseTransform) { if (!lookT.BaseTransform) { GUILayout.BeginHorizontal(FEditor_Styles.YellowBackground); } else { GUILayout.BeginHorizontal(); } EditorGUILayout.PropertyField(sp_basetr); if (GUILayout.Button("Try Find", new GUILayoutOption[2] { GUILayout.MaxWidth(90), GUILayout.MaxHeight(15) })) { lookT.FindBaseTransform(); EditorUtility.SetDirty(target); } GUILayout.EndHorizontal(); } GUILayout.EndHorizontal(); Color preColor = GUI.color; GUILayout.Space(3f); EditorGUILayout.PropertyField(sp_rotspd); GUILayout.Space(3f); if (lookT.BirdMode) { GUI.color = new Color(1f, 0.88f, 0.88f, 0.95f); } EditorGUILayout.PropertyField(sp_usmooth); GUI.color = preColor; EditorGUILayout.PropertyField(sp_starttpose); if (!lookT.Prevent180Error) { if (lookT.UltraSmoother > 0f) { GUI.color = new Color(1f, 1f, 0.35f, 0.8f); } } GUILayout.Space(2f); EditorGUILayout.PropertyField(sp_180prev); GUI.color = preColor; EditorGUIUtility.labelWidth = 0f; GUILayout.Space(5f); EditorGUILayout.EndVertical(); GUILayout.Space(5f); EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.BeginHorizontal(FEditor_Styles.BlueBackground); EditorGUILayout.HelpBox("Using more bones (back bones) to help rotate head (head-neck-spine)", MessageType.None); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); int preCount = lookT.BackBonesCount; EditorGUIUtility.labelWidth = 130f; EditorGUILayout.LabelField(new GUIContent("Backbones: (" + lookT.BackBonesCount + ")")); EditorGUIUtility.labelWidth = 0f; if (GUILayout.Button("+", new GUILayoutOption[2] { GUILayout.MaxWidth(28), GUILayout.MaxHeight(14) })) { lookT.BackBonesCount++; serializedObject.ApplyModifiedProperties(); if (!UpdateCustomInspector(lookT, false)) { Debug.Log("[LOOK ANIMATOR] Don't change backbones count in playmode"); } EditorUtility.SetDirty(target); } if (GUILayout.Button("-", new GUILayoutOption[2] { GUILayout.MaxWidth(28), GUILayout.MaxHeight(14) })) { lookT.BackBonesCount--; serializedObject.ApplyModifiedProperties(); if (!UpdateCustomInspector(lookT, false)) { Debug.Log("[LOOK ANIMATOR] Don't change backbones count in playmode"); } EditorUtility.SetDirty(target); } GUILayout.EndHorizontal(); if (lookT.BackBonesCount < 0) { lookT.BackBonesCount = 0; } if (preCount != lookT.BackBonesCount) { UpdateCustomInspector(lookT); } if (lookT.BackBonesCount > 0) { drawBackBones = EditorGUILayout.Foldout(drawBackBones, "View back bones", true); if (drawBackBones) { EditorGUI.indentLevel++; EditorGUIUtility.labelWidth = 150f; for (int i = 0; i < lookT.BackBonesTransforms.Length; i++) { string weightString = " " + Mathf.Round(lookT.RotationWeights[i] * 100f * lookT.WeightsMultiplier) + "%"; Transform preTr = lookT.BackBonesTransforms[i]; Transform newTr = (Transform)EditorGUILayout.ObjectField("Back bone [" + i + "]" + weightString, lookT.BackBonesTransforms[i], typeof(Transform), true); // If we assigned own bone if (preTr != newTr) { lookT.BackBonesTransforms[i] = newTr; lookT.AddCustomBackbone(lookT.BackBonesTransforms[i], i); EditorUtility.SetDirty(target); } } EditorGUIUtility.labelWidth = 0f; EditorGUI.indentLevel--; } GUILayout.Space(5f); EditorGUILayout.BeginHorizontal(); EditorGUIUtility.labelWidth = 105f; EditorGUILayout.PropertyField(sp_usecurve); EditorGUIUtility.labelWidth = 0f; if (lookT.CurveSpread) { EditorGUILayout.PropertyField(sp_falloff, new GUIContent(""), new GUILayoutOption[2] { GUILayout.MaxHeight(40f), GUILayout.MinHeight(30f) }); bool curveChanged = false; if (preKeyframes.Length != lookT.BackBonesFalloff.keys.Length) { curveChanged = true; } if (!curveChanged) { for (int i = 0; i < preKeyframes.Length; i++) { Keyframe pre = preKeyframes[i]; Keyframe curr = lookT.BackBonesFalloff.keys[i]; if (pre.value != curr.value || pre.time != curr.time || pre.inTangent != curr.inTangent || pre.outTangent != curr.outTangent) { curveChanged = true; break; } } } if (curveChanged) { if (preKeyframes != lookT.BackBonesFalloff.keys) { preKeyframes = lookT.BackBonesFalloff.keys; UpdateCustomInspector(lookT); EditorUtility.SetDirty(target); } } } else { EditorGUILayout.PropertyField(sp_fallvall, new GUIContent("")); } GUILayout.Space(8f); EditorGUILayout.EndHorizontal(); GUILayout.Space(8f); } EditorGUILayout.EndHorizontal(); GUILayout.Space(5f); UnderMainTab(); #region Limiting angles EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.BeginHorizontal(FEditor_Styles.GrayBackground); drawLimiting = EditorGUILayout.Foldout(drawLimiting, "Limiting & Others Tab", true); GUILayout.EndHorizontal(); if (drawLimiting) { #region Clamping angles bool wrongLimit = false; if (Mathf.Abs(lookT.XRotationLimits.x) > lookT.MaxRotationDiffrence) { wrongLimit = true; } if (Mathf.Abs(lookT.XRotationLimits.y) > lookT.MaxRotationDiffrence) { wrongLimit = true; } Color preCol = GUI.color; GUILayout.Space(4f); GUILayout.BeginVertical(FEditor_Styles.LBlueBackground); if (lookT.MaximumDistance > 0f) { EditorGUILayout.PropertyField(sp_maxdist); } else { GUILayout.BeginHorizontal(); //GUILayout.FlexibleSpace(); //EditorGUIUtility.labelWidth = 80; EditorGUILayout.PropertyField(sp_maxdist); //EditorGUIUtility.labelWidth = 0; EditorGUILayout.LabelField("(Infinity)", new GUILayoutOption[] { GUILayout.Width(70f) }); GUILayout.EndHorizontal(); } GUILayout.Space(4f); EditorGUILayout.PropertyField(sp_MinHeadLookAngle); if (lookT.MaximumDistance < 0f) { lookT.MaximumDistance = 0f; EditorUtility.SetDirty(target); } GUILayout.EndVertical(); GUILayout.Space(4f); if (!wrongLimit) { GUI.color = new Color(0.55f, 0.9f, 0.75f, 0.8f); } else { GUI.color = new Color(0.9f, 0.55f, 0.55f, 0.8f); } // X GUILayout.BeginVertical(FEditor_Styles.Emerald); GUILayout.BeginHorizontal(); GUILayout.Label(" Clamp Angle Horizontal (X)", GUILayout.MaxWidth(170f)); GUILayout.FlexibleSpace(); GUILayout.Label(Mathf.Round(lookT.XRotationLimits.x) + "°", FEditor_Styles.GrayBackground, GUILayout.MaxWidth(40f)); //FEditor_CustomInspectorHelpers.DrawMinMaxSphere(lookT.XRotationLimits.x, lookT.XRotationLimits.y, 14, lookT.XElasticRange); FEditor_CustomInspectorHelpers.DrawMinMaxSphere(lookT.XRotationLimits.x, lookT.XRotationLimits.y, 14, lookT.XElasticRange); GUILayout.Label(Mathf.Round(lookT.XRotationLimits.y) + "°", FEditor_Styles.GrayBackground, GUILayout.MaxWidth(40f)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); EditorGUILayout.MinMaxSlider(ref lookT.XRotationLimits.x, ref lookT.XRotationLimits.y, -180f, 180f); //if (Mathf.Abs(lookT.XRotationLimits.x) > lookT.MaxRotationDiffrence) lookT.MaxRotationDiffrence = Mathf.Abs(lookT.XRotationLimits.x); //if (Mathf.Abs(lookT.XRotationLimits.y) > lookT.MaxRotationDiffrence) lookT.MaxRotationDiffrence = Mathf.Abs(lookT.XRotationLimits.y); bothX = EditorGUILayout.Slider("Adjust symmetrical", bothX, 1f, 180f); EditorGUILayout.PropertyField(sp_elasticX); if (lastBothX != bothX) { lookT.XRotationLimits.x = -bothX; lookT.XRotationLimits.y = bothX; lastBothX = bothX; serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(target); } GUILayout.EndVertical(); GUILayout.Space(7f); GUI.color = new Color(0.6f, 0.75f, 0.9f, 0.8f); // Y GUILayout.BeginVertical(FEditor_Styles.LBlueBackground); GUILayout.BeginHorizontal(); GUILayout.Label(" Clamp Angle Vertical (Y)", GUILayout.MaxWidth(170f)); GUILayout.FlexibleSpace(); GUILayout.Label(Mathf.Round(lookT.YRotationLimits.x) + "°", FEditor_Styles.GrayBackground, GUILayout.MaxWidth(40f)); FEditor_CustomInspectorHelpers.DrawMinMaxVertSphere(-lookT.YRotationLimits.y, -lookT.YRotationLimits.x, 14, lookT.YElasticRange); GUILayout.Label(Mathf.Round(lookT.YRotationLimits.y) + "°", FEditor_Styles.GrayBackground, GUILayout.MaxWidth(40f)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); EditorGUILayout.MinMaxSlider(ref lookT.YRotationLimits.x, ref lookT.YRotationLimits.y, -90f, 90f); bothY = EditorGUILayout.Slider("Adjust symmetrical", bothY, 1f, 90f); EditorGUILayout.PropertyField(sp_elasticY); if (lastBothY != bothY) { lookT.YRotationLimits.x = -bothY; lookT.YRotationLimits.y = bothY; lastBothY = bothY; serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(target); } GUILayout.EndVertical(); #endregion GUI.color = preCol; GUILayout.Space(15f); GUILayout.BeginHorizontal(FEditor_Styles.BlueBackground); EditorGUILayout.HelpBox("If this angle is exceeded character will look forward", MessageType.None); GUILayout.EndHorizontal(); if (!wrongLimit) { GUI.color = new Color(0.55f, 0.9f, 0.75f, 0.8f); } else { GUI.color = new Color(0.9f, 0.55f, 0.55f, 0.8f); } EditorGUILayout.BeginVertical(FEditor_Styles.Emerald); GUILayout.BeginHorizontal(); lookT.MaxRotationDiffrence = EditorGUILayout.Slider("Max Angle Diff", lookT.MaxRotationDiffrence, 25f, 180f); FEditor_CustomInspectorHelpers.DrawMinMaxSphere(-lookT.MaxRotationDiffrence, lookT.MaxRotationDiffrence, 14); GUILayout.EndHorizontal(); lookT.DeltaAccelerationRange = EditorGUILayout.Slider(new GUIContent("Delta Accelerate", "If head have to rotate more than this value it's animation speed for rotating increases, small touch to make animation more realistic"), lookT.DeltaAccelerationRange, 25f, 70f); EditorGUILayout.PropertyField(sp_chretspeed); EditorGUILayout.PropertyField(sp_bigsmooth); GUILayout.Space(8f); EditorGUILayout.EndVertical(); GUI.color = preCol; serializedObject.ApplyModifiedProperties(); } GUILayout.EndVertical(); } #endregion #endregion #region Correcting bones orientations EditorGUI.indentLevel--; EditorGUILayout.BeginVertical(FEditor_Styles.GrayBackground); EditorGUI.indentLevel++; drawCorrecting = EditorGUILayout.Foldout(drawCorrecting, "Correcting rotations", true); if (drawCorrecting) { EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.Space(3f); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(sp_fixpres); EditorGUILayout.BeginVertical(new GUILayoutOption[2] { GUILayout.MaxWidth(28), GUILayout.MaxHeight(20) }); if (GUILayout.Button("▲", new GUILayoutOption[2] { GUILayout.MaxWidth(28), GUILayout.MaxHeight(10) })) { if ((int)lookT.FixingPreset == 0) { lookT.FixingPreset = (FLookAnimator.EFAxisFixOrder)(Enum.GetValues(typeof(FLookAnimator.EFAxisFixOrder)).Length - 1); } else { lookT.FixingPreset--; } EditorUtility.SetDirty(target); } if (GUILayout.Button("▼", new GUILayoutOption[2] { GUILayout.MaxWidth(28), GUILayout.MaxHeight(10) })) { if ((int)lookT.FixingPreset + 1 >= Enum.GetValues(typeof(FLookAnimator.EFAxisFixOrder)).Length) { lookT.FixingPreset = 0; } else { lookT.FixingPreset++; } EditorUtility.SetDirty(target); } EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); GUILayout.Space(3f); if (lookT.FixingPreset == FLookAnimator.EFAxisFixOrder.FullManual) { EditorGUILayout.PropertyField(sp_axesmul); GUILayout.Space(5f); EditorGUILayout.PropertyField(sp_manfromax); EditorGUILayout.PropertyField(sp_mantoax); GUILayout.Space(5f); } if (lookT.FixingPreset == FLookAnimator.EFAxisFixOrder.FromBased) { EditorGUILayout.LabelField("Auto Offset: " + RoundVector(lookT.OffsetAuto)); EditorGUILayout.LabelField("Auto From Axis: " + RoundVector(lookT.FromAuto)); } EditorGUILayout.PropertyField(sp_angoff); EditorGUILayout.PropertyField(sp_backoff); GUILayout.Space(5f); EditorGUILayout.PropertyField(sp_dray); GUILayout.Space(5f); EditorGUILayout.EndVertical(); GUILayout.Space(5f); } EditorGUILayout.EndVertical(); #endregion #region Additional parameters EditorGUI.indentLevel--; EditorGUILayout.BeginVertical(FEditor_Styles.GrayBackground); EditorGUI.indentLevel++; drawAdditional = EditorGUILayout.Foldout(drawAdditional, "Additional controll parameters", true); if (drawAdditional) { EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.Space(5f); EditorGUIUtility.labelWidth = 140; //lookT.BlendToOriginal = EditorGUILayout.Slider(new GUIContent("Animation Blend", "Main blend value for new head look rotations"), lookT.BlendToOriginal, 0f, 1f); EditorGUILayout.PropertyField(sp_blend); EditorGUIUtility.labelWidth = 180; GUILayout.Space(3f); EditorGUILayout.PropertyField(sp_eyespos); EditorGUILayout.PropertyField(sp_ancheyes); if (lookT.AnchorReferencePoint) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(sp_anchrefr); EditorGUI.indentLevel--; } GUILayout.Space(3f); EditorGUIUtility.labelWidth = 140; EditorGUILayout.PropertyField(sp_leadblend); GUILayout.Space(3f); bool wrong = false; if (!animatorDetected) { if (lookT.AnimateWithSource) { wrong = true; } } EditorGUILayout.BeginVertical(FEditor_Styles.GreenBackground); EditorGUIUtility.labelWidth = 160; Color preCol = GUI.color; if (wrong) { EditorGUILayout.HelpBox("Component can't find animator attached to your character, you should untoggle this variable if there isn't any animator working on character's animation", MessageType.Warning); GUI.color = new Color(1f, 1f, 0.35f, 0.8f); } EditorGUILayout.PropertyField(sp_animwithsource); if (lookT.AnimateWithSource) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(sp_monitor); EditorGUI.indentLevel--; } GUI.color = preCol; EditorGUIUtility.labelWidth = 0; EditorGUILayout.EndVertical(); GUILayout.Space(5f); // v1.0.7 - Bird Mode EditorGUILayout.BeginVertical(FEditor_Styles.LBlueBackground); EditorGUIUtility.labelWidth = 160; EditorGUILayout.PropertyField(sp_bird); if (lookT.BirdMode) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(sp_birdlag); EditorGUILayout.PropertyField(sp_birdspd); EditorGUILayout.PropertyField(sp_birdlagprog); EditorGUILayout.PropertyField(sp_birdfreq); EditorGUILayout.PropertyField(sp_birddel); EditorGUILayout.PropertyField(sp_birmaxdist); EditorGUILayout.PropertyField(sp_birddelgospeed); EditorGUI.indentLevel--; } EditorGUIUtility.labelWidth = 0; EditorGUILayout.EndVertical(); GUILayout.Space(5f); EditorGUILayout.EndVertical(); GUILayout.Space(5f); EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.BeginHorizontal(FEditor_Styles.BlueBackground); EditorGUILayout.HelpBox("If you don't want arms to be rotated when spine, bone is rotated by script", MessageType.None); GUILayout.EndHorizontal(); #region Supporting list in custom editor if (lookT.CompensationBones != null) { compensationBonesCount = lookT.CompensationBones.Count; } else { compensationBonesCount = 0; } GUILayout.BeginHorizontal(); compensationBonesCount = EditorGUILayout.IntField("Compensation Bones", compensationBonesCount); if (GUILayout.Button(new GUIContent("Find", "By pressing this button, algorithm will try to find bones with names 'Shoulder', 'Upper Arm' be aware, because you can have other objects inside including this names"), new GUILayoutOption[2] { GUILayout.MaxWidth(58), GUILayout.MaxHeight(14) })) { FindCompensationBones(lookT); } if (GUILayout.Button("+", new GUILayoutOption[2] { GUILayout.MaxWidth(28), GUILayout.MaxHeight(14) })) { serializedObject.ApplyModifiedProperties(); compensationBonesCount++; EditorUtility.SetDirty(target); } if (GUILayout.Button("-", new GUILayoutOption[2] { GUILayout.MaxWidth(28), GUILayout.MaxHeight(14) })) { if (lookT.CompensationBones.Count == 1) { lookT.CompensationBones = new List <Transform>(); compensationBonesCount = 0; //lookT.BackBonesCount = 0; } else { compensationBonesCount--; } serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(target); } GUILayout.EndHorizontal(); if (compensationBonesCount <= 0) { compensationBonesCount = 0; } else { if (compensationBonesCount > lookT.CompensationBones.Count) { for (int i = lookT.CompensationBones.Count; i < compensationBonesCount; i++) { lookT.CompensationBones.Add(null); } } else if (compensationBonesCount < lookT.CompensationBones.Count) { for (int i = lookT.CompensationBones.Count - 1; i >= compensationBonesCount; i--) { lookT.CompensationBones.RemoveAt(i); } } if (lookT.CompensationBones.Count > 0) { EditorGUI.indentLevel++; for (int i = 0; i < lookT.CompensationBones.Count; i++) { lookT.CompensationBones[i] = (Transform)EditorGUILayout.ObjectField("Bone [" + i + "]", lookT.CompensationBones[i], typeof(Transform), true); } EditorGUI.indentLevel--; GUILayout.Space(5f); EditorGUILayout.PropertyField(sp_compensblend); EditorGUILayout.PropertyField(sp_poscompens); } } #endregion EditorGUILayout.EndVertical(); GUILayout.Space(5f); } EditorGUILayout.EndVertical(); #endregion #region Optional parameters EditorGUI.indentLevel--; EditorGUILayout.BeginVertical(FEditor_Styles.GrayBackground); EditorGUI.indentLevel++; drawOptional = EditorGUILayout.Foldout(drawOptional, "Optional parameters", true); if (drawOptional) { EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.Space(10f); EditorGUILayout.PropertyField(sp_weighmul); GUILayout.Space(3f); GUILayout.BeginHorizontal(); EditorGUILayout.HelpBox("If animation is not animating some head bones (very rare case)", MessageType.None); GUILayout.EndHorizontal(); EditorGUILayout.PropertyField(sp_bonesnotanim); EditorGUILayout.PropertyField(sp_animphys); GUILayout.Space(5f); EditorGUILayout.EndVertical(); GUILayout.Space(5f); } EditorGUILayout.EndVertical(); #endregion EditorGUILayout.EndVertical(); } // Apply changed parameters variables serializedObject.ApplyModifiedProperties(); }
/// <summary> /// Comparison function for sorting keyframes into ascending time order. /// </summary> /// <param name="a"> /// The a. /// </param> /// <param name="b"> /// The b. /// </param> /// <returns> /// The compare keyframe times. /// </returns> private static int CompareKeyframeTimes(Keyframe a, Keyframe b) { return(a.Time.CompareTo(b.Time)); }
public override void OnInspectorGUI() { EditorGUILayout.Space(); Rect weightCurveRect = GUILayoutUtility.GetAspectRect(2.0f); Color previousGUIColor = GUI.color; GUI.color = Color.black; GUI.DrawTexture( new Rect( weightCurveRect.x - 1.0f, weightCurveRect.y - 1.0f, weightCurveRect.width + 2.0f, weightCurveRect.height + 2.0f), this.lineTexture); GUI.color = Color.grey; GUI.Box(weightCurveRect, ""); GUI.color = previousGUIColor; string error = null; if (this.targets.Length <= 1) { Effect targetEffect = (Effect)this.target; if (targetEffect.Duration != 0.0f) { Keyframe[] weightCurveKeyframes = new Keyframe[(int)(weightCurveRect.width * 0.4f)]; for (int i = 0; i < weightCurveKeyframes.Length; ++i) { float time = targetEffect.SimulatedTime - targetEffect.Duration + (i / (float)weightCurveKeyframes.Length) * targetEffect.Duration * 2.0f; weightCurveKeyframes[i] = new Keyframe(time, targetEffect.CalculateWeight(time)); } for (int i = 0; i < weightCurveKeyframes.Length - 1; ++i) { weightCurveKeyframes[i].outTangent = (weightCurveKeyframes[i + 1].value - weightCurveKeyframes[i].value) / (weightCurveKeyframes[i + 1].time - weightCurveKeyframes[i].time); weightCurveKeyframes[i + 1].inTangent = (weightCurveKeyframes[i].value - weightCurveKeyframes[i + 1].value) / (weightCurveKeyframes[i].time - weightCurveKeyframes[i + 1].time); } AnimationCurve weightCurve = new AnimationCurve(weightCurveKeyframes); EditorGUIUtility.DrawRegionSwatch( weightCurveRect, weightCurve, AnimationCurve.Linear( targetEffect.SimulatedTime - targetEffect.Duration, 0.0f, targetEffect.SimulatedTime + targetEffect.Duration, 0.0f), Color.cyan, Color.grey, new Rect( targetEffect.SimulatedTime - targetEffect.Duration, -MAX_WEIGHT, targetEffect.Duration * 2.0f, MAX_WEIGHT * 2.0f)); GUI.color = new Color(0.0f, 0.0f, 0.0f, 0.3f); float topLineY = weightCurveRect.y + weightCurveRect.height * ((MAX_WEIGHT - 1.0f) / (MAX_WEIGHT * 2.0f)); // Top Line GUI.DrawTexture( new Rect( weightCurveRect.x, topLineY, weightCurveRect.width, 1.0f), this.lineTexture); float bottomLineY = weightCurveRect.y + weightCurveRect.height * ((2.0f + MAX_WEIGHT - 1.0f) / (MAX_WEIGHT * 2.0f)); // Bottom Line GUI.DrawTexture( new Rect( weightCurveRect.x, bottomLineY, weightCurveRect.width, 1.0f), this.lineTexture); GUI.color = new Color(0.0f, 0.0f, 0.0f, 1.0f); // Middle Horizontal Line float middleLineThickness = 1.0f + (weightCurveRect.height % 2.0f == 1.0f ? 0.0f : 1.0f); GUI.DrawTexture( new Rect( weightCurveRect.x, weightCurveRect.y + weightCurveRect.height * 0.5f - (int)(middleLineThickness / 2.0f), weightCurveRect.width, middleLineThickness), this.lineTexture); //Middle Vertical Line middleLineThickness = 1.0f + (weightCurveRect.width % 2.0f == 1.0f ? 0.0f : 1.0f); GUI.DrawTexture( new Rect( weightCurveRect.x + weightCurveRect.width * 0.5f - (int)(middleLineThickness / 2.0f), weightCurveRect.y, middleLineThickness, weightCurveRect.height), this.lineTexture); if (targetEffect.IsSleeping) { GUI.color = new Color(1.0f, 0.3f, 0.3f, 0.6f); // Time Text GUI.Box( new Rect( weightCurveRect.x + weightCurveRect.width - 5.0f - 40.0f, bottomLineY - 5.0f - 20.0f, 40.0f, 20.0f), "Zzz"); } GUI.color = new Color(0.0f, 0.0f, 0.0f, 0.5f); // Time Text EditorGUI.LabelField( new Rect( weightCurveRect.x + 5.0f, topLineY + 5.0f, 95.0f, 16.0f), "Time: " + targetEffect.SimulatedTime.ToString("0.00")); // Weight Text EditorGUI.LabelField( new Rect( weightCurveRect.x + 5.0f, topLineY + 21.0f, 95.0f, 16.0f), "Weight: " + targetEffect.CalculateWeight().ToString("0.00")); } else { error = "zero duration"; } } else { error = "multiple objects selected"; } if (error != null) { if (this.errorStyle == null) { this.errorStyle = new GUIStyle(GUI.skin.label); this.errorStyle.alignment = TextAnchor.MiddleCenter; } GUI.color = Color.black; this.errorStyle.fontSize = 72; EditorGUI.LabelField(weightCurveRect, "X", this.errorStyle); GUI.color = new Color(1.0f, 1.0f, 1.0f, 0.5f); this.errorStyle.fontSize = 16; EditorGUI.LabelField( new Rect( weightCurveRect.x, weightCurveRect.y + weightCurveRect.height * 0.5f, weightCurveRect.width, weightCurveRect.height * 0.5f), error, this.errorStyle); } EditorGUILayout.Space(); GUI.color = previousGUIColor; base.OnInspectorGUI(); }
public void DeserializeBeforeRef(UABUnpacker unpacker, UABField field, ref object value, List <ISerializer> serializers) { var keyFrame = new Keyframe(); value = unpacker.Deserialize(keyFrame, field.fields, serializers); }
public static Vector3[] SmoothLine(Vector3[] inputPoints, float segmentSize) { //create curves AnimationCurve curveX = new AnimationCurve(); AnimationCurve curveY = new AnimationCurve(); AnimationCurve curveZ = new AnimationCurve(); //create keyframe sets Keyframe[] keysX = new Keyframe[inputPoints.Length]; Keyframe[] keysY = new Keyframe[inputPoints.Length]; Keyframe[] keysZ = new Keyframe[inputPoints.Length]; //set keyframes for (int i = 0; i < inputPoints.Length; i++) { keysX[i] = new Keyframe(i, inputPoints[i].x); keysY[i] = new Keyframe(i, inputPoints[i].y); keysZ[i] = new Keyframe(i, inputPoints[i].z); } //apply keyframes to curves curveX.keys = keysX; curveY.keys = keysY; curveZ.keys = keysZ; //smooth curve tangents for (int i = 0; i < inputPoints.Length; i++) { curveX.SmoothTangents(i, 0); curveY.SmoothTangents(i, 0); curveZ.SmoothTangents(i, 0); } //list to write smoothed values to List <Vector3> lineSegments = new List <Vector3>(); //find segments in each section for (int i = 0; i < inputPoints.Length; i++) { //add first point lineSegments.Add(inputPoints[i]); //make sure within range of array if (i + 1 < inputPoints.Length) { //find distance to next point float distanceToNext = Vector3.Distance(inputPoints[i], inputPoints[i + 1]); //number of segments int segments = (int)(distanceToNext / segmentSize); //add segments for (int s = 1; s < segments; s++) { //interpolated time on curve float time = ((float)s / (float)segments) + (float)i; //sample curves to find smoothed position Vector3 newSegment = new Vector3(curveX.Evaluate(time), curveY.Evaluate(time), curveZ.Evaluate(time)); //add to list lineSegments.Add(newSegment); } } } return(lineSegments.ToArray()); }
public override GradientColor GetValue(Keyframe <GradientColor> keyframe, float keyframeProgress) { _gradientColor.Lerp(keyframe.StartValue, keyframe.EndValue, keyframeProgress); return(_gradientColor); }
internal static void SetKeyBroken(ref Keyframe key, bool broken) { Internal_SetKeyBroken(ref key, broken); }
private void SetConstantCurve(CurveWrapper cw, float constantValue) { Keyframe[] keyframeArray = new Keyframe[1]; keyframeArray[0].time = 0f; keyframeArray[0].value = constantValue; cw.curve.keys = keyframeArray; cw.changed = true; }
extern private static void Internal_SetKeyBroken(ref Keyframe key, bool broken);
bool GetKeyBroken(Keyframe key) { return((key.tangentMode & kBrokenMask) != 0); }
float CalculateLinearTangent(Keyframe from, Keyframe to) { return((from.value - to.value) / (from.time - to.time)); }
//! //! sets the keyframe at the current time of the animation to a new value for the currently animated object //! automatically adds keyframe if there is none at this time of the animation //! public void setKeyframe() { bool movedSuccessfully = false; int keyIndex = -1; //x value Keyframe key = new Keyframe(animationController.currentAnimationTime, this.transform.position.x); for (int i = 0; i < this.transCurves[0].length; i++) { if (Mathf.Abs(this.transCurves[0].keys[i].time - animationController.currentAnimationTime) < 0.04) { this.transCurves[0].MoveKey(i, key); keyIndex = i; movedSuccessfully = true; } } if (!movedSuccessfully) { keyIndex = this.transCurves[0].AddKey(key); movedSuccessfully = false; } if (transCurves[0].keys.Length > 1) { if (keyIndex == 0) { this.transCurves[0].SmoothTangents(1, 0); } if (keyIndex == transCurves[0].keys.Length - 1) { this.transCurves[0].SmoothTangents(transCurves[0].keys.Length - 2, 0); } } this.transCurves[0].SmoothTangents(keyIndex, 0); //y value key = new Keyframe(animationController.currentAnimationTime, this.transform.position.y); for (int i = 0; i < this.transCurves[1].length; i++) { if (Mathf.Abs(this.transCurves[1].keys[i].time - animationController.currentAnimationTime) < 0.04) { this.transCurves[1].MoveKey(i, key); keyIndex = i; movedSuccessfully = true; } } if (!movedSuccessfully) { keyIndex = this.transCurves[1].AddKey(key); movedSuccessfully = false; } if (transCurves[1].keys.Length > 1) { if (keyIndex == 0) { this.transCurves[1].SmoothTangents(1, 0); } if (keyIndex == transCurves[1].keys.Length - 1) { this.transCurves[1].SmoothTangents(transCurves[1].keys.Length - 2, 0); } } this.transCurves[1].SmoothTangents(keyIndex, 0); //z value key = new Keyframe(animationController.currentAnimationTime, this.transform.position.z); for (int i = 0; i < this.transCurves[2].length; i++) { if (Mathf.Abs(this.transCurves[2].keys[i].time - animationController.currentAnimationTime) < 0.04) { this.transCurves[2].MoveKey(i, key); keyIndex = i; movedSuccessfully = true; } } if (!movedSuccessfully) { keyIndex = this.transCurves[2].AddKey(key); movedSuccessfully = false; } if (transCurves[2].keys.Length > 1) { if (keyIndex == 0) { this.transCurves[2].SmoothTangents(1, 0); } if (keyIndex == transCurves[2].keys.Length - 1) { this.transCurves[2].SmoothTangents(transCurves[2].keys.Length - 2, 0); } } this.transCurves[2].SmoothTangents(keyIndex, 0); animData.changeAnimationCurve(animData.getAnimationClips(target.gameObject)[0], typeof(Transform), "m_LocalPosition.x", transCurves[0]); animData.changeAnimationCurve(animData.getAnimationClips(target.gameObject)[0], typeof(Transform), "m_LocalPosition.y", transCurves[1]); animData.changeAnimationCurve(animData.getAnimationClips(target.gameObject)[0], typeof(Transform), "m_LocalPosition.z", transCurves[2]); updateAnimationCurves(); }
internal static void SetKeyRightTangentMode(ref Keyframe key, TangentMode tangentMode) { Internal_SetKeyRightTangentMode(ref key, tangentMode); }
public void AddTangentMenuItems(GenericMenu menu, List <KeyIdentifier> keyList) { bool flag = keyList.Count > 0; bool on = flag; bool on2 = flag; bool on3 = flag; bool on4 = flag; bool flag2 = flag; bool flag3 = flag; bool flag4 = flag; bool flag5 = flag; bool flag6 = flag; bool flag7 = flag; foreach (KeyIdentifier current in keyList) { Keyframe keyframe = current.keyframe; TangentMode keyTangentMode = CurveUtility.GetKeyTangentMode(keyframe, 0); TangentMode keyTangentMode2 = CurveUtility.GetKeyTangentMode(keyframe, 1); bool keyBroken = CurveUtility.GetKeyBroken(keyframe); if (keyTangentMode != TangentMode.Smooth || keyTangentMode2 != TangentMode.Smooth) { on = false; } if (keyBroken || keyTangentMode != TangentMode.Editable || keyTangentMode2 != TangentMode.Editable) { on2 = false; } if (keyBroken || keyTangentMode != TangentMode.Editable || keyframe.inTangent != 0f || keyTangentMode2 != TangentMode.Editable || keyframe.outTangent != 0f) { on3 = false; } if (!keyBroken) { on4 = false; } if (!keyBroken || keyTangentMode != TangentMode.Editable) { flag2 = false; } if (!keyBroken || keyTangentMode != TangentMode.Linear) { flag3 = false; } if (!keyBroken || keyTangentMode != TangentMode.Stepped) { flag4 = false; } if (!keyBroken || keyTangentMode2 != TangentMode.Editable) { flag5 = false; } if (!keyBroken || keyTangentMode2 != TangentMode.Linear) { flag6 = false; } if (!keyBroken || keyTangentMode2 != TangentMode.Stepped) { flag7 = false; } } if (flag) { menu.AddItem(EditorGUIUtility.TextContent("Auto"), on, new GenericMenu.MenuFunction2(this.SetSmooth), keyList); menu.AddItem(EditorGUIUtility.TextContent("Free Smooth"), on2, new GenericMenu.MenuFunction2(this.SetEditable), keyList); menu.AddItem(EditorGUIUtility.TextContent("Flat"), on3, new GenericMenu.MenuFunction2(this.SetFlat), keyList); menu.AddItem(EditorGUIUtility.TextContent("Broken"), on4, new GenericMenu.MenuFunction2(this.SetBroken), keyList); menu.AddSeparator(string.Empty); menu.AddItem(EditorGUIUtility.TextContent("Left Tangent/Free"), flag2, new GenericMenu.MenuFunction2(this.SetLeftEditable), keyList); menu.AddItem(EditorGUIUtility.TextContent("Left Tangent/Linear"), flag3, new GenericMenu.MenuFunction2(this.SetLeftLinear), keyList); menu.AddItem(EditorGUIUtility.TextContent("Left Tangent/Constant"), flag4, new GenericMenu.MenuFunction2(this.SetLeftConstant), keyList); menu.AddItem(EditorGUIUtility.TextContent("Right Tangent/Free"), flag5, new GenericMenu.MenuFunction2(this.SetRightEditable), keyList); menu.AddItem(EditorGUIUtility.TextContent("Right Tangent/Linear"), flag6, new GenericMenu.MenuFunction2(this.SetRightLinear), keyList); menu.AddItem(EditorGUIUtility.TextContent("Right Tangent/Constant"), flag7, new GenericMenu.MenuFunction2(this.SetRightConstant), keyList); menu.AddItem(EditorGUIUtility.TextContent("Both Tangents/Free"), flag5 && flag2, new GenericMenu.MenuFunction2(this.SetBothEditable), keyList); menu.AddItem(EditorGUIUtility.TextContent("Both Tangents/Linear"), flag6 && flag3, new GenericMenu.MenuFunction2(this.SetBothLinear), keyList); menu.AddItem(EditorGUIUtility.TextContent("Both Tangents/Constant"), flag7 && flag4, new GenericMenu.MenuFunction2(this.SetBothConstant), keyList); } else { menu.AddDisabledItem(EditorGUIUtility.TextContent("Auto")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Free Smooth")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Flat")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Broken")); menu.AddSeparator(string.Empty); menu.AddDisabledItem(EditorGUIUtility.TextContent("Left Tangent/Free")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Left Tangent/Linear")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Left Tangent/Constant")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Right Tangent/Free")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Right Tangent/Linear")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Right Tangent/Constant")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Both Tangents/Free")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Both Tangents/Linear")); menu.AddDisabledItem(EditorGUIUtility.TextContent("Both Tangents/Constant")); } }
extern private static bool Internal_GetKeyBroken(Keyframe key);
public static string FromKeyframe(Keyframe k) { return(FromKeyFrameImpl(k).ToString()); }
extern private static TangentMode Internal_GetKeyRightTangentMode(Keyframe key);
/// <summary> /// beginObject will already be called on the keyframe so it can be differentiated with /// a non animated value. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="composition"></param> /// <param name="reader"></param> /// <param name="scale"></param> /// <param name="valueParser"></param> /// <returns></returns> private static Keyframe <T> ParseKeyframe <T>(LottieComposition composition, JsonReader reader, float scale, IValueParser <T> valueParser) { Vector2? cp1 = null; Vector2? cp2 = null; float startFrame = 0; T startValue = default(T); T endValue = default(T); bool hold = false; IInterpolator interpolator; // Only used by PathKeyframe Vector2?pathCp1 = null; Vector2?pathCp2 = null; reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "t": startFrame = reader.NextDouble(); break; case "s": startValue = valueParser.Parse(reader, scale); break; case "e": endValue = valueParser.Parse(reader, scale); break; case "o": cp1 = JsonUtils.JsonToPoint(reader, scale); break; case "i": cp2 = JsonUtils.JsonToPoint(reader, scale); break; case "h": hold = reader.NextInt() == 1; break; case "to": pathCp1 = JsonUtils.JsonToPoint(reader, scale); break; case "ti": pathCp2 = JsonUtils.JsonToPoint(reader, scale); break; default: reader.SkipValue(); break; } } reader.EndObject(); if (hold) { endValue = startValue; // TODO: create a HoldInterpolator so progress changes don't invalidate. interpolator = LinearInterpolator; } else if (cp1 != null && cp2 != null) { cp1 = new Vector2(MiscUtils.Clamp(cp1.Value.X, -scale, scale), MiscUtils.Clamp(cp1.Value.Y, -MaxCpValue, MaxCpValue)); cp2 = new Vector2(MiscUtils.Clamp(cp2.Value.X, -scale, scale), MiscUtils.Clamp(cp2.Value.Y, -MaxCpValue, MaxCpValue)); int hash = Utils.Utils.HashFor(cp1.Value.X, cp1.Value.Y, cp2.Value.X, cp2.Value.Y); if (GetInterpolator(hash, out var interpolatorRef) == false || interpolatorRef.TryGetTarget(out interpolator) == false) { interpolator = new PathInterpolator(cp1.Value.X / scale, cp1.Value.Y / scale, cp2.Value.X / scale, cp2.Value.Y / scale); try { PutInterpolator(hash, new WeakReference <IInterpolator>(interpolator)); } catch { // It is not clear why but SparseArrayCompat sometimes fails with this: // https://github.com/airbnb/lottie-android/issues/452 // Because this is not a critical operation, we can safely just ignore it. // I was unable to repro this to attempt a proper fix. } } } else { interpolator = LinearInterpolator; } var keyframe = new Keyframe <T>(composition, startValue, endValue, interpolator, startFrame, null) { PathCp1 = pathCp1, PathCp2 = pathCp2 }; return(keyframe); }
internal static bool GetKeyBroken(Keyframe key) { return(Internal_GetKeyBroken(key)); }
//private static GameObject go; public static void Draw(InAudioNode node) { if (Application.isPlaying) { EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Play Node")) { var link = node.GetBank(); if (link != null && link.IsLoaded) { if (preview != null) { preview.Stop(); } preview = InAudio.Play(InAudioInstanceFinder.Instance.gameObject, node); preview.SpatialBlend = 0.0f; preview.OnCompleted = (go, audioNode) => preview = null; } else { Debug.Log("InAudio: Cannot preview node as its beloning bank is not loaded"); } } if (GUILayout.Button("Stop Playing Node") && preview != null) { InAudio.StopAll(InAudioInstanceFinder.Instance.gameObject); } if (GUILayout.Button("Stop All Instances")) { InAudio.StopAllOfNode(node); } EditorGUILayout.EndHorizontal(); } InAudioNodeData baseData = (InAudioNodeData)node._nodeData; EditorGUILayout.Separator(); DrawSelectedArea(node, baseData); Seperators(2); if (baseData.SelectedArea == 0) { EditorGUIHelper.DrawID(node._guid); #region Volume DataDrawerHelper.DrawVolume(baseData, ref baseData.MinVolume, ref baseData.MaxVolume, ref baseData.RandomVolume); #endregion Seperators(2); #region Parent pitch SetPitch(baseData); #endregion Seperators(2); #region Spatial blend SetSpatialBlend(baseData); #endregion Seperators(2); #region Delay GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); InUndoHelper.GUIUndo(baseData, "Randomize Delay", ref baseData.RandomizeDelay, () => EditorGUILayout.Toggle("Randomize Delay", baseData.RandomizeDelay)); if (baseData.RandomizeDelay) { InUndoHelper.GUIUndo(baseData, "Delay Change", ref baseData.InitialDelayMin, ref baseData.InitialDelayMax, (out float v1, out float v2) => { v1 = Mathf.Clamp(EditorGUILayout.FloatField("Min delay", baseData.InitialDelayMin), 0, baseData.InitialDelayMax); v2 = Mathf.Clamp(EditorGUILayout.FloatField("Max delay", baseData.InitialDelayMax), baseData.InitialDelayMin, float.MaxValue); }); } else { InUndoHelper.GUIUndo(baseData, "Delay", ref baseData.InitialDelayMin, () => { float delay = Mathf.Max(EditorGUILayout.FloatField("Initial delay", baseData.InitialDelayMin), 0); if (delay > baseData.InitialDelayMax) { baseData.InitialDelayMax = baseData.InitialDelayMin + 0.001f; } return(delay); }); } GUILayout.EndVertical(); GUILayout.BeginVertical(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); #endregion Seperators(2); #region Audio bus DataDrawerHelper.DrawMixer(node); #endregion Seperators(2); #region Loops GUI.enabled = true; GUILayout.BeginVertical(); InUndoHelper.GUIUndo(baseData, "Use looping", ref baseData.Loop, () => EditorGUILayout.Toggle("Loop", baseData.Loop)); if (baseData.Loop) { GUI.enabled = baseData.Loop; InUndoHelper.GUIUndo(baseData, "Loop Infinite", ref baseData.LoopInfinite, () => EditorGUILayout.Toggle("Loop Infinite", baseData.LoopInfinite)); if (baseData.Loop) { GUI.enabled = !baseData.LoopInfinite; } InUndoHelper.GUIUndo(baseData, "Loop Randomize", ref baseData.RandomizeLoops, () => EditorGUILayout.Toggle("Randomize Loop Count", baseData.RandomizeLoops)); if (!baseData.RandomizeLoops) { InUndoHelper.GUIUndo(baseData, "Loop Count", ref baseData.MinIterations, () => (byte)Mathf.Clamp(EditorGUILayout.IntField("Loop Count", baseData.MinIterations), 0, 255)); } else { GUILayout.BeginHorizontal(); InUndoHelper.GUIUndo(baseData, "Loop Count", ref baseData.MinIterations, ref baseData.MaxIterations, (out byte v1, out byte v2) => { v1 = (byte)Mathf.Clamp(EditorGUILayout.IntField("Min Loop Count", baseData.MinIterations), 0, 255); v2 = (byte)Mathf.Clamp(EditorGUILayout.IntField("Max Loop Count", baseData.MaxIterations), 0, 255); //Clamp to 0-255 and so that min/max doesn't overlap v2 = (byte)Mathf.Clamp(v2, v1, 255); v1 = (byte)Mathf.Clamp(v1, 0, v2); }); GUILayout.EndHorizontal(); } } GUI.enabled = true; GUILayout.EndVertical(); #endregion Seperators(2); #region Instance limiting InUndoHelper.GUIUndo(baseData, "Limit Instances (Global)", ref baseData.LimitInstances, () => EditorGUILayout.Toggle("Limit Instances", baseData.LimitInstances)); GUI.enabled = baseData.LimitInstances; if (baseData.LimitInstances) { InUndoHelper.GUIUndo(baseData, "Max Instance Cont", ref baseData.MaxInstances, () => Math.Max(EditorGUILayout.IntField("Max Instance Count", baseData.MaxInstances), 0)); InUndoHelper.GUIUndo(baseData, "Stealing Type", ref baseData.InstanceStealingTypes, () => (InstanceStealingTypes)EditorGUILayout.EnumPopup("Stealing Type", baseData.InstanceStealingTypes)); } GUI.enabled = true; #endregion Seperators(2); #region Priority InUndoHelper.GUIUndo(baseData, "Priority", ref baseData.Priority, () => EditorGUILayout.IntSlider("Priority", baseData.Priority, 0, 255)); #endregion Seperators(2); #region Sample offset InUndoHelper.GUIUndo(baseData, "Random Second Offset", ref baseData.RandomSecondsOffset, () => EditorGUILayout.Toggle("Random Second Offset", baseData.RandomSecondsOffset)); if (baseData.RandomSecondsOffset) { InUndoHelper.GUIUndo(baseData, "First item offset", ref baseData.MinSecondsOffset, ref baseData.MaxSecondsOffset, (out float v1, out float v2) => { v1 = Mathf.Clamp(EditorGUILayout.FloatField("Min offset", baseData.MinSecondsOffset), 0, baseData.MaxSecondsOffset); v2 = Mathf.Clamp(EditorGUILayout.FloatField("Max offset", baseData.MaxSecondsOffset), baseData.MinSecondsOffset, float.MaxValue); }); } else { InUndoHelper.GUIUndo(baseData, "Delay", ref baseData.MinSecondsOffset, () => { var delay = Mathf.Max(EditorGUILayout.FloatField("First clip offset", baseData.MinSecondsOffset), 0); if (delay > baseData.MaxSecondsOffset) { baseData.MaxSecondsOffset = baseData.MinSecondsOffset + 1; } return(delay); }); } if (node._type == AudioNodeType.Audio) { var nodeData = node._nodeData as InAudioData; if (nodeData._clip != null) { float length = nodeData._clip.ExactLength(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Clip length"); EditorGUILayout.SelectableLabel(length.ToString(), GUILayout.Height(EditorGUIUtility.singleLineHeight)); EditorGUILayout.EndHorizontal(); if (baseData.RandomSecondsOffset && (baseData.MinSecondsOffset > length || baseData.MaxSecondsOffset > length)) { EditorGUILayout.HelpBox("Offset exceeds sound clip length", MessageType.Warning); } else if (baseData.MinSecondsOffset > length) { EditorGUILayout.HelpBox("Offset exceeds sound clip length", MessageType.Warning); } } } #endregion } else { #region Attenuation if (!node._parent.IsRootOrFolder) { InUndoHelper.GUIUndo(baseData, "Override Parent", ref baseData.OverrideAttenuation, () => GUILayout.Toggle(baseData.OverrideAttenuation, "Override Parent")); } GUI.enabled = baseData.OverrideAttenuation; if (node._parent.IsRootOrFolder) { GUI.enabled = true; } InUndoHelper.GUIUndo(node, "Rolloff Mode", ref baseData.RolloffMode, () => (AudioRolloffMode)EditorGUILayout.EnumPopup("Volume Rolloff", baseData.RolloffMode)); InUndoHelper.GUIUndo(baseData, "Set Rolloff Distance", ref baseData.MinDistance, ref baseData.MaxDistance, (out float v1, out float v2) => { if (baseData.RolloffMode != AudioRolloffMode.Custom) { v1 = EditorGUILayout.FloatField("Min Distance", baseData.MinDistance); } else { v1 = baseData.MinDistance; } v2 = EditorGUILayout.FloatField("Max Distance", baseData.MaxDistance); v1 = Mathf.Max(v1, 0.00001f); v2 = Mathf.Max(v2, v1 + 0.01f); }); if (baseData.RolloffMode == AudioRolloffMode.Custom) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Rolloff"); InUndoHelper.GUIUndo(baseData, "Set Rolloff Curve", ref baseData.FalloffCurve, () => EditorGUILayout.CurveField(baseData.FalloffCurve, GUILayout.Height(200), GUILayout.Width(200))); //baseData.FalloffCurve = EditorGUILayout.CurveField(baseData.FalloffCurve, GUILayout.Height(200), GUILayout.Width(200)); EditorGUILayout.EndHorizontal(); var keys = baseData.FalloffCurve.keys; int keyCount = keys.Length; for (int i = 0; i < keyCount; i++) { Keyframe key = keys[i]; key.time = Mathf.Clamp01(key.time); key.value = Mathf.Clamp01(key.value); try { baseData.FalloffCurve.MoveKey(i, key); } catch (Exception) { } } if (GUILayout.Button("Reset curve", GUILayout.Width(150))) { InUndoHelper.RecordObject(baseData, "Reset Curve"); baseData.FalloffCurve = new AnimationCurve(new Keyframe(0, 1), new Keyframe(0.1f, 1), new Keyframe(1, 0)); } if (Selection.activeObject == null) { EditorGUILayout.HelpBox("Please select any game object in the scene.\nIt fixes a bug in Unity Editor API", MessageType.Info, true); } EditorGUILayout.HelpBox("Unity does not support setting custom rolloff via scripts. This will perform slower than a log/linear rolloff curve", MessageType.Warning, true); GUI.enabled = false; } #endregion GUI.enabled = true; } }
internal static TangentMode GetKeyRightTangentMode(Keyframe key) { return(Internal_GetKeyRightTangentMode(key)); }
public static AnimationClip CreateDefaultPose(RigBuilder rigBuilder) { if (rigBuilder == null) { throw new ArgumentNullException("It is not possible to bake curves without an RigBuilder."); } var defaultPoseClip = new AnimationClip() { name = "DefaultPose" }; if (!AnimationMode.InAnimationMode()) { return(defaultPoseClip); } var bindings = new List <EditorCurveBinding>(); var gameObjects = new Queue <GameObject>(); gameObjects.Enqueue(rigBuilder.gameObject); while (gameObjects.Count > 0) { var gameObject = gameObjects.Dequeue(); EditorCurveBinding[] allBindings = AnimationUtility.GetAnimatableBindings(gameObject, rigBuilder.gameObject); foreach (var binding in allBindings) { if (binding.isPPtrCurve) { continue; } if (binding.type == typeof(GameObject)) { continue; } UnityEngine.Object target = gameObject.GetComponent(binding.type); if (!AnimationMode.IsPropertyAnimated(target, binding.propertyName)) { continue; } bindings.Add(binding); } // Iterate over all child GOs for (int i = 0; i < gameObject.transform.childCount; i++) { Transform childTransform = gameObject.transform.GetChild(i); gameObjects.Enqueue(childTransform.gameObject); } } // Flush out animation mode modifications AnimationMode.BeginSampling(); AnimationMode.EndSampling(); foreach (var binding in bindings) { float floatValue; AnimationUtility.GetFloatValue(rigBuilder.gameObject, binding, out floatValue); var key = new Keyframe(0f, floatValue); var curve = new AnimationCurve(new Keyframe[] { key }); defaultPoseClip.SetCurve(binding.path, binding.type, binding.propertyName, curve); } return(defaultPoseClip); }
IEnumerator coReverseAtAngle(float seconds, float forwardAngle, float backwardAngle, int fames, bool isSlowInSlowOut, bool isStopAndGo) { while (currentBoard != null) { if (isStopAndGo) { rotationType = new AnimationCurve(new Keyframe(0, 0), new Keyframe(seconds, 180f), new Keyframe(seconds + stopWaitTime, 180f), new Keyframe(seconds * 2, 360f), new Keyframe((seconds * 2) + stopWaitTime, 360f)); rotationType.preWrapMode = WrapMode.Loop; rotationType.postWrapMode = WrapMode.Loop; SetCurveLinear(rotationType); currentBoard.transform.eulerAngles = new Vector3(currentBoard.transform.eulerAngles.x, currentBoard.transform.eulerAngles.y, rotationType.Evaluate(Time.time)); yield return(null); } else { rotationType = new AnimationCurve(); Keyframe[] newKeys = new Keyframe[fames]; int multiplier = 0; float currentAngle = 0; for (int i = 0; i < newKeys.Length; i++) { if (i == 0) { newKeys[i].time = 0; newKeys[i].value = 0; } else if (i % 2 != 0) { newKeys[i].time = seconds * multiplier; currentAngle += forwardAngle; newKeys[i].value = currentAngle; } else { newKeys[i].time = seconds * multiplier; currentAngle -= backwardAngle; newKeys[i].value = currentAngle; } multiplier++; rotationType.AddKey(newKeys[i]); } rotationType.preWrapMode = WrapMode.Loop; rotationType.postWrapMode = WrapMode.Loop; if (isSlowInSlowOut) { currentBoard.transform.eulerAngles = new Vector3(currentBoard.transform.eulerAngles.x, currentBoard.transform.eulerAngles.y, rotationType.Evaluate(Time.time)); yield return(null); } else { SetCurveLinear(rotationType); currentBoard.transform.eulerAngles = new Vector3(currentBoard.transform.eulerAngles.x, currentBoard.transform.eulerAngles.y, rotationType.Evaluate(Time.time)); yield return(null); } } } }
public static AnimationCurve[] CompressCurves(AnimationCurve[] curves, Func <AnimationCurve[], AnimationCurve[], float, bool> isGood, int checkSteps = 8) { var keyframes = new Keyframe[curves.Length][]; var position = new int[curves.Length]; var nextFrame = new int[curves.Length]; var compressedCurves = new AnimationCurve[curves.Length]; for (int i = 0; i < curves.Length; i++) { var keys = curves[i].keys; compressedCurves[i] = new AnimationCurve(keys); for (int j = 0; j < keys.Length; j++) { var leftT = AnimationUtility.GetKeyLeftTangentMode(curves[i], j); var rightT = AnimationUtility.GetKeyRightTangentMode(curves[i], j); AnimationUtility.SetKeyLeftTangentMode(compressedCurves[i], j, leftT); AnimationUtility.SetKeyRightTangentMode(compressedCurves[i], j, rightT); } keyframes[i] = keys; position[i] = keys.Length - 2; nextFrame[i] = keys.Length - 1; } do { for (int i = 0; i < curves.Length; i++) { if (position[i] > 0) { Keyframe nextKeyframe = keyframes[i][nextFrame[i]]; Keyframe currKeyframe = keyframes[i][position[i]]; Keyframe prevKeyframe = keyframes[i][position[i] - 1]; var leftT = AnimationUtility.GetKeyLeftTangentMode(compressedCurves[i], position[i]); var rightT = AnimationUtility.GetKeyRightTangentMode(compressedCurves[i], position[i]); compressedCurves[i].RemoveKey(position[i]); for (int k = 0; k < checkSteps; k++) { float percent = k / (checkSteps - 1.0f); float prevTime = Mathf.Lerp(currKeyframe.time, prevKeyframe.time, percent); float nextTime = Mathf.Lerp(currKeyframe.time, nextKeyframe.time, percent); bool isPrevGood = isGood(curves, compressedCurves, prevTime); bool isNextgood = isGood(curves, compressedCurves, nextTime); if (!isPrevGood || !isNextgood) { int index = compressedCurves[i].AddKey(currKeyframe); AnimationUtility.SetKeyLeftTangentMode(compressedCurves[i], index, leftT); AnimationUtility.SetKeyRightTangentMode(compressedCurves[i], index, rightT); nextFrame[i] = position[i]; break; } } position[i]--; } } } while (position.Query().Any(p => p > 0)); return(compressedCurves); }
extern private static void Internal_SetKeyRightTangentMode(ref Keyframe key, TangentMode tangentMode);
private void SetCurve(CurveWrapper cw, AnimationCurve curve) { Keyframe[] destinationArray = new Keyframe[curve.keys.Length]; Array.Copy(curve.keys, destinationArray, destinationArray.Length); cw.curve.keys = destinationArray; cw.changed = true; }
public void AddTangentMenuItems(GenericMenu menu, List <KeyIdentifier> keyList) { bool anyKeys = (keyList.Count > 0); // Find out which qualities apply to all the keys bool allClampedAuto = anyKeys; bool allAuto = anyKeys; bool allFreeSmooth = anyKeys; bool allFlat = anyKeys; bool allBroken = anyKeys; bool allLeftWeighted = anyKeys; bool allLeftFree = anyKeys; bool allLeftLinear = anyKeys; bool allLeftConstant = anyKeys; bool allRightWeighted = anyKeys; bool allRightFree = anyKeys; bool allRightLinear = anyKeys; bool allRightConstant = anyKeys; foreach (KeyIdentifier sel in keyList) { Keyframe key = sel.keyframe; TangentMode leftMode = AnimationUtility.GetKeyLeftTangentMode(key); TangentMode rightMode = AnimationUtility.GetKeyRightTangentMode(key); bool broken = AnimationUtility.GetKeyBroken(key); if (leftMode != TangentMode.ClampedAuto || rightMode != TangentMode.ClampedAuto) { allClampedAuto = false; } if (leftMode != TangentMode.Auto || rightMode != TangentMode.Auto) { allAuto = false; } if (broken || leftMode != TangentMode.Free || rightMode != TangentMode.Free) { allFreeSmooth = false; } if (broken || leftMode != TangentMode.Free || key.inTangent != 0 || rightMode != TangentMode.Free || key.outTangent != 0) { allFlat = false; } if (!broken) { allBroken = false; } if (!broken || leftMode != TangentMode.Free) { allLeftFree = false; } if (!broken || leftMode != TangentMode.Linear) { allLeftLinear = false; } if (!broken || leftMode != TangentMode.Constant) { allLeftConstant = false; } if (!broken || rightMode != TangentMode.Free) { allRightFree = false; } if (!broken || rightMode != TangentMode.Linear) { allRightLinear = false; } if (!broken || rightMode != TangentMode.Constant) { allRightConstant = false; } if ((key.weightedMode & WeightedMode.In) == WeightedMode.None) { allLeftWeighted = false; } if ((key.weightedMode & WeightedMode.Out) == WeightedMode.None) { allRightWeighted = false; } } if (anyKeys) { menu.AddItem(EditorGUIUtility.TrTextContent("Clamped Auto"), allClampedAuto, SetClampedAuto, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Auto"), allAuto, SetAuto, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Free Smooth"), allFreeSmooth, SetEditable, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Flat"), allFlat, SetFlat, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Broken"), allBroken, SetBroken, keyList); menu.AddSeparator(""); menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Free"), allLeftFree, SetLeftEditable, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Linear"), allLeftLinear, SetLeftLinear, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Constant"), allLeftConstant, SetLeftConstant, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Weighted"), allLeftWeighted, ToggleLeftWeighted, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Free"), allRightFree, SetRightEditable, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Linear"), allRightLinear, SetRightLinear, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Constant"), allRightConstant, SetRightConstant, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Weighted"), allRightWeighted, ToggleRightWeighted, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Free"), allRightFree && allLeftFree, SetBothEditable, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Linear"), allRightLinear && allLeftLinear, SetBothLinear, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Constant"), allRightConstant && allLeftConstant, SetBothConstant, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Weighted"), allRightWeighted && allLeftWeighted, ToggleBothWeighted, keyList); } else { menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Weighted")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Auto")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Free Smooth")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Flat")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Broken")); menu.AddSeparator(""); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Free")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Linear")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Constant")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Weighted")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Free")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Linear")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Constant")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Weighted")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Free")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Linear")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Constant")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Weighted")); } }