Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
This post has been wikified, any user with enough reputation can edit it.
avatar image
3
Question by shadi.lahham · Jun 26, 2012 at 11:48 AM · mousepixeltrackingdraw

Drawing with mouse on GUI or world texture

Hello,

I would like to be able to fluidly draw on top of any unity scene. I have tried to do this on the Gui as well as on a texture in a world object.

The code below works, but the mouse drawing is slow and jerky. The problem is that I don't get real time pos from Input.mousePosition. I tried to use Texture2D.SetPixels and Texture2D.Apply as little as possible.

My questions:

  1. How can I draw fluidly on a texture ? GUI or world object. I'm new to Unity so I am not sure the approach I chose is the correct one. Feel free to suggest different methods. I know there are other ways to get mouse input, but Input.mousePosition seemed the most precise.

  2. Is there a way to freeze the Unity3D engine and give the GUI priority ? I don't mind freezing the scene in some cases, while in others I would like the action to continue in the background.

  3. I also tried without the GUI, putting a semi transparent world object in front of the camera and drawing on its texture, thinking that function Update() might update faster than function OnGUI() but Input.mousePosition was just as slow.

  4. If I reduce the game world window, mouse tracking is more fluid. But I need this to run on a high resolution.

  5. I don't necessarily have to draw 1 pixel dots, I just used that as the first attempt. Eventually I would like to use brushes of various sizes. I saw here that textures can be linked to brushes in the inspector.

  6. Also, eventually I would like to draw not with the mouse but with gestures on an iPad. Will it be easy to replace Input.mousePosition with gesture inputs ? For now I don't have Unity Pro or the iOS addon, but plan to buy them later on.

  7. Is it possible to make a game like crayon physics with Unity ? or is it optimized for 3D rendering ? Just wondering if this is the right tool for what I need to do.

Notes:

I'm not making a game, but just used crayon physics as a reference of something that has fluid drawing capabilities.

I'm new to all this so please bare with me. Also, thought this might be useful for other people, so I will edit to add references to other answers.

System info: win7 64bit, decent graphic card.

Here is my code

 #pragma strict
 
 private var canvasBackground: Texture2D;
 private var locked: boolean = true;
 
 // initialize the canvas
 canvasBackground = new Texture2D(Screen.width, Screen.height);
 
 // get the size of the screen
 private    var pixels = Screen.width * Screen.height;
 
 // create a color array 
 private    var colors = new Color[pixels];
 
 private    var pencolor = Color.black;
 
 // buffer is used to avoid setting pixels on each onGUI call
 private var buffer = 0;
 
 // last detected mouse position
 private var lastpos:Vector3;
 
 private var reset:boolean = true;
 
 // fill color array with a BG color -- optional -- commented out to leave it transparent
 /* for (var i=0;i<pixels;i++)
 {
     colors[i] = Color.black;
 } */
 
 function OnGUI() {
 
     // mouse 1 shows the 'canvas'
     if (locked && (Input.GetMouseButton(1)) ) {
         locked = false;
     }
 
     if (locked)
         return;
 
     // mouse 2 hides the 'canvas'
     if (!locked && (Input.GetMouseButton(2)) ) {
         locked = true;
         return;
     }
 
     // mouse 0 'paints'
     if (Input.GetMouseButton(0)){
 
         var currpos:Vector3 = Input.mousePosition;
 
         if (reset){
             reset = false;
             lastpos = currpos;
         }
 
         line(lastpos.x, lastpos.y, currpos.x, currpos.y);
         lastpos = currpos;
 
         buffer++;
 
         if (buffer > 9){
 
             buffer = 0;
 
             canvasBackground.SetPixels(colors,0);
             canvasBackground.Apply(false);
         }
 
     } else {
         reset = true;
     }
 
     // GUI.Box(Rect(xpos, ypos, 120, 120), "");
     GUI.Box(Rect(0, 0, canvasBackground.width, canvasBackground.height), "");
 
     // Override the default texture with the custom texture.
     GUI.skin.box.normal.background = canvasBackground;
 
 }
 
 // Bresenham's line algorithm
 function line(x0:int, y0:int, x1:int, y1:int){
    var dx = Mathf.Abs(x1-x0);
    var dy = Mathf.Abs(y1-y0);
    var sx = (x0 < x1) ? 1 : -1;
    var sy = (y0 < y1) ? 1 : -1;
    var err = dx-dy;
 
    while(true){
 
      // Draw the 'pixels' in the color array     
     colors[x0 + Screen.width * y0] = pencolor;
 
      if ((x0==x1) && (y0==y1)) break;
      var e2 = 2*err;
      if (e2>-dy){
        err -= dy;
        x0  += sx;
      }
      if (e2 < dx){
        err += dx;
        y0  += sy;
      }
    }
 }


Comment
Add comment · Show 6
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Berenger · Jun 26, 2012 at 02:43 PM 1
Share

Interesting question ! Take a look at that example from Aron Granberg, and this one from me (it's a trick, I use particles + a camera with don't clear flag, the color buffer accumulates).

avatar image shadi.lahham · Jun 26, 2012 at 03:18 PM 1
Share

