Appendix: Migrating to pyglet 1.1
=================================

pyglet 1.1 introduces new features for rendering high performance graphics and
text, is more convenient to use, and integrates better with the operating
system.  Some of the existing interfaces have also been redesigned slightly to
conform with standard Python practice or to fix design flaws.  

.. contents::
    :local:

Compatibility and deprecation
-----------------------------

pyglet 1.1 is backward compatible with pyglet 1.0.  Any application that uses
only public and documented methods of pyglet 1.0 will continue to work
unchanged in pyglet 1.1.  If you encounter an issue where this is not the
case, please consider it a bug in pyglet and file an issue report.

Some methods have been marked *deprecated* in pyglet 1.1.  These methods
continue to work, but have been superceded by newer methods that are either
more efficient or have a better design.  The API reference has a complete list
of deprecated methods; the main changes are described in the next section. 

* Continue to use deprecated methods if your application needs to work with
  pyglet 1.0 as well as pyglet 1.1.
* New applications should not use deprecated methods.

Deprecated methods will continue to be supported in all minor revisions of
pyglet 1.x.  A pyglet 2.0 release will no longer support these methods.

Deprecated methods
------------------

The following minor changes have been made for design or efficiency reasons.
Applications which no longer need to support pyglet 1.0 should make the
appropriate changes to ensure the deprecated methods are not called.

The ``dispatch_events`` method on `Player` and the equivalent function on the
`pyglet.media` module should no longer be called.  In pyglet 1.1, media
objects schedule an update function on `pyglet.clock` at an appropriate
interval.  New applications using media are required to call
`pyglet.clock.tick` periodically.

The `AbstractImage` properties ``texture``, ``image_data``, and so on have
been replaced with equivalent methods ``get_texture``, ``get_image_data``,
etc.

The `ImageData` properties `data`, `format` and `pitch`, which together were
used to extract pixel data from an image, have been replaced with a single
function ``get_data``.  The `format` and `pitch` properties should now be used
only to determine the current format and pitch of the image.

The `get_current_context` function has been replaced with a global variable,
`current_context`, for efficiency.

New features replacing standard practice
----------------------------------------

pyglet 1.1 introduces new features that make it easier to program with, so the
standard practice as followed in many of the pyglet example programs has
changed.

Importing pyglet
^^^^^^^^^^^^^^^^

In pyglet 1.0, it was necessary to explicitly import each submodule required
by the application; for example::

    from pyglet import font
    from pyglet import image
    from pyglet import window

pyglet now lazily loads submodules on demand, so an application can get away
with importing just `pyglet`.  This is especially handy for modules that are
typically only used once in an application, and frees up the names ``font``,
``image``, ``window`` and so on for the application developer.  For example::

    window = pyglet.window.Window()

Application event loop
^^^^^^^^^^^^^^^^^^^^^^

Every application using pyglet 1.0 provides its own event loop, such as::

    while not window.has_exit:
        dt = clock.tick()
        update(dt)

        window.dispatch_events()
        window.clear()
        draw()
        window.flip()

Besides being somewhat repetitious to type, this type of event loop is
difficult to extend with more windows, and exausts all available system
resources, even if the application is not doing anything.

The new `pyglet.app` module provides an application event loop that is
less demanding of the CPU yet more responsive to user events.  A complete
application that opens an empty window can be written with::

    window = pyglet.window.Window()

    @window.event
    def on_draw():
        window.clear()

    pyglet.app.run()

Note the new `on_draw` event, which makes it easy to specify different drawing
functions for each window.  The `pyglet.app` event loop takes care of
dispatching events, ticking the clock, calling the draw function and flipping
the window buffer.

Update functions can be scheduled on the clock.  To have an update function be
called as often as possible, use `clock.schedule` (this effectively
degenerates into the older `dispatch_events` practice of thrashing the CPU)::
    
    def update(dt):
        pass
    clock.schedule(update)

Usually applications can update at a less frequent interval.  For example, a
game that is designed to run at 60Hz can use `clock.schedule_interval`::

    def update(dt):
        pass
    clock.schedule_interval(update, 1/60.0)

This also removes the need for `clock.set_fps_limit`.

Besides the advantages already listed, windows managed by the event loop
will not block while being resized or moved; and the menu bar on OS X can be
interacted with without blocking the application.

**It is highly recommended that all applications use the event loop.**  The
loop can be extended if you need to add additional hooks or integrate with
another package.  Applications continuing to use `Window.dispatch_events`
gain no advantage, but suffer from poorer response, increased CPU usage and
artifacts during window resizing and moving.

See `The application event loop` for more details.

Loading resources
^^^^^^^^^^^^^^^^^

Locating resources such as images, sound and video files, data files and fonts
is difficult to do correctly across all platforms, considering the effects of
a changing working directory and various distribution packages such as
setuptools, py2exe and py2app.

