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