// // This file is part of the Tremble package by Tiny Goose. // Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved. // using System; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; namespace TinyGoose.Tremble.Editor { [ManualPage("Entities/Brush Entity Builder", showInTree: false)] public class BrushBuilderPage : BuilderPageBase { public class SampleData : ScriptableObject { [SerializeField] internal string m_UnityName = "MyCoolBrush"; [SerializeField] internal string m_MapName = ""; [SerializeField] internal string m_Category = ""; [SerializeField] internal BrushType m_Type = BrushType.Solid; } protected override void OnPropertiesGUI() { RenderProperty(nameof(SampleData.m_UnityName), title: "MonoBehaviour Name", description: "The name of the main MonoBehaviour script for your brush entity."); RenderProperty(nameof(SampleData.m_MapName), title: "TrenchBroom name", description: "(optional) The entity name to use in TrenchBroom. Leave this blank to use the default."); RenderProperty(nameof(SampleData.m_Category), title: "Category Name", description: "(optional) The category/group name to use in TrenchBroom. Leave this blank to use the default."); RenderProperty(nameof(SampleData.m_Type), title: "Brush Type", description: "The brush type to use. Defaults to 'Solid'.", extraContent: () => { Foldout("Available Brush Types", () => { PropertyDescription("Solid", "A Solid brush with a texture.", "Example: a moving platform."); PropertyDescription("Liquid", "A brush with a texture, but with a trigger collision instead of a solid one.", "Example: a volume of water/lava, which damages players when entering."); PropertyDescription("Trigger", "A completely invisible brush which has a trigger collision.", "Example: a volume which triggers an event when players walk into the area."); PropertyDescription("Invisible", "A completely invisible brush which has solid collision.", "Example: an invisible wall to stop players going out of bounds."); }); }); } protected override void OnPostPropertiesGUI() { List attributeParts = new(16); if (!Sample.m_MapName.IsNullOrEmpty()) { attributeParts.Add($"\"{Sample.m_MapName}\""); } if (!Sample.m_Category.IsNullOrEmpty()) { attributeParts.Add($"category: \"{Sample.m_Category}\""); } if (Sample.m_Type != BrushType.Solid) { attributeParts.Add($"type: {nameof(BrushType)}.{Sample.m_Type}"); } string attrName = FormatAttributeName(typeof(BrushEntityAttribute)); string attributeLine = attributeParts.Count == 0 ? $"[{attrName}]" : $"[{attrName}({String.Join(", ", attributeParts)})]"; string unityName = Sample.m_UnityName.IsNullOrEmpty() ? "" : Sample.m_UnityName; string catName = Sample.m_Category.IsNullOrEmpty() ? FgdConsts.BRUSH_PREFIX : Sample.m_Category; string entName = Sample.m_MapName.IsNullOrEmpty() ? Sample.m_UnityName.ToNamingConvention(SyncSettings.TypeNamingConvention) : Sample.m_MapName; HorizontalLine(); GUILayout.BeginHorizontal(); { GUILayout.BeginVertical(); { H3("Create New Entity"); string code = "// Generated by Tremble v1.7.0\n" + $"// Brush entity '{catName}_{entName}'\n" + "\n" + "using UnityEngine;\n" + $"using {nameof(TinyGoose)}.{nameof(Tremble)};\n" + "\n" + attributeLine + "\n" + $"public class {unityName} : MonoBehaviour\n" + "{\n" + " // Your cool class here ;)\n" + "}"; CodeWithHeaderNoCopy($"Full source for {unityName}.cs", code); ActionBar_SingleAction("Save to new MonoBehaviour class", () => { string assetsFolder = Path.Combine(Directory.GetCurrentDirectory(), "Assets"); string filename = EditorUtility.SaveFilePanel($"Choose where to save {unityName}", assetsFolder, $"{unityName}.cs", "cs"); if (!filename.IsNullOrEmpty()) { File.WriteAllText(filename, code); EditorCompileUtil.CompileThen(typeof(BrushBuilderPage), nameof(OnPostCompile)); } }); } GUILayout.EndVertical(); GUILayout.Label("-or-", EditorStyles.centeredGreyMiniLabel, GUILayout.ExpandHeight(true)); GUILayout.BeginVertical(); { H3("Add to existing MonoBehaviour"); CodeWithHeaderNoCopy("Attribute line only (for existing MonoBehaviour)", attributeLine); ActionBar_SingleAction("Copy to clipboard", () => EditorGUIUtility.systemCopyBuffer = attributeLine); } GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } private static void OnPostCompile() { string message = TrenchBroomUtil.IsTrenchBroomRunning ? "Be sure to press F6 in TrenchBroom to reload entity definitions, so that your new entity appears!" : "All done!"; EditorUtility.DisplayDialog("MonoBehaviour created!", message, "Great!"); ManualWindow mw = EditorWindow.GetWindow(); if (mw) { mw.GoToPage(typeof(BrushEntitiesPage)); } } } }