<commit_before>﻿using UnityEngine;
using System;
using System.Linq;
using System.Collections.Generic;
using NodeEditorFramework;
using NodeEditorFramework.Utilities;
using System.Reflection;

namespace NodeEditorFramework 
{
	/// <summary>
	/// Collection of default Node Editor controls for the NodeEditorInputSystem
	/// </summary>
	public static class NodeEditorInputControls
	{
		#region Canvas Context Entries

		[ContextFillerAttribute (ContextType.Canvas)]
		private static void FillAddNodes (NodeEditorInputInfo inputInfo, GenericMenu canvasContextMenu) 
		{ // Show all nodes, and if a connection is drawn, only compatible nodes to auto-connect
			NodeEditorState state = inputInfo.editorState;
			List<Node> displayedNodes = state.connectOutput != null? NodeTypes.getCompatibleNodes (state.connectOutput) : NodeTypes.nodes.Keys.ToList ();
			foreach (Node compatibleNode in displayedNodes)
				canvasContextMenu.AddItem (new GUIContent ("Add " + NodeTypes.nodes[compatibleNode].adress), false, CreateNodeCallback, new NodeEditorInputInfo (compatibleNode.GetID, state));
		}

		private static void CreateNodeCallback (object infoObj)
		{
			NodeEditorInputInfo callback = infoObj as NodeEditorInputInfo;
			if (callback == null)
				throw new UnityException ("Callback Object passed by context is not of type NodeEditorInputInfo!");

			callback.SetAsCurrentEnvironment ();
			Node.Create (callback.message, NodeEditor.ScreenToCanvasSpace (callback.inputPos), callback.editorState.connectOutput);
			callback.editorState.connectOutput = null;
			NodeEditor.RepaintClients ();
		}

		#endregion

		#region Node Context Entries

		[ContextEntryAttribute (ContextType.Node, "Delete Node")]
		private static void DeleteNode (NodeEditorInputInfo inputInfo) 
		{
			inputInfo.SetAsCurrentEnvironment ();
			if (inputInfo.editorState.focusedNode != null) 
			{
				inputInfo.editorState.focusedNode.Delete ();
				inputInfo.inputEvent.Use ();
			}
		}

		[ContextEntryAttribute (ContextType.Node, "Duplicate Node")]
		private static void DuplicateNode (NodeEditorInputInfo inputInfo) 
		{
			inputInfo.SetAsCurrentEnvironment ();
			NodeEditorState state = inputInfo.editorState;
			if (state.focusedNode != null) 
			{ // Create new node of same type
				Node duplicatedNode = Node.Create (state.focusedNode.GetID, NodeEditor.ScreenToCanvasSpace (inputInfo.inputPos), state.connectOutput);
				state.selectedNode = state.focusedNode = duplicatedNode;
				state.connectOutput = null;
				inputInfo.inputEvent.Use ();
			}
		}

        #endregion

        #region Node Keyboard Control

        // Main Keyboard_Move method
        private static void KB_MoveNode(NodeEditorInputInfo inputInfo, KeyCode key)
        {
            Event e = Event.current;
            NodeEditorState state = inputInfo.editorState;
            if (state.selectedNode != null)
            { // Snap selected Node's position to multiples of 10
                Vector2 pos = state.selectedNode.rect.position;

                int shiftAmount = 0;

                // Increase the distance moved to 10 if shift if being held.
                if (Event.current.shift)
                    shiftAmount = 10;
                else
                    shiftAmount = 5;

                if (key == KeyCode.RightArrow)
                    pos = new Vector2(pos.x + shiftAmount, pos.y);
                else if (key == KeyCode.LeftArrow)
                    pos = new Vector2(pos.x - shiftAmount, pos.y);
                else if (key == KeyCode.DownArrow)
                    pos = new Vector2(pos.x, pos.y + shiftAmount);
                else if (key == KeyCode.UpArrow)
                    pos = new Vector2(pos.x, pos.y - shiftAmount);


                state.selectedNode.rect.position = pos;
                inputInfo.inputEvent.Use();
            }
            NodeEditor.RepaintClients();

        }

        
        [HotkeyAttribute(KeyCode.LeftArrow, EventType.KeyDown)]
        private static void KB_MoveNodeLeft(NodeEditorInputInfo inputInfo)   /// Left arrow functionality
        {
            HotkeyAttribute attr = GetHKAttribute(MethodBase.GetCurrentMethod());

            KB_MoveNode(inputInfo, attr.handledHotKey);
        }

