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
@@ -0,0 +1,618 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.CSharp;
|
||||
using System.CodeDom;
|
||||
using UnityEngine;
|
||||
using System.Security.Cryptography;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using VRC.Udon.Graph;
|
||||
using VRC.Udon.Graph.Interfaces;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace VRC.Udon.Editor.ProgramSources.UdonGraphProgram.UI
|
||||
{
|
||||
public static class UdonGraphExtensions
|
||||
{
|
||||
private static readonly Dictionary<string, string> FriendlyNameCache;
|
||||
|
||||
static UdonGraphExtensions()
|
||||
{
|
||||
FriendlyNameCache = new Dictionary<string, string>();
|
||||
StartsWithCache = new Dictionary<(string s, string prefix), bool>();
|
||||
}
|
||||
|
||||
#region Serialization Utilities
|
||||
private const byte ZIP_VERSION = 0;
|
||||
public static string ZipString(string str)
|
||||
{
|
||||
using (MemoryStream output = new MemoryStream())
|
||||
{
|
||||
using (DeflateStream gzip =
|
||||
new DeflateStream(output, System.IO.Compression.CompressionLevel.Optimal)) //, CompressionMode.Compress
|
||||
{
|
||||
using (StreamWriter writer =
|
||||
new StreamWriter(gzip, System.Text.Encoding.UTF8))
|
||||
{
|
||||
writer.Write(str);
|
||||
}
|
||||
}
|
||||
List<byte> outputList = output.ToArray().ToList();
|
||||
outputList.Insert(0, ZIP_VERSION); //Version Number
|
||||
return Convert.ToBase64String(outputList.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static string UnZipString(string input)
|
||||
{
|
||||
List<byte> inputList = new List<byte>(Convert.FromBase64String(input));
|
||||
if (inputList[0] != ZIP_VERSION) //Version Number
|
||||
{
|
||||
return "";
|
||||
}
|
||||
inputList.RemoveAt(0);
|
||||
using (MemoryStream inputStream = new MemoryStream(inputList.ToArray()))
|
||||
{
|
||||
using (DeflateStream gzip =
|
||||
new DeflateStream(inputStream, CompressionMode.Decompress))
|
||||
{
|
||||
using (StreamReader reader =
|
||||
new StreamReader(gzip, System.Text.Encoding.UTF8))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Color Utilities
|
||||
|
||||
public static class NodeColors
|
||||
{
|
||||
public static readonly Color Base = new Color(77f / 255f, 157f / 255f, 1);
|
||||
public static readonly Color Const = new Color(0.4f, 0.14f, 1f);
|
||||
public static readonly Color Variable = new Color(1f, 0.86f, 0.3f);
|
||||
public static readonly Color Function = new Color(1f, 0.42f, 0.14f);
|
||||
public static readonly Color Event = new Color(0.53f, 1f, 0.3f);
|
||||
public static readonly Color Return = new Color(0.89f, 0.2f, 0.2f);
|
||||
}
|
||||
|
||||
private static readonly MD5 _md5Hasher = MD5.Create();
|
||||
private static readonly Dictionary<Type, Color> _typeColors = new Dictionary<Type, Color>();
|
||||
|
||||
public static Color MapTypeToColor(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
return Color.white;
|
||||
}
|
||||
|
||||
if (type.IsPrimitive)
|
||||
{
|
||||
return new Color(0.12f, 0.53f, 0.9f);
|
||||
}
|
||||
|
||||
if (typeof(UnityEngine.Object).IsAssignableFrom(type))
|
||||
{
|
||||
return new Color(0.9f, 0.23f, 0.39f);
|
||||
}
|
||||
|
||||
if (type.IsValueType)
|
||||
{
|
||||
return NodeColors.Variable;
|
||||
}
|
||||
|
||||
if (_typeColors.ContainsKey(type))
|
||||
{
|
||||
return _typeColors[type];
|
||||
}
|
||||
|
||||
byte[] hashed = _md5Hasher.ComputeHash(type.ToString() == "T"
|
||||
? System.Text.Encoding.UTF8.GetBytes("T")
|
||||
: System.Text.Encoding.UTF8.GetBytes(type.Name));
|
||||
int iValue = BitConverter.ToInt32(hashed, 0);
|
||||
|
||||
//TODO: Make this provide more varied colors
|
||||
Color color = Color.HSVToRGB((iValue & 0xff) / 255f, .69f, 1f);
|
||||
|
||||
|
||||
_typeColors.Add(type, color);
|
||||
return color;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Documentation Utilities
|
||||
|
||||
public static bool ShouldShowDocumentationLink(UdonNodeDefinition definition)
|
||||
{
|
||||
List<string> specialNames = new List<string>
|
||||
{
|
||||
"Block",
|
||||
"Branch",
|
||||
"For",
|
||||
"While",
|
||||
"Foreach",
|
||||
"Get_Variable",
|
||||
"Set_Variable",
|
||||
"Event_Custom",
|
||||
"Event_OnDataStorageAdded",
|
||||
"Event_OnDataStorageChanged",
|
||||
"Event_OnDataStorageRemoved",
|
||||
"Event_OnDrop",
|
||||
"Event_Interact",
|
||||
"Event_OnNetworkReady",
|
||||
"Event_OnOwnershipTransferred",
|
||||
"Event_OnPickup",
|
||||
"Event_OnPickupUseDown",
|
||||
"Event_OnPickupUseUp",
|
||||
"Event_OnPlayerJoined",
|
||||
"Event_OnPlayerLeft",
|
||||
"Event_OnSpawn",
|
||||
"Event_OnStationEntered",
|
||||
"Event_OnStationExited",
|
||||
"Event_OnVideoEnd",
|
||||
"Event_OnVideoPause",
|
||||
"Event_OnVideoPlay",
|
||||
"Event_OnVideoStart",
|
||||
"VRCUdonCommonInterfacesIUdonEventReceiver.__SendCustomEvent__SystemString__SystemVoid",
|
||||
"VRCUdonCommonInterfacesIUdonEventReceiver.__SetHeapVariable__SystemString_SystemObject__SystemVoid",
|
||||
"VRCUdonCommonInterfacesIUdonEventReceiver.__GetHeapVariable__SystemString__SystemObject",
|
||||
"Const_VRCUdonCommonInterfacesIUdonEventReceiver",
|
||||
};
|
||||
|
||||
// Don't show for any of these
|
||||
return !(definition.type == null ||
|
||||
definition.type.Namespace == null ||
|
||||
specialNames.Contains(definition.fullName) ||
|
||||
(!definition.type.Namespace.Contains("UnityEngine") &&
|
||||
!definition.type.Namespace.Contains("System")));
|
||||
}
|
||||
|
||||
public static string GetDocumentationLink(UdonNodeDefinition definition)
|
||||
{
|
||||
if (definition.fullName.StartsWithCached("Event_"))
|
||||
{
|
||||
string url = "https://docs.unity3d.com/2018.4/Documentation/ScriptReference/MonoBehaviour.";
|
||||
url += definition.name;
|
||||
url += ".html";
|
||||
return url;
|
||||
}
|
||||
|
||||
if (definition.fullName.Contains("Array.__ctor"))
|
||||
{
|
||||
//I couldn't find the array constructor documentation
|
||||
return "https://docs.microsoft.com/en-us/dotnet/api/system.array?view=netframework-4.8";
|
||||
}
|
||||
|
||||
if (definition.fullName.Contains("Array.__Get"))
|
||||
{
|
||||
return "https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#indexer-operator-";
|
||||
}
|
||||
|
||||
if (definition.fullName.Contains(".__Equals__SystemObject"))
|
||||
{
|
||||
return "https://docs.microsoft.com/en-us/dotnet/api/system.object.equals?view=netframework-4.8";
|
||||
}
|
||||
|
||||
if (definition.name.Contains("[]"))
|
||||
{
|
||||
string url = "https://docs.microsoft.com/en-us/dotnet/api/system.array.";
|
||||
url += definition.name.Split(' ')[1];
|
||||
url += "?view=netframework-4.8";
|
||||
return url;
|
||||
}
|
||||
|
||||
if (definition.type.Namespace.Contains("UnityEngine"))
|
||||
{
|
||||
string url = "https://docs.unity3d.com/2018.4/Documentation/ScriptReference/";
|
||||
if (definition.type.Namespace != "UnityEngine")
|
||||
{
|
||||
url += definition.type.Namespace.Replace("UnityEngine.", "");
|
||||
url += ".";
|
||||
}
|
||||
url += definition.type.Name;
|
||||
|
||||
if (definition.fullName.Contains("__get_") || definition.fullName.Contains("__set_"))
|
||||
{
|
||||
if (definition.fullName.Contains("__get_"))
|
||||
{
|
||||
url += "-" + definition.name.Split(new[] { "get_" }, StringSplitOptions.None)[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
url += "-" + definition.name.Split(new[] { "set_" }, StringSplitOptions.None)[1];
|
||||
}
|
||||
|
||||
url += ".html";
|
||||
return url;
|
||||
}
|
||||
|
||||
if (definition.fullName.Contains("Const_") || definition.fullName.Contains("Type_") || definition.fullName.Contains("Variable_"))
|
||||
{
|
||||
url += ".html";
|
||||
return url;
|
||||
}
|
||||
|
||||
{
|
||||
// Methods
|
||||
url += "." + definition.name.Split(' ')[1];
|
||||
url += ".html";
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
if (definition.type.Namespace.Contains("System"))
|
||||
{
|
||||
string url = "https://docs.microsoft.com/en-us/dotnet/api/system.";
|
||||
url += definition.type.Name;
|
||||
if (definition.fullName.Contains("__get_") || definition.fullName.Contains("__set_"))
|
||||
{
|
||||
url += "." + definition.name.Split(' ')[1].Replace("get_", "").Replace("set_", "");
|
||||
url += "?view=netframework-4.8";
|
||||
return url;
|
||||
}
|
||||
|
||||
if (definition.name == "ctor")
|
||||
{
|
||||
url += ".-ctor";
|
||||
url += "?view=netframework-4.8#System_";
|
||||
url += definition.type.Name + "__ctor_";
|
||||
foreach (var pType in definition.Inputs)
|
||||
{
|
||||
url += "System_" + pType.type.Name.Replace('[', '_').Replace(']', '_') + "_";
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
if (definition.fullName.Contains("Const_") || definition.fullName.Contains("Type_"))
|
||||
{
|
||||
url += "?view=netframework-4.8";
|
||||
return url;
|
||||
}
|
||||
|
||||
{
|
||||
// Methods
|
||||
// not entirely sure what case this catches, but we were always doing the split before, and it was breaking if we didn't have . in the name.
|
||||
if (definition.name.Contains('.'))
|
||||
{
|
||||
url += "." + definition.name.Split(' ')[1];
|
||||
}
|
||||
url += "?view=netframework-4.8";
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static string FriendlyNameify(this string typeString)
|
||||
{
|
||||
if (typeString == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (FriendlyNameCache.ContainsKey(typeString))
|
||||
{
|
||||
return FriendlyNameCache[typeString];
|
||||
}
|
||||
string originalString = typeString;
|
||||
typeString = typeString.Replace("Single", "float");
|
||||
typeString = typeString.Replace("Int32", "int");
|
||||
typeString = typeString.Replace("String", "string");
|
||||
typeString = typeString.Replace("VRCUdonCommonInterfacesIUdonEventReceiver", "UdonBehaviour");
|
||||
typeString = typeString.Replace("UdonCommonInterfacesIUdonEventReceiver", "UdonBehaviour");
|
||||
typeString = typeString.Replace("IUdonEventReceiver", "UdonBehaviour");
|
||||
typeString = typeString.Replace("Const_VRCUdonCommonInterfacesIUdonEventReceiver", "UdonBehaviour");
|
||||
typeString = typeString.Replace("Array", "[]");
|
||||
typeString = typeString.Replace("SDK3VideoComponentsBaseBase", "");
|
||||
typeString = typeString.Replace("SDKBase", "");
|
||||
typeString = typeString.Replace("SDK3Components", "");
|
||||
typeString = typeString.Replace("VRCVRC", "VRC");
|
||||
typeString = typeString.Replace("TMPro", "");
|
||||
// ReSharper disable once StringLiteralTypo
|
||||
if (typeString.Replace("ector", "").Contains("ctor")) //Handle "Vector/vector"
|
||||
{
|
||||
typeString = typeString.ReplaceLast("ctor", "constructor");
|
||||
}
|
||||
|
||||
if (typeString == "IUdonEventReceiver")
|
||||
{
|
||||
typeString = "UdonBehaviour";
|
||||
}
|
||||
FriendlyNameCache.Add(originalString, typeString);
|
||||
return typeString;
|
||||
}
|
||||
|
||||
private static readonly Dictionary<(string s, string prefix), bool> StartsWithCache;
|
||||
public static bool StartsWithCached(this string s, string prefix)
|
||||
{
|
||||
if (StartsWithCache.ContainsKey((s, prefix)))
|
||||
{
|
||||
return StartsWithCache[(s, prefix)];
|
||||
}
|
||||
bool doesStartWith = s.StartsWith(prefix);
|
||||
StartsWithCache.Add((s, prefix), doesStartWith);
|
||||
return doesStartWith;
|
||||
}
|
||||
|
||||
public static string UppercaseFirst(this string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
char[] a = s.ToCharArray();
|
||||
a[0] = char.ToUpper(a[0]);
|
||||
return new string(a);
|
||||
}
|
||||
|
||||
public static string ReplaceFirst(this string text, string search, string replace)
|
||||
{
|
||||
int pos = text.IndexOf(search, StringComparison.Ordinal);
|
||||
if (pos < 0)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
|
||||
}
|
||||
|
||||
public static Type SlotTypeConverter(Type type, string fullName)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
return typeof(object);
|
||||
}
|
||||
|
||||
if (fullName.Contains("IUdonEventReceiver") && type == typeof(UnityEngine.Object))
|
||||
{
|
||||
return typeof(UdonBehaviour);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
public static string FriendlyTypeName(Type t)
|
||||
{
|
||||
if (t == null)
|
||||
{
|
||||
return "Flow";
|
||||
}
|
||||
|
||||
if (!t.IsPrimitive)
|
||||
{
|
||||
if (t == typeof(UnityEngine.Object))
|
||||
{
|
||||
return "Unity Object";
|
||||
}
|
||||
return t.Name;
|
||||
}
|
||||
using (CSharpCodeProvider provider = new CSharpCodeProvider())
|
||||
{
|
||||
CodeTypeReference typeRef = new CodeTypeReference(t);
|
||||
return provider.GetTypeOutput(typeRef);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReplaceLast(this string source, string find, string replace)
|
||||
{
|
||||
int place = source.LastIndexOf(find, StringComparison.Ordinal);
|
||||
|
||||
if (place == -1)
|
||||
return source;
|
||||
|
||||
string result = source.Remove(place, find.Length).Insert(place, replace);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string PrettyBaseName(string baseIdentifier)
|
||||
{
|
||||
string result = baseIdentifier.Replace("UnityEngine", "").Replace("System", "");
|
||||
string[] resultSplit = result.Split(new[] { "__" }, StringSplitOptions.None);
|
||||
if (resultSplit.Length >= 2)
|
||||
{
|
||||
result = $"{resultSplit[0]}{resultSplit[1]}";
|
||||
}
|
||||
result = result.FriendlyNameify();
|
||||
result = result.Replace("op_", "");
|
||||
result = result.Replace("_", " ");
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string PrettyString(string s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case "op_Equality":
|
||||
s = "==";
|
||||
break;
|
||||
|
||||
case "op_Inequality":
|
||||
s = "!=";
|
||||
break;
|
||||
|
||||
case "op_Addition":
|
||||
s = "+";
|
||||
break;
|
||||
case "VRCUdonCommonInterfacesIUdonEventReceiver":
|
||||
s = "UdonBehaviour";
|
||||
break;
|
||||
// ReSharper disable once RedundantEmptySwitchSection
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public static string ParseByCase(string strInput)
|
||||
{
|
||||
string strOutput = "";
|
||||
int intCurrentCharPos = 0;
|
||||
int intLastCharPos = strInput.Length - 1;
|
||||
for (intCurrentCharPos = 0; intCurrentCharPos <= intLastCharPos; intCurrentCharPos++)
|
||||
{
|
||||
char chrCurrentInputChar = strInput[intCurrentCharPos];
|
||||
char chrPreviousInputChar = chrCurrentInputChar;
|
||||
if (intCurrentCharPos > 0)
|
||||
{
|
||||
chrPreviousInputChar = strInput[intCurrentCharPos - 1];
|
||||
}
|
||||
|
||||
if (char.IsUpper(chrCurrentInputChar) && char.IsLower(chrPreviousInputChar))
|
||||
{
|
||||
strOutput += " ";
|
||||
}
|
||||
|
||||
strOutput += chrCurrentInputChar;
|
||||
}
|
||||
|
||||
return strOutput;
|
||||
}
|
||||
|
||||
public static string PrettyFullName(Graph.UdonNodeDefinition nodeDefinition, bool keepLong = false)
|
||||
{
|
||||
string fullName = nodeDefinition.fullName;
|
||||
string result;
|
||||
if (keepLong)
|
||||
{
|
||||
result = fullName.Replace("UnityEngine", "UnityEngine.").Replace("System", "System.");
|
||||
}
|
||||
else
|
||||
{
|
||||
result = fullName.Replace("UnityEngine", "").Replace("System", "");
|
||||
}
|
||||
|
||||
string[] resultSplit = result.Split(new[] { "__" }, StringSplitOptions.None);
|
||||
if (resultSplit.Length >= 3)
|
||||
{
|
||||
string outName = "";
|
||||
if (nodeDefinition.type != typeof(void))
|
||||
{
|
||||
if (nodeDefinition.Outputs.Count > 0)
|
||||
{
|
||||
outName = string.Join(", ", nodeDefinition.Outputs.Select(o => o.name));
|
||||
}
|
||||
}
|
||||
|
||||
result = nodeDefinition.Inputs.Count > 0
|
||||
? $"{resultSplit[0]}{resultSplit[1]}({string.Join(", ", nodeDefinition.Inputs.Select(s => s.name))}{outName})"
|
||||
: $"{resultSplit[0]}{resultSplit[1]}({resultSplit[2].Replace("_", ", ")}{outName})";
|
||||
}
|
||||
else if (resultSplit.Length >= 2)
|
||||
{
|
||||
result = $"{resultSplit[0]}{resultSplit[1]}()";
|
||||
}
|
||||
|
||||
if (!keepLong)
|
||||
{
|
||||
result = result.FriendlyNameify();
|
||||
result = result.Replace("op_", "");
|
||||
result = result.Replace("_", " ");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string GetSimpleNameForRegistry(Graph.Interfaces.INodeRegistry registry)
|
||||
{
|
||||
string registryName = registry.ToString().Replace("NodeRegistry", "").FriendlyNameify();
|
||||
registryName = registryName.Substring(registryName.LastIndexOf(".") + 1);
|
||||
registryName = registryName.Replace("UnityEngine", "");
|
||||
return registryName;
|
||||
}
|
||||
|
||||
private static Dictionary<UdonNodeDefinition, INodeRegistry> _definitionToRegistryLookup;
|
||||
public static INodeRegistry GetRegistryForDefinition(UdonNodeDefinition definition)
|
||||
{
|
||||
// Create lookup if needed
|
||||
if(_definitionToRegistryLookup == null)
|
||||
{
|
||||
_definitionToRegistryLookup = new Dictionary<UdonNodeDefinition, INodeRegistry>();
|
||||
|
||||
foreach (var registry in UdonEditorManager.Instance.GetNodeRegistries())
|
||||
{
|
||||
foreach (var nodeDefinition in registry.Value.GetNodeDefinitions())
|
||||
{
|
||||
_definitionToRegistryLookup.Add(nodeDefinition, registry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return found Registry or Null
|
||||
if (_definitionToRegistryLookup.ContainsKey(definition))
|
||||
{
|
||||
return _definitionToRegistryLookup[definition];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToLowerFirstChar(this string input)
|
||||
{
|
||||
string newString = input;
|
||||
if (!String.IsNullOrEmpty(newString) && Char.IsUpper(newString[0]))
|
||||
newString = Char.ToLower(newString[0]) + newString.Substring(1);
|
||||
return newString;
|
||||
}
|
||||
|
||||
public static string SanitizeVariableName(this string result)
|
||||
{
|
||||
result = result.Replace(" ", "");
|
||||
if (char.IsNumber(result[0]))
|
||||
{
|
||||
result = $"A{result}";
|
||||
}
|
||||
Regex rgx = new Regex("[^a-zA-Z0-9 _]");
|
||||
result = rgx.Replace(result, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
public static char EscapeLikeALiteral(string src)
|
||||
{
|
||||
switch (src)
|
||||
{
|
||||
//case "\\'": return '\'';
|
||||
//case "\\"": return '\"';
|
||||
case "\\0": return '\0';
|
||||
case "\\a": return '\a';
|
||||
case "\\b": return '\b';
|
||||
case "\\f": return '\f';
|
||||
case "\\n": return '\n';
|
||||
case "\\r": return '\r';
|
||||
case "\\t": return '\t';
|
||||
case "\\v": return '\v';
|
||||
case "\\": return '\\';
|
||||
default:
|
||||
throw new InvalidOperationException($"src was {src}");
|
||||
}
|
||||
}
|
||||
|
||||
public static string UnescapeLikeALiteral(char src)
|
||||
{
|
||||
switch (src)
|
||||
{
|
||||
//case "\\'": return '\'';
|
||||
//case "\\"": return '\"';
|
||||
case '\0': return "\\0";
|
||||
case '\a': return "\\a";
|
||||
case '\b': return "\\b";
|
||||
case '\f': return "\\f";
|
||||
case '\n': return "\\n";
|
||||
case '\r': return "\\r";
|
||||
case '\t': return "\\t";
|
||||
case '\v': return "\\v";
|
||||
//case '\\': return "\\";
|
||||
default:
|
||||
return src.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user