Example #1
0
    static void PlayModeStateChanged(PlayModeStateChange state)
    {
        BitAnimatorWindow window = GetWindow <BitAnimatorWindow>();

        switch (state)
        {
        case PlayModeStateChange.EnteredEditMode:
            isRunningTask = false;
            EditorUtility.ClearProgressBar();
            break;

        case PlayModeStateChange.ExitingEditMode:
            break;

        case PlayModeStateChange.EnteredPlayMode:
            if (window.targetID == 0)
            {
                return;
            }
            target          = EditorUtility.InstanceIDToObject(window.targetID) as BitAnimator;
            window.targetID = 0;
            if (target != null)
            {
                SetupRuntimeAnimation(target);
            }
            break;

        case PlayModeStateChange.ExitingPlayMode:
            break;
        }
    }
Example #2
0
    public static void WriteAnimation(BitAnimator bitAnimator)
    {
        Action <BitAnimator> updateCallback = (BitAnimator b) =>
        {
            EditorUtility.DisplayProgressBar("Creating animation", b.status, b.taskProgress);
        };
        Action <BitAnimator> finishCallback = (BitAnimator b) =>
        {
            b.core.FreeMemory();
            isRunningTask = false;
            executionTime = Time.realtimeSinceStartup - executionTime;
            EditorUtility.ClearProgressBar();
        };

        bitAnimator.StartCoroutine(bitAnimator.CreateAnimation(finishCallback, updateCallback));
        executionTime = Time.realtimeSinceStartup;
        isRunningTask = true;
    }
