Skip to content
This repository has been archived by the owner on Jan 22, 2022. It is now read-only.

Commit

Permalink
Add support for sync mode None
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
MerlinVR committed Sep 3, 2021
1 parent 5394f13 commit 0d6daed
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 42 deletions.
14 changes: 13 additions & 1 deletion Assets/UdonSharp/Editor/Editors/UdonSharpComponentExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using UdonSharp;
using UnityEditor;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

namespace UdonSharpEditor
Expand Down Expand Up @@ -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");
Expand Down
62 changes: 39 additions & 23 deletions Assets/UdonSharp/Editor/Editors/UdonSharpGUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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 });

Expand All @@ -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;
}
}

Expand Down
6 changes: 2 additions & 4 deletions Assets/UdonSharp/Editor/UdonSharpCompiler.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
41 changes: 27 additions & 14 deletions Assets/UdonSharp/Editor/UdonSharpEditorManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -733,15 +734,27 @@ static void UpdateSyncModes(List<UdonBehaviour> 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);
}
Expand All @@ -766,9 +779,9 @@ static void UpdateSyncModes(List<UdonBehaviour> 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
Expand Down Expand Up @@ -808,16 +821,16 @@ static void UpdateSyncModes(List<UdonBehaviour> 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);
Expand Down
4 changes: 4 additions & 0 deletions Assets/UdonSharp/Scripts/UdonSharpAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ public enum BehaviourSyncMode
/// </summary>
Any,
/// <summary>
/// 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
/// </summary>
None,
/// <summary>
/// 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
/// </summary>
NoVariableSync,
Expand Down

0 comments on commit 0d6daed

Please sign in to comment.