private void EventEditing(ref Map.Event e) { EditorGUI.BeginChangeCheck(); if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(map); } }
private void OnGUI() { map = Selection.activeObject as Map; speaker.clip = map?.song; if (map == null) { return; } bool rebuildBuffer = false; // ——— // Map settings EditorGUILayout.LabelField("Map settings: " + map.name, EditorStyles.boldLabel); EditorGUI.BeginChangeCheck(); var song = Extension.ObjectField(map.song, "Song"); var bpm = (int)(uint)EditorGUILayout.IntField("Song BPM", map.bpm); #region Track settings changes if (EditorGUI.EndChangeCheck()) { if (song != map.song) { // Release buffer is song is removed if (song == null) { view.buffer?.Release(); } else { rebuildBuffer = true; } // Save to asset & load on speaker map.song = speaker.clip = song; } if (bpm != map.bpm) { map.bpm = bpm; } EditorUtility.SetDirty(map); } #endregion if (map.song != null) { #region Waveform View EditorGUILayout.Space(); var rect = GUILayoutUtility.GetRect(0, View.Height, GUILayout.ExpandWidth(true)); if (rect.width > 1 && rect.width != view.width) { view.width = rect.width; rebuildBuffer = true; } Graphics.DrawTexture(rect, Texture2D.whiteTexture, material); // Get if mouse is inside Waveform rect float mouse = GetMouseInView(rect); #endregion #region View scroll float scroll = GUILayout.HorizontalScrollbar(view.scollPos, view.scrollSize, 0f, 1f); if (view.scollPos != scroll) { view.scollPos = scroll; rebuildBuffer = true; } // Allow zoom-in/-out if (mouse >= 0f && Event.current.type == EventType.ScrollWheel) { view.scrollSize += Event.current.delta.y * 0.01f; view.scrollSize = Mathf.Clamp(view.scrollSize, View.MinScrollSize, View.MaxScrollSize); rebuildBuffer = true; } float seconds = view.scrollSize * map.song.length; float startTime = view.scollPos * map.song.length; float endTime = (view.scollPos + view.scrollSize) * map.song.length; // Feed view limits if (rebuildBuffer) { material.SetFloat("startTime", startTime); material.SetFloat("endTime", endTime); } // Small indicator of how many seconds I'm seeing EditorGUILayout.LabelField("Distance: " + seconds + " seconds.", EditorStyles.miniLabel); #endregion #region Beat overlay float beatTime = 1f / (map.bpm / 60f); int beatAmount = Mathf.FloorToInt(seconds / beatTime); int firstBeat = Mathf.CeilToInt(startTime / beatTime); var mark = new Rect(0, rect.yMin, 2f, rect.height); for (int b = firstBeat; b != firstBeat + beatAmount; ++b) { float pos = Mathf.InverseLerp(startTime, endTime, b * beatTime); mark.x = Mathf.Lerp(rect.xMin, rect.xMax, pos); Color color; if (b == selectedBeat) { color = Color.yellow; } else if (b == playbackBeat) { color = Color.cyan; color.a = 0.9f; } else { color = Color.white; color.a = 0.2f; } // Draw beat marker EditorGUI.DrawRect(mark, color); } // Draw outer view borders GUI.DrawTexture(rect, Texture2D.whiteTexture, 0, false, 0, Color.black, borderWidth: 4, 0); // Feed shader with playback info if (speaker.isPlaying) { material.SetFloat("playbackPos", speaker.time); playbackBeat = Mathf.FloorToInt(speaker.time / beatTime); Repaint(); } #endregion #region Controls if (mouse >= 0f && Event.current.type == EventType.MouseDown) { // Right click if (Event.current.button == 0) { float clickTime = Mathf.Lerp(startTime, endTime, mouse); selectedBeat = Mathf.RoundToInt(clickTime / beatTime); Repaint(); } else // Left click if (Event.current.button == 1) { if (!speaker.isPlaying) { float pos = selectedBeat * beatTime; material.SetFloat("playbackStart", pos); speaker.Play(); speaker.time = pos; } else { material.SetFloat("playbackStart", 0f); material.SetFloat("playbackPos", 0f); speaker.Stop(); Repaint(); } } GUI.FocusControl(null); } #endregion #region Edit events // Make sure Maps has same amout of events as beats in the song int songBeats = Mathf.FloorToInt(map.song.length / beatTime); if (map.events.Length != songBeats) { var list = new Map.Event[songBeats]; for (int i = 0; (i != list.Length && i != map.events.Length); ++i) { // Don't waste previous events list[i] = map.events[i]; } map.events = list; } // Edit current beat event EventEditing(ref map.events[selectedBeat]); #endregion } // Rebuild samples buffer on demand if (rebuildBuffer || view.buffer == null) { BuildBuffer(); } }