Re: Snow effect over a GtkWindow



Hi guys,
I'm here to share with you the script I created in order to achieve
the falling snow effect: I hope you enjoy it.

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""Show of how to create a full-screen transparent window used to reproduce
the effect of objects falling over your desktop.
"""

from __future__ import division
import sys
from math import sin
from random import random

import cairo
import gobject
import gtk
from gtk import gdk


class OverlayWindow(object):
    """Full-screen transparent window.
    """

    def __init__(self, symbol, color, nelem):
        """Constructor.

        Other than create a window to draw things, we have to generate a list
        of objects (3d-coordinates).

        Keywords:
            symbol symbol displayed on screen.
            color color of the symbol.
            nelem number of elements to display.
        """
        self.symbol = symbol
        self.color = map(lambda v: int(v, 16) / 255,
                         [color[:2], color[2:4], color[4:6]])
        self.bin = [[3 * random() - 1.5, 2 * random() - 1, 2 * random()]
                    for _ in xrange(nelem)]
        self.time = 0L

        screen = gdk.screen_get_default()

        # Create off-screen contexts.
        width, height = screen.get_width(), screen.get_height()
        ratio = width / height
        self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
        self.context = cairo.Context(self.surface)
        self.context.scale(width * 0.5 / ratio, height / 2)
        self.context.translate(ratio, 1)

        # Create a full-screen window specifying we are entirely responsible
        # for drawing the background of the widget.
        win = gtk.Window()
        win.set_app_paintable(True)
        #win.fullscreen()

        # Let's try to use a colormap supporting transparency
        colormap = screen.get_rgba_colormap()
        if colormap:
            win.set_colormap(colormap)

        win.connect('delete-event', gtk.main_quit)
        win.connect('expose-event', self.expose_cb)
        win.show()

        gobject.timeout_add(66, self.refresh, win)

    def expose_cb(self, widget, event):
        """Output the content of the ImageSurface on the window context.
        """
        context = widget.window.cairo_create()

        # clip the context in order to display only the exposed area
        context.rectangle(event.area.x, event.area.y,
                          event.area.width, event.area.height)
        context.clip()

        # make the background transparent
        context.set_operator(cairo.OPERATOR_SOURCE)
        context.set_source_rgba(0, 0, 0, 0)

        # paint the content of the off-screen surface
        #context.set_source_surface(self.surface)
        context.paint()

        return False

    def refresh(self, widget):
        """Draw things over the off-screen context, and queue a redraw.
        """
        width, height = widget.window.get_size()
        self.draw(self.context)
        widget.queue_draw()

        return True

    def draw(self, context):
        """Draw the objects over the window.

        The movement of each objects follows a sinusoidal behavior based on the
        time variable.

        Keywords:
            context context used to draw.
        """
        symbol = self.symbol
        time = self.time

        context.set_operator(cairo.OPERATOR_SOURCE)
        context.set_source_rgba(0, 0, 0, 0)
        context.paint()

        context.set_operator(cairo.OPERATOR_OVER)

        for (i, item) in enumerate(self.bin):
            x, y, z = item

            x1 = (x + .1 * sin(time + i / 10)) / z
            y1 = y / z
            font_size = .05 / z

            x_bearing, y_bearing, width, height = \
                    context.text_extents(symbol)[:4]
            context.move_to(x1 - width / 2 - x_bearing,
                            y1 - height / 2 - y_bearing)

            r, g, b = map(lambda v: v / (z + 1), self.color)
            context.set_source_rgb(r, g, b)
            context.set_font_size(font_size)
            context.save()
            context.rotate(time + i / 10)
            context.show_text(symbol)
            context.restore()

            y = -1 if y1 > 1 else y + 0.005
            item[1] = y

        self.time += 0.05


def main():
    overlay = OverlayWindow('â', '99CCFF', 200)
    gtk.main()


if __name__ == '__main__':
    main()


Regards,
Matteo

On Sun, Dec 27, 2009 at 8:10 PM, Matteo Landi <landimatte gmail com> wrote:
Thanks for the hint.

On Sun, Dec 27, 2009 at 6:41 PM, Liam R E Quin <liam holoweb net> wrote:
On Sun, 2009-12-27 at 16:27 +0100, Matteo Landi wrote:
Hi all,
for fun I'm trying to reproduce snowflakes falling down on my
fullscreen gtk app.

I'd say look at "xsnow" if it's still around.

Liam


--
Liam Quin - XML Activity Lead, W3C, http://www.w3.org/People/Quin/
Pictures from old books: http://fromoldbooks.org/
Ankh: irc.sorcery.net irc.gnome.org www.advogato.org





--
Matteo Landi
http://www.matteolandi.net/




-- 
Matteo Landi
http://www.matteolandi.net/



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]