        [HotkeyAttribute(KeyCode.RightArrow, EventType.KeyDown)]
        public static void KB_MoveNodeRight(NodeEditorInputInfo inputInfo)   /// Right arrow functionality
        {
            HotkeyAttribute attr = GetHKAttribute(MethodBase.GetCurrentMethod());

            KB_MoveNode(inputInfo, attr.handledHotKey);
        }

        [HotkeyAttribute(KeyCode.UpArrow, EventType.KeyDown)]
        public static void KB_MoveNodeUp(NodeEditorInputInfo inputInfo)   /// Up arrow functionality
        {
            HotkeyAttribute attr = GetHKAttribute(MethodBase.GetCurrentMethod());

            KB_MoveNode(inputInfo, attr.handledHotKey);
        }

        [HotkeyAttribute(KeyCode.DownArrow, EventType.KeyDown)]
        public static void KB_MoveNodeDown(NodeEditorInputInfo inputInfo) /// Down arrow functionality
        {
            HotkeyAttribute attr = GetHKAttribute(MethodBase.GetCurrentMethod());

            KB_MoveNode(inputInfo, attr.handledHotKey);
        }
        

        private static HotkeyAttribute GetHKAttribute(MethodBase method)
        {
            return (HotkeyAttribute)method.GetCustomAttributes(typeof(HotkeyAttribute), true)[0];
        }

        private enum MoveNodeDirection
        {
            UP, DOWN, LEFT, RIGHT
        }

        #endregion

        #region Node Dragging

        [EventHandlerAttribute (EventType.MouseDown, priority = 110)] // Priority over hundred to make it call after the GUI
		private static void HandleNodeDraggingStart (NodeEditorInputInfo inputInfo) 
		{
			if (GUIUtility.hotControl > 0)
				return; // GUI has control

			NodeEditorState state = inputInfo.editorState;
			if (inputInfo.inputEvent.button == 0 && state.focusedNode != null && state.focusedNode == state.selectedNode && state.focusedNodeKnob == null) 
			{ // Clicked inside the selected Node, so start dragging it
				state.dragNode = true;
				state.dragStart = inputInfo.inputPos;
				state.dragPos = state.focusedNode.rect.position; // Need this here because of snapping
				state.dragOffset = Vector2.zero;
				inputInfo.inputEvent.delta = Vector2.zero;
			}
		}