Hi, thanks for the comment and the response. These are quite good and help me see that there are ways to do what I want :)

A question, how did you track the mouse movements in your example ?

Can you share some code or the source of the example that you made ?

Did you try out my code ? Why is the mouse input I get so slow and how can I improve it ?

Thanks :)

avatar image Berenger · Jun 26, 2012 at 09:54 PM 1
Share

Yup, here you go. Hope it works :)

avatar image shadi.lahham · Jun 27, 2012 at 09:34 PM 0
Share

Thanks for sharing. Took a detailed look. Your code is actually too complex for me to understand everything, but I got the main structure of it.

Ultimately, you are also using Input.mousePosition to get the mouse position. You just transform and do other things with it. And you call it from an update() not from an onGUI() call.

So I still don't get what is slowing me down. Is it the heavy overhead of repeated onGUI() ? is it SetPixels ? is it the fact that I do things in the GUI and not in the game world ? I tested out your code on the same machine and mouse tracking is super smooth. So it's not a performance issue.

I'll keep trying, but if anyone has ideas I'll be happy to hear :)

avatar image Berenger · Jun 27, 2012 at 10:19 PM 0
Share

I suppose it's because of the Apply function, even if you don't call it every frames

Show more comments

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by shadi.lahham · Jun 27, 2012 at 11:33 PM

This is not really an answer, just an extended comment.

I rewrote the code to track the mouse in update() instead of onGUI() but that hasn't made any difference.

I think that I should not use SetPixel or SetPixels. Any other way to do this ?

I like Berenger's trick, it's very fluid, but I need it to look more like real pen and brush painting. Also, Berenger's code is quite complex for me to replicate quickly. I would have to study C# and Unity more :)

Here is my code anyway, separated in two files now.

Driver.js

 #pragma strict
 
 private var cc : canvas;
 
 private var locked : boolean = true;
 
 // get the size of the screen
 private var pixels = Screen.width * Screen.height;
 
 // create a color array
 private var colors = new Color[pixels];
 
 private var pencolor = Color.black;
 
 // counter is used to avoid setting pixels on each onGUI call
 private var counter = 101;
 
 // last detected mouse position
 private var lastpos : Vector3;
 
 private var reset : boolean = true;
 
 function Start() {
     cc = GetComponent(canvas);
 
     // fill color array with a BG color
     for (var i = 0; i < pixels; i++) {
         colors[i] = Color(1.0, 1.0, 1.0, 0.45); // Color.white; // canvasBackground.GetPixel(0, 0);
     }
 
 }
 
 function Update() {
 
     // ctrl toggles locking of the 'canvas'
     if (Input.GetKeyUp(KeyCode.LeftControl)) {
         locked = !locked;
         // print(locked);
     }
 
     if (locked) {
         cc.draw = false;
         return;
     }
 
     cc.draw = true;
 
     // mouse 0 'paints'
     if (Input.GetMouseButton(0)) {
 
         var currpos : Vector3 = Input.mousePosition;
 
         if (reset) {
             reset = false;
             lastpos = currpos;
         }
 
         line(lastpos.x, lastpos.y, currpos.x, currpos.y);
         lastpos = currpos;
 
         counter++;
 
         if (counter > 3) {
 
             counter = 0;
 
             cc.setColors(colors);
         }
 
     } else {
         reset = true;
     }
 }
 
 // Bresenham's line algorithm
 function line(x0 : int, y0 : int, x1 : int, y1 : int) {
     var dx = Mathf.Abs(x1 - x0);
     var dy = Mathf.Abs(y1 - y0);
     var sx = (x0 < x1) ? 1 : -1;
     var sy = (y0 < y1) ? 1 : -1;
     var err = dx - dy;
     while (true) {
 
         // Do what you need to for this
         // setPixel(x0,y0);
         colors[x0 + Screen.width * y0] = pencolor;
 
         if ((x0 == x1) && (y0 == y1))
             break;
         var e2 = 2 * err;
         if (e2 > -dy) {
             err -= dy;
             x0 += sx;
         }
         if (e2 < dx) {
             err += dx;
             y0 += sy;
         }
     }
 }

and canvas.js

 #pragma strict
 
 public var draw : boolean = false;
 private var canvasBackground : Texture2D;
 
 // initialize the canvas
 canvasBackground = new Texture2D(Screen.width, Screen.height);
 
 function setColors(newColors:Color[]) {
     // print("set new colors");
 
     canvasBackground.SetPixels(newColors, 0); // rem 0
     canvasBackground.Apply(false);
 }
 
 function OnGUI() {
 
     if (!draw)
         return;
 
     // GUI.Box(Rect(xpos, ypos, 120, 120), "");
     GUI.Box(Rect(0, 0, canvasBackground.width, canvasBackground.height), "");
 
     // Override the default texture with the custom texture.
     GUI.skin.box.normal.background = canvasBackground;
 
 }
 
 function Start() {}
 
 function Update() {}
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

how to skethup lines at runtime with mouse position 1 Answer

How can you create a pixelization effect on mousedown? 0 Answers

Tracking slow mouse movements 1 Answer

Convert GetAxis (mouse) to VR head movement 1 Answer

How to find out which object is under a specific pixel 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges