/******************************************************************************/ /* Project - MudBun Publisher - Long Bunny Labs http://LongBunnyLabs.com Author - Ming-Lun "Allen" Chou http://AllenChou.net */ /******************************************************************************/ using System.IO; using UnityEditor; using UnityEngine; namespace MudBun { public class CreationMenu { // options //------------------------------------------------------------------------- public static bool IsQuickCreation = false; public static bool SwapSolidBrushes = false; //------------------------------------------------------------------------- // end: options // utils //------------------------------------------------------------------------- //[MenuItem("GameObject/MudBun", priority = 151)] //public static void MudBunSubMenuHelper() { } protected static GameObject CreateGameObject(string name) { var newGo = new GameObject(name); var selectedGo = Selection.activeGameObject; if (selectedGo != null) { bool shouldParent = true; if (IsQuickCreation) { shouldParent = selectedGo.GetComponent() != null || selectedGo.GetComponent() != null; } if (shouldParent) { // make child newGo.transform.parent = selectedGo.transform; } else { // make sibling newGo.transform.parent = selectedGo.transform.parent; } } Undo.RegisterCreatedObjectUndo(newGo, newGo.name); return newGo; } protected static GameObject OnBrushCreated(GameObject newGo, bool setAsFirstChild = false) { bool parentedUnderRenderer = false; var t = newGo.transform.parent; while (t != null) { if (t.GetComponent() != null) { parentedUnderRenderer = true; break; } t = t.parent; } if (!parentedUnderRenderer) { var renderer = new GameObject("Mud Renderer"); renderer.AddComponent(); if (newGo.transform.parent != null) { renderer.transform.parent = newGo.transform.parent; renderer.transform.localPosition = Vector3.zero; } newGo.transform.parent = renderer.transform; Undo.RegisterCreatedObjectUndo(renderer, renderer.name); } if (setAsFirstChild) newGo.transform.SetSiblingIndex(0); var selectedGo = Selection.activeGameObject; bool shouldSwap = SwapSolidBrushes && newGo.GetComponent() != null && !(newGo.GetComponent() is MudBrushGroup); if (shouldSwap) { newGo = HandleSwap(newGo, selectedGo); } else { newGo.transform.localPosition = Vector3.zero; newGo.transform.localScale = Vector3.one; } Selection.activeGameObject = newGo; return newGo; } // https://gist.github.com/allanolivei/9260107 public static string GetSelectedPathOrFallback() { string path = "Assets"; foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets)) { path = AssetDatabase.GetAssetPath(obj); if (!string.IsNullOrEmpty(path) && File.Exists(path)) { path = Path.GetDirectoryName(path); break; } } return path; } private static string[] s_aTransferPropertyName = { "Blend", "Operator", "Symmetry", "Round", }; private static GameObject HandleSwap(GameObject newGo, GameObject selectedGo) { if (selectedGo == null) return newGo; var newComp = newGo.GetComponent(); if (newComp != null) { var existingComp = selectedGo.GetComponent(); if (existingComp != null) { // transfer properties var existingType = existingComp.GetType(); var newType = newComp.GetType(); foreach (string propertyName in s_aTransferPropertyName) { var existingProp = existingType.GetProperty(propertyName); if (existingProp == null) continue; var newProp = newType.GetProperty(propertyName); if (newProp == null) continue; var existingValue = existingProp.GetValue(existingComp); newProp.SetValue(newComp, existingValue); } ExtraSolidBrushDestroy(selectedGo); Undo.DestroyObjectImmediate(existingComp); } UnityEditorInternal.ComponentUtility.CopyComponent(newComp); UnityEditorInternal.ComponentUtility.PasteComponentAsNew(selectedGo); selectedGo.name = newGo.name; ExtraSolidBrushInit(selectedGo); } Object.DestroyImmediate(newGo); return selectedGo; } //------------------------------------------------------------------------- // end: utils // extra init/destroy //------------------------------------------------------------------------- private static void ExtraSolidBrushInit(MudParticleSystem comp) { var go = comp.gameObject; var particles = go.AddComponent(); comp.Particles = particles; var main = particles.main; main.simulationSpace = ParticleSystemSimulationSpace.World; main.startLifetime = 2.0f; main.startSpeed = 2.0f; main.startSize = 0.1f; var shape = particles.shape; shape.enabled = true; shape.angle = 15.0f; shape.radius = 0.0f; var size = particles.sizeOverLifetime; size.enabled = true; size.size = new ParticleSystem.MinMaxCurve ( 1.0f, new AnimationCurve ( new Keyframe[] { new Keyframe(0.0f, 0.0f), new Keyframe(0.2f, 1.0f), new Keyframe(0.8f, 1.0f), new Keyframe(1.0f, 0.0f), } ) ); var renderer = go.GetComponent(); renderer.enabled = false; } private static void ExtraSolidBrushInit(MudCurveSimple comp) { var go = comp.gameObject; var pA = CreateGameObject("Curve Point A"); pA.transform.parent = go.transform; pA.transform.localPosition = new Vector3(-0.5f, 0.0f, 0.0f); var pC = CreateGameObject("Curve Control Point"); pC.transform.parent = go.transform; pC.transform.localPosition = new Vector3(0.0f, 0.5f, 0.0f); var pB = CreateGameObject("Curve Point B"); pB.transform.parent = go.transform; pB.transform.localPosition = new Vector3(0.5f, 0.0f, 0.0f); comp.PointA = pA.transform; comp.ControlPoint = pC.transform; comp.PointB = pB.transform; } private static void ExtraSolidBrushInit(MudCurveFull comp) { var go = comp.gameObject; var p0 = CreateGameObject("Curve Point (0)"); p0.transform.parent = go.transform; p0.transform.localPosition = new Vector3(-0.5f, 0.0f); var p1 = CreateGameObject("Curve Point (1)"); p1.transform.parent = go.transform; p1.transform.localPosition = new Vector3(0.0f, 0.5f, 0.0f); var p2 = CreateGameObject("Curve Point (2)"); p2.transform.parent = go.transform; p2.transform.localPosition = new Vector3(0.5f, 0.0f, 0.0f); comp.Points = new MudCurveFull.Point[] { new MudCurveFull.Point(p0, 0.2f), new MudCurveFull.Point(p1, 0.2f), new MudCurveFull.Point(p2, 0.2f), }; } private static void ExtraSolidBrushInit(GameObject go) { var solid = go.GetComponent(); if (solid == null) return; if (solid is MudParticleSystem) { ExtraSolidBrushInit((MudParticleSystem)solid); } else if (solid is MudCurveSimple) { ExtraSolidBrushInit((MudCurveSimple)solid); } else if (solid is MudCurveFull) { ExtraSolidBrushInit((MudCurveFull)solid); } } private static void ExtraSolidBrushDestroy(GameObject go) { var solid = go.GetComponent(); if (solid == null) return; if (solid is MudCurveSimple) { var curveSimple = (MudCurveSimple)solid; if (curveSimple.PointA.parent == curveSimple.transform) Object.DestroyImmediate(curveSimple.PointA.gameObject); if (curveSimple.PointB.parent == curveSimple.transform) Object.DestroyImmediate(curveSimple.PointB.gameObject); if (curveSimple.ControlPoint == curveSimple.transform) Object.DestroyImmediate(curveSimple.ControlPoint.gameObject); } else if (solid is MudCurveFull) { var curveFull = (MudCurveFull)solid; foreach (var p in curveFull.Points) { if (p.Transform.parent == curveFull.transform) Object.DestroyImmediate(p.Transform.gameObject); } } var ps = go.GetComponent(); if (ps != null) Object.DestroyImmediate(ps); var pr = go.GetComponent(); if (pr != null) Object.DestroyImmediate(pr); } //------------------------------------------------------------------------- // end: extra init/destroy // creation //------------------------------------------------------------------------- [MenuItem("GameObject/MudBun/Renderer", priority = 9)] public static GameObject CreateRenderer() { var go = CreateGameObject("Mud Renderer"); go.AddComponent(); Selection.activeGameObject = go; return go; } [MenuItem("GameObject/MudBun/Brush Group", priority = 8)] public static GameObject CreateBrushGroup() { var go = CreateGameObject("Mud Brush Group"); go.AddComponent(); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Primitives/Box", priority = 3)] public static GameObject CreateBox() { var go = CreateGameObject("Mud Box"); go.AddComponent(); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Primitives/Sphere", priority = 3)] public static GameObject CreateSphere() { var go = CreateGameObject("Mud Sphere"); go.AddComponent(); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Primitives/Cylinder", priority = 3)] public static GameObject CreateCylinder() { var go = CreateGameObject("Mud Cylinder"); go.AddComponent(); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Primitives/Cone", priority = 3)] public static GameObject CreateCone() { var go = CreateGameObject("Mud Cone"); var comp = go.AddComponent(); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Primitives/Torus", priority = 3)] public static GameObject CreateTorus() { var go = CreateGameObject("Mud Torus"); go.AddComponent(); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Primitives/Solid Angle", priority = 3)] public static GameObject CreateSolidAngle() { var go = CreateGameObject("Mud Solid Angle"); go.AddComponent(); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Primitives/Curve (Simple: 2 Points + 1 Control)", priority = 3)] public static GameObject CreateCurveSimple() { var go = CreateGameObject("Mud Curve (Simple)"); var comp = go.AddComponent(); comp.EnableNoise = false; ExtraSolidBrushInit(comp); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Primitives/Curve (Full: Any Points)", priority = 3)] public static GameObject CreateCurveFull() { var go = CreateGameObject("Mud Curve (Full)"); var comp = go.AddComponent(); //comp.EnableNoise = false; ExtraSolidBrushInit(comp); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Effects/Particle System", priority = 4)] public static GameObject CreateParticleSystem() { var go = CreateGameObject("Mud Particle System"); var comp = go.AddComponent(); go.transform.rotation = Quaternion.AngleAxis(-90.0f, Vector3.right); ExtraSolidBrushInit(comp); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Effects/Noise Volume", priority = 4)] public static GameObject CreateNoiseVolume() { var go = CreateGameObject("Mud Noise"); go.AddComponent(); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Effects/Noise Curve (Simple: 2 Points + 1 Control)", priority = 4)] public static GameObject CreateNoiseCurveSimple() { var go = CreateGameObject("Mud Curve (Simple)"); var comp = go.AddComponent(); comp.EnableNoise = true; ExtraSolidBrushInit(comp); return OnBrushCreated(go); } /* [MenuItem("GameObject/MudBun/Effects/Noise Curve (Full: Any Points)", priority = 3)] public static GameObject CreateNoiseCurveFull() { var go = CreateGameObject("Mud Curve (Full)"); var comp = go.AddComponent(); //comp.EnableNoise = true; var p0 = CreateGameObject("Curve Point (0)"); p0.transform.parent = go.transform; p0.transform.localPosition = new Vector3(-0.5f, 0.0f); var p1 = CreateGameObject("Curve Point (1)"); p1.transform.parent = go.transform; p1.transform.localPosition = new Vector3(0.0f, 0.5f, 0.0f); var p2 = CreateGameObject("Curve Point (2)"); p2.transform.parent = go.transform; p2.transform.localPosition = new Vector3(0.5f, 0.0f, 0.0f); comp.Points = new MudCurveFull.Point[] { new MudCurveFull.Point(p0, 0.2f), new MudCurveFull.Point(p1, 0.2f), new MudCurveFull.Point(p2, 0.2f), }; return OnBrushCreated(go); } */ [MenuItem("GameObject/MudBun/Distortion/Fish Eye", priority = 5)] public static GameObject CreateFishEye() { var go = CreateGameObject("Mud Fish Eye"); go.AddComponent(); return OnBrushCreated(go, true); } [MenuItem("GameObject/MudBun/Distortion/Twist", priority = 5)] public static GameObject CreateTwist() { var go = CreateGameObject("Mud Twist"); go.AddComponent(); go.transform.localScale = new Vector3(1.0f, 1.2f, 1.0f); return OnBrushCreated(go, true); } [MenuItem("GameObject/MudBun/Distortion/Pinch", priority = 5)] public static GameObject CreatePinch() { var go = CreateGameObject("Mud Pinch"); go.AddComponent(); return OnBrushCreated(go, true); } [MenuItem("GameObject/MudBun/Distortion/Quantize", priority = 5)] public static GameObject CreateQuantize() { var go = CreateGameObject("Mud Quantize"); go.AddComponent(); return OnBrushCreated(go, true); } [MenuItem("GameObject/MudBun/Modifiers/Noise Modifier", priority = 6)] public static GameObject CreateNoiseModifier() { var go = CreateGameObject("Mud Noise Modifier"); go.AddComponent(); return OnBrushCreated(go); } [MenuItem("GameObject/MudBun/Modifiers/Onion", priority = 6)] public static GameObject CreateOnion() { var go = CreateGameObject("Mud Onion"); go.AddComponent(); return OnBrushCreated(go); } //------------------------------------------------------------------------- // end: creation // materials //------------------------------------------------------------------------- private static void CreateRenderMaterial(string assetName, Material mat) { string path = $"{GetSelectedPathOrFallback()}/{assetName}.mat"; Material matCopy = new Material(mat); if (matCopy == null) { Debug.LogWarning("MudBun: Failed to create render material at \"{path\""); return; } ProjectWindowUtil.CreateAsset(matCopy, path); } [MenuItem("Assets/Create/MudBun/Basic Render Material/Mesh (Single-Textured)", priority = 200)] public static void CreateMeshSingleTexturedRendererMaterial() { CreateRenderMaterial ( "MudBun Mesh Renderer Material (Single-Textured)", ResourcesUtilEditor.DefaultMeshSingleTexturedMaterial ); } [MenuItem("Assets/Create/MudBun/Basic Render Material/Mesh (Multi-Textured)", priority = 200)] public static void CreateMeshMultiTexturedRendererMaterial() { CreateRenderMaterial ( "MudBun Mesh Renderer Material (Multi-Textured)", ResourcesUtilEditor.DefaultMeshMultiTexturedMaterial ); } [MenuItem("Assets/Create/MudBun/Basic Render Material/Splat (Single-Textured)", priority = 250)] public static void CreateSplatSingleTexturedRendererMaterial() { CreateRenderMaterial ( "MudBun Splat Renderer Material (Single-Textured)", ResourcesUtilEditor.DefaultSplatSingleTexturedMaterial ); } [MenuItem("Assets/Create/MudBun/Basic Render Material/Splat (Multi-Textured)", priority = 250)] public static void CreateSplatMultiTexturedRendererMaterial() { CreateRenderMaterial ( "MudBun Splat Renderer Material (Multi-Textured)", ResourcesUtilEditor.DefaultSplatMultiTexturedMaterial ); } [MenuItem("Assets/Create/MudBun/Basic Render Material/Decal", priority = 300)] public static void CreateDecalRendererMaterial() { CreateRenderMaterial ( "MudBun Decal Renderer Material", ResourcesUtilEditor.DefaultDecalMaterial ); } [MenuItem("Assets/Create/MudBun/Basic Render Material/Locked Mesh", priority = 350)] public static void CreateStandardMeshMaterial() { CreateRenderMaterial ( "MudBun Locked Mesh Material", ResourcesUtil.DefaultLockedMeshMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/Clay Mesh", priority = 350)] public static void CreateClayMeshMaterial() { CreateRenderMaterial ( "MudBun Clay Mesh Render Material", ResourcesUtilEditor.ClayMeshMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/Claymation Mesh", priority = 350)] public static void CreateClaymationMeshMaterial() { CreateRenderMaterial ( "MudBun Claymation Mesh Render Material", ResourcesUtilEditor.ClaymationMeshMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/Stopmotion Mesh", priority = 350)] public static void CreateStopmotionMeshMaterial() { CreateRenderMaterial ( "MudBun Stopmotion Mesh Render Material", ResourcesUtilEditor.StopmotionMeshMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/2D Mode Mesh/Alpha-Blended Transparent Mesh", priority = 351)] public static void CreateAlphaBlendedTransparentMeshMaterial() { CreateRenderMaterial ( "MudBun Alpha-Blended Transparent Mesh Render Material", ResourcesUtilEditor.AlphaBlendedTransparentMeshMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/2D Mode Mesh/Outline Mesh", priority = 351)] public static void CreateOutlineMeshMaterial() { CreateRenderMaterial ( "MudBun Alpha-Blended Transparent Mesh Render Material", ResourcesUtilEditor.OutlineMeshMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/2D Mode Mesh/SDF Ripple Mesh", priority = 351)] public static void CreateSdfRippleMeshMaterial() { CreateRenderMaterial ( "MudBun SDF Ripple Mesh Render Material", ResourcesUtilEditor.SdfRippleMeshMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/Brush Strokes Splat", priority = 400)] public static void CreateStrokesSplatMaterial() { CreateRenderMaterial ( "MudBun Brush Strokes Splat Render Material", ResourcesUtilEditor.BrushStrokesSplatMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/Floater Splat", priority = 400)] public static void CreateFloaterMaterial() { CreateRenderMaterial ( "MudBun Floater Splat Render Material", ResourcesUtilEditor.FloaterSplatMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/Floof Splat", priority = 400)] public static void CreateFloofMaterial() { CreateRenderMaterial ( "MudBun Floof Splat Render Material", ResourcesUtilEditor.FloofSplatMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/Leaf Splat", priority = 400)] public static void CreateLeafMaterial() { CreateRenderMaterial ( "MudBun Leaf Splat Render Material", ResourcesUtilEditor.LeafSplatMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/Stopmotion Splat", priority = 400)] public static void CreateStopmotionSplatMaterial() { CreateRenderMaterial ( "MudBun Stopmotion Splat Render Material", ResourcesUtilEditor.StopmotionSplatMaterial ); } #if !(UNITY_2021_1_OR_NEWER) // Unity shader graphs are not up to par in blend modes with ASE yet [MenuItem("Assets/Create/MudBun/Preset Render Material/Decal Paint (2x Multiplicative)", priority = 450)] public static void CreateDecalPaintMaterial() { CreateRenderMaterial ( "MudBun Decal Paint Render Material", ResourcesUtilEditor.DecalPaintMaterial ); } #endif [MenuItem("Assets/Create/MudBun/Preset Render Material/Decal Darken (Multiplicative)", priority = 450)] public static void CreateDecalDarkenMaterial() { CreateRenderMaterial ( "MudBun Decal Darken Render Material", ResourcesUtilEditor.DecalDarkenMaterial ); } [MenuItem("Assets/Create/MudBun/Preset Render Material/Decal Lighten (Additive)", priority = 450)] public static void CreateDecalLightenMaterial() { CreateRenderMaterial ( "MudBun Decal Lighten Render Material", ResourcesUtilEditor.DecalLightenMaterial ); } //------------------------------------------------------------------------- // end: materials } }