// =============================================================================== // LevelDecorator - Professional Environment Randomizer (Chaos Maker) // // Creator: Scove // Last Updated: 2024-05-08 // Version: 2.0 // // Purpose: // Quickly adds natural variety to your levels by randomizing the rotation // and scale of selected objects. Perfect for placing foliage, rocks, or debris. // // Key Features: // 1. Persistent Settings: Remembers your min/max values even after closing Unity. // 2. Uniform Scale: Toggle between independent axes or proportional scaling. // 3. Smart Rotation: Control specific Y-axis variance and subtle "tilt" separately. // 4. Undo Integrated: One click to randomize, one click to undo (Ctrl+Z). // // How to Use: // 1. Place this script in an 'Editor' folder. // 2. Open via: Menu -> Tools -> Level Decorator (Chaos Maker). // 3. Select the objects you want to randomize in the Scene. // 4. Adjust the sliders and click "Apply" or "Randomize Everything". // =============================================================================== using UnityEditor; using UnityEngine; namespace Editor { public class LevelDecorator : EditorWindow { // Settings Variables private Vector3 minScale = new Vector3(0.9f, 0.9f, 0.9f); private Vector3 maxScale = new Vector3(1.1f, 1.1f, 1.1f); private float maxRotationY = 180f; private float maxTilt = 5f; private bool uniformScale = true; [MenuItem("Tools/Level Decorator (Chaos Maker)")] public static void ShowWindow() { GetWindow("Chaos Maker"); } private void OnEnable() { LoadSettings(); } private void LoadSettings() { maxRotationY = EditorPrefs.GetFloat("LD_MaxRotY", 180f); maxTilt = EditorPrefs.GetFloat("LD_MaxTilt", 5f); uniformScale = EditorPrefs.GetBool("LD_Uniform", true); minScale.x = EditorPrefs.GetFloat("LD_MinScaleX", 0.9f); minScale.y = EditorPrefs.GetFloat("LD_MinScaleY", 0.9f); minScale.z = EditorPrefs.GetFloat("LD_MinScaleZ", 0.9f); maxScale.x = EditorPrefs.GetFloat("LD_MaxScaleX", 1.1f); maxScale.y = EditorPrefs.GetFloat("LD_MaxScaleY", 1.1f); maxScale.z = EditorPrefs.GetFloat("LD_MaxScaleZ", 1.1f); } private void SaveSettings() { EditorPrefs.SetFloat("LD_MaxRotY", maxRotationY); EditorPrefs.SetFloat("LD_MaxTilt", maxTilt); EditorPrefs.SetBool("LD_Uniform", uniformScale); EditorPrefs.SetFloat("LD_MinScaleX", minScale.x); EditorPrefs.SetFloat("LD_MinScaleY", minScale.y); EditorPrefs.SetFloat("LD_MinScaleZ", minScale.z); EditorPrefs.SetFloat("LD_MaxScaleX", maxScale.x); EditorPrefs.SetFloat("LD_MaxScaleY", maxScale.y); EditorPrefs.SetFloat("LD_MaxScaleZ", maxScale.z); } private void OnGUI() { GUILayout.Label("CHAOS MAKER - RANDOMIZER", EditorStyles.boldLabel); EditorGUILayout.Space(); EditorGUI.BeginChangeCheck(); // --- ROTATION SECTION --- EditorGUILayout.BeginVertical("box"); GUILayout.Label("1. Rotation", EditorStyles.boldLabel); maxRotationY = EditorGUILayout.Slider("Random Y Axis (0-360)", maxRotationY, 0, 360); maxTilt = EditorGUILayout.Slider("Random Tilt (X & Z)", maxTilt, 0, 45); if (GUILayout.Button("Randomize Rotation")) { ApplyRotation(); } EditorGUILayout.EndVertical(); EditorGUILayout.Space(); // --- SCALE SECTION --- EditorGUILayout.BeginVertical("box"); GUILayout.Label("2. Scale", EditorStyles.boldLabel); uniformScale = EditorGUILayout.Toggle("Uniform Scale", uniformScale); if (uniformScale) { float minU = minScale.x; float maxU = maxScale.x; minU = EditorGUILayout.FloatField("Min Scale", minU); maxU = EditorGUILayout.FloatField("Max Scale", maxU); minScale = new Vector3(minU, minU, minU); maxScale = new Vector3(maxU, maxU, maxU); } else { minScale = EditorGUILayout.Vector3Field("Min Scale", minScale); maxScale = EditorGUILayout.Vector3Field("Max Scale", maxScale); } if (GUILayout.Button("Randomize Scale")) { ApplyScale(); } EditorGUILayout.EndVertical(); EditorGUILayout.Space(10); // --- MASTER ACTION --- GUI.backgroundColor = new Color(0.7f, 1f, 0.7f); // Light green button if (GUILayout.Button("RANDOMIZE EVERYTHING", GUILayout.Height(40))) { ApplyRotation(); ApplyScale(); } GUI.backgroundColor = Color.white; if (EditorGUI.EndChangeCheck()) { SaveSettings(); } EditorGUILayout.Space(); int selectCount = Selection.transforms.Length; EditorGUILayout.HelpBox($"Objects Selected: {selectCount}\nSettings are automatically saved.", MessageType.None); } private void ApplyRotation() { if (Selection.transforms.Length == 0) return; Undo.RecordObjects(Selection.transforms, "Chaos Rotation"); foreach (Transform t in Selection.transforms) { Vector3 currentRot = t.localEulerAngles; float randY = Random.Range(-maxRotationY, maxRotationY); float randX = Random.Range(-maxTilt, maxTilt); float randZ = Random.Range(-maxTilt, maxTilt); t.localEulerAngles = new Vector3(currentRot.x + randX, currentRot.y + randY, currentRot.z + randZ); } Debug.Log($"[LevelDecorator] Rotation randomized for {Selection.transforms.Length} objects."); } private void ApplyScale() { if (Selection.transforms.Length == 0) return; Undo.RecordObjects(Selection.transforms, "Chaos Scale"); foreach (Transform t in Selection.transforms) { if (uniformScale) { float uniformRnd = Random.Range(minScale.x, maxScale.x); t.localScale = new Vector3(uniformRnd, uniformRnd, uniformRnd); } else { float rX = Random.Range(minScale.x, maxScale.x); float rY = Random.Range(minScale.y, maxScale.y); float rZ = Random.Range(minScale.z, maxScale.z); t.localScale = new Vector3(rX, rY, rZ); } } Debug.Log($"[LevelDecorator] Scale randomized for {Selection.transforms.Length} objects."); } } }