Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 137 additions & 13 deletions hrl/graphics/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,143 @@
"""HRL Graphics module - display device interfaces."""

from .datapixx import DATAPixx
from .gpu import GPU_RGB, GPU_grey
from .graphics import Graphics, Graphics_grey, Graphics_RGB
from .texture import Texture
from .viewpixx import VIEWPixx_grey, VIEWPixx_RGB
import importlib
import os
import platform

__all__ = [
"Graphics",
"Graphics_grey",
"Graphics_RGB",
"GPU_grey",
"GPU_RGB",
"DATAPixx",
"VIEWPixx_grey",
"VIEWPixx_RGB",
"new_graphics",
"ALIASES",
"GREY_ALIASES",
"RGB_ALIASES",
"Texture",
]

GREY_ALIASES = {
"gpu_grey": "gpu.GPU_grey",
"gpu": "gpu.GPU_grey",
"grey": "gpu.GPU_grey",
"gray": "gpu.GPU_grey",
"gray8": "gpu.GPU_grey",
"viewpixx": "viewpixx.VIEWPixx_grey",
"viewpixx_grey": "viewpixx.VIEWPixx_grey",
"viewpixx_gray": "viewpixx.VIEWPixx_grey",
"viewpixx_gray8": "viewpixx.VIEWPixx_grey",
"datapixx": "datapixx.DATAPixx",
"datapixx_grey": "datapixx.DATAPixx",
"datapixx_gray": "datapixx.DATAPixx",
"datapixx_gray8": "datapixx.DATAPixx",
}
RGB_ALIASES = {
"gpu_RGB": "gpu.GPU_RGB",
"RGB": "gpu.GPU_RGB",
"viewpixx_RGB": "viewpixx.VIEWPixx_RGB",
"viewpixx_color": "viewpixx.VIEWPixx_RGB",
"viewpixx_colour": "viewpixx.VIEWPixx_RGB",
}
ALIASES = {**GREY_ALIASES, **RGB_ALIASES}


def new_graphics(
graphics_alias,
width,
height,
background=0.5,
fullscreen=False,
double_buffer=True,
lut=None,
mouse=False,
screen=None,
width_offset=0,
):
"""Factory function to create appropriate Graphics subclass based on provided alias.

This function can be extended to read from a configuration file or environment
variables to determine which graphics device to instantiate (e.g., GPU, DataPixx, ViewPixx).

Parameters
----------
graphics_alias : str
alias for the desired graphics device. Valid options can be found in the
hrl.graphics.ALIASES.keys().
width : int
width of the screen in pixels.
height : int
height of the screen in pixels.
background : float or tuple, optional
background intensity value (0.0, 1.0), by default 0.5.
For grayscale devices, this is a gray level;
for color devices, can specify an RGB triplet.
fullscreen : bool, optional
run in Fullscreen, by default False
double_buffer : bool, optional
use double buffering, by default True.
lut : Path or str, optional
Path to Look-up Table, by default None.
mouse : bool, optional
enable mouse cursor, by default False.
screen : int or str, optional
which monitor to use, by default None (use the environment).
Given as an integer (e.g., 0, 1),
or as a string containing the X11 screen specification string (e.g., ":0.1" or ":1").
width_offset : int, optional
horizontal offset of the window, in pixels, by default 0.
Useful for setups with multiple monitors but a single Xscreen session.

Returns
-------
Graphics
an instance of a concrete Graphics subclass corresponding to the provided alias

Raises
------
ValueError
if the provided graphics_alias does not match any known device
"""
# Lazy import the graphics class based on alias
if graphics_alias in ALIASES:
module_name, class_name = ALIASES[graphics_alias].rsplit(".", 1)
module = importlib.import_module(f".{module_name}", package=__name__)
graphics_class = getattr(module, class_name)
else:
raise ValueError(
f"Unknown graphics device '{graphics_alias}'. Valid options are: "
f"{', '.join(list(ALIASES.keys()))}"
)

# Run screen setup for multiple monitor support
screen_setup(screen=screen, window_width_offset=width_offset)

return graphics_class(
width=width,
height=height,
background=background,
fullscreen=False,
double_buffer=double_buffer,
lut=lut,
mouse=mouse,
)


def screen_setup(screen, window_width_offset):
####### Setting up on which monitor to use
# In older systems or systems with separate Xscreens, the naming is still :0.0 or :0.1.
# For systems with only one screen, it is :1.
if platform.system() == "Linux":
print(f"Default screen number used by the OS: {os.environ['DISPLAY']}")

if screen is not None:
# legacy option for older configs or separate Xscreens
if os.environ["DISPLAY"] == ":0":
os.environ["DISPLAY"] = ":0." + str(screen)
else:
if isinstance(screen, str):
os.environ["DISPLAY"] = screen
elif isinstance(screen, int):
os.environ["DISPLAY"] = ":" + str(screen)

print(f"Display number changed to: {os.environ['DISPLAY']}")

## 11. Aug 2021
# we add a wdth_offset to be able to run HRL in setups with a
# single Xscreen but multiple monitors (a config with Xinerama enabled)
os.environ["SDL_VIDEO_WINDOW_POS"] = f"{window_width_offset},0"
Loading
Loading