public void Update(FiniteStateMachine stateMachine)
		{

            //the old distance between the p2-p3 node
            TrackNodeCurve curve =  stateData.Selected.GetComponent<ExtrudeNode> ().trackSegmentModify.GetLastCurve;
            Vector3 direction = curve.P2.GetGlobal () - curve.P3.GetGlobal ();

            TrackSegment4 trackSegment = UnityEngine.Object.Instantiate<TrackSegment4>( ScriptableSingleton<AssetManager>.Instance.getPrefab<TrackSegment4>(Prefabs.Straight));

            trackSegment.isLifthill = TrackUIHandle.instance.trackBuilder.liftToggle.isOn;
           /* if (TrackUIHandle.instance.trackEditUI.chainToggle.isOn) {
                trackSegment.isLifthill = true;
            }*/

            TrackUIHandle.instance.trackRide.Track.addSegment (trackSegment, stateData.Selected.GetComponent<ExtrudeNode> ().trackSegmentModify.GetIndexOfSegment ()+1);
			trackSegment.Initialize ();


            var modify = trackSegment.gameObject.AddComponent<TrackSegmentModify> ();
            stateData.Selected.GetComponent<ExtrudeNode> ().trackSegmentModify.ConnectWithForwardSegment(modify);


            //_stateData.Selected.GetComponent<ExtrudeNode>().TrackSegmentModify.GetLastCurve.P3

            modify.CalculateStartBinormal (true);
                
            stateData.Selected = modify.GetLastCurve.P3.gameObject.transform;

            //re-apply p2-p3 because that is lost when the segments are merged
            TrackNodeHelper.CalculateMatch (curve.P2, curve.P3.GetGlobal() + direction);

            stateMachine.ChangeState(new FreeDragWithSmoothing(stateData));

			//stateMachine.ChangeState (new IdleState (_stateData));
		}
        public void Update (FiniteStateMachine stateMachine)
        {
            var ray = Camera.main.ScreenPointToRay (Input.mousePosition);

            RotationNode rotationNode = stateData.Selected.GetComponent<RotationNode>();

            Vector3 planeNormal = rotationNode.AttachedNode.trackSegmentModify.TrackSegment.getTangentPoint (1.0f);
            Vector3 planeCenter = rotationNode.transform.position;

            float l = planeNormal.x * ray.origin.x + planeNormal.y * ray.origin.y + planeNormal.z * ray.origin.z;
            float r = planeNormal.x * planeCenter.x + planeNormal.y * planeCenter.y + planeCenter.z * planeNormal.z;

            float t = (-l + r) / (planeNormal.x * ray.direction.x + planeNormal.y * ray.direction.y + planeNormal.z * ray.direction.z);

            Vector3 loc = ray.origin + ray.direction * t;
            float diff = MathHelper.AngleSigned(rotationNode.AttachedNode.trackSegmentModify.TrackSegment.getNormal (1.0f),Vector3.Normalize (planeCenter- loc),planeNormal);

            rotationNode.AttachedNode.trackSegmentModify.CalculateWithNewTotalRotation ( Mathf.Round(diff + rotationNode.AttachedNode.trackSegmentModify.TrackSegment.totalRotation));
            rotationNode.AttachedNode.trackSegmentModify.invalidate = true;

            TrackSegmentModify nextSegment = rotationNode.AttachedNode.trackSegmentModify.GetNextSegment (true);

            if(nextSegment != null)
                nextSegment.invalidate = true;
       
            if (Input.GetMouseButtonUp (0)) {
                stateMachine.ChangeState(new IdleState (stateData));
            }
        }
        public override void Update (FiniteStateMachine stateMachine)
        {
            TrackNode trackNode = stateData.Selected.gameObject.GetComponent<TrackNode> ();
            base.Update (stateMachine);

            //calculate the match for the node segment
            TrackNodeHelper.CalculateMatch (trackNode, dragPosition);
            TrackNodeCurve previousCurve = trackNode.trackSegmentModify.getPreviousCurve (trackNode.trackCurve);

            float dist = Vector3.Distance (previousCurve.P3.GetGlobal (), trackNode.trackCurve.P3.GetGlobal ());
            Vector3 dir  = (trackNode.trackCurve.P3.GetGlobal () - previousCurve.P3.GetGlobal ()).normalized;

            TrackNodeHelper.CalculateMatch (trackNode.trackCurve.P1,trackNode.trackCurve.P0.GetGlobal() +  (dist/2.0f) * (trackNode.trackCurve.P1.GetGlobal() - trackNode.trackCurve.P0.GetGlobal()).normalized);


           
            Vector3 p0 = trackNode.trackCurve.P1.GetGlobal() - trackNode.trackCurve.P0.GetGlobal();
           
            Vector3 normal = Vector3.Cross (dir, p0).normalized;
            Vector3 p1final = - (Quaternion.AngleAxis (Vector3.Angle(-dir, p0),normal) * -dir).normalized;

            TrackNodeHelper.CalculateMatch (trackNode.trackCurve.P2,trackNode.trackCurve.P3.GetGlobal() +  (dist/2.0f) * p1final);

            var nextSegment = trackNode.trackSegmentModify.GetNextSegment (false);
            if (!stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.TrackSegment.isConnectedToNextSegment) {


                if (stateData.Selected.gameObject.GetComponent<TrackNode> ().nodePoint == TrackNode.NodeType.P3 && (dragPosition - nextSegment.GetFirstCurve.P0.GetGlobal ()).sqrMagnitude < .2f) {

                    float magnitude = Mathf.Abs ((nextSegment.GetFirstCurve.P0.GetGlobal () - nextSegment.GetFirstCurve.P1.GetGlobal ()).magnitude);


                    stateData.Selected.gameObject.GetComponent<TrackNode> ().SetPoint (nextSegment.GetFirstCurve.P0.GetGlobal ());
                    stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.GetLastCurve.P2.SetPoint (stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.GetLastCurve.P3.GetGlobal () + (nextSegment.TrackSegment.getTangentPoint (0f) * -1f * magnitude));
                    stateData.Selected.gameObject.GetComponent<TrackNode> ().CalculateLenghtAndNormals ();
                    stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.GetFirstCurve.P0.trackSegmentModify.CalculateStartBinormal (false);
                    stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.GetLastCurve.ClearExtrudeNode ();


                    nextSegment.GetFirstCurve.P0.CalculateLenghtAndNormals ();
                    if (Input.GetMouseButtonUp (0)) {
                        stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.ConnectWithForwardSegment (nextSegment);
                        stateMachine.ChangeState (new IdleState (stateData));
                    }
                    nextSegment.invalidate = true;

                    stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.invalidate = true;

                }
            }

            if (Input.GetMouseButtonUp (0)) {
                stateMachine.ChangeState(new IdleState (stateData));
            }

        }
        public void Update(FiniteStateMachine stateMachine)
        {


            var ray = Camera.main.ScreenPointToRay (Input.mousePosition);

			if (Input.GetMouseButtonDown (1)) {
				RaycastHit hit;
				if (Physics.Raycast (ray, out hit, Mathf.Infinity, LayerMasks.COASTER_TRACKS)) {
					if (hit.transform.name == "BezierNode") {
						stateData.SetActiveNode(hit.transform);
					}
				}
			}

            if (Input.GetMouseButtonDown (0)) {
                RaycastHit hit;

				if (Physics.Raycast (ray, out hit, Mathf.Infinity,LayerMasks.COASTER_TRACKS)) {
					stateData.Selected = hit.transform;
					stateData.FixedY = hit.transform.position.y;
					stateData.Offset = new Vector3(hit.transform.position.x - hit.point.x, 0, hit.transform.position.z - hit.point.z);

					stateData.Distance = (ray.origin - hit.point).magnitude;

                    if (hit.transform.name == "BezierNode") {
                        stateData.SetActiveNode (hit.transform);

                        TrackNode node = hit.transform.GetComponent<TrackNode> ();

                        var nextSegment = node.trackSegmentModify.GetNextSegment (true);
                        var previousSegment = node.trackSegmentModify.GetPreviousSegment (true);

                        if (node.nodePoint == TrackNode.NodeType.P1 && previousSegment != null && previousSegment.TrackSegment is Station) {
                            stateMachine.ChangeState (new LinearDragState (stateData));
                        } else if (node.nodePoint == TrackNode.NodeType.P2 && nextSegment != null && nextSegment.TrackSegment is Station) {
                            stateMachine.ChangeState (new LinearDragState (stateData));
                        } else {
                            stateMachine.ChangeState (new FreeDragState (stateData));
                        }
                    } else if (hit.transform.name == "ExtrudeNode") {
                        stateMachine.ChangeState (new ConsumeExtrudeNodeState (stateData));
                    } else if (hit.transform.name == "Rotate") {
                        stateMachine.ChangeState (new RotationState (stateData));
                    }
                }
              
            }
        }
        public override void Update(FiniteStateMachine stateMachine)
        {

            base.Update (stateMachine);

            TrackNode trackNode = stateData.Selected.gameObject.GetComponent<TrackNode> ();


            //calculate the match for the node segment
            TrackNodeHelper.CalculateMatch (trackNode, dragPosition);

            
			var nextSegment = trackNode.trackSegmentModify.GetNextSegment (false);
			if (!stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.TrackSegment.isConnectedToNextSegment) {
			
			
                if (stateData.Selected.gameObject.GetComponent<TrackNode> ().nodePoint == TrackNode.NodeType.P3 && (dragPosition - nextSegment.GetFirstCurve.P0.GetGlobal ()).sqrMagnitude < .2f) {
					
					float magnitude = Mathf.Abs ((nextSegment.GetFirstCurve.P0.GetGlobal () - nextSegment.GetFirstCurve.P1.GetGlobal ()).magnitude);


					stateData.Selected.gameObject.GetComponent<TrackNode> ().SetPoint (nextSegment.GetFirstCurve.P0.GetGlobal ());
					stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.GetLastCurve.P2.SetPoint (stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.GetLastCurve.P3.GetGlobal () + (nextSegment.TrackSegment.getTangentPoint (0f) * -1f * magnitude));
					stateData.Selected.gameObject.GetComponent<TrackNode> ().CalculateLenghtAndNormals ();
					stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.GetFirstCurve.P0.trackSegmentModify.CalculateStartBinormal (false);
					stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.GetLastCurve.ClearExtrudeNode ();


                    nextSegment.GetFirstCurve.P0.CalculateLenghtAndNormals ();
					if (Input.GetMouseButtonUp (0)) {
                        stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.ConnectWithForwardSegment (nextSegment);
                        stateMachine.ChangeState (new IdleState (stateData));
					}
					nextSegment.invalidate = true;

					stateData.Selected.gameObject.GetComponent<TrackNode> ().trackSegmentModify.invalidate = true;

				}
			}

            if (Input.GetMouseButtonUp (0)) {
				stateMachine.ChangeState(new IdleState (stateData));
            }
        }
		public void Update(FiniteStateMachine stateMachine)
		{
			
		}
		public void Update(FiniteStateMachine stateMachine)
		{
			var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
			Vector3 point = ray.GetPoint (stateData.Distance);
			Vector3 position = Vector3.zero;

			position = new Vector3 (point.x, stateData.FixedY, point.z) + new Vector3(stateData.Offset.x, stateData.Offset.y, stateData.Offset.z);


			TrackNode trackNode = stateData.Selected.gameObject.GetComponent<TrackNode> ();
			var nextSegment = trackNode.trackSegmentModify.GetNextSegment (true);
			var previousSegment = trackNode.trackSegmentModify.GetPreviousSegment (true);

			switch (trackNode.nodePoint) {

			case TrackNode.NodeType.P1:
				
				{

					trackNode.CalculateLenghtAndNormals ();


					float magnitude = Mathf.Abs((position - previousSegment.GetLastCurve.P3.GetGlobal ()).magnitude);
					trackNode.SetPoint (previousSegment.GetLastCurve.P3.GetGlobal() + (previousSegment.TrackSegment.getTangentPoint(1f) * magnitude));

					previousSegment.invalidate = true;
					trackNode.CalculateLenghtAndNormals ();

					trackNode.trackSegmentModify.CalculateStartBinormal (true);
					//TrackSegmentModify.TrackSegment.upgradeSavegameRecalculateBinormal (previousSegment.TrackSegment);


				}


				break;
			case TrackNode.NodeType.P2:


				trackNode.CalculateLenghtAndNormals ();

				{

					float magnitude = Mathf.Abs ((nextSegment.GetFirstCurve.P0.GetGlobal () - position).magnitude);

					trackNode.SetPoint (nextSegment.GetFirstCurve.P0.GetGlobal () + (nextSegment.TrackSegment.getTangentPoint (0.0f) * -1.0f * magnitude));

					nextSegment.invalidate = true;
					trackNode.CalculateLenghtAndNormals ();

					nextSegment.CalculateStartBinormal (true);
				}

				break;
			}

            trackNode.CalculateLenghtAndNormals ();
			trackNode.trackSegmentModify.invalidate = true;


			if (Input.GetMouseButtonUp (0)) {
				stateMachine.ChangeState(new IdleState (stateData));
			}
		}
        public virtual void Update (FiniteStateMachine stateMachine)
        {
            var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
            Vector3 point = ray.GetPoint (stateData.Distance);
            Vector3 position = Vector3.zero;
            if (!verticalDragState) {
                position = new Vector3 (point.x, stateData.FixedY, point.z) + new Vector3(stateData.Offset.x, stateData.Offset.y, stateData.Offset.z);

            } else
            {
                stateData.FixedY = point.y;
                position = new Vector3 (stateData.Selected.position.x, stateData.FixedY, stateData.Selected.position.z) + new Vector3(0, stateData.Offset.y, 0);
            }

            if (Input.GetKeyDown (Main.configuration.settings.verticalKey)) {
                stateData.Offset = new Vector3(stateData.Offset.x,stateData.Selected.transform.position.y - point.y, stateData.Offset.z);
                verticalDragState = true;

            } else if (Input.GetKeyUp (Main.configuration.settings.verticalKey)) {
                verticalDragState = false;
                stateData.Offset = (stateData.Selected.transform.position - point);

            }

                if (InputManager.getKey("BuildingSnapToGrid"))
                {
                    if (Input.GetKeyDown(KeyCode.Alpha0))
                    {
                        this.gridSubdivision = 1;
                        GameController.Instance.terrainGridBuilderProjector.setGridSubdivision(this.gridSubdivision);
                    }
                    for (int i = 1; i <= 9; i++)
                    {
                        if (Input.GetKeyDown(i + string.Empty))
                        {
                            this.gridSubdivision = (float)i;
                            GameController.Instance.terrainGridBuilderProjector.setGridSubdivision(this.gridSubdivision);
                        }
                    }
                }

            if (InputManager.getKeyDown ("BuildingSnapToGrid")) {
                isGridActive = true;
                GameController.Instance.terrainGridProjector.setHighIntensityEnabled (true);
                GameController.Instance.terrainGridBuilderProjector.setHighIntensityEnabled (true);
                GameController.Instance.terrainGridBuilderProjector.setGridSubdivision (this.gridSubdivision);
              
            } else if (InputManager.getKeyUp ("BuildingSnapToGrid")) {
                this.resetToDefaultGrid ();
                isGridActive = false;
            } 

            dragPosition = new Vector3 (Mathf.Round (position.x * 10.0f) /  10.0f, Mathf.Round (position.y *  10.0f) / 10.0f, Mathf.Round (position.z * 10.0f) /  10.0f);
            if (isGridActive) {
                dragPosition = new Vector3 (Mathf.Round (position.x * gridSubdivision) / gridSubdivision, Mathf.Round (position.y * gridSubdivision) / gridSubdivision, Mathf.Round (position.z * gridSubdivision) / gridSubdivision);

            }
            TrackUIHandle.instance.trackBuilder.generateNewGhost ();
                

        }