Source code for moderngl_window.context.headless.window

from pathlib import Path
from typing import Any, Optional

import moderngl

from moderngl_window.context.base import BaseWindow
from moderngl_window.context.headless.keys import Keys


[docs] class Window(BaseWindow): """Headless window. Do not currently support any form window events or key input. """ #: Name of the window name = "headless" keys = Keys def __init__(self, **kwargs: Any): super().__init__(**kwargs) self._fbo: Optional[moderngl.Framebuffer] = None self._vsync = False # We don't care about vsync in headless mode self._resizable = False # headless window is not resizable self._cursor = False # Headless don't have a cursor self._headless = True self.init_mgl_context() self.set_default_viewport() @property def fbo(self) -> moderngl.Framebuffer: """moderngl.Framebuffer: The default framebuffer""" if self._fbo is None: raise RuntimeError("No framebuffer created yet") return self._fbo
[docs] def init_mgl_context(self) -> None: """Create an standalone context and framebuffer""" if self._backend is not None: self._ctx = moderngl.create_standalone_context( require=self.gl_version_code, backend=self._backend, ) else: self._ctx = moderngl.create_standalone_context( require=self.gl_version_code, ) self._create_fbo() self.use()
def _create_fbo(self) -> None: if self._fbo: for attachment in self._fbo.color_attachments: attachment.release() if self._fbo.depth_attachment: self._fbo.depth_attachment.release() self._fbo.release() self._fbo = self.ctx.framebuffer( color_attachments=self.ctx.texture(self.size, 4, samples=self._samples), depth_attachment=self.ctx.depth_texture(self.size, samples=self._samples), ) @property def size(self) -> tuple[int, int]: """tuple[int, int]: current window size. This property also support assignment:: # Resize the window to 1000 x 1000 window.size = 1000, 1000 """ return self._width, self._height @size.setter def size(self, value: tuple[int, int]) -> None: if value == (self._width, self._height): return self._width, self._height = value self._create_fbo()
[docs] def use(self) -> None: """Bind the window's framebuffer""" if self._fbo is None: raise RuntimeError("No framebuffer created yet") self._fbo.use()
[docs] def clear( self, red: float = 0.0, green: float = 0.0, blue: float = 0.0, alpha: float = 0.0, depth: float = 1.0, viewport: Optional[tuple[int, int, int, int]] = None, ) -> None: """ Binds and clears the default framebuffer Args: red (float): color component green (float): color component blue (float): color component alpha (float): alpha component depth (float): depth value viewport (tuple): The viewport """ self.use() self._ctx.clear( red=red, green=green, blue=blue, alpha=alpha, depth=depth, viewport=viewport )
[docs] def swap_buffers(self) -> None: """ Placeholder. We currently don't do double buffering in headless mode. This may change in the future. """ # NOTE: No double buffering currently self._frames += 1 self._ctx.finish()
def _set_icon(self, icon_path: Path) -> None: """Do nothing when icon is set""" pass def _set_fullscreen(self, value: bool) -> None: """Do nothing when fullscreen is toggled""" pass def _set_vsync(self, value: bool) -> None: pass
[docs] def destroy(self) -> None: """Destroy the context""" self._ctx.release()