Open Seneral opened 8 years ago
I am trying to implement this now, I removed left click condition from the window panning and create another functions to listen when left click is performed in the window area and while not selecting any nodes.
How can I draw a rect in the canvas ?
`
#region Window Selecting
static Vector2 startSelectionPos;
[EventHandlerAttribute(EventType.MouseDown, priority = 105)] // Priority over hundred to make it call after the GUI
private static void HandleWindowSelectionStart(NodeEditorInputInfo inputInfo)
{
if (GUIUtility.hotControl > 0)
return; // GUI has control
NodeEditorState state = inputInfo.editorState;
if (inputInfo.inputEvent.button == 0 && state.focusedNode == null)
{ // Left clicked on the empty canvas -> Start the selection process
state.boxSelecting = true;
Debug.Log("box selecting start");
startSelectionPos = inputInfo.inputPos;
}
}
[EventHandlerAttribute(EventType.MouseDrag)]
private static void HandleWindowSelection(NodeEditorInputInfo inputInfo)
{
NodeEditorState state = inputInfo.editorState;
if (state.boxSelecting)
{
Debug.Log("box selecting");
Rect handleRect = new Rect();
handleRect.min = startSelectionPos;
handleRect.max = inputInfo.inputPos;
//handleRect.position += state.zoomPanAdjust + state.panOffset;
GUI.Box(handleRect, GUIContent.none);
NodeEditor.RepaintClients();
}
}
[EventHandlerAttribute(EventType.MouseDown)]
[EventHandlerAttribute(EventType.MouseUp)]
private static void HandleWindowSelectionEnd(NodeEditorInputInfo inputInfo)
{
if (inputInfo.editorState.boxSelecting)
{
Debug.Log("box selecting end");
inputInfo.editorState.boxSelecting = false;
}
}
#endregion
`
Hi @rudinesurya, cool that you're working on that. It will be very easy to draw the box, as it would probably need to be unscaled, so you could do that right before starting the scaling in the drawing function. You could also do that in HandleWindowSelection, just add the Repaint EventHandler in that case and also limit further instructions based on the eventType. Regarding the style, there is an editor style that the editor uses for the selection rect, so it could be used in the editor version atleast (when I'm back home I can search it for you, I've used it in a previous project). One note though, instead of disabling or replacing the panning controls, it'd be better to use different controls for the multi selection, like Shift or Shift-Left click. Left-click and dragging is simply the best and expected control for panning I think... Also, there might be issues regarding input when you're at the point where you're able to select ultiple nodes. You would have to search for references of both the active and focusd node and decide if it's apropriate to perform the action on all selected nodes instead. Selected/Active and focused nodes should still be seperate in the editor state though.
I am thinking of similar idea with the group feature. OnWindowSelectionEnd I will add all the nodes within the box into a static list. Then I might need to add another condition to the current drag node function to check if the selected node is inside the list. if it is then drag the whole list. What do you think =)
i think left clicking and dragging is usually used to group select, and middle mouse for panning. I know ue4, playmaker, mecanim uses this.
Ok, change panning controls to the middle button. Yes, it should work similar to this. But don't make it static, remember it has to do with the editor state, so it belongs there. Also shift-click to multi select would be nice. Not only drag, but also other controls have to be adjusted to the multi select if apropriate. I let you decide:)
I got inspiration from this old man’s speech and completed this multi-box selection function
This is the core code, `
private static void HandleMultipleSelect()
{
if (curEditorState.boxSelecting)
{
Rect handleRect = new Rect();
handleRect.min = NodeEditorInputControls.startSelectionPos;
handleRect.max = Event.current.mousePosition;
GUI.Box(handleRect, GUIContent.none, NodeEditorGUI.nodeBox);
Rect canvasRect = new Rect();
Vector2 start = ScreenToCanvasSpace(NodeEditorInputControls.startSelectionPos);
Vector2 end = ScreenToCanvasSpace(Event.current.mousePosition);
canvasRect.min = Vector2.Min(start, end);
canvasRect.max = Vector2.Max(start, end);
curEditorState.selectedNodes.Clear();
foreach (var node in curNodeCanvas.nodes)
{
if (canvasRect.Contains(node.position))
{
curEditorState.selectedNodes.Add(node);
}
}
}
}
` Hope it is useful to people who see this issue
As Seneral said, implementing these functions requires a lot of modification of the framework code, so I have no way to mention PR, sorry
If you want to see a more complete sample code, including the implementation of highlighting Node, please go to A state-synchronized Moba project
@wqaetly Thanks, that looks really good. I currently don't have a lot of time working on new features, I am currently focussing on my other project, MakersVR. But I will try implementing it soon. Contrary to popular bindings (Middle click to pan, left click to multi-select) I'd go with different bindings to preserve the current ones as much as possible. I thought about adding multi-select using shift-left-click (or control-left-click), which resembles the common keybinding for multi-selecting list items. I imagine that would be a lot more clunky, but I don't wan't to break existing user's muscle memory.
Yes, for example, the function of holding down shift to select multiple Nodes is also very important, because in some cases the Nodes you want to select may be scattered in various places in Canvas
But one thing is very important, that is, the selectedNode field in editorState must be changed to List
Description: Selecting, moving, deleting and duplicating multiple nodes.
State: None. May need adjustements to NodeEditorState and the input checking system.