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 OnGUI() { UTStyles.RenderHeader("Camera System Setup"); EditorGUILayout.HelpBox("Camera System requires PostProcessing, please install it by searching for PostProcessing in Window -> Package Manager", MessageType.Error); }
public override void OnInspectorGUI() { t = (UdonSharpBehaviour)target; showUdonSettings = (bool)(UTUtils.GetUTSetting("showUdonSettings", UTUtils.UTSettingType.Bool) ?? false); // we force-disable collision transfer for toolkit driven behaviours as it is not applicable if (!nonUBChecked) { nonUBMode = t.gameObject.GetComponent <UdonBehaviour>() == null; nonUBChecked = true; } if (!nonUBMode) { if (UdonSharpEditorUtility.GetBackingUdonBehaviour(t).AllowCollisionOwnershipTransfer) { UdonSharpEditorUtility.GetBackingUdonBehaviour(t).AllowCollisionOwnershipTransfer = false; } } var headerExited = false; EditorGUI.BeginChangeCheck(); showUdonSettings = GUILayout.Toggle(showUdonSettings, "Udon Settings", UTStyles.smallButton); if (EditorGUI.EndChangeCheck()) { UTUtils.SetUTSetting("showUdonSettings", UTUtils.UTSettingType.Bool, showUdonSettings); } if (showUdonSettings) { headerExited = UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(t, true); } if (headerExited) { return; } #region Caching if (!cacheBuilt) { tT = t.GetType(); programAsset = UdonSharpEditorUtility.GetUdonSharpProgramAsset(t); behInfo = new UTBehaviourInfo(t); var prop = serializedObject.GetIterator(); var next = prop.NextVisible(true); if (next) { do { if (prop.name == "m_Script") { continue; } if (!fieldCache.ContainsKey(prop.name)) { var newField = new UTField(prop); fieldCache.Add(prop.name, newField); if (newField.isInTabGroup) { if (!tabs.ContainsKey(newField.tabGroupName)) { tabs.Add(newField.tabGroupName, new Dictionary <string, UTFieldType>()); // we only support one tab group per behaviour right now if (!tabsExist) { fieldOrder.Add(newField.tabGroupName, UTFieldType.Tab); tabsExist = true; } } // since tabs can host foldouts - we need to explicitly retarget them // this logic could be generalized if i ever want to make all of this recursive if (newField.isInFoldout) { if (!foldouts.ContainsKey(newField.foldoutName)) { foldouts.Add(newField.foldoutName, new Dictionary <string, UTFieldType>()); tabs[newField.tabGroupName].Add(newField.foldoutName, UTFieldType.Foldout); } AddToFieldOrder(newField, prop, true); continue; } AddToFieldOrder(newField, prop, addToTabGroup: true); continue; } if (newField.isInFoldout) { if (!foldouts.ContainsKey(newField.foldoutName)) { foldouts.Add(newField.foldoutName, new Dictionary <string, UTFieldType>()); fieldOrder.Add(newField.foldoutName, UTFieldType.Foldout); } AddToFieldOrder(newField, prop, true); continue; } AddToFieldOrder(newField, prop); } } while (prop.NextVisible(false)); } cacheBuilt = true; return; } var e = Event.current; if (e.type == EventType.Repaint) { if (firstRepaint) { firstRepaint = false; return; } } #endregion if (behInfo.customName != null || behInfo.helpUrl != null) { EditorGUILayout.BeginHorizontal(); UTStyles.RenderHeader(behInfo.customName != null ? behInfo.customName : behInfo.name); if (behInfo.helpUrl != null) { if (GUILayout.Button("?", GUILayout.Height(26), GUILayout.Width(26))) { Application.OpenURL(behInfo.helpUrl); } } EditorGUILayout.EndHorizontal(); } if (behInfo.helpMsg != null) { UTStyles.RenderNote(behInfo.helpMsg); } if (behInfo.onBeforeEditor != null) { behInfo.onBeforeEditor.Invoke(t, new object[] { serializedObject }); } // handle jagged arrays Undo.RecordObject(t, "Change Properties"); EditorGUI.BeginChangeCheck(); droppedObjects = false; // this method is overrideable by custom code DrawGUI(); if (EditorGUI.EndChangeCheck() || droppedObjects || shouldReserialize) { if (behInfo.onValuesChanged != null) { behInfo.onValuesChanged.Invoke(t, new object[] { serializedObject }); } serializedObject.ApplyModifiedProperties(); } if (droppedObjects) { return; } if (behInfo.onAfterEditor != null) { behInfo.onAfterEditor.Invoke(t, new object[] { serializedObject }); } #region Buttons if (behInfo.buttons != null && !Application.isPlaying && behInfo.buttons.Length > 0) { buttonsExpanded = UTStyles.FoldoutHeader("Editor Methods", buttonsExpanded); if (buttonsExpanded) { EditorGUILayout.BeginVertical(new GUIStyle("helpBox")); foreach (var button in behInfo.buttons) { if (GUILayout.Button(button.Name)) { button.Invoke(t, new object[] {}); } } EditorGUILayout.EndVertical(); } } if (Application.isPlaying && behInfo.udonCustomEvents.Length > 0 && !nonUBMode) { methodsExpanded = UTStyles.FoldoutHeader("Udon Events", methodsExpanded); if (methodsExpanded) { EditorGUILayout.BeginVertical(new GUIStyle("helpBox")); var rowBreak = Mathf.Max(1, Mathf.Min(3, behInfo.udonCustomEvents.Length - 1)); var rowEndI = -100; foreach (var(button, i) in behInfo.udonCustomEvents.WithIndex()) { if (i == rowEndI && i != behInfo.udonCustomEvents.Length - 1) { EditorGUILayout.EndHorizontal(); } if (i % rowBreak == 0 && i != behInfo.udonCustomEvents.Length - 1) { EditorGUILayout.BeginHorizontal(); rowEndI = Math.Min(i + rowBreak, behInfo.udonCustomEvents.Length - 1); } if (GUILayout.Button(button)) { UdonSharpEditorUtility.GetBackingUdonBehaviour(t).SendCustomEvent(button); UdonSharpEditorUtility.CopyUdonToProxy(t); } if (i == behInfo.udonCustomEvents.Length - 1 && rowEndI != -100) { EditorGUILayout.EndHorizontal(); } } EditorGUILayout.EndVertical(); } } #endregion }