		[EventHandlerAttribute (EventType.MouseDrag)]
		private static void HandleNodeDragging (NodeEditorInputInfo inputInfo) 
		{
			NodeEditorState state = inputInfo.editorState;
			if (state.dragNode) 
			{ // If conditions apply, drag the selected node, else disable dragging
				if (state.selectedNode != null && GUIUtility.hotControl == 0)
				{ // Calculate new position for the dragged object<commit_msg>Keyboard Support #2<commit_after>﻿using UnityEngine;
using System;
using System.Linq;
using System.Collections.Generic;
using NodeEditorFramework;
using NodeEditorFramework.Utilities;
using System.Reflection;

namespace NodeEditorFramework 
{
	/// <summary>
	/// Collection of default Node Editor controls for the NodeEditorInputSystem
	/// </summary>
	public static class NodeEditorInputControls
	{
		#region Canvas Context Entries

		[ContextFillerAttribute (ContextType.Canvas)]
		private static void FillAddNodes (NodeEditorInputInfo inputInfo, GenericMenu canvasContextMenu) 
		{ // Show all nodes, and if a connection is drawn, only compatible nodes to auto-connect
			NodeEditorState state = inputInfo.editorState;
			List<Node> displayedNodes = state.connectOutput != null? NodeTypes.getCompatibleNodes (state.connectOutput) : NodeTypes.nodes.Keys.ToList ();
			foreach (Node compatibleNode in displayedNodes)
				canvasContextMenu.AddItem (new GUIContent ("Add " + NodeTypes.nodes[compatibleNode].adress), false, CreateNodeCallback, new NodeEditorInputInfo (compatibleNode.GetID, state));
		}

		private static void CreateNodeCallback (object infoObj)
		{
			NodeEditorInputInfo callback = infoObj as NodeEditorInputInfo;
			if (callback == null)
				throw new UnityException ("Callback Object passed by context is not of type NodeEditorInputInfo!");

			callback.SetAsCurrentEnvironment ();
			Node.Create (callback.message, NodeEditor.ScreenToCanvasSpace (callback.inputPos), callback.editorState.connectOutput);
			callback.editorState.connectOutput = null;
			NodeEditor.RepaintClients ();
		}

		#endregion

		#region Node Context Entries

		[ContextEntryAttribute (ContextType.Node, "Delete Node")]
		private static void DeleteNode (NodeEditorInputInfo inputInfo) 
		{
			inputInfo.SetAsCurrentEnvironment ();
			if (inputInfo.editorState.focusedNode != null) 
			{
				inputInfo.editorState.focusedNode.Delete ();
				inputInfo.inputEvent.Use ();
			}
		}

		[ContextEntryAttribute (ContextType.Node, "Duplicate Node")]
		private static void DuplicateNode (NodeEditorInputInfo inputInfo) 
		{
			inputInfo.SetAsCurrentEnvironment ();
			NodeEditorState state = inputInfo.editorState;
			if (state.focusedNode != null) 
			{ // Create new node of same type
				Node duplicatedNode = Node.Create (state.focusedNode.GetID, NodeEditor.ScreenToCanvasSpace (inputInfo.inputPos), state.connectOutput);
				state.selectedNode = state.focusedNode = duplicatedNode;
				state.connectOutput = null;
				inputInfo.inputEvent.Use ();
			}
		}

        #endregion

        #region Node Keyboard Control

        // Main Keyboard_Move method
        [HotkeyAttribute(KeyCode.UpArrow, EventType.KeyDown)]
        [HotkeyAttribute(KeyCode.LeftArrow, EventType.KeyDown)]
        [HotkeyAttribute(KeyCode.RightArrow, EventType.KeyDown)]
        [HotkeyAttribute(KeyCode.DownArrow, EventType.KeyDown)]
        private static void KB_MoveNode(NodeEditorInputInfo inputInfo)
        {
            NodeEditorState state = inputInfo.editorState;
            if (state.selectedNode != null)
            { 
                Vector2 pos = state.selectedNode.rect.position;

                int shiftAmount = 0;

                // Increase the distance moved to 10 if shift is being held.
                if (inputInfo.inputEvent.shift)
                    shiftAmount = 10;
                else
                    shiftAmount = 5;

                if (inputInfo.inputEvent.keyCode == KeyCode.RightArrow)
                    pos = new Vector2(pos.x + shiftAmount, pos.y);
                else if (inputInfo.inputEvent.keyCode == KeyCode.LeftArrow)
                    pos = new Vector2(pos.x - shiftAmount, pos.y);
                else if (inputInfo.inputEvent.keyCode == KeyCode.DownArrow)
                    pos = new Vector2(pos.x, pos.y + shiftAmount);
                else if (inputInfo.inputEvent.keyCode == KeyCode.UpArrow)
                    pos = new Vector2(pos.x, pos.y - shiftAmount);

                state.selectedNode.rect.position = pos;
                inputInfo.inputEvent.Use();
            }
            NodeEditor.RepaintClients();

        }


        #endregion

        #region Node Dragging

        [EventHandlerAttribute (EventType.MouseDown, priority = 110)] // Priority over hundred to make it call after the GUI
		private static void HandleNodeDraggingStart (NodeEditorInputInfo inputInfo) 
		{
			if (GUIUtility.hotControl > 0)
				return; // GUI has control

			NodeEditorState state = inputInfo.editorState;
			if (inputInfo.inputEvent.button == 0 && state.focusedNode != null && state.focusedNode == state.selectedNode && state.focusedNodeKnob == null) 
			{ // Clicked inside the selected Node, so start dragging it
				state.dragNode = true;
				state.dragStart = inputInfo.inputPos;
				state.dragPos = state.focusedNode.rect.position; // Need this here because of snapping
				state.dragOffset = Vector2.zero;
				inputInfo.inputEvent.delta = Vector2.zero;
			}
		}

		[EventHandlerAttribute (EventType.MouseDrag)]
		private static void HandleNodeDragging (NodeEditorInputInfo inputInfo) 
		{
			NodeEditorState state = inputInfo.editorState;
			if (state.dragNode) 
			{ // If conditions apply, drag the selected node, else disable dragging
				if (state.selectedNode != null && GUIUtility.hotControl == 0)
				{ // Calculate new position for the dragged object
{'fraction_non_alphanumeric': 0.08540103866128101, 'fraction_numerical': 0.003462204270051933, 'mean_word_length': 2.977704918032787, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4256613', 'n_tokens_mistral': 3555, 'n_tokens_neox': 3162, 'n_words': 823}