Skip to content

Commit

Permalink
black + ruff + use ruff in CI
Browse files Browse the repository at this point in the history
  • Loading branch information
einarf committed Nov 23, 2024
1 parent 6dc4527 commit dabe5c2
Show file tree
Hide file tree
Showing 73 changed files with 733 additions and 744 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,9 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Lint with flake8
- name: Lint with ruff
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
ruff check
- name: Test with pytest
run: |
# TODO: Figure out if we can run headless tests
Expand Down
59 changes: 29 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ you provide us your `moderngl.Context`.
## Install

```bash
$ pip install moderngl-window
pip install moderngl-window
```

## Supported Platforms
Expand Down Expand Up @@ -67,13 +67,13 @@ Test.run()
Run the example with different window backends:

```bash
$ python test.py --window pyglet
$ python test.py --window pygame2
$ python test.py --window glfw
$ python test.py --window sdl2
$ python test.py --window pyside2
$ python test.py --window pyqt5
$ python test.py --window tk
python test.py --window pyglet
python test.py --window pygame2
python test.py --window glfw
python test.py --window sdl2
python test.py --window pyside2
python test.py --window pyqt5
python test.py --window tk
```

`WindowConfig` classes are the simplest way to get started without knowing
Expand Down Expand Up @@ -103,8 +103,8 @@ pytest
## Building Docs

```bash
$ pip install -e .[dev]
$ sphinx-build -b html docs docs/_build
pip install -e .[dev]
sphinx-build -b html docs docs/_build
```

## Contributing
Expand Down Expand Up @@ -134,6 +134,7 @@ your package provides.
## Citation

If you need to cite this repository in academic research:

```txt
@Online{Forselv2020,
author = {Einar Forselv},
Expand All @@ -147,8 +148,7 @@ If you need to cite this repository in academic research:
```

If commit hash is required this can be found per release here:
https://github.com/moderngl/moderngl-window/releases

<https://github.com/moderngl/moderngl-window/releases>

## Attributions

Expand All @@ -157,33 +157,32 @@ and resources to make this project possible.

### Windows

