public bool TryGetTypeInfo(Type nativeType, out CKlaxScriptTypeInfo outTypeInfo)
        {
            if (nativeType == null)
            {
                outTypeInfo = null;
                return(false);
            }

            return(m_klaxTypeMap.TryGetValue(nativeType, out outTypeInfo));
        }
        private void RegisterType(CKlaxScriptTypeInfo typeInfo)
        {
            Type type = typeInfo.Type;

            Types.Add(typeInfo);
            m_klaxTypeMap.Add(typeInfo.Type, typeInfo);

            foreach (var method in type.GetMethods())
            {
                KlaxFunctionAttribute klaxFunction = method.GetCustomAttribute <KlaxFunctionAttribute>();
                if (klaxFunction != null)
                {
                    MethodInfo baseMethod = method.GetBaseDefinition();
                    if (baseMethod.DeclaringType == type)
                    {
                        typeInfo.Functions.Add(CreateFunction(klaxFunction, method));
                    }
                }
            }

            foreach (var property in type.GetProperties())
            {
                KlaxPropertyAttribute klaxProperty = property.GetCustomAttribute <KlaxPropertyAttribute>();
                if (klaxProperty != null)
                {
                    if (property.DeclaringType == type)
                    {
                        typeInfo.Properties.Add(CreateProperty(klaxProperty, property));
                    }
                }
            }

            foreach (var field in type.GetFields())
            {
                KlaxPropertyAttribute klaxProperty = field.GetCustomAttribute <KlaxPropertyAttribute>();
                if (klaxProperty != null)
                {
                    if (field.DeclaringType == type)
                    {
                        string name = klaxProperty.DisplayName ?? field.Name;
                        typeInfo.Properties.Add(CreateProperty(field, name, klaxProperty.Category, klaxProperty.IsReadOnly));
                    }
                }
                else
                {
                    KlaxEventAttribute klaxEvent = field.GetCustomAttribute <KlaxEventAttribute>();
                    if (klaxEvent != null && field.DeclaringType == type)
                    {
                        typeInfo.Events.Add(CreateEvent(field, klaxEvent));
                    }
                }
            }
        }
        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);
        }