File: basic_usage.rst

package info (click to toggle)
python-moderngl-window 2.4.6-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 69,220 kB
  • sloc: python: 11,387; makefile: 21
file content (188 lines) | stat: -rw-r--r-- 6,179 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

Basic usage (WindowConfig)
==========================

.. note:: This section is only relevant when using
   :py:class:`~moderngl_window.context.base.window.WindowConfig`.
   Go to the Custom Usage section if you provide your own window
   and context or want more control.

Using the :py:class:`~moderngl_window.context.base.window.WindowConfig`
interface is the simplest way to start with moderngl-window.
This can work for smaller projects and implies that this library
provides the window and moderngl context.

The API docs for this class alone should cover a lot of ground,
but we'll go through the basics here.

Basic example
-------------

The :py:class:`~moderngl_window.context.base.window.WindowConfig` is
simply a class you extend to customize/implement initialization,
window parameters, rendering code, keyboard input, mouse input
and access simpler shortcut methods for loading resources.

.. code:: python

    import moderngl_window as mglw

    class Test(mglw.WindowConfig):
        gl_version = (3, 3)
        window_size = (1920, 1080)

        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            # Do initialization here
            self.prog = self.ctx.program(...)
            self.vao = self.ctx.vertex_array(...)
            self.texture = self.ctx.texture(self.wnd.size, 4)

        def render(self, time, frametime):
            # This method is called every frame
            self.vao.render()

    # Blocking call entering rendering/event loop
    mglw.run_window_config(Test)

The :py:class:`~moderngl_window.context.base.window.WindowConfig`
instance will by default receive three external instances in ``__init__``
that can be accessed later with ``self``.

- ``self.ctx``: The ``moderngl.Context`` created by the configured window type
- ``self.wnd``: The window instance
- ``self.timer``: The :py:class:`moderngl_window.timers.clock.Timer`
  instance to control the current time (Values passed into ``render``)

Resource loading
----------------

The :py:class:`~moderngl_window.context.base.window.WindowConfig` class has
built in shortcuts to the resource loading system.

.. code:: python

    self.load_texture_2d('background.png')
    self.load_texture_array('tiles.png', layers=16)
    self.load_program('myprogram.glsl')
    self.load_text('textfile.txt')
    self.load_json('config.json')
    self.load_binary('data.bin')
    self.load_scene('cube.obj')
    self.load_scene('city.gltf')

All paths used in resource loading are relative to an absolute path
provided in the :py:class:`~moderngl_window.context.base.window.WindowConfig`.

.. code:: python

    from pathlib import Path

    class Test(mglw.WindowConfig):
        resource_dir = (Path(__file__).parent / 'resources').resolve()

If you need more than one search path for your resources, the
:py:mod:`moderngl_window.resources` module has methods for this.

Optionally an absolute path can be used to load a file at a
specific location bypassing the entire resource system.
This is not recommended, but is useful in some situations.

Generic events and window types
-------------------------------

The :py:class:`~moderngl_window.context.base.window.WindowConfig`
interface depends on the built in window types or a self-provided
window implementation of
:py:class:`~moderngl_window.context.base.window.BaseWindow`.
These window implementations convert window, key and mouse events
into a unified system so the user can switch between different window
types without altering the code.

Window libraries are not perfect and may at times work sub-optimally
on some platforms. They might also have different performance profiles.
The ability to switch between window types by just changing a config
value can be an advantage.

You can change what window class is used by passing in the
``--window`` option. Optionally you can modify the
:py:attr:`~moderngl_window.conf.Settings.WINDOW` attribute directly.

Command line arguments
----------------------

The :py:func:`~moderngl_window.run_window_config` method also reads arguments
from ``sys.argv`` making the user able to override config values in the class.

Example::

    python test.py --window glfw --fullscreen --vsync --samples 16 --cursor false --size 800x600

See code for :py:func:`moderngl_window.parse_args` for more details.

Window events
-------------

.. code:: python

    def resize(self, width: int, height: int):
        print("Window was resized. buffer size is {} x {}".format(width, height))

    def close(self):
        print("The window is closing")

    def iconify(self, iconify: bool):
        print("Window was iconified:", iconify)

Keyboard input
--------------

Implement the ``key_event`` and ``unicode_char_entered`` method to handle
key events.

.. code:: python

    def key_event(self, key, action, modifiers):
        # Key presses
        if action == self.wnd.keys.ACTION_PRESS:
            if key == self.wnd.keys.SPACE:
                print("SPACE key was pressed")

            # Using modifiers (shift and ctrl)

            if key == self.wnd.keys.Z and modifiers.shift:
                print("Shift + Z was pressed")

            if key == self.wnd.keys.Z and modifiers.ctrl:
                print("ctrl + Z was pressed")

        # Key releases
        elif action == self.wnd.keys.ACTION_RELEASE:
            if key == self.wnd.keys.SPACE:
                print("SPACE key was released")

    def unicode_char_entered(self, char: str):
        print('character entered:', char)


Mouse input
-----------

Implement the ``mouse_*`` methods to handle mouse input.

.. code:: python

    def mouse_position_event(self, x, y, dx, dy):
        print("Mouse position:", x, y, dx, dy)

    def mouse_drag_event(self, x, y, dx, dy):
        print("Mouse drag:", x, y, dx, dy)

    def mouse_scroll_event(self, x_offset: float, y_offset: float):
        print("Mouse wheel:", x_offset, y_offset)

    def mouse_press_event(self, x, y, button):
        print("Mouse button {} pressed at {}, {}".format(button, x, y))

    def mouse_release_event(self, x: int, y: int, button: int):
        print("Mouse button {} released at {}, {}".format(button, x, y))