SHARE
TWEET

UnityPaint converted to C#

meatbag Oct 28th, 2012 1,848 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class Uber : MonoBehaviour
  6. {
  7.  
  8. #region painter
  9. public Texture2D sourceBaseTex;
  10. private Texture2D baseTex;
  11.  
  12. void  Start ()
  13. {
  14.         baseTex = (Texture2D) Instantiate( sourceBaseTex );
  15. }
  16.  
  17.  
  18. private Vector2 dragStart;
  19. private Vector2 dragEnd;
  20. public enum Tool {
  21.         None,
  22.         Line,
  23.         Brush,
  24.         Eraser,
  25.         Vector
  26. }
  27. private int tool2 = 1;
  28. public Samples AntiAlias = Samples.Samples4;
  29. public Tool tool = Tool.Brush;
  30. public Texture[] toolimgs;
  31. public Texture2D colorCircle;
  32. public float lineWidth = 1;
  33. public float strokeWidth = 1;
  34. public Color col = Color.white;
  35. public Color col2 = Color.white;
  36. public GUISkin gskin;
  37. public LineTool lineTool = new LineTool();
  38. public BrushTool brush = new BrushTool();
  39. public EraserTool eraser = new EraserTool();
  40. public Stroke stroke = new Stroke();
  41. public int zoom = 1;
  42. BezierPoint[] BezierPoints;
  43. void  OnGUI (){
  44.         GUI.skin = gskin;
  45.        
  46.         GUILayout.BeginArea ( new Rect(5,5,100+baseTex.width*zoom,baseTex.height*zoom),"","Box");
  47.         GUILayout.BeginArea ( new Rect(0,0,100,baseTex.height*zoom));
  48.         tool2 = GUILayout.Toolbar(tool2,toolimgs,"Tool");
  49.  
  50. //      tool = System.Enum.Parse (Tool,tool2.ToString ());
  51.        
  52.         // FIXME: Defaults to brush tool, fix enum parse above.
  53.         tool = Tool.Brush;
  54.        
  55.        
  56.         GUILayout.Label ("Drawing Options");
  57.         GUILayout.Space (10);
  58.         switch (tool) {
  59.                 case Tool.Line:
  60.                         GUILayout.Label ("Size "+ Mathf.Round (lineTool.width*10)/10);
  61.                         lineTool.width = GUILayout.HorizontalSlider (lineTool.width,0,40);
  62.                         col = RGBCircle (col,"",colorCircle);
  63.                         break;
  64.                 case Tool.Brush:
  65.                         GUILayout.Label ("Size "+ Mathf.Round (brush.width*10)/10);
  66.                         brush.width = GUILayout.HorizontalSlider (brush.width,0,40);
  67.                         GUILayout.Label ("Hardness " + Mathf.Round (brush.hardness*10)/10);
  68.                         brush.hardness = GUILayout.HorizontalSlider (brush.hardness,0.1f,50);
  69.                         col = RGBCircle (col,"",colorCircle);
  70.                         break;
  71.                 case Tool.Eraser:
  72.                         GUILayout.Label ("Size "+ Mathf.Round (eraser.width*10)/10);
  73.                         eraser.width = GUILayout.HorizontalSlider (eraser.width,0,50);
  74.                         GUILayout.Label ("Hardness " + Mathf.Round (eraser.hardness*10)/10);
  75.                         eraser.hardness = GUILayout.HorizontalSlider (eraser.hardness,1,50);
  76.                         break;
  77.         }
  78.        
  79.         if (tool==Tool.Line) {
  80.                 stroke.enabled = GUILayout.Toggle (stroke.enabled,"Stroke");
  81.                 GUILayout.Label ("Stroke Width "+ Mathf.Round (stroke.width*10)/10);
  82.                 stroke.width = GUILayout.HorizontalSlider (stroke.width,0,lineWidth);
  83.                 GUILayout.Label ("Secondary Color");
  84.                 col2 = RGBCircle (col2,"",colorCircle);
  85.         }
  86.        
  87.         GUILayout.EndArea ();
  88.         GUI.DrawTexture ( new Rect(100,0,baseTex.width*zoom,baseTex.height*zoom),baseTex);
  89.         GUILayout.EndArea ();
  90. }
  91. private Vector2 preDrag;
  92. void  Update (){
  93.         Rect imgRect = new Rect(5+100,5,baseTex.width*zoom,baseTex.height*zoom);
  94.         Vector2 mouse = Input.mousePosition;
  95.         mouse.y = Screen.height-mouse.y;
  96.        
  97.         if (Input.GetKeyDown ("t")) {
  98.                 test ();
  99.         }
  100.         if (Input.GetKeyDown ("mouse 0")) {
  101.                
  102.                 if (imgRect.Contains (mouse)) {
  103.                         if (tool==Tool.Vector) {
  104.                                 var m2 = mouse-new Vector2(imgRect.x,imgRect.y);
  105.                                 m2.y = imgRect.height-m2.y;
  106.                                 var bz = new ArrayList (BezierPoints);
  107.                                 bz.Add (new BezierPoint (m2,m2-new Vector2(50,10),m2+new Vector2(50,10)));
  108.                                 BezierPoints = (BezierPoint[]) bz.ToArray();
  109.                                 DrawBezier (BezierPoints,lineTool.width,col,baseTex);
  110.                         }
  111.                        
  112.                         dragStart = mouse - new Vector2 (imgRect.x,imgRect.y);
  113.                         dragStart.y =imgRect.height-dragStart.y;
  114.                         dragStart.x = Mathf.Round (dragStart.x/zoom);
  115.                         dragStart.y = Mathf.Round (dragStart.y/zoom);
  116.                         //LineStart (mouse - Vector2 (imgRect.x,imgRect.y));
  117.                        
  118.                         dragEnd = mouse - new Vector2 (imgRect.x,imgRect.y);
  119.                         dragEnd.x = Mathf.Clamp (dragEnd.x,0,imgRect.width);
  120.                         dragEnd.y = imgRect.height-Mathf.Clamp (dragEnd.y,0,imgRect.height);
  121.                         dragEnd.x = Mathf.Round ( dragEnd.x/zoom);
  122.                         dragEnd.y = Mathf.Round ( dragEnd.y/zoom);
  123.                 } else {
  124.                         dragStart=Vector3.zero;
  125.                 }
  126.                
  127.         }
  128.         if (Input.GetKey ("mouse 0")) {
  129.                 if (dragStart==Vector2.zero) {
  130.                         return;
  131.                 }
  132.                 dragEnd = mouse - new Vector2 (imgRect.x,imgRect.y);
  133.                 dragEnd.x = Mathf.Clamp (dragEnd.x,0,imgRect.width);
  134.                 dragEnd.y = imgRect.height-Mathf.Clamp (dragEnd.y,0,imgRect.height);
  135.                 dragEnd.x = Mathf.Round ( dragEnd.x/zoom);
  136.                 dragEnd.y = Mathf.Round ( dragEnd.y/zoom);
  137.                
  138.                 if (tool==Tool.Brush) {
  139.                         Brush (dragEnd,preDrag);
  140.                 }
  141.                 if (tool==Tool.Eraser) {
  142.                         Eraser (dragEnd,preDrag);
  143.                 }
  144.                
  145.         }
  146.         if (Input.GetKeyUp ("mouse 0") && dragStart != Vector2.zero) {
  147.                 if (tool==Tool.Line) {
  148.                         dragEnd = mouse - new Vector2 (imgRect.x,imgRect.y);
  149.                         dragEnd.x = Mathf.Clamp (dragEnd.x,0,imgRect.width);
  150.                         dragEnd.y = imgRect.height-Mathf.Clamp (dragEnd.y,0,imgRect.height);
  151.                         dragEnd.x = Mathf.Round ( dragEnd.x/zoom);
  152.                         dragEnd.y = Mathf.Round ( dragEnd.y/zoom);
  153.                         Debug.Log ("Draw Line");
  154.                         NumSamples=AntiAlias;
  155.                         if (stroke.enabled) {
  156.                                 baseTex = DrawLine (dragStart,dragEnd,lineTool.width,col,baseTex,true,col2,stroke.width);
  157.                         } else {
  158.                                 baseTex = DrawLine (dragStart,dragEnd,lineTool.width,col,baseTex);
  159.                         }
  160.                 }
  161.                 dragStart=Vector2.zero;
  162.                 dragEnd=Vector2.zero;
  163.         }
  164.         preDrag = dragEnd;
  165. }
  166.  
  167. void  Brush ( Vector2 p1 ,  Vector2 p2  ){
  168.         NumSamples=AntiAlias;
  169.         if (p2 == Vector2.zero) {
  170.                 p2 = p1;
  171.         }
  172.         PaintLine (p1,p2,brush.width,col,brush.hardness,baseTex);
  173.         baseTex.Apply ();
  174. }
  175.  
  176. void  Eraser ( Vector2 p1 ,  Vector2 p2  ){
  177.         NumSamples=AntiAlias;
  178.         if (p2 == Vector2.zero) {
  179.                 p2 = p1;
  180.         }
  181.         PaintLine (p1,p2,eraser.width,Color.white,eraser.hardness,baseTex);
  182.         baseTex.Apply ();
  183. }
  184.  
  185. void  test (){
  186.         float startTime = Time.realtimeSinceStartup;
  187.         var w = 100;
  188.         var h = 100;
  189.         var p1 = new BezierPoint (new Vector2(10,0),new Vector2(5,20),new Vector2(20,0));
  190.         var p2 = new BezierPoint (new Vector2(50,10),new Vector2(40,20),new Vector2(60,-10));
  191.         var c = new BezierCurve (p1.main,p1.control2,p2.control1,p2.main);
  192.         p1.curve2=c;
  193.         p2.curve1=c;
  194.         Vector2 elapsedTime = new Vector2 ((Time.realtimeSinceStartup-startTime)*10,0);
  195.         float startTime2 = Time.realtimeSinceStartup;
  196.         for (var i=0;i<w*h;i++) {
  197.                 IsNearBezier (new Vector2(Random.value*80,Random.value*30),p1,p2,10);
  198.         }
  199.        
  200.         Vector2 elapsedTime2 = new Vector2 ((Time.realtimeSinceStartup-startTime2)*10,0);
  201.         Debug.Log ("Drawing took " + elapsedTime.ToString () + "  "+ elapsedTime2.ToString ());
  202.        
  203. }
  204.  
  205. public class LineTool {
  206.         public float width = 1;
  207. }
  208. public class EraserTool {
  209.         public float width = 1;
  210.         public float hardness = 1;
  211. }
  212. public class BrushTool {
  213.         public float width = 1;
  214.         public float hardness = 0;
  215.         public float spacing = 10;
  216. }
  217. public class Stroke {
  218.         public bool enabled= false;
  219.         public float width = 1;
  220. }
  221.  
  222. #endregion
  223.  
  224. #region gui controls
  225. static Color RGBSlider ( Color c ,  string label  )
  226. {
  227.         GUI.color=c;
  228.         GUILayout.Label (label);
  229.         GUI.color=Color.red;
  230.         c.r = GUILayout.HorizontalSlider (c.r,0,1);
  231.         GUI.color=Color.green;
  232.         c.g = GUILayout.HorizontalSlider (c.g,0,1);
  233.         GUI.color=Color.blue;
  234.         c.b = GUILayout.HorizontalSlider (c.b,0,1);
  235.         GUI.color=Color.white;
  236.         return c;
  237. }
  238.  
  239. static Color  RGBCircle ( Color c ,  string label ,  Texture2D colorCircle  ){
  240.         var r = GUILayoutUtility.GetAspectRect (1);
  241.         r.height = r.width -= 15;
  242.         var r2 = new Rect(r.x + r.width +5,r.y,10,r.height);
  243.         var hsb = new HSBColor (c);//It is much easier to work with HSB colours in this case
  244.        
  245.        
  246.         var cp = new Vector2 (r.x+r.width/2,r.y+r.height/2);
  247.        
  248.         if (Input.GetMouseButton (0)) {
  249.                 var InputVector= Vector2.zero;
  250.                 InputVector.x = cp.x - Event.current.mousePosition.x;
  251.                 InputVector.y = cp.y - Event.current.mousePosition.y;
  252.                
  253.                 var hyp = Mathf.Sqrt( (InputVector.x * InputVector.x) + (InputVector.y * InputVector.y) );
  254.                 if (hyp <= r.width/2 + 5) {
  255.                         hyp = Mathf.Clamp (hyp,0,r.width/2);
  256.                         float a = Vector3.Angle(new Vector3(-1,0,0), InputVector);
  257.                        
  258.                         if (InputVector.y<0) {
  259.                                 a = 360 - a;
  260.                         }
  261.                        
  262.                         hsb.h = a / 360;
  263.                         hsb.s = hyp / (r.width/2);
  264.                 }
  265.         }
  266.        
  267.         var hsb2 = new HSBColor (c);
  268.         hsb2.b = 1;
  269.         var c2 = hsb2.ToColor ();
  270.         GUI.color = c2;
  271.         hsb.b = GUI.VerticalSlider (r2,hsb.b,1.0f,0.0f,"BWSlider","verticalsliderthumb");
  272.        
  273.         GUI.color = Color.white * hsb.b;
  274.         GUI.color = new Color( GUI.color.r, GUI.color.g, GUI.color.b, 1);
  275.         GUI.Box (r,colorCircle,GUIStyle.none);
  276.        
  277.         var pos = (new Vector2 (Mathf.Cos (hsb.h*360*Mathf.Deg2Rad),-Mathf.Sin (hsb.h*360*Mathf.Deg2Rad))*r.width*hsb.s/2);
  278.        
  279.         GUI.color = c;
  280.         GUI.Box ( new Rect(pos.x-5+cp.x,pos.y-5+cp.y,10,10),"","ColorcirclePicker");
  281.         GUI.color = Color.white;
  282.        
  283.         c = hsb.ToColor ();
  284.         return c;
  285. }
  286. #endregion
  287.  
  288. #region drawing
  289.  
  290. public enum Samples {
  291.         None,
  292.         Samples2,
  293.         Samples4,
  294.         Samples8,
  295.         Samples16,
  296.         Samples32,
  297.         RotatedDisc
  298. }
  299.  
  300. static Samples NumSamples = Samples.Samples4;
  301.  
  302. static Texture2D  DrawLine ( Vector2 from ,  Vector2 to ,  float w ,  Color col ,  Texture2D tex  ){
  303.         return DrawLine (from,to,w,col,tex,false,Color.black,0);
  304. }
  305.  
  306. static Texture2D  DrawLine ( Vector2 from ,  Vector2 to ,  float w ,  Color col ,  Texture2D tex ,  bool stroke ,   Color strokeCol ,  float strokeWidth  ){
  307.         w = Mathf.Round (w);//It is important to round the numbers otherwise it will mess up with the texture width
  308.         strokeWidth = Mathf.Round (strokeWidth);
  309.        
  310.         var extent = w + strokeWidth;
  311.         var stY = Mathf.Clamp (Mathf.Min (from.y,to.y)-extent,0,tex.height);//This is the topmost Y value
  312.         var stX =  Mathf.Clamp (Mathf.Min (from.x,to.x)-extent,0,tex.width);
  313.         var endY = Mathf.Clamp (Mathf.Max (from.y,to.y)+extent,0,tex.height);
  314.         var endX = Mathf.Clamp (Mathf.Max (from.x,to.x)+extent,0,tex.width);//This is the rightmost Y value
  315.        
  316.         strokeWidth = strokeWidth/2;
  317.         var strokeInner = (w-strokeWidth)*(w-strokeWidth);
  318.         var strokeOuter = (w+strokeWidth)*(w+strokeWidth);
  319.         var strokeOuter2 = (w+strokeWidth+1)*(w+strokeWidth+1);
  320.         var sqrW = w*w;//It is much faster to calculate with squared values
  321.        
  322.         var lengthX = endX-stX;
  323.         var lengthY = endY-stY;
  324.         var start = new Vector2 (stX,stY);
  325.     Color[] pixels = tex.GetPixels((int)stX, (int)stY, (int)lengthX, (int)lengthY, 0);//Get all pixels
  326.        
  327.         for (int y=0;y<lengthY;y++)
  328.     {
  329.                 for (int x=0;x<lengthX;x++)
  330.         {//Loop through the pixels
  331.                         var p = new Vector2 (x,y) + start;
  332.                         var center = p + new Vector2(0.5f,0.5f);
  333.                         float dist = (center-NearestPointStrict(from,to,center)).sqrMagnitude;//The squared distance from the center of the pixels to the nearest point on the line
  334.                         if (dist<=strokeOuter2)
  335.                         {
  336.                                 var samples = Sample (p);
  337.                                 var c = Color.black;
  338.                                 var pc = pixels[y*(int)lengthX+x];
  339.                                 for (int i=0;i<samples.Length;i++) {//Loop through the samples
  340.                                         dist = (samples[i]-NearestPointStrict(from,to,samples[i])).sqrMagnitude;//The squared distance from the sample to the line
  341.                                         if (stroke) {
  342.                                                 if (dist<=strokeOuter && dist >= strokeInner) {
  343.                                                         c+=strokeCol;
  344.                                                 } else if (dist<sqrW) {
  345.                                                         c+=col;
  346.                                                 } else {
  347.                                                         c+=pc;
  348.                                                 }
  349.                                         } else {
  350.                                                 if (dist<sqrW) {//Is the distance smaller than the width of the line
  351.                                                         c+=col;
  352.                                                 } else {
  353.                                                         c+=pc;//No it wasn't, set it to be the original colour
  354.                                                 }
  355.                                         }
  356.                                 }
  357.                                 c /= samples.Length;//Get the avarage colour
  358.                 pixels[y * (int)lengthX + x] = c;
  359.                         }
  360.                 }
  361.         }
  362.     tex.SetPixels((int)stX, (int)stY, (int)lengthX, (int)lengthY, pixels, 0);
  363.         tex.Apply ();
  364.         return tex;
  365. }
  366.  
  367. static Texture2D  Paint ( Vector2 pos ,  float rad ,  Color col ,  float hardness ,  Texture2D tex  ){
  368.         var start = new Vector2 (Mathf.Clamp (pos.x-rad,0,tex.width),Mathf.Clamp (pos.y-rad,0,tex.height));
  369.         var width = rad*2;
  370.         var end = new Vector2 (Mathf.Clamp (pos.x+rad,0,tex.width),Mathf.Clamp (pos.y+rad,0,tex.height));
  371.         var widthX = Mathf.Round (end.x-start.x);
  372.         var widthY = Mathf.Round (end.y-start.y);
  373.         var sqrRad = rad*rad;
  374.         var sqrRad2 = (rad+1)*(rad+1);
  375.     Color[] pixels = tex.GetPixels((int)start.x, (int)start.y, (int)widthX, (int)widthY, 0);
  376.        
  377.         for (var y=0;y<widthY;y++)
  378.     {
  379.                 for (var x=0;x<widthX;x++)
  380.         {
  381.                         var p = new Vector2 (x,y) + start;
  382.                         var center = p + new Vector2(0.5f,0.5f);
  383.                         float dist = (center-pos).sqrMagnitude;
  384.                         if (dist>sqrRad2) {
  385.                                 continue;
  386.                         }
  387.                         var samples = Sample (p);
  388.                         var c = Color.black;
  389.                         for (var i=0;i<samples.Length;i++)
  390.             {
  391.                                 dist = GaussFalloff (Vector2.Distance(samples[i],pos),rad) * hardness;
  392.                                 if (dist>0)
  393.                 {
  394.                                         c += Color.Lerp (pixels[y*(int)widthX+x],col,dist);
  395.                                 }
  396.                 else
  397.                 {
  398.                                         c+=pixels[y*(int)widthX+x];
  399.                                 }
  400.                         }
  401.                         c /= samples.Length;
  402.                        
  403.                         pixels[y*(int)widthX+x]=c;
  404.                 }
  405.         }
  406.  
  407.     tex.SetPixels((int)start.x, (int)start.y, (int)widthX, (int)widthY, pixels, 0);
  408.         return tex;
  409. }
  410.  
  411. static Texture2D  PaintLine ( Vector2 from ,  Vector2 to ,  float rad ,  Color col ,  float hardness ,  Texture2D tex  )
  412. {
  413.         var width = rad*2;
  414.  
  415.     var extent = rad;
  416.     var stY = Mathf.Clamp(Mathf.Min(from.y, to.y) - extent, 0, tex.height);
  417.     var stX = Mathf.Clamp(Mathf.Min(from.x, to.x) - extent, 0, tex.width);
  418.     var endY = Mathf.Clamp(Mathf.Max(from.y, to.y) + extent, 0, tex.height);
  419.     var endX = Mathf.Clamp(Mathf.Max(from.x, to.x) + extent, 0, tex.width);
  420.  
  421.     var lengthX = endX - stX;
  422.     var lengthY = endY - stY;
  423.  
  424.     var sqrRad = rad * rad;
  425.     var sqrRad2 = (rad + 1) * (rad + 1);
  426.     Color[] pixels = tex.GetPixels((int)stX, (int)stY, (int)lengthX, (int)lengthY, 0);
  427.     var start = new Vector2(stX, stY);
  428.         //Debug.Log (widthX + "   "+ widthY + "   "+ widthX*widthY);
  429.         for (int y=0;y<(int)lengthY;y++)
  430.     {
  431.                 for (int x=0;x<(int)lengthX;x++)
  432.         {
  433.                         var p = new Vector2 (x,y) + start;
  434.             var center = p + new Vector2(0.5f, 0.5f);
  435.                         float dist = (center-NearestPointStrict(from,to,center)).sqrMagnitude;
  436.                         if (dist>sqrRad2) {
  437.                                 continue;
  438.                         }
  439.                         dist = GaussFalloff (Mathf.Sqrt(dist),rad) * hardness;
  440.                         //dist = (samples[i]-pos).sqrMagnitude;
  441.             Color c;
  442.                         if (dist>0) {
  443.                 c = Color.Lerp(pixels[y * (int)lengthX + x], col, dist);
  444.                         } else {
  445.                 c = pixels[y * (int)lengthX + x];
  446.                         }
  447.  
  448.             pixels[y * (int)lengthX + x] = c;
  449.                 }
  450.         }
  451.     tex.SetPixels((int)start.x, (int)start.y, (int)lengthX, (int)lengthY, pixels, 0);
  452.         return tex;
  453. }
  454.  
  455. internal class BezierPoint
  456. {
  457.         internal Vector2 main;
  458.         internal Vector2 control1;//Think of as left
  459.         internal Vector2 control2;//Right
  460.         //Rect rect;
  461.         internal BezierCurve curve1;//Left
  462.         internal BezierCurve curve2;//Right
  463.        
  464.         internal BezierPoint ( Vector2 m ,  Vector2 l ,  Vector2 r  ){
  465.                 main = m;
  466.                 control1 = l;
  467.                 control2 = r;
  468.         }
  469. }
  470.  
  471. internal class BezierCurve {
  472.         internal Vector2[] points;
  473.         internal float aproxLength;
  474.         internal Rect rect;
  475.         internal Vector2  Get ( float t  )
  476.         {
  477.                 int t2 = (int) Mathf.Round (t*(points.Length-1));
  478.                 return points[t2];
  479.         }
  480.  
  481.         void  Init ( Vector2 p0 ,  Vector2 p1 ,  Vector2 p2 ,  Vector2 p3  )
  482.         {
  483.                
  484.                 Vector2 topleft = new Vector2(Mathf.Infinity,Mathf.Infinity);
  485.                 Vector2 bottomright = new Vector2(Mathf.NegativeInfinity,Mathf.NegativeInfinity);
  486.                
  487.                 topleft.x = Mathf.Min (topleft.x,p0.x);
  488.                 topleft.x = Mathf.Min (topleft.x,p1.x);
  489.                 topleft.x = Mathf.Min (topleft.x,p2.x);
  490.                 topleft.x = Mathf.Min (topleft.x,p3.x);
  491.                
  492.                 topleft.y = Mathf.Min (topleft.y,p0.y);
  493.                 topleft.y = Mathf.Min (topleft.y,p1.y);
  494.                 topleft.y = Mathf.Min (topleft.y,p2.y);
  495.                 topleft.y = Mathf.Min (topleft.y,p3.y);
  496.                
  497.                 bottomright.x = Mathf.Max (bottomright.x,p0.x);
  498.                 bottomright.x = Mathf.Max (bottomright.x,p1.x);
  499.                 bottomright.x = Mathf.Max (bottomright.x,p2.x);
  500.                 bottomright.x = Mathf.Max (bottomright.x,p3.x);
  501.                
  502.                 bottomright.y = Mathf.Max (bottomright.y,p0.y);
  503.                 bottomright.y = Mathf.Max (bottomright.y,p1.y);
  504.                 bottomright.y = Mathf.Max (bottomright.y,p2.y);
  505.                 bottomright.y = Mathf.Max (bottomright.y,p3.y);
  506.                
  507.                 rect = new Rect(topleft.x,topleft.y,bottomright.x-topleft.x,bottomright.y-topleft.y);
  508.                
  509.                
  510.                 var ps = new List<Vector2>();
  511.                
  512.                 var point1  = CubicBezier (0,p0,p1,p2,p3);
  513.                 var point2  = CubicBezier (0.05f,p0,p1,p2,p3);
  514.                 var point3  = CubicBezier (0.1f,p0,p1,p2,p3);
  515.                 var point4  = CubicBezier (0.15f,p0,p1,p2,p3);
  516.                
  517.                 var point5  = CubicBezier (0.5f,p0,p1,p2,p3);
  518.                 var point6  = CubicBezier (0.55f,p0,p1,p2,p3);
  519.                 var point7  = CubicBezier (0.6f,p0,p1,p2,p3);
  520.                
  521.                 aproxLength = Vector2.Distance(point1,point2) + Vector2.Distance (point2,point3) + Vector2.Distance (point3,point4)  + Vector2.Distance (point5,point6)  + Vector2.Distance (point6,point7);
  522.                
  523.                 Debug.Log (Vector2.Distance(point1,point2) + "     " + Vector2.Distance(point3,point4) + "   " + Vector2.Distance(point6, point7));
  524.                 aproxLength*= 4;
  525.                
  526.                 float a2 = 0.5f/aproxLength;//Double the amount of points since the approximation is quite bad
  527.                 for (float i = 0 ;i<1;i+=a2)
  528.         {
  529.                         ps.Add (CubicBezier (i,p0,p1,p2,p3));
  530.                 }
  531.                
  532.                 points = ps.ToArray();
  533.         }
  534.        
  535.          internal BezierCurve ( Vector2 main ,  Vector2 control1 ,  Vector2 control2 ,  Vector2 end  )
  536.      {
  537.                 Init (main,control1,control2,end);
  538.         }
  539. }
  540.  
  541. static void  DrawBezier ( BezierPoint[] points ,  float rad ,  Color col ,  Texture2D tex  )
  542. {
  543.         rad = Mathf.Round (rad);//It is important to round the numbers otherwise it will mess up with the texture width
  544.        
  545.         if (points.Length<=1)
  546.                 return;
  547.        
  548.         Vector2 topleft = new Vector2(Mathf.Infinity,Mathf.Infinity);
  549.         Vector2 bottomright = new Vector2(0,0);
  550.        
  551.         for (int i=0;i<points.Length-1;i++)
  552.     {
  553.         Vector2 main = points[i].main;
  554.         Vector2 control2 = points[i].control2;
  555.         Vector2 control1 = points[i + 1].control1;
  556.         Vector2 main2 = points[i + 1].main;
  557.                 BezierCurve curve = new BezierCurve( main, control2, control1, main2 );
  558.                 points[i].curve2 = curve;
  559.                 points[i+1].curve1 = curve;
  560.                
  561.                 topleft.x = Mathf.Min (topleft.x,curve.rect.x);
  562.        
  563.                 topleft.y = Mathf.Min (topleft.y,curve.rect.y);
  564.        
  565.                 bottomright.x = Mathf.Max (bottomright.x,curve.rect.x+curve.rect.width);
  566.        
  567.                 bottomright.y = Mathf.Max (bottomright.y,curve.rect.y+curve.rect.height);
  568.         }
  569.        
  570.         topleft-= new Vector2(rad,rad);
  571.         bottomright+= new Vector2(rad,rad);
  572.        
  573.         var start = new Vector2 (Mathf.Clamp (topleft.x,0,tex.width),Mathf.Clamp (topleft.y,0,tex.height));
  574.     var width = new Vector2(Mathf.Clamp(bottomright.x - topleft.x, 0, tex.width - start.x), Mathf.Clamp(bottomright.y - topleft.y, 0, tex.height - start.y));
  575.  
  576.     Color[] pixels = tex.GetPixels((int)start.x, (int)start.y, (int)width.x, (int)width.y, 0);
  577.        
  578.         for (var y=0;y<width.y;y++)
  579.     {
  580.         for (var x = 0; x < width.x; x++)
  581.         {
  582.                         var p = new Vector2(x+start.x,y+start.y);
  583.                         if (!IsNearBeziers (p,points,rad+2))
  584.             {
  585.                                 continue;
  586.                         }
  587.                        
  588.                         var samples = Sample (p);
  589.                         var c = Color.black;
  590.                         var pc = pixels[y*(int)width.x+x];//Previous pixel color
  591.                         for (var i=0;i<samples.Length;i++)
  592.                         {
  593.                                 if (IsNearBeziers (samples[i],points,rad))
  594.                                 {
  595.                                         c+= col;
  596.                                 } else {
  597.                                         c+= pc;
  598.                                 }
  599.                         }
  600.                        
  601.                         c /= samples.Length;
  602.                        
  603.                         pixels[y*(int)width.x+x] = c;
  604.                 }
  605.         }
  606.  
  607.     tex.SetPixels((int)start.x, (int)start.y, (int)width.x, (int)width.y, pixels, 0);
  608.         tex.Apply ();
  609. }
  610.  
  611. static void AddP(List<Vector2> tmpList, Vector2 p, float ix, float iy )
  612. {
  613.     var x = p.x + ix;
  614.     var y = p.y + iy;
  615.     tmpList.Add(new Vector2(x, y));
  616. }
  617.  
  618. static Vector2[] Sample ( Vector2 p  )
  619. {
  620.         List<Vector2> tmpList = new List<Vector2>(32);
  621.  
  622.         switch (NumSamples)
  623.     {
  624.         case Samples.None:
  625.                         AddP(tmpList,p,0.5f,0.5f);
  626.             break;
  627.  
  628.         case Samples.Samples2:
  629.             AddP(tmpList,p,0.25f,0.5f);
  630.             AddP(tmpList,p,0.75f,0.5f);
  631.             break;
  632.  
  633.         case Samples.Samples4:
  634.             AddP(tmpList,p,0.25f,0.5f);
  635.             AddP(tmpList,p,0.75f,0.5f);
  636.             AddP(tmpList,p,0.5f,0.25f);
  637.             AddP(tmpList,p,0.5f,0.75f);
  638.             break;
  639.  
  640.         case Samples.Samples8:
  641.             AddP(tmpList,p,0.25f,0.5f);
  642.             AddP(tmpList,p,0.75f,0.5f);
  643.             AddP(tmpList,p,0.5f,0.25f);
  644.             AddP(tmpList,p,0.5f,0.75f);
  645.  
  646.             AddP(tmpList,p,0.25f,0.25f);
  647.             AddP(tmpList,p,0.75f,0.25f);
  648.             AddP(tmpList,p,0.25f,0.75f);
  649.             AddP(tmpList,p,0.75f,0.75f);
  650.             break;
  651.         case Samples.Samples16:        
  652.             AddP(tmpList,p,0,0);
  653.             AddP(tmpList,p,0.3f,0);
  654.             AddP(tmpList,p,0.7f,0);
  655.             AddP(tmpList,p,1,0);
  656.  
  657.             AddP(tmpList,p,0,0.3f);
  658.             AddP(tmpList,p,0.3f,0.3f);
  659.             AddP(tmpList,p,0.7f,0.3f);
  660.             AddP(tmpList,p,1,0.3f);
  661.  
  662.             AddP(tmpList,p,0,0.7f);
  663.             AddP(tmpList,p,0.3f,0.7f);
  664.             AddP(tmpList,p,0.7f,0.7f);
  665.             AddP(tmpList,p,1,0.7f);
  666.  
  667.             AddP(tmpList,p,0,1);
  668.             AddP(tmpList,p,0.3f,1);
  669.             AddP(tmpList,p,0.7f,1);
  670.             AddP(tmpList,p,1,1);
  671.                         break;
  672.  
  673.         case Samples.Samples32:
  674.             AddP(tmpList,p,0,0);
  675.             AddP(tmpList,p,1,0);
  676.             AddP(tmpList,p,0,1);
  677.             AddP(tmpList,p,1,1);
  678.  
  679.             AddP(tmpList,p,0.2f,0.2f);
  680.             AddP(tmpList,p,0.4f,0.2f);
  681.             AddP(tmpList,p,0.6f,0.2f);
  682.             AddP(tmpList,p,0.8f,0.2f);
  683.  
  684.             AddP(tmpList,p,0.2f,0.4f);
  685.             AddP(tmpList,p,0.4f,0.4f);
  686.             AddP(tmpList,p,0.6f,0.4f);
  687.             AddP(tmpList,p,0.8f,0.4f);
  688.  
  689.             AddP(tmpList,p,0.2f,0.6f);
  690.             AddP(tmpList,p,0.4f,0.6f);
  691.             AddP(tmpList,p,0.6f,0.6f);
  692.             AddP(tmpList,p,0.8f,0.6f);
  693.  
  694.             AddP(tmpList,p,0.2f,0.8f);
  695.             AddP(tmpList,p,0.4f,0.8f);
  696.             AddP(tmpList,p,0.6f,0.8f);
  697.             AddP(tmpList,p,0.8f,0.8f);
  698.  
  699.             AddP(tmpList,p,0.5f,0);
  700.             AddP(tmpList,p,0.5f,1);
  701.             AddP(tmpList,p,0,0.5f);
  702.             AddP(tmpList,p,1,0.5f);
  703.                        
  704.             AddP(tmpList,p,0.5f,0.5f);
  705.             break;
  706.         case Samples.RotatedDisc:
  707.             AddP(tmpList,p,0,0);
  708.             AddP(tmpList,p,1,0);
  709.             AddP(tmpList,p,0,1);
  710.             AddP(tmpList,p,1,1);
  711.  
  712.             Vector2 pq = new Vector2(p.x + 0.5f, p.y + 0.5f);
  713.             AddP(tmpList,pq,0.258f,0.965f);//Sin (75°) && Cos (75°)
  714.             AddP(tmpList,pq,-0.965f,-0.258f);
  715.             AddP(tmpList,pq,0.965f,0.258f);
  716.             AddP(tmpList,pq,0.258f,-0.965f);
  717.                 break;
  718.         }
  719.  
  720.     return tmpList.ToArray();
  721. }
  722.  
  723. #endregion
  724.  
  725. #region mathfx
  726.  
  727. static float Hermite ( float start ,   float end ,   float value  ){
  728.         return Mathf.Lerp(start, end, value * value * (3.0f - 2.0f * value));
  729. }
  730.        
  731. static float Sinerp ( float start ,   float end ,   float value  ){
  732.         return Mathf.Lerp(start, end, Mathf.Sin(value * Mathf.PI * 0.5f));
  733. }
  734.  
  735. static float Coserp ( float start ,   float end ,   float value  ){
  736.         return Mathf.Lerp(start, end, 1.0f - Mathf.Cos(value * Mathf.PI * 0.5f));
  737. }
  738.  
  739. static float Berp ( float start ,   float end ,   float value  ){
  740.         value = Mathf.Clamp01(value);
  741.         value = (Mathf.Sin(value * Mathf.PI * (0.2f + 2.5f * value * value * value)) * Mathf.Pow(1 - value, 2.2f) + value) * (1 + (1.2f * (1 - value)));
  742.         return start + (end - start) * value;
  743. }
  744.        
  745. static float SmoothStep ( float x ,   float min ,   float max  ){
  746.         x = Mathf.Clamp (x, min, max);
  747.         var v1= (x-min)/(max-min);
  748.         var v2= (x-min)/(max-min);
  749.         return -2*v1 * v1 *v1 + 3*v2 * v2;
  750. }
  751.  
  752. static float Lerp ( float start ,   float end ,   float value  ){
  753.         return ((1.0f - value) * start) + (value * end);
  754. }
  755.  
  756. static Vector3 NearestPoint ( Vector3 lineStart ,   Vector3 lineEnd ,   Vector3 point  ){
  757.         var lineDirection= Vector3.Normalize(lineEnd-lineStart);
  758.         var closestPoint= Vector3.Dot((point-lineStart),lineDirection)/Vector3.Dot(lineDirection,lineDirection);
  759.         return lineStart+(closestPoint*lineDirection);
  760. }
  761.  
  762. static Vector3 NearestPointStrict ( Vector3 lineStart ,   Vector3 lineEnd ,   Vector3 point  ){
  763.         var fullDirection= lineEnd-lineStart;
  764.         var lineDirection= Vector3.Normalize(fullDirection);
  765.         var closestPoint= Vector3.Dot((point-lineStart),lineDirection)/Vector3.Dot(lineDirection,lineDirection);
  766.         return lineStart+(Mathf.Clamp(closestPoint,0.0f,Vector3.Magnitude(fullDirection))*lineDirection);
  767. }
  768.  
  769. static Vector2 NearestPointStrict ( Vector2 lineStart ,   Vector2 lineEnd ,   Vector2 point  ){
  770.         var fullDirection= lineEnd-lineStart;
  771.         var lineDirection= Normalize(fullDirection);
  772.         var closestPoint= Vector2.Dot((point-lineStart),lineDirection)/Vector2.Dot(lineDirection,lineDirection);
  773.         return lineStart+(Mathf.Clamp(closestPoint,0.0f,fullDirection.magnitude)*lineDirection);
  774. }
  775.  
  776.  
  777.  
  778. static float Bounce ( float x  ){
  779.         return Mathf.Abs(Mathf.Sin(6.28f*(x+1)*(x+1)) * (1-x));
  780. }
  781.        
  782. // test for value that is near specified float (due to floating point inprecision)
  783. // all thanks to Opless for this!
  784. static bool Approx ( float val ,   float about ,   float range  ){
  785.          return ( ( Mathf.Abs(val - about) < range) );
  786. }
  787.  
  788. // test if a Vector3 is close to another Vector3 (due to floating point inprecision)
  789. // compares the square of the distance to the square of the range as this
  790. // avoids calculating a square root which is much slower than squaring the range
  791. static bool Approx ( Vector3 val ,   Vector3 about ,   float range  ){
  792.         return ( (val - about).sqrMagnitude < range*range);
  793. }
  794. static float GaussFalloff ( float distance  ,   float inRadius  ){
  795.         return Mathf.Clamp01 (Mathf.Pow (360.0f, -Mathf.Pow (distance / inRadius, 2.5f) - 0.01f));
  796. }
  797. // CLerp - Circular Lerp - is like lerp but handles the wraparound from 0 to 360.
  798. // This is useful when interpolating eulerAngles and the object
  799. // crosses the 0/360 boundary.  The standard Lerp function causes the object
  800. // to rotate in the wrong direction and looks stupid. Clerp fixes that.
  801. static float Clerp ( float start ,   float end ,   float value  ){
  802.    var min= 0.0f;
  803.    var max = 360.0f;
  804.    var half = Mathf.Abs((max - min) / 2.0f);//half the distance between min and max
  805.    var retval = 0.0f;
  806.    var diff = 0.0f;
  807.        
  808.    if((end - start) < -half){
  809.            diff = ((max - start)+end)*value;
  810.            retval =  start+diff;
  811.    }
  812.    else if((end - start) > half){
  813.            diff = -((max - end)+start)*value;
  814.            retval =  start+diff;
  815.    }
  816.    else retval =  start+(end-start)*value;
  817.        
  818.    return retval;
  819. }
  820.  
  821.  
  822. //======= NEW =========//
  823.  
  824.  
  825. static Vector2 RotateVector(Vector2 vector, float rad)
  826. {
  827.         rad *= Mathf.Deg2Rad;
  828.         var res = new Vector2 ((vector.x * Mathf.Cos(rad)) - (vector.y * Mathf.Sin(rad)),(vector.x * Mathf.Sin(rad)) + (vector.y * Mathf.Cos(rad)));
  829.     return res;
  830. }
  831.  
  832. static Vector2  IntersectPoint ( Vector2 start1 ,  Vector2 start2 ,  Vector2 dir1 ,  Vector2 dir2  ){
  833.         if (dir1.x==dir2.x) {
  834.                 return Vector2.zero;
  835.         }
  836.        
  837.         var h1 = dir1.y/dir1.x;
  838.     var h2 = dir2.y / dir2.x;
  839.        
  840.         if (h1==h2)
  841.     {
  842.                 return Vector2.zero;
  843.         }
  844.        
  845.         var line1 = new Vector2 (h1,start1.y-start1.x*h1);
  846.         var line2 = new Vector2 (h2,start2.y-start2.x*h2);
  847.        
  848.         var y1 = line2.y-line1.y;
  849.         var x1 = line1.x-line2.x;
  850.        
  851.         var x2 = y1 / x1;
  852.        
  853.         var y2 = line1.x*x2 + line1.y;
  854.         return new Vector2(x2,y2);
  855. }
  856.  
  857. static Vector2 ThreePointCircle ( Vector2 a1 ,  Vector2 a2 ,  Vector2 a3  )
  858. {
  859.         var dir = a2-a1;
  860.         dir /= 2;
  861.         var b1 = a1+dir;
  862.         dir = RotateVector (dir,90);
  863.     var l1 = dir;
  864.        
  865.         dir = a3-a2;
  866.         dir /= 2;
  867.     var b2 = a2 + dir;
  868.         dir = RotateVector (dir,90);
  869.     var l2 = dir;
  870.     var p = IntersectPoint(b1, b2, l1, l2);
  871.         return p;
  872. }
  873.  
  874. //===== Bezier ====== //
  875.  
  876. static Vector2  CubicBezier ( float t ,  Vector2 p0 ,  Vector2 p1 ,  Vector2 p2 ,  Vector2 p3  )
  877. {
  878.     // FIXME: fix bezier curve algorithm.
  879. /*      t = Mathf.Clamp01 (t);
  880.         var t2 = 1-t;
  881.     return Mathf.Pow(t2, 3) * p0 + 3 * Mathf.Pow(t2, 2) * t * p1 + 3 * t2 * Mathf.Pow(t, 2) * p2 + Mathf.Pow(t, 3) * p3;
  882.  */
  883.     return Vector2.zero;
  884. }
  885.  
  886. static Vector2 NearestPointOnBezier(Vector2 p, BezierCurve c, float accuracy, bool doubleAc)
  887. {
  888.          float minDist = Mathf.Infinity;
  889.         float minT = 0;
  890.         Vector2 minP = Vector2.zero;
  891.         for (float i = 0 ;i<1;i+=accuracy)
  892.     {
  893.                 var point  = c.Get (i);
  894.                 float d = (p - point).sqrMagnitude;
  895.                 if (d<minDist) {
  896.                         minDist=d;
  897.                         minT = i;
  898.                         minP = point;
  899.                 }
  900.         }
  901.        
  902.         if (!doubleAc)
  903.     {
  904.                 return minP;
  905.         }
  906.  
  907.     float st = Mathf.Clamp01(minT - accuracy);
  908.         float en = Mathf.Clamp01 (minT+accuracy);
  909.        
  910.        
  911.         for (var i=st;i<en;i+=accuracy/10)
  912.     {
  913.                 var point  = c.Get (i);
  914.                 float d= (p - point).sqrMagnitude;
  915.                 if (d<minDist)
  916.         {
  917.                         minDist=d;
  918.                         minT = i;
  919.                         minP = point;
  920.                 }
  921.         }
  922.        
  923.         return minP;
  924. }
  925.  
  926. static bool IsNearBezierTest ( Vector2 p ,  BezierCurve c ,  float accuracy ,  float maxDist  ){
  927.         Vector2 prepoint = c.Get (0);
  928.         for (float i = accuracy;i<1;i+=accuracy)
  929.     {
  930.                 var point  = c.Get (i);
  931.                 float d = (p - point).sqrMagnitude;
  932.                 float d2 = (prepoint - point + new Vector2(maxDist,maxDist)).sqrMagnitude;
  933.                 if (d<=d2*2)
  934.                         return true;
  935.         }
  936.        
  937.         return false;
  938. }
  939.  
  940. static Vector2  NearestPointOnBezier ( Vector2 p ,  Vector2 p0 ,  Vector2 p1 ,  Vector2 p2 ,  Vector2 p3  )
  941. {
  942.         float minDist = Mathf.Infinity;
  943.         float minT = 0;
  944.     Vector2 minP = Vector2.zero;
  945.         for (float i = 0 ;i<1;i+=0.01f)
  946.     {
  947.                 var point  = CubicBezier (i,p0,p1,p2,p3);
  948.                 float d = (p - point).sqrMagnitude;
  949.                 if (d<minDist) {
  950.                         minDist=d;
  951.                         minT = i;
  952.                         minP = point;
  953.                 }
  954.         }
  955.        
  956.         float st = Mathf.Clamp01 (minT-0.01f);
  957.     float en = Mathf.Clamp01(minT + 0.01f);
  958.        
  959.         for (var i=st;i<en;i+=0.001f)
  960.     {
  961.                 var point  = CubicBezier (i,p0,p1,p2,p3);
  962.                 var d= (p - point).sqrMagnitude;
  963.                 if (d<minDist)
  964.         {
  965.                         minDist=d;
  966.                         minT = i;
  967.                         minP = point;
  968.                 }
  969.         }
  970.        
  971.         return minP;
  972.        
  973. }
  974.  
  975. static bool  IsNearBezier ( Vector2 p ,  BezierPoint point1 ,  BezierPoint point2 ,  float rad  )
  976. {
  977.         if (point1.curve2 != point2.curve1) {
  978.                 Debug.LogError ("Curves Not The Same");
  979.                 return false;
  980.         }
  981.        
  982.         BezierCurve curve = point1.curve2;
  983.        
  984.         var r = curve.rect;
  985.         r.x-=rad;
  986.         r.y-=rad;
  987.         r.width+=rad*2;
  988.         r.height+=rad*2;
  989.        
  990.         if (!r.Contains (p)) {
  991.                 return false;
  992.         }
  993.        
  994.         var nearest = NearestPointOnBezier (p,curve,0.1f,false);
  995.        
  996.         var sec = point1.curve2.aproxLength/10;
  997.        
  998.         if ((nearest-p).sqrMagnitude>=(sec*3)*(sec*3)) {
  999.                 return false;
  1000.         }
  1001.        
  1002.         nearest = NearestPointOnBezier (p,curve,0.01f,true);
  1003.        
  1004.         if ((nearest-p).sqrMagnitude<=rad*rad) {
  1005.                 return true;
  1006.         }
  1007.        
  1008.         return false;
  1009. }
  1010.  
  1011. static bool  IsNearBeziers ( Vector2 p ,  BezierPoint[] points ,  float rad  )
  1012. {
  1013.         for (var i=0;i<points.Length-1;i++)
  1014.     {
  1015.                 if (IsNearBezier (p,points[i],points[i+1],rad))
  1016.         {
  1017.                         return true;
  1018.                 }
  1019.         }
  1020.         return false;
  1021. }
  1022.  
  1023. //====== End Bezier ========//
  1024.  
  1025. static Vector2  NearestPointOnCircle ( Vector2 p ,  Vector2 center ,  float w  )
  1026. {
  1027.         Vector2 dir = p-center;
  1028.         dir = Normalize (dir);
  1029.         dir *= w;
  1030.         return center+dir;
  1031. }
  1032. static Vector2 Normalize(Vector2 p)
  1033. {
  1034.         float mag = p.magnitude;
  1035.         return p/mag;
  1036. }
  1037.  
  1038. #endregion
  1039.  
  1040. };
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top