void Start () {

		// Cache camera
		mainCamera = Camera.main;

		// Parent the particle system to the main camera
		particles.particleSystemTransform.parent = mainCamera.transform;
		particles.shurikenParticleSystem.simulationSpace = ParticleSystemSimulationSpace.Local;

		// Create a new spline and set it up
		spline = new GameObject("Viewport Spline", typeof(PlaygroundSpline)).GetComponent<PlaygroundSpline>();
		spline.Loop = true;
		spline.Reset ();
		spline.SetControlPointMode(0, BezierControlPointMode.Free);
		spline.SetControlPointMode(1, BezierControlPointMode.Free);

		// Add three additional nodes (a basic spline will contain two initial nodes)
		spline.AddNode();
		spline.AddNode();
		spline.AddNode();

		// Set the nodes to match the viewport
		currentScreenX = Screen.width;
		currentScreenY = Screen.height;
		SetViewportNodes();

		// Assign the spline to the particle system
		particles.splines.Add (spline);

		// Make sure we're using the spline as source
		particles.source = SOURCEC.Spline;

		prevScreenOffset = screenOffset;
	}
	void OnEnable () {
		spline = target as PlaygroundSpline;
		
		playgroundSettings = PlaygroundSettingsC.GetReference();
		playgroundLanguage = PlaygroundSettingsC.GetLanguage();
		
		lastActiveTool = UnityEditor.Tools.current;
		
		UpdateUserList();
	}
		void OnEnable () 
		{
			if (noiseDistributionL == null || noiseDistributionL.keys.Length==0)
				SetAnimationCurveVals(ref noiseDistributionL);
			if (noiseDistributionR == null || noiseDistributionR.keys.Length==0)
				SetAnimationCurveVals(ref noiseDistributionR);
			if (GetComponent<Renderer>() == null)
				gameObject.AddComponent<MeshRenderer>();
			if (spline == null)
				spline = GetComponent<PlaygroundSpline>();
			if (spline != null)
				BuildSplineMesh(spline, points, width);
			SetVals();
		}
 void OnEnable()
 {
     if (noiseDistributionL == null || noiseDistributionL.keys.Length == 0)
     {
         SetAnimationCurveVals(ref noiseDistributionL);
     }
     if (noiseDistributionR == null || noiseDistributionR.keys.Length == 0)
     {
         SetAnimationCurveVals(ref noiseDistributionR);
     }
     if (GetComponent <Renderer>() == null)
     {
         gameObject.AddComponent <MeshRenderer>();
     }
     if (spline == null)
     {
         spline = GetComponent <PlaygroundSpline>();
     }
     if (spline != null)
     {
         BuildSplineMesh(spline, points, width);
     }
     SetVals();
 }
		public void BuildSplineMesh (PlaygroundSpline spline, int points, float width) 
		{
			if (points<2)
				points = 2;
			int totalVertices = points*2;
			MeshFilter _mf = GetComponent<MeshFilter>()!=null? GetComponent<MeshFilter>() : gameObject.AddComponent<MeshFilter>();
			Mesh _m = new Mesh();
			Vector3[] verts = new Vector3[totalVertices];
			Vector2[] uvs = new Vector2[totalVertices];
			int[] tris = new int[(points-1)*6];

			Vector3 up = meshUpDirection;

			// Construct the mesh
			for (int i = 0; i<points; i++)
			{
				// Create a normalized time value
				float t = (i*1f)/(points-1);
				float tNext = ((i*1f)+1)/(points-1);
				if (t>=1 && !spline.Loop)
					t = .9999f;
				if (tNext>=1 && !spline.Loop)
					tNext = .99999f;

				// Get the current and next position from the spline on time
				Vector3 currentPosition = spline.GetPoint (t);
				Vector3 nextPosition = spline.GetPoint (tNext);

				// Raycast down to determine surface (especially practical for roads / rivers)
				if (followSurface || followSurfaceRotation)
				{
					RaycastHit hit;
					if (Physics.Raycast (currentPosition, surfaceDirection, out hit))
					{
						if (followSurfaceRotation)
							up = hit.normal;
						if (followSurface)
							currentPosition = hit.point + (hit.normal * surfaceOffset);
					}
					if (followSurface)
					{
						if (Physics.Raycast (nextPosition, surfaceDirection, out hit))
						{
							nextPosition = hit.point + (hit.normal * surfaceOffset);
						}
					}
				}

				// Calculate noise (if enabled)
				float noiseAmountL = noise? Mathf.PerlinNoise((t%1f)*noiseScale.x, 0)*noiseStrength : 0;
				float noiseAmountR = noise? Mathf.PerlinNoise((t%1f)*noiseScale.y, 0)*noiseStrength : 0;

				if (noise && noiseDistribution)
				{
					noiseAmountL *= noiseDistributionL.Evaluate(t);
					noiseAmountR *= noiseDistributionR.Evaluate(t);
				}

				// Create two width point references based on current and next position
				Vector3 dir = (Vector3.Cross(up, nextPosition - currentPosition)).normalized;
				Vector3 lPoint = currentPosition + dir * ((width/2)+noiseAmountL);
				Vector3 rPoint = currentPosition - dir * ((width/2)+noiseAmountR);

				// Draw debug
				Debug.DrawLine(lPoint, rPoint);

				verts[i*2] = lPoint;
				verts[(i*2)+1] = rPoint;
				uvs[i*2] = new Vector2(t,0);
				uvs[(i*2)+1] = new Vector2(t,1f);

				if (i>0)
				{
					int triIndex = (i-1)*6;
					int vertIndex = i*2;

					tris[triIndex] = vertIndex-2;
					tris[triIndex+1] = vertIndex-1;
					tris[triIndex+2] = vertIndex;
					tris[triIndex+3] = vertIndex;
					tris[triIndex+4] = vertIndex-1;
					tris[triIndex+5] = vertIndex+1;
				}
			}

			// Assign the data to the mesh
			_m.vertices = verts;
			_m.uv = uvs;
			_m.triangles = tris;
			_m.RecalculateNormals();

			// Assign the mesh to the MeshFilter
			_mf.mesh = _m;
		}
        public void BuildSplineMesh(PlaygroundSpline spline, int points, float width)
        {
            if (points < 2)
            {
                points = 2;
            }
            int        totalVertices = points * 2;
            MeshFilter _mf           = GetComponent <MeshFilter>() != null?GetComponent <MeshFilter>() : gameObject.AddComponent <MeshFilter>();

            Mesh _m = new Mesh();

            Vector3[] verts = new Vector3[totalVertices];
            Vector2[] uvs   = new Vector2[totalVertices];
            int[]     tris  = new int[(points - 1) * 6];

            Vector3 up = meshUpDirection;

            // Construct the mesh
            for (int i = 0; i < points; i++)
            {
                // Create a normalized time value
                float t     = (i * 1f) / (points - 1);
                float tNext = ((i * 1f) + 1) / (points - 1);
                if (t >= 1 && !spline.Loop)
                {
                    t = .9999f;
                }
                if (tNext >= 1 && !spline.Loop)
                {
                    tNext = .99999f;
                }

                // Get the current and next position from the spline on time
                Vector3 currentPosition = spline.GetPoint(t);
                Vector3 nextPosition    = spline.GetPoint(tNext);

                // Raycast down to determine surface (especially practical for roads / rivers)
                if (followSurface || followSurfaceRotation)
                {
                    RaycastHit hit;
                    if (Physics.Raycast(currentPosition, surfaceDirection, out hit))
                    {
                        if (followSurfaceRotation)
                        {
                            up = hit.normal;
                        }
                        if (followSurface)
                        {
                            currentPosition = hit.point + (hit.normal * surfaceOffset);
                        }
                    }
                    if (followSurface)
                    {
                        if (Physics.Raycast(nextPosition, surfaceDirection, out hit))
                        {
                            nextPosition = hit.point + (hit.normal * surfaceOffset);
                        }
                    }
                }

                // Calculate noise (if enabled)
                float noiseAmountL = noise? Mathf.PerlinNoise((t % 1f) * noiseScale.x, 0) * noiseStrength : 0;
                float noiseAmountR = noise? Mathf.PerlinNoise((t % 1f) * noiseScale.y, 0) * noiseStrength : 0;

                if (noise && noiseDistribution)
                {
                    noiseAmountL *= noiseDistributionL.Evaluate(t);
                    noiseAmountR *= noiseDistributionR.Evaluate(t);
                }

                // Create two width point references based on current and next position
                Vector3 dir    = (Vector3.Cross(up, nextPosition - currentPosition)).normalized;
                Vector3 lPoint = currentPosition + dir * ((width / 2) + noiseAmountL);
                Vector3 rPoint = currentPosition - dir * ((width / 2) + noiseAmountR);

                // Draw debug
                Debug.DrawLine(lPoint, rPoint);

                verts[i * 2]       = lPoint;
                verts[(i * 2) + 1] = rPoint;
                uvs[i * 2]         = new Vector2(t, 0);
                uvs[(i * 2) + 1]   = new Vector2(t, 1f);

                if (i > 0)
                {
                    int triIndex  = (i - 1) * 6;
                    int vertIndex = i * 2;

                    tris[triIndex]     = vertIndex - 2;
                    tris[triIndex + 1] = vertIndex - 1;
                    tris[triIndex + 2] = vertIndex;
                    tris[triIndex + 3] = vertIndex;
                    tris[triIndex + 4] = vertIndex - 1;
                    tris[triIndex + 5] = vertIndex + 1;
                }
            }

            // Assign the data to the mesh
            _m.vertices  = verts;
            _m.uv        = uvs;
            _m.triangles = tris;
            _m.RecalculateNormals();

            // Assign the mesh to the MeshFilter
            _mf.mesh = _m;
        }