void ProcessNodeContextMenu(Node node) { GenericMenu genericMenu = new GenericMenu(); if (node.CanCreateLinkFrom()) { genericMenu.AddItem(new GUIContent("Create link"), false, () => { StartCreateLink(node); }); } else { genericMenu.AddDisabledItem(new GUIContent("Create link"), false); } if (nodeMenuHandlers.ContainsKey(node.GetType())) { INodeMenuHandler handler = nodeMenuHandlers[node.GetType()]; NodeMenuItem[] items = handler.NodeContextMenuItems(node, _model); if (items != null) { foreach (NodeMenuItem item in items) { if (!item.disabled) { genericMenu.AddItem(new GUIContent(item.label), item.ticked, item.Function); } else { genericMenu.AddDisabledItem(new GUIContent(item.label), item.ticked); } } } } if (node.CanBeHidden()) { genericMenu.AddItem(new GUIContent("Hide node"), !node.visible, () => node.visible = !node.visible); } else { genericMenu.AddDisabledItem(new GUIContent("Hide node"), !node.visible); } if (node.CanBeRemoved()) { genericMenu.AddItem(new GUIContent("Remove node"), false, () => { RemoveNode(node); LoadModel(_model); }); } else { genericMenu.AddDisabledItem(new GUIContent("Remove node"), false); } genericMenu.ShowAsContext(); }
/// <summary> /// Builds the menu items needed for the "Add node" menu. /// Looks for <c>INodeMenuHandler</c>s cached by the editor first, /// which falls back to the <c>NodeInfo</c> attribute on the <c>Node</c> itself, /// which falls back to adding the node type name to the menu root. /// </summary> /// <param name="menu">The menu to build onto.</param> /// <param name="mousePosition">The position of the mouse.</param> public void LoadNodeMenu(GenericMenu menu, Vector2 mousePosition) { Assembly engineAssembly = Assembly.Load("Assembly-CSharp"); IEnumerable <Type> nodeTypes = engineAssembly.GetTypes().Where(t => typeof(Node).IsAssignableFrom(t)); List <NodeMenuItem> menuItemsToAdd = new List <NodeMenuItem>(); foreach (Type type in nodeTypes) { bool usedMenuHandler = false; if (nodeMenuHandlers.ContainsKey(type)) { INodeMenuHandler handler = nodeMenuHandlers[type]; NodeMenuItem[] menuItems = handler.AddNodeMenuItems(_model, mousePosition - _offset, this); if (menuItems != null) { menuItemsToAdd.AddRange(menuItems); usedMenuHandler = true; } } if (!usedMenuHandler) { if (type.IsAbstract) { continue; } NodeInfoAttribute nodeAttribute = type.GetCustomAttribute <NodeInfoAttribute>(); if (nodeAttribute != null) { if (nodeAttribute.visible) { menuItemsToAdd.Add(new NodeMenuItem(nodeAttribute.menuLabel, () => AddNode(type, mousePosition), false, false)); } } else { menuItemsToAdd.Add(new NodeMenuItem(type.ToString(), () => AddNode(type, mousePosition), false, false)); } } } foreach (NodeMenuItem menuItem in menuItemsToAdd) { if (menuItem.disabled) { menu.AddDisabledItem(new GUIContent(menuItem.label), menuItem.ticked); } else { menu.AddItem(new GUIContent(menuItem.label), menuItem.ticked, menuItem.Function); } } }
void FindNodeMenuHandlers() { Assembly editorAssembly = Assembly.Load("Assembly-CSharp-Editor"); IEnumerable <Type> nodeMenuTypes = editorAssembly.GetTypes().Where(t => t.GetCustomAttribute <NodeMenuAttribute>() != null && typeof(INodeMenuHandler).IsAssignableFrom(t) ); foreach (Type nodeMenuType in nodeMenuTypes) { Type nodeType = nodeMenuType.GetCustomAttribute <NodeMenuAttribute>().NodeType; if (typeof(Node).IsAssignableFrom(nodeType)) { INodeMenuHandler handler = System.Activator.CreateInstance(nodeMenuType) as INodeMenuHandler; if (handler != null) { nodeMenuHandlers.Add(nodeType, handler); } } } }