The new `pyglet.resource` module implements the correct logic for all these
cases, making it simple to load resources that belong to a specific module or
the application as a whole.  A resource path can be set that is indexed once,
and can include filesystem directories, Python module paths and ZIP files.

For example, suppose your application ships with a ``logo.png`` that needs to
be loaded on startup.  In pyglet 1.0 you might have written::

    import os.path
    from pyglet import image

    script_dir = os.path.dirname(__file__)
    logo_filename = os.path.join(script_dir, 'logo.png')
    logo = image.load(logo_filename)

In pyglet 1.1, you can write::

    logo = pyglet.resource.image('logo.png')

And will actually work in more scenarios (such as within a setuptools egg
file, py2exe and py2app).

The resource module efficiently packs multiple small images into larger
textures, so there is less need for artists to create sprite sheets themselves
for efficient rendering.  Images and textures are also cached automatically.

See `Application resources` for more details.

New graphics features
---------------------

The `pyglet.graphics` module is a low-level abstraction of OpenGL vertex
arrays and buffer objects.  It is intended for use by developers who are
already very familiar with OpenGL and are after the best performance possible.
pyglet uses this module internally to implement its new sprite module and the
new text rendering module.  The `Graphics` chapter describes this module in
detail.

The `pyglet.sprite` module provide a fast, easy way to display 2D graphics on
screen.  Sprites can be moved, rotated, scaled and made translucent.  Using
the *batch* features of the new graphics API, multiple sprites can be drawn in
one go very quickly.  See `Sprites` for details.

The `pyglet.image.load_animation` function can load animated GIF images.
These are returned as an `Animation`, which exposes the individual image
frames and timings.  Animations can also be played directly on a sprite in
place of an image.  The `Animations` chapter describes how to use them.

The `pyglet.image.atlas` module packs multiple images into larger textures for
efficient rendering.  The `pyglet.resource` module uses this module for small
images automatically, but you can use it directly even if you're not making
use of `pyglet.resource`.  See `Texture bins and atlases` for details.

Images now have ``anchor_x`` and ``anchor_y`` attributes, which specify a
point from which the image should be drawn.  The sprite module also uses the
anchor point as the center of rotation.

Textures have a `get_transform` method for retrieving a `TextureRegion` that
refers to the same texture data in video memory, but with optional horizontal
or vertical flipping, or 90-degree rotation.

New text features
-----------------

The `pyglet.text` module can render formatted text efficiently.  A new class
`Label` supercedes the old `pyglet.font.Text` class (which is now actually
implemented in terms of `Label`).  The "Hello, World" application can now be
written::

    window = pyglet.window.Window()
    label = pyglet.text.Label('Hello, world', 
                              font_name='Times New Roman', 
                              font_size=36,
                              x=window.width//2, y=window.height//2,
                              halign='center', valign='center')

    @window.event
    def on_draw():
        window.clear()
        label.draw()

    pyglet.app.run()

You can also display multiple fonts and styles within one label, with
`HTMLLabel`::

    label = pyglet.text.HTMLLabel('<b>Hello</b>, <font color=red>world!</font>')

More advanced uses of the new text module permit applications to efficiently
display large, scrolling, formatted documents (for example, HTML files with
embedded images), and to allow the user to interactively edit text as in a
WYSIWYG text editor.

Other new features
------------------

`EventDispatcher` now has a `remove_handlers` method which provides finer
control over the event stack than `pop_handlers`. 

The ``@event`` decorator has been fixed so that it no longer overrides
existing event handlers on the object, which fixes the common problem of
handling the `on_resize` event.  For example, the following now works without
any surprises (in pyglet 1.0 this would override the default handler, which
sets up a default, necessary viewport and projection)::

    @window.event
    def on_resize(width, height):
        pass

A variant of `clock.schedule_interval`, `clock.schedule_interval_soft` has
been added.  This is for functions that need to be called periodically at a
given interval, but do not need to schedule the period immediately.    Soft
interval scheduling is used by the `pyglet.media` module to distribute the
work of decoding video and audio data over time, rather than stalling the CPU
periodically.  Games could use soft interval scheduling to spread the
regular computational requirements of multiple agents out over time.

In pyglet 1.0, `font.load` attempted to match the font resolution (DPI) with
the operating system's typical behaviour.  For example, on Linux and Mac OS X
the default DPI was typically set at 72, and on Windows at 96.  While this
would be useful for writing a word processor, it adds a burden on the
application developer to ensure their fonts work at arbitrary resolutions.  In
pyglet 1.1 the default DPI is set at 96 across all platforms.  It can still be
overridden explicitly by the application if desired.

Video sources in `pyglet.media` can now be stepped through frame-by-frame:
individual image frames can be extracted without needing to play back the
video in realtime.

For a complete list of new features and bug fixes, see the ``CHANGELOG``
distributed with the source distribution.
