Add VRChat and GitHub packages to Unity project
This commit is contained in:
1 parent
0334a52b21
commit
85538aaccc
3297 files changed
+847877
No files matched your search
+968
@@ -0,0 +1,968 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using JetBrains.Annotations;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.Video;
|
||||
#if VRC_SDK_VRCSDK3
|
||||
using VRC.SDK3.Components;
|
||||
using TMPro;
|
||||
#endif
|
||||
#if UDON
|
||||
using VRC.Udon;
|
||||
#endif
|
||||
#if !VRC_CLIENT && UNITY_EDITOR && VRC_SDK_VRCSDK3
|
||||
using UnityEditor;
|
||||
using UnityEngine.SceneManagement;
|
||||
#endif
|
||||
|
||||
namespace VRC.Core
|
||||
{
|
||||
public class UnityEventFilter
|
||||
{
|
||||
// These types are will always be prohibited even if they are derived from an allowed type.
|
||||
private static readonly HashSet<Type> _prohibitedUIEventTargetTypes = new HashSet<Type>
|
||||
{
|
||||
#if VRC_CLIENT
|
||||
typeof(RenderHeads.Media.AVProVideo.MediaPlayer),
|
||||
#endif
|
||||
#if VRC_SDK_VRCSDK3
|
||||
typeof(VRCUrlInputField),
|
||||
#endif
|
||||
typeof(VideoPlayer)
|
||||
};
|
||||
|
||||
private static readonly Lazy<Dictionary<Type, AllowedMethodFilter>> _allowedUnityEventTargetTypes =
|
||||
new Lazy<Dictionary<Type, AllowedMethodFilter>>(GetRuntimeUnityEventTargetAccessFilterDictionary);
|
||||
|
||||
private static Dictionary<Type, AllowedMethodFilter> AllowedUnityEventTargetTypes => _allowedUnityEventTargetTypes.Value;
|
||||
|
||||
private static readonly Lazy<int> _debugLevel = new Lazy<int>(InitializeLogging);
|
||||
private static int DebugLevel => _debugLevel.Value;
|
||||
|
||||
// Builds a HashSet of allowed types, and their derived types, and removes explicitly prohibited types.
|
||||
private static Dictionary<Type, AllowedMethodFilter> GetRuntimeUnityEventTargetAccessFilterDictionary()
|
||||
{
|
||||
Dictionary<Type, AllowedMethodFilter> accessFilterDictionary = new Dictionary<Type, AllowedMethodFilter>(_initialTargetAccessFilters);
|
||||
AddDerivedTypes(accessFilterDictionary);
|
||||
RemoveProhibitedTypes(accessFilterDictionary);
|
||||
|
||||
#if VERBOSE_EVENT_SANITIZATION_LOGGING
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
foreach(KeyValuePair<Type, AllowedMethodFilter> entry in accessFilterDictionary)
|
||||
{
|
||||
stringBuilder.AppendLine(entry.Key.FullName);
|
||||
AllowedMethodFilter targetMethodAccessFilter = entry.Value;
|
||||
foreach(string targetMethod in targetMethodAccessFilter.GetTargetMethodNames())
|
||||
{
|
||||
stringBuilder.AppendLine($" {targetMethod}");
|
||||
}
|
||||
|
||||
stringBuilder.AppendLine();
|
||||
}
|
||||
|
||||
VerboseLog(stringBuilder.ToString());
|
||||
#endif
|
||||
|
||||
return accessFilterDictionary;
|
||||
}
|
||||
|
||||
#if !VRC_CLIENT && UNITY_EDITOR && VRC_SDK_VRCSDK3
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
private static void SetupPlayMode()
|
||||
{
|
||||
EditorApplication.playModeStateChanged += RunFilteringOnPlayModeEntry;
|
||||
}
|
||||
|
||||
private static void RunFilteringOnPlayModeEntry(PlayModeStateChange playModeStateChange)
|
||||
{
|
||||
switch(playModeStateChange)
|
||||
{
|
||||
case PlayModeStateChange.EnteredPlayMode:
|
||||
{
|
||||
for(int sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++)
|
||||
{
|
||||
Scene currentScene = SceneManager.GetSceneAt(sceneIndex);
|
||||
List<GameObject> rootGameObjects = new List<GameObject>();
|
||||
currentScene.GetRootGameObjects(rootGameObjects);
|
||||
|
||||
FilterUIEvents(rootGameObjects);
|
||||
FilterAnimatorEvents(rootGameObjects);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PlayModeStateChange.EnteredEditMode:
|
||||
case PlayModeStateChange.ExitingEditMode:
|
||||
case PlayModeStateChange.ExitingPlayMode:
|
||||
{
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(playModeStateChange), playModeStateChange, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private static int InitializeLogging()
|
||||
{
|
||||
int hashCode = typeof(UnityEventFilter).GetHashCode();
|
||||
Logger.DescribeDebugLevel(hashCode, "UnityEventFilter", Logger.Color.red);
|
||||
Logger.AddDebugLevel(hashCode);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static void FilterUIEvents(GameObject gameObject)
|
||||
{
|
||||
List<UIBehaviour> uiBehaviours = new List<UIBehaviour>();
|
||||
gameObject.GetComponentsInChildren(true, uiBehaviours);
|
||||
|
||||
FilterUIBehaviourEvents(uiBehaviours);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static void FilterUIEvents(List<GameObject> gameObjects)
|
||||
{
|
||||
HashSet<UIBehaviour> uiBehaviours = new HashSet<UIBehaviour>();
|
||||
List<UIBehaviour> uiBehavioursWorkingList = new List<UIBehaviour>();
|
||||
foreach(GameObject gameObject in gameObjects)
|
||||
{
|
||||
gameObject.GetComponentsInChildren(true, uiBehavioursWorkingList);
|
||||
uiBehaviours.UnionWith(uiBehavioursWorkingList);
|
||||
}
|
||||
|
||||
FilterUIBehaviourEvents(uiBehaviours);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static void FilterAnimatorEvents(GameObject gameObject)
|
||||
{
|
||||
List<Animator> animators = new List<Animator>();
|
||||
gameObject.GetComponentsInChildren(true, animators);
|
||||
|
||||
FilterAnimatorEvents(animators);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static void FilterAnimatorEvents(List<GameObject> gameObjects)
|
||||
{
|
||||
HashSet<Animator> animators = new HashSet<Animator>();
|
||||
List<Animator> animatorsWorkingList = new List<Animator>();
|
||||
foreach(GameObject gameObject in gameObjects)
|
||||
{
|
||||
gameObject.GetComponentsInChildren(true, animatorsWorkingList);
|
||||
animators.UnionWith(animatorsWorkingList);
|
||||
}
|
||||
|
||||
FilterAnimatorEvents(animators);
|
||||
}
|
||||
|
||||
private static void FilterUIBehaviourEvents(IEnumerable<UIBehaviour> uiBehaviours)
|
||||
{
|
||||
Dictionary<Type, List<UIBehaviour>> uiBehavioursByType = new Dictionary<Type, List<UIBehaviour>>();
|
||||
foreach(UIBehaviour uiBehaviour in uiBehaviours)
|
||||
{
|
||||
if(uiBehaviour == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Type uiBehaviourType = uiBehaviour.GetType();
|
||||
if(!uiBehavioursByType.TryGetValue(uiBehaviourType, out List<UIBehaviour> uiBehavioursOfType))
|
||||
{
|
||||
uiBehavioursByType.Add(uiBehaviourType, new List<UIBehaviour> {uiBehaviour});
|
||||
continue;
|
||||
}
|
||||
|
||||
uiBehavioursOfType.Add(uiBehaviour);
|
||||
}
|
||||
|
||||
foreach(KeyValuePair<Type, List<UIBehaviour>> uiBehavioursOfTypeKvp in uiBehavioursByType)
|
||||
{
|
||||
Type uiBehaviourType = uiBehavioursOfTypeKvp.Key;
|
||||
FieldInfo[] fieldInfos = uiBehaviourType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
|
||||
List<FieldInfo> unityEventFieldInfos = new List<FieldInfo>();
|
||||
foreach(FieldInfo fieldInfo in fieldInfos)
|
||||
{
|
||||
if(typeof(UnityEventBase).IsAssignableFrom(fieldInfo.FieldType))
|
||||
{
|
||||
unityEventFieldInfos.Add(fieldInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if(unityEventFieldInfos.Count <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FieldInfo persistentCallsGroupFieldInfo = typeof(UnityEventBase).GetField("m_PersistentCalls", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if(persistentCallsGroupFieldInfo == null)
|
||||
{
|
||||
VerboseLog($"Could not find 'm_PersistentCalls' on UnityEventBase.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(UIBehaviour uiBehaviour in uiBehavioursOfTypeKvp.Value)
|
||||
{
|
||||
VerboseLog($"Checking '{uiBehaviour.name} for UI Events.", uiBehaviour);
|
||||
foreach(FieldInfo unityEventFieldInfo in unityEventFieldInfos)
|
||||
{
|
||||
VerboseLog($"Checking field '{unityEventFieldInfo.Name}' on '{uiBehaviour.name}.", uiBehaviour);
|
||||
UnityEventBase unityEventBase = unityEventFieldInfo.GetValue(uiBehaviour) as UnityEventBase;
|
||||
if(unityEventBase == null)
|
||||
{
|
||||
VerboseLog($"Null '{unityEventFieldInfo.Name}' UnityEvent on {uiBehaviour.name}.", uiBehaviour);
|
||||
continue;
|
||||
}
|
||||
|
||||
int numEventListeners = unityEventBase.GetPersistentEventCount();
|
||||
VerboseLog($"There are '{numEventListeners}' on event '{unityEventFieldInfo.Name}' on '{uiBehaviour.name}.", uiBehaviour);
|
||||
for(int index = 0; index < numEventListeners; index++)
|
||||
{
|
||||
string persistentMethodName = unityEventBase.GetPersistentMethodName(index);
|
||||
|
||||
UnityEngine.Object persistentTarget = unityEventBase.GetPersistentTarget(index);
|
||||
if(persistentTarget == null)
|
||||
{
|
||||
VerboseLog($"The target for listener '{index}' on event '{unityEventFieldInfo.Name}' on '{uiBehaviour.name} is null.", uiBehaviour);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(IsTargetPermitted(persistentTarget, persistentMethodName))
|
||||
{
|
||||
VerboseLog(
|
||||
$"Allowing event '{unityEventFieldInfo.Name}' on '{uiBehaviour.name}' to call '{persistentMethodName}' on target '{persistentTarget.name}'.",
|
||||
uiBehaviour);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
LogRemoval(
|
||||
$"Events on '{uiBehaviour.name}' were removed because one of them targeted a prohibited type '{persistentTarget.GetType().Name}', method '{persistentMethodName}' or object '{persistentTarget.name}'.",
|
||||
uiBehaviour);
|
||||
|
||||
unityEventFieldInfo.SetValue(uiBehaviour, Activator.CreateInstance(unityEventBase.GetType()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void FilterAnimatorEvents(IEnumerable<Animator> animators)
|
||||
{
|
||||
foreach(Animator animator in animators)
|
||||
{
|
||||
if(animator == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RuntimeAnimatorController animatorController = animator.runtimeAnimatorController;
|
||||
if(animatorController == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(AnimationClip animationClip in animatorController.animationClips)
|
||||
{
|
||||
if(animationClip == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach(AnimationEvent animationEvent in animationClip.events)
|
||||
{
|
||||
if(animationEvent == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string animationEventFunctionName = animationEvent.functionName;
|
||||
if(_allowedAnimationEventFunctionNames.Contains(animationEventFunctionName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
animationClip.events = null;
|
||||
LogRemoval(
|
||||
$"Removed AnimationEvents from AnimationClip used by the Animator on '{animator.gameObject}' because the event targets '{animationEventFunctionName}' which is not allowed.");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("VERBOSE_EVENT_SANITIZATION_LOGGING")]
|
||||
private static void VerboseLog(string message, UnityEngine.Object target = null)
|
||||
{
|
||||
Logger.LogWarning(message, DebugLevel, target);
|
||||
}
|
||||
|
||||
private static void LogRemoval(string message, UnityEngine.Object target = null)
|
||||
{
|
||||
Logger.LogWarning(message, DebugLevel, target);
|
||||
}
|
||||
|
||||
private static bool IsTargetPermitted(UnityEngine.Object target, string targetMethod)
|
||||
{
|
||||
// Block anything blacklisted by Udon to prevent UnityEvents from being used to bypass the blacklist.
|
||||
// NOTE: This will only block events targeting objects that are blacklisted before the UnityEventSanitizer is run.
|
||||
// If objects are added to the blacklist after scene loading has finished it will be necessary to re-run the UnityEventSanitizer.
|
||||
#if UDON
|
||||
if(UdonManager.Instance.IsBlacklisted(target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
Type persistentTargetType = target.GetType();
|
||||
if(!AllowedUnityEventTargetTypes.TryGetValue(persistentTargetType, out AllowedMethodFilter accessFilter))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return accessFilter.IsTargetMethodAllowed(targetMethod);
|
||||
}
|
||||
|
||||
// Adds types derived from whitelisted types.
|
||||
private static void AddDerivedTypes(Dictionary<Type, AllowedMethodFilter> accessFilterDictionary)
|
||||
{
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
foreach(Assembly assembly in assemblies)
|
||||
{
|
||||
foreach(Type type in assembly.GetTypes())
|
||||
{
|
||||
if(accessFilterDictionary.ContainsKey(type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!typeof(Component).IsAssignableFrom(type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Type currentType = type;
|
||||
while(currentType != typeof(object) && currentType != null)
|
||||
{
|
||||
if(accessFilterDictionary.TryGetValue(currentType, out AllowedMethodFilter accessFilter))
|
||||
{
|
||||
accessFilterDictionary.Add(type, accessFilter);
|
||||
break;
|
||||
}
|
||||
|
||||
currentType = currentType.BaseType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Removes prohibited types and types derived from them.
|
||||
private static void RemoveProhibitedTypes(Dictionary<Type, AllowedMethodFilter> accessFilterDictionary)
|
||||
{
|
||||
foreach(Type prohibitedType in _prohibitedUIEventTargetTypes)
|
||||
{
|
||||
foreach(Type accessFilterType in accessFilterDictionary.Keys.ToArray())
|
||||
{
|
||||
if(prohibitedType.IsAssignableFrom(accessFilterType))
|
||||
{
|
||||
accessFilterDictionary.Remove(accessFilterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Type, AllowedMethodFilter> _initialTargetAccessFilters = new Dictionary<Type, AllowedMethodFilter>
|
||||
{
|
||||
{
|
||||
typeof(GameObject), new AllowedMethodFilter(
|
||||
new List<string>
|
||||
{
|
||||
nameof(GameObject.SetActive)
|
||||
},
|
||||
new List<string>())
|
||||
},
|
||||
{
|
||||
typeof(AudioSource),
|
||||
new AllowedMethodFilter(
|
||||
new List<string>
|
||||
{
|
||||
nameof(AudioSource.Pause),
|
||||
nameof(AudioSource.Play),
|
||||
nameof(AudioSource.PlayDelayed),
|
||||
nameof(AudioSource.PlayOneShot),
|
||||
nameof(AudioSource.Stop),
|
||||
nameof(AudioSource.UnPause)
|
||||
},
|
||||
new List<string>
|
||||
{
|
||||
nameof(AudioSource.bypassEffects),
|
||||
nameof(AudioSource.bypassListenerEffects),
|
||||
nameof(AudioSource.bypassReverbZones),
|
||||
nameof(AudioSource.dopplerLevel),
|
||||
nameof(AudioSource.enabled),
|
||||
nameof(AudioSource.loop),
|
||||
nameof(AudioSource.maxDistance),
|
||||
nameof(AudioSource.rolloffMode),
|
||||
nameof(AudioSource.minDistance),
|
||||
nameof(AudioSource.mute),
|
||||
nameof(AudioSource.pitch),
|
||||
nameof(AudioSource.playOnAwake),
|
||||
nameof(AudioSource.priority),
|
||||
nameof(AudioSource.spatialize),
|
||||
nameof(AudioSource.spread),
|
||||
nameof(AudioSource.time),
|
||||
nameof(AudioSource.volume)
|
||||
}
|
||||
)
|
||||
},
|
||||
{
|
||||
typeof(AudioDistortionFilter), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(AudioDistortionFilter.distortionLevel),
|
||||
nameof(AudioDistortionFilter.enabled)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(AudioEchoFilter), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(AudioEchoFilter.decayRatio),
|
||||
nameof(AudioEchoFilter.delay),
|
||||
nameof(AudioEchoFilter.dryMix),
|
||||
nameof(AudioEchoFilter.enabled),
|
||||
nameof(AudioEchoFilter.wetMix)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(AudioHighPassFilter), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(AudioHighPassFilter.cutoffFrequency),
|
||||
nameof(AudioHighPassFilter.enabled),
|
||||
nameof(AudioHighPassFilter.highpassResonanceQ)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(AudioLowPassFilter), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(AudioLowPassFilter.cutoffFrequency),
|
||||
nameof(AudioLowPassFilter.enabled),
|
||||
nameof(AudioLowPassFilter.lowpassResonanceQ)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(AudioReverbFilter), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(AudioReverbFilter.decayHFRatio),
|
||||
nameof(AudioReverbFilter.decayTime),
|
||||
nameof(AudioReverbFilter.density),
|
||||
nameof(AudioReverbFilter.diffusion),
|
||||
nameof(AudioReverbFilter.dryLevel),
|
||||
nameof(AudioReverbFilter.enabled),
|
||||
nameof(AudioReverbFilter.hfReference),
|
||||
nameof(AudioReverbFilter.reflectionsDelay),
|
||||
nameof(AudioReverbFilter.reflectionsLevel),
|
||||
nameof(AudioReverbFilter.reverbDelay),
|
||||
nameof(AudioReverbFilter.reverbLevel),
|
||||
nameof(AudioReverbFilter.room),
|
||||
nameof(AudioReverbFilter.roomHF),
|
||||
nameof(AudioReverbFilter.roomLF)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(AudioReverbZone), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(AudioReverbZone.decayHFRatio),
|
||||
nameof(AudioReverbZone.decayTime),
|
||||
nameof(AudioReverbZone.density),
|
||||
nameof(AudioReverbZone.diffusion),
|
||||
nameof(AudioReverbZone.enabled),
|
||||
nameof(AudioReverbZone.HFReference),
|
||||
nameof(AudioReverbZone.LFReference),
|
||||
nameof(AudioReverbZone.maxDistance),
|
||||
nameof(AudioReverbZone.minDistance),
|
||||
nameof(AudioReverbZone.reflections),
|
||||
nameof(AudioReverbZone.reflectionsDelay),
|
||||
nameof(AudioReverbZone.room),
|
||||
nameof(AudioReverbZone.roomHF),
|
||||
nameof(AudioReverbZone.roomLF)
|
||||
})
|
||||
},
|
||||
#if UDON
|
||||
{
|
||||
typeof(UdonBehaviour), new AllowedMethodFilter(
|
||||
new List<string>
|
||||
{
|
||||
nameof(UdonBehaviour.RunProgram),
|
||||
nameof(UdonBehaviour.SendCustomEvent),
|
||||
nameof(UdonBehaviour.Interact),
|
||||
},
|
||||
new List<string>()
|
||||
{
|
||||
nameof(UdonBehaviour.enabled)
|
||||
})
|
||||
},
|
||||
#endif
|
||||
{
|
||||
typeof(MeshRenderer), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(MeshRenderer.shadowCastingMode),
|
||||
nameof(MeshRenderer.enabled),
|
||||
nameof(MeshRenderer.probeAnchor),
|
||||
nameof(MeshRenderer.probeAnchor),
|
||||
nameof(MeshRenderer.receiveShadows),
|
||||
nameof(MeshRenderer.lightProbeUsage)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Collider), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Collider.enabled),
|
||||
nameof(Collider.isTrigger)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(SkinnedMeshRenderer), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(SkinnedMeshRenderer.allowOcclusionWhenDynamic),
|
||||
nameof(SkinnedMeshRenderer.shadowCastingMode),
|
||||
nameof(SkinnedMeshRenderer.enabled),
|
||||
nameof(SkinnedMeshRenderer.lightProbeProxyVolumeOverride),
|
||||
nameof(SkinnedMeshRenderer.motionVectorGenerationMode),
|
||||
nameof(SkinnedMeshRenderer.probeAnchor),
|
||||
nameof(SkinnedMeshRenderer.receiveShadows),
|
||||
nameof(SkinnedMeshRenderer.rootBone),
|
||||
nameof(SkinnedMeshRenderer.skinnedMotionVectors),
|
||||
nameof(SkinnedMeshRenderer.updateWhenOffscreen),
|
||||
nameof(SkinnedMeshRenderer.lightProbeUsage)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Light), new AllowedMethodFilter(
|
||||
new List<string>
|
||||
{
|
||||
nameof(Light.Reset)
|
||||
},
|
||||
new List<string>
|
||||
{
|
||||
nameof(Light.bounceIntensity),
|
||||
nameof(Light.colorTemperature),
|
||||
nameof(Light.cookie),
|
||||
nameof(Light.enabled),
|
||||
nameof(Light.intensity),
|
||||
nameof(Light.range),
|
||||
nameof(Light.shadowBias),
|
||||
nameof(Light.shadowNearPlane),
|
||||
nameof(Light.shadowNormalBias),
|
||||
nameof(Light.shadowStrength),
|
||||
nameof(Light.spotAngle)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(ParticleSystem), new AllowedMethodFilter(
|
||||
new List<string>
|
||||
{
|
||||
nameof(ParticleSystem.Clear),
|
||||
nameof(ParticleSystem.Emit),
|
||||
nameof(ParticleSystem.Pause),
|
||||
nameof(ParticleSystem.Pause),
|
||||
nameof(ParticleSystem.Play),
|
||||
nameof(ParticleSystem.Simulate),
|
||||
nameof(ParticleSystem.Stop),
|
||||
nameof(ParticleSystem.Stop),
|
||||
nameof(ParticleSystem.TriggerSubEmitter)
|
||||
},
|
||||
new List<string>
|
||||
{
|
||||
nameof(ParticleSystem.time),
|
||||
nameof(ParticleSystem.useAutoRandomSeed)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(ParticleSystemForceField), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(ParticleSystemForceField.endRange),
|
||||
nameof(ParticleSystemForceField.gravityFocus),
|
||||
nameof(ParticleSystemForceField.length),
|
||||
nameof(ParticleSystemForceField.multiplyDragByParticleSize),
|
||||
nameof(ParticleSystemForceField.multiplyDragByParticleVelocity),
|
||||
nameof(ParticleSystemForceField.startRange)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Projector), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Projector.aspectRatio),
|
||||
nameof(Projector.enabled),
|
||||
nameof(Projector.nearClipPlane),
|
||||
nameof(Projector.farClipPlane),
|
||||
nameof(Projector.fieldOfView),
|
||||
nameof(Projector.orthographic),
|
||||
nameof(Projector.orthographicSize)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(LineRenderer), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(LineRenderer.allowOcclusionWhenDynamic),
|
||||
nameof(LineRenderer.shadowCastingMode),
|
||||
nameof(LineRenderer.enabled),
|
||||
nameof(LineRenderer.endWidth),
|
||||
nameof(LineRenderer.loop),
|
||||
nameof(LineRenderer.motionVectorGenerationMode),
|
||||
nameof(LineRenderer.numCapVertices),
|
||||
nameof(LineRenderer.numCornerVertices),
|
||||
nameof(LineRenderer.probeAnchor),
|
||||
nameof(LineRenderer.receiveShadows),
|
||||
nameof(LineRenderer.shadowBias),
|
||||
nameof(LineRenderer.startWidth),
|
||||
nameof(LineRenderer.lightProbeUsage),
|
||||
nameof(LineRenderer.useWorldSpace),
|
||||
nameof(LineRenderer.widthMultiplier)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(TrailRenderer), new AllowedMethodFilter(
|
||||
new List<string>
|
||||
{
|
||||
nameof(TrailRenderer.Clear)
|
||||
},
|
||||
new List<string>
|
||||
{
|
||||
nameof(TrailRenderer.allowOcclusionWhenDynamic),
|
||||
nameof(TrailRenderer.autodestruct),
|
||||
nameof(TrailRenderer.shadowCastingMode),
|
||||
nameof(TrailRenderer.enabled),
|
||||
nameof(TrailRenderer.emitting),
|
||||
nameof(TrailRenderer.endWidth),
|
||||
nameof(TrailRenderer.motionVectorGenerationMode),
|
||||
nameof(TrailRenderer.numCapVertices),
|
||||
nameof(TrailRenderer.numCornerVertices),
|
||||
nameof(TrailRenderer.probeAnchor),
|
||||
nameof(TrailRenderer.receiveShadows),
|
||||
nameof(TrailRenderer.shadowBias),
|
||||
nameof(TrailRenderer.startWidth),
|
||||
nameof(TrailRenderer.lightProbeUsage),
|
||||
nameof(TrailRenderer.widthMultiplier)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Animator), new AllowedMethodFilter(
|
||||
new List<string>
|
||||
{
|
||||
nameof(Animator.Play),
|
||||
nameof(Animator.PlayInFixedTime),
|
||||
nameof(Animator.Rebind),
|
||||
nameof(Animator.SetBool),
|
||||
nameof(Animator.SetFloat),
|
||||
nameof(Animator.SetInteger),
|
||||
nameof(Animator.SetTrigger),
|
||||
nameof(Animator.ResetTrigger)
|
||||
},
|
||||
new List<string>
|
||||
{
|
||||
nameof(Animator.speed),
|
||||
nameof(Animator.enabled)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Text), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Text.alignByGeometry),
|
||||
nameof(Text.enabled),
|
||||
nameof(Text.fontSize),
|
||||
nameof(Text.lineSpacing),
|
||||
nameof(Text.maskable),
|
||||
nameof(Text.raycastTarget),
|
||||
nameof(Text.resizeTextForBestFit),
|
||||
nameof(Text.resizeTextMaxSize),
|
||||
nameof(Text.resizeTextMinSize),
|
||||
nameof(Text.supportRichText),
|
||||
nameof(Text.text)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Image), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Image.alphaHitTestMinimumThreshold),
|
||||
nameof(Image.enabled),
|
||||
nameof(Image.fillAmount),
|
||||
nameof(Image.fillCenter),
|
||||
nameof(Image.fillClockwise),
|
||||
nameof(Image.fillOrigin),
|
||||
nameof(Image.maskable),
|
||||
nameof(Image.preserveAspect),
|
||||
nameof(Image.raycastTarget),
|
||||
nameof(Image.useSpriteMesh)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(RawImage), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(RawImage.enabled),
|
||||
nameof(RawImage.maskable),
|
||||
nameof(RawImage.raycastTarget)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(InputField), new AllowedMethodFilter(
|
||||
new List<string>
|
||||
{
|
||||
"Append",
|
||||
nameof(InputField.ForceLabelUpdate)
|
||||
},
|
||||
new List<string>
|
||||
{
|
||||
nameof(InputField.caretBlinkRate),
|
||||
nameof(InputField.caretPosition),
|
||||
nameof(InputField.caretWidth),
|
||||
nameof(InputField.characterLimit),
|
||||
nameof(InputField.customCaretColor),
|
||||
nameof(InputField.enabled),
|
||||
nameof(InputField.interactable),
|
||||
nameof(InputField.readOnly),
|
||||
nameof(InputField.selectionAnchorPosition),
|
||||
nameof(InputField.text),
|
||||
nameof(InputField.textComponent),
|
||||
nameof(InputField.selectionFocusPosition)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Dropdown), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Dropdown.captionText),
|
||||
nameof(Dropdown.enabled),
|
||||
nameof(Dropdown.interactable),
|
||||
nameof(Dropdown.itemText),
|
||||
nameof(Dropdown.targetGraphic),
|
||||
nameof(Dropdown.template),
|
||||
nameof(Dropdown.value)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Slider), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Slider.enabled),
|
||||
nameof(Slider.fillRect),
|
||||
nameof(Slider.handleRect),
|
||||
nameof(Slider.interactable),
|
||||
nameof(Slider.maxValue),
|
||||
nameof(Slider.minValue),
|
||||
nameof(Slider.normalizedValue),
|
||||
nameof(Slider.targetGraphic),
|
||||
nameof(Slider.value),
|
||||
nameof(Slider.wholeNumbers)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Toggle), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Toggle.enabled),
|
||||
nameof(Toggle.group),
|
||||
nameof(Toggle.interactable),
|
||||
nameof(Toggle.isOn),
|
||||
nameof(Toggle.targetGraphic)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Scrollbar), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Scrollbar.enabled),
|
||||
nameof(Scrollbar.handleRect),
|
||||
nameof(Scrollbar.interactable),
|
||||
nameof(Scrollbar.numberOfSteps),
|
||||
nameof(Scrollbar.size),
|
||||
nameof(Scrollbar.targetGraphic),
|
||||
nameof(Scrollbar.value)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(ScrollRect), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(ScrollRect.content),
|
||||
nameof(ScrollRect.decelerationRate),
|
||||
nameof(ScrollRect.elasticity),
|
||||
nameof(ScrollRect.enabled),
|
||||
nameof(ScrollRect.horizontal),
|
||||
nameof(ScrollRect.horizontalNormalizedPosition),
|
||||
nameof(ScrollRect.horizontalScrollbar),
|
||||
nameof(ScrollRect.horizontalScrollbarSpacing),
|
||||
nameof(ScrollRect.inertia),
|
||||
nameof(ScrollRect.scrollSensitivity),
|
||||
nameof(ScrollRect.vertical),
|
||||
nameof(ScrollRect.verticalNormalizedPosition),
|
||||
nameof(ScrollRect.verticalScrollbar),
|
||||
nameof(ScrollRect.verticalScrollbarSpacing),
|
||||
nameof(ScrollRect.viewport)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Button), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Button.enabled),
|
||||
nameof(Button.interactable),
|
||||
nameof(Button.targetGraphic)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Mask), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Mask.enabled),
|
||||
nameof(Mask.showMaskGraphic)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(RectMask2D), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(RectMask2D.enabled)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Selectable), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(Selectable.enabled),
|
||||
nameof(Selectable.interactable),
|
||||
nameof(Selectable.targetGraphic)
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(ToggleGroup), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(ToggleGroup.allowSwitchOff),
|
||||
nameof(ToggleGroup.enabled)
|
||||
})
|
||||
},
|
||||
#if VRC_SDK_VRCSDK3 // only access Cinemachine and TMPro after install
|
||||
{
|
||||
typeof(TextMeshPro), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(TextMeshPro.text),
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(TextMeshProUGUI), new AllowedMethodFilter(
|
||||
new List<string>(),
|
||||
new List<string>
|
||||
{
|
||||
nameof(TextMeshProUGUI.text),
|
||||
})
|
||||
},
|
||||
{
|
||||
typeof(Cinemachine.CinemachineVirtualCamera), new AllowedMethodFilter(
|
||||
new List<string>()
|
||||
{
|
||||
nameof(Cinemachine.CinemachineVirtualCamera.Priority),
|
||||
},
|
||||
new List<string>())
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> _allowedAnimationEventFunctionNames = new HashSet<string>
|
||||
{
|
||||
"RunProgram",
|
||||
"SendCustomEvent",
|
||||
"Play",
|
||||
"Pause",
|
||||
"Stop",
|
||||
"PlayInFixedTime",
|
||||
"Rebind",
|
||||
"SetBool",
|
||||
"SetFloat",
|
||||
"SetInteger",
|
||||
"SetTrigger",
|
||||
"ResetTrigger",
|
||||
"SetActive"
|
||||
};
|
||||
|
||||
private class AllowedMethodFilter
|
||||
{
|
||||
private readonly HashSet<string> _allowedTargets;
|
||||
|
||||
[PublicAPI]
|
||||
public AllowedMethodFilter(List<string> allowedTargetMethodNames, List<string> allowedTargetPropertyNames)
|
||||
{
|
||||
_allowedTargets = new HashSet<string>();
|
||||
_allowedTargets.UnionWith(allowedTargetMethodNames);
|
||||
foreach(string allowedTargetProperty in allowedTargetPropertyNames)
|
||||
{
|
||||
_allowedTargets.Add($"get_{allowedTargetProperty}");
|
||||
_allowedTargets.Add($"set_{allowedTargetProperty}");
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsTargetMethodAllowed(string targetMethodName)
|
||||
{
|
||||
return _allowedTargets.Contains(targetMethodName);
|
||||
}
|
||||
|
||||
#if VERBOSE_EVENT_SANITIZATION_LOGGING
|
||||
public List<string> GetTargetMethodNames()
|
||||
{
|
||||
return _allowedTargets.ToList();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87f13d6a98e54fb78ca47650a29029a5
|
||||
timeCreated: 1594690552
|
||||
Reference in new issue
Block a user