Search Unity

Making a color wheel / color picker?

Discussion in 'Scripting' started by Fishypants, Oct 25, 2009.

  1. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Hello, I was wondering how I can convert the mouse position to a point on a texture? If I can figure out how to do that then I am assuming I could use "Texture2D.ReadPixels" to get the color under the mouse position, am I correct?

    I am having trouble trying to figure this one out. Any help would be appreciated. Thank you.
     
  2. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Anybody?
     
  3. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    One way to go would be to use a raycast to detect the point on the object under the mouse (see this example script). The RaycastHit object returned by the raycast contains the texture coordinate of the target point. Rather than use Texture2D.GetPixels (ReadPixels actually does something slightly different), you could pass the texture coordinate directly to Texture2D.GetPixelBilinear and avoid calculating the pixel position of the coordinate.
     
  4. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    yay! :D Thanks very much andeeee. I will try that out and post my results.
     
  5. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
  6. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    @ andeeee-
    Hey, I am trying to piece this together, and am a little unclear. Does the physics.raycast work for GUI elements?

    @ bigkahuna-
    I am looking at the code for UnityPaint right now . . . although I am a bit lost. I am assuming the function that handles the RGB picking is the RGBCircle function . . right? Im not seeing anywhere where the guy uses raycasting, but a lot of:

    Code (csharp):
    1. pos = (Vector2 (Mathf.Cos ( hsb.h*360*Mathf.Deg2Rad), -Mathf.Deg2Rad))*r.width*hsb.s/2);
    I see the if(Input.GetMouseButton(0)) section, so I am pretty sure the code to get the clicked on color is there, but im not quite making sense of it. :(
     
  7. GaborD

    GaborD

    Joined:
    Jul 9, 2007
    Posts:
    42
    You can make a color picker hassle-free right in the UI.

    This is what I use to tint parts of the character in my character editor.

    You can even hold the mouse button down and move the cursor around on the picker and it updates realtime on the model, smoothly changing the colors if your texture has smooth color-gradients.

    colorPicker is a Texture2D, col is obviously a Color.
    xxx and yyy are just the position of the button on the screen. Makes it easy to duplicate and set up if you need several colorpickers.
    You will have to adjust the numbers for offset and textureheight depending on the texture you use (the 9, 5 and 41). Also make sure the button is a bit bigger than the texture, or it will get squashed and it stops working pixelperfectly. (I needed a buttonheight of 55 for my texheight of 41 for instance. I am sure there are ways to make the button fit better if you play with the button styles, but I liked how it looked out of the box, so I chose the easy road)


    Code (csharp):
    1. if (GUI.RepeatButton (Rect (xxx,yyy,215,55), colorPicker)) {
    2.                 pickpos = Event.current.mousePosition;
    3.                 aaa = pickpos.x-xxx-9;
    4.                 bbb = pickpos.y-yyy-5;
    5.                 col = colorPicker.GetPixel(aaa,41-bbb);
    6.  
    7.                 model.materials[matnum].SetColor("_Color",col);
    8.             }
     
  8. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    Very nice solution GaborD, I'll have to remember this one!
     
  9. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    :D Awesome GaborD. I will try your solution as well. Seems pretty straight forward.

    So far I have a function that uses a black and white image, and tints it with a predetermined color. The last part I am missing is to be able to pick the color, so I am hoping to get this part done soon. As soon as I figure it out I will post my result so as to help other n00bs out. Thanks again for the replies everyone.
     
  10. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Hey GaborD, it took me a bit to get the hang of it, but I got it to work! :D Thank you so much for sharing this.

    It took a bit of messing with the offsets and image sizes to get the right combination, but I think I found one that works well.

    As a side note, where are you getting the 9 and 5 from in your code? Are those just random numbers that seemed to work well, or is there a basis for arriving at those? Just curious, because I would like to fully understand whats going on as I am trying to learn Unity. Thanks again.
     
  11. GaborD

    GaborD

    Joined:
    Jul 9, 2007
    Posts:
    42
    There is some space between the button edge and the texture edge plus my texture had a thin border too, so those added up to the values that worked.
    I just tried around until it was pixelperfect. :)
     
  12. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    awesome, thanks again! :D
     
  13. DigitalAdam

    DigitalAdam

    Joined:
    Jul 18, 2007
    Posts:
    1,204
    @Fishypants - I'm really interested in getting this to work for an Avatar creator, using the color selected as the base for a character mesh. Would you be able to share your code in getting this to work, I know that you said GaborD gave you a hand? I'm really new to codding so I don't know how to use GaborD's script...

    Thanks!
     
  14. davidmaggot

    davidmaggot

    Joined:
    Feb 8, 2011
    Posts:
    13
    Thanks GaborD for sharing seems to works fine !!
     
  15. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    Adam -

    I modified GaborD's original code, and converted it to C# (since thats what I am using now). Hopefully you find it useful:

    Drag this onto a game object. In the inspector, drag an image into the "Color Picker" slot that you want to use as a color picker. Set the "Image Width" and "Image Height" attributes to be the size of the image. When you click and drag inside the image, color information should show up in the Console.
    Code (csharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections;
    4.  
    5. public class ColorPicker : MonoBehaviour {
    6.     public Texture2D colorPicker;
    7.     public int ImageWidth = 100;
    8.     public int ImageHeight = 100;
    9.  
    10.     void OnGUI(){
    11.         if (GUI.RepeatButton(new Rect(10, 10, ImageWidth, ImageHeight), colorPicker)) {
    12.                 Vector2 pickpos = Event.current.mousePosition;
    13.                 int aaa = Convert.ToInt32(pickpos.x);
    14.                 int bbb = Convert.ToInt32(pickpos.y);
    15.                 Color col = colorPicker.GetPixel(aaa,41-bbb);
    16.  
    17.                 // "col" is the color value that Unity is returning.
    18.                 // Here you would do something with this color value, like
    19.                 // set a model's material tint value to this color to have it change
    20.                 // colors, etc, etc.
    21.                 //
    22.                 // Right now we are just printing the RGBA color values to the Console
    23.                 Debug.Log(col);
    24.         }
    25.     }
    26. }
    27.  
    You'll have to find out how to change a models color value somewhere in the forum, as I don't remember how to do it offhand and I don't have my old example on me (computer died) (>.<)
     
  16. Time.toMoveOn

    Time.toMoveOn

    Joined:
    Dec 4, 2012
    Posts:
    1
    I'd like to share what I did, in UnityScript not C#.

    Have a look :

    Code (csharp):
    1. var target : Transform;  // change color of :
    2.  
    3. // var background : Texture2D;  // add a background (see line 34)
    4.  
    5. var colorPicker : Texture2D;  // next settings for texture 256x256   /!\ Don't forget to make the texture readable (Select your texture : in Inspector [Texture Import Setting] > Texture Type > Advanced > Read/Write enabled > True  then Apply).
    6.  
    7. var imageX : int = 0;
    8. var imageY : int = 0;
    9. var imageWidth : int = 260;
    10. var imageHeight : int = 260;
    11. var buttonBorderH : float = 4.0;
    12. var buttonBorderV : float = 0.0;
    13.  
    14.  
    15. function OnGUI() {
    16.        
    17.     if (GUI.RepeatButton(Rect(imageX, imageY, imageWidth, imageHeight), colorPicker)) {
    18.  
    19.         var pickpos : Vector2 = Event.current.mousePosition; // give mouse position Vector2(x,y)
    20.  
    21.         var aaa : int = pickpos.x - imageX - buttonBorderH;
    22.  
    23.         var bbb : int =  pickpos.y - imageY - buttonBorderV;
    24.  
    25.         var col : Color = colorPicker.GetPixel(aaa,colorPicker.height-bbb); // return pixel color at coordinates(x,y) ! of texture2D !
    26.  
    27.  
    28.             // Debug.Log(pickpos);
    29.            
    30.             target.renderer.material.color = col;
    31.  
    32.     }
    33.    
    34.     // GUI.Label(Rect(imageX + 5.5, imageY + 2.5, 254, 254), background);        // background Label
    35. }
    36.  
    37.  
    38. @script ExecuteInEditMode  // make it visible in Game window without pressing Play
    Works fine. Up for more advices - still beginner myself.
     
    Last edited: Dec 7, 2012
  17. kofexStudios

    kofexStudios

    Joined:
    Sep 23, 2012
    Posts:
    3
    Wow, interesting solutions. Can someone upload the particular color picker texture that worked perfectly

    Thanks in advance
     
  18. Toonsylvania

    Toonsylvania

    Joined:
    Jun 1, 2010
    Posts:
    29
    Here is a good color picker for those who need it...
     

    Attached Files:

  19. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,085
    What are the offsets you used for this one?
     
  20. r67en

    r67en

    Joined:
    May 13, 2013
    Posts:
    4
    Dimensions for the posted image are 400 x 400. If you use a different image, set ImageWidth and ImageHeight to the dimensions of the image.

    Many thanks to the original coders; I found this to be very useful.
     
  21. DeveshPandey

    DeveshPandey

    Joined:
    Sep 30, 2012
    Posts:
    221
    Hi Guys,

    I have tried this code :

    Its always printing the value RGBA(1.000, 1.000, 1.000, 0.000)
    please let me know what I am missing, I have enabled read/write in advanced texture type also.
     
  22. srancsik

    srancsik

    Joined:
    Aug 10, 2013
    Posts:
    7
    Guys, THANK A LOT!!!
    I wish everything was as well documented and final solution shared as this one. Very useful, I am so grateful!
     
  23. anirudha_vfx

    anirudha_vfx

    Joined:
    Oct 12, 2013
    Posts:
    11
    Select the texture you are using for color picking, and in inspector window change the texture type to advanced, and enbale read/write. It will work. Also a BMP is preferred.
     
  24. voxi

    voxi

    Joined:
    Dec 3, 2013
    Posts:
    60
    @Fishypants ,

    Hi there, and thanks for your code help!!

    I fixed your C# version for you so the texture does not flip on the Y axis:

    Code (csharp):
    1.     //image pallette
    2.             palletAnchorX = Screen.width/2- pallette.width/2;
    3.             palletAnchorY = Screen.height/2- pallette.height/2+60;
    4.  
    5.             if (GUI.RepeatButton (new Rect (palletAnchorX, palletAnchorY, ImageWidth, ImageHeight), pallette)) {
    6.  
    7.                 Vector2 pickpos = Event.current.mousePosition;
    8.                
    9.                 int aaa = Convert.ToInt32 (pickpos.x-palletAnchorX-offsetX);
    10.                 int bbb = ImageHeight - Convert.ToInt32 (pickpos.y-palletAnchorY-offsetY);
    11.  
    12.                 Color col = pallette.GetPixel (aaa,bbb);
    13.                 palletteColorCurrent = col;
    14.    



    You set the image values to compensate for the unity padding 100 pixel texture + 12 padding and outline.
    This is thy the offset is set to 6

    Change the X and Y anchors variables for setting your buttons position,This will allow you to move the pallet around anywhere on the screen, and not have to change the offset value.


    Thanks for everyone who posted here, I have a great looking , user-changeable, color pallet!
     
    Last edited: Jan 5, 2014
  25. Fishypants

    Fishypants

    Joined:
    Jan 25, 2009
    Posts:
    444
    @voxi -
    Nice job! Lookin sweet.
     
  26. tcuvillier

    tcuvillier

    Joined:
    Dec 28, 2013
    Posts:
    8
    Thanks fishypants voxi, simple and to the point just what I needed :)
     
  27. jainam

    jainam

    Joined:
    Oct 20, 2013
    Posts:
    9
    Cool! What I was exactly looking for! Thanks!
     
  28. jainam

    jainam

    Joined:
    Oct 20, 2013
    Posts:
    9
    I have one question though....a short overview of what I want to do first. I want to use this color picker in my app settings to customize the app. I was thinking to use two lines (images), one vertical and one horizontal to select the color from a rectangular color palette. The vertical line for "X" coordinate on the color palette and horizontal for "Y" coordinate. So, the (x,y) coordinate would be the color selected. So by dragging these two lines, user can select a color. Is there a way to do it? Or any other way to do it without lines?
     
  29. look1231241

    look1231241

    Joined:
    Jan 15, 2013
    Posts:
    1
    I have modified Fishypants's code, it can change the rect of colorPicker textrue,I think it will more helpfully.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class ColorPick : MonoBehaviour {
    6.  
    7.     public Transform target;
    8.    
    9.     /*  
    10.     /!\ Don't forget to make the texture readable
    11.     (Select your texture : in Inspector
    12.     [Texture Import Setting] > Texture Type > Advanced > Read/Write enabled > True  then Apply).
    13.     */
    14.     public Texture2D colorPicker;  
    15.      
    16.     public Rect colorPanelRect = new Rect(0,0,200,200);
    17.    
    18.     void OnGUI() {
    19.         GUI.DrawTexture(colorPanelRect, colorPicker);
    20.         if (GUI.RepeatButton(colorPanelRect, ""))
    21.         {
    22.             Vector2 pickpos  = Event.current.mousePosition;
    23.             float aaa  = pickpos.x - colorPanelRect.x;
    24.      
    25.             float bbb  =  pickpos.y - colorPanelRect.y;
    26.            
    27.             int aaa2  = (int)(aaa * (colorPicker.width / (colorPanelRect.width + 0.0f)));
    28.      
    29.             int bbb2  =  (int)((colorPanelRect.height - bbb) * (colorPicker.height / (colorPanelRect.height + 0.0f)));
    30.      
    31.             Color col  = colorPicker.GetPixel(aaa2, bbb2);
    32.      
    33.             Debug.Log(aaa2 + "||||||" + bbb2);
    34.             target.renderer.material.color = col;
    35.         }
    36.     }
    37. }
    38.  
     
    avrkwiatek likes this.
  30. Robot_Butler

    Robot_Butler

    Joined:
    Aug 17, 2013
    Posts:
    7
    I know this is an old form, i thought i'd give it a shoot anyway.

    The lasts guys post works great, lots of talent, the problem is using the "Event.current.mousePosition" on a device, doesn't update the finger position. I've tried playing around with a few touch commands, but cant seem to nail it.

    No hurry, but if anyone could chuck a solution. i would be most grateful :)
     
  31. mhicauber

    mhicauber

    Joined:
    Nov 5, 2014
    Posts:
    2
    Using Touch.position ?