public override bool BeforeGUI(ref Rect position, SerializedProperty property, GUIContent label, bool visible) { if (!visible) { return(false); } if (isInList) { return(true); } var lRect = GUILayoutUtility.GetLastRect(); var rect = EditorGUI.IndentedRect(position); var fullWidth = EditorGUIUtility.currentViewWidth; rect.width = EditorGUIUtility.currentViewWidth; if (Math.Abs(fullWidth - lRect.width) > 0.1f) { rect.width -= fullWidth - lRect.width; } rect.height = mHeight; UTStyles.RenderSectionHeader(ref rect, text); position.yMin += mHeight + 3; return(true); }
private void OnGUI() { emptyLayer = 0; UTUtils.GetLayerMasks(); UTStyles.RenderHeader("Camera System Setup"); UTStyles.RenderNote("This tool will set up a camera system in your scene, for more details on how to customize the camera - consult the documentation page."); if (GUILayout.Button("Documentation", GUILayout.ExpandWidth(true))) { Application.OpenURL(WikiURL); } UTStyles.RenderSectionHeader("Position and Style"); var newCameraSpot = (Transform)EditorGUILayout.ObjectField("Camera Position", cameraSpot, typeof(Transform), true); if (newCameraSpot != cameraSpot) { setup = false; } cameraSpot = newCameraSpot; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Watermark Overlay"); watermark = (Texture)EditorGUILayout.ObjectField(watermark, typeof(Texture), true); EditorGUILayout.EndHorizontal(); UTStyles.RenderNote("Overlay should be a 16:9 transparent texture"); addGuide = EditorGUILayout.Toggle("Add Camera Guide", addGuide); if (addGuide) { var newGuideStyle = (GuideStyle)EditorGUILayout.EnumPopup("Guide Panel Style", guideStyle); if (newGuideStyle != guideStyle || standObj == null || standObjEditor == null) { var standPath = newGuideStyle == GuideStyle.Futuristic ? SciFiStandPath : TikiStandPath; standObj = AssetDatabase.LoadAssetAtPath(GetAssetPath(standPath), typeof(object)); standObjEditor = UnityEditor.Editor.CreateEditor(standObj); } var r = GUILayoutUtility.GetRect(450, 150); standObjEditor.OnPreviewGUI(r, EditorStyles.helpBox); guideStyle = newGuideStyle; } UTStyles.RenderSectionHeader("PostProcessing and Collisions"); UTStyles.RenderNote("Layers are very important to the overall setup. Make sure you follow the instructions below"); layers.Clear(); for (int i = 0; i < 32; i++) { var layerName = LayerMask.LayerToName(i); if (layerName.Length > 0) { layers.Add($"[{i}] {layerName}"); } else { if (i > 22 && emptyLayer == 0) { emptyLayer = i; } layers.Add($"[{i}] -- not set --"); } } var layersArr = layers.ToArray(); if (emptyLayer != 0) { if (GUILayout.Button("Setup Layers")) { SetupLayers(); } UTStyles.RenderNote("It seems like you have empty layers available, UdonToolkit can set up everything for you if you click the button above"); UTStyles.HorizontalLine(); } cameraPPLayer = EditorGUILayout.Popup("Camera PP Layer", cameraPPLayer, layersArr); UTStyles.RenderNote("This layer will be used for detecting PP volumes for the Camera System"); if (cameraPPLayer == 22) { EditorGUILayout.HelpBox("It is crucial to not put Camera PP volumes on the same layer as the main PostProcessing, or your own view will be affected by the camera effects", MessageType.Warning); } if (setup) { var oldColor = GUI.backgroundColor; GUI.backgroundColor = Color.green; UTStyles.RenderNote("Camera system has been set up in the scene!"); GUI.backgroundColor = oldColor; } if (GUILayout.Button("Create Camera System", GUILayout.Height(30))) { RunCameraSetup(); } if (GUILayout.Button("Add Guide Stand Only", GUILayout.Height(20))) { AddGuide(); } }
public override void OnInspectorGUI() { droppedObjects = false; isPlaying = !Application.isPlaying; t = (UdonSharpBehaviour)target; if (cT == null) { cT = t.GetType(); undoString = $"Update {cT.Name}"; } if (drawDefaultInspector) { DrawDefaultGUI(t); return; } if (UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(t, true)) { return; } // Header var customNameAttr = cT.GetCustomAttributes(typeof(CustomNameAttribute)) .Select(i => i as CustomNameAttribute).ToArray(); var helpUrlAttribute = cT.GetCustomAttributes(typeof(HelpURLAttribute)) .Select(i => i as HelpURLAttribute).ToArray(); if (customNameAttr.Any() || helpUrlAttribute.Any()) { EditorGUILayout.BeginHorizontal(); UTStyles.RenderHeader(customNameAttr.Any() ? customNameAttr[0].name : cT.Name.Replace("Controller", "")); if (helpUrlAttribute.Any()) { if (GUILayout.Button("?", GUILayout.Height(26), GUILayout.Width(26))) { Application.OpenURL(helpUrlAttribute[0].URL); } } EditorGUILayout.EndHorizontal(); } EditorGUI.BeginChangeCheck(); serializedObject.Update(); // Help Box var helpBoxAttr = cT.GetCustomAttributes(typeof(HelpMessageAttribute)) .Select(i => i as HelpMessageAttribute).ToArray(); if (helpBoxAttr.Any()) { UTStyles.RenderNote(helpBoxAttr[0]?.helpMessage); } // Check prefabs if (PrefabUtility.IsPartOfAnyPrefab(t.gameObject)) { EditorGUILayout.HelpBox( "Udon doesn't play well with Prefabs. " + "It is recommended to unpack your prefabs when modifying any values.\n" + "Right click the prefab and choose \"Unpack Prefab\"", MessageType.Warning); } // Before Editor Callback var beforeEditorCallback = cT.GetCustomAttribute <OnBeforeEditorAttribute>(); if (beforeEditorCallback != null) { var m = cT.GetMethod(beforeEditorCallback.methodName); m?.Invoke(t, new object[] { serializedObject }); } // for direct editing of fields in case of jagged arrays - we need to record changes Undo.RecordObject(t, undoString); // Actual GUI try { DrawGUI(t); } catch (Exception ex) { // for some reason unity likes to throw ExitGUI exceptions when looking up scene objects // even tho it doesnt throw them when you don't try-catch if (ex.GetType() != typeof(ExitGUIException)) { Debug.LogException(ex); } } // After Editor Callback var afterEditorCallback = cT.GetCustomAttribute <OnAfterEditorAttribute>(); if (afterEditorCallback != null) { var m = cT.GetMethod(afterEditorCallback.methodName); m?.Invoke(t, new object[] { serializedObject }); } if (EditorGUI.EndChangeCheck() || droppedObjects) { // Global Values Callback var globalEditorCallback = cT.GetCustomAttribute <OnValuesChangedAttribute>(); if (globalEditorCallback != null) { var m = cT.GetMethod(globalEditorCallback.methodName); m?.Invoke(t, new object[] { serializedObject }); } serializedObject.ApplyModifiedProperties(); } if (droppedObjects) { return; } // Extra Methods var methods = cT.GetMethods(methodFlags).Where(i => i.GetCustomAttribute <ButtonAttribute>() != null).ToArray(); var buttons = methods .Select(i => i.GetCustomAttribute <ButtonAttribute>()) .Where(i => i != null) .ToArray(); if (buttons.Any()) { UTStyles.RenderSectionHeader("Methods"); var rowBreak = Mathf.Max(1, Mathf.Min(3, buttons.Length - 1)); var rowEndI = -100; foreach (var(button, i) in buttons.WithIndex()) { if (i == rowEndI && i != buttons.Length - 1) { EditorGUILayout.EndHorizontal(); } if (i % rowBreak == 0 && i != buttons.Length - 1) { EditorGUILayout.BeginHorizontal(); rowEndI = Math.Min(i + rowBreak, buttons.Length - 1); } EditorGUI.BeginDisabledGroup(isPlaying && !button.activeInEditMode); if (GUILayout.Button(button.text)) { if (button.activeInEditMode) { methods[i].Invoke(t, new object[] {}); } else { UdonSharpEditorUtility.GetProxyBehaviour(t.GetComponent <UdonBehaviour>()).SendCustomEvent(methods[i].Name); } } EditorGUI.EndDisabledGroup(); if (i == buttons.Length - 1 && rowEndI != -100) { EditorGUILayout.EndHorizontal(); } } } UTStyles.HorizontalLine(); if (GUILayout.Button("Show Default Inspector", UTStyles.smallButton)) { drawDefaultInspector = true; } }
private void HandleArray(SerializedProperty prop) { var attrs = UTUtils.GetPropertyAttributes(prop); var modifierAttrs = UTUtils.GetPropertyAttributes <Attribute>(prop); var isGroup = attrs.Where(a => a is ListViewAttribute).ToArray().Length > 0; var groupAttribute = attrs.Select(a => a as ListViewAttribute).ToArray(); var onValueChangedAttribute = UTUtils.GetPropertyAttribute <OnValueChangedAttribute>(prop); // hideIf attribute var hideIfAttribute = modifierAttrs.OfType <HideIfAttribute>().ToArray(); var isHidden = hideIfAttribute.Length > 0 && UTUtils.GetVisibleThroughAttribute(prop, hideIfAttribute[0].methodName, false); // handling for regular arrays, make nicer down the line if (!isGroup) { if (isHidden) { return; } RenderArray(prop, onValueChangedAttribute?.methodName); if (droppedObjects) { return; } RenderHelpBox(prop); return; } var groupName = groupAttribute[0].name; var items = cT.GetFields().Where(f => f.GetAttribute <ListViewAttribute>() != null && f.GetAttribute <ListViewAttribute>().name == groupName) .ToList(); // fast exit on 1 element with list view if (items.Count < 2) { if (isHidden) { return; } RenderArray(prop, onValueChangedAttribute?.methodName); if (droppedObjects) { return; } RenderHelpBox(prop); return; } var index = items.FindIndex(a => a.Name == prop.name); if (index > 0) { return; } var sectionHeaderAttribute = UTUtils.GetPropertyAttribute <SectionHeaderAttribute>(prop); if (sectionHeaderAttribute != null) { UTStyles.RenderSectionHeader(sectionHeaderAttribute.text); } if (isHidden) { return; } var otherProp = serializedObject.FindProperty(items[1].Name); var leftPopupAttribute = UTUtils.GetPropertyAttribute <PopupAttribute>(prop); var rightPopupAttribute = UTUtils.GetPropertyAttribute <PopupAttribute>(otherProp); if (rightPopupAttribute != null || leftPopupAttribute != null) { RenderStackedArray(groupAttribute[0].name, prop, otherProp, leftPopupAttribute, rightPopupAttribute, groupAttribute[0].addMethodName, groupAttribute[0].addButtonText, onValueChangedAttribute?.methodName); if (droppedObjects) { return; } RenderHelpBox(prop); return; } RenderStackedArray(groupAttribute[0].name, prop, otherProp, groupAttribute[0].addMethodName, groupAttribute[0].addButtonText, onValueChangedAttribute?.methodName); if (droppedObjects) { return; } RenderHelpBox(prop); }
public override void BeforeGUI(SerializedProperty property) { UTStyles.RenderSectionHeader(text); }