///Gets the bound rect for the nodes Rect GetNodeBounds(List <Node> nodes, Rect container, bool expandToContainer = false) { if (nodes == null || nodes.Count == 0) { return(container); } var arr = new Rect[nodes.Count]; for (var i = 0; i < nodes.Count; i++) { arr[i] = nodes[i].nodeRect; } var result = RectUtils.GetBoundRect(arr); if (expandToContainer) { result = RectUtils.GetBoundRect(result, container); } return(result); }
private Rectangle CalcRotatedBounds() { Size size = CalcStraightSize(); Matrix transform = new Matrix(); transform.Rotate(angle); Point[] boundPoints = { new Point(0, 0), new Point(size.Width, 0), new Point(size.Width, size.Height), new Point(0, size.Height) }; transform.TransformPoints(boundPoints); Rectangle result = new Rectangle(); foreach (Point p in boundPoints) { if (p.X < result.X) { RectUtils.SetLeft(ref result, p.X); } if (p.X > result.Right) { RectUtils.SetRight(ref result, p.X); } if (p.Y < result.Y) { RectUtils.SetTop(ref result, p.Y); } if (p.Y > result.Bottom) { RectUtils.SetBottom(ref result, p.Y); } } return(result); }
protected override void Execute(List <InputEntity> entities) { foreach (var entity in entities) { if (entity.hasInputSelectionFrameStart && entity.hasInputSelectionFrameEnd) { Vector3 sPos = entity.inputSelectionFrameStart.position; Vector3 ePos = entity.inputSelectionFrameEnd.position; Rect builtRect = RectUtils.CreateFromPoints(sPos, ePos); UiEntity rectEntity = uiContext.selectionUiEntity; if (rectEntity == null) { rectEntity = uiContext.CreateEntity(); rectEntity.isSelectionUi = true; rectEntity.AddAsset("Prefabs/SelectionRect"); } rectEntity.ReplaceRect(builtRect); } } }
/// <summary> /// 随机出生 /// </summary> /// <returns></returns> public Grid RandomBornGrid() { List <Rectangle> rects = RectUtils.Split(CheckGirdIsBlock, bornRect); List <Rectangle> x9rects = GetNeedsRects(rects, 9, 9);// >= 9的格子 间距3格 Rectangle targetRect; //左上角x y int x; int y; if (x9rects.Count > 0) { int idx = UnityEngine.Random.Range(0, x9rects.Count); targetRect = x9rects[idx]; //距离边框3格,能保证离敌人3格 x = RandomX(targetRect.x, targetRect.right, 3, 3 + Tracker.BornGroundSize[0]); y = RandomY(targetRect.y, targetRect.bottom, 3, 3 + Tracker.BornGroundSize[1]); return(grids[x, y]); } List <Rectangle> x3rects = GetNeedsRects(rects, 3, 3); if (x3rects.Count > 0) { int idx = UnityEngine.Random.Range(0, x3rects.Count); targetRect = x3rects[idx]; x = targetRect.x + UnityEngine.Random.Range(0, targetRect.width - Tracker.BornGroundSize[1]); y = targetRect.y + UnityEngine.Random.Range(0, targetRect.height - Tracker.BornGroundSize[1]); return(grids[x, y]); } //没有“放置点”,随机一个点,Warrning:考虑随机到敌人“身上”的情况 targetRect = Map.rect; x = RandomX(targetRect.x, targetRect.right, 3, 3 + Tracker.BornGroundSize[0]); y = RandomY(targetRect.y, targetRect.bottom, 3, 3 + Tracker.BornGroundSize[1]); return(grids[x, y]); }
public static Rect GetNodeRect(IList <NodeComponent> nodes) { if (nodes == null || nodes.Count == 0) { return(Rect.zero); } if (nodes.Count == 1) { return(nodes[0].editorRect); } Rect rect = Rect.zero; foreach (var node in nodes) { if (rect == Rect.zero) { rect = node.editorRect; continue; } rect = RectUtils.Encompass(rect, node.editorRect); } return(rect); }
public static Rect GetNodeRect(IList <UNodeView> nodes) { if (nodes == null || nodes.Count == 0) { return(Rect.zero); } if (nodes.Count == 1) { return(GetNodeRect(nodes[0])); } Rect rect = Rect.zero; foreach (var node in nodes) { if (rect == Rect.zero) { rect = GetNodeRect(node); continue; } rect = RectUtils.Encompass(rect, GetNodeRect(node)); } return(rect); }
public void OnPointerEnter(PointerEventData eventData) { if (PopUpManager.Instance.IsShowing()) { return; } // Show RectTransform rectTransform = GetComponent <RectTransform>(); PopUpManager.Instance.Show(data, RectUtils.RectTransformToScreenSpace(rectTransform)); if (OnTriggered != null) { OnTriggered.Invoke(); } // Destroy if (destroyOnTriggered) { Destroy(this); } }
public static List <TimelineClipUnion> Build(List <TimelineClipGUI> clips) { List <TimelineClipUnion> list = new List <TimelineClipUnion>(); List <TimelineClipUnion> result; if (clips == null) { result = list; } else { TimelineClipUnion timelineClipUnion = null; foreach (TimelineClipGUI current in clips) { Rect rect; if (timelineClipUnion == null) { timelineClipUnion = new TimelineClipUnion(); timelineClipUnion.Add(current); list.Add(timelineClipUnion); } else if (RectUtils.Intersection(current.bounds, timelineClipUnion.m_BoundingRect, ref rect)) { timelineClipUnion.Add(current); } else { timelineClipUnion = new TimelineClipUnion(); timelineClipUnion.Add(current); list.Add(timelineClipUnion); } } result = list; } return(result); }
public void OnMouseEnter() { // if (PopUpManager.Instance.IsShowing()) return; PointerEventData pointerEventData = new PointerEventData(EventSystem.current); //Set the Pointer Event Position to that of the mouse position pointerEventData.position = Input.mousePosition; //Create a list of Raycast Results List <RaycastResult> results = new List <RaycastResult>(); GraphicRaycaster gRaycaster = PopUpManager.Instance.GetGraphicRaycaster(); gRaycaster.Raycast(pointerEventData, results); if (results.Count != 0) { return; // Some kind of UI over trigger } // Show Collider collider = GetComponent <Collider>(); PopUpManager.Instance.Show(data, RectUtils.ColliderToScreenSpace(collider)); if (OnTriggered != null) { OnTriggered.Invoke(); } // Destroy if (destroyOnTriggered) { Destroy(this); } }
sealed protected override void DrawNodeConnections(Rect drawCanvas, bool fullDrawPass, Vector2 canvasMousePos, float zoomFactor) { var e = Event.current; //Receive connections first if (clickedPort != null && e.type == EventType.MouseUp && e.button == 0) { if (nodeRect.Contains(e.mousePosition)) { foreach (FSMConnection connection in inConnections) { if (connection.sourceNode == clickedPort.parent) { Debug.LogWarning("State is already connected to target state. Consider using a 'ConditionList' on the existing transition if you want to check multiple conditions"); clickedPort = null; e.Use(); return; } } graph.ConnectNodes(clickedPort.parent, this); clickedPort = null; e.Use(); } else { dragDropMisses++; if (dragDropMisses == graph.allNodes.Count && clickedPort != null) { var source = clickedPort.parent; var pos = Event.current.mousePosition; var menu = new GenericMenu(); clickedPort = null; menu.AddItem(new GUIContent("Add Action State"), false, () => { var newState = graph.AddNode <ActionState>(pos); graph.ConnectNodes(source, newState); }); //PostGUI cause of zoom factors Graph.PostGUI += () => { menu.ShowAsContext(); }; Event.current.Use(); e.Use(); } } } var portRectLeft = new Rect(0, 0, 20, 20); var portRectRight = new Rect(0, 0, 20, 20); var portRectBottom = new Rect(0, 0, 20, 20); portRectLeft.center = new Vector2(nodeRect.x - 11, nodeRect.center.y); portRectRight.center = new Vector2(nodeRect.xMax + 11, nodeRect.center.y); portRectBottom.center = new Vector2(nodeRect.center.x, nodeRect.yMax + 11); if (maxOutConnections != 0) { if (fullDrawPass || drawCanvas.Overlaps(nodeRect)) { EditorGUIUtility.AddCursorRect(portRectLeft, MouseCursor.ArrowPlus); EditorGUIUtility.AddCursorRect(portRectRight, MouseCursor.ArrowPlus); EditorGUIUtility.AddCursorRect(portRectBottom, MouseCursor.ArrowPlus); GUI.color = new Color(1, 1, 1, 0.3f); GUI.Box(portRectLeft, string.Empty, (GUIStyle)"arrowLeft"); GUI.Box(portRectRight, string.Empty, (GUIStyle)"arrowRight"); if (maxInConnections == 0) { GUI.Box(portRectBottom, string.Empty, (GUIStyle)"arrowBottom"); } GUI.color = Color.white; if (Graph.allowClick && e.type == EventType.MouseDown && e.button == 0) { if (portRectLeft.Contains(e.mousePosition)) { clickedPort = new GUIPort(this, portRectLeft.center); dragDropMisses = 0; e.Use(); } if (portRectRight.Contains(e.mousePosition)) { clickedPort = new GUIPort(this, portRectRight.center); dragDropMisses = 0; e.Use(); } if (maxInConnections == 0 && portRectBottom.Contains(e.mousePosition)) { clickedPort = new GUIPort(this, portRectBottom.center); dragDropMisses = 0; e.Use(); } } } } if (clickedPort != null && clickedPort.parent == this) { Handles.DrawBezier(clickedPort.pos, e.mousePosition, clickedPort.pos, e.mousePosition, new Color(0.5f, 0.5f, 0.8f, 0.8f), null, 2); } for (var i = 0; i < outConnections.Count; i++) { var connection = outConnections[i] as FSMConnection; var targetState = connection.targetNode as FSMState; if (targetState == null) //In case of MissingNode type { continue; } var targetPos = targetState.GetConnectedInPortPosition(connection); var sourcePos = Vector2.zero; if (nodeRect.center.x <= targetPos.x) { sourcePos = portRectRight.center; } if (nodeRect.center.x > targetPos.x) { sourcePos = portRectLeft.center; } if (maxInConnections == 0 && nodeRect.center.y < targetPos.y - 50 && Mathf.Abs(nodeRect.center.x - targetPos.x) < 200) { sourcePos = portRectBottom.center; } var boundRect = RectUtils.GetBoundRect(sourcePos, targetPos); if (fullDrawPass || drawCanvas.Overlaps(boundRect)) { connection.DrawConnectionGUI(sourcePos, targetPos); } } }
public override Point GetLocation(ArtboardSnapParameters parameters) { return(RectUtils.GetPoint(parameters.Rect, RectPoint)); }
//Seal it... sealed protected override void DrawNodeConnections(Rect drawCanvas, bool fullDrawPass, Vector2 canvasMousePos, float zoomFactor) { var e = Event.current; //Port container graphics if (fullDrawPass || drawCanvas.Overlaps(rect)) { GUI.Box(new Rect(rect.x - 8, rect.y + 2, 10, rect.height), string.Empty, CanvasStyles.nodePortContainer); GUI.Box(new Rect(rect.xMax - 2, rect.y + 2, 10, rect.height), string.Empty, CanvasStyles.nodePortContainer); } /// if (fullDrawPass || drawCanvas.Overlaps(rect)) { var portRect = new Rect(0, 0, 10, 10); //INPUT Ports if (orderedInputs != null) { Port instancePort = null; for (var i = 0; i < orderedInputs.Length; i++) { var port = orderedInputs[i]; var canConnect = true; if (clickedPort != null) { if ((port == clickedPort) || (clickedPort.parent == port.parent) || (clickedPort.IsInputPort()) || (port.isConnected && port is ValueInput) || (!TypeConverter.HasConvertion(clickedPort.type, port.type))) { canConnect = false; } } port.pos = new Vector2(rect.x - 5, rect.y + port.posOffsetY); portRect.width = port.isConnected? 12:10; portRect.height = portRect.width; portRect.center = port.pos; //first gameobject or component port is considered to be the 'instance' port by convention if (port == firstValuePort) { if (port.IsUnitySceneObject()) { instancePort = port; } } //Port graphic if (clickedPort != null && !canConnect && clickedPort != port) { GUI.color = new Color(1, 1, 1, 0.3f); } GUI.Box(portRect, string.Empty, port.isConnected? CanvasStyles.nodePortConnected : CanvasStyles.nodePortEmpty); GUI.color = Color.white; //Tooltip if (portRect.Contains(e.mousePosition)) { var labelString = (canConnect || port.isConnected || port == clickedPort)? port.type.FriendlyName() : "Can't Connect Here"; var size = CanvasStyles.box.CalcSize(new GUIContent(labelString)); var rect = new Rect(0, 0, size.x + 10, size.y + 5); rect.x = portRect.x - size.x - 10; rect.y = portRect.y - size.y / 2; GUI.Box(rect, labelString, CanvasStyles.box); //Or value } else { if (port is ValueInput && !port.isConnected) { //Only these types are shown their value if (port.type.IsValueType || port.type == typeof(Type) || port.type == typeof(string) || port.IsUnityObject()) { var value = (port as ValueInput).serializedValue; string labelString = null; if (!(port as ValueInput).isDefaultValue) { if (value is UnityEngine.Object && value as UnityEngine.Object != null) { labelString = string.Format("<b><color=#66ff33>{0}</color></b>", (value as UnityEngine.Object).name); } else { labelString = value.ToStringAdvanced(); } } else if (port == instancePort) { var exists = true; if (graphAgent != null && typeof(Component).IsAssignableFrom(port.type)) { exists = graphAgent.GetComponent(port.type) != null; } var color = exists? "66ff33" : "ff3300"; labelString = string.Format("<color=#{0}><b>♟ <i>Self</i></b></color>", color); } else { GUI.color = new Color(1, 1, 1, 0.15f); labelString = value.ToStringAdvanced(); } var size = CanvasStyles.label.CalcSize(new GUIContent(labelString)); var rect = new Rect(0, 0, size.x, size.y); rect.x = portRect.x - size.x - 5; rect.y = portRect.y - size.y * 0.3f; //*0.3? something's wrong here. FIX GUI.Label(rect, labelString, CanvasStyles.label); GUI.color = Color.white; } } } if (GraphEditorUtility.allowClick) { //Right click removes connections if (port.isConnected && e.type == EventType.ContextClick && portRect.Contains(e.mousePosition)) { foreach (var c in GetInPortConnections(port)) { graph.RemoveConnection(c); } e.Use(); return; } //Click initialize new drag & drop connection if (e.type == EventType.MouseDown && e.button == 0 && portRect.Contains(e.mousePosition)) { if (port.CanAcceptConnections()) { dragDropMisses = 0; clickedPort = port; e.Use(); } } //Drop on creates connection if (e.type == EventType.MouseUp && e.button == 0 && clickedPort != null) { if (portRect.Contains(e.mousePosition) && port.CanAcceptConnections()) { BinderConnection.Create(clickedPort, port); clickedPort = null; e.Use(); } } } } } //OUTPUT Ports if (orderedOutputs != null) { for (var i = 0; i < orderedOutputs.Length; i++) { var port = orderedOutputs[i]; var canConnect = true; if (clickedPort != null) { if ((port == clickedPort) || (clickedPort.parent == port.parent) || (clickedPort.IsOutputPort()) || (port.isConnected && port is FlowOutput) || (!TypeConverter.HasConvertion(port.type, clickedPort.type))) { canConnect = false; } } port.pos = new Vector2(rect.xMax + 5, rect.y + port.posOffsetY); portRect.width = port.isConnected? 12:10; portRect.height = portRect.width; portRect.center = port.pos; //Port graphic if (clickedPort != null && !canConnect && clickedPort != port) { GUI.color = new Color(1, 1, 1, 0.3f); } GUI.Box(portRect, string.Empty, port.isConnected? CanvasStyles.nodePortConnected : CanvasStyles.nodePortEmpty); GUI.color = Color.white; //Tooltip if (portRect.Contains(e.mousePosition)) { var labelString = (canConnect || port.isConnected || port == clickedPort)? port.type.FriendlyName() : "Can't Connect Here"; var size = CanvasStyles.box.CalcSize(new GUIContent(labelString)); var rect = new Rect(0, 0, size.x + 10, size.y + 5); rect.x = portRect.x + 15; rect.y = portRect.y - portRect.height / 2; GUI.Box(rect, labelString, CanvasStyles.box); } if (GraphEditorUtility.allowClick) { //Right click removes connections if (e.type == EventType.ContextClick && portRect.Contains(e.mousePosition)) { foreach (var c in GetOutPortConnections(port)) { graph.RemoveConnection(c); } e.Use(); return; } //Click initialize new drag & drop connection if (e.type == EventType.MouseDown && e.button == 0 && portRect.Contains(e.mousePosition)) { if (port.CanAcceptConnections()) { dragDropMisses = 0; clickedPort = port; e.Use(); } } //Drop on creates connection if (e.type == EventType.MouseUp && e.button == 0 && clickedPort != null) { if (portRect.Contains(e.mousePosition) && port.CanAcceptConnections()) { BinderConnection.Create(port, clickedPort); clickedPort = null; e.Use(); } } } } } } ///ACCEPT CONNECTION if (clickedPort != null && e.type == EventType.MouseUp) { ///ON NODE if (rect.Contains(e.mousePosition)) { var cachePort = clickedPort; var menu = new GenericMenu(); if (cachePort is ValueOutput || cachePort is FlowOutput) { if (orderedInputs != null) { foreach (var _port in orderedInputs.Where(p => p.CanAcceptConnections() && TypeConverter.HasConvertion(cachePort.type, p.type))) { var port = _port; menu.AddItem(new GUIContent(string.Format("To: '{0}'", port.name)), false, () => { BinderConnection.Create(cachePort, port); }); } } } else { if (orderedOutputs != null) { foreach (var _port in orderedOutputs.Where(p => p.CanAcceptConnections() && TypeConverter.HasConvertion(p.type, cachePort.type))) { var port = _port; menu.AddItem(new GUIContent(string.Format("From: '{0}'", port.name)), false, () => { BinderConnection.Create(port, cachePort); }); } } } //append menu items menu = OnDragAndDropPortContextMenu(menu, cachePort); //if there is only 1 option, just do it if (menu.GetItemCount() == 1) { EditorUtils.GetMenuItems(menu)[0].func(); } else { GraphEditorUtility.PostGUI += () => { menu.ShowAsContext(); }; } clickedPort = null; e.Use(); /// ///ON CANVAS } else { dragDropMisses++; if (dragDropMisses == graph.allNodes.Count && clickedPort != null) { var cachePort = clickedPort; clickedPort = null; DoContextPortConnectionMenu(cachePort, e.mousePosition, zoomFactor); e.Use(); } } } //Temp connection line when linking if (clickedPort != null && clickedPort.parent == this) { var from = clickedPort.pos; var to = e.mousePosition; var xDiff = (from.x - to.x) * 0.8f; xDiff = to.x > from.x? xDiff : -xDiff; var tangA = clickedPort is FlowInput || clickedPort is ValueInput? new Vector2(xDiff, 0) : new Vector2(-xDiff, 0); var tangB = tangA * -1; Handles.DrawBezier(from, to, from + tangA, to + tangB, new Color(0.5f, 0.5f, 0.8f, 0.8f), null, 3); } //Actualy draw the existing connections for (var i = 0; i < outConnections.Count; i++) { var binder = outConnections[i] as BinderConnection; if (binder != null) //for in case it's MissingConnection { var sourcePort = binder.sourcePort; var targetPort = binder.targetPort; if (sourcePort != null && targetPort != null) { if (fullDrawPass || drawCanvas.Overlaps(RectUtils.GetBoundRect(sourcePort.pos, targetPort.pos))) { binder.DrawConnectionGUI(sourcePort.pos, targetPort.pos); } } } } }
internal static Point GetPoint(this Rect rect, RectPoint rectPoint) { return(RectUtils.GetPoint(rect, rectPoint)); }
public static double HalfWidth(this Rect rect) { return(RectUtils.HalfWidth(rect)); }
///---------------------------------------------------------------------------------------------- ///---------------------------------------------------------------------------------------------- ///Convert nodes to macro (with a bit of hocus pocus) public static void ConvertNodesToMacro(List <Node> originalNodes) { if (originalNodes == null || originalNodes.Count == 0) { return; } if (!UnityEditor.EditorUtility.DisplayDialog("Convert to Macro", "This will create a new Macro out of the nodes.\nPlease note that since Macros are assets, Scene Object references will not be saved.\nThe Macro can NOT be unpacked later on.\nContinue?", "Yes", "No!")) { return; } //create asset var newMacro = EditorUtils.CreateAsset <Macro>(); if (newMacro == null) { return; } //undo var graph = (FlowScriptBase)originalNodes[0].graph; graph.RecordUndo("Convert To Macro"); //clone nodes var cloned = Graph.CloneNodes(originalNodes, newMacro, -newMacro.translation); //clear initial "example" ports newMacro.inputDefinitions.Clear(); newMacro.outputDefinitions.Clear(); //cache used ports var inputMergeMapSource = new Dictionary <Port, Port>(); var inputMergeMapTarget = new Dictionary <Port, Port>(); var outputMergeMapTarget = new Dictionary <Port, Port>(); var outputMergeMapSource = new Dictionary <Port, Port>(); //relink copied nodes to inside macro entry/exit for (var i = 0; i < originalNodes.Count; i++) { var originalNode = originalNodes[i]; //create macro entry node port definitions and link those to input ports of cloned nodes inside foreach (var originalInputConnection in originalNode.inConnections.OfType <BinderConnection>()) { //only do stuff if link source node is not part of the clones if (originalNodes.Contains(originalInputConnection.sourceNode)) { continue; } Port defSourcePort = null; //merge same input ports and same target ports if (!inputMergeMapSource.TryGetValue(originalInputConnection.sourcePort, out defSourcePort)) { if (!inputMergeMapTarget.TryGetValue(originalInputConnection.targetPort, out defSourcePort)) { //remark: we use sourcePort.type instead of target port type, so that connections remain assignable var def = new DynamicPortDefinition(originalInputConnection.targetPort.name, originalInputConnection.sourcePort.type); defSourcePort = newMacro.AddInputDefinition(def); inputMergeMapTarget[originalInputConnection.targetPort] = defSourcePort; } inputMergeMapSource[originalInputConnection.sourcePort] = defSourcePort; } if (defSourcePort.CanAcceptConnections()) //check this for case of merged FlowPorts { var targetPort = (cloned[i] as FlowNode).GetInputPort(originalInputConnection.targetPortID); BinderConnection.Create(defSourcePort, targetPort); } } //create macro exit node port definitions and link those to output ports of cloned nodes inside foreach (var originalOutputConnection in originalNode.outConnections.OfType <BinderConnection>()) { //only do stuff if link target node is not part of the clones if (originalNodes.Contains(originalOutputConnection.targetNode)) { continue; } Port defTargetPort = null; //merge same input ports and same target ports if (!outputMergeMapTarget.TryGetValue(originalOutputConnection.targetPort, out defTargetPort)) { if (!outputMergeMapSource.TryGetValue(originalOutputConnection.sourcePort, out defTargetPort)) { var def = new DynamicPortDefinition(originalOutputConnection.sourcePort.name, originalOutputConnection.sourcePort.type); defTargetPort = newMacro.AddOutputDefinition(def); outputMergeMapSource[originalOutputConnection.sourcePort] = defTargetPort; } outputMergeMapTarget[originalOutputConnection.targetPort] = defTargetPort; } if (defTargetPort.CanAcceptConnections()) //check this for case of merged ValuePorts { var sourcePort = (cloned[i] as FlowNode).GetOutputPort(originalOutputConnection.sourcePortID); BinderConnection.Create(sourcePort, defTargetPort); } } } //Delete originals var originalBounds = RectUtils.GetBoundRect(originalNodes.Select(n => n.rect).ToArray()); foreach (var node in originalNodes.ToArray()) { graph.RemoveNode(node, false); } //Create MacroWrapper. Relink macro wrapper to outside nodes var wrapperPos = originalBounds.center; wrapperPos.x = (int)wrapperPos.x; wrapperPos.y = (int)wrapperPos.y; var wrapper = graph.AddMacroNode(newMacro, wrapperPos, null, null); wrapper.GatherPorts(); foreach (var pair in inputMergeMapSource) { var source = pair.Key; var target = wrapper.GetInputPort(pair.Value.ID); BinderConnection.Create(source, target); } foreach (var pair in outputMergeMapTarget) { var source = wrapper.GetOutputPort(pair.Value.ID); var target = pair.Key; BinderConnection.Create(source, target); } //organize a bit var clonedBounds = RectUtils.GetBoundRect(cloned.Select(n => n.rect).ToArray()); newMacro.entry.position = new Vector2((int)(clonedBounds.xMin - 300), (int)clonedBounds.yMin); newMacro.exit.position = new Vector2((int)(clonedBounds.xMax + 300), (int)clonedBounds.yMin); newMacro.translation = -newMacro.entry.position + new Vector2(300, 300); // //validate and save newMacro.Validate(); UnityEditor.AssetDatabase.SaveAssets(); }
protected override Rect ArrangeOverride(Size desiredSize) { return(RectUtils.CalcAlignBox(ScreenBoundsCore, desiredSize.Rect(), Popup.HorizontalAlignment, Popup.VerticalAlignment)); }
//Do graphical multi selection box for nodes static void DoCanvasRectSelection(Rect container) { if (GraphEditorUtility.allowClick && e.type == EventType.MouseDown && e.button == 0 && !e.alt && canvasRect.Contains(CanvasToView(e.mousePosition))) { currentMultiSelection.Clear(); if (GraphEditorUtility.activeElements != null && GraphEditorUtility.activeElements.Count > 0) { currentMultiSelection.AddRange(GraphEditorUtility.activeElements); } GraphEditorUtility.activeElement = null; selectionStartPos = e.mousePosition; isMultiSelecting = true; e.Use(); } if (isMultiSelecting && e.rawType == EventType.MouseUp) { var rect = RectUtils.GetBoundRect(selectionStartPos, e.mousePosition); var overlapedNodes = currentGraph.allNodes.Where(n => rect.Overlaps(n.rect) && !n.isHidden).ToList(); isMultiSelecting = false; if (e.control && e.shift && rect.width > 50 && rect.height > 50) { Undo.RegisterCompleteObjectUndo(currentGraph, "Create Group"); if (currentGraph.canvasGroups == null) { currentGraph.canvasGroups = new List <CanvasGroup>(); } currentGraph.canvasGroups.Add(new CanvasGroup(rect, "New Canvas Group")); } else if (e.control && !e.shift) { if (overlapedNodes.Count > 0) { GraphEditorUtility.activeElements = currentMultiSelection.Union(overlapedNodes.Cast <object>().ToList()).ToList(); e.Use(); } Undo.RegisterCompleteObjectUndo(currentGraph, "Add nodes"); } else if (!e.control && e.shift) { if (overlapedNodes.Count > 0) { //Debug.Log("currentnodes:" + currentMultiSelection.Count + "reduce nodes:" + overlapedNodes.Count); GraphEditorUtility.activeElements = currentMultiSelection.Except(overlapedNodes.Cast <object>().ToList()).ToList(); e.Use(); } Undo.RegisterCompleteObjectUndo(currentGraph, "reduce nodes"); } else { if (overlapedNodes.Count > 0) { GraphEditorUtility.activeElements = overlapedNodes.Cast <object>().ToList(); e.Use(); } } } if (isMultiSelecting) { var rect = RectUtils.GetBoundRect(selectionStartPos, e.mousePosition); if (rect.width > 5 && rect.height > 5) { GUI.color = new Color(0.5f, 0.5f, 1, 0.3f); GUI.Box(rect, string.Empty, CanvasStyles.box); foreach (var node in currentGraph.allNodes) { if (rect.Overlaps(node.rect) && !node.isHidden) { var highlightRect = node.rect; GUI.Box(highlightRect, string.Empty, CanvasStyles.windowHighlight); } } if (rect.width > 50 && rect.height > 50) { GUI.color = new Color(1, 1, 1, e.control? 0.6f : 0.15f); GUI.Label(new Rect(e.mousePosition.x + 16, e.mousePosition.y, 120, 22), "<i>+ control and shift for group</i>", CanvasStyles.label); } } } GUI.color = Color.white; }
public IEnumerator UpdateScopeGeometryAfterMovedElements() { Scope scope = CreateScope(10, 10); // Allow one frame for the scope to be placed onto a layer and for the nodes to compute their layouts yield return(null); // Allow one frame for the scope to compute its geometry (position) yield return(null); // Allow one frame for the scope to update its layout yield return(null); // Get the total margins around the content of the scope float leftMargin, topMargin, rightMargin, bottomMargin; GetScopeMargins(scope, out leftMargin, out topMargin, out rightMargin, out bottomMargin); Vector2 initialSize = scope.GetPosition().size; Rect node1Geom = m_Node1.GetPosition(); Rect node2Geom = m_Node2.GetPosition(); scope.AddElement(m_Node1); scope.AddElement(m_Node2); // Allow couple frames for the scope to compute its geometry (position) int iteration = 0; while (scope.hasPendingGeometryUpdate && iteration++ < k_MaxIterations) { yield return(null); } // Allow one frame for the scope to update its layout yield return(null); // Moves node1 and node2 node1Geom.x -= 20; node1Geom.y -= 30; node2Geom.x += 40; node2Geom.y += 50; m_Node1.SetPosition(node1Geom); m_Node2.SetPosition(node2Geom); // Allow two frames for node1 and node2 to compute their layouts yield return(null); yield return(null); // Allow couple frames for the scope to compute its geometry (position) iteration = 0; while (scope.hasPendingGeometryUpdate && iteration++ < k_MaxIterations) { yield return(null); } // Allow one frame for the scope to update its layout yield return(null); // Computes the bounding rect of node1 and node2 Rect contentBoundingRectInViewportSpace = GetBoundingRectInViewportSpace(scope.containedElements); Rect scopeGeometryInViewportSpace = scope.ChangeCoordinatesTo(graphView.contentViewContainer, scope.GetRect()); // Verify that the geometries of node1 and node2 have not changed while the geometry of the scope has been recomputed Assert.AreEqual(node1Geom, m_Node1.GetPosition()); Assert.AreEqual(node2Geom, m_Node2.GetPosition()); Assert.AreEqual(scopeGeometryInViewportSpace, RectUtils.Inflate(contentBoundingRectInViewportSpace, leftMargin, topMargin, rightMargin, bottomMargin)); }
public static Range <double> GetRange(this Rect rect, Orientation orientation) { return(RectUtils.GetRange(rect, orientation)); }
public static Rect IntersectionWith(this Rect rect, Rect another) { return(RectUtils.Intersect(rect, another)); }
public void RecomputeBounds() { if (m_WaitingRecompute) { return; } //title width should be at least as wide as a context to be valid. float titleWidth = m_Title.layout.width; bool invalidTitleWidth = float.IsNaN(titleWidth) || titleWidth < 50; bool titleEmpty = string.IsNullOrEmpty(m_Title.text) || invalidTitleWidth; if (titleEmpty) { m_Title.AddToClassList("empty"); } else { m_Title.RemoveFromClassList("empty"); } Rect rect = Rect.zero; if (m_Contexts != null) { foreach (var context in m_Contexts) { if (context != null) { if (rect == Rect.zero) { rect = context.localBound; } else { rect = RectUtils.Encompass(rect, context.GetPosition()); } } } } if (float.IsNaN(rect.xMin) || float.IsNaN(rect.yMin) || float.IsNaN(rect.width) || float.IsNaN(rect.height)) { rect = Rect.zero; } rect = RectUtils.Inflate(rect, 20, titleEmpty ? 20 : m_Title.layout.height, 20, 20); if (invalidTitleWidth) { SetPosition(rect); if (!m_WaitingRecompute) { m_WaitingRecompute = true; schedule.Execute(() => { m_WaitingRecompute = false; RecomputeBounds(); }).ExecuteLater(0); // title height might have changed if width have changed } } else { SetPosition(rect); } }
public static double GetMinPart(this Rect rect, Orientation orientation) { return(RectUtils.GetMinPart(rect, orientation)); }
//Draw the ports and connections sealed protected override void DrawNodeConnections(Rect drawCanvas, bool fullDrawPass, Vector2 canvasMousePos, float zoomFactor) { var e = Event.current; //Receive connections first if (clickedPort != null && e.type == EventType.MouseUp && e.button == 0) { if (rect.Contains(e.mousePosition)) { graph.ConnectNodes(clickedPort.parent, this); clickedPort = null; e.Use(); } else { dragDropMisses++; if (dragDropMisses == graph.allNodes.Count && clickedPort != null) { var source = clickedPort.parent; var pos = Event.current.mousePosition; var menu = new GenericMenu(); clickedPort = null; menu.AddItem(new GUIContent("Add Action State"), false, () => { var newState = graph.AddNode <ActionState>(pos); graph.ConnectNodes(source, newState); }); //PostGUI cause of zoom factors GraphEditorUtility.PostGUI += () => { menu.ShowAsContext(); }; Event.current.Use(); e.Use(); } } } var portRectLeft = new Rect(0, 0, 20, 20); var portRectRight = new Rect(0, 0, 20, 20); var portRectBottom = new Rect(0, 0, 20, 20); portRectLeft.center = new Vector2(rect.x - 11, rect.center.y); portRectRight.center = new Vector2(rect.xMax + 11, rect.center.y); portRectBottom.center = new Vector2(rect.center.x, rect.yMax + 11); if (maxOutConnections != 0) { if (fullDrawPass || drawCanvas.Overlaps(rect)) { EditorGUIUtility.AddCursorRect(portRectLeft, MouseCursor.ArrowPlus); EditorGUIUtility.AddCursorRect(portRectRight, MouseCursor.ArrowPlus); EditorGUIUtility.AddCursorRect(portRectBottom, MouseCursor.ArrowPlus); GUI.color = new Color(1, 1, 1, 0.3f); GUI.DrawTexture(portRectLeft, StyleSheet.arrowLeft); GUI.DrawTexture(portRectRight, StyleSheet.arrowRight); if (maxInConnections == 0) { GUI.DrawTexture(portRectBottom, StyleSheet.arrowBottom); } GUI.color = Color.white; if (GraphEditorUtility.allowClick && e.type == EventType.MouseDown && e.button == 0) { if (portRectLeft.Contains(e.mousePosition)) { clickedPort = new GUIPort(this, portRectLeft.center); dragDropMisses = 0; e.Use(); } if (portRectRight.Contains(e.mousePosition)) { clickedPort = new GUIPort(this, portRectRight.center); dragDropMisses = 0; e.Use(); } if (maxInConnections == 0 && portRectBottom.Contains(e.mousePosition)) { clickedPort = new GUIPort(this, portRectBottom.center); dragDropMisses = 0; e.Use(); } } } } //draw new linking if (clickedPort != null && clickedPort.parent == this) { Handles.DrawBezier(clickedPort.pos, e.mousePosition, clickedPort.pos, e.mousePosition, new Color(0.5f, 0.5f, 0.8f, 0.8f), null, 2); } //draw out connections for (var i = 0; i < outConnections.Count; i++) { var connection = outConnections[i] as FSMConnection; var targetState = connection.targetNode as FSMState; if (targetState == null) { //In case of MissingNode type continue; } var targetPos = targetState.GetConnectedInPortPosition(connection); var sourcePos = Vector2.zero; if (rect.center.x <= targetPos.x) { sourcePos = portRectRight.center; } if (rect.center.x > targetPos.x) { sourcePos = portRectLeft.center; } if (maxInConnections == 0 && rect.center.y < targetPos.y - 50 && Mathf.Abs(rect.center.x - targetPos.x) < 200) { sourcePos = portRectBottom.center; } var boundRect = RectUtils.GetBoundRect(sourcePos, targetPos); if (fullDrawPass || drawCanvas.Overlaps(boundRect)) { connection.DrawConnectionGUI(sourcePos, targetPos); } } }
///Translate the graph to the center of the target connection public void FocusConnection(Connection connection) { var bound = RectUtils.GetBoundRect(connection.sourceNode.nodeRect, connection.targetNode.nodeRect); FocusPosition(bound.center); }
///Editor. Draw the connections line from this node, to all of its children. This is the default hierarchical tree style. Override in each system's base node class. virtual protected void DrawNodeConnections(Rect drawCanvas, bool fullDrawPass, Vector2 canvasMousePos, float zoomFactor) { var e = Event.current; //Receive connections first if ( clickedPort != null && e.type == EventType.MouseUp && e.button == 0 ) { if ( rect.Contains(e.mousePosition) ) { graph.ConnectNodes(clickedPort.parent, this, clickedPort.portIndex); clickedPort = null; e.Use(); } else { dragDropMisses++; if ( dragDropMisses == graph.allNodes.Count && clickedPort != null ) { var source = clickedPort.parent; var index = clickedPort.portIndex; var pos = e.mousePosition; clickedPort = null; System.Action<System.Type> Selected = delegate (System.Type type) { var newNode = graph.AddNode(type, pos); graph.ConnectNodes(source, newNode, index); GraphEditorUtility.activeElement = newNode; }; var menu = EditorUtils.GetTypeSelectionMenu(graph.baseNodeType, Selected); if ( zoomFactor == 1 ) { menu.ShowAsBrowser(string.Format("Add {0} Node", graph.GetType().Name), graph.baseNodeType); } else { GraphEditorUtility.PostGUI += () => { menu.ShowAsContext(); }; } e.Use(); } } } if ( maxOutConnections == 0 ) { return; } if ( fullDrawPass || drawCanvas.Overlaps(rect) ) { var nodeOutputBox = new Rect(rect.x, rect.yMax - 4, rect.width, 12); GUI.Box(nodeOutputBox, string.Empty, StyleSheet.nodePortContainer); //draw the ports if ( outConnections.Count < maxOutConnections || maxOutConnections == -1 ) { for ( var i = 0; i < outConnections.Count + 1; i++ ) { var portRect = new Rect(0, 0, 10, 10); portRect.center = new Vector2(( ( rect.width / ( outConnections.Count + 1 ) ) * ( i + 0.5f ) ) + rect.xMin, rect.yMax + 6); GUI.Box(portRect, string.Empty, StyleSheet.nodePortEmpty); if ( collapsed ) { continue; } if ( GraphEditorUtility.allowClick ) { //start a connection by clicking a port EditorGUIUtility.AddCursorRect(portRect, MouseCursor.ArrowPlus); if ( e.type == EventType.MouseDown && e.button == 0 && portRect.Contains(e.mousePosition) ) { dragDropMisses = 0; clickedPort = new GUIPort(i, this, portRect.center); e.Use(); } } } } } //draw the new drag&drop connection line if ( clickedPort != null && clickedPort.parent == this ) { var tangA = default(Vector2); var tangB = default(Vector2); ParadoxNotion.CurveUtils.ResolveTangents(clickedPort.pos, e.mousePosition, 0.5f, PlanarDirection.Vertical, out tangA, out tangB); Handles.DrawBezier(clickedPort.pos, e.mousePosition, clickedPort.pos + tangA, e.mousePosition + tangB, StyleSheet.GetStatusColor(Status.Resting).WithAlpha(0.8f), null, 3); } //draw all connected lines for ( var i = 0; i < outConnections.Count; i++ ) { var connection = outConnections[i]; if ( connection != null ) { var sourcePos = new Vector2(( ( rect.width / ( outConnections.Count + 1 ) ) * ( i + 1 ) ) + rect.xMin, rect.yMax + 6); var targetPos = new Vector2(connection.targetNode.rect.center.x, connection.targetNode.rect.y); var sourcePortRect = new Rect(0, 0, 12, 12); sourcePortRect.center = sourcePos; var targetPortRect = new Rect(0, 0, 15, 15); targetPortRect.center = targetPos; var boundRect = RectUtils.GetBoundRect(sourcePortRect, targetPortRect); if ( fullDrawPass || drawCanvas.Overlaps(boundRect) ) { GUI.Box(sourcePortRect, string.Empty, StyleSheet.nodePortConnected); if ( collapsed || connection.targetNode.isHidden ) { continue; } connection.DrawConnectionGUI(sourcePos, targetPos); if ( GraphEditorUtility.allowClick ) { //On right click disconnect connection from the source. if ( e.type == EventType.ContextClick && sourcePortRect.Contains(e.mousePosition) ) { graph.RemoveConnection(connection); e.Use(); return; } //On right click disconnect connection from the target. if ( e.type == EventType.ContextClick && targetPortRect.Contains(e.mousePosition) ) { graph.RemoveConnection(connection); e.Use(); return; } } } } } }
public static Point GetTopRight(this Rect rect) { return(RectUtils.GetTopRight(rect)); }
/// A simple reorderable list. Pass the list and a function to call for GUI. The callback comes with the current iterated element index in the list static void Internal_ReorderableList(IList list, ReorderableListOptions options, ReorderableListCallback GUICallback, UnityObject unityObject) { if (list == null || list.Count == 0) { return; } if (!pickedListIndex.ContainsKey(list)) { pickedListIndex[list] = -1; } var e = Event.current; var pickedIndex = pickedListIndex[list]; var handleStyle = new GUIStyle("label"); handleStyle.alignment = TextAnchor.MiddleCenter; for (var i = 0; i < list.Count; i++) { GUILayout.BeginHorizontal(); GUILayout.Space(16); GUILayout.BeginVertical(); GUICallback(i, pickedIndex == i); GUILayout.EndVertical(); var lastRect = GUILayoutUtility.GetLastRect(); var pickRect = Rect.MinMaxRect(lastRect.xMin - 16, lastRect.yMin, lastRect.xMin, lastRect.yMax); GUI.color = new Color(1, 1, 1, 0.5f); GUI.Label(pickRect, "☰", handleStyle); GUI.color = Color.white; if (options.allowRemove) { GUILayout.Space(16); var removeRect = Rect.MinMaxRect(lastRect.xMax, lastRect.yMin, lastRect.xMax + 16, lastRect.yMax); if (GUI.Button(removeRect, "X")) { if (unityObject != null) { Undo.RecordObject(unityObject, "Remove Item"); } list.RemoveAt(i); GUI.changed = true; if (unityObject != null) { EditorUtility.SetDirty(unityObject); } } } GUILayout.EndHorizontal(); GUI.color = Color.white; GUI.backgroundColor = Color.white; EditorGUIUtility.AddCursorRect(pickRect, MouseCursor.MoveArrow); var boundRect = RectUtils.GetBoundRect(lastRect, pickRect); if (pickRect.Contains(e.mousePosition) && e.type == EventType.MouseDown) { pickedListIndex[list] = i; } if (pickedIndex == i) { GUI.Box(boundRect, string.Empty); } if (pickedIndex != -1 && pickedIndex != i && boundRect.Contains(e.mousePosition)) { var markRect = new Rect(boundRect.x, boundRect.y - 2, boundRect.width, 2); if (pickedIndex < i) { markRect.y = boundRect.yMax - 2; } GUI.Box(markRect, string.Empty); if (e.type == EventType.MouseUp) { if (unityObject != null) { Undo.RecordObject(unityObject, "Reorder Item"); } var obj = list[pickedIndex]; list.RemoveAt(pickedIndex); list.Insert(i, obj); pickedListIndex[list] = -1; GUI.changed = true; if (unityObject != null) { EditorUtility.SetDirty(unityObject); } } } } if (e.rawType == EventType.MouseUp) { pickedListIndex[list] = -1; } }
public static double HalfHeight(this Rect rect) { return(RectUtils.HalfHeight(rect)); }
void BuildRefactorContextualMenu(IReadOnlyCollection <IGraphElementModel> selectedModels) { var models = selectedModels.OfType <INodeModel>().ToArray(); if (!models.Any()) { return; } var enableConvertToFunction = true; var enableExtractMacro = true; var enableExtractFunction = true; var canDisable = models.Any(); var willDisable = models.Any(n => n.State == ModelState.Enabled); if (models.Length > 1) { enableConvertToFunction = false; } if (models.Any(x => x.IsStacked)) { enableExtractMacro = false; } else { enableExtractFunction = false; enableConvertToFunction = false; } if (models.OfType <IStackModel>().Any() || (!m_GraphView.store.GetState().CurrentGraphModel.Stencil.Capabilities.HasFlag(StencilCapabilityFlags.SupportsMacros))) { enableConvertToFunction = false; enableExtractMacro = false; enableExtractFunction = false; } if (enableConvertToFunction || enableExtractMacro || enableExtractFunction) { m_Evt.menu.AppendSeparator(); } if (enableConvertToFunction) { m_Evt.menu.AppendAction("Refactor/Convert to Function", _ => m_Store.Dispatch(new RefactorConvertToFunctionAction(models.Single())), _ => DropdownMenuAction.Status.Normal); } if (canDisable) { m_Evt.menu.AppendAction(willDisable ? "Disable Selection" : "Enable Selection", menuAction => { m_Store.Dispatch(new SetNodeEnabledStateAction(models, willDisable ? ModelState.Disabled : ModelState.Enabled)); }); } if (Unsupported.IsDeveloperBuild()) { m_Evt.menu.AppendAction("Internal/Redefine Node", action => { foreach (var model in selectedModels.OfType <NodeModel>()) { model.DefineNode(); } }, _ => DropdownMenuAction.Status.Normal); m_Evt.menu.AppendAction("Internal/Refresh Selected Element(s)", menuAction => { m_Store.Dispatch(new RefreshUIAction(selectedModels.ToList())); }, _ => DropdownMenuAction.Status.Normal); } if (enableExtractMacro) { m_Evt.menu.AppendAction("Refactor/Extract Macro", menuAction => { var rectToFit = new Rect(); bool first = true; foreach (var model in models) { GraphElement ge = null; if (m_GraphView.UIController.ModelsToNodeMapping?.TryGetValue(model, out ge) ?? false) { var r = ge.GetPosition(); rectToFit = first ? r : RectUtils.Encompass(rectToFit, r); first = false; } } string assetPath = AssetDatabase.GetAssetPath(m_GraphView.store.GetState()?.CurrentGraphModel?.AssetModel as VSGraphAssetModel); string macroPath = null; if (!string.IsNullOrEmpty(assetPath)) { var assetFolder = Path.GetDirectoryName(assetPath); macroPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(assetFolder ?? "", "MyMacro.asset")); } m_Store.Dispatch(new RefactorExtractMacroAction(m_Selection.OfType <IHasGraphElementModel>().Select(x => x.GraphElementModel).ToList(), rectToFit.center, macroPath)); }, x => DropdownMenuAction.Status.Normal); } if (enableExtractFunction) { m_Evt.menu.AppendAction("Refactor/Extract Function", menuAction => { var rectToFit = new Rect(); bool first = true; foreach (var model in models) { GraphElement ge = null; if (m_GraphView.UIController.ModelsToNodeMapping?.TryGetValue(model, out ge) ?? false) { var r = ge.GetPosition(); rectToFit = first ? r : RectUtils.Encompass(rectToFit, r); first = false; } } m_Store.Dispatch(new RefactorExtractFunctionAction(m_Selection)); }, x => DropdownMenuAction.Status.Normal); } }
public static double GetSize(this Rect rect, Orientation orientation) { return(RectUtils.GetSize(rect, orientation)); }