Files
BABA_YAGA/Assets/Editor/TimeLord.cs
2026-03-26 20:27:19 +07:00

146 lines
5.6 KiB
C#

// ===============================================================================
// 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)
{
// Only display the panel when the game is actually running
if (!Application.isPlaying) return;
Handles.BeginGUI();
// Calculate center-top position dynamically based on current Scene View size
float posX = (sceneView.position.width - PANEL_WIDTH) / 2f;
float posY = 15f;
Rect panelRect = new Rect(posX, posY, PANEL_WIDTH, PANEL_HEIGHT);
// Draw the main background box
GUI.Box(panelRect, GUIContent.none, EditorStyles.helpBox);
GUILayout.BeginArea(new Rect(posX + 10, posY + 10, PANEL_WIDTH - 20, PANEL_HEIGHT - 20));
// --- 1. HEADER (Title & Current Speed) ---
GUIStyle headerStyle = new GUIStyle(EditorStyles.boldLabel)
{
richText = true,
alignment = TextAnchor.MiddleCenter,
fontSize = 13
};
// Format the time scale to show 2 decimal places
string currentSpeedText = EditorApplication.isPaused ? "<color=#FF6B6B>PAUSED</color>" : $"<color=#4ECDC4>{Time.timeScale:F2}x</color>";
GUILayout.Label($"⏳ <b>TIME LORD</b> | Current: {currentSpeedText}", headerStyle);
GUILayout.Space(5);
// --- 2. TIME SLIDER (Fine-tune control) ---
EditorGUI.BeginChangeCheck();
float newTimeScale = GUILayout.HorizontalSlider(Time.timeScale, 0f, 10f);
if (EditorGUI.EndChangeCheck())
{
Time.timeScale = newTimeScale;
// Auto-resume if adjusting slider while paused
if (EditorApplication.isPaused && newTimeScale > 0f)
{
EditorApplication.isPaused = false;
}
}
GUILayout.Space(5);
// --- 3. PRESET SPEED BUTTONS ---
GUILayout.BeginHorizontal();
DrawSpeedButton("0.1x", 0.1f);
DrawSpeedButton("0.5x", 0.5f);
DrawSpeedButton("1x", 1f);
DrawSpeedButton("2x", 2f);
DrawSpeedButton("5x", 5f);
GUILayout.EndHorizontal();
GUILayout.Space(5);
// --- 4. PAUSE / RESUME BUTTON ---
Color oldBgColor = GUI.backgroundColor;
GUI.backgroundColor = EditorApplication.isPaused ? new Color(1f, 0.4f, 0.4f) : new Color(0.9f, 0.9f, 0.9f);
string pauseLabel = EditorApplication.isPaused ? "▶ RESUME GAME" : "⏸ PAUSE GAME";
GUIStyle pauseStyle = new GUIStyle(GUI.skin.button) { fontStyle = FontStyle.Bold };
if (GUILayout.Button(pauseLabel, pauseStyle, GUILayout.Height(25)))
{
EditorApplication.isPaused = !EditorApplication.isPaused;
}
GUI.backgroundColor = oldBgColor;
GUILayout.EndArea();
Handles.EndGUI();
}
/// <summary>
/// Draws a preset button that automatically highlights green if it matches the current time scale.
/// </summary>
private static void DrawSpeedButton(string label, float targetSpeed)
{
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
}
if (GUILayout.Button(label, GUILayout.Height(22)))
{
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;
}
}
}