Esempio n. 1
0
        /// <summary>
        /// Verifies that Udon supports the given type and resolves the type name used to reference it in Udon
        /// </summary>
        /// <param name="externType">The found type</param>
        /// <param name="skipBaseTypeRemap">Skips remapping base VRCSDK types, this is primarily used for VRCSDK function return value types since they may point to the base type and we want to maintain that.</param>
        /// <returns>The Udon type name string if it is a valid Udon type,
        ///     or null if it is not a valid Udon type.</returns>
        public string GetUdonTypeName(System.Type externType, bool skipBaseTypeRemap = false)
        {
            if (!skipBaseTypeRemap)
            {
                externType = UdonSharpUtils.RemapBaseType(externType);
            }

            string externTypeName = externType.GetNameWithoutGenericArity();

            while (externType.IsArray || externType.IsByRef)
            {
                externType = externType.GetElementType();
            }

            string typeNamespace = externType.Namespace;

            // Handle nested type names (+ sign in names)
            if (externType.DeclaringType != null)
            {
                string declaringTypeNamespace = "";

                System.Type declaringType = externType.DeclaringType;

                while (declaringType != null)
                {
                    declaringTypeNamespace = $"{externType.DeclaringType.Name}.{declaringTypeNamespace}";
                    declaringType          = declaringType.DeclaringType;
                }

                typeNamespace += $".{declaringTypeNamespace}";
            }

            if (externTypeName == "T" || externTypeName == "T[]")
            {
                typeNamespace = "";
            }

            string fullTypeName = SanitizeTypeName($"{typeNamespace}.{externTypeName}");

            foreach (System.Type genericType in externType.GetGenericArguments())
            {
                fullTypeName += GetUdonTypeName(genericType);
            }

            // Seems like Udon does shortening for this specific type somewhere
            if (fullTypeName == "SystemCollectionsGenericListT")
            {
                fullTypeName = "ListT";
            }
            else if (fullTypeName == "SystemCollectionsGenericIEnumerableT")
            {
                fullTypeName = "IEnumerableT";
            }

            fullTypeName = fullTypeName.Replace("VRCUdonUdonBehaviour", "VRCUdonCommonInterfacesIUdonEventReceiver");

            return(fullTypeName);
        }
Esempio n. 2
0
        public string GetUdonFieldAccessorName(FieldInfo externField, FieldAccessorType accessorType, bool validate = true)
        {
            System.Type fieldType = UdonSharpUtils.RemapBaseType(externField.DeclaringType);

            string functionNamespace = SanitizeTypeName(fieldType.FullName).Replace("VRCUdonUdonBehaviour", "VRCUdonCommonInterfacesIUdonEventReceiver");
            string methodName        = $"__{(accessorType == FieldAccessorType.Get ? "get" : "set")}_{externField.Name.Trim('_')}";

            string paramStr = $"__{GetUdonTypeName(externField.FieldType)}";

            string finalFunctionSig = $"{functionNamespace}.{methodName}{paramStr}";

            if (validate && !nodeDefinitionLookup.Contains(finalFunctionSig))
            {
                throw new System.Exception($"Field accessor {finalFunctionSig} is not exposed in Udon");
            }

            return(finalFunctionSig);
        }
Esempio n. 3
0
        /// <summary>
        /// Verifies that Udon supports the given method and resolves the name used to reference it in Udon EXTERN calls
        /// </summary>
        /// <param name="externMethod"></param>
        /// <returns></returns>
        public string GetUdonMethodName(MethodBase externMethod, bool validate = true, List <System.Type> genericArguments = null)
        {
            System.Type methodSourceType = externMethod.ReflectedType;

            if (genericArguments != null)
            {
                if (genericArguments.Count != 1)
                {
                    throw new System.ArgumentException("UdonSharp only supports 1 type generic methods at the moment");
                }

                methodSourceType = genericArguments.First();
            }

            methodSourceType = UdonSharpUtils.RemapBaseType(methodSourceType);

            bool isUdonSharpBehaviour = false;

            if (methodSourceType == typeof(UdonSharpBehaviour) || methodSourceType.IsSubclassOf(typeof(UdonSharpBehaviour)))
            {
                methodSourceType     = typeof(VRC.Udon.UdonBehaviour);
                isUdonSharpBehaviour = true;
            }

            string functionNamespace = SanitizeTypeName(methodSourceType.FullName ?? methodSourceType.Namespace + methodSourceType.Name).Replace("VRCUdonUdonBehaviour", "VRCUdonCommonInterfacesIUdonEventReceiver");

            string methodName = $"__{externMethod.Name.Trim('_').TrimStart('.')}";

            ParameterInfo[] methodParams = externMethod.GetParameters();

            if (isUdonSharpBehaviour &&
                methodName == "__VRCInstantiate")
            {
                functionNamespace = "VRCInstantiate";
                methodName        = "__Instantiate";
            }

            string paramStr = "";

            if (methodParams.Length > 0)
            {
                paramStr = "_"; // Arg separator

                foreach (ParameterInfo parameterInfo in methodParams)
                {
                    paramStr += $"_{GetUdonTypeName(parameterInfo.ParameterType, true)}";
                }
            }
            else if (externMethod is ConstructorInfo)
            {
                paramStr = "__";
            }

            string returnStr = "";

            if (externMethod is MethodInfo)
            {
                returnStr = $"__{GetUdonTypeName(((MethodInfo)externMethod).ReturnType, true)}";
            }
            else if (externMethod is ConstructorInfo)
            {
                returnStr = $"__{GetUdonTypeName(((ConstructorInfo)externMethod).DeclaringType)}";
            }
            else
            {
                throw new System.Exception("Invalid extern method type for getting Udon name");
            }

            string finalFunctionSig = $"{functionNamespace}.{methodName}{paramStr}{returnStr}";

            if (validate && !nodeDefinitionLookup.Contains(finalFunctionSig))
            {
                throw new System.Exception($"Method {finalFunctionSig} is not exposed in Udon");
            }

            return(finalFunctionSig);
        }