public bool TryGetFunctionInfo(MethodInfo methodInfo, out CKlaxScriptFunctionInfo outFunctionInfo)
 {
     if (methodInfo == null)
     {
         outFunctionInfo = null;
         return(false);
     }
     return(m_klaxFunctionMap.TryGetValue(methodInfo, out outFunctionInfo));
 }
        public void GetNodeSuggestions(CKlaxScriptNodeQueryContext context, List <CKlaxScriptNodeFactory> suggestions)
        {
            if (suggestions.Capacity < MINIMUM_SUGGESTION_CAPACITY)
            {
                suggestions.Capacity = MINIMUM_SUGGESTION_CAPACITY;
            }

            suggestions.Clear();

            for (int i = 0, count = Types.Count; i < count; i++)
            {
                CKlaxScriptTypeInfo type = Types[i];
                bool bIncludeAll         = type.Type == context.InputPinType;

                for (int k = 0, funcCount = type.Functions.Count; k < funcCount; k++)
                {
                    CKlaxScriptFunctionInfo func = type.Functions[k];
                    Type declaringType           = func.methodInfo.IsStatic ? null : func.methodInfo.DeclaringType;
                    if (bIncludeAll || context.InputPinType == null || func.inputParameter.Any((t) => t.IsAssignableFrom(context.InputPinType)))
                    {
                        CKlaxScriptNodeFactory factory = new CKlaxScriptNodeFactory(func.displayName, func.category, func.tooltip, declaringType, false, () =>
                        {
                            return(new CExecuteFunctionNode()
                            {
                                TargetMethod = func.methodInfo,
                                IsImplicit = func.bIsImplicit,
                            });
                        });

                        suggestions.Add(factory);
                    }
                }

                int propertyCount = type.Properties.Count;
                for (int j = 0; j < propertyCount; j++)
                {
                    CKlaxScriptPropertyInfo prop = type.Properties[j];
                    if (bIncludeAll || context.InputPinType == null || prop.propertyType.IsAssignableFrom(context.InputPinType) || prop.declaringType.IsAssignableFrom(context.InputPinType))
                    {
                        CKlaxScriptNodeFactory getFactory = new CKlaxScriptNodeFactory("Get " + prop.displayName, prop.category, prop.tooltip, prop.declaringType, true, () =>
                        {
                            return(prop.fieldInfo != null ? new CGetMemberNode(prop.fieldInfo) : new CGetMemberNode(prop.propertyInfo));
                        });

                        suggestions.Add(getFactory);

                        if (!prop.bIsReadOnly)
                        {
                            CKlaxScriptNodeFactory setFactory = new CKlaxScriptNodeFactory("Set " + prop.displayName, prop.category, prop.tooltip, prop.declaringType, true, () =>
                            {
                                return(prop.fieldInfo != null ? new CSetMemberNode(prop.fieldInfo) : new CSetMemberNode(prop.propertyInfo));
                            });
                            suggestions.Add(setFactory);
                        }
                    }
                }
            }

            for (int i = 0, funcCount = LibraryFunctions.Count; i < funcCount; i++)
            {
                CKlaxScriptFunctionInfo func = LibraryFunctions[i];
                Type declaringType           = func.methodInfo.IsStatic ? null : func.methodInfo.DeclaringType;
                if (context.InputPinType == null || func.inputParameter.Any((t) => t.IsAssignableFrom(context.InputPinType)))
                {
                    CKlaxScriptNodeFactory factory = new CKlaxScriptNodeFactory(func.displayName, func.category, func.tooltip, declaringType, false, () =>
                    {
                        return(new CExecuteFunctionNode()
                        {
                            TargetMethod = func.methodInfo,
                            IsImplicit = func.bIsImplicit,
                        });
                    });

                    suggestions.Add(factory);
                }
            }

            if (context.QueryObject != null)
            {
                foreach (CKlaxScriptInterfaceReference interfaceReference in context.QueryObject.IncludedInterfaces)
                {
                    CKlaxScriptInterface klaxInterface = interfaceReference.GetInterface();
                    foreach (var interfaceFunction in klaxInterface.Functions)
                    {
                        CKlaxScriptNodeFactory factory = new CKlaxScriptNodeFactory(interfaceFunction.Name, "Interfaces", "", null, false, () =>
                        {
                            return(new CExecuteInterfaceFunctionNode(interfaceFunction));
                        });
                        suggestions.Add(factory);
                    }
                }

                foreach (CCustomFunctionGraph functionGraph in context.QueryObject.FunctionGraphs)
                {
                    CKlaxScriptNodeFactory factory = new CKlaxScriptNodeFactory(functionGraph.Name, "Script Functions", "", null, false, () =>
                    {
                        CExecuteCustomFunctionNode functionNode = new CExecuteCustomFunctionNode(functionGraph);
                        functionNode.ResolveFunctionReference(context.QueryObject);
                        return(functionNode);
                    });
                    suggestions.Add(factory);
                }
            }

            suggestions.AddRange(m_customNodeFactories);
        }
        private void GenerateMethod(CKlaxScriptFunctionInfo function, EKlaxFunctionLocation location, int typeIndex, int functionIndex)
        {
            MethodInfo methodInfo = function.methodInfo;

            ParameterInfo[] parameters      = methodInfo.GetParameters();
            ParameterInfo[] outParameters   = parameters.Where(param => param.IsOut || (param.ParameterType.IsByRef && !param.IsIn)).ToArray();
            ParameterInfo[] inRefParameters = parameters.Where(param => param.ParameterType.IsByRef && param.IsIn).ToArray();
            ParameterInfo   returnParameter = methodInfo.ReturnParameter;

            //Check if any invalid parameters are detected
            TypeBuilder typeBuilder = m_moduleBuilder.DefineType(methodInfo.DeclaringType + "_" + methodInfo.Name + "_Type", TypeAttributes.Public);

            //Build MethodInfo field to map generated type to method info
            FieldBuilder methodLocationFieldBuilder = typeBuilder.DefineField(METHOD_LOCATION_NAME, typeof(EKlaxFunctionLocation), FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.HasDefault | FieldAttributes.Literal);

            methodLocationFieldBuilder.SetConstant(location);

            FieldBuilder typeIndexFieldBuilder = typeBuilder.DefineField(TYPE_INDEX_NAME, typeof(int), FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.HasDefault | FieldAttributes.Literal);

            typeIndexFieldBuilder.SetConstant(typeIndex);

            FieldBuilder functionIndexFieldBuilder = typeBuilder.DefineField(FUNCTION_INDEX_NAME, typeof(int), FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.HasDefault | FieldAttributes.Literal);

            functionIndexFieldBuilder.SetConstant(functionIndex);

            //Build execution method
            MethodBuilder methodBuilder = typeBuilder.DefineMethod(METHOD_NAME, MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, CallingConventions.Standard, null, new Type[] { m_genericObjectListType, m_genericObjectListType });
            ILGenerator   generator     = methodBuilder.GetILGenerator();

            bool bHasReturnType    = returnParameter.ParameterType != typeof(void);
            bool bIsStaticFunction = methodInfo.IsStatic;

            int returnParameterCount = 0;
            int outParameterCount    = 0;
            int inRefParameterCount  = 0;

            if (returnParameter.ParameterType != typeof(void))
            {
                generator.DeclareLocal(returnParameter.ParameterType);
                returnParameterCount++;
            }

            foreach (var outParam in outParameters)
            {
                generator.DeclareLocal(outParam.ParameterType.IsByRef ? outParam.ParameterType.GetElementType() : outParam.ParameterType);
                outParameterCount = outParameters.Length;
            }

            foreach (var inParam in inRefParameters)
            {
                generator.DeclareLocal(inParam.ParameterType.GetElementType());
                inRefParameterCount = inRefParameters.Length;
            }

            //Fill local variables for in ref parameters of desired function
            for (int i = 0, length = inRefParameters.Length; i < length; i++)
            {
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldc_I4_S, (sbyte)(Array.IndexOf(parameters, inRefParameters[i]) + (bIsStaticFunction ? 0 : 1)));
                generator.Emit(OpCodes.Callvirt, m_genericObjectListGetter);

                Type underlyingType = inRefParameters[i].ParameterType.GetElementType();
                if (underlyingType.IsValueType)
                {
                    generator.Emit(OpCodes.Unbox_Any, underlyingType);
                }
                generator.Emit(OpCodes.Stloc, (short)(returnParameterCount + outParameterCount + i));
            }

            //If we call a member function, convert the first argument into the target type and put onto evaluation stack
            if (!bIsStaticFunction)
            {
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldc_I4_0);
                generator.Emit(OpCodes.Callvirt, m_genericObjectListGetter);
                generator.Emit(OpCodes.Castclass, methodInfo.DeclaringType);
            }

            for (int i = 0, length = parameters.Length; i < length; i++)
            {
                if (parameters[i].IsOut)
                {
                    //Put out parameters onto evaluation stack
                    generator.Emit(OpCodes.Ldloca_S, (byte)(Array.IndexOf(outParameters, parameters[i]) + (bHasReturnType ? 1 : 0)));
                }
                else if (parameters[i].IsIn && parameters[i].ParameterType.IsByRef)
                {
                    generator.Emit(OpCodes.Ldloca_S, (byte)(Array.IndexOf(inRefParameters, parameters[i]) + returnParameterCount + outParameterCount));
                }
                else
                {
                    PutObjectOntoEvaluationStack_IL(generator, i - GetOutParametersBefore(i, parameters) + (bIsStaticFunction ? 0 : 1), parameters[i].ParameterType);
                }
            }

            generator.Emit(OpCodes.Call, methodInfo);

            if (returnParameter.ParameterType != typeof(void))
            {
                //Store return value in output list
                generator.Emit(OpCodes.Stloc_0);
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Ldloc_0);
                AddObjectToObjectList_IL(generator, returnParameter.ParameterType);
            }

            if (outParameters.Length > 0)
            {
                for (int i = 0, length = outParameters.Length; i < length; i++)
                {
                    generator.Emit(OpCodes.Ldarg_1);

                    generator.Emit(OpCodes.Ldloc, (short)(i + (bHasReturnType ? 1 : 0)));
                    AddObjectToObjectList_IL(generator, outParameters[i].ParameterType);
                }
            }

            generator.Emit(OpCodes.Ret);

            typeBuilder.CreateType();
        }
        private CKlaxScriptFunctionInfo CreateFunction(KlaxFunctionAttribute attribute, MethodInfo method)
        {
            ParameterInfo[]         parameters = method.GetParameters();
            CKlaxScriptFunctionInfo info       = new CKlaxScriptFunctionInfo
            {
                methodInfo     = method,
                displayName    = attribute.DisplayName ?? method.Name,
                category       = attribute.Category,
                tooltip        = attribute.Tooltip,
                inputParameter = parameters.Where(whereInfo => !whereInfo.IsOut).Select(selectInfo => selectInfo.ParameterType).ToArray(),
                inputParametersDefaultValue = method.GetParameters().Where(whereInfo => !whereInfo.IsOut).Select(selectInfo => (selectInfo.HasDefaultValue ? selectInfo.DefaultValue : null)).ToArray(),
                bIsImplicit = attribute.IsImplicit,
            };

            info.inputParameterNames = new string[info.inputParameter.Length];
            for (int i = 0, length = info.inputParameter.Length; i < length; i++)
            {
                string result = parameters[i].Name;
                switch (i)
                {
                case 0:
                    if (attribute.ParameterName1 != null)
                    {
                        result = attribute.ParameterName1;
                    }
                    break;

                case 1:
                    if (attribute.ParameterName2 != null)
                    {
                        result = attribute.ParameterName2;
                    }
                    break;

                case 2:
                    if (attribute.ParameterName3 != null)
                    {
                        result = attribute.ParameterName3;
                    }
                    break;

                case 3:
                    if (attribute.ParameterName4 != null)
                    {
                        result = attribute.ParameterName4;
                    }
                    break;

                case 4:
                    if (attribute.ParameterName5 != null)
                    {
                        result = attribute.ParameterName5;
                    }
                    break;

                case 5:
                    if (attribute.ParameterName6 != null)
                    {
                        result = attribute.ParameterName6;
                    }
                    break;

                case 6:
                    if (attribute.ParameterName7 != null)
                    {
                        result = attribute.ParameterName7;
                    }
                    break;

                case 7:
                    if (attribute.ParameterName8 != null)
                    {
                        result = attribute.ParameterName8;
                    }
                    break;

                case 8:
                    if (attribute.ParameterName9 != null)
                    {
                        result = attribute.ParameterName9;
                    }
                    break;

                case 9:
                    if (attribute.ParameterName10 != null)
                    {
                        result = attribute.ParameterName10;
                    }
                    break;
                }

                info.inputParameterNames[i] = result;
            }

            m_klaxFunctionMap.Add(method, info);

            return(info);
        }
 public SKlaxScriptFunctionProxy(CKlaxScriptFunctionInfo method)
 {
     methodInfo     = method.methodInfo;
     compiledMethod = method.compiledMethod;
     bIsCompiled    = compiledMethod != null;
 }