Codea Brush

SimeonSimeon Admin Mod
edited February 2012 in Examples Posts: 5,199

I thought this was really cool. @Grant, a friend and colleague of mine made this while learning Codea. And painted the picture in it:

Codea Brush Pro


  • Posts: 29

    This is great! Steady line. Did your friend use a stylus?

  • SimeonSimeon Admin Mod
    Posts: 5,199

    I'm not too sure. I'll ask him tomorrow. If he did then I want a stylus :)

  • BortelsBortels Mod
    Posts: 1,557

    That's the ugliest dog I ever did see. But nice picture! :-)

  • beebee
    Posts: 381

    A dog? I thought it's a cow! :D

  • @Simeon. Wow, my respect! This is amazing! Never thought one can do that. With the primitives created I am more in the field of drawing cubic art from the mid 1930ies ... Already this gives interesting results, but it's using pure geometrical objects only. How long did you colleague work on that, and how did he solve the problem of deleting unwanted lines, dots, ... With my fingers this is a bit difficult, maybe a stylus is the right tool for that...

  • Posts: 130

    @Simeon, great example. Want to add this example in next version? I want to know how was made it.
    @Simeon, This example, gave me an idea. It's about Color Picker, I see this app have few colors available, not all colors like a Color Picker. I suggest you to add new feature to Codea: Ability to open Color Picker inside Run Time App, for choose any color. For example: showColorPicker() this works like showKeyboard()
    What you think?

  • Posts: 2,161

    I want this code too.

    Incidentally, @Georgian, my extended colour class has a colour picker in it. It picks from a list, rather than a general colour picker, so isn't always suitable.

  • Posts: 2,820

    AWSOME! Did it pose for him in this picture? here You should have put Codea on record and posted it in fat forward. It would've been awsome :-)

  • Posts: 5

    Hi all, a few answers - it was just my finger using only the circle with a single touch. Yes I think a stylus would be better.

    I started the project with my nine year old son to intro him to coding. 

    At this point I change the color and brush size with the parameters. The limited color pallet was for my daughter who kept asking how to make skin color. The irony is I forgot to put skin color in.

    Painting with white is the only way to delete, so it is more like oil painting where you just keep painting over if you make a mistake. After I had finished I thought dang I should have recorded it, but I didn't think it would have turned out so well. I might do another some time.

    The hardest part was remembering the RGB colors I used as I went. An eye dropper tool would make it simpler. Dylan had a good idea which I might try, but I do find SketchBook Pro better to use (not surprisingly). I might keep plugging away but I have an idea for a game I'd like to try.

    All that said I was extremely happy with the results considering how limited my program currently is. 

    The code is probably simple and clumsy, as I really don't get to do much coding anymore. I'll post it so people can see. But I already have a few ideas to improve like layers.

  • Posts: 2,161

    Now if only there were a way to distinguish between a stylus and a finger. Then one could easily simulate pastel drawing.

    Let me reiterate: I want that code. If you've nowhere to post it, send it to me and I'll post it.

  • edited February 2012 Posts: 273

    Nice work @Grant! And I second Andrew's request.

    Re: Sketchbook Pro... I find Procreate (another brilliant Oz iOS app) much (I mean really MUCH) better. If you are not aware of it you may want to check it out.

  • edited February 2012 Posts: 5

    function setup()     backingMode(RETAINED)     count = 0     thicknessTest = 0     paletteSize = 35     currentCol = 0     yColSelect = 0          parameter("thicknessFill", 2, 50, 25)     parameter("red", 0, 255)     parameter("green",0, 255)     parameter("blue",0, 255)     parameter("alpha", 0, 255, 255)              -- This sets the background color to white         bgCol = color(255, 255, 255, 255)         background(bgCol)      end -- This function gets called once every frame function draw()          noSmooth()     globalCol = color(red, green, blue, alpha)     -- the first touch creates an artifact of a single dark dot if alpha is less than 255     -- i did turn off the ellipse, but then you cannot tap to draw a dot.      -- the tapTouch draws only one ellipse rather than repeated alpha ellipses as draw is called     if CurrentTouch.state == BEGAN then         pushStyle()             if tapTouch == false then                 fill(globalCol)                 -- set the colour and thickness from the parameters                 ellipse(CurrentTouch.x, CurrentTouch.y, thicknessFill, thicknessFill)                 tapTouch = true             end         popStyle()                  elseif CurrentTouch.state == MOVING then             pushStyle()             stroke(globalCol)             fill(globalCol)                      -- set the colour and thickness from the parrameters             ellipse(CurrentTouch.x, CurrentTouch.y, thicknessFill, thicknessFill)             popStyle()             tapTouch = false                  elseif CurrentTouch.state == ENDED then             pushStyle()                 fill(0, 0, 0, 255)             popStyle()             tapTouch = false         end          -- make the size snd colour indicator near top left screen     -- give the ellipse a white outline so we can see when fill colour is black     toolbar()           end function toolbar()          gradFactor = 1     shadowWidth = 8     baseCol = 200     menuBar = 70     -- bit of eyecandy drop shadow     for shadow = 1, shadowWidth do         gradFactor = 255-(baseCol/shadowWidth) * shadow         fill(gradFactor, gradFactor, gradFactor, 255)         rect(0, 0, menuBar + shadowWidth - shadow, HEIGHT)     end          fill(234, 234, 234, 255)     rect(0, 0, 70, HEIGHT)          --create the current brush style with white backing, white impotant when using alpha < 255     pushStyle()         stroke(255, 255, 255, 255)         strokeWidth(1)         fill(255)         ellipse(paletteSize, HEIGHT - paletteSize, thicknessFill, thicknessFill)         fill(globalCol)         ellipse(paletteSize, HEIGHT - paletteSize, thicknessFill, thicknessFill)     popStyle()          startPoz = HEIGHT - 50     --draw palette          if CurrentTouch.state == BEGAN then         if CurrentTouch.x < menuBar then             handledColSelect = true             yColSelect = CurrentTouch.y                      end     elseif CurrentTouch.state == ENDED then     end               -- draw the color palette, and test for click     for pCount = 1, 14 do         -- 5 is offset between palette squares then need to add offset to allow for center draw         topPalSquare = (startPoz - ((paletteSize + 5) * pCount)) + (paletteSize/2)         botPalSquare = topPalSquare - paletteSize                  -- yColSelect having value > 0 means a touch on color palette as the handle touch has         -- found that the touches x is on the palette         -- find out which color                  if yColSelect < topPalSquare and yColSelect > botPalSquare then             pushStyle()                 c = getCol(pCount)                 if handledColSelect then                     red = c[1]                     green = c[2]                     blue = c[3]                     handledColSelect = false                 else                                      end                 --alpha = c[4]                 fill(c)                 strokeWidth(2)                 stroke(255, 255, 255, 255)                 rectMode(CENTER)                 rect(paletteSize, (startPoz - (paletteSize + 5) * pCount), paletteSize -6 ,paletteSize - 6 )             popStyle()         else             c = getCol(pCount)             fill(c)             pushStyle()                 rectMode(CENTER)                 rect(paletteSize, startPoz - (paletteSize + 5) * pCount, paletteSize, paletteSize )             popStyle()         end         pushStyle()         fill(255)         --text(pCount, paletteSize, startPoz - (paletteSize + 5) * pCount)         popStyle()     end          --[[ this is for a bg change but cannot use backingMode(RETAINED) and then change bg     -- the new idea is to place the drawing into an image with setContext() could also create     -- layers with a numbers of images          if yColSelect < 100 and yColSelect > 70 then         bgCol = globalCol              end         --draw the background color changer     pushStyle()         -- bg indicator         stroke(255)         fill(bgCol)         rect(27, 80, 25, 25)         -- forground color indicator         stroke(0)         fill(globalCol)         strokeWidth(1)         rect(17, 90, 25, 25)     popStyle() ]]--      end function getCol(index)          if index == 1 then         c = color(255, 0, 0, 255)     elseif index == 2 then         c = color(255, 127, 0, 255)     elseif index == 3 then         c = color(255, 255, 0, 255)     elseif index == 4 then         c = color(0, 255, 0, 255)     elseif index == 5 then         c = color(0, 255, 255, 255)     elseif index == 6 then         c = color(0, 0, 255, 255)     elseif index == 7 then         c = color(127, 0, 255, 255)     elseif index == 8 then         c = color(255, 0, 255, 255)     elseif index == 9 then         c = color(0, 0, 0, 255)     elseif index == 10 then         c = color(51, 51, 51, 255)     elseif index == 11 then         c = color(102, 102, 102, 255)     elseif index == 12 then         c = color(153, 153, 153, 255)     elseif index == 13 then         c = color(204, 204, 204, 255)     elseif index == 14 then         c = color(255, 255, 255, 255)     end     return (c) end

    If someone neatens it up please feel free to post back. As I have said I'm rusty.

  • edited February 2012 Posts: 273

    Grant , the forum is using php markdown for formatting. You can 'fence' your code using three tilde marks ~~~ before and after to maintain your code's formatting.

  • SimeonSimeon Admin Mod
    edited February 2012 Posts: 5,199

    I've just added the code block stuff to the FAQ, too. I should have had it in there from the start.

    Thanks for sharing your code, @Grant. It's a really good example.

    It's kind of amazing to think that you can create your own drawing tool on an iPad and then draw a great picture in it.

  • edited February 2012 Posts: 273
     It's kind of amazing to think that you can create your own drawing tool on an iPad and then draw a great picture in it.

    OTOH it's also kind of amazing that the world has become a place where artists accept tools made by others in order to express themselves.

    Edit: There is definitely something to be said for @Ipda41001's statement and link the other day...

    "Unless you make it yourself, it can't truly be yours."

  • SimeonSimeon Admin Mod
    Posts: 5,199

    Oh I don't know, have you seen the TED talk about building a toaster from scratch? It's almost impossible for one person to do because of the hierarchy of tools needed. Very, very few artists would create every tool in their arsenal (including the tools needed to create other tools).

  • That's probally the best description on Codea. Yes, we use it for play and enjoy it but Codea is also tool that makes tools.

  • edited February 2012 Posts: 273
     Oh I don't know, have you seen the TED talk about building a toaster from scratch? It's almost impossible for one person to do because of the hierarchy of tools needed. Very, very few artists would create every tool in their arsenal (including the tools needed to create other tools).

    Agreed @Simeon and @Ipda41001 -- there is no argument to the fact that we all today "stand on the shoulders of giants."

    I just thought that it was "kind of amazing" that this has become so much part of our nature that we remark on (and appreciate) instances when it is not the case.

    The older I get the more I appreciate the radicalness of McLuhan's 'message' concerning the message: i.e. overt content is "merely eye candy" and the actual message is embedded within the form/medium/tool.

    (At least this afternoon, and of course YMMV.)

  • edited February 2012 Posts: 5

    It is interesting thought @Blanchot, and the closer you get to the origin of a craft, the more likely the practitioner would have made their own tools (a painter making their own brush), and these tools might best match the practioners needs (assuming they did a reasonable job at making them) it would at lease give them a unique result differentiating them from the rest. Even in a mature industry the practioners are likely to have the best idea of what they need from their tools, but specialisation and complexity means they no longer have the capability of making them. 

    Two Lives Left made Codea as they wanted to be able to do their craft on an iPad, in this case they can and have made a great tool and the community is helping shape it. 

    It begs the question can the practitioner with limited programming skills make a better tool than the best programmer who has little understanding of the practitioners craft? Naturally a person with an understanding of both might win hands down. 

  • The practioner has the edge and I clearly saw that in Fred's work on the ABCmusic player. I can only help with basic things. Though I've listened to music since before I can remember, I don't really even know all the basic terms.

  • Posts: 384

    You're too kind, @ipda41001. I have enough knowledge to sketch out something that almost works. I think the best results these days come from close and iterative collaboration between people with different skills.
    PS I love the rhino/sketcher, @Grant

  • edited February 2012 Posts: 76

    @Grant Thank you for Brush program. I advised my daughter to practice her english vocabulary by writting words in Brush program. She is happy to practice the vocabulary with the program. She can draw each picture for each word. When she can remember the words, I will test her by drawing the pictures and she has to write all words matching with the pictures.

    I modified the program to run in Full screen and use the current picked color to chang the pen thickness by clicking the current color. Every time you click the current color, the thickness is increased by 5. The additional code is as follows

    function touched(touch)
        if touch.state==ENDED then
            if touch.x>=paletteSize-25 and touch.x<=paletteSize+25 and touch.y>=HEIGHT-paletteSize
                and touch.y<=HEIGHT-paletteSize+25 then
                    if thicknessFill==50 then
                        thicknessFill = thicknessFill + 5
  • Posts: 5

    Cool thanks @sanit, at full screen, it would benift from a few other tools as well. Interesting to hear its adaption and use in education. I have kids aged 4, 6 and 9, as such are quite interested in technology tools for learning.

  • Posts: 688


    Just a quick observation - obviously there's no direct equivalent of the C switch statement in lua but your getCol() function could be implemented like this...

    local cIndexTab = {
      color(255, 0, 0, 255),
      color(255, 127, 0, 255),
      color(255, 255, 0, 255),
      color(0, 255, 0, 255),
      color(0, 255, 255, 255),
      color(0, 0, 255, 255),
      color(127, 0, 255, 255),
      color(255, 0, 255, 255),
      color(0, 0, 0, 255),
      color(51, 51, 51, 255),
      color(102, 102, 102, 255),
      color(153, 153, 153, 255),
      color(204, 204, 204, 255),
      color(255, 255, 255, 255),
    function getCol(index)
       return cIndexTab[index]

    All I did was pre-calculate a table with the colour values and then just used the index parameter to "index" the table (remembering that in Lua table index's start at 1).

    Just my $0.02 (love the image however and congrats on getting hooked with the programming bug!)

  • Posts: 35

    Just dropped 'Brushes' from my wishlist...

  • edited May 2012 Posts: 29


    I downloaded and started playing with the code. Very fun (takes me back to the very first program I ever hacked together on an Amstrad cpc464 ).

    I altered it a little, instead of drawing ellipses while moving (which I found, when you were drawing quickly would just leave a trail of circles) I altered the line to draw a line -

    so THIS:

     elseif CurrentTouch.state == MOVING then
                -- set the colour and thickness from the parrameters
                ellipse(CurrentTouch.x, CurrentTouch.y, thicknessFill, thicknessFill)
                tapTouch = false

    Became this:

     elseif CurrentTouch.state == MOVING then
                strokeWidth(thicknessFill) -- set the thickness for the line we're about to draw
               -- draw a line from where the touch was in the LAST frame to where the touch is in the current frame
                line(CurrentTouch.prevX, CurrentTouch.prevY, CurrentTouch.x, CurrentTouch.y)           
                -- set the colour and thickness from the parrameters
                -- ellipse(CurrentTouch.x, CurrentTouch.y, thicknessFill, thicknessFill)
                tapTouch = false

    I found though, that this shows a bug(maybe?) in that when noSmooth() was enabled the strokeWidth() could never really draw a thicker line than about 10 pixels. Disabling noSmooth() allowed me to go up as much as I liked (I set the thickness to 100 and no problems)

    (noSmooth() enabled also introduced lots of gaps - but I'm guessing (based on a little bit of testing) that's because noSmooth() oddly decreases the framerate?)

    (I'm running on the new Ipad, whether that makes a difference or not, I dunno)

    The other disadvantage is that the alpha blending is happening too quickly-so the lines are merging even with a low alpha into a solid colour. But, I'm willing to take the hit :)

    (Some background: I haven't coded in a few years, worked in IT for 20years until I could break away into drawing comics-which was always my hobby while I worked in IT. I eventually managed it, discovered I no longer have a hobby and so have turned to programming... I'm eagerly awaiting codea 1.4 - and would LOVE it if Apple took their blinkers off and realised that allowing people to share could easily would be in their best interests.)

  • SimeonSimeon Admin Mod
    Posts: 5,199

    @pjholden Line width: unfortunately that's a limitation of OpenGL's line rendering. It can't go thicker than 20 pixels (which is 10 pixels on a retina device). OpenGL native line rendering is used when noSmooth() is enabled.

  • Posts: 29

    Cheers @simeon - good to know :)

  • Posts: 80

    I think i found a bug with the new iPad and backingMode(retained). The Images seem to scroll upwards, maybe some buffering/resolution Problem? Or is it just me?

  • SimeonSimeon Admin Mod
    Posts: 5,199

    I can't seem to get this to happen on my device. Does the "Handling Touches" example project do the same thing for you? (It uses retained backing)

  • Posts: 1

    I see the issue with the 'Handling Touches' example. The screen seems to scroll up in the background behind the touched point leaving a trail of circles going upwards. The number of circles in the trail is always the same so they 'clump up' together as you move your finger upwards. ( I would attach a screenshot, but can't work out how to paste it into the comments)

    Some factors that may help pinpoint the issue:

    The problem only occurs in portrait mode. If I rotate into landscape then it immediately start working correctly, breaking again when rotated back into portrait.

    When I turn on video recording (in portrait mode), the program immediately starts working correctly, then reverts to being broken when recording is stopped.

    As the circles go up the screen, they get progressively more squashed along the Y axis.

    I have an iPad 2 & 3 here as I'm in the process of upgrading, so can confirm that it is only the iPad 3 which exhibits the problem.

    Sorry that my first post is a 'negative' one. Am new to Codea and have been having real fun with it so far. I just ran into this issue tonight in the process of getting the shiny new iPad 3 up and running. I know that reproducing a problem is often half the battle so wanted to try and help. Happy to try anything to narrow it down further if you need me to.

  • SimeonSimeon Admin Mod
    Posts: 5,199

    @Oz_Jerry portrait mode was the key — I see it too now. Thank you for reporting this. It might actually be an iOS retina GL bug. I don't think we're doing strange when we enable the retained backing mode.

  • Posts: 80

    If you put the backingMode(retained) at line 1 (Not in the setup routine) the error stays regardless of the portrait mode, maybe that helps at some Point?

  • Just to chime in here (been a while since I've been on here) but yeah amazing work!!
    Really think its amazing to be able to create the tools to make your work, I'm a big fan and practitioner of this. except i dont make the computers I use...thats where I have to draw the line.

  • Jmv38Jmv38 Mod
    edited January 2013 Posts: 3,295

    .@Grant i just discover your great painting program. This another of CODEA gems that are deeply burried into the forum... I'd like to collect some of those gems in my web repo, so others (and I) can find them easily. Do you allow me to put the code in my web repo, crediting you as the author and owner of the code, of course?

  • Posts: 666

    @Jvm38, yes, this is another gem! I can't believe I hadn't found it digging through here before, either!

  • Posts: 666

    @Jvm38, yes, this is another gem! I can't believe I hadn't found it digging through here before, either!

Sign In or Register to comment.