From 0d6daed2f133c2fdf0994358bcfabcd67c404e20 Mon Sep 17 00:00:00 2001 From: Merlin <36685500+MerlinVR@users.noreply.github.com> Date: Fri, 3 Sep 2021 15:41:38 -0700 Subject: [PATCH] Add support for sync mode None - Hacky initial support that probably needs work to interact cleanly with how VRC now enforces the sync mode through the API to be the same on all components on the same game object --- .../Editors/UdonSharpComponentExtensions.cs | 14 ++++- .../UdonSharp/Editor/Editors/UdonSharpGUI.cs | 62 ++++++++++++------- Assets/UdonSharp/Editor/UdonSharpCompiler.cs | 6 +- .../Editor/UdonSharpEditorManager.cs | 41 +++++++----- .../UdonSharp/Scripts/UdonSharpAttributes.cs | 4 ++ 5 files changed, 85 insertions(+), 42 deletions(-) diff --git a/Assets/UdonSharp/Editor/Editors/UdonSharpComponentExtensions.cs b/Assets/UdonSharp/Editor/Editors/UdonSharpComponentExtensions.cs index 31de6bce..79162272 100644 --- a/Assets/UdonSharp/Editor/Editors/UdonSharpComponentExtensions.cs +++ b/Assets/UdonSharp/Editor/Editors/UdonSharpComponentExtensions.cs @@ -4,6 +4,7 @@ using UdonSharp; using UnityEditor; using UnityEngine; +using VRC.SDKBase; using VRC.Udon; namespace UdonSharpEditor @@ -150,7 +151,18 @@ public static UdonSharpBehaviour AddUdonSharpComponent(this GameObject gameObjec udonBehaviour.AllowCollisionOwnershipTransfer = false; #pragma warning restore CS0618 // Type or member is obsolete - udonBehaviour.Reliable = programAsset.behaviourSyncMode == BehaviourSyncMode.Manual; + switch (programAsset.behaviourSyncMode) + { + case BehaviourSyncMode.Continuous: + udonBehaviour.SyncMethod = Networking.SyncType.Continuous; + break; + case BehaviourSyncMode.Manual: + udonBehaviour.SyncMethod = Networking.SyncType.Manual; + break; + case BehaviourSyncMode.None: + udonBehaviour.SyncMethod = Networking.SyncType.None; + break; + } SerializedObject componentAsset = new SerializedObject(udonBehaviour); SerializedProperty serializedProgramAssetProperty = componentAsset.FindProperty("serializedProgramAsset"); diff --git a/Assets/UdonSharp/Editor/Editors/UdonSharpGUI.cs b/Assets/UdonSharp/Editor/Editors/UdonSharpGUI.cs index b7dc28a9..c51cc830 100644 --- a/Assets/UdonSharp/Editor/Editors/UdonSharpGUI.cs +++ b/Assets/UdonSharp/Editor/Editors/UdonSharpGUI.cs @@ -10,6 +10,7 @@ using UdonSharp.Compiler; using UnityEditor; using UnityEngine; +using VRC.SDKBase; using VRC.Udon; using VRC.Udon.Common; using VRC.Udon.Common.Interfaces; @@ -28,11 +29,12 @@ internal class SyncModeMenu : EditorWindow private static GUIStyle descriptionStyle; private static readonly List<(GUIContent, GUIContent)> Labels = new List<(GUIContent, GUIContent)>(new[] { + (new GUIContent("None"), new GUIContent("Replication will be disabled. Variables cannot be synced, and this behaviour will not receive network events.")), (new GUIContent("Continuous"), new GUIContent("Continuous replication is intended for frequently-updated variables of small size, and will be tweened.")), (new GUIContent("Manual"), new GUIContent("Manual replication is intended for infrequently-updated variables of small or large size, and will not be tweened.")), }); - - static Rect GetAreaRect(Rect rect) + + private static Rect GetAreaRect(Rect rect) { const float borderWidth = 1f; @@ -68,7 +70,7 @@ void DrawSelectionOption(GUIContent title, GUIContent descriptor, int index) checkboxStyle.padding.right = 0; checkboxStyle.margin.right = 0; - if (udonBehaviour.Reliable == (index == 1)) + if (udonBehaviour.SyncMethod == (Networking.SyncType)(index + 1)) EditorGUILayout.LabelField("✔", checkboxStyle, GUILayout.Width(10f)); else EditorGUILayout.LabelField("", checkboxStyle, GUILayout.Width(10f)); @@ -103,14 +105,14 @@ void DrawSelectionOption(GUIContent title, GUIContent descriptor, int index) } } - void SelectIndex(int idx) + private void SelectIndex(int idx) { selectedIdx = idx; - if (udonBehaviour.Reliable != (selectedIdx == 1)) + if (udonBehaviour.SyncMethod != (Networking.SyncType)(selectedIdx + 1)) { Undo.RecordObject(udonBehaviour, "Change sync mode"); - udonBehaviour.Reliable = selectedIdx == 1; + udonBehaviour.SyncMethod = (Networking.SyncType)(selectedIdx + 1); PrefabUtility.RecordPrefabInstancePropertyModifications(udonBehaviour); } @@ -141,7 +143,7 @@ void DrawSelectionOutline(Rect rect) GUI.Box(new Rect(rect.x - outlineWidth, rect.y + rect.height + outlineWidth + 1f, rect.width + outlineWidth * 2f, outlineWidth), GUIContent.none, outlineStyle); } - internal static Rect GUIToScreenRect(Rect rect) + private static Rect GUIToScreenRect(Rect rect) { Vector2 point = GUIUtility.GUIToScreenPoint(new Vector2(rect.x, rect.y)); rect.x = point.x; @@ -190,7 +192,7 @@ public static void Show(Rect controlRect, UdonBehaviour[] behaviours) menu.ShowDropDown(controlRect, dropdownSize); } - static Vector2 CalculateDropdownSize(Rect controlRect) + private static Vector2 CalculateDropdownSize(Rect controlRect) { Rect areaRect = GetAreaRect(controlRect); areaRect.width -= 30f; // Checkbox width @@ -200,7 +202,7 @@ static Vector2 CalculateDropdownSize(Rect controlRect) for (int i = 0; i < Labels.Count; ++i) { totalHeight += EditorStyles.boldLabel.CalcHeight(Labels[i].Item1, areaRect.width); - totalHeight += 6f; // Space() + totalHeight += 13f; // Space() totalHeight += descriptionStyle.CalcHeight(Labels[i].Item2, areaRect.width); totalHeight += selectionStyle.margin.vertical; totalHeight += selectionStyle.padding.vertical; @@ -211,22 +213,22 @@ static Vector2 CalculateDropdownSize(Rect controlRect) return new Vector2(controlRect.width, totalHeight); } - static Array popupLocationArray; + private static Array _popupLocationArray; void ShowDropDown(Rect controlRect, Vector2 size) { - if (popupLocationArray == null) + if (_popupLocationArray == null) { System.Type popupLocationType = AppDomain.CurrentDomain.GetAssemblies().First(e => e.GetName().Name == "UnityEditor").GetType("UnityEditor.PopupLocation"); - popupLocationArray = (Array)Activator.CreateInstance(popupLocationType.MakeArrayType(), 2); - popupLocationArray.SetValue(0, 0); // PopupLocation.Below - popupLocationArray.SetValue(4, 1); // PopupLocation.Overlay + _popupLocationArray = (Array)Activator.CreateInstance(popupLocationType.MakeArrayType(), 2); + _popupLocationArray.SetValue(0, 0); // PopupLocation.Below + _popupLocationArray.SetValue(4, 1); // PopupLocation.Overlay } MethodInfo showAsDropDownMethod = typeof(EditorWindow).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).First(e => e.GetParameters().Length == 3); - showAsDropDownMethod.Invoke(this, new object[] { controlRect, size, popupLocationArray }); + showAsDropDownMethod.Invoke(this, new object[] { controlRect, size, _popupLocationArray }); } } #endregion @@ -1364,7 +1366,7 @@ internal static void DrawSyncSettings(UdonBehaviour behaviour) if (otherBehaviour.programSource is UdonSharpProgramAsset otherBehaviourProgram && otherBehaviourProgram.behaviourSyncMode == BehaviourSyncMode.NoVariableSync) continue; - if (otherBehaviour.Reliable) + if (otherBehaviour.SyncMethod == Networking.SyncType.Manual) hasReliableSync = true; else hasContinuousSync = true; @@ -1381,7 +1383,7 @@ internal static void DrawSyncSettings(UdonBehaviour behaviour) } // Dropdown for the sync settings - if (programAsset.behaviourSyncMode != BehaviourSyncMode.NoVariableSync) + if (programAsset.behaviourSyncMode != BehaviourSyncMode.NoVariableSync && programAsset.behaviourSyncMode != BehaviourSyncMode.None) { bool allowsSyncConfig = programAsset.behaviourSyncMode == BehaviourSyncMode.Any; @@ -1396,7 +1398,21 @@ internal static void DrawSyncSettings(UdonBehaviour behaviour) if (dropdownButtonMethod == null) dropdownButtonMethod = typeof(EditorGUI).GetMethod("DropdownButton", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(int), typeof(Rect), typeof(GUIContent), typeof(GUIStyle) }, null); - if ((bool)dropdownButtonMethod.Invoke(null, new object[] { id, dropdownRect, new GUIContent(behaviour.Reliable ? "Manual" : "Continuous"), EditorStyles.miniPullDown })) + string dropdownText; + switch (behaviour.SyncMethod) + { + case Networking.SyncType.Continuous: + dropdownText = "Continuous"; + break; + case Networking.SyncType.Manual: + dropdownText = "Manual"; + break; + default: + dropdownText = "None"; + break; + } + + if ((bool)dropdownButtonMethod.Invoke(null, new object[] { id, dropdownRect, new GUIContent(dropdownText), EditorStyles.miniPullDown })) { SyncModeMenu.Show(syncMethodRect, new UdonBehaviour[] { behaviour }); @@ -1405,18 +1421,18 @@ internal static void DrawSyncSettings(UdonBehaviour behaviour) EditorGUI.EndDisabledGroup(); - bool newReliableState = behaviour.Reliable; + bool newReliableState = behaviour.SyncMethod == Networking.SyncType.Manual; // Handle auto setting of sync mode if the component has just been created - if (programAsset.behaviourSyncMode == BehaviourSyncMode.Continuous && behaviour.Reliable) + if (programAsset.behaviourSyncMode == BehaviourSyncMode.Continuous && behaviour.SyncMethod == Networking.SyncType.Manual) newReliableState = false; - else if (programAsset.behaviourSyncMode == BehaviourSyncMode.Manual && !behaviour.Reliable) + else if (programAsset.behaviourSyncMode == BehaviourSyncMode.Manual && behaviour.SyncMethod != Networking.SyncType.Manual) newReliableState = true; - if (newReliableState != behaviour.Reliable) + if (newReliableState != (behaviour.SyncMethod == Networking.SyncType.Manual)) { Undo.RecordObject(behaviour, "Update sync mode"); - behaviour.Reliable = newReliableState; + behaviour.SyncMethod = newReliableState ? Networking.SyncType.Manual : Networking.SyncType.Continuous; } } diff --git a/Assets/UdonSharp/Editor/UdonSharpCompiler.cs b/Assets/UdonSharp/Editor/UdonSharpCompiler.cs index 9c22c5b2..b607d34c 100644 --- a/Assets/UdonSharp/Editor/UdonSharpCompiler.cs +++ b/Assets/UdonSharp/Editor/UdonSharpCompiler.cs @@ -1,13 +1,11 @@ -using System.CodeDom; + +using System.CodeDom; using System.CodeDom.Compiler; -using System.Collections.Concurrent; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Text; -using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.CodeAnalysis; diff --git a/Assets/UdonSharp/Editor/UdonSharpEditorManager.cs b/Assets/UdonSharp/Editor/UdonSharpEditorManager.cs index c1dd293a..d7f4aee6 100644 --- a/Assets/UdonSharp/Editor/UdonSharpEditorManager.cs +++ b/Assets/UdonSharp/Editor/UdonSharpEditorManager.cs @@ -10,6 +10,7 @@ using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; +using VRC.SDKBase; using VRC.Udon; using VRC.Udon.Common; using VRC.Udon.Common.Interfaces; @@ -733,15 +734,27 @@ static void UpdateSyncModes(List udonBehaviours) behaviourGameObjects.Add(behaviour.gameObject); - if (behaviour.Reliable == true && programAsset.behaviourSyncMode == BehaviourSyncMode.Continuous) - { - behaviour.Reliable = false; - modificationCount++; - PrefabUtility.RecordPrefabInstancePropertyModifications(behaviour); - } - else if (behaviour.Reliable == false && programAsset.behaviourSyncMode == BehaviourSyncMode.Manual) + if (programAsset.behaviourSyncMode == BehaviourSyncMode.Any || + programAsset.behaviourSyncMode == BehaviourSyncMode.NoVariableSync) + continue; + + if (behaviour.SyncMethod == Networking.SyncType.None && programAsset.behaviourSyncMode != BehaviourSyncMode.None || + behaviour.SyncMethod == Networking.SyncType.Continuous && programAsset.behaviourSyncMode != BehaviourSyncMode.Continuous || + behaviour.SyncMethod == Networking.SyncType.Manual && programAsset.behaviourSyncMode != BehaviourSyncMode.Manual) { - behaviour.Reliable = true; + switch (programAsset.behaviourSyncMode) + { + case BehaviourSyncMode.Continuous: + behaviour.SyncMethod = Networking.SyncType.Continuous; + break; + case BehaviourSyncMode.Manual: + behaviour.SyncMethod = Networking.SyncType.Manual; + break; + case BehaviourSyncMode.None: + behaviour.SyncMethod = Networking.SyncType.None; + break; + } + modificationCount++; PrefabUtility.RecordPrefabInstancePropertyModifications(behaviour); } @@ -766,9 +779,9 @@ static void UpdateSyncModes(List udonBehaviours) continue; } - if (objectBehaviour.Reliable) + if (objectBehaviour.SyncMethod == Networking.SyncType.Manual) hasManual = true; - else + else if (objectBehaviour.SyncMethod == Networking.SyncType.Continuous) hasContinuous = true; #pragma warning disable CS0618 // Type or member is obsolete @@ -808,16 +821,16 @@ static void UpdateSyncModes(List udonBehaviours) { if (behaviour.programSource is UdonSharpProgramAsset programAsset && programAsset.behaviourSyncMode == BehaviourSyncMode.NoVariableSync) { - if (hasManual && !behaviour.Reliable) + if (hasManual && behaviour.SyncMethod != Networking.SyncType.Manual) { - behaviour.Reliable = true; + behaviour.SyncMethod = Networking.SyncType.Manual; modificationCount++; PrefabUtility.RecordPrefabInstancePropertyModifications(behaviour); } - else if (behaviour.Reliable) + else if (behaviour.SyncMethod == Networking.SyncType.Manual) { - behaviour.Reliable = false; + behaviour.SyncMethod = Networking.SyncType.Continuous; modificationCount++; PrefabUtility.RecordPrefabInstancePropertyModifications(behaviour); diff --git a/Assets/UdonSharp/Scripts/UdonSharpAttributes.cs b/Assets/UdonSharp/Scripts/UdonSharpAttributes.cs index d4f22f73..d3fbdc59 100644 --- a/Assets/UdonSharp/Scripts/UdonSharpAttributes.cs +++ b/Assets/UdonSharp/Scripts/UdonSharpAttributes.cs @@ -52,6 +52,10 @@ public enum BehaviourSyncMode /// Any, /// + /// Enforces no synced variables on the behaviour and hides the selection dropdown in the UI for the sync mode. Nothing is synced and SendCustomNetworkEvent will not work on the behaviour + /// + None, + /// /// Enforces no synced variables on the behaviour and hides the selection dropdown in the UI for the sync mode, SendCustomNetworkEvent() will still work on this behaviour /// NoVariableSync,