[10:05] <qwased> how can i look at past irc classroom logs?
[10:06] <mbudde> http://irclogs.ubuntu.com/
[10:06] <qwased> thanks
[16:08] <reida010> s
[16:18] <didrocks> jono: did you receive my slides? (and for generating the translation string, just quickly package or quickly share/release)
[16:20] <jono> didrocks, yep, they are in there :)
[16:20] <jono> didrocks, isnt there an argument to pass setup.py if I remember right?
[16:20] <jono> I remember dpm did something
[16:21] <RainCT> not sure if it's related at all with what you are talking about, but there is:  python setup.py build_i18n
[16:22] <jono> RainCT, thats it!
[16:22] <jono> woo!
[16:22] <didrocks> jono: if you want to do that outside of quickly yes (but the previous command calls that). It's ./setup.py --build-i18n
[16:22] <didrocks> let me check for the syntax exactly :)
[16:22] <didrocks> one sec
[16:22] <jono> thats cool for updating the translations template without packaging
[16:22] <jono> thanks RainCT, didrocks!
[17:01] <laszlok> Hello everyone, i'm gonna be talking about using cairo with python today
[17:02] <laszlok> I haven't prepared any slides, but I'll be using some links
[17:02] <laszlok> and it will be less structured than usual, so feel free to shout out or ask questions at any time in #ubuntu-classroom-chat
[17:03] <laszlok> I won't mind taking a large detour, we'll probably have plenty of time for it
[17:03] <laszlok> So cairo is a drawing API
[17:04] <laszlok> if you know about SVG graphics, it does the same sort of thing
[17:04] <laszlok> it has strokes, fills, gradients, etc
[17:04] <laszlok> Its also a very modern drawing api
[17:04] <laszlok> the library was written quite recently
[17:05] <laszlok> I mean modern in that it has good alpha support, and really good antialiasing
[17:05] <laszlok> so when you draw graphics they scale well and look very clean
[17:06] <laszlok> unlike previous generation APIs like Java graphics (don't get me started)
[17:07] <laszlok> Cairo integrates really well with GTK, in fact most widgets in GTK are now drawn using cairo
[17:07] <laszlok> I will show you how to use it with GTK and also how to use some other cairo backends like svg, pdf, and png
[17:08] <laszlok> In terms of creating stunning interfaces, it can be done with cairo. If you create a stunning GTK app then you are doing it with cairo anyway ;)
[17:08] <laszlok> however cairo is low level
[17:09] <laszlok> if you are using cairo directly you are drawing all the lines and calculating all the geometry yourself
[17:10] <laszlok> There was a talk yesterday about goocanvas, which uses cairo and gives a much higher level view. You can deal with objects instead of geometry calculations.
[17:10] <laszlok> But if anyone has questions about that, please ask
[17:10] <laszlok> http://www.cairographics.org/samples/
[17:11] <laszlok> here is a page on the cairo website with some sample code and how it will look
[17:11] <laszlok> the code is in C, but it is quite similar to python as you will see
[17:12] <laszlok> QUESTION: Can we build all the application interface using Cairo (except for the Window container)?
[17:14] <laszlok> yes you can, but it will involve a lot of trickiness if you want to detect mouse clicks on many different objects
[17:14] <laszlok> it will work fine for a simple drawing, but once you start using lots of objects you might find the geometry to figure out which one is clicked it too much
[17:14] <laszlok> this is why things like goocanvas were invented; to automate those things
[17:15] <laszlok> QUESTION: can we use cairo to create the interface separate from the logic that runs the program?
[17:15] <laszlok> yes, in the same way that you would have a GTK interface separate from the program logic
[17:16] <laszlok> QUESTION: maybe for later, is there a preferred way of doing animations in cairo?
[17:16] <laszlok> cairo does not provide support for animations, so it has to be done essentially the same as animations in other drawing apis
[17:17] <laszlok> that means having a timer to redraw the screen and have code to redraw the whole screen (or just the parts that change)
[17:18] <laszlok> so as you can see in the samples, cairo has primitives for arcs, lines, etc.
[17:18] <laszlok> Thinking about an interface in these primitives is a bit low level, but it gives you the great flexibility
[17:19] <laszlok> QUESTION: Does the animation redraw method you just described use a lot of cpu power?
[17:19] <laszlok> if your drawing is complex, it probably will
[17:19] <laszlok> but cairo is quite efficient, and allows you flexibility for caching drawings
[17:20] <laszlok> for example if you have a background which requires a long time to draw, you can draw it to an ImageSurface in memory instead
[17:20] <laszlok> and then it is one operation to draw it on screen
[17:21] <laszlok> QUESTION: would like to add to performance that strokes are the ones that are expensive.
[17:21] <laszlok> that's not a question ;)
[17:22] <laszlok> http://www.cairographics.org/documentation/pycairo/reference/index.html
[17:22] <laszlok> here is the python documentation for cairo
[17:22] <laszlok> that is good reference when looking at the next link
[17:23] <laszlok> http://laszlopandy.com/files/drawing_interface.html
[17:23] <laszlok> here is some poorly commented python code I prepared
[17:23] <laszlok> QUESTION: waht are all the required components to start working on cairo+python?
[17:23] <laszlok> only cairo, python and pycairo
[17:24] <laszlok> if you want to render directly on screen (as opposed to png or svg) you should have pygtk installed as well
[17:24] <laszlok> for example, in the code i prepared I am importing both gtk and cairo
[17:25] <laszlok> copy and paste this code into your editor
[17:25] <laszlok> if you run it with no arguments you will get a gtk window
[17:25] <laszlok> if you give it 'png', 'svg' or 'pdf' as an argument, it will generate that kind of file
[17:25] <laszlok> so lets take a look at the GTK code, in the DrawingInterface class
[17:26] <laszlok> it creates a window, and adds a gtk.DrawingArea
[17:27] <laszlok> the DrawingArea is a widget which is like a blank canvas we can draw to
[17:28] <laszlok> then we set the size of the window, and show it
[17:28] <laszlok> not much to see there
[17:28] <laszlok> the expose event is the event when the X server tells the window to redraw itself
[17:28] <laszlok> so this is what we are using to trigger our drawing code
[17:29] <laszlok> also notice that in the GTK code the cairo context is created directy from the widget. GTK is integrated with cairo and makes it easy
[17:29] <laszlok> the context is what holds all the information about your drawing as you add lines and shapes
[17:30] <laszlok> the draw_rounded_rentangle() method is converted from the C example on http://www.cairographics.org/samples/
[17:30] <laszlok> if you compare them you can see it is mostly identical code
[17:31] <laszlok> QUESTION: please explain the underlying functiosn used in on_expose
[17:31] <laszlok> http://laszlopandy.com/files/drawing_interface.html
[17:31] <laszlok> in on_expose we create the cairo context associated with the widget
[17:32] <laszlok> so when we draw using that context, it will draw on the widget
[17:32] <laszlok> widget.get_allocation() returns a renctangle with the width and height of the window, so we know how much space we have to draw
[17:32] <laszlok> and self.drawing.draw() calls the method on the drawing class three lines below that
[17:33] <laszlok> QUESTION: will the get_allocation be called only after drawing.draw is called?
[17:33] <laszlok> this is equivalent to:
[17:33] <laszlok> rectangle = widget.get_allocation()
[17:33] <laszlok> self.drawing.draw(ctx, rectangle)
[17:34] <laszlok> so the draw() method can know the size of the widget
[17:34] <laszlok> by default, the DrawingArea widget is the default gtk colour
[17:35] <laszlok> so in the draw() method I create a rectangle the size of the widget and fill it with white
[17:35] <laszlok> the context remembers things like rectangles i have created, and also what colour i set it
[17:36] <laszlok> after I call fill() the rectangle is removed from the context and put on the screen, but the colour is still set
[17:36] <laszlok> so remember to change your colour or it will be whatever you set it previously
[17:36] <laszlok> QUESTION: Is it possible to do some basic 3d transformation? (Like perspective on GIMP)
[17:36] <laszlok> cairo is a 2d canvas, but you can do transformation
[17:36] <laszlok> to fake a perspective
[17:37] <laszlok> take a look at http://www.cairographics.org/documentation/pycairo/reference/matrix.html#class-matrix
[17:38] <laszlok> In get_gradient() http://laszlopandy.com/files/drawing_interface.html
[17:38] <laszlok> you can see cairo makes gradients really simple
[17:38] <laszlok> you create a gradient with a start and end point to define how long the colour change will be and in what direction
[17:39] <laszlok> and then you set stops on the gradient, just like you would do on inkscape or other graphics programs
[17:39] <laszlok> the first argument to add_color_stop_rgb is the offset between 0 and 1
[17:39] <laszlok> so i set two colour stops. One at the beginning and one at the end
[17:40] <laszlok> you can easily add a third one in set it to offset 0.5 and your gradient will blend three colours
[17:41] <laszlok> now look at the bottom part of the code where it says if arg == 'pdf':
[17:41] <laszlok> i mentioned earlier about using image surfaces to store your drawing in memory
[17:41] <laszlok> surfaces also allow you do store in files
[17:42] <laszlok> QUESTION: can you set the gradient to go through the hues in the opposite direction?
[17:42] <laszlok> yes
[17:42] <laszlok> either reverse the offsets
[17:42] <laszlok> (set the first one to offset 1, and second to offset 0)
[17:43] <laszlok> or reverse the pairs of (x,y) parameters to the LinearGradient constructor
[17:44] <laszlok> QUESTION: does the context variable acts as a placeholder or as a memory buffer?
[17:44] <laszlok> it is the same as the drawing context created from the GTK widget except it writes to a file
[17:45] <laszlok> so it will store your drawing in memory and write it to the file when you complete a fill() or stroke()
[17:45] <laszlok> QUESTION: How to make it write to a jpg file?
[17:46] <laszlok> JPG file compression is meant for pictures where there are not perfectly smooth lines
[17:46] <laszlok> PNG compression works much better for drawings, things with smooth and sharp borders
[17:46] <laszlok> so cairo does not support JPG directly, i would write to svg or png and use imagemagick to convert it
[17:48] <laszlok> so as you can see, cairo surfaces make it really easy to export to other formats
[17:49] <laszlok> and if you were writing on windows or mac, you would use a surface specifically for the platform and the rest of the api would be the same
[17:50] <laszlok> any questions?
[17:50] <laszlok> QUESTION: does cairo do that "redraw only changed parts" automagically, or do we manually tell what changed ?
[17:50] <laszlok> you could have to do that manually
[17:51] <laszlok> in this case i redraw the white rectangle each time, therefore blanking the entire screen
[17:51] <laszlok> this is something that goocanvas would also automate for you
[17:52] <laszlok> QUESTION: How difficult is it to use cairo in combination with pygoocanvas?  (For example, if I wanted to draw/animate something like a progress indicator on top of my goocanvas while waiting for goocanvas to update during a slow operation.)
[17:52] <laszlok> that seems like a strange use case, but it should work
[17:52] <laszlok> theoretically you can use cairo to draw on top of any GTK widget
[17:53] <laszlok> as long as the proper flags are set
[17:55] <laszlok> QUESTION: What are the advantages of using cairo directly instead of through goocanvas?
[17:55] <laszlok> goocanvas is much higher level
[17:55] <laszlok> and cairo is very lightweight
[17:56] <laszlok> if you are doing something simple and want the flexibility, or don't mind doing the drawing manually then cairo is the way to go
[17:56] <laszlok> its really easy to get started with, and can work with GTK mouse clicks, etc well for simpler things
[17:57] <laszlok> if you know you have a bunch of objects you want to drag around on the screen, goocanvas will probably make your life much easier
[17:57] <laszlok> QUESTION: the png format uses the format_argb32 constant. the manual shows 3 more. can u tell the formats they specify?
[17:58] <laszlok> referring to http://www.cairographics.org/documentation/pycairo/reference/constants.html#constants-format
[17:58] <laszlok> FORMAT_ARGB32 is colour surface with alpha support
[17:59] <laszlok> FORMAT_RGB24 is the same without alpha support so you will not be able to do transparency
[17:59] <laszlok> the others are for alpha only masks and do not store colour values
[18:00] <laszlok> these formats are for image surfaces. You may need to specify alpha only if you want to make a transparency mask
[18:01] <didrocks> awesome laszlok, thanks for your session :) Just a question, when will you do a Quickly template for a cairo project? :p (kidding)
[18:01] <didrocks> so, welcome everyone on the session about Quickly 0.4
[18:02] <didrocks> [SLIDE 1]
[18:02] <didrocks> who is interested on what we backed for Quickly 0.4? hands up in -chat!
[18:03] <didrocks> nice
[18:03] <didrocks> so, I'm Didier Roche, one of the Quickly developer and also desktop team member
[18:04] <didrocks> (and fresh ubuntu core dev :))
[18:04] <didrocks> for people not seeing the slide, you can get them at http://people.canonical.com/~didrocks/Quickly-0.4.pdf
[18:04] <didrocks> it should be on the Session tab in lernid
[18:05] <didrocks> so, first, what this session is *not* about
[18:05] <didrocks> this session isn't a presentation of Quickly. This has already been done later this week by Rick Spencer. logs availabled at https://wiki.ubuntu.com/MeetingLogs/OpWeek1003/Quickly
[18:06] <didrocks> [SLIDE 2]
[18:06] <didrocks> (at least, it works me in lernid :p)
[18:06] <didrocks> (and that's not Quickly's fault ;))
[18:06] <didrocks> so, 0.4 is unfortunately still in development
[18:07] <didrocks> it still needs some stuff to be added in launchpad to make things easier
[18:07] <didrocks> and I prefer to do that the right way than a quickly screenscrapping
[18:07] <didrocks> so, warning, it's unstable, the current version is 0.3.5
[18:07] <didrocks> I hope to release the stable version before lucid beta 1
[18:08] <didrocks> in any case, Quickly 0.4 will be in lucid :)
[18:08] <didrocks> so, a little about stats
[18:08] <didrocks> last version which is 0.2.6 has been release approximately 6 months before
[18:08] <didrocks> and a lot happens in 6 months :)
[18:09] <didrocks> you can see some stats for the addicts: 250 commits and 12930 changed lines
[18:09] <didrocks> to be honest, some file had been moved, so if we want to be fair, I would say 4000 code of code have been really impacted
[18:09] <didrocks> it's a lot, and I'll show you now what are in those lines :)
[18:10] <didrocks> [SLIDE 3]
[18:10] <didrocks> souces: how to be informed of what's new?
[18:10] <didrocks> well, this session is dedicated to that, so that's a good first step :)
[18:10] <didrocks> (I'll probably blog on planet ubuntu too when Quickly 0.4 will be out)
[18:11] <didrocks> a more detailed sources the NEWS file in trunk
[18:11] <didrocks> I try to keep it pretty complete
[18:11] <didrocks> and of course, if you want full details, you have to read the 250 commits :)
[18:13] <didrocks> let's first see what's the most noticeable changes
[18:13] <didrocks> the first thing is that the ubuntu-project template (the only one which existed in 0.2.x) is no more…
[18:13] <didrocks> don't be panic, it has just been renamed ubuntu-application
[18:13] <didrocks> of course, existing project will be transitionned appropriately so that you don't have to change anything for existing Quickly users
[18:13] <didrocks> Quickly 0.4 will welcome at least one new template, and even maybe a third one in trunk :)
[18:14] <didrocks> ubuntu-cli template is to create a command line soft with all the ubuntu-application intgration
[18:14] <didrocks> (a lot of people asked for a cli template :))
[18:14] <didrocks> ubuntu-game (or pygame, or whatever) will be detailed later in this week by Rick, you should be already aware of that if you read planet ubuntu
[18:15] <didrocks> also, artfwo (thanks to the template inheritance I'll described later) is beginning to implement a gedit-plugin template
[18:15] <didrocks> so, a lot of goodness to come in a very short time :)
[18:15] <didrocks> [SLIDE 4]
[18:16] <didrocks> as there is no question, let's dive a little bit more on what's interest most of you: ubuntu-project… hum… ubuntu-application new capability ;)
[18:17] <didrocks> first thing (and I'll come back later on that) you have to understand is that your existing app will be converted for 0.4
[18:17] <didrocks> it will be the first time you run a quickly command on it
[18:17] <didrocks> (also if you proceed some tab completion)
[18:17] <didrocks> that's needed and it's a new Quickly core capability
[18:18] <didrocks> that implies that projects which will be converted to Quickly 0.4 won't work anymore with a previous version of Quickly
[18:18] <didrocks> (it's still possible to convert back by hand, but complicated)
[18:19] <didrocks> as I wrote, ubuntu-application in 0.4 has a new versionning scheme
[18:19] <didrocks> that means that project will follow by default ubuntu way of versionning thing
[18:19] <didrocks> for instance, if I run "quickly release" just now, my release will be 10.03
[18:19] <didrocks> if I run quickly release again, it will be 10.03.1
[18:19] <didrocks> and so on :)
[18:20] <didrocks> you are still able to provide your release version yourself
[18:20] <didrocks> the second point is the most tricky one but the one on the top priority list
[18:20] <didrocks> did you have some troubles setting up your gpg and ssh key on LP to make your first quickly share/quickly release?
[18:21] <didrocks> that will be (we hope) part of the past in 0.4!
[18:22] <didrocks> this is what I'm currently working and that needs a lot of work on launchpad side… and I'm not a LP hacker
[18:22] <didrocks> so, normally, if you don't have one, Quickly will do everything for your
[18:22] <didrocks> you*
[18:23] <didrocks> also, selecting the right email adress through some algorithms :)
[18:23] <didrocks> moving on…
[18:23] <didrocks> quickly license has been totally reshaped
[18:23] <didrocks> no more Copyright file which populate an AUTHOR file, you will only have to edit the AUTHOR one
[18:23] <didrocks> (this confused some people before)
[18:24] <didrocks> the next one is more interesting
[18:24] <didrocks> when you quickly release, your changelog will automatically be collected with all the messages you provided in "quickly save <your message>" from the last release
[18:24] <didrocks> it will create a release and milestone on launchpad
[18:24] <didrocks> upload your tarball too to be available on the first page
[18:25] <didrocks> and create an annoucement with your changelog
[18:25] <didrocks> of course, as a good upstream, it signs the tarball file too (as it's recommended as a best practice)
[18:26] <didrocks> you can see what it gives on my test project: https://edge.launchpad.net/fooby
[18:26] <didrocks> next point is ppa
[18:27] <didrocks> when Quickly 0.2 was released, launchpad only enabled you to have one ppa
[18:27] <didrocks> which was called… "ppa"
[18:27] <didrocks> things have changed now and you can have multiple ppa
[18:27] <didrocks> also, some people would like to upload the package to a team ppa
[18:27] <didrocks> and to be honest, that makes sense :)
[18:27] <didrocks> so, now, you can upload to any ppa you want
[18:28] <didrocks> either by providing --ppa <ppa_name>
[18:28] <didrocks> to quickly share and release
[18:28] <didrocks> or to put it as a default with quickly configure ppa <ppa_name>
[18:28] <didrocks> of course, shell completion still works there and give you the list of all ppa you have access
[18:29] <didrocks> (/!\ it's slow on LP side, can take more than 10s)
[18:29] <didrocks> ppa_name can be: "myppa" or "team/ppaname"
[18:29] <didrocks> and shell completion works for everycase :)
[18:30] <didrocks> on another aspect, as I wrote some commands have been rename to be more consistent
[18:30] <didrocks> quickly dialog is now quickly add dialog
[18:30] <didrocks> (that will avoid in the futur to have 50 commands in a template)
[18:30] <didrocks> quickly lp-project is quickly configure lp-project
[18:30] <didrocks> and quickly glade is now quickly design
[18:31] <didrocks> of course, as always, statement completion is here to help you to find commands name and arguments to the commands :)
[18:31] <didrocks> for instance quickly configure [tab][tab] will show you all available options like ppa, lp-project, bzr
[18:32] <didrocks> [SLIDE 5]
[18:32] <didrocks> ah, I like very much next option :)
[18:32] <didrocks> when you "quickly release", now, you will have the about dialog automatically refreshed
[18:33] <didrocks> that means, your logo, but also the new version number appears, the Copyright holder, the homepage, the Credit (authors) button and license one
[18:33] <didrocks> so, no need to before or to think about them, Quickly is handling that for you :)
[18:34] <didrocks> that avoid to make a .1 release with "I forgot to…"
[18:34] <didrocks> next item (no, not the blank one) had been asked also by a lot of persons
[18:34] <didrocks> being able to add manual dependencies
[18:35] <didrocks> "why care, quickly already grab all the depends for us?" you will tell me…
[18:35] <didrocks> that's both true and false to be honest :)
[18:35] <didrocks> for instance, if you launch a command yourself as a subprocess pythondistutils-extra won't find it and you will have a missing dependency
[18:36] <didrocks> so now, for that, you can just fire away $ quickly configure dependencies
[18:36] <didrocks> as "dependencies" is typo-prone, think about using shell completion for that too :)
[18:37] <didrocks> next thing is bzr branch, as for ppa, you can tell where you can push and pull your code if you are interested in :)
[18:37] <didrocks> quickly configure bzr of course :)
[18:38] <didrocks> maybe the tutorial which (I'm afraid) is still not internationalized will be thanks to fagan. But nothing sure yet, still ongoing work :)
[18:39] <didrocks> of course, this was only the most important things I can list for that session for ubuntu-application template, but there are a lot of various fixes, new licenses available, packagin tweak, internationalized application, and so on :)
[18:39] <didrocks> [SLIDE 6]
[18:39] <didrocks> oh btw, I forgot about the apport hook!
[18:40] <didrocks> all project will come (but you can still disabling that if you don't want) an apport hook by default
[18:40] <didrocks> and the menu will have the launchpad addition for translation and help in the help menu
[18:40] <didrocks> ok, so, now, really slide 6 :)
[18:41] <didrocks> this is for prospective template developers and people interested in making a GUI for Quickly
[18:41] <didrocks> first thing is importing commands between templates is available
[18:41] <didrocks> QUESTION: does having an apport hook mean that if the program crashes and stuff you can send a detailed report to the launchpad project?
[18:41] <didrocks> dbell: exactly :)
[18:42] <didrocks> and you get that for free :)
[18:42] <didrocks> so, back on importing commands
[18:42] <didrocks> if one day you want to look at the ubuntu-cli template
[18:42] <didrocks> you will see that there is 0 line of code
[18:42] <didrocks> yes, no typo, I said 0!
[18:43] <didrocks> it's just a new boiler plate, and I import all commands from ubuntu-application
[18:43] <didrocks> so, basically, there is a commandsconfig with:
[18:43] <didrocks> [ubuntu-application]
[18:43] <didrocks> IMPORT=configure;create;edit;license;package;release;run;save;shar
[18:44] <didrocks> (for obvious reason for a cli template, I don't import design and add dialog :))
[18:44] <didrocks> and then, I can create a ubuntu-cli application, edit, licence, package…
[18:44] <didrocks> and get statement completion for all of those using the new boiler plate code :)
[18:45] <didrocks> so, creating a template from an existing one is really really easy
[18:45] <didrocks> QUESTION: Will apps still work if python-launchpad-integration isn't installed (eg. on other distros)
[18:45] <didrocks> RainCT: we try to include that as a patch, so that pristine tarball doesn't have that code and so other distros aren't impacted
[18:45] <didrocks> (it's basically a try: pass)
[18:46] <didrocks> well, other functions (quickly ;))
[18:46] <didrocks> you can now pass option to template
[18:46] <didrocks> we have apport integration
[18:46] <didrocks> so ubuntu-bug quickly is your friend :)
[18:47] <didrocks> as I told you, you can now quickly configure [tab][tab] --ppa [tab][tab]
[18:47] <didrocks> that means that the core has now option completion for you
[18:47] <didrocks> we handle template upgrade
[18:47] <didrocks> (even if you launch a command from one template into another project)
[18:47] <didrocks> like quickly --template my-awesome-template foocommand
[18:48] <didrocks> we have also now an API
[18:48] <didrocks> so, if you want to build a GUI or integrate it into an IDE, that's the way to go :)
[18:48] <didrocks> of course, in addition to thing, many fixes and refactoring
[18:48] <didrocks> [SLIDE 7]
[18:49] <didrocks> I've already talked about the ubuntu-cli template
[18:49] <didrocks> the most important thing is that it's a new boiler plate for no code for the commands :)
[18:49] <didrocks> if you want to implement your own template with import of ubuntu-application command, that's where to look for examples
[18:50] <didrocks> QUESTION: Any examples on the API?
[18:50] <didrocks> osteenbergen47: basically, you just have to "from quickly import api" and then, look at the api file
[18:50] <didrocks> if you are interested in that, join #quickly and I can help you :)
[18:50] <didrocks> QUESTION: is there a tutorial on how to do own/custom templates ?
[18:51] <didrocks> oskude: I've written one for Quickly 0.2, let me find the link
[18:51] <didrocks> http://blog.didrocks.fr/index.php/post/Build-your-application-quickly-with-Quickly%3A-Inside-Quickly-part-6
[18:52] <didrocks> (and now, I kill my Internet connexion as I host myself my server ;))
[18:52] <didrocks> this is quite outdated
[18:52] <didrocks> I will refresh that once 0.4 out
[18:52] <didrocks> [SLIDE 8]
[18:52] <didrocks> so, you want to try Quickly 0.4? (well, 0.3.5)
[18:53] <didrocks> as I mentionned before, we warned, you can't convert back your project to the previous format
[18:53] <didrocks> and I don't have the time to ensure that everycommand works at each commit, but I try to fix the issue within the day
[18:53] <didrocks> so, jump into #quickly, so that you can yell at me that it's broken :)
[18:54] <didrocks> and if you want to test, branch the trunk
[18:54] <didrocks> bzr branch lp:quickly
[18:54] <didrocks> export PATH=<path_to_your_trun>/bin:$PATH
[18:54] <didrocks> (note the /bin :))
[18:54] <didrocks> quickly --version should normally answer you about the current version
[18:54] <didrocks> [SLIDE 9]
[18:55] <didrocks> of course special thanks to Rick to have the idea of this project
[18:55] <didrocks> and he will do the two next session, stay around :)
[18:55] <didrocks> also some contributors are really awesome and help pushing the project further :)
[18:55] <didrocks> [SLIDE 10]
[18:55] <didrocks> so, taking questions now in the 5 remaining minutes
[18:56] <didrocks> QUESTION: Is there an easy way to try fresh quickly on Karmic? The straightforward setup.py build/install way results in a lot of errors.
[18:56] <didrocks> right, there is a bug logged about that
[18:56] <didrocks> I don't see anything preventing for backporting to karmic
[18:56] <didrocks> BUT
[18:56] <didrocks> you need last distutils-extra version
[18:57] <didrocks> (else you can't add depends, nor you have the automated changelog goodness)
[18:57] <didrocks> and I probably have to fix setup.py
[18:57] <didrocks> I think I'll try to provide a package in the quickly ppa for karmic
[18:57] <didrocks> QUESTION: Is there a ppa-daily of Quickly for auto installing the last one?
[18:58] <didrocks> there is a daily ppa, jcastro was the owner IIRC, I don't know the current state to be honest
[18:58] <didrocks> I think export PATH is more convenient :)
[18:58] <didrocks> and that's what I do everyday :)
[18:59] <didrocks> well, of course the day we can do "quickly release lucid", I think Quickly will take some thousands lines of code :)
[18:59] <jcastro> The dailies work, if they don't work for you just poke me.
[18:59] <didrocks> but as I still like my job, it won't happen :)
[18:59] <didrocks> I guess it's time :)
[18:59] <didrocks> and thanks jcastro
[19:00] <didrocks> thanks all for your attention
[19:00] <didrocks> now, stage is to you rickspencer3
[19:00] <didrocks> and thanks for having launched Quickly once more :)
[19:01] <rickspencer3> hi all
[19:01] <rickspencer3> ready for some pygame stuff?
[19:02] <rickspencer3> great
[19:02] <rickspencer3> as usual, I got my notes ready before hand and stuck them on the wiki:
[19:02] <rickspencer3> https://wiki.ubuntu.com/UbuntuOpportunisticDeveloperWeek/PyGameClassNotes
[19:03] <rickspencer3> so I'll go through each section and take questions
[19:03] <rickspencer3> Pygame is a library for making arcade style sprite games
[19:03] <rickspencer3> It features very easy blitting and colision detection
[19:03] <rickspencer3> I have some sample code to help with understanding pygame here:
[19:03] <rickspencer3> https://code.edge.launchpad.net/~rick-rickspencer3/pygame-template/trunk
[19:03] <rickspencer3> I think you can go:
[19:04] <rickspencer3> bzr branch lp:pygame-template too
[19:05] <rickspencer3> note that some of this code is a bit old, and I need to reformat it and such
[19:05] <rickspencer3> but it
[19:05] <rickspencer3> s failry readable
[19:05] <rickspencer3> however, it will eventually be a quickly template, hopefully in time for lucid
[19:05] <rickspencer3> if you want to grab that it might help you follow the class a bit, but it is not required
[19:05] <rickspencer3> it comes with some basic game play that you can study and modify
[19:05] <rickspencer3> essentially, it is kind of like asteroids
[19:05] <rickspencer3> you control the black triangle in the middle, and there are two enemies
[19:05] <rickspencer3> Of course you will want some docs
[19:05] <rickspencer3> Pygame has good docs here:
[19:05] <rickspencer3> http://www.pygame.org/docs/
[19:06] <rickspencer3> before we discuss how to set up a game
[19:06] <rickspencer3> any questions?
[19:06] <rickspencer3> ok, then let us rock
[19:06] <rickspencer3> so, you're going to set up a game
[19:06] <rickspencer3> first thing you need to do is set up a game surface
[19:07] <rickspencer3> and do other initalizations
[19:07] <rickspencer3> so ..
[19:07] <rickspencer3> initialize pygame libraries
[19:07] <rickspencer3> pygame.font.init()
[19:07] <rickspencer3> pygame.mixer.init()
[19:07] <rickspencer3> (assuming you are using fonts and sound of course)
[19:07] <rickspencer3> then create a screen
[19:07] <rickspencer3> the screen will be the surface on which your sprites will be drawn, essentially where your game will occur
[19:07] <rickspencer3> screen = pygame.display.set_mode((800, 480))
[19:08] <rickspencer3> that's for an 800 x 400 pixel game
[19:08] <rickspencer3> also, create a couple of variable you will need later
[19:08] <rickspencer3> like a background image
[19:08] <rickspencer3> background = pygame.image.load(path_to_background)
[19:08] <rickspencer3> notice the image is a PyGame image
[19:08] <rickspencer3> and a clock
[19:08] <rickspencer3> clock = pygame.time.Clock()
[19:08] <rickspencer3> you'll see why we need the clock next
[19:09] <rickspencer3> pygame games use a good old fashioned input loop
[19:09] <rickspencer3> don't know if you all ever programmed with an event loop
[19:09] <rickspencer3> but it was very common for writing GUI apps back around when dinosaurs used computers
[19:09] <rickspencer3> essentially, you tell your app to keep looping
[19:09] <rickspencer3> and whenever it goes through the loop do a few things
[19:10] <rickspencer3> 1. respond to user input
[19:10] <rickspencer3> 2.update data for any sprites on the screen
[19:10] <rickspencer3> this includes seeing if any sprites have collided
[19:10] <rickspencer3> 3. redraw everything
[19:10] <rickspencer3> let's look at setting up a game loop
[19:10] <rickspencer3>  while 1:
[19:10] <rickspencer3>   clock.tick(15)
[19:10] <rickspencer3>   if ControllerTick() == 0:
[19:10] <rickspencer3>    return
[19:10] <rickspencer3>   if not game.paused:
[19:10] <rickspencer3>    ViewTick()
[19:10] <rickspencer3>    if CheckCollisions() == 0:
[19:10] <rickspencer3>     return
[19:10] <rickspencer3> you can see this code in the crashteroids file at line 169
[19:11] <rickspencer3> so first, the loop just runs and runs until etiher ControllerTick or CheckCollisions returns 0
[19:11] <rickspencer3> the first line in the loop basically says to have 15 frames per second
[19:11] <rickspencer3> this is not like a sleep function where the argument says how long to sleep
[19:11] <rickspencer3> make sure that you pick a number that is low enough that a lower powered computer can keep up, if you care about that kind of thing
[19:11] <rickspencer3> The next line calls ControllerTick()
[19:11] <rickspencer3> This function checks for user input, which I will explain in a moment, and the updates all the game data
[19:11] <rickspencer3> this is a function that *you* write
[19:12] <rickspencer3> it's not built into PyGame
[19:12] <rickspencer3> then next in the loop
[19:12] <rickspencer3> assuming that the game is not paused, it will go ahead and update the view and do collision detection
[19:12] <rickspencer3> The reason that controllertick is always called is because this function controlls pausing and unpausing of the game
[19:12] <rickspencer3> if you didn't call it every time through, the user couldn't unpause
[19:12] <rickspencer3> we'll look at each of these functions in more detail
[19:12] <rickspencer3> but first, questions?
[19:13] <ClassBot> mhall119 asked: what file is that in?
[19:13] <rickspencer3> it's in crashteroids/bin/crashteroids
[19:13] <ClassBot> ryzrecreel asked: What kind of image formats can you use?
[19:13] <rickspencer3> dunno for sure
[19:13] <rickspencer3> I always use png
[19:14] <rickspencer3> ok, no more questions, so moving on
[19:14] <rickspencer3> let's start by handling user input
[19:14] <rickspencer3> pygame basically queues up input events
[19:14] <rickspencer3> you can then loop through them and respond to each event
[19:14] <rickspencer3> at line 93, you can see how the loop is set up
[19:14] <rickspencer3>  for event in pygame.event.get():
[19:14] <rickspencer3>   if event.type == pygame.QUIT:
[19:14] <rickspencer3>    return 0
[19:14] <rickspencer3> pygame.QUIT is called when the window closes or such
[19:14] <rickspencer3> of course you could also do something smart and save game state or such
[19:15] <rickspencer3> but this code returns 0, which causes the main event loop to quit
[19:15] <rickspencer3> now, let's say what I want to do is make the ship go forward when the user presses the j key
[19:15] <rickspencer3> (which is what crashteroids does by default)
[19:15] <rickspencer3> first I ask what kind of event it was
[19:15] <rickspencer3>   if event.type == pygame.KEYDOWN:
[19:15] <rickspencer3> yup, I want to respond to key down events
[19:16] <rickspencer3> so this I'll write some code here
[19:16] <rickspencer3> and then if it was a key event, what key was pressed
[19:16] <rickspencer3>     if event.key == pygame.K_l:
[19:16] <rickspencer3>      #do something
[19:16] <rickspencer3> oops
[19:16] <rickspencer3> that's for l key :)
[19:16] <rickspencer3> I guess l is for move, and j is to shoot
[19:17] <rickspencer3> in any case, you can probably guess that the correct event.key is pygame.k_j to respond to the j key
[19:17] <rickspencer3> ;)
[19:17] <rickspencer3> you can see the whole tree of if, else statements starting at line 89
[19:17] <rickspencer3> there are also events for the mouse and joysticks even
[19:17] <rickspencer3> so it's easy to create games that aren't only using the keyboard if you want
[19:17] <rickspencer3> so that's how to handle input
[19:17] <rickspencer3> let's look at sprites, but first, any questions?
[19:18] <ClassBot> mhall119 asked: any kind of vector graphics?
[19:18] <rickspencer3> could be, but PyGame is really sprite based
[19:18] <rickspencer3> vector graphics is how games like asteroids and battlezone, and starcastle and stuff were created
[19:18] <rickspencer3> but sprites are when you use images
[19:19] <ClassBot> M49 asked: Does pygame have any dialog for key configuration?
[19:19] <rickspencer3> not that I know of
[19:19] <rickspencer3> that would be a nice thing to add to a quickly template though, wouldn't it
[19:19] <rickspencer3> I would guess that you would just use PyGtk for this
[19:19] <rickspencer3> create it yourself
[19:19] <rickspencer3> ok
[19:19] <rickspencer3> let's move on to sprites
[19:20] <rickspencer3> A sprite is basically an image in an arcade game
[19:20] <rickspencer3> pygame handles blitting for you, which is quite nice
[19:20] <rickspencer3> I'll discuss blitting in a bit
[19:20] <rickspencer3> If you wrote games long ago, you may remember rendering a sprite strip to an offscreen graphics world
[19:20] <rickspencer3> and then selecting bits of that strip and copying them to the onscreen graphics world
[19:20] <rickspencer3> pygame does not reqiure that at all
[19:20] <rickspencer3> it is much more fun and easy
[19:21] <rickspencer3> you just subclass the Sprite class
[19:21] <rickspencer3> one key thing a sprite has is an Pygame.Image member, called image
[19:21] <rickspencer3> I usually like to keep the original image around, as if you keep rotating the image and such, it will get more and more distorted over time
[19:22] <rickspencer3> so when I create a sprite object, I set up the image member like this:
[19:22] <rickspencer3>   self.masterImage = pygame.image.load(path_to_image_file)
[19:22] <rickspencer3>   self.image = self.masterImage
[19:22] <rickspencer3> this is all in the BastSprite class, btw, if you want to see the code in situ
[19:22] <rickspencer3> a sprite also has a "virtual" function, called update
[19:22] <rickspencer3> update is supposed to be called to tell a sprite to update it's data for a tick
[19:22] <rickspencer3> you set things like the sprite's x, y coordinates in this function, and such
[19:22] <rickspencer3> all your sprites should use this because you can then add a sprite to a RenderUpdates sprite group
[19:23] <rickspencer3> don't add your own custom named method to do this, or you will lose a lot of benefits of PyGame
[19:23] <rickspencer3> call update for that group, which will call update for each sprite
[19:23] <rickspencer3> you create a sprite group like this:
[19:23] <rickspencer3> enemies = pygame.sprite.RenderUpdates()
[19:24] <rickspencer3> and then you can add an sprite to that group
[19:24] <rickspencer3> enemies.add(create_enemy())
[19:24] <rickspencer3> you can also empty a sprite group
[19:24] <rickspencer3> enemies.empty()
[19:24] <rickspencer3> useful when you are resetting a level or something
[19:24] <rickspencer3> as we'll see later, sprite groups also help lots with collision detection
[19:24] <rickspencer3> back to sprites though
[19:24] <rickspencer3> so you have an image on a sprite
[19:24] <rickspencer3> you also need to define an x and y for your sprite
[19:25] <rickspencer3> I in my sprite subclass, I might set x and y randomly like this:
[19:25] <rickspencer3>    self.x = random.randint(0,300)
[19:25] <rickspencer3>    self.y = random.randint(0,140)
[19:25] <rickspencer3> (only when the sprite is created, of course)
[19:25] <rickspencer3> but then on each call to update(), just change the x and/or y if the sprite is moving
[19:25] <rickspencer3> sprites also have a "kill()" member function
[19:25] <rickspencer3> calling kill causes the sprite to be removed from the playing surface
[19:25] <rickspencer3> questions before we talk about updating the display?
[19:26] <ClassBot> mhall119 asked: can you change the image on update?
[19:26] <rickspencer3> yes
[19:26] <rickspencer3> absolutely
[19:26] <rickspencer3> you can also rotate it and other things
[19:26] <rickspencer3> my sprites usually have an "explode" method
[19:27] <rickspencer3> which causes a stage of an explosion to be displayed with each tick in update
[19:27] <rickspencer3> so if you look at crashteroids, changing images on update is how I get the explosion effect
[19:27] <ClassBot> mhall119 asked: Like, to animate your sprite
[19:27] <rickspencer3> totally
[19:27] <rickspencer3> like if you had a tank
[19:27] <rickspencer3> and it was going to shoot a missle
[19:28] <rickspencer3> you could have swap in images that make it look like a little guy loading the turret or something
[19:28] <ClassBot> mhall119 asked: can you layer images to make a single sprite image?
[19:28] <rickspencer3> hmmm
[19:28] <rickspencer3> not that I know of
[19:28] <rickspencer3> I don't think a sprite can composit images like that
[19:29] <rickspencer3> ok
[19:29] <rickspencer3> so now you have your event loop running, your game surface set up, and some sprites created
[19:29] <rickspencer3> now we need to actually draw the sprites
[19:29] <rickspencer3> for sprites that are not in a sprite group, we need to blit them
[19:29] <rickspencer3> fortunately this does not involve the crazy gworld hackery of days of hold
[19:29] <rickspencer3> pygame gives us a blit method
[19:29] <rickspencer3> blitting is essentially the act of repainting parts of the screen that have changed
[19:29] <rickspencer3> without blitting, the whole screen repaints and appears to flash
[19:30] <rickspencer3> so to blit the blackgroud, we'll use the screen to blit
[19:30] <rickspencer3> remember when we created teh screen object? now it's time to use it
[19:30] <rickspencer3> screen.blit(background, [0,0])
[19:30] <rickspencer3> I think that blitting the background like this basically repaints the whole background image over everything
[19:30] <rickspencer3> if you are tuning for a very slow platform, or a game with lots and lots of sprites, you may not want do it this way or you get flashing
[19:30] <rickspencer3> in those cases you might need to track the parts of the background exposed by moving sprites
[19:31] <rickspencer3> this is a bit of work, but probably will not be necessary for you to do
[19:31] <rickspencer3> I certainly have never run into trouble with this
[19:31] <rickspencer3> for all I know, blit() is smart enough to not cause flashing
[19:31] <rickspencer3> to blit an individual sprite, you have to tell the screen the image to use and the rect, or xy coords and dimensions, for hte sprite to blit
[19:31] <rickspencer3> So if we have a sprite object called "g", we blit it like this:
[19:31] <rickspencer3> screen.blit(g.image, g.rect)
[19:31] <rickspencer3> sprites in a sprite group are a bit easier to blit
[19:32] <rickspencer3> you can tell the sprite group to blit them all:
[19:32] <rickspencer3>  enemies.draw(screen)
[19:32] <rickspencer3> this blits all the enemies for you
[19:32] <rickspencer3> we do this each time through the loop
[19:33] <rickspencer3> in ViewTick()
[19:33] <rickspencer3> question before we discuss collision detection?
[19:33] <ClassBot> w1nGNUtz asked: will you explain anitmations? I'd like to understand how to animate an sprite using the clock
[19:33] <rickspencer3> yeah
[19:33] <rickspencer3> so let's say you want have an animation that shows a guy walking
[19:33] <rickspencer3> create enough images to show taking a step smoothly
[19:34] <rickspencer3> I'll guess it will take 8 frames to show smooth step
[19:34] <rickspencer3> in the sprites update method
[19:34] <rickspencer3> swap in the next image each time through
[19:34] <rickspencer3> for example
[19:34] <rickspencer3> when I show a guy exploding
[19:34] <rickspencer3> I have 8 frames or so showing the explosion
[19:35] <rickspencer3> named ship_explode_1.png to ship_explode_8.png
[19:35] <rickspencer3> (or named similary, I forget exactly what I named them)
[19:35] <rickspencer3> then I keep track in the update method of a counting variable
[19:35] <rickspencer3> let me get the exact code, hold on
[19:36] <rickspencer3>   if self.exploding:
[19:36] <rickspencer3>    #do an explosion image for each tick
[19:36] <rickspencer3>    self.explodestage += 1
[19:36] <rickspencer3>    e = self.explodestage
[19:36] <rickspencer3>    if e < 8:#there are 7 explosion images
[19:36] <rickspencer3>     e = str(e)
[19:36] <rickspencer3>     self.masterImage = pygame.image.load(crashteroidsconfig.guy_explode_stage + e  + ".png")
[19:36] <rickspencer3>     self.updateImage()
[19:36] <rickspencer3> updateImage is a function I wrote that rotates the image and does some other stuff
[19:37] <rickspencer3> but essentially sets the sprites image member, like this:
[19:37] <rickspencer3> self.image = pygame.transform.rotate(self.masterImage,self.orientation)
[19:37] <rickspencer3> (if you weren't doing rotation and stuff, you could just assign the new image directly)
[19:37] <ClassBot> mhall119 asked: does pygame offer any kind of "damage" data to tell what parts of the screen should be repainted?
[19:38] <rickspencer3> I don't know
[19:38] <rickspencer3> I always let the sprites blit() method take care of that for me
[19:38] <rickspencer3> I don't think you'll to track this
[19:38] <rickspencer3> back in the day, you would always track the previous rect for the sprites location
[19:38] <rickspencer3> so that you could repaint it with the background
[19:39] <rickspencer3> but I don't think PyGame requires this
[19:39] <ClassBot> gooomba asked: Is pygame also suited for non-arcade games like chess for example?
[19:39] <rickspencer3> yes
[19:39] <rickspencer3> it wuold be good for board games for sure
[19:40] <rickspencer3> ok, so collision detection
[19:40] <rickspencer3> so let's say when an enemy rams our guy, we want both to be killed
[19:40] <rickspencer3> but how to tell when an ememy hits?
[19:40] <rickspencer3> detecting overlapping sprites is called "collision detection" and is handled quite well by PyGame
[19:40] <rickspencer3> this saves you tons of work
[19:40] <rickspencer3> (believe me, tracking rects and writing code to detect overlapping rects is not fun or easy!)
[19:41] <rickspencer3> you can detect if two sprites have collided using pygame.sprite.spritecollide (), collideany, or groupcollide
[19:41] <rickspencer3> so let's see if our guy, called g, has collided with an enemy
[19:41] <rickspencer3>   e = pygame.sprite.spritecollideany(g, enemies)
[19:41] <rickspencer3> call this each tick
[19:41] <rickspencer3> I always have specific function to handle collision detection
[19:41] <rickspencer3> if the guy has not collided with any enemies, e will be None
[19:42] <rickspencer3> but when e is not None, that means boom
[19:42] <rickspencer3> "boom"
[19:42] <rickspencer3> let's say your guys shoots bullets
[19:42] <rickspencer3> those bullets will most likely be managed in a sprite group
[19:42] <rickspencer3> so we should also see if any enemies were killed by bullets
[19:42] <rickspencer3> hits_dict = pygame.sprite.groupcollide(bullets, enemies, False, False)
[19:42] <rickspencer3> since we are asking for a collision between groups of sprites
[19:42] <rickspencer3> here you get back a dictionary
[19:42] <rickspencer3> the keys are sprites from the first sprite group
[19:42] <rickspencer3> and the values are keys from the second sprite group
[19:42] <rickspencer3> so then we can just go through and kill each bullet and enemy for the collision:
[19:43] <rickspencer3>    for b in hits_dict:
[19:43] <rickspencer3>     for e in hits_dict[b]:
[19:43] <rickspencer3>      e.kill()
[19:43] <rickspencer3>      b.kill()
[19:43] <rickspencer3> ok, next and last section is on playing sounds
[19:43] <rickspencer3> any questions first?
[19:43] <ClassBot> mhall119 asked: does pygame have any kind of scene-graph, to animate sprites without writing a whole bunch of python code?
[19:43] <rickspencer3> if I know what that meant, I would give you a pithy answer
[19:43] <rickspencer3> unfortunately, I have to say "I don't know"
[19:44] <ClassBot> M49 asked: Does it track only bounding boxes or does it use trasparency information from sprites?
[19:44] <rickspencer3> the bounding box one
[19:44] <rickspencer3> actually, you can set the rect for the sprite specifically
[19:44] <rickspencer3> I often set the rect for the sprite to be slightly smaller than the image itself
[19:44] <rickspencer3> this give a nice effect where two sprites can just touch
[19:44] <rickspencer3> and not explode
[19:44] <rickspencer3> it gives a nice "near miss" effect
[19:45] <rickspencer3> it also lets you tune each rect to different shaped sprites
[19:45] <rickspencer3> note that the rect is only used for collision detection so far as I know
[19:45] <rickspencer3> so the whole image will always be displayed
[19:46] <rickspencer3> ok, finally, sounds
[19:46] <rickspencer3> we use the Pygame.mixer module to manage sounds
[19:46] <rickspencer3> we need to initialize it before we use it:
[19:46] <rickspencer3> pygame.mixer.init()
[19:46] <rickspencer3> now I'll load an explosion sound to play when my guy explodes:
[19:46] <rickspencer3> self.explosionSound = pygame.mixer.Sound(path_to_sound_file)
[19:47] <rickspencer3> let's assume this sound is a bit loud, we can adjust the volume as we like:
[19:47] <rickspencer3>   self.explosionSound.set_volume(.2)
[19:47] <rickspencer3> then we can play the sound:
[19:47] <rickspencer3>    self.explosionSound.play()
[19:47] <rickspencer3> we can stop it too if it's going too long:
[19:47] <rickspencer3>    self.explosionSound.stop()
[19:47] <rickspencer3> the mixer module is quite rich
[19:47] <rickspencer3> there are channels, fades, and all kinds of stuff
[19:48] <rickspencer3> so
[19:48] <rickspencer3> that was the last "chapter" for the class
[19:48] <rickspencer3> we're a bit early
[19:48] <rickspencer3> any questions?
[19:48] <ClassBot> gooomba asked: what are the "False"-arguments in groupcollide() for?
[19:48] <rickspencer3> shucks, I forget
[19:48]  * rickspencer3 looks at docs
[19:49] <rickspencer3> huh
[19:49] <rickspencer3> http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.groupcollide
[19:49] <rickspencer3> no longer seems part of the API
[19:49] <rickspencer3> I guess I can just remove that from the template
[19:50] <ClassBot> mhall119 asked: what audio formats does mixer support?
[19:50] <rickspencer3> I know ogg and wav
[19:50] <rickspencer3> don't know what else, sorry
[19:51] <rickspencer3> there are nine minutes left
[19:51] <rickspencer3> any last questions, requests?
[19:51] <rickspencer3> (otherwise I'll grab some soda and get ready for my next session ;) )
[19:52] <ClassBot> oskude asked: how do i use the examples on that pygame site ?
[19:52] <rickspencer3> I'm not sure what you are asking specifically
[19:52] <rickspencer3> but I don't think they are set up as runable samples, but rather like code snippets
[19:53] <rickspencer3> I used those samples heavily back when I was learning PyGame tough
[19:53] <rickspencer3> ok, looks like no more questions
[19:53] <rickspencer3> please feel free to join us in #quickly
[19:54] <rickspencer3> any feedback on the PyGame template and how to improve it, what's wrong with it, etc...
[19:54] <rickspencer3> is much appreciated
[19:54] <rickspencer3> thanks all!
[20:02] <rickspencer3> hi all
[20:02] <rickspencer3> soooo
[20:02] <rickspencer3> I'm here to talk about photobomb
[20:02] <rickspencer3> jono thought some folks might be interested in hearing about some of the technology that I used and such
[20:03] <rickspencer3> to make it easier to walk through, I put some screenshots and some notes:
[20:03] <rickspencer3> here:
[20:03] <rickspencer3> http://theravingrick.blogspot.com/2010/03/photobomb-featured-app-for-opp-dev-week.html
[20:04] <rickspencer3> shall I begin with photobomb?
[20:05] <rickspencer3> I wrote the first iteration of Photobomb one Saturday afternoon.
[20:05] <rickspencer3> does everyone know what it does?
[20:05] <rickspencer3> it's basically a hacked together photo editor
[20:06] <rickspencer3> that let's you mash up images from sources like your feeds, your computer, the web, your web cam, etc...
[20:06] <rickspencer3> do some fun stuff
[20:06] <rickspencer3> and then you can save the image or tweet it
[20:06] <rickspencer3> I wrote this totally just for the fun of it in my spare time
[20:06] <rickspencer3> during January, I set the goal of writing one new feature a night
[20:06] <rickspencer3> so I got pretty far with it that way
[20:06] <rickspencer3> of course, it's a bit buggy still
[20:07] <rickspencer3> but it's kinda fun to use
[20:07] <rickspencer3> anyone who wants to contribute to it, fork it, whatever
[20:07] <rickspencer3> by all means, have a go
[20:07] <rickspencer3> anyway ...
[20:07] <rickspencer3> I used Quickly to get the project started, so it was just a matter of laying out some UI in Glade, and then figuring out how to manipulate images.
[20:07] <rickspencer3> I used Python Imaging Library (PIL) to create a cropped version of that little squirrel, and to paste it onto the picture.
[20:08] <rickspencer3> PIL is a complete and power library. It was a bit tough figuring out the masking to crop the squirrel image as desired, but I eventually managed.
[20:08] <rickspencer3> I ended up moving away from PIL, but from what I saw, I was impressed
[20:08] <rickspencer3> any questions do far?
[20:09] <ClassBot> mhall119 asked: where can we get the code?
[20:09] <rickspencer3> it's in a junk branch
[20:09]  * rickspencer3 gets
[20:09] <rickspencer3> https://code.edge.launchpad.net/~rick-rickspencer3/+junk/photobomb
[20:09] <rickspencer3> party on!
[20:09] <rickspencer3> I think it might be in my ppa too
[20:10] <rickspencer3> ok
[20:10] <rickspencer3> so following along to the next screen shot
[20:10] <rickspencer3> I added the ability to choose an image to stick in there
[20:11] <rickspencer3> and photobomb with that little squirrel
[20:11] <rickspencer3> It turned out to be tedious to write code to open an image file.
[20:11] <rickspencer3> So I added a prompt to quickly.widgets to handle opening files.
[20:11] <rickspencer3> Having your own library of reusable widgets is quite a luxury.
[20:11] <rickspencer3> if you look closely at the screenshot ...
[20:11] <rickspencer3> Note that I didn't know the gtk.FileChooser API that well, so made a couple of early mistakes, such as handling the existing file replace functionality myself.
[20:11] <rickspencer3> Didn't realize that the API could handle it
[20:12] <rickspencer3> but in any case, the shell of photobomb is PyGtk of course
[20:12] <rickspencer3> and I had to learn a bit about some areas of Gtk that I hadn't used too much
[20:12] <rickspencer3> any questions about that one?
[20:13] <ClassBot> mhall119 asked: Did you already know Glade before you started this?
[20:13] <rickspencer3> oh yes
[20:13] <rickspencer3> quite
[20:13] <rickspencer3> at first, you think Glade is your enemy
[20:13] <rickspencer3> but after a while, you learn it is our friend
[20:13] <rickspencer3> but Glade can be a bit hard to learn
[20:14] <rickspencer3> and it isn't designed to do everything
[20:14] <rickspencer3> so writing gtk.UIBuilder code is still part of hte process
[20:14] <rickspencer3> quickly makes this a bit easier, by giving each window a builder function
[20:14] <rickspencer3> I mean builder member
[20:14] <rickspencer3> so you can go:
[20:14] <rickspencer3> self.builder.get_object("hbox1").pack_start(my_widget)
[20:15] <ClassBot> mhall119 asked: does photobomb run on Karmic?  or just Lucid?
[20:15] <rickspencer3> well
[20:15] <rickspencer3> it's packaged for Lucid
[20:15] <rickspencer3> because it uses quickly-widgets
[20:15] <rickspencer3> which is in the quidgets project
[20:15] <rickspencer3> however, if you want to run it
[20:15] <rickspencer3> it shouldn't be too hard
[20:15] <rickspencer3> just branch photobomb
[20:16] <rickspencer3> then branch quidgets
[20:16] <rickspencer3> then stick quidgets/quickly dir in photobomb/photobomb, and it might work
[20:17] <rickspencer3> or just put quidgets somewhere on disk and set the python path when you run it
[20:17] <rickspencer3> !PYTHONPATH="~/quidgets/quickly" python photobomb/bin/photobomb
[20:17] <rickspencer3> for example
[20:17] <ClassBot> mhall119 asked: Any good tutorials on learning to make Glade my friend?
[20:17] <rickspencer3> mmm
[20:17] <rickspencer3> not really
[20:18] <rickspencer3> there are a bunch of tutorials
[20:18] <rickspencer3> but many are out of date, since PyGtk moved form LibGlade to UI Builder
[20:18] <rickspencer3> if you have Quickly installed, there is a bit in there to help you get started
[20:18] <rickspencer3> #ubuntu-app-devel is a good place to ask specific gladey questions
[20:19] <rickspencer3> unless it's about workign with a quickly template, in which case #quickly might be better
[20:19] <rickspencer3> ok
[20:19] <rickspencer3> so next section
[20:19] <rickspencer3> When I tried to implement some captioning and other features, I came to realize that PIL was just not designed for the kind of stuff I wanted to do with it.
[20:19] <rickspencer3> When I switched to GooCanvas, it became much easier to add features.
[20:19] <rickspencer3> I was able to add resizing, rotation, and drag to move in a matter of an hour or so.
[20:20] <rickspencer3> A couple of days later I fixed an issue with dragging rotated items that resulted from the craziness involved with items in goocanvas maintaining their own coordinate system seperate from the goocanvas they are in.
[20:21] <rickspencer3> questions about PIL, GooCanvas, or anything else so far?
[20:21] <ClassBot> mhall119 asked: it doesn't look like you did much with glade, do you find yourself doing most UI building directly in python?
[20:21] <rickspencer3> yes
[20:22] <rickspencer3> I genreally use glade to set up containers
[20:22] <rickspencer3> then I target those container from code
[20:22] <rickspencer3> especially for custom images and such'
[20:22] <rickspencer3> also, I use subclassing a lot
[20:22] <rickspencer3> and I haven't done much work to make my own widgets work within glade
[20:22] <rickspencer3> ok
[20:22] <rickspencer3> I could then go and the ability for users to use a pen tool in photobomb.
[20:23] <rickspencer3> This required managing mouse events and creating a PolyLine object from the collected mouse points.
[20:23] <rickspencer3> Later I found that a Path worked better than a PolyLine for creating the Ink. I still have not figured out how to add points to an existing Path.
[20:23] <rickspencer3> As a result, Photobomb recreates the Path with each mouse move. This gets slow if the Path is not short.
[20:23] <rickspencer3> I did a session on GooCanvas yesterday, but can take some quick questions on it today
[20:24] <rickspencer3> I used the gtk.ColorChooserDialog for color selection.
[20:24] <rickspencer3> I also added color button and ink width button.
[20:24] <rickspencer3> originally, These hosted a goocanvas, and I just added a path to each and set the properties of the Path to display the selected color and width.
[20:25] <rickspencer3> later I changed the color button to change it's background to show the correct color
[20:25] <rickspencer3> I mean, selected color
[20:25] <rickspencer3> there's a "color selection" button in Gtk, but it didn't quite suite my UI
[20:25] <rickspencer3> in terms of getting settings from users
[20:25] <rickspencer3> I had already created quickly.prompts to make it easy to collect a line width from the user. (quickly.prompts.integer()).
[20:26] <rickspencer3> I could handle this with a GooCanvas.Widget object embedded in situ, but that's a lot of work and using quickly.prompts.string() is a one-liner.
[20:26] <rickspencer3> questions so far?
[20:26] <rickspencer3> following along, the next thing I implemented was adding text to the goocanvas
[20:26] <rickspencer3> I added a gtk.STOCK_EDIT button to collect text from the user.
[20:27] <rickspencer3> well, that was just to manage the correct icon
[20:28] <rickspencer3> since i wanted buttons to be compact
[20:28] <rickspencer3> I used toolbar buttons, and just setting them to stock worked well
[20:28] <rickspencer3> later, I had to hack around some limitations to how "stock" works
[20:29] <rickspencer3> I used a quickly.prompts.string() to collect the string to display from the user.
[20:29] <rickspencer3> next I added the some feedback about the current selection
[20:29] <rickspencer3> To display selection, I simply used a GooCanvas.Rect with a bit of buffer around the selected object.
[20:30] <rickspencer3> I could have added stock selection points from gtk, but that sounded like a lot of work.
[20:30] <rickspencer3> questions so far?
[20:32] <rickspencer3> I added a bit of opacity to the selection box. This works better, as you can see what is behind the selected item
[20:32] <rickspencer3> Then I added opacity to other selectable items.
[20:32] <rickspencer3> I sniped some code from segphault's grabbersnap app to figure out how to set up rgba colors.
[20:33] <rickspencer3> It's a bit of a hack, but seems to work well.
[20:33] <rickspencer3> At this point in the project I also switched from having the user open individual images to add, to iterating through the Pictures directory and adding a button for each encountered image.
[20:33] <rickspencer3> I accomplished this asynchronously by putting this on a thread, using quickly.widgets.asynch_task_progressbox()
[20:33] <rickspencer3> This simplifies threaded coding a bit, but I am finding that threads + Python + PyGtk don't work out as well as I want, no matter how carefully I code it
[20:33] <rickspencer3> happy to take questions now if you've gottem'
[20:34] <rickspencer3> so moving on to the web cam feature
[20:34] <rickspencer3> Web Cam support is an important feature for Photobomb,
[20:34] <rickspencer3> but the available APIs looked daunting.
[20:35] <rickspencer3> That is, until I discovered that Pygame had a simplified web cam interface.
[20:35] <rickspencer3> I created a quickly.widget to handle web cam integration and added that widget to Photobomb.
[20:35] <rickspencer3> Note that this means quickly.widgets depends on PyGame.
[20:35] <rickspencer3> I think I shall move the webcam widget out of the default install and make it available in some other manner.
[20:35] <rickspencer3> Having another source of images meant that I needed to add a gtk.Notebook to handle switching between the two sources.
[20:36] <rickspencer3> I later went on to use icons for the notebook tabs, but labels worked fine when there were only 2 sources
[20:36] <rickspencer3> Questions so far?
[20:36] <ClassBot> w1nGNUtz asked: It seems some programs take too long to evolve. How could it be if you manage to do this so quickly?
[20:36] <rickspencer3> hmm
[20:36] <rickspencer3> interesting quetsion
[20:37] <rickspencer3> I guess I just did one new feature a night
[20:37] <rickspencer3> I refactored as I went
[20:37] <rickspencer3> to support adding new features
[20:37] <rickspencer3> this was a really fun project to work on
[20:37] <rickspencer3> so I don't know
[20:37] <rickspencer3> I guess PyGtk + GooCanvas are just really productive libraries
[20:38] <ClassBot> titeuf_87 asked: is there any reasons you went with pygame instead of gstreamer?
[20:38] <rickspencer3> for the simple reason that I discovered the PyGame api, and it looked like I could do it
[20:38] <rickspencer3> I would switch to gstreamer if I saw sample code that convinced me it would be easy to do
[20:38] <rickspencer3> I would love to break the PyGame dependency
[20:39] <rickspencer3> ok
[20:39] <rickspencer3> so Web image searching
[20:39] <rickspencer3> I added this next
[20:39] <rickspencer3> so you could search for a term, and then get back a list of related images
[20:39] <rickspencer3> I ended up using the Yahoo! image search api for this
[20:40] <rickspencer3> for the sole reason that the API was dead simple to use and well documented
[20:40] <rickspencer3> around this time, someone picked up another program I wrote, and added good support for extracting image urls from a web page
[20:41] <rickspencer3> so I sniped that code and made it so that if you entered a URL
[20:41] <rickspencer3> instead of doing an image search, it would scrape images from that page
[20:41] <rickspencer3> while I was at it, I also let the user type in a url directly to a photo and loaded that
[20:41] <rickspencer3> I think the web image search functionality is really fun to use
[20:41] <rickspencer3> like, "it would be funny if a picture of a cat were here"
[20:42] <rickspencer3> type "cats"
[20:42] <rickspencer3> and then you can get the cat, use the clipping tool, and drag it where you want
[20:42] <rickspencer3> I'll pause to see if there are questions now
[20:42] <rickspencer3> ok
[20:43] <rickspencer3> so the next major change I made was from toolbar buttons to normal buttons
[20:43] <rickspencer3> the motivation was this:
[20:43] <rickspencer3> Changing size, rotation, and opacity required the user to click the button once for each increment.
[20:43] <rickspencer3> So rotating something to be upside required the user to go "click click click click", etc...
[20:43] <rickspencer3> What I wanted was the user to click the button, and hold it down as the image rotated, and then to stop when it was positioned as desired.
[20:43] <rickspencer3> Sadly, there is no "key-down" event on gtk.Toolbars.
[20:43] <rickspencer3> well, gtk.ToolButtons, I mean
[20:43] <rickspencer3> So I had to switch Photobomb from using toolbars to using regular gtk.Button.
[20:44] <rickspencer3> I achieved the layout by using a gtk.Table
[20:44] <rickspencer3> I also created a new quickly.widget.PressAndHold widget to add press and hold functionality
[20:44] <rickspencer3> I accomplish the asynch behavior with gobject.timeout_add(250, self.__tick).
[20:44] <rickspencer3> At each tick the button emits a signal telling the consuming app to do something.
[20:44] <rickspencer3> Questions?
[20:45] <ClassBot> M49 asked: Does it check license metadata for pictures?
[20:45] <rickspencer3> nope
[20:45] <rickspencer3> that might be a nice feature to add though
[20:45] <rickspencer3> especially if this is something that concerns you
[20:46] <rickspencer3> but I don't think it's pertinent to the way I envisioned folks using photobomb
[20:46] <rickspencer3> basically, making funny pictures from themselves and their friends
[20:46] <rickspencer3> ok
[20:46] <rickspencer3> last section is on the Social Network Integration
[20:46] <rickspencer3> this was almost all achieved with Gwibber
[20:46] <rickspencer3> Because Gwibber uses desktopcouch to store messages in Lucid,
[20:47] <rickspencer3>  I could add the feature to grovel through the messages and extract images coming from social feeds to display.
[20:47] <rickspencer3> Of course, this will only work in Lucid ;)
[20:47] <rickspencer3> I also sniped Gwibber's fb credentials from desktopcouch, and used that and some FML to get images from Facebook.
[20:47] <rickspencer3> so your gwibber tab of the notebook loads up all the images in feeds you subscribe to, and also any images in facebook ...
[20:48] <rickspencer3> that are tagged with any of your friends so long as the image has been modified in the last 5 days
[20:48] <rickspencer3> I think this aspect of photobomb is really fun
[20:48] <rickspencer3> converging your personal feeds into an app that is designed to mash 'em all up
[20:48] <rickspencer3> I used the Gwibber API to add broadcasting Photobomb images.
[20:49] <rickspencer3> The GooCanvas renders a png that is saved to a temp location.
[20:49] <rickspencer3> Then pycurl uploads the image to imgur.com, which returns a url.
[20:49] <rickspencer3> Gwibber's GwibberPosterVBox to broadcast the URL.
[20:49] <rickspencer3> So that
[20:49] <rickspencer3> s the photobomb showcase
[20:49] <rickspencer3> I would love finish off photobomb sometime and let folks have fun with it
[20:49] <rickspencer3> but I've been a bit busy
[20:50] <rickspencer3> there are few bugs here and there, some of them quite annoying, as they involve frozen UI
[20:50] <rickspencer3> so, 10 minutes left
[20:50] <rickspencer3> happy to discuss anything now, answer any questions
[20:51] <rickspencer3> ok
[20:51] <rickspencer3> I'm going to call that a wrap, then
[20:51] <rickspencer3> thanks all for coming!
[20:51] <rickspencer3> and if anyone wants to contribute to photobomb in any way
[20:51] <rickspencer3> I am totally open to that'
[20:51] <rickspencer3> it's more fun working on these things together ;)