Files
BABA_YAGA/Assets/Editors/TimeLord.cs

143 lines
5.5 KiB
C#
Raw Normal View History

2026-06-16 16:57:07 +07:00
#if UNITY_EDITOR
2026-03-26 20:27:19 +07:00
// ===============================================================================
// TimeLord - In-Scene Time Manipulation Tool
//
// Creator: Scove
// Last Updated: 2026-03-03
// Version: 2.0 (Sleek UI & Ergonomic Controls)
//
// Purpose:
// Provides a floating, interactive control panel inside the Scene View during
// Play Mode. Allows developers to easily manipulate game time (slow motion,
// fast forward, or pause) without constantly looking away from the action.
//
// Key Features:
// 1. Floating Dashboard: Clean, unobtrusive UI placed directly in the Scene View.
// 2. Dynamic Slider: Drag to fine-tune the time scale smoothly from 0x to 10x.
// 3. Smart Highlighting: Active speeds light up (Green), making it easy to read.
// 4. Auto-Resume: Clicking a speed preset while paused automatically resumes play.
// 5. Visual Pause State: Prominent pause button changes color when active.
//
// How to Use:
// 1. Place this script in an 'Editor' folder.
// 2. Hit PLAY in Unity.
// 3. Move your mouse to the Scene View and use the top-center Time Lord panel!
// ===============================================================================
using UnityEditor;
using UnityEngine;
namespace Editor
{
[InitializeOnLoad]
public class TimeLord
{
// Panel configuration
private const float PANEL_WIDTH = 340f;
private const float PANEL_HEIGHT = 105f;
static TimeLord()
{
// Unsubscribe first to prevent double-hooking upon script recompile
SceneView.duringSceneGui -= OnSceneGUI;
SceneView.duringSceneGui += OnSceneGUI;
}
private static void OnSceneGUI(SceneView sceneView)
{
if (!Application.isPlaying) return;
Handles.BeginGUI();
2026-07-04 18:01:40 +07:00
float panelWidth = 460f;
float panelHeight = 40f;
float posX = (sceneView.position.width - panelWidth) / 2f;
float posY = 20f;
Rect panelRect = new Rect(posX, posY, panelWidth, panelHeight);
2026-03-26 20:27:19 +07:00
2026-07-04 18:01:40 +07:00
// Sleek semi-transparent dark background
EditorGUI.DrawRect(panelRect, new Color(0.1f, 0.1f, 0.1f, 0.85f));
// Thin accent line at the top
EditorGUI.DrawRect(new Rect(posX, posY, panelWidth, 2), new Color(0.3f, 0.7f, 1f, 0.8f));
2026-03-26 20:27:19 +07:00
2026-07-04 18:01:40 +07:00
GUILayout.BeginArea(new Rect(posX + 10, posY + 8, panelWidth - 20, panelHeight - 16));
GUILayout.BeginHorizontal();
2026-03-26 20:27:19 +07:00
2026-07-04 18:01:40 +07:00
// --- 1. HEADER (Current Speed) ---
2026-03-26 20:27:19 +07:00
string currentSpeedText = EditorApplication.isPaused ? "<color=#FF6B6B>PAUSED</color>" : $"<color=#4ECDC4>{Time.timeScale:F2}x</color>";
2026-07-04 18:01:40 +07:00
GUILayout.Label($"⏳ {currentSpeedText}", new GUIStyle(EditorStyles.boldLabel) { richText = true, fontSize = 13, alignment = TextAnchor.MiddleLeft }, GUILayout.Width(80));
2026-03-26 20:27:19 +07:00
// --- 2. TIME SLIDER (Fine-tune control) ---
EditorGUI.BeginChangeCheck();
2026-07-04 18:01:40 +07:00
float newTimeScale = GUILayout.HorizontalSlider(Time.timeScale, 0f, 10f, GUILayout.Width(80), GUILayout.Height(20));
2026-03-26 20:27:19 +07:00
if (EditorGUI.EndChangeCheck())
{
Time.timeScale = newTimeScale;
if (EditorApplication.isPaused && newTimeScale > 0f)
{
EditorApplication.isPaused = false;
}
}
2026-07-04 18:01:40 +07:00
GUILayout.Space(15);
2026-03-26 20:27:19 +07:00
// --- 3. PRESET SPEED BUTTONS ---
2026-07-04 18:01:40 +07:00
DrawSpeedButton("0.5x", 0.5f, 35);
DrawSpeedButton("1x", 1f, 30);
DrawSpeedButton("2x", 2f, 30);
DrawSpeedButton("5x", 5f, 30);
2026-03-26 20:27:19 +07:00
2026-07-04 18:01:40 +07:00
GUILayout.FlexibleSpace();
2026-03-26 20:27:19 +07:00
// --- 4. PAUSE / RESUME BUTTON ---
Color oldBgColor = GUI.backgroundColor;
2026-07-04 18:01:40 +07:00
GUI.backgroundColor = EditorApplication.isPaused ? new Color(1f, 0.4f, 0.4f) : new Color(0.8f, 0.8f, 0.8f);
2026-03-26 20:27:19 +07:00
2026-07-04 18:01:40 +07:00
string pauseLabel = EditorApplication.isPaused ? "▶ RESUME" : "⏸ PAUSE";
2026-03-26 20:27:19 +07:00
GUIStyle pauseStyle = new GUIStyle(GUI.skin.button) { fontStyle = FontStyle.Bold };
2026-07-04 18:01:40 +07:00
if (GUILayout.Button(pauseLabel, pauseStyle, GUILayout.Width(80), GUILayout.Height(24)))
2026-03-26 20:27:19 +07:00
{
EditorApplication.isPaused = !EditorApplication.isPaused;
}
GUI.backgroundColor = oldBgColor;
2026-07-04 18:01:40 +07:00
GUILayout.EndHorizontal();
2026-03-26 20:27:19 +07:00
GUILayout.EndArea();
2026-07-04 18:01:40 +07:00
2026-03-26 20:27:19 +07:00
Handles.EndGUI();
}
/// <summary>
/// Draws a preset button that automatically highlights green if it matches the current time scale.
/// </summary>
2026-07-04 18:01:40 +07:00
private static void DrawSpeedButton(string label, float targetSpeed, float width)
2026-03-26 20:27:19 +07:00
{
Color oldBgColor = GUI.backgroundColor;
// Highlight green if this is the active speed AND the game is not paused
bool isActive = Mathf.Approximately(Time.timeScale, targetSpeed) && !EditorApplication.isPaused;
if (isActive)
{
GUI.backgroundColor = new Color(0.4f, 1f, 0.4f); // Light Green
}
2026-07-04 18:01:40 +07:00
if (GUILayout.Button(label, GUILayout.Width(width), GUILayout.Height(24)))
2026-03-26 20:27:19 +07:00
{
Time.timeScale = targetSpeed;
// Auto-resume if the player clicked a speed while paused
if (EditorApplication.isPaused)
{
EditorApplication.isPaused = false;
}
}
// Restore previous color
GUI.backgroundColor = oldBgColor;
}
}
2026-06-16 16:57:07 +07:00
}
#endif