* pyglet (https://github.com/pyglet/pyglet)
* pygame (https://github.com/pygame/pygame)
* pyGLFW (https://github.com/FlorianRhiem/pyGLFW)
* PySDL2 (https://github.com/marcusva/py-sdl2)
* PySide2 (https://wiki.qt.io/Qt_for_Python)
* PyQt5 (https://www.riverbankcomputing.com/software/pyqt/intro)
* tkinter (https://github.com/jonwright/pyopengltk)
* pyglet (<https://github.com/pyglet/pyglet>)
* pygame (<https://github.com/pygame/pygame>)
* pyGLFW (<https://github.com/FlorianRhiem/pyGLFW>)
* PySDL2 (<https://github.com/marcusva/py-sdl2>)
* PySide2 (<https://wiki.qt.io/Qt_for_Python>)
* PyQt5 (<https://www.riverbankcomputing.com/software/pyqt/intro>)
* tkinter (<https://github.com/jonwright/pyopengltk>)

### Loaders

* Pillow (https://python-pillow.org/)
* pywavefront (https://github.com/pywavefront/PyWavefront)
* trimesh (https://github.com/mikedh/trimesh)
* Pillow (<https://python-pillow.org/>)
* pywavefront (<https://github.com/pywavefront/PyWavefront>)
* trimesh (<https://github.com/mikedh/trimesh>)

### Testing & Utility

* PyGLM (https://github.com/Zuzu-Typ/PyGLM)
* numpy (https://github.com/numpy/numpy)
* pytest (https://docs.pytest.org/en/latest/)
* flake8 (https://gitlab.com/pycqa/flake8)
* coverage (https://github.com/nedbat/coveragepy)
* tox (https://tox.readthedocs.io/en/latest/)
* PyGLM (<https://github.com/Zuzu-Typ/PyGLM>)
* ruff (<https://github.com/astral-sh/ruff>)
* numpy (<https://github.com/numpy/numpy>)
* pytest (<https://docs.pytest.org/en/latest/>)
* coverage (<https://github.com/nedbat/coveragepy>)

## Resources

* NASA 3D Resources (https://github.com/nasa/NASA-3D-Resources)
* glTF Sample Models (https://github.com/KhronosGroup/glTF-Sample-Models)
* NASA 3D Resources (<https://github.com/nasa/NASA-3D-Resources>)
* glTF Sample Models (<https://github.com/KhronosGroup/glTF-Sample-Models>)

## Some History

Expand Down
85 changes: 47 additions & 38 deletions examples/advanced/fragment_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@ class FragmentPicking(moderngl_window.WindowConfig):
The normal is then used to hide points that point
away from the camera.
"""

title = "Fragment Picking"
gl_version = 3, 3
window_size = 1280, 720
aspect_ratio = None
resizable = True
resource_dir = (Path(__file__) / '../../resources').resolve()
resource_dir = (Path(__file__) / "../../resources").resolve()

def __init__(self, **kwargs):
super().__init__(**kwargs)
print("window buffer size:", self.wnd.buffer_size)
self.marker_file = Path('markers.bin')
self.marker_file = Path("markers.bin")
# Object rotation
self.x_rot = 0
self.y_rot = 0
# Object position
self.zoom = 0

# Load scene cached to speed up loading!
self.scene = self.load_scene('scenes/fragment_picking/centered.obj', cache=True)
self.scene = self.load_scene("scenes/fragment_picking/centered.obj", cache=True)
# Grab the raw mesh/vertexarray
self.mesh = self.scene.root_nodes[0].mesh.vao
self.mesh_texture = self.scene.root_nodes[0].mesh.material.mat_texture.texture
Expand All @@ -58,9 +59,9 @@ def __init__(self, **kwargs):
# RGBA color/diffuse layer
self.offscreen_diffuse = self.ctx.texture(self.wnd.buffer_size, 4)
# Textures for storing normals (16 bit floats)
self.offscreen_normals = self.ctx.texture(self.wnd.buffer_size, 4, dtype='f2')
self.offscreen_normals = self.ctx.texture(self.wnd.buffer_size, 4, dtype="f2")
# Texture for storing the view positions rendered to framebuffer
self.offscreen_viewpos = self.ctx.texture(self.wnd.buffer_size, 4, dtype='f4')
self.offscreen_viewpos = self.ctx.texture(self.wnd.buffer_size, 4, dtype="f4")
# Texture for storing depth values
self.offscreen_depth = self.ctx.depth_texture(self.wnd.buffer_size)
# Create a framebuffer we can render to
Expand All @@ -77,45 +78,49 @@ def __init__(self, **kwargs):
# temporary so we can use it as a normal texture
self.depth_sampler = self.ctx.sampler(
filter=(moderngl.LINEAR, moderngl.LINEAR),
compare_func='',
compare_func="",
)

# A fullscreen quad just for rendering offscreen textures to the window
self.quad_fs = geometry.quad_fs()

# --- Shaders
# Simple program just rendering texture
self.texture_program = self.load_program('programs/fragment_picking/texture.glsl')
self.texture_program['texture0'].value = 0
self.texture_program = self.load_program("programs/fragment_picking/texture.glsl")
self.texture_program["texture0"].value = 0
# Geomtry shader writing to two offscreen layers (color, normal) + depth
self.geometry_program = self.load_program('programs/fragment_picking/geometry.glsl')
self.geometry_program['texture0'].value = 0 # use texture channel 0
self.geometry_program = self.load_program("programs/fragment_picking/geometry.glsl")
self.geometry_program["texture0"].value = 0 # use texture channel 0

# Shader for linearizing depth (debug visualization)
self.linearize_depth_program = self.load_program('programs/linearize_depth.glsl')
self.linearize_depth_program['texture0'].value = 0
self.linearize_depth_program['near'].value = self.projection.near
self.linearize_depth_program['far'].value = self.projection.far
self.linearize_depth_program = self.load_program("programs/linearize_depth.glsl")
self.linearize_depth_program["texture0"].value = 0
self.linearize_depth_program["near"].value = self.projection.near
self.linearize_depth_program["far"].value = self.projection.far

# Shader for picking the world position of a fragment
self.fragment_picker_program = self.load_program('programs/fragment_picking/picker.glsl')
self.fragment_picker_program['position_texture'].value = 0 # Read from texture channel 0
self.fragment_picker_program['normal_texture'].value = 1 # Read from texture channel 1
self.fragment_picker_program['diffuse_texture'].value = 2 # Read from texture channel 2
self.fragment_picker_program = self.load_program("programs/fragment_picking/picker.glsl")
self.fragment_picker_program["position_texture"].value = 0 # Read from texture channel 0
self.fragment_picker_program["normal_texture"].value = 1 # Read from texture channel 1
self.fragment_picker_program["diffuse_texture"].value = 2 # Read from texture channel 2

# Picker geometry
self.marker_byte_size = 7 * 4 # position + normal + temperature (7 x 32bit floats)
self.marker_byte_size = 7 * 4 # position + normal + temperature (7 x 32bit floats)
self.picker_output = self.ctx.buffer(reserve=self.marker_byte_size)
self.picker_vao = VAO(mode=moderngl.POINTS)

# Shader for rendering markers
self.marker_program = self.load_program('programs/fragment_picking/markers.glsl')
self.marker_program['color'].value = 1.0, 0.0, 0.0, 1.0
self.marker_program = self.load_program("programs/fragment_picking/markers.glsl")
self.marker_program["color"].value = 1.0, 0.0, 0.0, 1.0

# Marker geometry
self.marker_buffer = self.ctx.buffer(reserve=self.marker_byte_size * 1000) # Resever room for 1000 points
self.marker_buffer = self.ctx.buffer(
reserve=self.marker_byte_size * 1000
) # Resever room for 1000 points
self.marker_vao = VAO(name="markers", mode=moderngl.POINTS)
self.marker_vao.buffer(self.marker_buffer, '3f 3f 1f', ['in_position', 'in_normal', 'temperature'])
self.marker_vao.buffer(
self.marker_buffer, "3f 3f 1f", ["in_position", "in_normal", "temperature"]
)
self.num_markers = 0

# Debug geometry
Expand All @@ -135,8 +140,8 @@ def render(self, time, frametime):
self.offscreen.use()

# Render the scene
self.geometry_program['modelview'].write(self.modelview)
self.geometry_program['projection'].write(self.projection.matrix)
self.geometry_program["modelview"].write(self.modelview)
self.geometry_program["projection"].write(self.projection.matrix)
self.mesh_texture.use(location=0) # bind texture from obj file to channel 0
self.depth_sampler.use(location=0)
self.mesh.render(self.geometry_program) # render mesh
Expand All @@ -153,8 +158,8 @@ def render(self, time, frametime):
# Render markers
if self.num_markers > 0:
self.ctx.point_size = 6.0 # Specify fragment size of the markers
self.marker_program['modelview'].write(self.modelview)
self.marker_program['projection'].write(self.projection.matrix)
self.marker_program["modelview"].write(self.modelview)
self.marker_program["projection"].write(self.projection.matrix)
self.marker_vao.render(self.marker_program, vertices=self.num_markers)

self.render_debug()
Expand Down Expand Up @@ -187,27 +192,31 @@ def mouse_press_event(self, x, y, button):

# mouse coordinates starts in upper left corner
# pixel positions starts and lower left corner
pos = int(x * self.wnd.pixel_ratio), int(self.wnd.buffer_height - (y * self.wnd.pixel_ratio))
pos = int(x * self.wnd.pixel_ratio), int(
self.wnd.buffer_height - (y * self.wnd.pixel_ratio)
)
print("Picking mouse position", x, y)
print("Viewport position", pos)

self.fragment_picker_program['texel_pos'].value = pos
self.fragment_picker_program['modelview'].write(self.modelview)
self.fragment_picker_program["texel_pos"].value = pos
self.fragment_picker_program["modelview"].write(self.modelview)
self.offscreen_viewpos.use(location=0)
self.offscreen_normals.use(location=1)
self.offscreen_diffuse.use(location=2)
self.picker_vao.transform(self.fragment_picker_program, self.picker_output, vertices=1)

# Print position
x, y, z, nx, ny, nz, temperature = struct.unpack('7f', self.picker_output.read())
x, y, z, nx, ny, nz, temperature = struct.unpack("7f", self.picker_output.read())
if z == 0.0:
print('Point is not on the mesh')
print("Point is not on the mesh")
return

print(f"Position: {x} {y} {z}")
print(f"Normal: {nx} {ny} {nz}")
print(f"Temperature: {round(temperature * 255)} (byte) {temperature} (float)")
self.marker_buffer.write(self.picker_output.read(), offset=self.marker_byte_size * self.num_markers)
self.marker_buffer.write(
self.picker_output.read(), offset=self.marker_byte_size * self.num_markers
)
self.num_markers += 1

def mouse_scroll_event(self, x_offset, y_offset):
Expand All @@ -219,19 +228,19 @@ def key_event(self, key, action, modifiers):
# Key presses
if action == keys.ACTION_PRESS:
if key == keys.F1:
print('Loading marker file')
print("Loading marker file")
self.load_markers(self.marker_file)

if key == keys.F2:
print('Saving marker file')
print("Saving marker file")
self.save_markers(self.marker_file)

def load_markers(self, path: Path):
"""Loads markers from file"""
if not self.marker_file.exists():
return

with open(self.marker_file, mode='rb') as fd:
with open(self.marker_file, mode="rb") as fd:
size = self.marker_file.stat().st_size
self.num_markers = size // self.marker_byte_size
self.marker_buffer.write(fd.read(), offset=0)
Expand All @@ -241,9 +250,9 @@ def save_markers(self, path: Path):
if self.num_markers == 0:
return

with open('markers.bin', mode='wb') as fd:
with open("markers.bin", mode="wb") as fd:
fd.write(self.marker_buffer.read(size=self.num_markers * self.marker_byte_size))


if __name__ == '__main__':
if __name__ == "__main__":
moderngl_window.run_window_config(FragmentPicking)
1 change: 0 additions & 1 deletion examples/advanced/navier_stokes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import random
from pathlib import Path
import numpy as np
import glm

import moderngl_window
Expand Down
Loading

0 comments on commit dabe5c2

Please sign in to comment.