Example #3
0
    void OnGUI()
    {
        if (target == null)
        {
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.BeginVertical();
            GUILayout.FlexibleSpace();
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            bool createNew = GUILayout.Button("Create new BitAnimator", GUILayout.MinHeight(40), GUILayout.MaxWidth(180));
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            if (createNew)
            {
                GameObject animatorGO = new GameObject("New Animator");
                target = animatorGO.AddComponent <BitAnimator>();
                target.animatorObject = animatorGO.AddComponent <Animator>();
                AudioSource audioSource = animatorGO.AddComponent <AudioSource>();
                audioSource.minDistance  = 10;
                audioSource.volume       = 0.25f;
                audioSource.dopplerLevel = 0;
                audioSource.spatialize   = false;
                GameObject targetGO = GameObject.CreatePrimitive(PrimitiveType.Cube);
                targetGO.transform.parent = animatorGO.transform;
                DestroyImmediate(targetGO.GetComponent <BoxCollider>());
                target.targetObject    = targetGO;
                Selection.activeObject = target;
            }
            else
            {
                BitAnimator[] bitAnimators = Resources.FindObjectsOfTypeAll <BitAnimator>();
                if (bitAnimators.Length > 0)
                {
                    GUILayout.FlexibleSpace();
                    target = (BitAnimator)EditorGUILayout.ObjectField("BitAnimator", target, typeof(BitAnimator), true);
                    GUILayout.Label("Or select exists animator:");
                    scroll = GUILayout.BeginScrollView(scroll, EditorStyles.helpBox);
                    selectedBitAnimator = GUILayout.SelectionGrid(selectedBitAnimator, bitAnimators.Select(c =>
                    {
                        AudioSource audio = c.GetComponentInChildren <AudioSource>();
                        return(c.gameObject.name + (c.audioClip != null ? " | " + c.audioClip.name : ""));
                    }).ToArray(), 1, EditorStyles.radioButton);
                    GUILayout.EndScrollView();
                    if (selectedBitAnimator >= 0)
                    {
                        Selection.activeObject = bitAnimators[selectedBitAnimator];
                        GUILayout.BeginHorizontal();
                        GUILayout.FlexibleSpace();
                        if (GUILayout.Button("Open", GUILayout.MinHeight(40), GUILayout.MaxWidth(180)))
                        {
                            target = bitAnimators[selectedBitAnimator];
                            selectedBitAnimator = -1;
                        }
                        GUILayout.FlexibleSpace();
                        GUILayout.EndHorizontal();
                    }
                }
                GUILayout.FlexibleSpace();
            }
            GUILayout.EndVertical();
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
        }
        else if (target.recordSlots.Count == 0)
        {
            target = (BitAnimator)EditorGUILayout.ObjectField("BitAnimator", target, typeof(BitAnimator), true);
            EditorGUILayout.HelpBox("This window only for visualization. Setup BitAnimator in the inspector window", MessageType.Info);
        }
        else
        {
            openSettings = EditorGUILayout.Foldout(openSettings, "Show settings", true);
            if (openSettings)
            {
                EditorGUI.indentLevel += 1;
                target   = (BitAnimator)EditorGUILayout.ObjectField("BitAnimator", target, typeof(BitAnimator), true);
                mode     = (ComputeProgram.VisualizationMode)EditorGUILayout.EnumFlagsField("Visualization modes", mode);
                scale    = EditorGUILayout.Slider("Scale", scale, 1, 30);
                multiply = Mathf.Pow(10.0f, EditorGUILayout.Slider("Multiply Log", Mathf.Log10(multiply), -5, 5));
                EditorGUILayout.LabelField(String.Format("Multiply = {0:F6}, AutoMultiply = {1:F6}, RMS = {2:F6}, Max = {3:F6}, Median = {4:F6}", multiply, autoMultiply, rms, maximum, median));
                if ((mode & ComputeProgram.VisualizationMode.RuntimeNormalize) != 0)
                {
                    autoNormilizeSpeed = EditorGUILayout.Slider("AutoNormilize Speed", autoNormilizeSpeed, 0, 50);
                }
                smoothFrequency = EditorGUILayout.Slider("FrequencySmooth", smoothFrequency, 0, 1);
                using (new EditorGUI.DisabledScope(audio == null || animation == null))
                {
                    if (audio != null && audio.clip != null)
                    {
                        EditorGUI.BeginChangeCheck();
                        time = audio.time;
                        time = EditorGUILayout.Slider("Animation play time", time, 0, audio.clip.length);
                        if (animation != null)
                        {
                            AnimationState anim = animation["BitAnimator.RuntimeAnimation"];
                            anim.speed = audio.pitch;
                            if (EditorGUI.EndChangeCheck())
                            {
                                bool oldState = anim.enabled;
                                anim.enabled = true;
                                audio.time   = time;
                                anim.time    = time;
                                animation.Sample();
                                anim.enabled = oldState;
                            }
                            else if (Mathf.Abs(anim.time - audio.time) > 0.05f)
                            {
                                anim.time = audio.time;
                            }
                        }
                        else if (EditorGUI.EndChangeCheck())
                        {
                            audio.time = time;
                        }
                    }
                    else
                    {
                        time = EditorGUILayout.Slider("Sound clip play time", time, 0, 0);
                    }
                    GUILayout.BeginHorizontal();
                    if (audio != null && animation != null)
                    {
                        if (audio.isPlaying)
                        {
                            if (GUILayout.Button("Pause", GUILayout.MaxWidth(128)))
                            {
                                audio.Pause();
                                animation.Stop();
                            }
                        }
                        else
                        {
                            if (GUILayout.Button("Play", GUILayout.MaxWidth(128)))
                            {
                                audio.Play();
                                animation.Play();
                                animation["BitAnimator.RuntimeAnimation"].time = audio.time;
                            }
                        }
                    }
                    else
                    {
                        GUILayout.Button("Play", GUILayout.MaxWidth(128));
                    }

                    if (GUILayout.Button("Reset view", GUILayout.MaxWidth(128)))
                    {
                        ResetView();
                    }

                    if (BPM > 0)
                    {
                        GUILayout.Label("BPM: " + BPM);
                    }
                    GUILayout.EndHorizontal();
                }
                if (target != null)
                {
                    if (target.core != null)
                    {
                        //volumeCurve = EditorGUILayout.CurveField(volumeCurve);

                        /*if (GUILayout.Button("Decimation test", GUILayout.MaxWidth(128)))
                         * {
                         *
                         *  AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(target.animationAssetPath);
                         *  EditorCurveBinding[] b = AnimationUtility.GetCurveBindings(clip);
                         *  AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, b[1]);
                         *  StringBuilder str = new StringBuilder();
                         *  Keyframe[] keyframes = curve.keys;
                         *  //float rmsQuality = -(float)Math.Log(Math.Max(0.001, target.quality), Math.E) / 8.0f;
                         *  var values = keyframes.Select(k => (double)k.value);
                         *  double mean = values.Sum() / keyframes.Length;
                         *  double sd = Math.Sqrt(values.Select(v => (v - mean) * (v - mean)).Sum() / keyframes.Length);
                         *  double rms = Math.Sqrt(values.Select(v => v * v).Sum() / keyframes.Length);
                         *  double avg_sqrV = 0, v1 = 0;
                         *  foreach (double v in values)
                         *  {
                         *      double dv = v - v1;
                         *      avg_sqrV += dv * dv;
                         *      v1 = v;
                         *  }
                         *  avg_sqrV = Math.Sqrt(avg_sqrV / keyframes.Length);
                         *  str.AppendLine(String.Format("[Original] Mean = {0:F4}, SD = {1:F4}, RMS = {2:F4}, v^2 = {3:F4}, Count = {4}", mean, sd, rms, avg_sqrV, keyframes.Length));
                         *
                         *  float rq = Mathf.Pow(10.0f, -6.0f * target.quality * target.quality - 1.0f);
                         *  keyframes = target.core.DecimateAnimationCurve(curve.keys, rq).Where(k => k != null).Single();
                         *  values = keyframes.Select(k => (double)k.value);
                         *  mean = values.Sum() / keyframes.Length;
                         *  sd = Math.Sqrt(values.Select(v => (v - mean) * (v - mean)).Sum() / keyframes.Length);
                         *  rms = Math.Sqrt(values.Select(v => v * v).Sum() / keyframes.Length);
                         *  avg_sqrV = 0; v1 = 0;
                         *  foreach (double v in values)
                         *  {
                         *      double dv = v - v1;
                         *      avg_sqrV += dv * dv;
                         *      v1 = v;
                         *  }
                         *  avg_sqrV = Math.Sqrt(avg_sqrV / keyframes.Length);
                         *  str.AppendLine(String.Format("[Deciamated] Quality = {0}, Mean = {1:F4}, SD = {2:F4}, RMS = {3:F4}, v^2 = {4:F4}, Count = {5}", rq, mean, sd, rms, avg_sqrV, keyframes.Length));
                         *  curve.keys = keyframes;
                         *  Debug.Log(str);
                         *  AnimationUtility.SetEditorCurve(clip, b[0], curve);
                         *  AssetDatabase.SaveAssets();
                         *  AssetDatabase.Refresh();
                         * }*/
                        if (GUILayout.Button("Get BPM", GUILayout.MaxWidth(128)))
                        {
                            BPM = target.core.GetBPM();
                        }
                        EditorGUI.BeginChangeCheck();
                        plotGraphic = (PlotGraphic)EditorGUILayout.EnumPopup("Plot graphic", plotGraphic);
                        if (EditorGUI.EndChangeCheck())
                        {
                            if (texture == null)
                            {
                                texture = new RenderTexture(512, 256, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                                texture.enableRandomWrite = true;
                                texture.Create();
                                target.core.texture = texture;
                            }
                            target.core.RenderBPM(texture);
                            autoMultiply = 1.0f / rms;
                        }
                        if (texture != null)
                        {
                            if (Event.current.type == EventType.Repaint)
                            {
                                box = GUILayoutUtility.GetRect(position.width, position.height);
                                GUI.Box(box, texture);

                                int w = Mathf.FloorToInt(box.width / 8.0f) * 8;
                                int h = Mathf.FloorToInt(box.height / 8.0f) * 8;
                                if (texture.width != w || texture.height != h)
                                {
                                    texture.Release();
                                    texture = new RenderTexture(w, h, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                                    texture.enableRandomWrite = true;
                                    texture.Create();
                                    target.core.texture = texture;
                                }
                            }
                            else
                            {
                                GUILayout.Box(texture, GUILayout.MinWidth(32), GUILayout.MinHeight(32), GUILayout.MaxWidth(2048), GUILayout.MaxHeight(2048));
                            }
                        }
                    }
                }
                int vram = SystemInfo.graphicsMemorySize;
                GUILayout.Label(string.Format("Available VRAM: {0:F3}GB | Used: {1:F3}GB", vram / 1024.0f, target != null && target.core != null ? target.core.UsedVRAM / 1024.0f / 1024.0f / 1024.0f : 0), EditorStyles.boldLabel);
                EditorGUI.indentLevel -= 1;
            }
            else if (texture != null)
            {
                if (Event.current.type == EventType.Repaint)
                {
                    Rect rect = GUILayoutUtility.GetRect(position.width, position.height);
                    GUI.Box(rect, texture);

                    int w = Mathf.FloorToInt(rect.width / 8.0f) * 8;
                    int h = Mathf.FloorToInt(rect.height / 8.0f) * 8;
                    if (texture.width != w || texture.height != h)
                    {
                        texture.Release();
                        texture = new RenderTexture(w, h, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                        texture.enableRandomWrite = true;
                        texture.Create();
                        target.core.texture = texture;
                    }
                }
                else
                {
                    GUILayout.Box(texture, GUILayout.MinWidth(32), GUILayout.MinHeight(32), GUILayout.MaxWidth(2048), GUILayout.MaxHeight(2048));
                }
            }
            EditorGUIUtility.AddCursorRect(box, MouseCursor.SlideArrow);
            if (Event.current.type == EventType.MouseDown)
            {
                mouseDown = Event.current.mousePosition;
            }
            else if (Event.current.type == EventType.MouseUp)
            {
                mouseDown = -Vector2.one;
            }
            else if (Event.current.type == EventType.MouseDrag && box.Contains(mouseDown))
            {
                if (mouseDown.x >= 0 && audio != null)
                {
                    audio.time -= Event.current.delta.x / box.width * scale;
                    if (animation != null)
                    {
                        AnimationState anim  = animation["BitAnimator.RuntimeAnimation"];
                        bool           state = anim.enabled;
                        anim.enabled = true;
                        anim.time    = audio.time;
                        animation.Sample();
                        anim.enabled = state;
                    }
                    Event.current.Use();
                }
            }
            else if (Event.current.type == EventType.MouseMove)
            {
                pos = Event.current.mousePosition;
                if (box.Contains(pos))
                {
                    pos -= box.position;
                }
                else
                {
                    pos = Vector2.zero;
                }

                /*if (plotGraphic == PlotGraphic.BPM)
                 * {
                 *  float offset = (box.width - texture.width) / 2.0f;
                 *  pos.x -= offset;
                 *  BPM = Mathf.FloorToInt(pos.x / texture.width * 256 + 40);
                 *  Event.current.Use();
                 * }*/
            }
            else if (Event.current.type == EventType.ScrollWheel)
            {
                if (box.Contains(Event.current.mousePosition))
                {
                    scale *= Event.current.delta.y < 0 ? 1.125f : 1.0f / 1.125f;
                    Event.current.Use();
                }
            }
        }
    }
Example #4
0
    public static void SetupRuntimeAnimation(BitAnimator bitAnimator)
    {
        Animator animator = bitAnimator.animatorObject;

        //animator.runtimeAnimatorController = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPathWithClip(Path.ChangeExtension(bitAnimator.animationAssetPath, "controller"), clip);
        animation = animator.gameObject.GetComponent <Animation>();
        if (animation == null)
        {
            animation = animator.gameObject.AddComponent <Animation>();
        }
        animation.playAutomatically = false;
        AnimationState runtimeAnimation = animation["BitAnimator.RuntimeAnimation"];

        if (runtimeAnimation == null)
        {
            AnimationClip clip = new AnimationClip
            {
                name   = bitAnimator.audioClip.name,
                legacy = true
            };
            animation.AddClip(clip, "BitAnimator.RuntimeAnimation");
            runtimeAnimation = animation["BitAnimator.RuntimeAnimation"];
        }
        animation.clip           = runtimeAnimation.clip;
        animation.clip.frameRate = (float)bitAnimator.audioClip.frequency / (1 << bitAnimator.FFTWindowLog) * bitAnimator.multisamples;
        Action <BitAnimator> updateCallback = (BitAnimator b) =>
        {
            EditorUtility.DisplayProgressBar("Creating animation", b.status, b.taskProgress);
        };
        Action <BitAnimator> finishCallback = (BitAnimator b) =>
        {
            b.core.FreeMemory();
            isRunningTask = false;
            executionTime = Time.realtimeSinceStartup - executionTime;
            EditorUtility.ClearProgressBar();
            animation.Play();
            //audio.enabled = true;
            if (!audio.isPlaying)
            {
                audio.Play();
            }
        };

        bitAnimator.StartCoroutine(bitAnimator.ComputeAnimation(runtimeAnimation.clip, finishCallback, updateCallback));
        if (EditorApplication.isPlaying)
        {
            bitAnimator.animatorObject.enabled = false;
        }
        isRunningTask = true;
        executionTime = Time.realtimeSinceStartup;

        audio = bitAnimator.animatorObject.gameObject.GetComponentInChildren <AudioSource>();
        if (audio == null)
        {
            audio = bitAnimator.animatorObject.gameObject.AddComponent <AudioSource>();
        }

        if (audio.clip != bitAnimator.audioClip)
        {
            audio.clip         = bitAnimator.audioClip;
            audio.volume       = 0.25f;
            audio.minDistance  = 10;
            audio.dopplerLevel = 0;
            audio.spatialBlend = 0;
            audio.spatialize   = false;
        }
    }
Example #5
0
    void Update()
    {
        if (!isRunningTask)
        {
            if (!EditorApplication.isPlaying && animation != null)
            {
                animation["BitAnimator.RuntimeAnimation"].time = audio.time;
                animation.Sample();
            }
            if (!isRunningTask && !EditorApplication.isPaused && target != null && target.core != null && target.recordSlots.Count > 0 && animation != null && audio != null)
            {
                target.animationTime = audio.time;

                if (texture == null)
                {
                    texture = new RenderTexture(512, 256, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                    texture.enableRandomWrite = true;
                    texture.Create();
                    target.core.texture = texture;
                }
                BitAnimator.RecordSlot slot = target.recordSlots[selectedSlot];
                BitAnimator.SetMode(ref mode, target.calculateLoudness, target.energyCorrection);
                target.core.mode          = mode;
                target.core.resolveFactor = target.deconvolution;
                target.core.SetRemap(slot.remap);
                float         mul        = autoMultiply * multiply;
                ComputeBuffer viewValues = null;
                switch (plotGraphic)
                {
                case PlotGraphic.Histogram:
                    viewValues = target.core.RenderHistogram(
                        texture,
                        audio.time,
                        mul,
                        slot.startFreq,
                        slot.endFreq,
                        slot.ampSmoothness,
                        smoothFrequency);
                    break;

                case PlotGraphic.Peaks:
                    viewValues = target.core.RenderPeaks(
                        texture,
                        audio.time,
                        scale,
                        mul,
                        slot.startFreq,
                        slot.endFreq,
                        slot.ampSmoothness,
                        smoothFrequency,
                        slot.damping);
                    break;

                case PlotGraphic.Spectrum:
                    viewValues = target.core.RenderSpectrum(
                        texture,
                        audio.time,
                        scale,
                        mul,
                        slot.startFreq,
                        slot.endFreq,
                        slot.ampSmoothness,
                        smoothFrequency);
                    break;

                    /*case PlotGraphic.Tones:
                     *  target.core.RenderMainTone(
                     *      texture,
                     *      audio.time,
                     *      scale,
                     *      mul,
                     *      slot.ampSmoothness,
                     *      smoothFrequency);
                     *  break;
                     * case PlotGraphic.Wave:
                     *  rms = target.core.RenderWave(texture, audio.time, 2.0f, mul, slot.ampSmoothness, smoothFrequency); break;*/
                }
                if (viewValues != null)
                {
                    float[] values = new float[target.core.spectrumChunks];
                    viewValues.GetData(values);
                    Array.Sort(values);
                    median  = values[target.core.spectrumChunks / 2];
                    maximum = Math.Max(0.00001f, values[target.core.spectrumChunks - 1]);
                    rms     = target.core.GetRMS(values);
                    if (resetInNextFrame)
                    {
                        if (float.IsInfinity(multiply) || float.IsNaN(multiply))
                        {
                            multiply = 1.0f;
                        }
                        if (float.IsInfinity(autoMultiply) || float.IsNaN(autoMultiply))
                        {
                            autoMultiply = 1.0f;
                        }
                        if (float.IsInfinity(maximum) || float.IsNaN(maximum))
                        {
                            maximum = 1.0f;
                        }
                        autoMultiply     = 0.95f / (maximum / autoMultiply / multiply);
                        resetInNextFrame = false;
                    }
                    if (audio.isPlaying && (mode & ComputeProgram.VisualizationMode.RuntimeNormalize) != 0)
                    {
                        float delta = 0.95f / (maximum / autoMultiply / multiply) - autoMultiply;
                        if (delta < 0)
                        {
                            float k = 1.0f - Mathf.Exp(-Time.deltaTime * autoNormilizeSpeed);
                            autoMultiply += k * delta;
                        }
                    }
                }
                Repaint();
            }
        }
    }