What's the best way to paint in Unity? - c#

I'm making a little game, you're given a canvas and have to completely fill it up by painting everything. The problem is that I don't know how to let the user draw on an object in the UI.
I researched 2DTextures and their setPixel() method, but that seems limiting, because making an 800x600 2DTexture would mean you'd have to paint 480000 pixels, and that's too much. If I make the 2DTexture smaller, 150x100 for example, it would be to small. I'd basically need to make the pixels "bigger", each one being a 4x4 of the real pixels.
Another thing I thought of is making a grid in the UI (150x100) and make the single cells change color then touched. Is this viable? How would I go about doing it?
Last thing, I need to check when the canvas is finished, so I need a way to check the color of every pixel (or cell,in case of the grid), would iterating every pixel with getPixel() be fast enough?

Related

Draw a moving point on a fixed draw

I am trying to do the following:
Open a new form and draw few lines and arcs (this is working well).
When an event occurs a new coordinate (x1,y1) is calculated, and a
small circle should be drawn at that coordinate.
When the next event occurs, a small circle should be drawn at
(x2,y2), and the first circle should disappear, while keeping the
lines and arcs that were drawn at step 1.
How do I delete the first circle while keeping all the rest?
Thank you
Once a circle has been drawn, there is no way to delete it. So, you need to clear the entire canvas with the background color and redraw everything.
So, you need to:
Come up with a bunch of "shape" classes for representing each line and each ark and each circle. They will probably all derive from some common base "Shape" class which offers methods that are common to all shapes, for example, a method to draw the shape on a canvas.
Instantiate objects from these classes to represent the shapes that are supposed drawn on the screen, and keep these objects in a list throughout the lifetime of your application.
When the event occurs, you make any changes to your shapes, (in your case, remove a circle and add another circle, or, more likely, change the coordinates of an existing circle without removing it and re-inserting it in the list,) and then you need to invalidate the canvas control that you presumably use for painting, (search for "Invalidate" for documentation,) so as to cause the canvas to repaint itself.
You override the paint method of the canvas control so as to do your painting: first you clear the control to its background color, and then you iterate through your list of shapes, calling each shape to draw itself on the canvas.
Of course this will cause flicker; if that's unacceptable, then you will need to read up on how to implement "double buffering" (look it up) to eliminate the flicker.
Another approach for flicker elimination is to only erase and repaint the area that has changed. In your case, that would be the smallest rectangle that contains both the circle in its old location, and the circle in its new location. So, instead of invalidating the entire canvas, you invalidate only that rectangle. The problem with this approach is that other shapes that cross the invalidated area might appear to be redrawn somewhat inaccurately. This may be unacceptable, or it may be acceptable, you will not know unless you try it.
You can't in the way you're thinking of, because the graphics works like MSPaint (a 2d array of pixels and when it's drawn, it's drawn) not Adobe Photoshop (layers or objects that can be moved independently)
The easiest thing to do is implement photoshop-like functionality yourself and keep eg a List of everything you want to draw, draw from the list (the list includes a circle) then later, remove that circle from the list, add another one and redraw the whole canvas from the list
I know it seems wasteful, and you probably could get into the mechanics of saving the pixels you drew over when you draw the first circle and restore them to erase the circle, but it's far more complex than just ditching it all and starting over every time

How can I create a good panel for displaying rectangles in C#?

I am a not very good at C# yet so bear with me,
I am trying to create a program that can edit pictures of small sizes (16x16, 32x32, etc...), specifically Minecraft texture files. I need to create a drawing surface where I can display rectangles on. I want to use WPF rectangles because they are working for me so far. I tried putting them on a WPF Grid panel but creating a good size grid panel with 1 pixel wide rows and columns takes about thirty seconds and that's quite a lot of time. Any ideas are helpful.
I'm getting the feel that your direction might not be the most efficient.
Of course, it's quite possible to convert an image into a lot of rectangles, but it's really not efficient once you have a lot of pixels. (32x32 = 1024 rectangles.)
So, instead of going along with WPF rectangles, like you want to, I would urge you to reconsider. Instead, try to work with WriteableBitmap.
From your vague description, I assume you are writing a paint like program, where the user can select a color and draw with the mouse on the texture with that color. By binding the WriteableBitmap up to an Image tag, and adding an event listener to the MouseMove event, you can get the mouse position, and whether the left/right mouse button is pressed or not. Combine that with some math involving the x position and the ActualWidth, and the y position and ActualHeight, of the Image, you can find the pixel the mouse is over, and set the color of that pixel.
So basically, Rectangles are not your best bet. Especially if you try to make a 32x32 grid to contain them. Use WriteableBitmap.
I would suggest using something more lightweight like DrawingVisuals. Alternatively if you really just want to display the textures you can preprocess them and display the result as a normal Image.

How can I prevent GDI+ from re-drawing everything on paint?

I want to change the colour of certain parts of a control which is using GDI+ to draw itself, like when certain objects are hovered/clicked, for example.
How can I re-draw only the necessary parts? It seems bad to re-draw thousands of pixels when I only need to make a change to a few of them.
To be specific, I have drawn anywhere from 1 to 128 rectangles, and I will need to re-draw anywhere from 1 to 128 rectangles in various events. I don't want to re-draw 128 rectangles in order to make a change to only 1-127.
I have read that it is a bad idea to use drawing code in places which are not the on paint event. But, is it possible to do this when relying on the paint event?
You can use one of the Control.Invalidate methods to specify the region you want to redraw.
Then in the Paint event hander you can check the invalidated region with the e.ClipRectangle property.

What layout should I use if I'm going to place 60 (more in the future) images in a grid-like layout?

I need them to be ordered neatly and be able to use animations on each image.
The animation will be a simple "grow" effect to symbolize that the image has been selected. So when a user clicks the image, that Image will grow a bit.
So, a grid? A stack? I'm a bit confused.
A WrapPanel might be one possible choice. This will avoid you having to pre-determine the number of columns of images, making that flexible depending on available width.
When an image is selected, you could simply modify its RenderTransform temporarily to increase the scale factor, which will make it grow a bit without affecting the other images around it.

GDI+: Alternatives to DrawReversible for visual selection indicators?

I've searched around for an alternative way of drawing selection indicators for visual objects (like selected edges, lines etc.) without the use of ControlPaint.DrawReversibleFrame and related XOR methods. The reasons are unwanted XOR-ing "artifacts", reversibility not applying to bitmaps, no control of the actual visual look and slowness.
On the other hand I want to avoid having to repaint the whole scene (map actually) if a user decides he wants to deselect an object or two, because the repaint could be quite expensive.
So the only alternative I can see is implementing some basic drawing logic directly on a Bitmap, but with storing the previous contents of the pixels before they change. Then (in theory) I would be able to reapply old contents of, say, an selected edge rectangle if the user chooses to deselect that edge.
My question is whether you think this is a good idea or do you see some other alternatives to my problem (within the GDI+)?
Thanks in advance
If the selection indicator is just drawn on the top of the unselected object, you can use two bitmaps, draw all the unselected objects on the background one and the selection indicators on the other, and paint them both on screen.
Else, you can do the same, except that you render the selected objects instead of just indicators.
Only store the rectangles "of interest" in an off screen buffer. And repaint when the focus is lost. . . Or if you can redraw just the portion as it appears normally based on in memory data you should be fine. Otherwise it seems that you have the gist of it.

Categories

Resources