private static void OnActiveContextMenuShowAsync() { Profiler.BeginEvent("Setup Anim Graph Context Menu (async)"); foreach (var scriptType in Editor.Instance.CodeEditing.All.Get()) { if (!SurfaceUtils.IsValidVisualScriptType(scriptType)) { continue; } // Skip Newtonsoft.Json stuff var scriptTypeTypeName = scriptType.TypeName; if (scriptTypeTypeName.StartsWith("Newtonsoft.Json.")) { continue; } var scriptTypeName = scriptType.Name; // Enum if (scriptType.IsEnum) { // Create node archetype var node = (NodeArchetype)Archetypes.Constants.Nodes[10].Clone(); node.DefaultValues[0] = Activator.CreateInstance(scriptType.Type); node.Flags &= ~NodeFlags.NoSpawnViaGUI; node.Title = scriptTypeName; node.Description = Editor.Instance.CodeDocs.GetTooltip(scriptType); // Create group archetype var groupKey = new KeyValuePair <string, ushort>(scriptTypeName, 2); if (!_cache.TryGetValue(groupKey, out var group)) { group = new GroupArchetype { GroupID = groupKey.Value, Name = groupKey.Key, Color = new Color(243, 156, 18), Tag = _version, Archetypes = new List <NodeArchetype>(), }; _cache.Add(groupKey, group); } // Add node to the group ((IList <NodeArchetype>)group.Archetypes).Add(node); continue; } // Structure if (scriptType.IsValueType) { if (scriptType.IsVoid) { continue; } // Create group archetype var groupKey = new KeyValuePair <string, ushort>(scriptTypeName, 4); if (!_cache.TryGetValue(groupKey, out var group)) { group = new GroupArchetype { GroupID = groupKey.Value, Name = groupKey.Key, Color = new Color(155, 89, 182), Tag = _version, Archetypes = new List <NodeArchetype>(), }; _cache.Add(groupKey, group); } var tooltip = Editor.Instance.CodeDocs.GetTooltip(scriptType); // Create Pack node archetype var node = (NodeArchetype)Archetypes.Packing.Nodes[6].Clone(); node.DefaultValues[0] = scriptTypeTypeName; node.Flags &= ~NodeFlags.NoSpawnViaGUI; node.Title = "Pack " + scriptTypeName; node.Description = tooltip; ((IList <NodeArchetype>)group.Archetypes).Add(node); // Create Unpack node archetype node = (NodeArchetype)Archetypes.Packing.Nodes[13].Clone(); node.DefaultValues[0] = scriptTypeTypeName; node.Flags &= ~NodeFlags.NoSpawnViaGUI; node.Title = "Unpack " + scriptTypeName; node.Description = tooltip; ((IList <NodeArchetype>)group.Archetypes).Add(node); } } // Add group to context menu (on a main thread) FlaxEngine.Scripting.InvokeOnUpdate(() => { lock (_locker) { _taskContextMenu.AddGroups(_cache.Values); _taskContextMenu = null; } }); Profiler.EndEvent(); lock (_locker) { _task = null; } }
private static void OnActiveContextMenuShowAsync() { Profiler.BeginEvent("Setup Visual Script Context Menu (async)"); #if DEBUG_INVOKE_METHODS_SEARCHING || DEBUG_FIELDS_SEARCHING var searchStartTime = DateTime.Now; var searchHitsCount = 0; #endif foreach (var scriptType in Editor.Instance.CodeEditing.All.Get()) { if (!SurfaceUtils.IsValidVisualScriptType(scriptType)) { continue; } // Skip Newtonsoft.Json stuff var scriptTypeTypeName = scriptType.TypeName; if (scriptTypeTypeName.StartsWith("Newtonsoft.Json.")) { continue; } var scriptTypeName = scriptType.Name; // Enum if (scriptType.IsEnum) { // Create node archetype var node = (NodeArchetype)Archetypes.Constants.Nodes[10].Clone(); node.DefaultValues[0] = Activator.CreateInstance(scriptType.Type); node.Flags &= ~NodeFlags.NoSpawnViaGUI; node.Title = scriptTypeName; node.Description = scriptTypeTypeName; var attributes = scriptType.GetAttributes(false); var tooltipAttribute = (TooltipAttribute)attributes.FirstOrDefault(x => x is TooltipAttribute); if (tooltipAttribute != null) { node.Description += "\n" + tooltipAttribute.Text; } // Create group archetype var groupKey = new KeyValuePair <string, ushort>(scriptTypeName, 2); if (!_cache.TryGetValue(groupKey, out var group)) { group = new GroupArchetype { GroupID = groupKey.Value, Name = groupKey.Key, Color = new Color(243, 156, 18), Tag = _version, Archetypes = new List <NodeArchetype>(), }; _cache.Add(groupKey, group); } // Add node to the group ((IList <NodeArchetype>)group.Archetypes).Add(node); continue; } // Structure if (scriptType.IsValueType) { if (scriptType.IsVoid) { continue; } // Create group archetype var groupKey = new KeyValuePair <string, ushort>(scriptTypeName, 4); if (!_cache.TryGetValue(groupKey, out var group)) { group = new GroupArchetype { GroupID = groupKey.Value, Name = groupKey.Key, Color = new Color(155, 89, 182), Tag = _version, Archetypes = new List <NodeArchetype>(), }; _cache.Add(groupKey, group); } var attributes = scriptType.GetAttributes(false); var tooltipAttribute = (TooltipAttribute)attributes.FirstOrDefault(x => x is TooltipAttribute); // Create Pack node archetype var node = (NodeArchetype)Archetypes.Packing.Nodes[6].Clone(); node.DefaultValues[0] = scriptTypeTypeName; node.Flags &= ~NodeFlags.NoSpawnViaGUI; node.Title = "Pack " + scriptTypeName; node.Description = scriptTypeTypeName; if (tooltipAttribute != null) { node.Description += "\n" + tooltipAttribute.Text; } ((IList <NodeArchetype>)group.Archetypes).Add(node); // Create Unpack node archetype node = (NodeArchetype)Archetypes.Packing.Nodes[13].Clone(); node.DefaultValues[0] = scriptTypeTypeName; node.Flags &= ~NodeFlags.NoSpawnViaGUI; node.Title = "Unpack " + scriptTypeName; node.Description = scriptTypeTypeName; if (tooltipAttribute != null) { node.Description += "\n" + tooltipAttribute.Text; } ((IList <NodeArchetype>)group.Archetypes).Add(node); } foreach (var member in scriptType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)) { if (member.IsGeneric) { continue; } if (member.IsMethod) { // Skip methods not declared in this type if (member.Type is MethodInfo m && m.GetBaseDefinition().DeclaringType != m.DeclaringType) { continue; } var name = member.Name; if (name == "ToString") { continue; } // Skip if searching by name doesn't return a match var members = scriptType.GetMembers(name, MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); if (!members.Contains(member)) { continue; } // Check if method is valid for Visual Script usage if (SurfaceUtils.IsValidVisualScriptInvokeMethod(member, out var parameters)) { // Create node archetype var node = (NodeArchetype)Archetypes.Function.Nodes[3].Clone(); node.DefaultValues[0] = scriptTypeTypeName; node.DefaultValues[1] = name; node.DefaultValues[2] = parameters.Length; node.Flags &= ~NodeFlags.NoSpawnViaGUI; node.Title = SurfaceUtils.GetMethodDisplayName((string)node.DefaultValues[1]); node.Description = SurfaceUtils.GetVisualScriptMemberInfoDescription(member); node.SubTitle = string.Format(" (in {0})", scriptTypeName); node.Tag = member; // Create group archetype var groupKey = new KeyValuePair <string, ushort>(scriptTypeName, 16); if (!_cache.TryGetValue(groupKey, out var group)) { group = new GroupArchetype { GroupID = groupKey.Value, Name = groupKey.Key, Color = new Color(109, 160, 24), Tag = _version, Archetypes = new List <NodeArchetype>(), }; _cache.Add(groupKey, group); } // Add node to the group ((IList <NodeArchetype>)group.Archetypes).Add(node); #if DEBUG_INVOKE_METHODS_SEARCHING Editor.LogWarning(scriptTypeTypeName + " -> " + member.GetSignature()); searchHitsCount++; #endif } } else if (member.IsField) { var name = member.Name; // Skip if searching by name doesn't return a match var members = scriptType.GetMembers(name, MemberTypes.Field, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); if (!members.Contains(member)) { continue; } // Check if field is valid for Visual Script usage if (SurfaceUtils.IsValidVisualScriptField(member)) { if (member.HasGet) { // Create node archetype var node = (NodeArchetype)Archetypes.Function.Nodes[6].Clone(); node.DefaultValues[0] = scriptTypeTypeName; node.DefaultValues[1] = name; node.DefaultValues[2] = member.ValueType.TypeName; node.DefaultValues[3] = member.IsStatic; node.Flags &= ~NodeFlags.NoSpawnViaGUI; node.Title = "Get " + name; node.Description = SurfaceUtils.GetVisualScriptMemberInfoDescription(member); node.SubTitle = string.Format(" (in {0})", scriptTypeName); // Create group archetype var groupKey = new KeyValuePair <string, ushort>(scriptTypeName, 16); if (!_cache.TryGetValue(groupKey, out var group)) { group = new GroupArchetype { GroupID = groupKey.Value, Name = groupKey.Key, Color = new Color(109, 160, 24), Tag = _version, Archetypes = new List <NodeArchetype>(), }; _cache.Add(groupKey, group); } // Add node to the group ((IList <NodeArchetype>)group.Archetypes).Add(node); #if DEBUG_FIELDS_SEARCHING Editor.LogWarning(scriptTypeTypeName + " -> Get " + member.GetSignature()); searchHitsCount++; #endif } if (member.HasSet) { // Create node archetype var node = (NodeArchetype)Archetypes.Function.Nodes[7].Clone(); node.DefaultValues[0] = scriptTypeTypeName; node.DefaultValues[1] = name; node.DefaultValues[2] = member.ValueType.TypeName; node.DefaultValues[3] = member.IsStatic; node.Flags &= ~NodeFlags.NoSpawnViaGUI; node.Title = "Set " + name; node.Description = SurfaceUtils.GetVisualScriptMemberInfoDescription(member); node.SubTitle = string.Format(" (in {0})", scriptTypeName); // Create group archetype var groupKey = new KeyValuePair <string, ushort>(scriptTypeName, 16); if (!_cache.TryGetValue(groupKey, out var group)) { group = new GroupArchetype { GroupID = groupKey.Value, Name = groupKey.Key, Color = new Color(109, 160, 24), Tag = _version, Archetypes = new List <NodeArchetype>(), }; _cache.Add(groupKey, group); } // Add node to the group ((IList <NodeArchetype>)group.Archetypes).Add(node); #if DEBUG_FIELDS_SEARCHING Editor.LogWarning(scriptTypeTypeName + " -> Set " + member.GetSignature()); searchHitsCount++; #endif } } } } } // Add group to context menu (on a main thread) FlaxEngine.Scripting.InvokeOnUpdate(() => { #if DEBUG_INVOKE_METHODS_SEARCHING || DEBUG_FIELDS_SEARCHING var addStartTime = DateTime.Now; #endif lock (_locker) { _taskContextMenu.AddGroups(_cache.Values); _taskContextMenu = null; } #if DEBUG_INVOKE_METHODS_SEARCHING || DEBUG_FIELDS_SEARCHING Editor.LogError($"Added items to VisjectCM in: {(DateTime.Now - addStartTime).TotalMilliseconds} ms"); #endif }); #if DEBUG_INVOKE_METHODS_SEARCHING || DEBUG_FIELDS_SEARCHING Editor.LogError($"Collected {searchHitsCount} items in: {(DateTime.Now - searchStartTime).TotalMilliseconds} ms"); #endif Profiler.EndEvent(); lock (_locker) { _task = null; } }