protected override void OnPointerUp() { base.OnPointerUp(); NodeProperties nodeBehaviour = this.GetComponent <NodeProperties>(); if (nodeBehaviour.m_nodeType == NodeProperties.NodeType.Simple) { if (m_attachedAnchor == null) { if (m_snappedAnchor != null) { m_attachedAnchor = m_snappedAnchor; m_snappedAnchor.Spread(); Destroy(nodeBehaviour.m_deactivatedGUIItem); } else { Destroy(this.gameObject); nodeBehaviour.m_deactivatedGUIItem.SetActive(true); } } } else if (nodeBehaviour.m_nodeType == NodeProperties.NodeType.TargetIndicator) { if (m_snappedAnchor != null) { this.m_parentNode.GetComponent <NodeMovement>().MoveParentNodeToAnchor(m_snappedAnchor); } Destroy(this.gameObject); //destroy the target indicator node Destroy(m_parentNode.GetComponent <NodeTouchHandler>().m_targetIndicatorBridge); //destroy the target indicator node } }
/** * Try to snap a node to an anchor if the distance to it is small enough ( <= m_snapDistance) * **/ bool SnapToClosestAnchor() { List <GridAnchor> allAnchors = m_gameController.m_anchors; for (int anchorIndex = 0; anchorIndex != allAnchors.Count; anchorIndex++) { GridAnchor snapAnchor = allAnchors[anchorIndex]; Vector2 position = this.transform.position; float fDistanceToAnchor = (position - snapAnchor.m_position).magnitude; if (snapAnchor != m_snappedAnchor) { if (fDistanceToAnchor <= m_snapDistance) { m_snappedAnchor = snapAnchor; transform.position = new Vector3(snapAnchor.m_position.x, snapAnchor.m_position.y, transform.position.z); return(true); } } } return(false); }
private GameObject m_parentNode; //the parent node of the target indicator node public void Awake() { m_snappedAnchor = null; m_attachedAnchor = null; m_targetAnchor = null; m_targetIndicatorNode = null; m_parentNode = null; }
/** * Moves the node to a target node on a straight line * **/ public void MoveParentNodeToAnchor(GridAnchor anchor) { if (m_movementPoints > 0) { m_moveStartAnchor = this.GetComponent <NodeTouchHandler>().m_attachedAnchor; m_moveEndAnchor = anchor; m_moving = true; m_movementPoints--; } }
/** * Removes a child anchor of this bridge * **/ public void RemoveAnchor(GridAnchor anchor) { //check if bridge is not already in this List for (int anchorIndex = 0; anchorIndex != m_anchors.Count; anchorIndex++) { if (m_anchors[anchorIndex].Equals(anchor)) { m_anchors.Remove(anchor); return; } } }
/** * Same as int AnchorExists(GridAnchor anchor) but this time search with the position as parameter * Returns the index of the anchor in this collection. * **/ int AnchorExists(Vector2 position) { for (int anchorIndex = 0; anchorIndex != m_anchors.Count; anchorIndex++) { GridAnchor anchorAtIndex = m_anchors[anchorIndex]; if (MathUtils.AreVec2PointsEqual(position, anchorAtIndex.m_position)) { return(anchorIndex); } } return(-1); }
/** * Set a new anchor as a child of this bridge * **/ public void PushAnchor(GridAnchor anchor) { for (int anchorIndex = 0; anchorIndex != m_anchors.Count; anchorIndex++) { if (m_anchors[anchorIndex].Equals(anchor)) { return; } } m_anchors.Add(anchor); }
public IntVector2 GetCellOffsets(GridData grid, GridAnchor anchor) { switch (anchor) { case GridAnchor.TOP: return(new IntVector2(0, -1 * grid.size.y)); case GridAnchor.BOTTOM: return(new IntVector2(0, this.grid.size.y)); case GridAnchor.RIGHT: return(new IntVector2(this.grid.size.x, 0)); case GridAnchor.LEFT: return(new IntVector2(-1 * grid.size.x, 0)); } return(new IntVector2(0, 0)); }
// Will add grid at runtime with settings of the current grid public void AddGrid(GridData grid, GridAnchor anchor) { var offset = GetCellOffsets(grid, anchor); foreach (var cell in grid.cells) { cell.cell.row += offset.x; cell.cell.column += offset.y; this.grid.cells.Add(cell); } RecalculateGridSize(); PositionGridCellsView(); }
/** * Try to unsnap a node to an anchor if the distance to it is big enough ( > m_snapDistance) * **/ void TryToUnsnap() { Vector2 mouseWorldPosition = CoordinatesUtils.SharedInstance.GetMousePositionInWorldCoordinates(); float fDistanceFromMouseToAnchor = (mouseWorldPosition - m_snappedAnchor.m_position).magnitude; if (fDistanceFromMouseToAnchor > m_snapDistance) { this.transform.position = mouseWorldPosition; //reset the zvalue float nodeZValue = this.GetComponent <NodeProperties>().GetZValue(); transform.position = new Vector3(transform.position.x, transform.position.y, nodeZValue); m_snappedAnchor = null; } }
/** * Anchors are points where nodes can be attached to. * They are obtained calculating the intersections between pending bridges **/ void ObtainAnchors() { m_anchors = new List <GridAnchor>(); GameObject[] allBridges = GameObject.FindGameObjectsWithTag("Bridge"); for (int fadedBridgeIndex1 = 0; fadedBridgeIndex1 != allBridges.Length; fadedBridgeIndex1++) { GameObject bridgeObject1 = allBridges[fadedBridgeIndex1]; Bridge bridge1 = bridgeObject1.GetComponent <Bridge>(); for (int bridgeIndex2 = fadedBridgeIndex1 + 1; bridgeIndex2 != allBridges.Length; bridgeIndex2++) { GameObject bridgeObject2 = allBridges[bridgeIndex2]; Bridge bridge2 = bridgeObject2.GetComponent <Bridge>(); bool bIntersect; Vector2 intersection; MathUtils.TwoSegmentsIntersection(bridge1.m_startPoint, bridge1.m_endPoint, bridge2.m_startPoint, bridge2.m_endPoint, out bIntersect, out intersection); if (bIntersect) { int anchorExistsIndex = AnchorExists(intersection); GridAnchor anchor; if (anchorExistsIndex >= 0) { anchor = m_anchors[anchorExistsIndex]; } else { anchor = new GridAnchor(intersection); m_anchors.Add(anchor); } anchor.PushBridge(bridge1); anchor.PushBridge(bridge2); bridge1.PushAnchor(anchor); bridge2.PushAnchor(anchor); } } } }
/* * Find the target Anchor where the pointer is heading for when trying to move one of his nodes * **/ private void FindTargetAnchor() { Vector2 attachedAnchorToMouseDirection = CoordinatesUtils.SharedInstance.GetMousePositionInWorldCoordinates() - m_attachedAnchor.m_position; List <GridAnchor> neighbouringAnchors = m_attachedAnchor.m_neighbouringAnchors; //find the direction where to drag the node based on the value of the dot product of mouseToAttachedAnchor direction and direction form the attached anchor ta neighbouring anchor //the max value of this product (i.e smallest angle between vectors) determines the anchor we have to head for float maxDotProduct = float.MinValue; foreach (GridAnchor neighbouringAnchor in neighbouringAnchors) { Vector2 attachedAnchorToNeighbouringAnchorDirection = neighbouringAnchor.m_position - m_attachedAnchor.m_position; attachedAnchorToNeighbouringAnchorDirection.Normalize(); float dotProduct = Vector2.Dot(attachedAnchorToNeighbouringAnchorDirection, attachedAnchorToMouseDirection); if (dotProduct > maxDotProduct) { maxDotProduct = dotProduct; m_targetAnchor = neighbouringAnchor; } } }
private GridAnchor m_spreadAnchor; //the anchor where the spread begins /** * Create solid bridges that will scale and cover all faded bridges around this anchor * **/ public void SpreadAroundAnchorPoint(GridAnchor anchor) { Vector3 spreadBridgePosition = anchor.m_position; spreadBridgePosition.z = -150.0f; GameObject clonedObject = (GameObject)Instantiate(m_bridgePrefab, spreadBridgePosition, this.transform.rotation); Transform transform = clonedObject.GetComponent <Transform>(); transform.localScale = new Vector3(0.0f, transform.localScale.y, transform.localScale.z); m_spreadBridge = clonedObject.GetComponent <Bridge>(); m_spreadBridge.m_type = Bridge.BridgeType.Spreading; m_spreadBridge.m_startPoint = anchor.m_position; m_spreadBridge.m_endPoint = anchor.m_position; m_spreadBridge.PushAnchor(anchor); BridgeSpread bridgeSpreadComponent = clonedObject.GetComponent <BridgeSpread>(); bridgeSpreadComponent.m_spreadAnchor = anchor; bridgeSpreadComponent.m_coveredBridge = this.gameObject.GetComponent <Bridge>(); anchor.m_linked = true; }
public View() { var bkgdBrush = new ImageBrush(Common.ElectricRed); var horzEnumValues = Enum.GetValues(typeof(HorizontalAlignment)); var vertEnumValues = Enum.GetValues(typeof(VerticalAlignment)); Common.PrepareDemoGrid(this, horzEnumValues.Length, vertEnumValues.Length, SolidColorBrushes.Blue.Brush, bkgdBrush); var padding = new Thickness(new Length(5.0, Unit.Px)); int col = 0, row = 0; foreach (HorizontalAlignment horz in horzEnumValues) { foreach (VerticalAlignment vert in vertEnumValues) { var anchor = new GridAnchor(col, row); var e_textBlock = new TextBlock() { Text = $"{horz}, {vert}", Foreground = SolidColorBrushes.White.Brush, Background = SolidColorBrushes.DarkMagenta.Brush, Padding = padding, HorizontalAlignment = horz, VerticalAlignment = vert }; this.Children.Add(e_textBlock, anchor); ++row; } row = 0; ++col; } }
/** * Retrieve closest anchors to parameter anchor on this bridge (at most 2 anchors) * **/ public List <GridAnchor> GetNeighbouringAnchors(GridAnchor anchor) { List <GridAnchor> neighbouringAnchors = new List <GridAnchor>(); neighbouringAnchors.Capacity = 2; //at most 2 neighbouring anchors //find the closest linked anchor on segment [anchor.Position; m_startPoint] GridAnchor neighbouringLinkedAnchor = FindClosestAnchorOnSegment(anchor, m_startPoint); if (neighbouringLinkedAnchor != null) { neighbouringAnchors.Add(neighbouringLinkedAnchor); } //do the same for the segment [anchor.Position; m_endPoint] neighbouringLinkedAnchor = FindClosestAnchorOnSegment(anchor, m_endPoint); if (neighbouringLinkedAnchor != null) { neighbouringAnchors.Add(neighbouringLinkedAnchor); } return(neighbouringAnchors); }
/** * Returns the closest anchor on segment [anchor.Position; segmentEndPoint] or null if no one was found * **/ private GridAnchor FindClosestAnchorOnSegment(GridAnchor anchor, Vector2 segmentEndPoint) { GridAnchor minDistanceAnchor = null; float minDistance = int.MaxValue; foreach (GridAnchor segmentAnchor in m_anchors) { if (segmentAnchor.Equals(anchor)) { continue; } if (MathUtils.isLinePointContainedInSegment(segmentAnchor.m_position, anchor.m_position, segmentEndPoint)) { float sqrDistanceToAnchor = (segmentAnchor.m_position - anchor.m_position).sqrMagnitude; if (sqrDistanceToAnchor < minDistance) { minDistanceAnchor = segmentAnchor; minDistance = sqrDistanceToAnchor; } } } return(minDistanceAnchor); }
protected override bool OnPointerMove(Vector2 pointerLocation, ref Vector2 delta) { if (!base.OnPointerMove(pointerLocation, ref delta)) { return(false); } NodeProperties nodeBehaviour = this.GetComponent <NodeProperties>(); NodeMovement nodeMovement = this.GetComponent <NodeMovement>(); if (nodeBehaviour.m_nodeType == NodeProperties.NodeType.Simple) //SIMPLE NODES { if (m_attachedAnchor == null) //node can move freely (i.e it has been dragged from GUI item list) { SnapToClosestAnchor(); if (m_snappedAnchor != null) { TryToUnsnap(); } else { Vector3 deltaVec3 = delta; this.transform.position += deltaVec3; } } else { if (nodeMovement.m_movementPoints > 0 && m_targetIndicatorNode == null) { //instantiate a special node that will serve as a indicator that can snap on neighbouring reachable anchors Vector3 targetIndicatorPosition = transform.position; targetIndicatorPosition.z = NodeProperties.TARGET_ANCHOR_NODE_Z_VALUE; m_targetIndicatorNode = (GameObject)Instantiate(m_targetIndicatorNodePrefab, targetIndicatorPosition, Quaternion.identity); m_targetIndicatorNode.GetComponent <NodeProperties>().m_nodeType = NodeProperties.NodeType.TargetIndicator; m_targetIndicatorNode.GetComponent <NodeTouchHandler>().m_attachedAnchor = this.m_attachedAnchor; m_targetIndicatorNode.GetComponent <NodeTouchHandler>().m_parentNode = this.gameObject; GameObject targetIndicatorBridge = (GameObject)Instantiate(m_targetIndicatorBridgePrefab); targetIndicatorBridge.GetComponent <Bridge>().m_type = Bridge.BridgeType.TargetIndicator; targetIndicatorBridge.GetComponent <Bridge>().m_startPoint = targetIndicatorPosition; targetIndicatorBridge.GetComponent <Bridge>().m_endPoint = targetIndicatorPosition; this.m_targetIndicatorBridge = targetIndicatorBridge; } } } else if (nodeBehaviour.m_nodeType == NodeProperties.NodeType.TargetIndicator) { FindTargetAnchor(); Vector2 attachedAnchorToMouseDirection = CoordinatesUtils.SharedInstance.GetMousePositionInWorldCoordinates() - m_attachedAnchor.m_position; Vector2 attachedAnchorToTargetAnchorDirection = m_targetAnchor.m_position - m_attachedAnchor.m_position; float fDistanceToTargetAnchor = attachedAnchorToTargetAnchorDirection.magnitude; attachedAnchorToTargetAnchorDirection.Normalize(); //Project the first vector on the second one float fProjectionLength = Vector2.Dot(attachedAnchorToMouseDirection, attachedAnchorToTargetAnchorDirection); if (fProjectionLength <= fDistanceToTargetAnchor) { bool bMoveTargetIndicator = false; if (m_snappedAnchor != null) { TryToUnsnap(); if (m_snappedAnchor == null) //unsnap succeeded { bMoveTargetIndicator = true; } } else { Vector3 oldPosition = transform.position; if (SnapToClosestAnchor()) { if (m_snappedAnchor == m_targetAnchor) { fProjectionLength = fDistanceToTargetAnchor; } else if (m_snappedAnchor == m_attachedAnchor) //remove the SnapToClosestAnchor effect by resetting the previous position and m_snappedAnchor to null { transform.position = oldPosition; m_snappedAnchor = null; } } bMoveTargetIndicator = true; } if (bMoveTargetIndicator) { //set the new position of target indicator node float targetIndicatorNodeZValue = transform.position.z; transform.position = m_attachedAnchor.m_position + attachedAnchorToTargetAnchorDirection * fProjectionLength; transform.position = new Vector3(transform.position.x, transform.position.y, targetIndicatorNodeZValue); //update the endpoint of the target indicator bridge m_parentNode.GetComponent <NodeTouchHandler>().m_targetIndicatorBridge.GetComponent <Bridge>().m_endPoint = transform.position; } } } return(true); }