From 0825a94b24205a39172d6d5cb740dc1dea661b20 Mon Sep 17 00:00:00 2001 From: Patrick Faion Date: Tue, 22 Sep 2020 20:01:12 +0200 Subject: [PATCH 01/57] [WIP] --- .../pupil_detector_plugins/pye3d_plugin.py | 6 ++--- .../visualizer_pye3d.py | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py index fc0663eca7..23e929d0b8 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py @@ -47,9 +47,7 @@ def detect(self, frame, **kwargs): raise RuntimeError("No 2D detection result! Needed for pye3D!") datum_2d["raw_edges"] = [] - result = self.detector.update_and_detect( - datum_2d, frame.gray, debug_toggle=self.is_debug_window_open - ) + result = self.detector.update_and_detect(datum_2d, frame.gray, debug=True) eye_id = self.g_pool.eye_id result["timestamp"] = frame.timestamp @@ -123,5 +121,5 @@ def debug_window_close(self): def debug_window_update(self): if self.is_debug_window_open: self.debugVisualizer3D.update_window( - self.g_pool, self.detector.debug_result + self.g_pool, self._recent_detection_result ) diff --git a/pupil_src/shared_modules/pupil_detector_plugins/visualizer_pye3d.py b/pupil_src/shared_modules/pupil_detector_plugins/visualizer_pye3d.py index 357834cf43..bd415e052b 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/visualizer_pye3d.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/visualizer_pye3d.py @@ -226,6 +226,29 @@ def update_window(self, g_pool, result): alpha=1.0, ) + bins = np.array(result["debug_info"]["bins"]) + print(bins) + m = np.max(bins) + if m > 0: + bins = bins / m + px_per_bin = result["debug_info"]["px_per_bin"] + w, h = bins.shape + for row in range(h): + for col in range(w): + + x0 = col * px_per_bin + x1 = (col + 1) * px_per_bin + y0 = row * px_per_bin + y1 = (row + 1) * px_per_bin + + glColor4f(1, 0, 0, bins[row, col]) + glBegin(GL_QUADS) + glVertex3f(x0, y0, 0) + glVertex3f(x0, y1, 0) + glVertex3f(x1, y1, 0) + glVertex3f(x1, y0, 0) + glEnd() + glLoadMatrixf(self.get_adjusted_pixel_space_matrix(15)) self.draw_frustum(self.image_width, self.image_height, self.focal_length) glLoadMatrixf(self.get_anthropomorphic_matrix()) From 50c428d8d59c3a3ee6f46471c52c97001362b97f Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Wed, 23 Sep 2020 09:05:16 +0200 Subject: [PATCH 02/57] Move custom helper functions from glfw.py to gl_utils --- pupil_src/launchables/eye.py | 12 +-- pupil_src/launchables/player.py | 16 +-- pupil_src/launchables/world.py | 14 +-- .../controller/gui_window.py | 3 +- .../camera_intrinsics_estimation.py | 1 + pupil_src/shared_modules/gl_utils/utils.py | 102 +++++++++++++++++- .../gl_utils/window_position_manager.py | 7 +- pupil_src/shared_modules/log_display.py | 3 +- pupil_src/shared_modules/service_ui.py | 10 +- pupil_src/shared_modules/system_graphs.py | 3 +- .../video_overlay/ui/interactions.py | 5 +- pupil_src/shared_modules/visualizer.py | 3 +- 12 files changed, 142 insertions(+), 37 deletions(-) diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index 2ebfffa3f0..e5a00d0542 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -259,7 +259,7 @@ def consume_events_and_render_buffer(): for button, action, mods in user_input.buttons: x, y = glfw.glfwGetCursorPos(main_window) - pos = glfw.window_coordinate_to_framebuffer_coordinate( + pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) pos = normalize(pos, g_pool.camera_render_size) @@ -302,8 +302,8 @@ def on_resize(window, w, h): active_window = glfw.glfwGetCurrentContext() glfw.glfwMakeContextCurrent(window) - content_scale = glfw.get_content_scale(window) - framebuffer_scale = glfw.get_framebuffer_scale(window) + content_scale = gl_utils.get_content_scale(window) + framebuffer_scale = gl_utils.get_framebuffer_scale(window) g_pool.gui.scale = content_scale window_size = w, h g_pool.camera_render_size = w - int(icon_bar_width * g_pool.gui.scale), h @@ -340,7 +340,7 @@ def on_window_mouse_button(window, button, action, mods): g_pool.gui.update_button(button, action, mods) def on_pos(window, x, y): - x, y = glfw.window_coordinate_to_framebuffer_coordinate( + x, y = gl_utils.window_coordinate_to_framebuffer_coordinate( window, x, y, cached_scale=None ) g_pool.gui.update_mouse(x, y) @@ -453,8 +453,8 @@ def set_window_size(): f_height *= frame_scale_factor # Get current display scale factor - content_scale = glfw.get_content_scale(main_window) - framebuffer_scale = glfw.get_framebuffer_scale(main_window) + content_scale = gl_utils.get_content_scale(main_window) + framebuffer_scale = gl_utils.get_framebuffer_scale(main_window) display_scale_factor = content_scale / framebuffer_scale # Scale the capture frame size by display scale factor diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index 8a3fc28e0f..a393e900df 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -204,7 +204,7 @@ def consume_events_and_render_buffer(): for b in user_input.buttons: button, action, mods = b x, y = glfw.glfwGetCursorPos(main_window) - pos = glfw.window_coordinate_to_framebuffer_coordinate( + pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) pos = normalize(pos, g_pool.camera_render_size) @@ -238,8 +238,8 @@ def on_resize(window, w, h): gl_utils.glClear(gl_utils.GL_COLOR_BUFFER_BIT) gl_utils.glClearColor(0, 0, 0, 1) - content_scale = glfw.get_content_scale(window) - framebuffer_scale = glfw.get_framebuffer_scale(window) + content_scale = gl_utils.get_content_scale(window) + framebuffer_scale = gl_utils.get_framebuffer_scale(window) g_pool.gui.scale = content_scale window_size = w, h g_pool.camera_render_size = w - int(icon_bar_width * g_pool.gui.scale), h @@ -270,7 +270,7 @@ def on_window_mouse_button(window, button, action, mods): g_pool.gui.update_button(button, action, mods) def on_pos(window, x, y): - x, y = glfw.window_coordinate_to_framebuffer_coordinate( + x, y = gl_utils.window_coordinate_to_framebuffer_coordinate( window, x, y, cached_scale=None ) g_pool.gui.update_mouse(x, y) @@ -476,8 +476,8 @@ def set_window_size(): f_width, f_height = g_pool.capture.frame_size # Get current display scale factor - content_scale = glfw.get_content_scale(main_window) - framebuffer_scale = glfw.get_framebuffer_scale(main_window) + content_scale = gl_utils.get_content_scale(main_window) + framebuffer_scale = gl_utils.get_framebuffer_scale(main_window) display_scale_factor = content_scale / framebuffer_scale # Scale the capture frame size by display scale factor @@ -708,7 +708,7 @@ def handle_notifications(n): for b in user_input.buttons: button, action, mods = b x, y = glfw.glfwGetCursorPos(main_window) - pos = glfw.window_coordinate_to_framebuffer_coordinate( + pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) pos = normalize(pos, g_pool.camera_render_size) @@ -889,7 +889,7 @@ def display_string(string, font_size, center_y): while not glfw.glfwWindowShouldClose(window) and not process_was_interrupted: fb_size = glfw.glfwGetFramebufferSize(window) - content_scale = glfw.get_content_scale(window) + content_scale = gl_utils.get_content_scale(window) gl_utils.adjust_gl_view(*fb_size) if rec_dir: diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index d1860edb9c..8bad863a1b 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -343,7 +343,7 @@ def consume_events_and_render_buffer(): for button, action, mods in user_input.buttons: x, y = glfw.glfwGetCursorPos(main_window) - pos = glfw.window_coordinate_to_framebuffer_coordinate( + pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) pos = normalize(pos, camera_render_size) @@ -379,8 +379,8 @@ def on_resize(window, w, h): gl_utils.glClear(gl_utils.GL_COLOR_BUFFER_BIT) gl_utils.glClearColor(0, 0, 0, 1) - content_scale = glfw.get_content_scale(window) - framebuffer_scale = glfw.get_framebuffer_scale(window) + content_scale = gl_utils.get_content_scale(window) + framebuffer_scale = gl_utils.get_framebuffer_scale(window) g_pool.gui.scale = content_scale window_size = w, h camera_render_size = w - int(icon_bar_width * g_pool.gui.scale), h @@ -412,7 +412,7 @@ def on_window_mouse_button(window, button, action, mods): g_pool.gui.update_button(button, action, mods) def on_pos(window, x, y): - x, y = glfw.window_coordinate_to_framebuffer_coordinate( + x, y = gl_utils.window_coordinate_to_framebuffer_coordinate( window, x, y, cached_scale=None ) g_pool.gui.update_mouse(x, y) @@ -562,8 +562,8 @@ def set_window_size(): f_width, f_height = g_pool.capture.frame_size # Get current display scale factor - content_scale = glfw.get_content_scale(main_window) - framebuffer_scale = glfw.get_framebuffer_scale(main_window) + content_scale = gl_utils.get_content_scale(main_window) + framebuffer_scale = gl_utils.get_framebuffer_scale(main_window) display_scale_factor = content_scale / framebuffer_scale # Scale the capture frame size by display scale factor @@ -766,7 +766,7 @@ def window_should_update(): for button, action, mods in user_input.buttons: x, y = glfw.glfwGetCursorPos(main_window) - pos = glfw.window_coordinate_to_framebuffer_coordinate( + pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) pos = normalize(pos, camera_render_size) diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py index 3c79a29b71..0792ae05e5 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py @@ -8,6 +8,7 @@ from gl_utils import adjust_gl_view from gl_utils import basic_gl_setup from gl_utils import clear_gl_screen +import gl_utils from pyglui.cygl.utils import draw_polyline @@ -30,7 +31,7 @@ def unsafe_handle(self): @property def content_scale(self) -> float: if self.__gl_handle is not None: - return glfw.get_content_scale(self.__gl_handle) + return gl_utils.get_content_scale(self.__gl_handle) else: return 1.0 diff --git a/pupil_src/shared_modules/camera_intrinsics_estimation.py b/pupil_src/shared_modules/camera_intrinsics_estimation.py index 41b4d68970..0ee6012b34 100644 --- a/pupil_src/shared_modules/camera_intrinsics_estimation.py +++ b/pupil_src/shared_modules/camera_intrinsics_estimation.py @@ -26,6 +26,7 @@ from pyglui.pyfontstash import fontstash from pyglui.ui import get_opensans_font_path from glfw import * +import gl_utils from plugin import Plugin diff --git a/pupil_src/shared_modules/gl_utils/utils.py b/pupil_src/shared_modules/gl_utils/utils.py index f761a276c9..8b87321d6e 100644 --- a/pupil_src/shared_modules/gl_utils/utils.py +++ b/pupil_src/shared_modules/gl_utils/utils.py @@ -10,6 +10,7 @@ """ import logging import math +import typing as T import numpy as np import OpenGL @@ -18,6 +19,7 @@ from OpenGL.GLU import gluPerspective, gluErrorString import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API # OpenGL.FULL_LOGGING = True OpenGL.ERROR_LOGGING = False @@ -34,6 +36,16 @@ "cvmat_to_glmat", "is_window_visible", "Coord_System", + "_Margins", + "_Rectangle", + "get_content_scale", + "get_framebuffer_scale", + "window_coordinate_to_framebuffer_coordinate", + "get_monitor_workarea_rect", + "get_window_content_rect", + "get_window_frame_size_margins", + "get_window_frame_rect", + "get_window_title_bar_rect", ] @@ -91,8 +103,8 @@ def custom_gl_error_handling( def is_window_visible(window): - visible = glfw.glfwGetWindowAttrib(window, glfw.GLFW_VISIBLE) - iconified = glfw.glfwGetWindowAttrib(window, glfw.GLFW_ICONIFIED) + visible = glfw.GLFW.glfwGetWindowAttrib(window, glfw.GLFW.GLFW_VISIBLE) + iconified = glfw.GLFW.glfwGetWindowAttrib(window, glfw.GLFW.GLFW_ICONIFIED) return visible and not iconified @@ -211,3 +223,89 @@ def __exit__(self, *exc): glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() + + +class _Margins(T.NamedTuple): + left: int + top: int + right: int + bottom: int + + +class _Rectangle(T.NamedTuple): + x: int + y: int + width: int + height: int + + def intersection(self, other: "_Rectangle") -> T.Optional["_Rectangle"]: + in_min_x = max(self.x, other.x) + in_min_y = max(self.y, other.y) + + in_max_x = min(self.x + self.width, other.x + other.width) + in_max_y = min(self.y + self.height, other.y + other.height) + + if in_min_x < in_max_x and in_min_y < in_max_y: + return _Rectangle( + x=in_min_x, + y=in_min_y, + width=in_max_x - in_min_x, + height=in_max_y - in_min_y, + ) + else: + return None + + +def get_content_scale(window) -> float: + # TODO: Explicitly rename to `get_content_scale_x` + return glfw.GLFW.glfwGetWindowContentScale(window)[0] + + +def get_framebuffer_scale(window) -> float: + window_width = glfw.GLFW.glfwGetWindowSize(window)[0] + framebuffer_width = glfw.GLFW.glfwGetFramebufferSize(window)[0] + + try: + return float(framebuffer_width / window_width) + except ZeroDivisionError: + return 1.0 + + +def window_coordinate_to_framebuffer_coordinate(window, x, y, cached_scale=None): + scale = cached_scale or get_framebuffer_scale(window) + return x * scale, y * scale + + +def get_monitor_workarea_rect(monitor) -> _Rectangle: + x, y, w, h = glfw.GLFW.glfwGetMonitorWorkarea(monitor) + return _Rectangle(x=x, y=y, width=w, height=h) + + +def get_window_content_rect(window) -> _Rectangle: + x, y = glfw.GLFW.glfwGetWindowPos(window) + w, h = glfw.GLFW.glfwGetWindowSize(window) + return _Rectangle(x=x, y=y, width=w, height=h) + + +def get_window_frame_size_margins(window) -> _Margins: + left, top, right, bottom = glfw.GLFW.glfwGetWindowFrameSize(window) + return _Margins(left=left, top=top, right=right, bottom=bottom) + + +def get_window_frame_rect(window) -> _Rectangle: + content_rect = get_window_content_rect(window) + frame_edges = get_window_frame_size_margins(window) + return _Rectangle( + x=content_rect.x - frame_edges.left, + y=content_rect.y - frame_edges.top, + width=content_rect.width + frame_edges.left + frame_edges.right, + height=content_rect.height + frame_edges.top + frame_edges.bottom, + ) + + +def get_window_title_bar_rect(window) -> _Rectangle: + frame_rect = get_window_frame_rect(window) + frame_edges = get_window_frame_size_margins(window) + return _Rectangle( + x=frame_rect.x, y=frame_rect.y, width=frame_rect.width, height=frame_edges.top + ) diff --git a/pupil_src/shared_modules/gl_utils/window_position_manager.py b/pupil_src/shared_modules/gl_utils/window_position_manager.py index 60b26f38ab..d8c5925e27 100644 --- a/pupil_src/shared_modules/gl_utils/window_position_manager.py +++ b/pupil_src/shared_modules/gl_utils/window_position_manager.py @@ -13,6 +13,7 @@ import typing as T import glfw +import gl_utils class WindowPositionManager: @@ -62,12 +63,12 @@ def _will_window_be_visible_in_monitor( ) -> bool: # Get the current window size and edges, and monitor rect window_size = glfw.glfwGetWindowSize(window) - window_edges = glfw.glfwGetWindowFrameSize(window) - monitor_rect = glfw.glfwGetMonitorWorkarea(monitor) + window_edges = gl_utils.get_window_frame_size_margins(window) + monitor_rect = gl_utils.get_monitor_workarea_rect(monitor) # Calculate what the title bar rect would be # if the proposed `window_position` would be the actual window position - title_bar_rect = glfw._Rectangle( + title_bar_rect = gl_utils._Rectangle( x=window_position[0] - window_edges.left, y=window_position[1] - window_edges.top, width=window_size[0] + window_edges.left + window_edges.right, diff --git a/pupil_src/shared_modules/log_display.py b/pupil_src/shared_modules/log_display.py index f7d278bee2..04415ee8ae 100644 --- a/pupil_src/shared_modules/log_display.py +++ b/pupil_src/shared_modules/log_display.py @@ -17,6 +17,7 @@ from pyglui.pyfontstash import fontstash from pyglui.ui import get_opensans_font_path import glfw +import gl_utils def color_from_level(lvl): @@ -86,7 +87,7 @@ def on_log(self, record): self.alpha = min(self.alpha, 6.0) def on_window_resize(self, window, w, h): - self.window_scale = glfw.get_content_scale(window) + self.window_scale = gl_utils.get_content_scale(window) self.glfont.set_size(32 * self.window_scale) self.window_size = w, h self.tex.resize(*self.window_size) diff --git a/pupil_src/shared_modules/service_ui.py b/pupil_src/shared_modules/service_ui.py index 611fde4f46..029ef7123f 100644 --- a/pupil_src/shared_modules/service_ui.py +++ b/pupil_src/shared_modules/service_ui.py @@ -80,7 +80,7 @@ def on_resize(window, w, h): gl_utils.glClearColor(0, 0, 0, 1) self.window_size = w, h - self.content_scale = glfw.get_content_scale(window) + self.content_scale = gl_utils.get_content_scale(window) g_pool.gui.scale = self.content_scale g_pool.gui.update_window(w, h) g_pool.gui.collect_menus() @@ -98,7 +98,7 @@ def on_window_mouse_button(window, button, action, mods): g_pool.gui.update_button(button, action, mods) def on_pos(window, x, y): - x, y = glfw.window_coordinate_to_framebuffer_coordinate( + x, y = gl_utils.window_coordinate_to_framebuffer_coordinate( window, x, y, cached_scale=None ) g_pool.gui.update_mouse(x, y) @@ -111,8 +111,8 @@ def set_window_size(): f_width, f_height = window_size_default # Get current display scale factor - content_scale = glfw.get_content_scale(main_window) - framebuffer_scale = glfw.get_framebuffer_scale(main_window) + content_scale = gl_utils.get_content_scale(main_window) + framebuffer_scale = gl_utils.get_framebuffer_scale(main_window) display_scale_factor = content_scale / framebuffer_scale # Scale the capture frame size by display scale factor @@ -238,7 +238,7 @@ def get_init_dict(self): if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): - content_scale = glfw.get_content_scale(self.g_pool.main_window) + content_scale = gl_utils.get_content_scale(self.g_pool.main_window) f_width, f_height = ( f_width / content_scale, f_height / content_scale, diff --git a/pupil_src/shared_modules/system_graphs.py b/pupil_src/shared_modules/system_graphs.py index face887390..ecda5c1b9d 100644 --- a/pupil_src/shared_modules/system_graphs.py +++ b/pupil_src/shared_modules/system_graphs.py @@ -12,6 +12,7 @@ import os import psutil import glfw +import gl_utils from pyglui import ui, graph from pyglui.cygl.utils import RGBA, mix_smooth from plugin import System_Plugin_Base @@ -73,7 +74,7 @@ def init_ui(self): def on_window_resize(self, window, *args): fb_size = glfw.glfwGetFramebufferSize(window) - content_scale = glfw.get_content_scale(window) + content_scale = gl_utils.get_content_scale(window) self.cpu_graph.scale = content_scale self.fps_graph.scale = content_scale diff --git a/pupil_src/shared_modules/video_overlay/ui/interactions.py b/pupil_src/shared_modules/video_overlay/ui/interactions.py index d6bdc8163f..138ebf4ed5 100644 --- a/pupil_src/shared_modules/video_overlay/ui/interactions.py +++ b/pupil_src/shared_modules/video_overlay/ui/interactions.py @@ -10,6 +10,7 @@ """ from glfw import get_content_scale, glfwGetCurrentContext, glfwGetCursorPos, GLFW_PRESS +import gl_utils from methods import normalize, denormalize @@ -60,8 +61,8 @@ def _effective_overlay_frame_size(self): def current_mouse_pos(window, camera_render_size, frame_size): - content_scale = get_content_scale(window) - x, y = glfwGetCursorPos(glfwGetCurrentContext()) + content_scale = gl_utils.get_content_scale(window) + x, y = glfw.GLFW.glfwGetCursorPos(glfw.GLFW.glfwGetCurrentContext()) pos = x * content_scale, y * content_scale pos = normalize(pos, camera_render_size) # Position in img pixels diff --git a/pupil_src/shared_modules/visualizer.py b/pupil_src/shared_modules/visualizer.py index ad0ad0c4d0..2f6a347132 100644 --- a/pupil_src/shared_modules/visualizer.py +++ b/pupil_src/shared_modules/visualizer.py @@ -10,6 +10,7 @@ """ from glfw import * +import gl_utils from OpenGL.GL import * from platform import system @@ -228,7 +229,7 @@ def on_window_mouse_button(self, window, button, action, mods): self.input["button"] = None def on_pos(self, window, x, y): - x, y = window_coordinate_to_framebuffer_coordinate( + x, y = gl_utils.window_coordinate_to_framebuffer_coordinate( window, x, y, cached_scale=None ) # self.gui.update_mouse(x,y) From 76a62a3d885efe57711653c776bede7eb6402de4 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Wed, 23 Sep 2020 09:20:13 +0200 Subject: [PATCH 03/57] Use qualified glfw.GLFW module for GLFW C API --- pupil_src/launchables/eye.py | 57 ++++++++------ pupil_src/launchables/player.py | 77 +++++++++++-------- pupil_src/launchables/world.py | 56 ++++++++------ .../controller/gui_monitor.py | 14 ++-- .../controller/gui_window.py | 43 ++++++----- .../natural_feature_plugin.py | 6 +- .../screen_marker_plugin.py | 4 +- .../single_marker_plugin.py | 4 +- .../camera_intrinsics_estimation.py | 46 ++++++----- .../reference_location_controllers.py | 3 +- .../gl_utils/window_position_manager.py | 5 +- .../head_pose_tracker/ui/gl_window.py | 39 +++++----- pupil_src/shared_modules/log_display.py | 6 +- .../shared_modules/marker_auto_trim_marks.py | 4 +- .../detector_2d_plugin.py | 1 + pupil_src/shared_modules/roi.py | 5 +- pupil_src/shared_modules/service_ui.py | 33 ++++---- .../shared_modules/surface_tracker/gui.py | 55 +++++++------ pupil_src/shared_modules/system_graphs.py | 3 +- .../video_overlay/ui/interactions.py | 5 +- pupil_src/shared_modules/vis_watermark.py | 9 ++- pupil_src/shared_modules/visualizer.py | 49 ++++++------ 22 files changed, 297 insertions(+), 227 deletions(-) diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index e5a00d0542..7fdea70b55 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -123,6 +123,7 @@ def eye( # display import glfw + import glfw.GLFW # TODO: Remove when switching to pyglfw API from pyglui import ui, graph, cygl from pyglui.cygl.utils import draw_points, RGBA, draw_polyline from pyglui.cygl.utils import Named_Texture @@ -233,7 +234,7 @@ def get_timestamp(): ] def consume_events_and_render_buffer(): - glfw.glfwMakeContextCurrent(main_window) + glfw.GLFW.glfwMakeContextCurrent(main_window) clear_gl_screen() if all(c > 0 for c in g_pool.camera_render_size): @@ -248,17 +249,19 @@ def consume_events_and_render_buffer(): # render GUI try: - clipboard = glfw.glfwGetClipboardString(main_window).decode() + clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() except AttributeError: # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.glfwSetClipboardString(main_window, user_input.clipboard.encode()) + glfw.GLFW.glfwSetClipboardString( + main_window, user_input.clipboard.encode() + ) for button, action, mods in user_input.buttons: - x, y = glfw.glfwGetCursorPos(main_window) + x, y = glfw.GLFW.glfwGetCursorPos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -283,14 +286,16 @@ def consume_events_and_render_buffer(): break # update screen - glfw.glfwSwapBuffers(main_window) + glfw.GLFW.glfwSwapBuffers(main_window) # Callback functions def on_resize(window, w, h): nonlocal window_size nonlocal content_scale - is_minimized = bool(glfw.glfwGetWindowAttrib(window, glfw.GLFW_ICONIFIED)) + is_minimized = bool( + glfw.GLFW.glfwGetWindowAttrib(window, glfw.GLFW.GLFW_ICONIFIED) + ) if is_minimized: return @@ -300,8 +305,8 @@ def on_resize(window, w, h): gl_utils.glClear(gl_utils.GL_COLOR_BUFFER_BIT) gl_utils.glClearColor(0, 0, 0, 1) - active_window = glfw.glfwGetCurrentContext() - glfw.glfwMakeContextCurrent(window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(window) content_scale = gl_utils.get_content_scale(window) framebuffer_scale = gl_utils.get_framebuffer_scale(window) g_pool.gui.scale = content_scale @@ -313,15 +318,19 @@ def on_resize(window, w, h): g.scale = content_scale g.adjust_window_size(w, h) adjust_gl_view(w, h) - glfw.glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwMakeContextCurrent(active_window) # Minimum window size required, otherwise parts of the UI can cause openGL # issues with permanent effects. Depends on the content scale, which can # potentially be dynamically modified, so we re-adjust the size limits every # time here. min_size = int(2 * icon_bar_width * g_pool.gui.scale / framebuffer_scale) - glfw.glfwSetWindowSizeLimits( - window, min_size, min_size, glfw.GLFW_DONT_CARE, glfw.GLFW_DONT_CARE + glfw.GLFW.glfwSetWindowSizeLimits( + window, + min_size, + min_size, + glfw.GLFW.GLFW_DONT_CARE, + glfw.GLFW.GLFW_DONT_CARE, ) # Needed, to update the window buffer while resizing @@ -400,9 +409,9 @@ def toggle_general_settings(collapsed): # Initialize glfw glfw.glfwInit() - glfw.glfwWindowHint(glfw.GLFW_SCALE_TO_MONITOR, glfw.GLFW_TRUE) + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) if hide_ui: - glfw.glfwWindowHint(glfw.GLFW_VISIBLE, 0) # hide window + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_VISIBLE, 0) # hide window title = "Pupil Capture - eye {}".format(eye_id) # Pupil Cam1 uses 4:3 resolutions. Pupil Cam2 and Cam3 use 1:1 resolutions. @@ -420,9 +429,9 @@ def toggle_general_settings(collapsed): default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) - glfw.glfwSetWindowPos(main_window, window_pos[0], window_pos[1]) + glfw.GLFW.glfwSetWindowPos(main_window, window_pos[0], window_pos[1]) - glfw.glfwMakeContextCurrent(main_window) + glfw.GLFW.glfwMakeContextCurrent(main_window) cygl.utils.init() # gl_state settings @@ -465,7 +474,7 @@ def set_window_size(): f_width += icon_bar_width * display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) - glfw.glfwSetWindowSize(main_window, int(f_width), int(f_height)) + glfw.GLFW.glfwSetWindowSize(main_window, int(f_width), int(f_height)) general_settings.append(ui.Button("Reset window size", set_window_size)) general_settings.append(ui.Switch("flip", g_pool, label="Flip image display")) @@ -554,7 +563,7 @@ def set_window_size(): g_pool.graphs = [cpu_graph, fps_graph] # set the last saved window size - on_resize(main_window, *glfw.glfwGetFramebufferSize(main_window)) + on_resize(main_window, *glfw.GLFW.glfwGetFramebufferSize(main_window)) should_publish_frames = False frame_publish_format = "jpeg" @@ -571,7 +580,7 @@ def window_should_update(): frame = None # Event loop - while not glfw.glfwWindowShouldClose(main_window): + while not glfw.GLFW.glfwWindowShouldClose(main_window): if notify_sub.new_data: t, notification = notify_sub.recv() @@ -711,7 +720,7 @@ def window_should_update(): if window_should_update(): if is_window_visible(main_window): consume_events_and_render_buffer() - glfw.glfwPollEvents() + glfw.GLFW.glfwPollEvents() # END while running @@ -729,9 +738,11 @@ def window_should_update(): session_settings["version"] = str(g_pool.version) if not hide_ui: - glfw.glfwRestoreWindow(main_window) # need to do this for windows os - session_settings["window_position"] = glfw.glfwGetWindowPos(main_window) - session_window_size = glfw.glfwGetWindowSize(main_window) + glfw.GLFW.glfwRestoreWindow(main_window) # need to do this for windows os + session_settings["window_position"] = glfw.GLFW.glfwGetWindowPos( + main_window + ) + session_window_size = glfw.GLFW.glfwGetWindowSize(main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): @@ -751,7 +762,7 @@ def window_should_update(): glfw.glfwDestroyWindow(main_window) g_pool.gui.terminate() - glfw.glfwTerminate() + glfw.GLFW.glfwTerminate() logger.info("Process shutting down.") diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index a393e900df..727b20d32d 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -71,6 +71,7 @@ def player( # display import glfw + import glfw.GLFW # TODO: Remove when switching to pyglfw API # check versions for our own depedencies as they are fast-changing from pyglui import __version__ as pyglui_version @@ -192,18 +193,20 @@ def consume_events_and_render_buffer(): gl_utils.glViewport(0, 0, *window_size) try: - clipboard = glfw.glfwGetClipboardString(main_window).decode() + clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() except AttributeError: # clipbaord is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.glfwSetClipboardString(main_window, user_input.clipboard.encode()) + glfw.GLFW.glfwSetClipboardString( + main_window, user_input.clipboard.encode() + ) for b in user_input.buttons: button, action, mods = b - x, y = glfw.glfwGetCursorPos(main_window) + x, y = glfw.GLFW.glfwGetCursorPos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -224,7 +227,7 @@ def consume_events_and_render_buffer(): if plugin.on_char(char_): break - glfw.glfwSwapBuffers(main_window) + glfw.GLFW.glfwSwapBuffers(main_window) # Callback functions def on_resize(window, w, h): @@ -253,8 +256,12 @@ def on_resize(window, w, h): # potentially be dynamically modified, so we re-adjust the size limits every # time here. min_size = int(2 * icon_bar_width * g_pool.gui.scale / framebuffer_scale) - glfw.glfwSetWindowSizeLimits( - window, min_size, min_size, glfw.GLFW_DONT_CARE, glfw.GLFW_DONT_CARE + glfw.GLFW.glfwSetWindowSizeLimits( + window, + min_size, + min_size, + glfw.GLFW.GLFW_DONT_CARE, + glfw.GLFW.GLFW_DONT_CARE, ) # Needed, to update the window buffer while resizing @@ -303,7 +310,7 @@ def _restart_with_recording(rec_dir): ipc_pub.notify( {"subject": "player_drop_process.should_start", "rec_dir": rec_dir} ) - glfw.glfwSetWindowShouldClose(g_pool.main_window, True) + glfw.GLFW.glfwSetWindowShouldClose(g_pool.main_window, True) tick = delta_t() @@ -359,8 +366,8 @@ def get_dt(): window_name = f"Pupil Player: {meta_info.recording_name} - {rec_dir}" glfw.glfwInit() - glfw.glfwWindowHint(glfw.GLFW_SCALE_TO_MONITOR, glfw.GLFW_TRUE) main_window = glfw.glfwCreateWindow(width, height, window_name, None, None) + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( @@ -368,9 +375,9 @@ def get_dt(): default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) - glfw.glfwSetWindowPos(main_window, window_pos[0], window_pos[1]) + glfw.GLFW.glfwSetWindowPos(main_window, window_pos[0], window_pos[1]) - glfw.glfwMakeContextCurrent(main_window) + glfw.GLFW.glfwMakeContextCurrent(main_window) cygl.utils.init() g_pool.main_window = main_window @@ -433,7 +440,7 @@ def do_export(_): def reset_restart(): logger.warning("Resetting all settings and restarting Player.") - glfw.glfwSetWindowShouldClose(main_window, True) + glfw.GLFW.glfwSetWindowShouldClose(main_window, True) ipc_pub.notify({"subject": "clear_settings_process.should_start"}) ipc_pub.notify( { @@ -488,7 +495,7 @@ def set_window_size(): f_width += icon_bar_width * display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) - glfw.glfwSetWindowSize(main_window, int(f_width), int(f_height)) + glfw.GLFW.glfwSetWindowSize(main_window, int(f_width), int(f_height)) general_settings = ui.Growing_Menu("General", header_pos="headline") general_settings.append(ui.Button("Reset window size", set_window_size)) @@ -625,7 +632,7 @@ def set_window_size(): g_pool.image_tex = Named_Texture() # trigger on_resize - on_resize(main_window, *glfw.glfwGetFramebufferSize(main_window)) + on_resize(main_window, *glfw.GLFW.glfwGetFramebufferSize(main_window)) def handle_notifications(n): subject = n["subject"] @@ -651,7 +658,8 @@ def handle_notifications(n): ) while ( - not glfw.glfwWindowShouldClose(main_window) and not process_was_interrupted + not glfw.GLFW.glfwWindowShouldClose(main_window) + and not process_was_interrupted ): # fetch newest notifications @@ -681,8 +689,8 @@ def handle_notifications(n): # check if a plugin need to be destroyed g_pool.plugins.clean() - glfw.glfwMakeContextCurrent(main_window) - glfw.glfwPollEvents() + glfw.GLFW.glfwMakeContextCurrent(main_window) + glfw.GLFW.glfwPollEvents() # render visual feedback from loaded plugins if gl_utils.is_window_visible(main_window): @@ -694,20 +702,20 @@ def handle_notifications(n): gl_utils.glViewport(0, 0, *window_size) try: - clipboard = glfw.glfwGetClipboardString(main_window).decode() + clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() except AttributeError: # clipbaord is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.glfwSetClipboardString( + glfw.GLFW.glfwSetClipboardString( main_window, user_input.clipboard.encode() ) for b in user_input.buttons: button, action, mods = b - x, y = glfw.glfwGetCursorPos(main_window) + x, y = glfw.GLFW.glfwGetCursorPos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -730,7 +738,7 @@ def handle_notifications(n): # present frames at appropriate speed g_pool.seek_control.wait(events["frame"].timestamp) - glfw.glfwSwapBuffers(main_window) + glfw.GLFW.glfwSwapBuffers(main_window) session_settings["loaded_plugins"] = g_pool.plugins.get_initializers() session_settings["min_data_confidence"] = g_pool.min_data_confidence @@ -738,10 +746,10 @@ def handle_notifications(n): "min_calibration_confidence" ] = g_pool.min_calibration_confidence session_settings["ui_config"] = g_pool.gui.configuration - session_settings["window_position"] = glfw.glfwGetWindowPos(main_window) + session_settings["window_position"] = glfw.GLFW.glfwGetWindowPos(main_window) session_settings["version"] = str(g_pool.version) - session_window_size = glfw.glfwGetWindowSize(main_window) + session_window_size = glfw.GLFW.glfwGetWindowSize(main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): @@ -798,6 +806,7 @@ def player_drop( try: import glfw + import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from OpenGL.GL import glClearColor from version_utils import parse_version @@ -845,12 +854,12 @@ def on_drop(window, count, paths): w, h = session_settings.get("window_size", (1280, 720)) glfw.glfwInit() - glfw.glfwWindowHint(glfw.GLFW_SCALE_TO_MONITOR, glfw.GLFW_TRUE) - glfw.glfwWindowHint(glfw.GLFW_RESIZABLE, 0) window = glfw.glfwCreateWindow(w, h, "Pupil Player") - glfw.glfwWindowHint(glfw.GLFW_RESIZABLE, 1) + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_RESIZABLE, 0) + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_RESIZABLE, 1) - glfw.glfwMakeContextCurrent(window) + glfw.GLFW.glfwMakeContextCurrent(window) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( @@ -858,7 +867,7 @@ def on_drop(window, count, paths): default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) - glfw.glfwSetWindowPos(window, window_pos[0], window_pos[1]) + glfw.GLFW.glfwSetWindowPos(window, window_pos[0], window_pos[1]) glfw.glfwSetDropCallback(window, on_drop) @@ -886,9 +895,11 @@ def display_string(string, font_size, center_y): glfont.set_color_float((1.0, 1.0, 1.0, 1.0)) glfont.draw_text(x, y, string) - while not glfw.glfwWindowShouldClose(window) and not process_was_interrupted: + while ( + not glfw.GLFW.glfwWindowShouldClose(window) and not process_was_interrupted + ): - fb_size = glfw.glfwGetFramebufferSize(window) + fb_size = glfw.GLFW.glfwGetFramebufferSize(window) content_scale = gl_utils.get_content_scale(window) gl_utils.adjust_gl_view(*fb_size) @@ -916,7 +927,7 @@ def display_string(string, font_size, center_y): center_y = 288 + tip_font_size * idx * 1.2 display_string(line, font_size=tip_font_size, center_y=center_y) - glfw.glfwSwapBuffers(window) + glfw.GLFW.glfwSwapBuffers(window) if rec_dir: try: @@ -935,11 +946,11 @@ def display_string(string, font_size, center_y): tip = err.reason rec_dir = None else: - glfw.glfwSetWindowShouldClose(window, True) + glfw.GLFW.glfwSetWindowShouldClose(window, True) - glfw.glfwPollEvents() + glfw.GLFW.glfwPollEvents() - session_settings["window_position"] = glfw.glfwGetWindowPos(window) + session_settings["window_position"] = glfw.GLFW.glfwGetWindowPos(window) session_settings.close() glfw.glfwDestroyWindow(window) if rec_dir: diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index 8bad863a1b..32d2035599 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -118,6 +118,7 @@ def detection_enabled_setter(is_on: bool): # display import glfw + import glfw.GLFW # TODO: Remove when switching to pyglfw API from version_utils import parse_version from pyglui import ui, cygl, __version__ as pyglui_version @@ -332,17 +333,19 @@ def consume_events_and_render_buffer(): gl_utils.glViewport(0, 0, *window_size) try: - clipboard = glfw.glfwGetClipboardString(main_window).decode() + clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() except AttributeError: # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.glfwSetClipboardString(main_window, user_input.clipboard.encode()) + glfw.GLFW.glfwSetClipboardString( + main_window, user_input.clipboard.encode() + ) for button, action, mods in user_input.buttons: - x, y = glfw.glfwGetCursorPos(main_window) + x, y = glfw.GLFW.glfwGetCursorPos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -364,7 +367,7 @@ def consume_events_and_render_buffer(): if plugin.on_char(char_): break - glfw.glfwSwapBuffers(main_window) + glfw.GLFW.glfwSwapBuffers(main_window) # Callback functions def on_resize(window, w, h): @@ -395,8 +398,12 @@ def on_resize(window, w, h): # potentially be dynamically modified, so we re-adjust the size limits every # time here. min_size = int(2 * icon_bar_width * g_pool.gui.scale / framebuffer_scale) - glfw.glfwSetWindowSizeLimits( - window, min_size, min_size, glfw.GLFW_DONT_CARE, glfw.GLFW_DONT_CARE + glfw.GLFW.glfwSetWindowSizeLimits( + window, + min_size, + min_size, + glfw.GLFW.GLFW_DONT_CARE, + glfw.GLFW.GLFW_DONT_CARE, ) # Needed, to update the window buffer while resizing @@ -510,10 +517,10 @@ def handle_notifications(noti): # window and gl setup glfw.glfwInit() - glfw.glfwWindowHint(glfw.GLFW_SCALE_TO_MONITOR, glfw.GLFW_TRUE) + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) if hide_ui: - glfw.glfwWindowHint(glfw.GLFW_VISIBLE, 0) # hide window main_window = glfw.glfwCreateWindow(width, height, "Pupil Capture - World") + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_VISIBLE, 0) # hide window window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( @@ -521,15 +528,15 @@ def handle_notifications(noti): default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) - glfw.glfwSetWindowPos(main_window, window_pos[0], window_pos[1]) + glfw.GLFW.glfwSetWindowPos(main_window, window_pos[0], window_pos[1]) - glfw.glfwMakeContextCurrent(main_window) + glfw.GLFW.glfwMakeContextCurrent(main_window) cygl.utils.init() g_pool.main_window = main_window def reset_restart(): logger.warning("Resetting all settings and restarting Capture.") - glfw.glfwSetWindowShouldClose(main_window, True) + glfw.GLFW.glfwSetWindowShouldClose(main_window, True) ipc_pub.notify({"subject": "clear_settings_process.should_start"}) ipc_pub.notify({"subject": "world_process.should_start", "delay": 2.0}) @@ -574,7 +581,7 @@ def set_window_size(): f_width += icon_bar_width * display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) - glfw.glfwSetWindowSize(main_window, int(f_width), int(f_height)) + glfw.GLFW.glfwSetWindowSize(main_window, int(f_width), int(f_height)) general_settings.append(ui.Button("Reset window size", set_window_size)) general_settings.append( @@ -684,7 +691,7 @@ def window_should_update(): return next(window_update_timer) # trigger setup of window and gl sizes - on_resize(main_window, *glfw.glfwGetFramebufferSize(main_window)) + on_resize(main_window, *glfw.GLFW.glfwGetFramebufferSize(main_window)) if session_settings.get("eye1_process_alive", True): launch_eye_process(1, delay=0.6) @@ -696,7 +703,8 @@ def window_should_update(): # Event loop while ( - not glfw.glfwWindowShouldClose(main_window) and not process_was_interrupted + not glfw.GLFW.glfwWindowShouldClose(main_window) + and not process_was_interrupted ): # fetch newest notifications @@ -742,9 +750,9 @@ def window_should_update(): for d in data: ipc_pub.send(d) - glfw.glfwMakeContextCurrent(main_window) + glfw.GLFW.glfwMakeContextCurrent(main_window) # render visual feedback from loaded plugins - glfw.glfwPollEvents() + glfw.GLFW.glfwPollEvents() if window_should_update() and gl_utils.is_window_visible(main_window): gl_utils.glViewport(0, 0, *camera_render_size) @@ -753,19 +761,19 @@ def window_should_update(): gl_utils.glViewport(0, 0, *window_size) try: - clipboard = glfw.glfwGetClipboardString(main_window).decode() + clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() except AttributeError: # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.glfwSetClipboardString( + glfw.GLFW.glfwSetClipboardString( main_window, user_input.clipboard.encode() ) for button, action, mods in user_input.buttons: - x, y = glfw.glfwGetCursorPos(main_window) + x, y = glfw.GLFW.glfwGetCursorPos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -787,7 +795,7 @@ def window_should_update(): if plugin.on_char(char_): break - glfw.glfwSwapBuffers(main_window) + glfw.GLFW.glfwSwapBuffers(main_window) session_settings["loaded_plugins"] = g_pool.plugins.get_initializers() session_settings["ui_config"] = g_pool.gui.configuration @@ -801,9 +809,11 @@ def window_should_update(): session_settings["audio_mode"] = audio.get_audio_mode() if not hide_ui: - glfw.glfwRestoreWindow(main_window) # need to do this for windows os - session_settings["window_position"] = glfw.glfwGetWindowPos(main_window) - session_window_size = glfw.glfwGetWindowSize(main_window) + glfw.GLFW.glfwRestoreWindow(main_window) # need to do this for windows os + session_settings["window_position"] = glfw.GLFW.glfwGetWindowPos( + main_window + ) + session_window_size = glfw.GLFW.glfwGetWindowSize(main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py index 6257692c62..af0cf9fc5c 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py @@ -1,12 +1,8 @@ import collections import typing as T -from glfw import ( - glfwGetMonitors, - glfwGetMonitorName, - glfwGetPrimaryMonitor, - glfwGetVideoMode, -) +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API try: from typing import OrderedDict as T_OrderedDict # Python 3.7.2 @@ -37,7 +33,7 @@ class GUIMonitor: def __init__(self, index, gl_handle): self.__gl_handle = gl_handle - self.__name = glfwGetMonitorName(gl_handle).decode("utf-8") + self.__name = glfw.GLFW.glfwGetMonitorName(gl_handle).decode("utf-8") self.__index = index @property @@ -70,7 +66,7 @@ def is_available(self) -> bool: @staticmethod def currently_connected_monitors() -> T.List["GUIMonitor"]: - return [GUIMonitor(i, h) for i, h in enumerate(glfwGetMonitors())] + return [GUIMonitor(i, h) for i, h in enumerate(glfw.GLFW.glfwGetMonitors())] @staticmethod def currently_connected_monitors_by_name() -> T_OrderedDict[str, "GUIMonitor"]: @@ -80,7 +76,7 @@ def currently_connected_monitors_by_name() -> T_OrderedDict[str, "GUIMonitor"]: @staticmethod def primary_monitor() -> "GUIMonitor": - gl_handle = glfwGetPrimaryMonitor() + gl_handle = glfw.GLFW.glfwGetPrimaryMonitor() return GUIMonitor(0, gl_handle) @staticmethod diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py index 0792ae05e5..95d26eb674 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py @@ -8,6 +8,7 @@ from gl_utils import adjust_gl_view from gl_utils import basic_gl_setup from gl_utils import clear_gl_screen +import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from pyglui.cygl.utils import draw_polyline @@ -38,7 +39,7 @@ def content_scale(self) -> float: @property def window_size(self) -> T.Tuple[int, int]: if self.__gl_handle is not None: - return glfw.glfwGetFramebufferSize(self.__gl_handle) + return glfw.GLFW.glfwGetFramebufferSize(self.__gl_handle) else: return (0, 0) @@ -47,13 +48,13 @@ def is_open(self) -> bool: return self.__gl_handle is not None def cursor_hide(self): - glfw.glfwSetInputMode( - self.__gl_handle, glfw.GLFW_CURSOR, glfw.GLFW_CURSOR_HIDDEN + glfw.GLFW.glfwSetInputMode( + self.__gl_handle, glfw.GLFW.GLFW_CURSOR, glfw.GLFW.GLFW_CURSOR_HIDDEN ) def cursor_disable(self): - glfw.glfwSetInputMode( - self.__gl_handle, glfw.GLFW_CURSOR, glfw.GLFW_CURSOR_DISABLED + glfw.GLFW.glfwSetInputMode( + self.__gl_handle, glfw.GLFW.GLFW_CURSOR, glfw.GLFW.GLFW_CURSOR_DISABLED ) def open( @@ -93,26 +94,28 @@ def open( # a blank window directly in fullscreen mode. By creating it windowed and # then switching to fullscreen it will stay white the entire time. self.__gl_handle = glfw.glfwCreateWindow( - *size, title, share=glfw.glfwGetCurrentContext() + *size, title, share=glfw.GLFW.glfwGetCurrentContext() ) if not is_fullscreen: - glfw.glfwSetWindowPos(self.__gl_handle, *position) + glfw.GLFW.glfwSetWindowPos(self.__gl_handle, *position) # Register callbacks glfw.glfwSetFramebufferSizeCallback(self.__gl_handle, self.on_resize) glfw.glfwSetKeyCallback(self.__gl_handle, self.on_key) glfw.glfwSetMouseButtonCallback(self.__gl_handle, self.on_mouse_button) - self.on_resize(self.__gl_handle, *glfw.glfwGetFramebufferSize(self.__gl_handle)) + self.on_resize( + self.__gl_handle, *glfw.GLFW.glfwGetFramebufferSize(self.__gl_handle) + ) # gl_state settings with self._switch_to_current_context(): basic_gl_setup() - glfw.glfwSwapInterval(0) + glfw.GLFW.glfwSwapInterval(0) if is_fullscreen: # Switch to full screen here. See NOTE above at glfwCreateWindow(). - glfw.glfwSetWindowMonitor( + glfw.GLFW.glfwSetWindowMonitor( self.__gl_handle, gui_monitor.unsafe_handle, 0, @@ -125,8 +128,8 @@ def close(self): if not self.is_open: return with self._switch_to_current_context(): - glfw.glfwSetInputMode( - self.__gl_handle, glfw.GLFW_CURSOR, glfw.GLFW_CURSOR_NORMAL + glfw.GLFW.glfwSetInputMode( + self.__gl_handle, glfw.GLFW.GLFW_CURSOR, glfw.GLFW.GLFW_CURSOR_NORMAL ) glfw.glfwDestroyWindow(self.__gl_handle) self.__gl_handle = None @@ -136,7 +139,7 @@ def drawing_context(self): if self.__gl_handle is None: return - if glfw.glfwWindowShouldClose(self.__gl_handle): + if glfw.GLFW.glfwWindowShouldClose(self.__gl_handle): self.close() return @@ -152,19 +155,19 @@ def drawing_context(self): yield self.unsafe_handle - glfw.glfwSwapBuffers(self.unsafe_handle) + glfw.GLFW.glfwSwapBuffers(self.unsafe_handle) def on_resize(self, gl_handle, w, h): with self._switch_to_current_context(): adjust_gl_view(w, h) def on_key(self, gl_handle, key, scancode, action, mods): - if action == glfw.GLFW_PRESS: - if key == glfw.GLFW_KEY_ESCAPE: + if action == glfw.GLFW.GLFW_PRESS: + if key == glfw.GLFW.GLFW_KEY_ESCAPE: self.on_key_press_escape() def on_mouse_button(self, gl_handle, button, action, mods): - if action == glfw.GLFW_PRESS: + if action == glfw.GLFW.GLFW_PRESS: self.on_left_click() def on_left_click(self): @@ -175,9 +178,9 @@ def on_key_press_escape(self): @contextlib.contextmanager def _switch_to_current_context(self): - previous_context = glfw.glfwGetCurrentContext() - glfw.glfwMakeContextCurrent(self.__gl_handle) + previous_context = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(self.__gl_handle) try: yield finally: - glfw.glfwMakeContextCurrent(previous_context) + glfw.GLFW.glfwMakeContextCurrent(previous_context) diff --git a/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py b/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py index b9952749f5..6acafbcda3 100644 --- a/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py @@ -15,10 +15,12 @@ import cv2 import numpy as np +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API + from methods import normalize from pyglui import ui from pyglui.cygl.utils import draw_points_norm, RGBA -from glfw import GLFW_PRESS import audio from .controller import GUIMonitor @@ -114,7 +116,7 @@ def gl_display(self): ) def on_click(self, pos, button, action): - if action == GLFW_PRESS and self.is_active: + if action == glfw.GLFW.GLFW_PRESS and self.is_active: self.__feature_tracker.reset(pos) self.__number_of_ref_points_gathered_from_last_click = 0 return True # click consumed diff --git a/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py b/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py index 054b57ba37..d1d33f24df 100644 --- a/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py @@ -15,7 +15,9 @@ import numpy as np from gl_utils import adjust_gl_view, clear_gl_screen, basic_gl_setup import OpenGL.GL as gl -from glfw import * + +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API from circle_detector import CircleTracker from platform import system diff --git a/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py b/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py index 076e33c030..9e5905252c 100644 --- a/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py @@ -25,7 +25,9 @@ from circle_detector import CircleTracker from gl_utils import adjust_gl_view, clear_gl_screen, basic_gl_setup import OpenGL.GL as gl -from glfw import * + +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API from .mixin import MonitorSelectionMixin from .controller import ( diff --git a/pupil_src/shared_modules/camera_intrinsics_estimation.py b/pupil_src/shared_modules/camera_intrinsics_estimation.py index 0ee6012b34..fca0424837 100644 --- a/pupil_src/shared_modules/camera_intrinsics_estimation.py +++ b/pupil_src/shared_modules/camera_intrinsics_estimation.py @@ -25,7 +25,9 @@ from pyglui.cygl.utils import draw_polyline, draw_points, RGBA, draw_gl_texture from pyglui.pyfontstash import fontstash from pyglui.ui import get_opensans_font_path -from glfw import * + +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from plugin import Plugin @@ -38,10 +40,10 @@ # window calbacks def on_resize(window, w, h): - active_window = glfwGetCurrentContext() - glfwMakeContextCurrent(window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(window) adjust_gl_view(w, h) - glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwMakeContextCurrent(active_window) class Camera_Intrinsics_Estimation(Plugin): @@ -103,7 +105,9 @@ def init_ui(self): self.menu.label = "Camera Intrinsics Estimation" def get_monitors_idx_list(): - monitors = [glfwGetMonitorName(m) for m in glfwGetMonitors()] + monitors = [ + glfw.GLFW.glfwGetMonitorName(m) for m in glfw.GLFW.glfwGetMonitors() + ] return range(len(monitors)), monitors if self.monitor_idx not in get_monitors_idx_list()[0]: @@ -181,14 +185,14 @@ def open_window(self): if not self._window: if self.fullscreen: try: - monitor = glfwGetMonitors()[self.monitor_idx] + monitor = glfw.GLFW.glfwGetMonitors()[self.monitor_idx] except Exception: logger.warning( "Monitor at index %s no longer availalbe using default" % idx ) self.monitor_idx = 0 - monitor = glfwGetMonitors()[self.monitor_idx] mode = glfwGetVideoMode(monitor) + monitor = glfw.GLFW.glfwGetMonitors()[self.monitor_idx] height, width = mode[0], mode[1] else: monitor = None @@ -199,11 +203,11 @@ def open_window(self): width, "Calibration", monitor=monitor, - share=glfwGetCurrentContext(), + share=glfw.GLFW.glfwGetCurrentContext(), ) if not self.fullscreen: # move to y = 31 for windows os - glfwSetWindowPos(self._window, 200, 31) + glfw.GLFW.glfwSetWindowPos(self._window, 200, 31) # Register callbacks glfwSetFramebufferSizeCallback(self._window, on_resize) @@ -211,23 +215,23 @@ def open_window(self): glfwSetWindowCloseCallback(self._window, self.on_close) glfwSetMouseButtonCallback(self._window, self.on_window_mouse_button) - on_resize(self._window, *glfwGetFramebufferSize(self._window)) + on_resize(self._window, *glfw.GLFW.glfwGetFramebufferSize(self._window)) # gl_state settings - active_window = glfwGetCurrentContext() - glfwMakeContextCurrent(self._window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(self._window) basic_gl_setup() - glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwMakeContextCurrent(active_window) self.clicks_to_close = 5 def on_window_key(self, window, key, scancode, action, mods): - if action == GLFW_PRESS: - if key == GLFW_KEY_ESCAPE: + if action == glfw.GLFW.GLFW_PRESS: + if key == glfw.GLFW.GLFW_KEY_ESCAPE: self.on_close() def on_window_mouse_button(self, window, button, action, mods): - if action == GLFW_PRESS: + if action == glfw.GLFW.GLFW_PRESS: self.clicks_to_close -= 1 if self.clicks_to_close == 0: self.on_close() @@ -357,14 +361,14 @@ def gl_display(self): gl.glPopMatrix() def gl_display_in_window(self): - active_window = glfwGetCurrentContext() - glfwMakeContextCurrent(self._window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(self._window) clear_gl_screen() gl.glMatrixMode(gl.GL_PROJECTION) gl.glLoadIdentity() - p_window_size = glfwGetWindowSize(self._window) + p_window_size = glfw.GLFW.glfwGetWindowSize(self._window) r = p_window_size[0] / 15.0 # compensate for radius of marker gl.glOrtho(-r, p_window_size[0] + r, p_window_size[1] + r, -r, -1, 1) @@ -387,8 +391,8 @@ def gl_display_in_window(self): "Touch {} more times to close window.".format(self.clicks_to_close), ) - glfwSwapBuffers(self._window) - glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwSwapBuffers(self._window) + glfw.GLFW.glfwMakeContextCurrent(active_window) def get_init_dict(self): return {"monitor_idx": self.monitor_idx} diff --git a/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py b/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py index 19e141a326..46ce51b8a0 100644 --- a/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py +++ b/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py @@ -14,6 +14,7 @@ import numpy as np import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API import tasklib from gaze_producer import model, worker from observable import Observable @@ -102,7 +103,7 @@ def jump_to_prev_ref(self): self._seek_to_frame(prev_ref.frame_index) def _on_click(self, pos, button, action): - if action == glfw.GLFW_PRESS: + if action == glfw.GLFW.GLFW_PRESS: self._add_or_delete_ref_on_click(pos) def _add_or_delete_ref_on_click(self, pos): diff --git a/pupil_src/shared_modules/gl_utils/window_position_manager.py b/pupil_src/shared_modules/gl_utils/window_position_manager.py index d8c5925e27..3160698bfb 100644 --- a/pupil_src/shared_modules/gl_utils/window_position_manager.py +++ b/pupil_src/shared_modules/gl_utils/window_position_manager.py @@ -13,6 +13,7 @@ import typing as T import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils @@ -49,7 +50,7 @@ def validate_previous_position(monitor) -> bool: window_position=previous_position, ) - if any(validate_previous_position(m) for m in glfw.glfwGetMonitors()): + if any(validate_previous_position(m) for m in glfw.GLFW.glfwGetMonitors()): return previous_position else: return default_position @@ -62,7 +63,7 @@ def _will_window_be_visible_in_monitor( window, monitor, window_position, min_visible_width=30, min_visible_height=20 ) -> bool: # Get the current window size and edges, and monitor rect - window_size = glfw.glfwGetWindowSize(window) + window_size = glfw.GLFW.glfwGetWindowSize(window) window_edges = gl_utils.get_window_frame_size_margins(window) monitor_rect = gl_utils.get_monitor_workarea_rect(monitor) diff --git a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py index cabe90ab9b..7f1e412cdf 100644 --- a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py +++ b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py @@ -16,6 +16,7 @@ import gl_utils import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API from observable import Observable # FOR SMOOTH RENDERING @@ -62,20 +63,20 @@ def _init_trackball(): def _glfw_init(self): glfw.glfwInit() - glfw.glfwWindowHint(glfw.GLFW_SCALE_TO_MONITOR, glfw.GLFW_TRUE) window = glfw.glfwCreateWindow( title="Head Pose Tracker Visualizer", share=glfw.glfwGetCurrentContext() + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) ) return window @staticmethod def _gl_state_settings(window): - active_window = glfw.glfwGetCurrentContext() - glfw.glfwMakeContextCurrent(window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(window) gl_utils.basic_gl_setup() gl_utils.make_coord_system_norm_based() - glfw.glfwSwapInterval(0) - glfw.glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwSwapInterval(0) + glfw.GLFW.glfwMakeContextCurrent(active_window) def _register_callbacks(self, window): glfw.glfwSetWindowSizeCallback(window, self._on_set_window_size) @@ -87,8 +88,10 @@ def _register_callbacks(self, window): glfw.glfwSetWindowCloseCallback(window, self._on_set_window_close) def _set_initial_window_state(self): - glfw.glfwSetWindowPos(self._window, *self._general_settings.window_position) - glfw.glfwSetWindowSize(self._window, *self._general_settings.window_size) + glfw.GLFW.glfwSetWindowPos( + self._window, *self._general_settings.window_position + ) + glfw.GLFW.glfwSetWindowSize(self._window, *self._general_settings.window_size) def _on_set_window_size(self, window, w, h): self._general_settings.window_size = (w, h) @@ -98,16 +101,16 @@ def _on_set_window_pos(self, window, x, y): def _on_set_frame_buffer_size(self, window, w, h): self._trackball.set_window_size(w, h) - active_window = glfw.glfwGetCurrentContext() - glfw.glfwMakeContextCurrent(window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(window) gl_utils.adjust_gl_view(w, h) - glfw.glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwMakeContextCurrent(active_window) def _on_set_mouse_button(self, window, button, action, mods): - if action == glfw.GLFW_PRESS: + if action == glfw.GLFW.GLFW_PRESS: self._input["down"] = True - self._input["mouse"] = glfw.glfwGetCursorPos(window) - elif action == glfw.GLFW_RELEASE: + self._input["mouse"] = glfw.GLFW.glfwGetCursorPos(window) + elif action == glfw.GLFW.GLFW_RELEASE: self._input["down"] = False def _on_set_cursor_pos(self, window, x, y): @@ -139,17 +142,17 @@ def _on_gl_display(self): if not self._window: return - active_window = glfw.glfwGetCurrentContext() - glfw.glfwMakeContextCurrent(self._window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(self._window) self._init_3d_window() self._trackball.push() self._render() self._trackball.pop() - glfw.glfwSwapBuffers(self._window) - glfw.glfwMakeContextCurrent(active_window) - glfw.glfwPollEvents() + glfw.GLFW.glfwSwapBuffers(self._window) + glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwPollEvents() @staticmethod def _init_3d_window(): diff --git a/pupil_src/shared_modules/log_display.py b/pupil_src/shared_modules/log_display.py index 04415ee8ae..5579ee7cff 100644 --- a/pupil_src/shared_modules/log_display.py +++ b/pupil_src/shared_modules/log_display.py @@ -12,11 +12,11 @@ from plugin import System_Plugin_Base from pyglui.cygl.utils import Render_Target, push_ortho, pop_ortho import logging -from glfw import glfwGetFramebufferSize, glfwGetCurrentContext import zmq_tools from pyglui.pyfontstash import fontstash from pyglui.ui import get_opensans_font_path import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils @@ -67,7 +67,9 @@ def init_ui(self): self.glfont.set_color_float((0.2, 0.5, 0.9, 1.0)) self.glfont.set_align_string(v_align="center", h_align="middle") - self.window_size = glfwGetFramebufferSize(glfwGetCurrentContext()) + self.window_size = glfw.GLFW.glfwGetFramebufferSize( + glfw.GLFW.glfwGetCurrentContext() + ) self.tex = Render_Target(*self.window_size) self._socket = zmq_tools.Msg_Receiver( diff --git a/pupil_src/shared_modules/marker_auto_trim_marks.py b/pupil_src/shared_modules/marker_auto_trim_marks.py index 8442f3dd5b..f16f6bd7f9 100644 --- a/pupil_src/shared_modules/marker_auto_trim_marks.py +++ b/pupil_src/shared_modules/marker_auto_trim_marks.py @@ -22,7 +22,9 @@ from gl_utils import adjust_gl_view, clear_gl_screen, basic_gl_setup, cvmat_to_glmat from pyglui.cygl.utils import RGBA, draw_points, draw_polyline from OpenGL.GL import * -from glfw import * + +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API import numpy as np from itertools import groupby diff --git a/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py index 418af9da11..dbe248d533 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py @@ -15,6 +15,7 @@ from pyglui.cygl.utils import draw_gl_texture import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API from gl_utils import ( adjust_gl_view, basic_gl_setup, diff --git a/pupil_src/shared_modules/roi.py b/pupil_src/shared_modules/roi.py index 3df3505290..4c1c184195 100644 --- a/pupil_src/shared_modules/roi.py +++ b/pupil_src/shared_modules/roi.py @@ -19,6 +19,7 @@ from pyglui.cygl.utils import draw_polyline as cygl_draw_polyline import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API from methods import denormalize, normalize from observable import Observable from plugin import Plugin @@ -289,12 +290,12 @@ def on_click(self, pos: Vec2, button: int, action: int) -> bool: if not self.has_frame or self.model.is_invalid(): return False - if action == glfw.GLFW_PRESS: + if action == glfw.GLFW.GLFW_PRESS: clicked_handle = self.get_handle_at(pos) if clicked_handle != self.active_handle: self.active_handle = clicked_handle return True - elif action == glfw.GLFW_RELEASE: + elif action == glfw.GLFW.GLFW_RELEASE: if self.active_handle != Handle.NONE: self.active_handle = Handle.NONE return True diff --git a/pupil_src/shared_modules/service_ui.py b/pupil_src/shared_modules/service_ui.py index 029ef7123f..edc7b5cb4d 100644 --- a/pupil_src/shared_modules/service_ui.py +++ b/pupil_src/shared_modules/service_ui.py @@ -16,6 +16,7 @@ import numpy as np import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from pyglui import ui, cygl from plugin import System_Plugin_Base @@ -49,10 +50,10 @@ def __init__( self.texture = np.zeros((1, 1, 3), dtype=np.uint8) + 128 glfw.glfwInit() - glfw.glfwWindowHint(glfw.GLFW_SCALE_TO_MONITOR, glfw.GLFW_TRUE) + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) if g_pool.hide_ui: - glfw.glfwWindowHint(glfw.GLFW_VISIBLE, 0) # hide window main_window = glfw.glfwCreateWindow(*window_size, "Pupil Service") + glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_VISIBLE, 0) # hide window window_position_manager = gl_utils.WindowPositionManager() window_position = window_position_manager.new_window_position( @@ -60,9 +61,9 @@ def __init__( default_position=window_position_default, previous_position=window_position, ) - glfw.glfwSetWindowPos(main_window, *window_position) + glfw.GLFW.glfwSetWindowPos(main_window, *window_position) - glfw.glfwMakeContextCurrent(main_window) + glfw.GLFW.glfwMakeContextCurrent(main_window) cygl.utils.init() g_pool.main_window = main_window @@ -120,11 +121,11 @@ def set_window_size(): f_height *= display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) - glfw.glfwSetWindowSize(main_window, int(f_width), int(f_height)) + glfw.GLFW.glfwSetWindowSize(main_window, int(f_width), int(f_height)) def reset_restart(): logger.warning("Resetting all settings and restarting Capture.") - glfw.glfwSetWindowShouldClose(main_window, True) + glfw.GLFW.glfwSetWindowShouldClose(main_window, True) self.notify_all({"subject": "clear_settings_process.should_start"}) self.notify_all({"subject": "service_process.should_start", "delay": 2.0}) @@ -174,7 +175,7 @@ def reset_restart(): g_pool.gui.configuration = ui_config gl_utils.basic_gl_setup() - on_resize(g_pool.main_window, *glfw.glfwGetFramebufferSize(main_window)) + on_resize(g_pool.main_window, *glfw.GLFW.glfwGetFramebufferSize(main_window)) def on_notify(self, notification): if notification["subject"] == "service_process.ui.should_update": @@ -184,12 +185,12 @@ def on_notify(self, notification): self.update_ui() def update_ui(self): - if not glfw.glfwWindowShouldClose(self.g_pool.main_window): + if not glfw.GLFW.glfwWindowShouldClose(self.g_pool.main_window): gl_utils.glViewport(0, 0, *self.window_size) - glfw.glfwPollEvents() + glfw.GLFW.glfwPollEvents() self.gl_display() try: - clipboard = glfw.glfwGetClipboardString( + clipboard = glfw.GLFW.glfwGetClipboardString( self.g_pool.main_window ).decode() except AttributeError: # clipbaord is None, might happen on startup @@ -198,11 +199,11 @@ def update_ui(self): user_input = self.g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.glfwSetClipboardString( + glfw.GLFW.glfwSetClipboardString( self.g_pool.main_window, user_input.clipboard.encode() ) - glfw.glfwSwapBuffers(self.g_pool.main_window) + glfw.GLFW.glfwSwapBuffers(self.g_pool.main_window) else: self.notify_all({"subject": "service_process.should_stop"}) @@ -215,14 +216,14 @@ def gl_display(self): def cleanup(self): if not self.g_pool.hide_ui: - glfw.glfwRestoreWindow(self.g_pool.main_window) + glfw.GLFW.glfwRestoreWindow(self.g_pool.main_window) del self.g_pool.menubar[:] self.g_pool.gui.remove(self.g_pool.menubar) self.g_pool.gui.terminate() glfw.glfwDestroyWindow(self.g_pool.main_window) - glfw.glfwTerminate() + glfw.GLFW.glfwTerminate() del self.g_pool.gui del self.g_pool.main_window @@ -230,11 +231,11 @@ def cleanup(self): def get_init_dict(self): sess = { - "window_position": glfw.glfwGetWindowPos(self.g_pool.main_window), + "window_position": glfw.GLFW.glfwGetWindowPos(self.g_pool.main_window), "ui_config": self.g_pool.gui.configuration, } - session_window_size = glfw.glfwGetWindowSize(self.g_pool.main_window) + session_window_size = glfw.GLFW.glfwGetWindowSize(self.g_pool.main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): diff --git a/pupil_src/shared_modules/surface_tracker/gui.py b/pupil_src/shared_modules/surface_tracker/gui.py index a087d01392..69a746068c 100644 --- a/pupil_src/shared_modules/surface_tracker/gui.py +++ b/pupil_src/shared_modules/surface_tracker/gui.py @@ -21,6 +21,7 @@ import gl_utils import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API from .surface_marker import Surface_Marker_Type @@ -400,7 +401,7 @@ def on_click(self, pos, button, action): return def _on_click_menu_buttons(self, action, pos): - if action == glfw.GLFW_PRESS: + if action == glfw.GLFW.GLFW_PRESS: for surface in reversed(self.tracker.surfaces): if not surface.detected: @@ -438,11 +439,17 @@ def _on_click_corner_handles(self, action, pos): ) for idx, corner in enumerate(img_corners): dist = np.linalg.norm(corner - pos) - if action == glfw.GLFW_PRESS and dist < self.button_click_radius: + if ( + action == glfw.GLFW.GLFW_PRESS + and dist < self.button_click_radius + ): self.tracker._edit_surf_verts.append((surface, idx)) # click event consumed; give a chance for other surfaces' corners to react to it was_event_consumed = True - elif action == glfw.GLFW_RELEASE and self.tracker._edit_surf_verts: + elif ( + action == glfw.GLFW.GLFW_RELEASE + and self.tracker._edit_surf_verts + ): self.tracker.notify_all( { "subject": "surface_tracker.surfaces_changed", @@ -456,7 +463,7 @@ def _on_click_corner_handles(self, action, pos): return was_event_consumed def _on_click_marker_toggles(self, action, pos): - if action == glfw.GLFW_PRESS: + if action == glfw.GLFW.GLFW_PRESS: for surface in self._edit_surf_markers: if not surface.detected: continue @@ -563,10 +570,10 @@ def open_window(self): win_w, "Reference Surface: " + self.surface.name, monitor=monitor, - share=glfw.glfwGetCurrentContext(), + share=glfw.GLFW.glfwGetCurrentContext(), ) - glfw.glfwSetWindowPos( + glfw.GLFW.glfwSetWindowPos( self._window, self.window_position_default[0], self.window_position_default[1], @@ -583,18 +590,20 @@ def open_window(self): glfw.glfwSetCursorPosCallback(self._window, self.on_pos) glfw.glfwSetScrollCallback(self._window, self.on_scroll) - self.on_resize(self._window, *glfw.glfwGetFramebufferSize(self._window)) + self.on_resize( + self._window, *glfw.GLFW.glfwGetFramebufferSize(self._window) + ) # gl_state settings - active_window = glfw.glfwGetCurrentContext() - glfw.glfwMakeContextCurrent(self._window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(self._window) gl_utils.basic_gl_setup() gl_utils.make_coord_system_norm_based() # refresh speed settings - glfw.glfwSwapInterval(0) + glfw.GLFW.glfwSwapInterval(0) - glfw.glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwMakeContextCurrent(active_window) def close_window(self): if self._window: @@ -610,8 +619,8 @@ def gl_display_in_window(self, world_tex): here we map a selected surface onto a separate window. """ if self._window and self.surface.detected: - active_window = glfw.glfwGetCurrentContext() - glfw.glfwMakeContextCurrent(self._window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(self._window) gl_utils.clear_gl_screen() # cv uses 3x3 gl uses 4x4 transformation matrices @@ -643,8 +652,8 @@ def gl_display_in_window(self, world_tex): self.draw_recent_pupil_positions() - glfw.glfwSwapBuffers(self._window) - glfw.glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwSwapBuffers(self._window) + glfw.GLFW.glfwMakeContextCurrent(active_window) def draw_recent_pupil_positions(self): try: @@ -662,24 +671,24 @@ def draw_recent_pupil_positions(self): def on_resize(self, window, w, h): self.trackball.set_window_size(w, h) - active_window = glfw.glfwGetCurrentContext() - glfw.glfwMakeContextCurrent(window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(window) gl_utils.adjust_gl_view(w, h) - glfw.glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwMakeContextCurrent(active_window) def on_window_key(self, window, key, scancode, action, mods): - if action == glfw.GLFW_PRESS: - if key == glfw.GLFW_KEY_ESCAPE: + if action == glfw.GLFW.GLFW_PRESS: + if key == glfw.GLFW.GLFW_KEY_ESCAPE: self.on_close() def on_close(self, window=None): self.close_window() def on_window_mouse_button(self, window, button, action, mods): - if action == glfw.GLFW_PRESS: + if action == glfw.GLFW.GLFW_PRESS: self.input["down"] = True - self.input["mouse"] = glfw.glfwGetCursorPos(window) - if action == glfw.GLFW_RELEASE: + self.input["mouse"] = glfw.GLFW.glfwGetCursorPos(window) + if action == glfw.GLFW.GLFW_RELEASE: self.input["down"] = False def on_pos(self, window, x, y): diff --git a/pupil_src/shared_modules/system_graphs.py b/pupil_src/shared_modules/system_graphs.py index ecda5c1b9d..ace0115d02 100644 --- a/pupil_src/shared_modules/system_graphs.py +++ b/pupil_src/shared_modules/system_graphs.py @@ -12,6 +12,7 @@ import os import psutil import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from pyglui import ui, graph from pyglui.cygl.utils import RGBA, mix_smooth @@ -73,7 +74,7 @@ def init_ui(self): self.on_window_resize(self.g_pool.main_window) def on_window_resize(self, window, *args): - fb_size = glfw.glfwGetFramebufferSize(window) + fb_size = glfw.GLFW.glfwGetFramebufferSize(window) content_scale = gl_utils.get_content_scale(window) self.cpu_graph.scale = content_scale diff --git a/pupil_src/shared_modules/video_overlay/ui/interactions.py b/pupil_src/shared_modules/video_overlay/ui/interactions.py index 138ebf4ed5..e8fef69007 100644 --- a/pupil_src/shared_modules/video_overlay/ui/interactions.py +++ b/pupil_src/shared_modules/video_overlay/ui/interactions.py @@ -8,8 +8,9 @@ See COPYING and COPYING.LESSER for license details. ---------------------------------------------------------------------------~(*) """ +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API -from glfw import get_content_scale, glfwGetCurrentContext, glfwGetCursorPos, GLFW_PRESS import gl_utils from methods import normalize, denormalize @@ -25,7 +26,7 @@ def on_click(self, pos, button, action): if not self.overlay.valid_video_loaded: return False # click event has not been consumed - click_engaged = action == GLFW_PRESS + click_engaged = action == glfw.GLFW.GLFW_PRESS if click_engaged and self._in_bounds(pos): self.drag_offset = self._calculate_offset(pos) return True diff --git a/pupil_src/shared_modules/vis_watermark.py b/pupil_src/shared_modules/vis_watermark.py index 56609309cd..3f5be16891 100644 --- a/pupil_src/shared_modules/vis_watermark.py +++ b/pupil_src/shared_modules/vis_watermark.py @@ -17,7 +17,8 @@ import os from pyglui import ui -from glfw import glfwGetCursorPos, glfwGetWindowSize, glfwGetCurrentContext +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API from methods import normalize, denormalize import logging @@ -80,8 +81,10 @@ def recent_events(self, events): if not frame: return if self.drag_offset is not None: - pos = glfwGetCursorPos(glfwGetCurrentContext()) - pos = normalize(pos, glfwGetWindowSize(glfwGetCurrentContext())) + pos = glfw.GLFW.glfwGetCursorPos(glfw.GLFW.glfwGetCurrentContext()) + pos = normalize( + pos, glfw.GLFW.glfwGetWindowSize(glfw.GLFW.glfwGetCurrentContext()) + ) pos = denormalize( pos, (frame.img.shape[1], frame.img.shape[0]) ) # Position in img pixels diff --git a/pupil_src/shared_modules/visualizer.py b/pupil_src/shared_modules/visualizer.py index 2f6a347132..87c8a91ce5 100644 --- a/pupil_src/shared_modules/visualizer.py +++ b/pupil_src/shared_modules/visualizer.py @@ -9,7 +9,8 @@ ---------------------------------------------------------------------------~(*) """ -from glfw import * +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from OpenGL.GL import * from platform import system @@ -48,21 +49,21 @@ def __init__(self, g_pool, name="Visualizer", run_independently=False): def begin_update_window(self): if self.window: - if glfwWindowShouldClose(self.window): + if glfw.GLFW.glfwWindowShouldClose(self.window): self.close_window() return - self.other_window = glfwGetCurrentContext() - glfwMakeContextCurrent(self.window) + self.other_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(self.window) def update_window(self): pass def end_update_window(self): if self.window: - glfwSwapBuffers(self.window) - glfwPollEvents() - glfwMakeContextCurrent(self.other_window) + glfw.GLFW.glfwSwapBuffers(self.window) + glfw.GLFW.glfwPollEvents() + glfw.GLFW.glfwMakeContextCurrent(self.other_window) ############## DRAWING FUNCTIONS ############################## @@ -166,8 +167,10 @@ def open_window(self): # get glfw started if self.run_independently: glfwInit() - glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE) self.window = glfwCreateWindow( + glfw.GLFW.glfwWindowHint( + glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE + ) self.window_size[0], self.window_size[1], self.name, None ) else: @@ -176,14 +179,14 @@ def open_window(self): self.window_size[1], self.name, None, - share=glfwGetCurrentContext(), + share=glfw.GLFW.glfwGetCurrentContext(), ) - self.other_window = glfwGetCurrentContext() + self.other_window = glfw.GLFW.glfwGetCurrentContext() - glfwMakeContextCurrent(self.window) - glfwSwapInterval(0) - glfwSetWindowPos( + glfw.GLFW.glfwMakeContextCurrent(self.window) + glfw.GLFW.glfwSwapInterval(0) + glfw.GLFW.glfwSetWindowPos( self.window, window_position_default[0], window_position_default[1] ) # Register callbacks window @@ -206,8 +209,8 @@ def open_window(self): self.glfont.add_font("opensans", get_opensans_font_path()) self.glfont.set_size(18) self.glfont.set_color_float((0.2, 0.5, 0.9, 1.0)) - self.on_resize(self.window, *glfwGetFramebufferSize(self.window)) - glfwMakeContextCurrent(self.other_window) + self.on_resize(self.window, *glfw.GLFW.glfwGetFramebufferSize(self.window)) + glfw.GLFW.glfwMakeContextCurrent(self.other_window) ############ window callbacks ################# def on_resize(self, window, w, h): @@ -215,17 +218,17 @@ def on_resize(self, window, w, h): w = max(w, 1) self.window_size = (w, h) - active_window = glfwGetCurrentContext() - glfwMakeContextCurrent(window) + active_window = glfw.GLFW.glfwGetCurrentContext() + glfw.GLFW.glfwMakeContextCurrent(window) self.adjust_gl_view(w, h) - glfwMakeContextCurrent(active_window) + glfw.GLFW.glfwMakeContextCurrent(active_window) def on_window_mouse_button(self, window, button, action, mods): # self.gui.update_button(button,action,mods) - if action == GLFW_PRESS: + if action == glfw.GLFW.GLFW_PRESS: self.input["button"] = button - self.input["mouse"] = glfwGetCursorPos(window) - if action == GLFW_RELEASE: + self.input["mouse"] = glfw.GLFW.glfwGetCursorPos(window) + if action == glfw.GLFW.GLFW_RELEASE: self.input["button"] = None def on_pos(self, window, x, y): @@ -233,11 +236,11 @@ def on_pos(self, window, x, y): window, x, y, cached_scale=None ) # self.gui.update_mouse(x,y) - if self.input["button"] == GLFW_MOUSE_BUTTON_RIGHT: + if self.input["button"] == glfw.GLFW.GLFW_MOUSE_BUTTON_RIGHT: old_x, old_y = self.input["mouse"] self.trackball.drag_to(x - old_x, y - old_y) self.input["mouse"] = x, y - if self.input["button"] == GLFW_MOUSE_BUTTON_LEFT: + if self.input["button"] == glfw.GLFW.GLFW_MOUSE_BUTTON_LEFT: old_x, old_y = self.input["mouse"] self.trackball.pan_to(x - old_x, y - old_y) self.input["mouse"] = x, y From b9ee7bb051c351ef452f0661cfa64ca41d1c64e9 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Wed, 23 Sep 2020 09:43:33 +0200 Subject: [PATCH 04/57] Rename adapted glfw functions to gl_utils.legacy_* --- pupil_src/launchables/eye.py | 26 +- pupil_src/launchables/player.py | 32 +- pupil_src/launchables/world.py | 26 +- .../controller/gui_monitor.py | 2 +- .../controller/gui_window.py | 16 +- .../camera_intrinsics_estimation.py | 16 +- pupil_src/shared_modules/gl_utils/__init__.py | 20 + .../shared_modules/gl_utils/glfw_legacy.py | 229 +++++ pupil_src/shared_modules/glfw.py | 843 ------------------ .../head_pose_tracker/ui/gl_window.py | 29 +- pupil_src/shared_modules/service_ui.py | 18 +- .../shared_modules/surface_tracker/gui.py | 18 +- pupil_src/shared_modules/visualizer.py | 28 +- 13 files changed, 371 insertions(+), 932 deletions(-) create mode 100644 pupil_src/shared_modules/gl_utils/glfw_legacy.py delete mode 100644 pupil_src/shared_modules/glfw.py diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index 7fdea70b55..585234a436 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -408,7 +408,7 @@ def toggle_general_settings(collapsed): general_settings.collapsed = collapsed # Initialize glfw - glfw.glfwInit() + gl_utils.legacy_glfw_init() glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) if hide_ui: glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_VISIBLE, 0) # hide window @@ -421,7 +421,9 @@ def toggle_general_settings(collapsed): default_window_size = 500 + icon_bar_width, 500 width, height = session_settings.get("window_size", default_window_size) - main_window = glfw.glfwCreateWindow(width, height, title, None, None) + main_window = gl_utils.legacy_glfw_create_window( + width, height, title, None, None + ) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( @@ -528,14 +530,16 @@ def set_window_size(): g_pool.rec_path = None # Register callbacks main_window - glfw.glfwSetFramebufferSizeCallback(main_window, on_resize) - glfw.glfwSetWindowIconifyCallback(main_window, on_iconify) - glfw.glfwSetKeyCallback(main_window, on_window_key) - glfw.glfwSetCharCallback(main_window, on_window_char) - glfw.glfwSetMouseButtonCallback(main_window, on_window_mouse_button) - glfw.glfwSetCursorPosCallback(main_window, on_pos) - glfw.glfwSetScrollCallback(main_window, on_scroll) - glfw.glfwSetDropCallback(main_window, on_drop) + gl_utils.legacy_glfw_set_framebuffer_size_callback(main_window, on_resize) + gl_utils.legacy_glfw_set_window_iconify_callback(main_window, on_iconify) + gl_utils.legacy_glfw_set_key_callback(main_window, on_window_key) + gl_utils.legacy_glfw_set_char_callback(main_window, on_window_char) + gl_utils.legacy_glfw_set_mouse_button_callback( + main_window, on_window_mouse_button + ) + gl_utils.legacy_glfw_set_cursor_pos_callback(main_window, on_pos) + gl_utils.legacy_glfw_set_scroll_callback(main_window, on_scroll) + gl_utils.legacy_glfw_set_drop_callback(main_window, on_drop) # load last gui configuration g_pool.gui.configuration = session_settings.get("ui_config", {}) @@ -760,7 +764,7 @@ def window_should_update(): plugin.alive = False g_pool.plugins.clean() - glfw.glfwDestroyWindow(main_window) + gl_utils.legacy_glfw_destroy_window(main_window) g_pool.gui.terminate() glfw.GLFW.glfwTerminate() logger.info("Process shutting down.") diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index 727b20d32d..b6a751d14e 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -365,9 +365,11 @@ def get_dt(): window_name = f"Pupil Player: {meta_info.recording_name} - {rec_dir}" - glfw.glfwInit() - main_window = glfw.glfwCreateWindow(width, height, window_name, None, None) + gl_utils.legacy_glfw_init() glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) + main_window = gl_utils.legacy_glfw_create_window( + width, height, window_name, None, None + ) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( @@ -610,13 +612,15 @@ def set_window_size(): ) # Register callbacks main_window - glfw.glfwSetFramebufferSizeCallback(main_window, on_resize) - glfw.glfwSetKeyCallback(main_window, on_window_key) - glfw.glfwSetCharCallback(main_window, on_window_char) - glfw.glfwSetMouseButtonCallback(main_window, on_window_mouse_button) - glfw.glfwSetCursorPosCallback(main_window, on_pos) - glfw.glfwSetScrollCallback(main_window, on_scroll) - glfw.glfwSetDropCallback(main_window, on_drop) + gl_utils.legacy_glfw_set_framebuffer_size_callback(main_window, on_resize) + gl_utils.legacy_glfw_set_key_callback(main_window, on_window_key) + gl_utils.legacy_glfw_set_char_callback(main_window, on_window_char) + gl_utils.legacy_glfw_set_mouse_button_callback( + main_window, on_window_mouse_button + ) + gl_utils.legacy_glfw_set_cursor_pos_callback(main_window, on_pos) + gl_utils.legacy_glfw_set_scroll_callback(main_window, on_scroll) + gl_utils.legacy_glfw_set_drop_callback(main_window, on_drop) toggle_general_settings(True) @@ -767,7 +771,7 @@ def handle_notifications(n): g_pool.plugins.clean() g_pool.gui.terminate() - glfw.glfwDestroyWindow(main_window) + gl_utils.legacy_glfw_destroy_window(main_window) except Exception: import traceback @@ -853,10 +857,10 @@ def on_drop(window, count, paths): session_settings.clear() w, h = session_settings.get("window_size", (1280, 720)) - glfw.glfwInit() - window = glfw.glfwCreateWindow(w, h, "Pupil Player") + gl_utils.legacy_glfw_init() glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_RESIZABLE, 0) + window = gl_utils.legacy_glfw_create_window(w, h, "Pupil Player") glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_RESIZABLE, 1) glfw.GLFW.glfwMakeContextCurrent(window) @@ -869,7 +873,7 @@ def on_drop(window, count, paths): ) glfw.GLFW.glfwSetWindowPos(window, window_pos[0], window_pos[1]) - glfw.glfwSetDropCallback(window, on_drop) + gl_utils.legacy_glfw_set_drop_callback(window, on_drop) glfont = fontstash.Context() glfont.add_font("roboto", get_roboto_font_path()) @@ -952,7 +956,7 @@ def display_string(string, font_size, center_y): session_settings["window_position"] = glfw.GLFW.glfwGetWindowPos(window) session_settings.close() - glfw.glfwDestroyWindow(window) + gl_utils.legacy_glfw_destroy_window(window) if rec_dir: ipc_pub.notify( {"subject": "player_process.should_start", "rec_dir": rec_dir} diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index 32d2035599..28bd5ff130 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -516,11 +516,13 @@ def handle_notifications(noti): ) # window and gl setup - glfw.glfwInit() + gl_utils.legacy_glfw_init() glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) if hide_ui: - main_window = glfw.glfwCreateWindow(width, height, "Pupil Capture - World") glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_VISIBLE, 0) # hide window + main_window = gl_utils.legacy_glfw_create_window( + width, height, "Pupil Capture - World" + ) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( @@ -662,13 +664,15 @@ def set_window_size(): ) # Register callbacks main_window - glfw.glfwSetFramebufferSizeCallback(main_window, on_resize) - glfw.glfwSetKeyCallback(main_window, on_window_key) - glfw.glfwSetCharCallback(main_window, on_window_char) - glfw.glfwSetMouseButtonCallback(main_window, on_window_mouse_button) - glfw.glfwSetCursorPosCallback(main_window, on_pos) - glfw.glfwSetScrollCallback(main_window, on_scroll) - glfw.glfwSetDropCallback(main_window, on_drop) + gl_utils.legacy_glfw_set_framebuffer_size_callback(main_window, on_resize) + gl_utils.legacy_glfw_set_key_callback(main_window, on_window_key) + gl_utils.legacy_glfw_set_char_callback(main_window, on_window_char) + gl_utils.legacy_glfw_set_mouse_button_callback( + main_window, on_window_mouse_button + ) + gl_utils.legacy_glfw_set_cursor_pos_callback(main_window, on_pos) + gl_utils.legacy_glfw_set_scroll_callback(main_window, on_scroll) + gl_utils.legacy_glfw_set_drop_callback(main_window, on_drop) # gl_state settings gl_utils.basic_gl_setup() @@ -831,8 +835,8 @@ def window_should_update(): g_pool.plugins.clean() g_pool.gui.terminate() - glfw.glfwDestroyWindow(main_window) - glfw.glfwTerminate() + gl_utils.legacy_glfw_destroy_window(main_window) + glfw.GLFW.glfwTerminate() except Exception: import traceback diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py index af0cf9fc5c..2b28e01874 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py @@ -57,7 +57,7 @@ def refresh_rate(self) -> int: @property def current_video_mode(self) -> "GUIMonitor.VideoMode": - gl_video_mode = glfwGetVideoMode(self.__gl_handle) + gl_video_mode = gl_utils.legacy_glfw_get_video_mode(self.__gl_handle) return GUIMonitor.VideoMode(*gl_video_mode) @property diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py index 95d26eb674..8635b9d0fb 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py @@ -93,7 +93,7 @@ def open( # windows you might experience a black screen for up to 1 sec when creating # a blank window directly in fullscreen mode. By creating it windowed and # then switching to fullscreen it will stay white the entire time. - self.__gl_handle = glfw.glfwCreateWindow( + self.__gl_handle = gl_utils.legacy_glfw_create_window( *size, title, share=glfw.GLFW.glfwGetCurrentContext() ) @@ -101,9 +101,13 @@ def open( glfw.GLFW.glfwSetWindowPos(self.__gl_handle, *position) # Register callbacks - glfw.glfwSetFramebufferSizeCallback(self.__gl_handle, self.on_resize) - glfw.glfwSetKeyCallback(self.__gl_handle, self.on_key) - glfw.glfwSetMouseButtonCallback(self.__gl_handle, self.on_mouse_button) + gl_utils.legacy_glfw_set_framebuffer_size_callback( + self.__gl_handle, self.on_resize + ) + gl_utils.legacy_glfw_set_key_callback(self.__gl_handle, self.on_key) + gl_utils.legacy_glfw_set_mouse_button_callback( + self.__gl_handle, self.on_mouse_button + ) self.on_resize( self.__gl_handle, *glfw.GLFW.glfwGetFramebufferSize(self.__gl_handle) ) @@ -114,7 +118,7 @@ def open( glfw.GLFW.glfwSwapInterval(0) if is_fullscreen: - # Switch to full screen here. See NOTE above at glfwCreateWindow(). + # Switch to full screen here. See NOTE above at legacy_glfw_create_window(). glfw.GLFW.glfwSetWindowMonitor( self.__gl_handle, gui_monitor.unsafe_handle, @@ -131,7 +135,7 @@ def close(self): glfw.GLFW.glfwSetInputMode( self.__gl_handle, glfw.GLFW.GLFW_CURSOR, glfw.GLFW.GLFW_CURSOR_NORMAL ) - glfw.glfwDestroyWindow(self.__gl_handle) + gl_utils.legacy_glfw_destroy_window(self.__gl_handle) self.__gl_handle = None @contextlib.contextmanager diff --git a/pupil_src/shared_modules/camera_intrinsics_estimation.py b/pupil_src/shared_modules/camera_intrinsics_estimation.py index fca0424837..a19586b033 100644 --- a/pupil_src/shared_modules/camera_intrinsics_estimation.py +++ b/pupil_src/shared_modules/camera_intrinsics_estimation.py @@ -191,14 +191,14 @@ def open_window(self): "Monitor at index %s no longer availalbe using default" % idx ) self.monitor_idx = 0 - mode = glfwGetVideoMode(monitor) monitor = glfw.GLFW.glfwGetMonitors()[self.monitor_idx] + mode = gl_utils.legacy_glfw_get_video_mode(monitor) height, width = mode[0], mode[1] else: monitor = None height, width = 640, 480 - self._window = glfwCreateWindow( + self._window = gl_utils.legacy_glfw_create_window( height, width, "Calibration", @@ -210,10 +210,12 @@ def open_window(self): glfw.GLFW.glfwSetWindowPos(self._window, 200, 31) # Register callbacks - glfwSetFramebufferSizeCallback(self._window, on_resize) - glfwSetKeyCallback(self._window, self.on_window_key) - glfwSetWindowCloseCallback(self._window, self.on_close) - glfwSetMouseButtonCallback(self._window, self.on_window_mouse_button) + gl_utils.legacy_glfw_set_framebuffer_size_callback(self._window, on_resize) + gl_utils.legacy_glfw_set_key_callback(self._window, self.on_window_key) + gl_utils.legacy_glfw_set_window_close_callback(self._window, self.on_close) + gl_utils.legacy_glfw_set_mouse_button_callback( + self._window, self.on_window_mouse_button + ) on_resize(self._window, *glfw.GLFW.glfwGetFramebufferSize(self._window)) @@ -242,7 +244,7 @@ def on_close(self, window=None): def close_window(self): self.window_should_close = False if self._window: - glfwDestroyWindow(self._window) + gl_utils.legacy_glfw_destroy_window(self._window) self._window = None def calculate(self): diff --git a/pupil_src/shared_modules/gl_utils/__init__.py b/pupil_src/shared_modules/gl_utils/__init__.py index 6473d08d3e..a58c93ba8f 100644 --- a/pupil_src/shared_modules/gl_utils/__init__.py +++ b/pupil_src/shared_modules/gl_utils/__init__.py @@ -12,3 +12,23 @@ from .utils import * from .trackball import * from .window_position_manager import WindowPositionManager + +# TODO: Remove calls to legacy functions +from .glfw_legacy import ( + legacy_glfw_get_video_mode, + legacy_glfw_get_error, + legacy_glfw_init, + legacy_glfw_create_window, + legacy_glfw_destroy_window, + legacy_glfw_set_window_pos_callback, + legacy_glfw_set_window_size_callback, + legacy_glfw_set_window_close_callback, + legacy_glfw_set_window_iconify_callback, + legacy_glfw_set_framebuffer_size_callback, + legacy_glfw_set_key_callback, + legacy_glfw_set_char_callback, + legacy_glfw_set_mouse_button_callback, + legacy_glfw_set_cursor_pos_callback, + legacy_glfw_set_scroll_callback, + legacy_glfw_set_drop_callback +) diff --git a/pupil_src/shared_modules/gl_utils/glfw_legacy.py b/pupil_src/shared_modules/gl_utils/glfw_legacy.py new file mode 100644 index 0000000000..54493a7ceb --- /dev/null +++ b/pupil_src/shared_modules/gl_utils/glfw_legacy.py @@ -0,0 +1,229 @@ +import glfw +import glfw.GLFW # TODO: Remove when switching to pyglfw API +import logging + + +logger = logging.getLogger(__name__) + + +__windows__ = [] +__c_callbacks__ = {} +__py_callbacks__ = {} + + +def legacy_glfw_get_video_mode(monitor): + mode_struct = glfw.GLFW.glfwGetVideoMode(monitor) + return ( + mode_struct.width, + mode_struct.height, + mode_struct.red_bits, + mode_struct.blue_bits, + mode_struct.green_bits, + mode_struct.refresh_rate, + ) + + +def legacy_glfw_get_error(): + code, msg = glfw.GLFW.glfwGetError() + if code: + return msg.value.decode() + + +def legacy_glfw_init(): + res = glfw.GLFW.glfwInit() + if res < 0: + raise Exception(f"GLFW could not be initialized: {legacy_glfw_get_error()}") + + +def legacy_glfw_create_window( + width=640, height=480, title="GLFW Window", monitor=None, share=None +): + + window = glfw.GLFW.glfwCreateWindow(width, height, title, monitor, share) + + if window: + __windows__.append(window) + index = __windows__.index(window) + __c_callbacks__[index] = {} + __py_callbacks__[index] = { + "window_pos_fun": None, + "window_size_fun": None, + "window_close_fun": None, + "window_iconify_fun": None, + "framebuffer_size_fun": None, + "key_fun": None, + "char_fun": None, + "mouse_button_fun": None, + "cursor_pos_fun": None, + "scroll_fun": None, + "drop_fun": None, + } + return window + else: + raise Exception(f"GLFW window failed to create: {legacy_glfw_get_error()}") + + +def legacy_glfw_destroy_window(window): + index = __windows__.index(window) + try: + __c_callbacks__[index] + except KeyError: + logger.error("Window already destroyed.") + else: + glfw.GLFW.glfwDestroyWindow(window) + # We do not delete window from the list (or it would impact windows numbering) + # del __windows__[index] + del __c_callbacks__[index] + del __py_callbacks__[index] + + +### CALLBACKS + +import ctypes + + +def __set_window_callback( + window, callback, key: str, c_func_type, glfw_callback_setter +): + index = __windows__.index(window) + old_callback = __py_callbacks__[index][key] + __py_callbacks__[index][key] = callback + + if callback: + callback = c_func_type(callback) + + __c_callbacks__[index][key] = callback + glfw_callback_setter(window, callback) + return old_callback + + +def legacy_glfw_set_window_pos_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="window_pos_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWmonitor), ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetWindowPosCallback, + ) + + +def legacy_glfw_set_window_size_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="window_size_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetWindowSizeCallback, + ) + + +def legacy_glfw_set_window_close_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="window_close_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetWindowCloseCallback, + ) + + +def legacy_glfw_set_window_iconify_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="window_iconify_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetWindowIconifyCallback, + ) + + +def legacy_glfw_set_framebuffer_size_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="framebuffer_size_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetFramebufferSizeCallback, + ) + + +def legacy_glfw_set_key_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="key_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetKeyCallback, + ) + + +def legacy_glfw_set_char_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="char_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetCharCallback, + ) + + +def legacy_glfw_set_mouse_button_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="mouse_button_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetMouseButtonCallback, + ) + + +def legacy_glfw_set_cursor_pos_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="cursor_pos_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetCursorPosCallback, + ) + + +def legacy_glfw_set_scroll_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="scroll_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetScrollCallback, + ) + + +def legacy_glfw_set_drop_callback(window, callback=None): + __set_window_callback( + window=window, + callback=callback, + key="drop_fun", + c_func_type=ctypes.CFUNCTYPE( + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + ), + glfw_callback_setter=glfw.GLFW.glfwSetDropCallback, + ) diff --git a/pupil_src/shared_modules/glfw.py b/pupil_src/shared_modules/glfw.py deleted file mode 100644 index 0ea6e6acb6..0000000000 --- a/pupil_src/shared_modules/glfw.py +++ /dev/null @@ -1,843 +0,0 @@ -# ----------------------------------------------------------------------------- -# GLFW - An OpenGL framework -# API version: 3.0.1 -# WWW: http://www.glfw.org/ -# ---------------------------------------------------------------------------- -# Copyright (c) 2002-2006 Marcus Geelnard -# Copyright (c) 2006-2010 Camilla Berglund -# -# Python bindings - Copyright (c) 2013 Nicolas P. Rougier -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would -# be appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not -# be misrepresented as being the original software. -# -# 3. This notice may not be removed or altered from any source -# distribution. -# -# ---------------- -# changes by moritz kassner: -# small bugfixes, changed binary loading routine. -# Upgrade to 3.1.x api. -# ----------------------------------------------------------------------------- - -import sys, os -import ctypes -from ctypes import ( - c_int, - c_ushort, - c_char_p, - c_double, - c_uint, - c_char, - c_float, - Structure, - CFUNCTYPE, - byref, - POINTER, -) -import platform -from ctypes.util import find_library - -import logging -import typing as T - -logger = logging.getLogger(__name__) - -os_name = platform.system() -del platform - - -if getattr(sys, "frozen", False): - # we are running in a |PyInstaller| bundle using a local version - # you will need to add glfw.so/dylib in your spec file. - if os_name == "Linux": - filename = "libglfw.so" - elif os_name == "Darwin": - filename = "libglfw.dylib" - elif os_name == "Windows": - filename = "glfw3.dll" - else: - filename = "libglfw.dll" - dll_path = os.path.join(sys._MEIPASS, filename) - -else: - # we are running in a normal Python environment - if os_name == "Linux": - dll_path = find_library("glfw") - elif os_name == "Darwin": - dll_path = find_library("glfw") - if not dll_path: - dll_path = find_library("glfw3") - if dll_path: - # deprecation warning, TODO: remove with next release - logger.warning( - "Deprecation warning: Please update your homebrew glfw installation by running `brew migrate glfw`" - ) - elif os_name == "Windows": - dll_path = find_library( - "glfw3" - ) # os.path.join(os.path.dirname(os.path.abspath(os.path.curdir)), 'shared_modules', 'external', 'glfw3') - else: - dll_path = find_library("glfw") - if not dll_path: - raise RuntimeError("GLFW library not found") - -_glfw = ctypes.CDLL(dll_path) - -# --- Version ----------------------------------------------------------------- -GLFW_VERSION_MAJOR = 3 -GLFW_VERSION_MINOR = 1 -GLFW_VERSION_REVISION = 1 -__version__ = GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION - -GLFW_FALSE = 0 -GLFW_TRUE = 1 -GLFW_DONT_CARE = -1 - -# --- Input handling definitions ---------------------------------------------- -GLFW_RELEASE = 0 -GLFW_PRESS = 1 -GLFW_REPEAT = 2 - -# --- Keys -------------------------------------------------------------------- - -# --- The unknown key --------------------------------------------------------- -GLFW_KEY_UNKNOWN = -1 - -# --- Printable keys ---------------------------------------------------------- -GLFW_KEY_SPACE = 32 -GLFW_KEY_APOSTROPHE = 39 # '' -GLFW_KEY_COMMA = 44 # , -GLFW_KEY_MINUS = 45 # - -GLFW_KEY_PERIOD = 46 # . -GLFW_KEY_SLASH = 47 # / -GLFW_KEY_0 = 48 -GLFW_KEY_1 = 49 -GLFW_KEY_2 = 50 -GLFW_KEY_3 = 51 -GLFW_KEY_4 = 52 -GLFW_KEY_5 = 53 -GLFW_KEY_6 = 54 -GLFW_KEY_7 = 55 -GLFW_KEY_8 = 56 -GLFW_KEY_9 = 57 -GLFW_KEY_SEMICOLON = 59 # ; -GLFW_KEY_EQUAL = 61 # = -GLFW_KEY_A = 65 -GLFW_KEY_B = 66 -GLFW_KEY_C = 67 -GLFW_KEY_D = 68 -GLFW_KEY_E = 69 -GLFW_KEY_F = 70 -GLFW_KEY_G = 71 -GLFW_KEY_H = 72 -GLFW_KEY_I = 73 -GLFW_KEY_J = 74 -GLFW_KEY_K = 75 -GLFW_KEY_L = 76 -GLFW_KEY_M = 77 -GLFW_KEY_N = 78 -GLFW_KEY_O = 79 -GLFW_KEY_P = 80 -GLFW_KEY_Q = 81 -GLFW_KEY_R = 82 -GLFW_KEY_S = 83 -GLFW_KEY_T = 84 -GLFW_KEY_U = 85 -GLFW_KEY_V = 86 -GLFW_KEY_W = 87 -GLFW_KEY_X = 88 -GLFW_KEY_Y = 89 -GLFW_KEY_Z = 90 -GLFW_KEY_LEFT_BRACKET = 91 # [ -GLFW_KEY_BACKSLASH = 92 # \ -GLFW_KEY_RIGHT_BRACKET = 93 # ] -GLFW_KEY_GRAVE_ACCENT = 96 # ` -GLFW_KEY_WORLD_1 = 161 # non-US #1 -GLFW_KEY_WORLD_2 = 162 # non-US #2 - -# --- Function keys ----------------------------------------------------------- -GLFW_KEY_ESCAPE = 256 -GLFW_KEY_ENTER = 257 -GLFW_KEY_TAB = 258 -GLFW_KEY_BACKSPACE = 259 -GLFW_KEY_INSERT = 260 -GLFW_KEY_DELETE = 261 -GLFW_KEY_RIGHT = 262 -GLFW_KEY_LEFT = 263 -GLFW_KEY_DOWN = 264 -GLFW_KEY_UP = 265 -GLFW_KEY_PAGE_UP = 266 -GLFW_KEY_PAGE_DOWN = 267 -GLFW_KEY_HOME = 268 -GLFW_KEY_END = 269 -GLFW_KEY_CAPS_LOCK = 280 -GLFW_KEY_SCROLL_LOCK = 281 -GLFW_KEY_NUM_LOCK = 282 -GLFW_KEY_PRINT_SCREEN = 283 -GLFW_KEY_PAUSE = 284 -GLFW_KEY_F1 = 290 -GLFW_KEY_F2 = 291 -GLFW_KEY_F3 = 292 -GLFW_KEY_F4 = 293 -GLFW_KEY_F5 = 294 -GLFW_KEY_F6 = 295 -GLFW_KEY_F7 = 296 -GLFW_KEY_F8 = 297 -GLFW_KEY_F9 = 298 -GLFW_KEY_F10 = 299 -GLFW_KEY_F11 = 300 -GLFW_KEY_F12 = 301 -GLFW_KEY_F13 = 302 -GLFW_KEY_F14 = 303 -GLFW_KEY_F15 = 304 -GLFW_KEY_F16 = 305 -GLFW_KEY_F17 = 306 -GLFW_KEY_F18 = 307 -GLFW_KEY_F19 = 308 -GLFW_KEY_F20 = 309 -GLFW_KEY_F21 = 310 -GLFW_KEY_F22 = 311 -GLFW_KEY_F23 = 312 -GLFW_KEY_F24 = 313 -GLFW_KEY_F25 = 314 -GLFW_KEY_KP_0 = 320 -GLFW_KEY_KP_1 = 321 -GLFW_KEY_KP_2 = 322 -GLFW_KEY_KP_3 = 323 -GLFW_KEY_KP_4 = 324 -GLFW_KEY_KP_5 = 325 -GLFW_KEY_KP_6 = 326 -GLFW_KEY_KP_7 = 327 -GLFW_KEY_KP_8 = 328 -GLFW_KEY_KP_9 = 329 -GLFW_KEY_KP_DECIMAL = 330 -GLFW_KEY_KP_DIVIDE = 331 -GLFW_KEY_KP_MULTIPLY = 332 -GLFW_KEY_KP_SUBTRACT = 333 -GLFW_KEY_KP_ADD = 334 -GLFW_KEY_KP_ENTER = 335 -GLFW_KEY_KP_EQUAL = 336 -GLFW_KEY_LEFT_SHIFT = 340 -GLFW_KEY_LEFT_CONTROL = 341 -GLFW_KEY_LEFT_ALT = 342 -GLFW_KEY_LEFT_SUPER = 343 -GLFW_KEY_RIGHT_SHIFT = 344 -GLFW_KEY_RIGHT_CONTROL = 345 -GLFW_KEY_RIGHT_ALT = 346 -GLFW_KEY_RIGHT_SUPER = 347 -GLFW_KEY_MENU = 348 -GLFW_KEY_LAST = GLFW_KEY_MENU - - -# --- Modifiers --------------------------------------------------------------- -GLFW_MOD_SHIFT = 0x0001 -GLFW_MOD_CONTROL = 0x0002 -GLFW_MOD_ALT = 0x0004 -GLFW_MOD_SUPER = 0x0008 - -# --- Mouse ------------------------------------------------------------------- -GLFW_MOUSE_BUTTON_1 = 0 -GLFW_MOUSE_BUTTON_2 = 1 -GLFW_MOUSE_BUTTON_3 = 2 -GLFW_MOUSE_BUTTON_4 = 3 -GLFW_MOUSE_BUTTON_5 = 4 -GLFW_MOUSE_BUTTON_6 = 5 -GLFW_MOUSE_BUTTON_7 = 6 -GLFW_MOUSE_BUTTON_8 = 7 -GLFW_MOUSE_BUTTON_LAST = GLFW_MOUSE_BUTTON_8 -GLFW_MOUSE_BUTTON_LEFT = GLFW_MOUSE_BUTTON_1 -GLFW_MOUSE_BUTTON_RIGHT = GLFW_MOUSE_BUTTON_2 -GLFW_MOUSE_BUTTON_MIDDLE = GLFW_MOUSE_BUTTON_3 - - -# --- Joystick ---------------------------------------------------------------- -GLFW_JOYSTICK_1 = 0 -GLFW_JOYSTICK_2 = 1 -GLFW_JOYSTICK_3 = 2 -GLFW_JOYSTICK_4 = 3 -GLFW_JOYSTICK_5 = 4 -GLFW_JOYSTICK_6 = 5 -GLFW_JOYSTICK_7 = 6 -GLFW_JOYSTICK_8 = 7 -GLFW_JOYSTICK_9 = 8 -GLFW_JOYSTICK_10 = 9 -GLFW_JOYSTICK_11 = 10 -GLFW_JOYSTICK_12 = 11 -GLFW_JOYSTICK_13 = 12 -GLFW_JOYSTICK_14 = 13 -GLFW_JOYSTICK_15 = 14 -GLFW_JOYSTICK_16 = 15 -GLFW_JOYSTICK_LAST = GLFW_JOYSTICK_16 - - -# --- Error codes ------------------------------------------------------------- -GLFW_NOT_INITIALIZED = 0x00010001 -GLFW_NO_CURRENT_CONTEXT = 0x00010002 -GLFW_INVALID_ENUM = 0x00010003 -GLFW_INVALID_VALUE = 0x00010004 -GLFW_OUT_OF_MEMORY = 0x00010005 -GLFW_API_UNAVAILABLE = 0x00010006 -GLFW_VERSION_UNAVAILABLE = 0x00010007 -GLFW_PLATFORM_ERROR = 0x00010008 -GLFW_FORMAT_UNAVAILABLE = 0x00010009 - -# --- -GLFW_FOCUSED = 0x00020001 -GLFW_ICONIFIED = 0x00020002 -GLFW_RESIZABLE = 0x00020003 -GLFW_VISIBLE = 0x00020004 -GLFW_DECORATED = 0x00020005 - -# --- -GLFW_RED_BITS = 0x00021001 -GLFW_GREEN_BITS = 0x00021002 -GLFW_BLUE_BITS = 0x00021003 -GLFW_ALPHA_BITS = 0x00021004 -GLFW_DEPTH_BITS = 0x00021005 -GLFW_STENCIL_BITS = 0x00021006 -GLFW_ACCUM_RED_BITS = 0x00021007 -GLFW_ACCUM_GREEN_BITS = 0x00021008 -GLFW_ACCUM_BLUE_BITS = 0x00021009 -GLFW_ACCUM_ALPHA_BITS = 0x0002100A -GLFW_AUX_BUFFERS = 0x0002100B -GLFW_STEREO = 0x0002100C -GLFW_SAMPLES = 0x0002100D -GLFW_SRGB_CAPABLE = 0x0002100E -GLFW_REFRESH_RATE = 0x0002100F - -# --- -GLFW_CLIENT_API = 0x00022001 -GLFW_CONTEXT_VERSION_MAJOR = 0x00022002 -GLFW_CONTEXT_VERSION_MINOR = 0x00022003 -GLFW_CONTEXT_REVISION = 0x00022004 -GLFW_CONTEXT_ROBUSTNESS = 0x00022005 -GLFW_OPENGL_FORWARD_COMPAT = 0x00022006 -GLFW_OPENGL_DEBUG_CONTEXT = 0x00022007 -GLFW_OPENGL_PROFILE = 0x00022008 -# GLFW_CONTEXT_RELEASE_BEHAVIOR = 0x00022009 -# GLFW_CONTEXT_NO_ERROR = 0x0002200A -# GLFW_CONTEXT_CREATION_API = 0x0002200B -GLFW_SCALE_TO_MONITOR = 0x0002200C - -# --- -GLFW_OPENGL_API = 0x00030001 -GLFW_OPENGL_ES_API = 0x00030002 - -# --- -GLFW_NO_ROBUSTNESS = 0 -GLFW_NO_RESET_NOTIFICATION = 0x00031001 -GLFW_LOSE_CONTEXT_ON_RESET = 0x00031002 - -# --- -GLFW_OPENGL_ANY_PROFILE = 0 -GLFW_OPENGL_CORE_PROFILE = 0x00032001 -GLFW_OPENGL_COMPAT_PROFILE = 0x00032002 - -# --- -GLFW_CURSOR = 0x00033001 -GLFW_STICKY_KEYS = 0x00033002 -GLFW_STICKY_MOUSE_BUTTONS = 0x00033003 - -# --- -GLFW_CURSOR_NORMAL = 0x00034001 -GLFW_CURSOR_HIDDEN = 0x00034002 -GLFW_CURSOR_DISABLED = 0x00034003 - -# --- -GLFW_CONNECTED = 0x00040001 -GLFW_DISCONNECTED = 0x00040002 - - -# --- Structures -------------------------------------------------------------- -class GLFWvidmode(Structure): - _fields_ = [ - ("width", c_int), - ("height", c_int), - ("redBits", c_int), - ("greenBits", c_int), - ("blueBits", c_int), - ("refreshRate", c_int), - ] - - -class GLFWgammaramp(Structure): - _fields_ = [ - ("red", POINTER(c_ushort)), - ("green", POINTER(c_ushort)), - ("blue", POINTER(c_ushort)), - ("size", c_int), - ] - - -class GLFWwindow(Structure): - pass - - -class GLFWmonitor(Structure): - pass - - -# --- Callbacks --------------------------------------------------------------- -errorfun = CFUNCTYPE(None, c_int, c_char_p) -windowposfun = CFUNCTYPE(None, POINTER(GLFWwindow), c_int, c_int) -windowsizefun = CFUNCTYPE(None, POINTER(GLFWwindow), c_int, c_int) -windowclosefun = CFUNCTYPE(None, POINTER(GLFWwindow)) -windowrefreshfun = CFUNCTYPE(None, POINTER(GLFWwindow)) -windowfocusfun = CFUNCTYPE(None, POINTER(GLFWwindow), c_int) -windowiconifyfun = CFUNCTYPE(None, POINTER(GLFWwindow), c_int) -framebuffersizefun = CFUNCTYPE(None, POINTER(GLFWwindow), c_int, c_int) -mousebuttonfun = CFUNCTYPE(None, POINTER(GLFWwindow), c_int, c_int, c_int) -cursorposfun = CFUNCTYPE(None, POINTER(GLFWwindow), c_double, c_double) -cursorenterfun = CFUNCTYPE(None, POINTER(GLFWwindow), c_int) -scrollfun = CFUNCTYPE(None, POINTER(GLFWwindow), c_double, c_double) -keyfun = CFUNCTYPE(None, POINTER(GLFWwindow), c_int, c_int, c_int, c_int) -charfun = CFUNCTYPE(None, POINTER(GLFWwindow), c_uint) -monitorfun = CFUNCTYPE(None, POINTER(GLFWmonitor), c_int) -dropfun = CFUNCTYPE(None, POINTER(GLFWmonitor), c_int, POINTER(c_char_p)) - -# --- Init -------------------------------------------------------------------- -# glfwInit = _glfw.glfwInit -glfwTerminate = _glfw.glfwTerminate -# glfwGetVersion = _glfw.glfwGetVersion -glfwGetVersionString = _glfw.glfwGetVersionString -glfwGetVersionString.restype = c_char_p - -# --- Error ------------------------------------------------------------------- -# glfwSetErrorCallback = _glfw.glfwSetErrorCallback - -# --- Monitor ----------------------------------------------------------------- -# glfwGetMonitors = _glfw.glfwGetMonitors -# glfwGetMonitors.restype = POINTER(GLFWmonitor) -glfwGetPrimaryMonitor = _glfw.glfwGetPrimaryMonitor -glfwGetPrimaryMonitor.restype = POINTER(GLFWmonitor) -# glfwGetMonitorPos = _glfw.glfwGetMonitorPos -# glfwGetMonitorWorkarea = _glfw.glfwGetMonitorWorkarea -# glfwGetMonitorPhysicalSize = _glfw.glfwGetMonitorPhysicalSize -glfwGetMonitorName = _glfw.glfwGetMonitorName -glfwGetMonitorName.restype = c_char_p -# glfwSetMonitorCallback = _glfw.glfwSetMonitorCallback -# glfwGetVideoModes = _glfw.glfwGetVideoModes -# glfwGetVideoMode = _glfw.glfwGetVideoMode - -# --- Gama -------------------------------------------------------------------- -glfwSetGamma = _glfw.glfwSetGamma -# glfwGetGammaRamp = _glfw.glfwGetGammaRamp -# glfwSetGammaRamp = _glfw.glfwSetGammaRamp - -# --- Window ------------------------------------------------------------------ -glfwDefaultWindowHints = _glfw.glfwDefaultWindowHints -glfwWindowHint = _glfw.glfwWindowHint -# glfwCreateWindow = _glfw.glfwCreateWindow -# glfwDestroyWindow = _glfw.glfwDestroyWindow -glfwWindowShouldClose = _glfw.glfwWindowShouldClose -glfwSetWindowShouldClose = _glfw.glfwSetWindowShouldClose -glfwSetWindowTitle = _glfw.glfwSetWindowTitle -# glfwGetWindowPos = _glfw.glfwGetWindowPos -glfwSetWindowPos = _glfw.glfwSetWindowPos -# glfwGetWindowSize = _glfw.glfwGetWindowSize -glfwSetWindowSizeLimits = _glfw.glfwSetWindowSizeLimits -glfwSetWindowSize = _glfw.glfwSetWindowSize -# glfwGetFramebufferSize = _glfw.glfwGetFramebufferSize -# glfwGetWindowFrameSize = _glfw.glfwGetWindowFrameSize -glfwIconifyWindow = _glfw.glfwIconifyWindow -glfwRestoreWindow = _glfw.glfwRestoreWindow -glfwShowWindow = _glfw.glfwShowWindow -glfwHideWindow = _glfw.glfwHideWindow -glfwGetWindowMonitor = _glfw.glfwGetWindowMonitor -glfwSetWindowMonitor = _glfw.glfwSetWindowMonitor -glfwGetWindowAttrib = _glfw.glfwGetWindowAttrib -glfwSetWindowUserPointer = _glfw.glfwSetWindowUserPointer -glfwGetWindowUserPointer = _glfw.glfwGetWindowUserPointer -# glfwSetWindowPosCallback = _glfw.glfwSetWindowPosCallback -# glfwSetWindowSizeCallback = _glfw.glfwSetWindowSizeCallback -# glfwSetWindowCloseCallback = _glfw.glfwSetWindowCloseCallback -# glfwSetWindowRefreshCallback = _glfw.glfwSetWindowRefreshCallback -# glfwSetWindowFocusCallback = _glfw.glfwSetWindowFocusCallback -# glfwSetWindowIconifyCallback = _glfw.glfwSetWindowIconifyCallback -# glfwSetFramebufferSizeCallback = _glfw.glfwSetFramebufferSizeCallback -glfwPollEvents = _glfw.glfwPollEvents -glfwWaitEvents = _glfw.glfwWaitEvents - -# --- Input ------------------------------------------------------------------- -glfwGetInputMode = _glfw.glfwGetInputMode -glfwSetInputMode = _glfw.glfwSetInputMode -glfwGetKey = _glfw.glfwGetKey -glfwGetMouseButton = _glfw.glfwGetMouseButton -# glfwGetCursorPos = _glfw.glfwGetCursorPos -glfwSetCursorPos = _glfw.glfwSetCursorPos -# glfwSetKeyCallback = _glfw.glfwSetKeyCallback -# glfwSetCharCallback = _glfw.glfwSetCharCallback -# glfwSetMouseButtonCallback = _glfw.glfwSetMouseButtonCallback -# glfwSetCursorPosCallback = _glfw.glfwSetCursorPosCallback -# glfwSetCursorEnterCallback = _glfw.glfwSetCursorEnterCallback -# glfwSetScrollCallback = _glfw.glfwSetScrollCallback -glfwJoystickPresent = _glfw.glfwJoystickPresent -# glfwGetJoystickAxes = _glfw.glfwGetJoystickAxes -# glfwGetJoystickButtons = _glfw.glfwGetJoystickButtons -glfwGetJoystickName = _glfw.glfwGetJoystickName -glfwGetJoystickName.restype = c_char_p - -# --- Clipboard --------------------------------------------------------------- -glfwSetClipboardString = _glfw.glfwSetClipboardString -glfwGetClipboardString = _glfw.glfwGetClipboardString -glfwGetClipboardString.restype = c_char_p - -# --- Timer ------------------------------------------------------------------- -glfwGetTime = _glfw.glfwGetTime -glfwGetTime.restype = c_double -glfwSetTime = _glfw.glfwSetTime - -# --- Context ----------------------------------------------------------------- -glfwMakeContextCurrent = _glfw.glfwMakeContextCurrent -# glfwGetCurrentContext = _glfw.glfwGetCurrentContext -glfwSwapBuffers = _glfw.glfwSwapBuffers -glfwSwapInterval = _glfw.glfwSwapInterval -glfwExtensionSupported = _glfw.glfwExtensionSupported -glfwGetProcAddress = _glfw.glfwGetProcAddress - - -# --- Pythonizer -------------------------------------------------------------- - -# This keeps track of current windows -__windows__ = [] - -# This is to prevent garbage collection on callbacks -__c_callbacks__ = {} -__py_callbacks__ = {} - - -class _Margins(T.NamedTuple): - left: int - top: int - right: int - bottom: int - - -class _Rectangle(T.NamedTuple): - x: int - y: int - width: int - height: int - - def intersection(self, other: "_Rectangle") -> T.Optional["_Rectangle"]: - in_min_x = max(self.x, other.x) - in_min_y = max(self.y, other.y) - - in_max_x = min(self.x + self.width, other.x + other.width) - in_max_y = min(self.y + self.height, other.y + other.height) - - if in_min_x < in_max_x and in_min_y < in_max_y: - return _Rectangle( - x=in_min_x, - y=in_min_y, - width=in_max_x - in_min_x, - height=in_max_y - in_min_y, - ) - else: - return None - - -def glfwGetError(): - _glfwGetError = _glfw.glfwGetError - _glfwGetError.argtypes = [POINTER(c_char_p)] - _glfwGetError.restype = c_int - msg = c_char_p() - result = _glfwGetError(byref(msg)) - if result: - return msg.value.decode() - - -def glfwInit(): - import os - - # glfw changes the directory,so we change it back. - cwd = os.getcwd() - # Initialize - res = _glfw.glfwInit() - # Restore the old cwd. - os.chdir(cwd) - del os - if res < 0: - raise Exception(f"GLFW could not be initialized: {glfwGetError()}") - - -def glfwCreateWindow( - width=640, height=480, title="GLFW Window", monitor=None, share=None -): - _glfw.glfwCreateWindow.restype = POINTER(GLFWwindow) - window = _glfw.glfwCreateWindow( - width, height, title.encode("utf-8"), monitor, share - ) - if window: - __windows__.append(window) - index = __windows__.index(window) - __c_callbacks__[index] = {} - __py_callbacks__[index] = { - "errorfun": None, - "monitorfun": None, - "windowposfun": None, - "windowsizefun": None, - "windowclosefun": None, - "windowrefreshfun": None, - "windowfocusfun": None, - "windowiconifyfun": None, - "framebuffersizefun": None, - "keyfun": None, - "charfun": None, - "mousebuttonfun": None, - "cursorposfun": None, - "cursorenterfun": None, - "scrollfun": None, - "dropfun": None, - } - return window - else: - raise Exception(f"GLFW window failed to create: {glfwGetError()}") - - -def glfwDestroyWindow(window): - index = __windows__.index(window) - try: - __c_callbacks__[index] - except KeyError: - logger.error("Window already destroyed.") - else: - _glfw.glfwDestroyWindow(window) - # We do not delete window from the list (or it would impact windows numbering) - # del __windows__[index] - del __c_callbacks__[index] - del __py_callbacks__[index] - - -def glfwGetVersion(): - major, minor, rev = c_int(0), c_int(0), c_int(0) - _glfw.glfwGetVersion(byref(major), byref(minor), byref(rev)) - return major.value, minor.value, rev.value - - -def glfwGetWindowPos(window): - xpos, ypos = c_int(0), c_int(0) - _glfw.glfwGetWindowPos(window, byref(xpos), byref(ypos)) - return xpos.value, ypos.value - - -def glfwGetCursorPos(window): - xpos, ypos = c_double(0), c_double(0) - _glfw.glfwGetCursorPos(window, byref(xpos), byref(ypos)) - return xpos.value, ypos.value - - -def glfwGetWindowSize(window): - width, height = c_int(0), c_int(0) - _glfw.glfwGetWindowSize(window, byref(width), byref(height)) - return width.value, height.value - - -def glfwGetCurrentContext(): - _glfw.glfwGetCurrentContext.restype = POINTER(GLFWwindow) - return _glfw.glfwGetCurrentContext() - - -def glfwGetFramebufferSize(window): - width, height = c_int(0), c_int(0) - _glfw.glfwGetFramebufferSize(window, byref(width), byref(height)) - return width.value, height.value - - -def glfwGetWindowFrameSize(window) -> _Margins: - """""" - left, top, right, bottom = c_int(0), c_int(0), c_int(0), c_int(0) - _glfw.glfwGetWindowFrameSize( - window, byref(left), byref(top), byref(right), byref(bottom) - ) - return _Margins( - left=left.value, top=top.value, right=right.value, bottom=bottom.value - ) - - -def glfwGetMonitors(): - count = c_int(0) - _glfw.glfwGetMonitors.restype = POINTER(POINTER(GLFWmonitor)) - c_monitors = _glfw.glfwGetMonitors(byref(count)) - return [c_monitors[i] for i in range(count.value)] - - -def glfwGetVideoModes(monitor): - count = c_int(0) - _glfw.glfwGetVideoModes.restype = POINTER(GLFWvidmode) - c_modes = _glfw.glfwGetVideoModes(monitor, byref(count)) - modes = [] - for i in range(count.value): - modes.append( - ( - c_modes[i].width, - c_modes[i].height, - c_modes[i].redBits, - c_modes[i].blueBits, - c_modes[i].greenBits, - c_modes[i].refreshRate, - ) - ) - return modes - - -def glfwGetMonitorPos(monitor): - xpos, ypos = c_int(0), c_int(0) - _glfw.glfwGetMonitorPos(monitor, byref(xpos), byref(ypos)) - return xpos.value, ypos.value - - -def glfwGetMonitorWorkarea(monitor) -> _Rectangle: - xpos, ypos, width, height = c_int(0), c_int(0), c_int(0), c_int(0) - _glfw.glfwGetMonitorWorkarea( - monitor, byref(xpos), byref(ypos), byref(width), byref(height) - ) - return _Rectangle( - x=xpos.value, y=ypos.value, width=width.value, height=height.value - ) - - -def glfwGetMonitorPhysicalSize(monitor): - width, height = c_int(0), c_int(0) - _glfw.glfwGetMonitorPhysicalSize(monitor, byref(width), byref(height)) - return width.value, height.value - - -def glfwGetVideoMode(monitor): - _glfw.glfwGetVideoMode.restype = POINTER(GLFWvidmode) - c_mode = _glfw.glfwGetVideoMode(monitor) - return ( - c_mode.contents.width, - c_mode.contents.height, - c_mode.contents.redBits, - c_mode.contents.blueBits, - c_mode.contents.greenBits, - c_mode.contents.refreshRate, - ) - - -def glfwGetWindowContentScale(window): - xscale, yscale = c_float(0), c_float(0) - _glfw.glfwGetWindowContentScale(window, byref(xscale), byref(yscale)) - return xscale.value, yscale.value - - -def GetGammaRamp(monitor): - _glfw.glfwGetGammaRamp.restype = POINTER(GLFWgammaramp) - c_gamma = _glfw.glfwGetGammaRamp(monitor).contents - gamma = {"red": [], "green": [], "blue": []} - if c_gamma: - for i in range(c_gamma.size): - gamma["red"].append(c_gamma.red[i]) - gamma["green"].append(c_gamma.green[i]) - gamma["blue"].append(c_gamma.blue[i]) - return gamma - - -def glfwGetJoystickAxes(joy): - count = c_int(0) - _glfw.glfwGetJoystickAxes.restype = POINTER(c_float) - c_axes = _glfw.glfwGetJoystickAxes(joy, byref(count)) - axes = [c_axes[i].value for i in range(count)] - - -def glfwGetJoystickButtons(joy): - count = c_int(0) - _glfw.glfwGetJoystickButtons.restype = POINTER(c_int) - c_buttons = _glfw.glfwGetJoystickButtons(joy, byref(count)) - buttons = [c_buttons[i].value for i in range(count)] - - -# --- Callbacks --------------------------------------------------------------- - - -def __callback__(name): - callback = "glfwSet{}Callback".format(name) - fun = "{}fun".format(name.lower()) - code = """ -def {callback}(window, callback = None): - index = __windows__.index(window) - old_callback = __py_callbacks__[index]['{fun}'] - __py_callbacks__[index]['{fun}'] = callback - if callback: callback = {fun}(callback) - __c_callbacks__[index]['{fun}'] = callback - _glfw.{callback}(window, callback) - return old_callback""".format( - callback=callback, fun=fun - ) - return code - - -exec(__callback__("Error")) -exec(__callback__("Monitor")) -exec(__callback__("WindowPos")) -exec(__callback__("WindowSize")) -exec(__callback__("WindowClose")) -exec(__callback__("WindowRefresh")) -exec(__callback__("WindowFocus")) -exec(__callback__("WindowIconify")) -exec(__callback__("FramebufferSize")) -exec(__callback__("Key")) -exec(__callback__("Char")) -exec(__callback__("MouseButton")) -exec(__callback__("CursorPos")) -exec(__callback__("Scroll")) -exec(__callback__("Drop")) - - -def get_content_scale(window) -> float: - return glfwGetWindowContentScale(window)[0] - - -def get_framebuffer_scale(window) -> float: - window_width = glfwGetWindowSize(window)[0] - framebuffer_width = glfwGetFramebufferSize(window)[0] - - try: - return float(framebuffer_width / window_width) - except ZeroDivisionError: - return 1.0 - - -def window_coordinate_to_framebuffer_coordinate(window, x, y, cached_scale=None): - scale = cached_scale or get_framebuffer_scale(window) - return x * scale, y * scale - - -def get_window_content_rect(window) -> _Rectangle: - x, y = glfwGetWindowPos(window) - w, h = glfwGetWindowSize(window) - return _Rectangle(x=x, y=y, width=w, height=h) - - -def get_window_frame_rect(window) -> _Rectangle: - content_rect = get_window_content_rect(window) - frame_edges = glfwGetWindowFrameSize(window) - return _Rectangle( - x=content_rect.x - frame_edges.left, - y=content_rect.y - frame_edges.top, - width=content_rect.width + frame_edges.left + frame_edges.right, - height=content_rect.height + frame_edges.top + frame_edges.bottom, - ) - - -def get_window_title_bar_rect(window) -> _Rectangle: - frame_rect = get_window_frame_rect(window) - frame_edges = glfwGetWindowFrameSize(window) - return _Rectangle( - x=frame_rect.x, y=frame_rect.y, width=frame_rect.width, height=frame_edges.top - ) diff --git a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py index 7f1e412cdf..5e6b45cefe 100644 --- a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py +++ b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py @@ -62,10 +62,11 @@ def _init_trackball(): return trackball def _glfw_init(self): - glfw.glfwInit() - window = glfw.glfwCreateWindow( - title="Head Pose Tracker Visualizer", share=glfw.glfwGetCurrentContext() + gl_utils.legacy_glfw_init() glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) + window = gl_utils.legacy_glfw_create_window( + title="Head Pose Tracker Visualizer", + share=glfw.GLFW.glfwGetCurrentContext(), ) return window @@ -79,13 +80,19 @@ def _gl_state_settings(window): glfw.GLFW.glfwMakeContextCurrent(active_window) def _register_callbacks(self, window): - glfw.glfwSetWindowSizeCallback(window, self._on_set_window_size) - glfw.glfwSetWindowPosCallback(window, self._on_set_window_pos) - glfw.glfwSetFramebufferSizeCallback(window, self._on_set_frame_buffer_size) - glfw.glfwSetMouseButtonCallback(window, self._on_set_mouse_button) - glfw.glfwSetCursorPosCallback(window, self._on_set_cursor_pos) - glfw.glfwSetScrollCallback(window, self._on_set_scroll) - glfw.glfwSetWindowCloseCallback(window, self._on_set_window_close) + gl_utils.legacy_glfw_set_window_size_callback(window, self._on_set_window_size) + gl_utils.legacy_glfw_set_window_pos_callback(window, self._on_set_window_pos) + gl_utils.legacy_glfw_set_framebuffer_size_callback( + window, self._on_set_frame_buffer_size + ) + gl_utils.legacy_glfw_set_mouse_button_callback( + window, self._on_set_mouse_button + ) + gl_utils.legacy_glfw_set_cursor_pos_callback(window, self._on_set_cursor_pos) + gl_utils.legacy_glfw_set_scroll_callback(window, self._on_set_scroll) + gl_utils.legacy_glfw_set_window_close_callback( + window, self._on_set_window_close + ) def _set_initial_window_state(self): glfw.GLFW.glfwSetWindowPos( @@ -135,7 +142,7 @@ def _close(self): self._glfw_deinit(self._window) def _glfw_deinit(self, window): - glfw.glfwDestroyWindow(window) + gl_utils.legacy_glfw_destroy_window(window) self._window = None def _on_gl_display(self): diff --git a/pupil_src/shared_modules/service_ui.py b/pupil_src/shared_modules/service_ui.py index edc7b5cb4d..acf7d466f2 100644 --- a/pupil_src/shared_modules/service_ui.py +++ b/pupil_src/shared_modules/service_ui.py @@ -49,11 +49,11 @@ def __init__( self.texture = np.zeros((1, 1, 3), dtype=np.uint8) + 128 - glfw.glfwInit() + gl_utils.legacy_glfw_init() glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) if g_pool.hide_ui: - main_window = glfw.glfwCreateWindow(*window_size, "Pupil Service") glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_VISIBLE, 0) # hide window + main_window = gl_utils.legacy_glfw_create_window(*window_size, "Pupil Service") window_position_manager = gl_utils.WindowPositionManager() window_position = window_position_manager.new_window_position( @@ -166,12 +166,12 @@ def reset_restart(): g_pool.menubar.append(ui.Button("Restart with default settings", reset_restart)) # Register callbacks main_window - glfw.glfwSetFramebufferSizeCallback(main_window, on_resize) - glfw.glfwSetKeyCallback(main_window, on_window_key) - glfw.glfwSetCharCallback(main_window, on_window_char) - glfw.glfwSetMouseButtonCallback(main_window, on_window_mouse_button) - glfw.glfwSetCursorPosCallback(main_window, on_pos) - glfw.glfwSetScrollCallback(main_window, on_scroll) + gl_utils.legacy_glfw_set_framebuffer_size_callback(main_window, on_resize) + gl_utils.legacy_glfw_set_key_callback(main_window, on_window_key) + gl_utils.legacy_glfw_set_char_callback(main_window, on_window_char) + gl_utils.legacy_glfw_set_mouse_button_callback(main_window, on_window_mouse_button) + gl_utils.legacy_glfw_set_cursor_pos_callback(main_window, on_pos) + gl_utils.legacy_glfw_set_scroll_callback(main_window, on_scroll) g_pool.gui.configuration = ui_config gl_utils.basic_gl_setup() @@ -222,7 +222,7 @@ def cleanup(self): self.g_pool.gui.remove(self.g_pool.menubar) self.g_pool.gui.terminate() - glfw.glfwDestroyWindow(self.g_pool.main_window) + gl_utils.legacy_glfw_destroy_window(self.g_pool.main_window) glfw.GLFW.glfwTerminate() del self.g_pool.gui diff --git a/pupil_src/shared_modules/surface_tracker/gui.py b/pupil_src/shared_modules/surface_tracker/gui.py index 69a746068c..a464f0ada3 100644 --- a/pupil_src/shared_modules/surface_tracker/gui.py +++ b/pupil_src/shared_modules/surface_tracker/gui.py @@ -565,7 +565,7 @@ def open_window(self): win_h = 640 win_w = int(win_h / surface_aspect_ratio) - self._window = glfw.glfwCreateWindow( + self._window = gl_utils.legacy_glfw_create_window( win_h, win_w, "Reference Surface: " + self.surface.name, @@ -583,12 +583,14 @@ def open_window(self): self.input = {"down": False, "mouse": (0, 0)} # Register callbacks - glfw.glfwSetFramebufferSizeCallback(self._window, self.on_resize) - glfw.glfwSetKeyCallback(self._window, self.on_window_key) - glfw.glfwSetWindowCloseCallback(self._window, self.on_close) - glfw.glfwSetMouseButtonCallback(self._window, self.on_window_mouse_button) - glfw.glfwSetCursorPosCallback(self._window, self.on_pos) - glfw.glfwSetScrollCallback(self._window, self.on_scroll) + gl_utils.legacy_glfw_set_framebuffer_size_callback(self._window, self.on_resize) + gl_utils.legacy_glfw_set_key_callback(self._window, self.on_window_key) + gl_utils.legacy_glfw_set_window_close_callback(self._window, self.on_close) + gl_utils.legacy_glfw_set_mouse_button_callback( + self._window, self.on_window_mouse_button + ) + gl_utils.legacy_glfw_set_cursor_pos_callback(self._window, self.on_pos) + gl_utils.legacy_glfw_set_scroll_callback(self._window, self.on_scroll) self.on_resize( self._window, *glfw.GLFW.glfwGetFramebufferSize(self._window) @@ -607,7 +609,7 @@ def open_window(self): def close_window(self): if self._window: - glfw.glfwDestroyWindow(self._window) + gl_utils.legacy_glfw_destroy_window(self._window) self._window = None self.window_should_close = False diff --git a/pupil_src/shared_modules/visualizer.py b/pupil_src/shared_modules/visualizer.py index 87c8a91ce5..df4b285602 100644 --- a/pupil_src/shared_modules/visualizer.py +++ b/pupil_src/shared_modules/visualizer.py @@ -157,7 +157,7 @@ def clear_gl_screen(self): def close_window(self): if self.window: - glfwDestroyWindow(self.window) + gl_utils.legacy_glfw_destroy_window(self.window) self.window = None def open_window(self): @@ -166,15 +166,15 @@ def open_window(self): # get glfw started if self.run_independently: - glfwInit() - self.window = glfwCreateWindow( + gl_utils.legacy_glfw_init() glfw.GLFW.glfwWindowHint( glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE ) + self.window = gl_utils.legacy_glfw_create_window( self.window_size[0], self.window_size[1], self.name, None ) else: - self.window = glfwCreateWindow( + self.window = gl_utils.legacy_glfw_create_window( self.window_size[0], self.window_size[1], self.name, @@ -190,13 +190,19 @@ def open_window(self): self.window, window_position_default[0], window_position_default[1] ) # Register callbacks window - glfwSetFramebufferSizeCallback(self.window, self.on_resize) - glfwSetWindowIconifyCallback(self.window, self.on_iconify) - glfwSetKeyCallback(self.window, self.on_window_key) - glfwSetCharCallback(self.window, self.on_window_char) - glfwSetMouseButtonCallback(self.window, self.on_window_mouse_button) - glfwSetCursorPosCallback(self.window, self.on_pos) - glfwSetScrollCallback(self.window, self.on_scroll) + gl_utils.legacy_glfw_set_framebuffer_size_callback( + self.window, self.on_resize + ) + gl_utils.legacy_glfw_set_window_iconify_callback( + self.window, self.on_iconify + ) + gl_utils.legacy_glfw_set_key_callback(self.window, self.on_window_key) + gl_utils.legacy_glfw_set_char_callback(self.window, self.on_window_char) + gl_utils.legacy_glfw_set_mouse_button_callback( + self.window, self.on_window_mouse_button + ) + gl_utils.legacy_glfw_set_cursor_pos_callback(self.window, self.on_pos) + gl_utils.legacy_glfw_set_scroll_callback(self.window, self.on_scroll) # get glfw started if self.run_independently: From 30fc9230430d77745902398520b6abd276c0780f Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Wed, 23 Sep 2020 09:44:08 +0200 Subject: [PATCH 05/57] Use qualified gl_utils functions in gui_window --- .../calibration_choreography/controller/gui_window.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py index 8635b9d0fb..5a904b2669 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py @@ -5,9 +5,6 @@ import OpenGL.GL as gl import glfw -from gl_utils import adjust_gl_view -from gl_utils import basic_gl_setup -from gl_utils import clear_gl_screen import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils @@ -114,7 +111,7 @@ def open( # gl_state settings with self._switch_to_current_context(): - basic_gl_setup() + gl_utils.basic_gl_setup() glfw.GLFW.glfwSwapInterval(0) if is_fullscreen: @@ -148,7 +145,7 @@ def drawing_context(self): return with self._switch_to_current_context(): - clear_gl_screen() + gl_utils.clear_gl_screen() gl.glMatrixMode(gl.GL_PROJECTION) gl.glLoadIdentity() @@ -163,7 +160,7 @@ def drawing_context(self): def on_resize(self, gl_handle, w, h): with self._switch_to_current_context(): - adjust_gl_view(w, h) + gl_utils.adjust_gl_view(w, h) def on_key(self, gl_handle, key, scancode, action, mods): if action == glfw.GLFW.GLFW_PRESS: From 7ec2c36035e4dbfcd519b5810105c589f079ed88 Mon Sep 17 00:00:00 2001 From: Patrick Faion Date: Wed, 23 Sep 2020 10:29:05 +0200 Subject: [PATCH 06/57] Revert bin visualization --- .../visualizer_pye3d.py | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/pupil_src/shared_modules/pupil_detector_plugins/visualizer_pye3d.py b/pupil_src/shared_modules/pupil_detector_plugins/visualizer_pye3d.py index bd415e052b..357834cf43 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/visualizer_pye3d.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/visualizer_pye3d.py @@ -226,29 +226,6 @@ def update_window(self, g_pool, result): alpha=1.0, ) - bins = np.array(result["debug_info"]["bins"]) - print(bins) - m = np.max(bins) - if m > 0: - bins = bins / m - px_per_bin = result["debug_info"]["px_per_bin"] - w, h = bins.shape - for row in range(h): - for col in range(w): - - x0 = col * px_per_bin - x1 = (col + 1) * px_per_bin - y0 = row * px_per_bin - y1 = (row + 1) * px_per_bin - - glColor4f(1, 0, 0, bins[row, col]) - glBegin(GL_QUADS) - glVertex3f(x0, y0, 0) - glVertex3f(x0, y1, 0) - glVertex3f(x1, y1, 0) - glVertex3f(x1, y0, 0) - glEnd() - glLoadMatrixf(self.get_adjusted_pixel_space_matrix(15)) self.draw_frustum(self.image_width, self.image_height, self.focal_length) glLoadMatrixf(self.get_anthropomorphic_matrix()) From 8dda784be7e15026003dea5d4808d5777029de0c Mon Sep 17 00:00:00 2001 From: Patrick Faion Date: Wed, 23 Sep 2020 18:42:09 +0200 Subject: [PATCH 07/57] [WIP] --- .../pupil_detector_plugins/pye3d_plugin.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py index 23e929d0b8..6473ae5ae4 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py @@ -12,6 +12,8 @@ from pye3d.detector_3d import Detector3D from pyglui import ui +from matplotlib import pyplot as plt +import pyqtgraph as pq from .detector_base_plugin import PupilDetectorPlugin from .visualizer_2d import draw_eyeball_outline, draw_pupil_outline @@ -36,6 +38,9 @@ def __init__(self, g_pool): g_pool, self.detector.settings["focal_length"] ) + self.data = [] + self.ts = [] + def detect(self, frame, **kwargs): previous_detection_results = kwargs.get("previous_detection_results", []) for datum in previous_detection_results: @@ -55,6 +60,23 @@ def detect(self, frame, **kwargs): result["id"] = eye_id result["method"] = "3d c++" + if result["confidence"] > 0.6: + hist = 400 + self.data.append(result["diameter_3d"]) + self.ts.append(frame.timestamp) + self.data = self.data[-hist:] + self.ts = self.ts[-hist:] + + global plotWidget + try: + plotWidget + except NameError: + plotWidget = pq.plot(title=f"Test {self.g_pool.eye_id}") + + plotWidget.clear() + plotWidget.plot(self.ts, self.data) + plotWidget.setYRange(0.5, 4.5) + return result def on_notify(self, notification): From 437f17b994fb7e1730a91df55543b0a0f1b140be Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Mon, 28 Sep 2020 23:30:13 +0200 Subject: [PATCH 08/57] Fix glfw_legacy function type definitions --- .../shared_modules/gl_utils/glfw_legacy.py | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/pupil_src/shared_modules/gl_utils/glfw_legacy.py b/pupil_src/shared_modules/gl_utils/glfw_legacy.py index 54493a7ceb..22095db249 100644 --- a/pupil_src/shared_modules/gl_utils/glfw_legacy.py +++ b/pupil_src/shared_modules/gl_utils/glfw_legacy.py @@ -103,7 +103,7 @@ def legacy_glfw_set_window_pos_callback(window, callback=None): callback=callback, key="window_pos_fun", c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWmonitor), ctypes.c_int + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int ), glfw_callback_setter=glfw.GLFW.glfwSetWindowPosCallback, ) @@ -126,9 +126,7 @@ def legacy_glfw_set_window_close_callback(window, callback=None): window=window, callback=callback, key="window_close_fun", - c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int - ), + c_func_type=ctypes.CFUNCTYPE(None, ctypes.POINTER(glfw._GLFWwindow)), glfw_callback_setter=glfw.GLFW.glfwSetWindowCloseCallback, ) @@ -139,7 +137,7 @@ def legacy_glfw_set_window_iconify_callback(window, callback=None): callback=callback, key="window_iconify_fun", c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int ), glfw_callback_setter=glfw.GLFW.glfwSetWindowIconifyCallback, ) @@ -163,7 +161,12 @@ def legacy_glfw_set_key_callback(window, callback=None): callback=callback, key="key_fun", c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + None, + ctypes.POINTER(glfw._GLFWwindow), + ctypes.c_int, + ctypes.c_int, + ctypes.c_int, + ctypes.c_int, ), glfw_callback_setter=glfw.GLFW.glfwSetKeyCallback, ) @@ -175,7 +178,7 @@ def legacy_glfw_set_char_callback(window, callback=None): callback=callback, key="char_fun", c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int ), glfw_callback_setter=glfw.GLFW.glfwSetCharCallback, ) @@ -187,7 +190,11 @@ def legacy_glfw_set_mouse_button_callback(window, callback=None): callback=callback, key="mouse_button_fun", c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + None, + ctypes.POINTER(glfw._GLFWwindow), + ctypes.c_int, + ctypes.c_int, + ctypes.c_int, ), glfw_callback_setter=glfw.GLFW.glfwSetMouseButtonCallback, ) @@ -199,7 +206,7 @@ def legacy_glfw_set_cursor_pos_callback(window, callback=None): callback=callback, key="cursor_pos_fun", c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_double, ctypes.c_double ), glfw_callback_setter=glfw.GLFW.glfwSetCursorPosCallback, ) @@ -211,7 +218,7 @@ def legacy_glfw_set_scroll_callback(window, callback=None): callback=callback, key="scroll_fun", c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_double, ctypes.c_double ), glfw_callback_setter=glfw.GLFW.glfwSetScrollCallback, ) @@ -223,7 +230,10 @@ def legacy_glfw_set_drop_callback(window, callback=None): callback=callback, key="drop_fun", c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int + None, + ctypes.POINTER(glfw._GLFWwindow), + ctypes.c_int, + ctypes.POINTER(ctypes.c_char_p), ), glfw_callback_setter=glfw.GLFW.glfwSetDropCallback, ) From ebf9fea2abf0b9ff4ab5c9c2c930810a6c404cec Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 29 Sep 2020 01:38:17 +0200 Subject: [PATCH 09/57] Convert glfw calls from C API to Python naming --- pupil_src/launchables/eye.py | 52 ++++++------- pupil_src/launchables/player.py | 75 +++++++++---------- pupil_src/launchables/world.py | 57 +++++++------- .../controller/gui_monitor.py | 6 +- .../controller/gui_window.py | 42 +++++------ .../natural_feature_plugin.py | 2 +- .../camera_intrinsics_estimation.py | 42 +++++------ .../reference_location_controllers.py | 2 +- .../shared_modules/gl_utils/glfw_legacy.py | 32 ++++---- pupil_src/shared_modules/gl_utils/utils.py | 18 ++--- .../gl_utils/window_position_manager.py | 4 +- .../head_pose_tracker/ui/gl_window.py | 40 +++++----- pupil_src/shared_modules/log_display.py | 4 +- pupil_src/shared_modules/roi.py | 4 +- pupil_src/shared_modules/service_ui.py | 38 +++++----- .../shared_modules/surface_tracker/gui.py | 58 +++++++------- pupil_src/shared_modules/system_graphs.py | 2 +- .../video_overlay/ui/interactions.py | 4 +- pupil_src/shared_modules/vis_watermark.py | 6 +- pupil_src/shared_modules/visualizer.py | 46 ++++++------ 20 files changed, 245 insertions(+), 289 deletions(-) diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index 585234a436..80e090c360 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -234,7 +234,7 @@ def get_timestamp(): ] def consume_events_and_render_buffer(): - glfw.GLFW.glfwMakeContextCurrent(main_window) + glfw.make_context_current(main_window) clear_gl_screen() if all(c > 0 for c in g_pool.camera_render_size): @@ -249,19 +249,17 @@ def consume_events_and_render_buffer(): # render GUI try: - clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() + clipboard = glfw.get_clipboard_string(main_window).decode() except AttributeError: # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.GLFW.glfwSetClipboardString( - main_window, user_input.clipboard.encode() - ) + glfw.set_clipboard_string(main_window, user_input.clipboard.encode()) for button, action, mods in user_input.buttons: - x, y = glfw.GLFW.glfwGetCursorPos(main_window) + x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -286,16 +284,14 @@ def consume_events_and_render_buffer(): break # update screen - glfw.GLFW.glfwSwapBuffers(main_window) + glfw.swap_buffers(main_window) # Callback functions def on_resize(window, w, h): nonlocal window_size nonlocal content_scale - is_minimized = bool( - glfw.GLFW.glfwGetWindowAttrib(window, glfw.GLFW.GLFW_ICONIFIED) - ) + is_minimized = bool(glfw.get_window_attrib(window, glfw.ICONIFIED)) if is_minimized: return @@ -305,8 +301,8 @@ def on_resize(window, w, h): gl_utils.glClear(gl_utils.GL_COLOR_BUFFER_BIT) gl_utils.glClearColor(0, 0, 0, 1) - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(window) + active_window = glfw.get_current_context() + glfw.make_context_current(window) content_scale = gl_utils.get_content_scale(window) framebuffer_scale = gl_utils.get_framebuffer_scale(window) g_pool.gui.scale = content_scale @@ -318,19 +314,19 @@ def on_resize(window, w, h): g.scale = content_scale g.adjust_window_size(w, h) adjust_gl_view(w, h) - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.make_context_current(active_window) # Minimum window size required, otherwise parts of the UI can cause openGL # issues with permanent effects. Depends on the content scale, which can # potentially be dynamically modified, so we re-adjust the size limits every # time here. min_size = int(2 * icon_bar_width * g_pool.gui.scale / framebuffer_scale) - glfw.GLFW.glfwSetWindowSizeLimits( + glfw.set_window_size_limits( window, min_size, min_size, - glfw.GLFW.GLFW_DONT_CARE, - glfw.GLFW.GLFW_DONT_CARE, + glfw.DONT_CARE, + glfw.DONT_CARE, ) # Needed, to update the window buffer while resizing @@ -409,9 +405,9 @@ def toggle_general_settings(collapsed): # Initialize glfw gl_utils.legacy_glfw_init() - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) + glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) if hide_ui: - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_VISIBLE, 0) # hide window + glfw.window_hint(glfw.VISIBLE, 0) # hide window title = "Pupil Capture - eye {}".format(eye_id) # Pupil Cam1 uses 4:3 resolutions. Pupil Cam2 and Cam3 use 1:1 resolutions. @@ -431,9 +427,9 @@ def toggle_general_settings(collapsed): default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) - glfw.GLFW.glfwSetWindowPos(main_window, window_pos[0], window_pos[1]) + glfw.set_window_pos(main_window, window_pos[0], window_pos[1]) - glfw.GLFW.glfwMakeContextCurrent(main_window) + glfw.make_context_current(main_window) cygl.utils.init() # gl_state settings @@ -476,7 +472,7 @@ def set_window_size(): f_width += icon_bar_width * display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) - glfw.GLFW.glfwSetWindowSize(main_window, int(f_width), int(f_height)) + glfw.set_window_size(main_window, int(f_width), int(f_height)) general_settings.append(ui.Button("Reset window size", set_window_size)) general_settings.append(ui.Switch("flip", g_pool, label="Flip image display")) @@ -567,7 +563,7 @@ def set_window_size(): g_pool.graphs = [cpu_graph, fps_graph] # set the last saved window size - on_resize(main_window, *glfw.GLFW.glfwGetFramebufferSize(main_window)) + on_resize(main_window, *glfw.get_framebuffer_size(main_window)) should_publish_frames = False frame_publish_format = "jpeg" @@ -584,7 +580,7 @@ def window_should_update(): frame = None # Event loop - while not glfw.GLFW.glfwWindowShouldClose(main_window): + while not glfw.window_should_close(main_window): if notify_sub.new_data: t, notification = notify_sub.recv() @@ -724,7 +720,7 @@ def window_should_update(): if window_should_update(): if is_window_visible(main_window): consume_events_and_render_buffer() - glfw.GLFW.glfwPollEvents() + glfw.poll_events() # END while running @@ -742,11 +738,9 @@ def window_should_update(): session_settings["version"] = str(g_pool.version) if not hide_ui: - glfw.GLFW.glfwRestoreWindow(main_window) # need to do this for windows os - session_settings["window_position"] = glfw.GLFW.glfwGetWindowPos( - main_window - ) - session_window_size = glfw.GLFW.glfwGetWindowSize(main_window) + glfw.restore_window(main_window) # need to do this for windows os + session_settings["window_position"] = glfw.get_window_pos(main_window) + session_window_size = glfw.get_window_size(main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index b6a751d14e..77a22a734b 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -193,20 +193,18 @@ def consume_events_and_render_buffer(): gl_utils.glViewport(0, 0, *window_size) try: - clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() + clipboard = glfw.get_clipboard_string(main_window).decode() except AttributeError: # clipbaord is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.GLFW.glfwSetClipboardString( - main_window, user_input.clipboard.encode() - ) + glfw.set_clipboard_string(main_window, user_input.clipboard.encode()) for b in user_input.buttons: button, action, mods = b - x, y = glfw.GLFW.glfwGetCursorPos(main_window) + x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -227,7 +225,7 @@ def consume_events_and_render_buffer(): if plugin.on_char(char_): break - glfw.GLFW.glfwSwapBuffers(main_window) + glfw.swap_buffers(main_window) # Callback functions def on_resize(window, w, h): @@ -256,12 +254,12 @@ def on_resize(window, w, h): # potentially be dynamically modified, so we re-adjust the size limits every # time here. min_size = int(2 * icon_bar_width * g_pool.gui.scale / framebuffer_scale) - glfw.GLFW.glfwSetWindowSizeLimits( + glfw.set_window_size_limits( window, min_size, min_size, - glfw.GLFW.GLFW_DONT_CARE, - glfw.GLFW.GLFW_DONT_CARE, + glfw.DONT_CARE, + glfw.DONT_CARE, ) # Needed, to update the window buffer while resizing @@ -310,7 +308,7 @@ def _restart_with_recording(rec_dir): ipc_pub.notify( {"subject": "player_drop_process.should_start", "rec_dir": rec_dir} ) - glfw.GLFW.glfwSetWindowShouldClose(g_pool.main_window, True) + glfw.set_window_should_close(g_pool.main_window, True) tick = delta_t() @@ -366,7 +364,7 @@ def get_dt(): window_name = f"Pupil Player: {meta_info.recording_name} - {rec_dir}" gl_utils.legacy_glfw_init() - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) + glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) main_window = gl_utils.legacy_glfw_create_window( width, height, window_name, None, None ) @@ -377,9 +375,9 @@ def get_dt(): default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) - glfw.GLFW.glfwSetWindowPos(main_window, window_pos[0], window_pos[1]) + glfw.set_window_pos(main_window, window_pos[0], window_pos[1]) - glfw.GLFW.glfwMakeContextCurrent(main_window) + glfw.make_context_current(main_window) cygl.utils.init() g_pool.main_window = main_window @@ -442,7 +440,7 @@ def do_export(_): def reset_restart(): logger.warning("Resetting all settings and restarting Player.") - glfw.GLFW.glfwSetWindowShouldClose(main_window, True) + glfw.set_window_should_close(main_window, True) ipc_pub.notify({"subject": "clear_settings_process.should_start"}) ipc_pub.notify( { @@ -497,7 +495,7 @@ def set_window_size(): f_width += icon_bar_width * display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) - glfw.GLFW.glfwSetWindowSize(main_window, int(f_width), int(f_height)) + glfw.set_window_size(main_window, int(f_width), int(f_height)) general_settings = ui.Growing_Menu("General", header_pos="headline") general_settings.append(ui.Button("Reset window size", set_window_size)) @@ -636,7 +634,7 @@ def set_window_size(): g_pool.image_tex = Named_Texture() # trigger on_resize - on_resize(main_window, *glfw.GLFW.glfwGetFramebufferSize(main_window)) + on_resize(main_window, *glfw.get_framebuffer_size(main_window)) def handle_notifications(n): subject = n["subject"] @@ -661,10 +659,7 @@ def handle_notifications(n): } ) - while ( - not glfw.GLFW.glfwWindowShouldClose(main_window) - and not process_was_interrupted - ): + while not glfw.window_should_close(main_window) and not process_was_interrupted: # fetch newest notifications new_notifications = [] @@ -693,8 +688,8 @@ def handle_notifications(n): # check if a plugin need to be destroyed g_pool.plugins.clean() - glfw.GLFW.glfwMakeContextCurrent(main_window) - glfw.GLFW.glfwPollEvents() + glfw.make_context_current(main_window) + glfw.poll_events() # render visual feedback from loaded plugins if gl_utils.is_window_visible(main_window): @@ -706,20 +701,20 @@ def handle_notifications(n): gl_utils.glViewport(0, 0, *window_size) try: - clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() + clipboard = glfw.get_clipboard_string(main_window).decode() except AttributeError: # clipbaord is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.GLFW.glfwSetClipboardString( + glfw.set_clipboard_string( main_window, user_input.clipboard.encode() ) for b in user_input.buttons: button, action, mods = b - x, y = glfw.GLFW.glfwGetCursorPos(main_window) + x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -742,7 +737,7 @@ def handle_notifications(n): # present frames at appropriate speed g_pool.seek_control.wait(events["frame"].timestamp) - glfw.GLFW.glfwSwapBuffers(main_window) + glfw.swap_buffers(main_window) session_settings["loaded_plugins"] = g_pool.plugins.get_initializers() session_settings["min_data_confidence"] = g_pool.min_data_confidence @@ -750,10 +745,10 @@ def handle_notifications(n): "min_calibration_confidence" ] = g_pool.min_calibration_confidence session_settings["ui_config"] = g_pool.gui.configuration - session_settings["window_position"] = glfw.GLFW.glfwGetWindowPos(main_window) + session_settings["window_position"] = glfw.get_window_pos(main_window) session_settings["version"] = str(g_pool.version) - session_window_size = glfw.GLFW.glfwGetWindowSize(main_window) + session_window_size = glfw.get_window_size(main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): @@ -858,12 +853,12 @@ def on_drop(window, count, paths): w, h = session_settings.get("window_size", (1280, 720)) gl_utils.legacy_glfw_init() - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_RESIZABLE, 0) + glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) + glfw.window_hint(glfw.RESIZABLE, 0) window = gl_utils.legacy_glfw_create_window(w, h, "Pupil Player") - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_RESIZABLE, 1) + glfw.window_hint(glfw.RESIZABLE, 1) - glfw.GLFW.glfwMakeContextCurrent(window) + glfw.make_context_current(window) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( @@ -871,7 +866,7 @@ def on_drop(window, count, paths): default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) - glfw.GLFW.glfwSetWindowPos(window, window_pos[0], window_pos[1]) + glfw.set_window_pos(window, window_pos[0], window_pos[1]) gl_utils.legacy_glfw_set_drop_callback(window, on_drop) @@ -899,11 +894,9 @@ def display_string(string, font_size, center_y): glfont.set_color_float((1.0, 1.0, 1.0, 1.0)) glfont.draw_text(x, y, string) - while ( - not glfw.GLFW.glfwWindowShouldClose(window) and not process_was_interrupted - ): + while not glfw.window_should_close(window) and not process_was_interrupted: - fb_size = glfw.GLFW.glfwGetFramebufferSize(window) + fb_size = glfw.get_framebuffer_size(window) content_scale = gl_utils.get_content_scale(window) gl_utils.adjust_gl_view(*fb_size) @@ -931,7 +924,7 @@ def display_string(string, font_size, center_y): center_y = 288 + tip_font_size * idx * 1.2 display_string(line, font_size=tip_font_size, center_y=center_y) - glfw.GLFW.glfwSwapBuffers(window) + glfw.swap_buffers(window) if rec_dir: try: @@ -950,11 +943,11 @@ def display_string(string, font_size, center_y): tip = err.reason rec_dir = None else: - glfw.GLFW.glfwSetWindowShouldClose(window, True) + glfw.set_window_should_close(window, True) - glfw.GLFW.glfwPollEvents() + glfw.poll_events() - session_settings["window_position"] = glfw.GLFW.glfwGetWindowPos(window) + session_settings["window_position"] = glfw.get_window_pos(window) session_settings.close() gl_utils.legacy_glfw_destroy_window(window) if rec_dir: diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index 28bd5ff130..0f2ce31ac6 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -333,19 +333,17 @@ def consume_events_and_render_buffer(): gl_utils.glViewport(0, 0, *window_size) try: - clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() + clipboard = glfw.get_clipboard_string(main_window).decode() except AttributeError: # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.GLFW.glfwSetClipboardString( - main_window, user_input.clipboard.encode() - ) + glfw.set_clipboard_string(main_window, user_input.clipboard.encode()) for button, action, mods in user_input.buttons: - x, y = glfw.GLFW.glfwGetCursorPos(main_window) + x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -367,7 +365,7 @@ def consume_events_and_render_buffer(): if plugin.on_char(char_): break - glfw.GLFW.glfwSwapBuffers(main_window) + glfw.swap_buffers(main_window) # Callback functions def on_resize(window, w, h): @@ -398,12 +396,12 @@ def on_resize(window, w, h): # potentially be dynamically modified, so we re-adjust the size limits every # time here. min_size = int(2 * icon_bar_width * g_pool.gui.scale / framebuffer_scale) - glfw.GLFW.glfwSetWindowSizeLimits( + glfw.set_window_size_limits( window, min_size, min_size, - glfw.GLFW.GLFW_DONT_CARE, - glfw.GLFW.GLFW_DONT_CARE, + glfw.DONT_CARE, + glfw.DONT_CARE, ) # Needed, to update the window buffer while resizing @@ -517,9 +515,9 @@ def handle_notifications(noti): # window and gl setup gl_utils.legacy_glfw_init() - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) + glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) if hide_ui: - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_VISIBLE, 0) # hide window + glfw.window_hint(glfw.VISIBLE, 0) # hide window main_window = gl_utils.legacy_glfw_create_window( width, height, "Pupil Capture - World" ) @@ -530,15 +528,15 @@ def handle_notifications(noti): default_position=window_position_default, previous_position=session_settings.get("window_position", None), ) - glfw.GLFW.glfwSetWindowPos(main_window, window_pos[0], window_pos[1]) + glfw.set_window_pos(main_window, window_pos[0], window_pos[1]) - glfw.GLFW.glfwMakeContextCurrent(main_window) + glfw.make_context_current(main_window) cygl.utils.init() g_pool.main_window = main_window def reset_restart(): logger.warning("Resetting all settings and restarting Capture.") - glfw.GLFW.glfwSetWindowShouldClose(main_window, True) + glfw.set_window_should_close(main_window, True) ipc_pub.notify({"subject": "clear_settings_process.should_start"}) ipc_pub.notify({"subject": "world_process.should_start", "delay": 2.0}) @@ -583,7 +581,7 @@ def set_window_size(): f_width += icon_bar_width * display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) - glfw.GLFW.glfwSetWindowSize(main_window, int(f_width), int(f_height)) + glfw.set_window_size(main_window, int(f_width), int(f_height)) general_settings.append(ui.Button("Reset window size", set_window_size)) general_settings.append( @@ -695,7 +693,7 @@ def window_should_update(): return next(window_update_timer) # trigger setup of window and gl sizes - on_resize(main_window, *glfw.GLFW.glfwGetFramebufferSize(main_window)) + on_resize(main_window, *glfw.get_framebuffer_size(main_window)) if session_settings.get("eye1_process_alive", True): launch_eye_process(1, delay=0.6) @@ -706,10 +704,7 @@ def window_should_update(): logger.warning("Process started.") # Event loop - while ( - not glfw.GLFW.glfwWindowShouldClose(main_window) - and not process_was_interrupted - ): + while not glfw.window_should_close(main_window) and not process_was_interrupted: # fetch newest notifications new_notifications = [] @@ -754,9 +749,9 @@ def window_should_update(): for d in data: ipc_pub.send(d) - glfw.GLFW.glfwMakeContextCurrent(main_window) + glfw.make_context_current(main_window) # render visual feedback from loaded plugins - glfw.GLFW.glfwPollEvents() + glfw.poll_events() if window_should_update() and gl_utils.is_window_visible(main_window): gl_utils.glViewport(0, 0, *camera_render_size) @@ -765,19 +760,19 @@ def window_should_update(): gl_utils.glViewport(0, 0, *window_size) try: - clipboard = glfw.GLFW.glfwGetClipboardString(main_window).decode() + clipboard = glfw.get_clipboard_string(main_window).decode() except AttributeError: # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.GLFW.glfwSetClipboardString( + glfw.set_clipboard_string( main_window, user_input.clipboard.encode() ) for button, action, mods in user_input.buttons: - x, y = glfw.GLFW.glfwGetCursorPos(main_window) + x, y = glfw.get_cursor_pos(main_window) pos = gl_utils.window_coordinate_to_framebuffer_coordinate( main_window, x, y, cached_scale=None ) @@ -799,7 +794,7 @@ def window_should_update(): if plugin.on_char(char_): break - glfw.GLFW.glfwSwapBuffers(main_window) + glfw.swap_buffers(main_window) session_settings["loaded_plugins"] = g_pool.plugins.get_initializers() session_settings["ui_config"] = g_pool.gui.configuration @@ -813,11 +808,9 @@ def window_should_update(): session_settings["audio_mode"] = audio.get_audio_mode() if not hide_ui: - glfw.GLFW.glfwRestoreWindow(main_window) # need to do this for windows os - session_settings["window_position"] = glfw.GLFW.glfwGetWindowPos( - main_window - ) - session_window_size = glfw.GLFW.glfwGetWindowSize(main_window) + glfw.restore_window(main_window) # need to do this for windows os + session_settings["window_position"] = glfw.get_window_pos(main_window) + session_window_size = glfw.get_window_size(main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): @@ -836,7 +829,7 @@ def window_should_update(): g_pool.gui.terminate() gl_utils.legacy_glfw_destroy_window(main_window) - glfw.GLFW.glfwTerminate() + glfw.terminate() except Exception: import traceback diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py index 2b28e01874..aebf2edfc6 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py @@ -33,7 +33,7 @@ class GUIMonitor: def __init__(self, index, gl_handle): self.__gl_handle = gl_handle - self.__name = glfw.GLFW.glfwGetMonitorName(gl_handle).decode("utf-8") + self.__name = glfw.get_monitor_name(gl_handle).decode("utf-8") self.__index = index @property @@ -66,7 +66,7 @@ def is_available(self) -> bool: @staticmethod def currently_connected_monitors() -> T.List["GUIMonitor"]: - return [GUIMonitor(i, h) for i, h in enumerate(glfw.GLFW.glfwGetMonitors())] + return [GUIMonitor(i, h) for i, h in enumerate(glfw.get_monitors())] @staticmethod def currently_connected_monitors_by_name() -> T_OrderedDict[str, "GUIMonitor"]: @@ -76,7 +76,7 @@ def currently_connected_monitors_by_name() -> T_OrderedDict[str, "GUIMonitor"]: @staticmethod def primary_monitor() -> "GUIMonitor": - gl_handle = glfw.GLFW.glfwGetPrimaryMonitor() + gl_handle = glfw.get_primary_monitor() return GUIMonitor(0, gl_handle) @staticmethod diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py index 5a904b2669..a854e966f6 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py @@ -36,7 +36,7 @@ def content_scale(self) -> float: @property def window_size(self) -> T.Tuple[int, int]: if self.__gl_handle is not None: - return glfw.GLFW.glfwGetFramebufferSize(self.__gl_handle) + return glfw.get_framebuffer_size(self.__gl_handle) else: return (0, 0) @@ -45,14 +45,10 @@ def is_open(self) -> bool: return self.__gl_handle is not None def cursor_hide(self): - glfw.GLFW.glfwSetInputMode( - self.__gl_handle, glfw.GLFW.GLFW_CURSOR, glfw.GLFW.GLFW_CURSOR_HIDDEN - ) + glfw.set_input_mode(self.__gl_handle, glfw.CURSOR, glfw.CURSOR_HIDDEN) def cursor_disable(self): - glfw.GLFW.glfwSetInputMode( - self.__gl_handle, glfw.GLFW.GLFW_CURSOR, glfw.GLFW.GLFW_CURSOR_DISABLED - ) + glfw.set_input_mode(self.__gl_handle, glfw.CURSOR, glfw.CURSOR_DISABLED) def open( self, @@ -91,11 +87,11 @@ def open( # a blank window directly in fullscreen mode. By creating it windowed and # then switching to fullscreen it will stay white the entire time. self.__gl_handle = gl_utils.legacy_glfw_create_window( - *size, title, share=glfw.GLFW.glfwGetCurrentContext() + *size, title, share=glfw.get_current_context() ) if not is_fullscreen: - glfw.GLFW.glfwSetWindowPos(self.__gl_handle, *position) + glfw.set_window_pos(self.__gl_handle, *position) # Register callbacks gl_utils.legacy_glfw_set_framebuffer_size_callback( @@ -105,18 +101,16 @@ def open( gl_utils.legacy_glfw_set_mouse_button_callback( self.__gl_handle, self.on_mouse_button ) - self.on_resize( - self.__gl_handle, *glfw.GLFW.glfwGetFramebufferSize(self.__gl_handle) - ) + self.on_resize(self.__gl_handle, *glfw.get_framebuffer_size(self.__gl_handle)) # gl_state settings with self._switch_to_current_context(): gl_utils.basic_gl_setup() - glfw.GLFW.glfwSwapInterval(0) + glfw.swap_interval(0) if is_fullscreen: # Switch to full screen here. See NOTE above at legacy_glfw_create_window(). - glfw.GLFW.glfwSetWindowMonitor( + glfw.set_window_monitor( self.__gl_handle, gui_monitor.unsafe_handle, 0, @@ -129,9 +123,7 @@ def close(self): if not self.is_open: return with self._switch_to_current_context(): - glfw.GLFW.glfwSetInputMode( - self.__gl_handle, glfw.GLFW.GLFW_CURSOR, glfw.GLFW.GLFW_CURSOR_NORMAL - ) + glfw.set_input_mode(self.__gl_handle, glfw.CURSOR, glfw.CURSOR_NORMAL) gl_utils.legacy_glfw_destroy_window(self.__gl_handle) self.__gl_handle = None @@ -140,7 +132,7 @@ def drawing_context(self): if self.__gl_handle is None: return - if glfw.GLFW.glfwWindowShouldClose(self.__gl_handle): + if glfw.window_should_close(self.__gl_handle): self.close() return @@ -156,19 +148,19 @@ def drawing_context(self): yield self.unsafe_handle - glfw.GLFW.glfwSwapBuffers(self.unsafe_handle) + glfw.swap_buffers(self.unsafe_handle) def on_resize(self, gl_handle, w, h): with self._switch_to_current_context(): gl_utils.adjust_gl_view(w, h) def on_key(self, gl_handle, key, scancode, action, mods): - if action == glfw.GLFW.GLFW_PRESS: - if key == glfw.GLFW.GLFW_KEY_ESCAPE: + if action == glfw.PRESS: + if key == glfw.KEY_ESCAPE: self.on_key_press_escape() def on_mouse_button(self, gl_handle, button, action, mods): - if action == glfw.GLFW.GLFW_PRESS: + if action == glfw.PRESS: self.on_left_click() def on_left_click(self): @@ -179,9 +171,9 @@ def on_key_press_escape(self): @contextlib.contextmanager def _switch_to_current_context(self): - previous_context = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(self.__gl_handle) + previous_context = glfw.get_current_context() + glfw.make_context_current(self.__gl_handle) try: yield finally: - glfw.GLFW.glfwMakeContextCurrent(previous_context) + glfw.make_context_current(previous_context) diff --git a/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py b/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py index 6acafbcda3..2c95fdbdfb 100644 --- a/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py @@ -116,7 +116,7 @@ def gl_display(self): ) def on_click(self, pos, button, action): - if action == glfw.GLFW.GLFW_PRESS and self.is_active: + if action == glfw.PRESS and self.is_active: self.__feature_tracker.reset(pos) self.__number_of_ref_points_gathered_from_last_click = 0 return True # click consumed diff --git a/pupil_src/shared_modules/camera_intrinsics_estimation.py b/pupil_src/shared_modules/camera_intrinsics_estimation.py index a19586b033..e73ac69902 100644 --- a/pupil_src/shared_modules/camera_intrinsics_estimation.py +++ b/pupil_src/shared_modules/camera_intrinsics_estimation.py @@ -40,10 +40,10 @@ # window calbacks def on_resize(window, w, h): - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(window) + active_window = glfw.get_current_context() + glfw.make_context_current(window) adjust_gl_view(w, h) - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.make_context_current(active_window) class Camera_Intrinsics_Estimation(Plugin): @@ -105,9 +105,7 @@ def init_ui(self): self.menu.label = "Camera Intrinsics Estimation" def get_monitors_idx_list(): - monitors = [ - glfw.GLFW.glfwGetMonitorName(m) for m in glfw.GLFW.glfwGetMonitors() - ] + monitors = [glfw.get_monitor_name(m) for m in glfw.get_monitors()] return range(len(monitors)), monitors if self.monitor_idx not in get_monitors_idx_list()[0]: @@ -185,13 +183,13 @@ def open_window(self): if not self._window: if self.fullscreen: try: - monitor = glfw.GLFW.glfwGetMonitors()[self.monitor_idx] + monitor = glfw.get_monitors()[self.monitor_idx] except Exception: logger.warning( "Monitor at index %s no longer availalbe using default" % idx ) self.monitor_idx = 0 - monitor = glfw.GLFW.glfwGetMonitors()[self.monitor_idx] + monitor = glfw.get_monitors()[self.monitor_idx] mode = gl_utils.legacy_glfw_get_video_mode(monitor) height, width = mode[0], mode[1] else: @@ -203,11 +201,11 @@ def open_window(self): width, "Calibration", monitor=monitor, - share=glfw.GLFW.glfwGetCurrentContext(), + share=glfw.get_current_context(), ) if not self.fullscreen: # move to y = 31 for windows os - glfw.GLFW.glfwSetWindowPos(self._window, 200, 31) + glfw.set_window_pos(self._window, 200, 31) # Register callbacks gl_utils.legacy_glfw_set_framebuffer_size_callback(self._window, on_resize) @@ -217,23 +215,23 @@ def open_window(self): self._window, self.on_window_mouse_button ) - on_resize(self._window, *glfw.GLFW.glfwGetFramebufferSize(self._window)) + on_resize(self._window, *glfw.get_framebuffer_size(self._window)) # gl_state settings - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(self._window) + active_window = glfw.get_current_context() + glfw.make_context_current(self._window) basic_gl_setup() - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.make_context_current(active_window) self.clicks_to_close = 5 def on_window_key(self, window, key, scancode, action, mods): - if action == glfw.GLFW.GLFW_PRESS: - if key == glfw.GLFW.GLFW_KEY_ESCAPE: + if action == glfw.PRESS: + if key == glfw.KEY_ESCAPE: self.on_close() def on_window_mouse_button(self, window, button, action, mods): - if action == glfw.GLFW.GLFW_PRESS: + if action == glfw.PRESS: self.clicks_to_close -= 1 if self.clicks_to_close == 0: self.on_close() @@ -363,14 +361,14 @@ def gl_display(self): gl.glPopMatrix() def gl_display_in_window(self): - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(self._window) + active_window = glfw.get_current_context() + glfw.make_context_current(self._window) clear_gl_screen() gl.glMatrixMode(gl.GL_PROJECTION) gl.glLoadIdentity() - p_window_size = glfw.GLFW.glfwGetWindowSize(self._window) + p_window_size = glfw.get_window_size(self._window) r = p_window_size[0] / 15.0 # compensate for radius of marker gl.glOrtho(-r, p_window_size[0] + r, p_window_size[1] + r, -r, -1, 1) @@ -393,8 +391,8 @@ def gl_display_in_window(self): "Touch {} more times to close window.".format(self.clicks_to_close), ) - glfw.GLFW.glfwSwapBuffers(self._window) - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.swap_buffers(self._window) + glfw.make_context_current(active_window) def get_init_dict(self): return {"monitor_idx": self.monitor_idx} diff --git a/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py b/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py index 46ce51b8a0..fcf1d15fd0 100644 --- a/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py +++ b/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py @@ -103,7 +103,7 @@ def jump_to_prev_ref(self): self._seek_to_frame(prev_ref.frame_index) def _on_click(self, pos, button, action): - if action == glfw.GLFW.GLFW_PRESS: + if action == glfw.PRESS: self._add_or_delete_ref_on_click(pos) def _add_or_delete_ref_on_click(self, pos): diff --git a/pupil_src/shared_modules/gl_utils/glfw_legacy.py b/pupil_src/shared_modules/gl_utils/glfw_legacy.py index 22095db249..5e7c19c0ad 100644 --- a/pupil_src/shared_modules/gl_utils/glfw_legacy.py +++ b/pupil_src/shared_modules/gl_utils/glfw_legacy.py @@ -12,7 +12,7 @@ def legacy_glfw_get_video_mode(monitor): - mode_struct = glfw.GLFW.glfwGetVideoMode(monitor) + mode_struct = glfw.get_video_mode(monitor) return ( mode_struct.width, mode_struct.height, @@ -24,13 +24,13 @@ def legacy_glfw_get_video_mode(monitor): def legacy_glfw_get_error(): - code, msg = glfw.GLFW.glfwGetError() + code, msg = glfw.get_error() if code: return msg.value.decode() def legacy_glfw_init(): - res = glfw.GLFW.glfwInit() + res = glfw.init() if res < 0: raise Exception(f"GLFW could not be initialized: {legacy_glfw_get_error()}") @@ -39,7 +39,7 @@ def legacy_glfw_create_window( width=640, height=480, title="GLFW Window", monitor=None, share=None ): - window = glfw.GLFW.glfwCreateWindow(width, height, title, monitor, share) + window = glfw.create_window(width, height, title, monitor, share) if window: __windows__.append(window) @@ -70,7 +70,7 @@ def legacy_glfw_destroy_window(window): except KeyError: logger.error("Window already destroyed.") else: - glfw.GLFW.glfwDestroyWindow(window) + glfw.destroy_window(window) # We do not delete window from the list (or it would impact windows numbering) # del __windows__[index] del __c_callbacks__[index] @@ -105,7 +105,7 @@ def legacy_glfw_set_window_pos_callback(window, callback=None): c_func_type=ctypes.CFUNCTYPE( None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int ), - glfw_callback_setter=glfw.GLFW.glfwSetWindowPosCallback, + glfw_callback_setter=glfw.set_window_posCallback, ) @@ -117,7 +117,7 @@ def legacy_glfw_set_window_size_callback(window, callback=None): c_func_type=ctypes.CFUNCTYPE( None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int ), - glfw_callback_setter=glfw.GLFW.glfwSetWindowSizeCallback, + glfw_callback_setter=glfw.set_window_sizeCallback, ) @@ -127,7 +127,7 @@ def legacy_glfw_set_window_close_callback(window, callback=None): callback=callback, key="window_close_fun", c_func_type=ctypes.CFUNCTYPE(None, ctypes.POINTER(glfw._GLFWwindow)), - glfw_callback_setter=glfw.GLFW.glfwSetWindowCloseCallback, + glfw_callback_setter=glfw.set_window_close_callback, ) @@ -139,7 +139,7 @@ def legacy_glfw_set_window_iconify_callback(window, callback=None): c_func_type=ctypes.CFUNCTYPE( None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int ), - glfw_callback_setter=glfw.GLFW.glfwSetWindowIconifyCallback, + glfw_callback_setter=glfw.set_window_iconify_callback, ) @@ -151,7 +151,7 @@ def legacy_glfw_set_framebuffer_size_callback(window, callback=None): c_func_type=ctypes.CFUNCTYPE( None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int ), - glfw_callback_setter=glfw.GLFW.glfwSetFramebufferSizeCallback, + glfw_callback_setter=glfw.set_framebuffer_size_callback, ) @@ -168,7 +168,7 @@ def legacy_glfw_set_key_callback(window, callback=None): ctypes.c_int, ctypes.c_int, ), - glfw_callback_setter=glfw.GLFW.glfwSetKeyCallback, + glfw_callback_setter=glfw.set_key_callback, ) @@ -180,7 +180,7 @@ def legacy_glfw_set_char_callback(window, callback=None): c_func_type=ctypes.CFUNCTYPE( None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int ), - glfw_callback_setter=glfw.GLFW.glfwSetCharCallback, + glfw_callback_setter=glfw.set_char_callback, ) @@ -196,7 +196,7 @@ def legacy_glfw_set_mouse_button_callback(window, callback=None): ctypes.c_int, ctypes.c_int, ), - glfw_callback_setter=glfw.GLFW.glfwSetMouseButtonCallback, + glfw_callback_setter=glfw.set_mouse_button_callback, ) @@ -208,7 +208,7 @@ def legacy_glfw_set_cursor_pos_callback(window, callback=None): c_func_type=ctypes.CFUNCTYPE( None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_double, ctypes.c_double ), - glfw_callback_setter=glfw.GLFW.glfwSetCursorPosCallback, + glfw_callback_setter=glfw.set_cursor_pos_callback, ) @@ -220,7 +220,7 @@ def legacy_glfw_set_scroll_callback(window, callback=None): c_func_type=ctypes.CFUNCTYPE( None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_double, ctypes.c_double ), - glfw_callback_setter=glfw.GLFW.glfwSetScrollCallback, + glfw_callback_setter=glfw.set_scroll_callback, ) @@ -235,5 +235,5 @@ def legacy_glfw_set_drop_callback(window, callback=None): ctypes.c_int, ctypes.POINTER(ctypes.c_char_p), ), - glfw_callback_setter=glfw.GLFW.glfwSetDropCallback, + glfw_callback_setter=glfw.set_drop_callback, ) diff --git a/pupil_src/shared_modules/gl_utils/utils.py b/pupil_src/shared_modules/gl_utils/utils.py index 8b87321d6e..2940c5eac1 100644 --- a/pupil_src/shared_modules/gl_utils/utils.py +++ b/pupil_src/shared_modules/gl_utils/utils.py @@ -103,8 +103,8 @@ def custom_gl_error_handling( def is_window_visible(window): - visible = glfw.GLFW.glfwGetWindowAttrib(window, glfw.GLFW.GLFW_VISIBLE) - iconified = glfw.GLFW.glfwGetWindowAttrib(window, glfw.GLFW.GLFW_ICONIFIED) + visible = glfw.get_window_attrib(window, glfw.VISIBLE) + iconified = glfw.get_window_attrib(window, glfw.ICONIFIED) return visible and not iconified @@ -258,12 +258,12 @@ def intersection(self, other: "_Rectangle") -> T.Optional["_Rectangle"]: def get_content_scale(window) -> float: # TODO: Explicitly rename to `get_content_scale_x` - return glfw.GLFW.glfwGetWindowContentScale(window)[0] + return glfw.get_window_content_scale(window)[0] def get_framebuffer_scale(window) -> float: - window_width = glfw.GLFW.glfwGetWindowSize(window)[0] - framebuffer_width = glfw.GLFW.glfwGetFramebufferSize(window)[0] + window_width = glfw.get_window_size(window)[0] + framebuffer_width = glfw.get_framebuffer_size(window)[0] try: return float(framebuffer_width / window_width) @@ -277,18 +277,18 @@ def window_coordinate_to_framebuffer_coordinate(window, x, y, cached_scale=None) def get_monitor_workarea_rect(monitor) -> _Rectangle: - x, y, w, h = glfw.GLFW.glfwGetMonitorWorkarea(monitor) + x, y, w, h = glfw.get_monitor_workarea(monitor) return _Rectangle(x=x, y=y, width=w, height=h) def get_window_content_rect(window) -> _Rectangle: - x, y = glfw.GLFW.glfwGetWindowPos(window) - w, h = glfw.GLFW.glfwGetWindowSize(window) + x, y = glfw.get_window_pos(window) + w, h = glfw.get_window_size(window) return _Rectangle(x=x, y=y, width=w, height=h) def get_window_frame_size_margins(window) -> _Margins: - left, top, right, bottom = glfw.GLFW.glfwGetWindowFrameSize(window) + left, top, right, bottom = glfw.get_window_frame_size(window) return _Margins(left=left, top=top, right=right, bottom=bottom) diff --git a/pupil_src/shared_modules/gl_utils/window_position_manager.py b/pupil_src/shared_modules/gl_utils/window_position_manager.py index 3160698bfb..9af748f6fb 100644 --- a/pupil_src/shared_modules/gl_utils/window_position_manager.py +++ b/pupil_src/shared_modules/gl_utils/window_position_manager.py @@ -50,7 +50,7 @@ def validate_previous_position(monitor) -> bool: window_position=previous_position, ) - if any(validate_previous_position(m) for m in glfw.GLFW.glfwGetMonitors()): + if any(validate_previous_position(m) for m in glfw.get_monitors()): return previous_position else: return default_position @@ -63,7 +63,7 @@ def _will_window_be_visible_in_monitor( window, monitor, window_position, min_visible_width=30, min_visible_height=20 ) -> bool: # Get the current window size and edges, and monitor rect - window_size = glfw.GLFW.glfwGetWindowSize(window) + window_size = glfw.get_window_size(window) window_edges = gl_utils.get_window_frame_size_margins(window) monitor_rect = gl_utils.get_monitor_workarea_rect(monitor) diff --git a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py index 5e6b45cefe..f33ea48f55 100644 --- a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py +++ b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py @@ -63,21 +63,21 @@ def _init_trackball(): def _glfw_init(self): gl_utils.legacy_glfw_init() - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) + glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) window = gl_utils.legacy_glfw_create_window( title="Head Pose Tracker Visualizer", - share=glfw.GLFW.glfwGetCurrentContext(), + share=glfw.get_current_context(), ) return window @staticmethod def _gl_state_settings(window): - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(window) + active_window = glfw.get_current_context() + glfw.make_context_current(window) gl_utils.basic_gl_setup() gl_utils.make_coord_system_norm_based() - glfw.GLFW.glfwSwapInterval(0) - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.swap_interval(0) + glfw.make_context_current(active_window) def _register_callbacks(self, window): gl_utils.legacy_glfw_set_window_size_callback(window, self._on_set_window_size) @@ -95,10 +95,8 @@ def _register_callbacks(self, window): ) def _set_initial_window_state(self): - glfw.GLFW.glfwSetWindowPos( - self._window, *self._general_settings.window_position - ) - glfw.GLFW.glfwSetWindowSize(self._window, *self._general_settings.window_size) + glfw.set_window_pos(self._window, *self._general_settings.window_position) + glfw.set_window_size(self._window, *self._general_settings.window_size) def _on_set_window_size(self, window, w, h): self._general_settings.window_size = (w, h) @@ -108,16 +106,16 @@ def _on_set_window_pos(self, window, x, y): def _on_set_frame_buffer_size(self, window, w, h): self._trackball.set_window_size(w, h) - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(window) + active_window = glfw.get_current_context() + glfw.make_context_current(window) gl_utils.adjust_gl_view(w, h) - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.make_context_current(active_window) def _on_set_mouse_button(self, window, button, action, mods): - if action == glfw.GLFW.GLFW_PRESS: + if action == glfw.PRESS: self._input["down"] = True - self._input["mouse"] = glfw.GLFW.glfwGetCursorPos(window) - elif action == glfw.GLFW.GLFW_RELEASE: + self._input["mouse"] = glfw.get_cursor_pos(window) + elif action == glfw.RELEASE: self._input["down"] = False def _on_set_cursor_pos(self, window, x, y): @@ -149,17 +147,17 @@ def _on_gl_display(self): if not self._window: return - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(self._window) + active_window = glfw.get_current_context() + glfw.make_context_current(self._window) self._init_3d_window() self._trackball.push() self._render() self._trackball.pop() - glfw.GLFW.glfwSwapBuffers(self._window) - glfw.GLFW.glfwMakeContextCurrent(active_window) - glfw.GLFW.glfwPollEvents() + glfw.swap_buffers(self._window) + glfw.make_context_current(active_window) + glfw.poll_events() @staticmethod def _init_3d_window(): diff --git a/pupil_src/shared_modules/log_display.py b/pupil_src/shared_modules/log_display.py index 5579ee7cff..970ffb46dc 100644 --- a/pupil_src/shared_modules/log_display.py +++ b/pupil_src/shared_modules/log_display.py @@ -67,9 +67,7 @@ def init_ui(self): self.glfont.set_color_float((0.2, 0.5, 0.9, 1.0)) self.glfont.set_align_string(v_align="center", h_align="middle") - self.window_size = glfw.GLFW.glfwGetFramebufferSize( - glfw.GLFW.glfwGetCurrentContext() - ) + self.window_size = glfw.get_framebuffer_size(glfw.get_current_context()) self.tex = Render_Target(*self.window_size) self._socket = zmq_tools.Msg_Receiver( diff --git a/pupil_src/shared_modules/roi.py b/pupil_src/shared_modules/roi.py index 4c1c184195..f7d61de42a 100644 --- a/pupil_src/shared_modules/roi.py +++ b/pupil_src/shared_modules/roi.py @@ -290,12 +290,12 @@ def on_click(self, pos: Vec2, button: int, action: int) -> bool: if not self.has_frame or self.model.is_invalid(): return False - if action == glfw.GLFW.GLFW_PRESS: + if action == glfw.PRESS: clicked_handle = self.get_handle_at(pos) if clicked_handle != self.active_handle: self.active_handle = clicked_handle return True - elif action == glfw.GLFW.GLFW_RELEASE: + elif action == glfw.RELEASE: if self.active_handle != Handle.NONE: self.active_handle = Handle.NONE return True diff --git a/pupil_src/shared_modules/service_ui.py b/pupil_src/shared_modules/service_ui.py index acf7d466f2..3724b9c2ac 100644 --- a/pupil_src/shared_modules/service_ui.py +++ b/pupil_src/shared_modules/service_ui.py @@ -50,9 +50,9 @@ def __init__( self.texture = np.zeros((1, 1, 3), dtype=np.uint8) + 128 gl_utils.legacy_glfw_init() - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE) + glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) if g_pool.hide_ui: - glfw.GLFW.glfwWindowHint(glfw.GLFW.GLFW_VISIBLE, 0) # hide window + glfw.window_hint(glfw.VISIBLE, 0) # hide window main_window = gl_utils.legacy_glfw_create_window(*window_size, "Pupil Service") window_position_manager = gl_utils.WindowPositionManager() @@ -61,9 +61,9 @@ def __init__( default_position=window_position_default, previous_position=window_position, ) - glfw.GLFW.glfwSetWindowPos(main_window, *window_position) + glfw.set_window_pos(main_window, *window_position) - glfw.GLFW.glfwMakeContextCurrent(main_window) + glfw.make_context_current(main_window) cygl.utils.init() g_pool.main_window = main_window @@ -121,11 +121,11 @@ def set_window_size(): f_height *= display_scale_factor # Set the newly calculated size (scaled capture frame size + scaled icon bar width) - glfw.GLFW.glfwSetWindowSize(main_window, int(f_width), int(f_height)) + glfw.set_window_size(main_window, int(f_width), int(f_height)) def reset_restart(): logger.warning("Resetting all settings and restarting Capture.") - glfw.GLFW.glfwSetWindowShouldClose(main_window, True) + glfw.set_window_should_close(main_window, True) self.notify_all({"subject": "clear_settings_process.should_start"}) self.notify_all({"subject": "service_process.should_start", "delay": 2.0}) @@ -169,13 +169,15 @@ def reset_restart(): gl_utils.legacy_glfw_set_framebuffer_size_callback(main_window, on_resize) gl_utils.legacy_glfw_set_key_callback(main_window, on_window_key) gl_utils.legacy_glfw_set_char_callback(main_window, on_window_char) - gl_utils.legacy_glfw_set_mouse_button_callback(main_window, on_window_mouse_button) + gl_utils.legacy_glfw_set_mouse_button_callback( + main_window, on_window_mouse_button + ) gl_utils.legacy_glfw_set_cursor_pos_callback(main_window, on_pos) gl_utils.legacy_glfw_set_scroll_callback(main_window, on_scroll) g_pool.gui.configuration = ui_config gl_utils.basic_gl_setup() - on_resize(g_pool.main_window, *glfw.GLFW.glfwGetFramebufferSize(main_window)) + on_resize(g_pool.main_window, *glfw.get_framebuffer_size(main_window)) def on_notify(self, notification): if notification["subject"] == "service_process.ui.should_update": @@ -185,25 +187,23 @@ def on_notify(self, notification): self.update_ui() def update_ui(self): - if not glfw.GLFW.glfwWindowShouldClose(self.g_pool.main_window): + if not glfw.window_should_close(self.g_pool.main_window): gl_utils.glViewport(0, 0, *self.window_size) - glfw.GLFW.glfwPollEvents() + glfw.poll_events() self.gl_display() try: - clipboard = glfw.GLFW.glfwGetClipboardString( - self.g_pool.main_window - ).decode() + clipboard = glfw.get_clipboard_string(self.g_pool.main_window).decode() except AttributeError: # clipbaord is None, might happen on startup clipboard = "" self.g_pool.gui.update_clipboard(clipboard) user_input = self.g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.GLFW.glfwSetClipboardString( + glfw.set_clipboard_string( self.g_pool.main_window, user_input.clipboard.encode() ) - glfw.GLFW.glfwSwapBuffers(self.g_pool.main_window) + glfw.swap_buffers(self.g_pool.main_window) else: self.notify_all({"subject": "service_process.should_stop"}) @@ -216,14 +216,14 @@ def gl_display(self): def cleanup(self): if not self.g_pool.hide_ui: - glfw.GLFW.glfwRestoreWindow(self.g_pool.main_window) + glfw.restore_window(self.g_pool.main_window) del self.g_pool.menubar[:] self.g_pool.gui.remove(self.g_pool.menubar) self.g_pool.gui.terminate() gl_utils.legacy_glfw_destroy_window(self.g_pool.main_window) - glfw.GLFW.glfwTerminate() + glfw.terminate() del self.g_pool.gui del self.g_pool.main_window @@ -231,11 +231,11 @@ def cleanup(self): def get_init_dict(self): sess = { - "window_position": glfw.GLFW.glfwGetWindowPos(self.g_pool.main_window), + "window_position": glfw.get_window_pos(self.g_pool.main_window), "ui_config": self.g_pool.gui.configuration, } - session_window_size = glfw.GLFW.glfwGetWindowSize(self.g_pool.main_window) + session_window_size = glfw.get_window_size(self.g_pool.main_window) if 0 not in session_window_size: f_width, f_height = session_window_size if platform.system() in ("Windows", "Linux"): diff --git a/pupil_src/shared_modules/surface_tracker/gui.py b/pupil_src/shared_modules/surface_tracker/gui.py index a464f0ada3..c51abf69b5 100644 --- a/pupil_src/shared_modules/surface_tracker/gui.py +++ b/pupil_src/shared_modules/surface_tracker/gui.py @@ -401,7 +401,7 @@ def on_click(self, pos, button, action): return def _on_click_menu_buttons(self, action, pos): - if action == glfw.GLFW.GLFW_PRESS: + if action == glfw.PRESS: for surface in reversed(self.tracker.surfaces): if not surface.detected: @@ -439,17 +439,11 @@ def _on_click_corner_handles(self, action, pos): ) for idx, corner in enumerate(img_corners): dist = np.linalg.norm(corner - pos) - if ( - action == glfw.GLFW.GLFW_PRESS - and dist < self.button_click_radius - ): + if action == glfw.PRESS and dist < self.button_click_radius: self.tracker._edit_surf_verts.append((surface, idx)) # click event consumed; give a chance for other surfaces' corners to react to it was_event_consumed = True - elif ( - action == glfw.GLFW.GLFW_RELEASE - and self.tracker._edit_surf_verts - ): + elif action == glfw.RELEASE and self.tracker._edit_surf_verts: self.tracker.notify_all( { "subject": "surface_tracker.surfaces_changed", @@ -463,7 +457,7 @@ def _on_click_corner_handles(self, action, pos): return was_event_consumed def _on_click_marker_toggles(self, action, pos): - if action == glfw.GLFW.GLFW_PRESS: + if action == glfw.PRESS: for surface in self._edit_surf_markers: if not surface.detected: continue @@ -570,10 +564,10 @@ def open_window(self): win_w, "Reference Surface: " + self.surface.name, monitor=monitor, - share=glfw.GLFW.glfwGetCurrentContext(), + share=glfw.get_current_context(), ) - glfw.GLFW.glfwSetWindowPos( + glfw.set_window_pos( self._window, self.window_position_default[0], self.window_position_default[1], @@ -583,7 +577,9 @@ def open_window(self): self.input = {"down": False, "mouse": (0, 0)} # Register callbacks - gl_utils.legacy_glfw_set_framebuffer_size_callback(self._window, self.on_resize) + gl_utils.legacy_glfw_set_framebuffer_size_callback( + self._window, self.on_resize + ) gl_utils.legacy_glfw_set_key_callback(self._window, self.on_window_key) gl_utils.legacy_glfw_set_window_close_callback(self._window, self.on_close) gl_utils.legacy_glfw_set_mouse_button_callback( @@ -592,20 +588,18 @@ def open_window(self): gl_utils.legacy_glfw_set_cursor_pos_callback(self._window, self.on_pos) gl_utils.legacy_glfw_set_scroll_callback(self._window, self.on_scroll) - self.on_resize( - self._window, *glfw.GLFW.glfwGetFramebufferSize(self._window) - ) + self.on_resize(self._window, *glfw.get_framebuffer_size(self._window)) # gl_state settings - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(self._window) + active_window = glfw.get_current_context() + glfw.make_context_current(self._window) gl_utils.basic_gl_setup() gl_utils.make_coord_system_norm_based() # refresh speed settings - glfw.GLFW.glfwSwapInterval(0) + glfw.swap_interval(0) - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.make_context_current(active_window) def close_window(self): if self._window: @@ -621,8 +615,8 @@ def gl_display_in_window(self, world_tex): here we map a selected surface onto a separate window. """ if self._window and self.surface.detected: - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(self._window) + active_window = glfw.get_current_context() + glfw.make_context_current(self._window) gl_utils.clear_gl_screen() # cv uses 3x3 gl uses 4x4 transformation matrices @@ -654,8 +648,8 @@ def gl_display_in_window(self, world_tex): self.draw_recent_pupil_positions() - glfw.GLFW.glfwSwapBuffers(self._window) - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.swap_buffers(self._window) + glfw.make_context_current(active_window) def draw_recent_pupil_positions(self): try: @@ -673,24 +667,24 @@ def draw_recent_pupil_positions(self): def on_resize(self, window, w, h): self.trackball.set_window_size(w, h) - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(window) + active_window = glfw.get_current_context() + glfw.make_context_current(window) gl_utils.adjust_gl_view(w, h) - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.make_context_current(active_window) def on_window_key(self, window, key, scancode, action, mods): - if action == glfw.GLFW.GLFW_PRESS: - if key == glfw.GLFW.GLFW_KEY_ESCAPE: + if action == glfw.PRESS: + if key == glfw.KEY_ESCAPE: self.on_close() def on_close(self, window=None): self.close_window() def on_window_mouse_button(self, window, button, action, mods): - if action == glfw.GLFW.GLFW_PRESS: + if action == glfw.PRESS: self.input["down"] = True - self.input["mouse"] = glfw.GLFW.glfwGetCursorPos(window) - if action == glfw.GLFW.GLFW_RELEASE: + self.input["mouse"] = glfw.get_cursor_pos(window) + if action == glfw.RELEASE: self.input["down"] = False def on_pos(self, window, x, y): diff --git a/pupil_src/shared_modules/system_graphs.py b/pupil_src/shared_modules/system_graphs.py index ace0115d02..375402a009 100644 --- a/pupil_src/shared_modules/system_graphs.py +++ b/pupil_src/shared_modules/system_graphs.py @@ -74,7 +74,7 @@ def init_ui(self): self.on_window_resize(self.g_pool.main_window) def on_window_resize(self, window, *args): - fb_size = glfw.GLFW.glfwGetFramebufferSize(window) + fb_size = glfw.get_framebuffer_size(window) content_scale = gl_utils.get_content_scale(window) self.cpu_graph.scale = content_scale diff --git a/pupil_src/shared_modules/video_overlay/ui/interactions.py b/pupil_src/shared_modules/video_overlay/ui/interactions.py index e8fef69007..867c27b0d4 100644 --- a/pupil_src/shared_modules/video_overlay/ui/interactions.py +++ b/pupil_src/shared_modules/video_overlay/ui/interactions.py @@ -26,7 +26,7 @@ def on_click(self, pos, button, action): if not self.overlay.valid_video_loaded: return False # click event has not been consumed - click_engaged = action == glfw.GLFW.GLFW_PRESS + click_engaged = action == glfw.PRESS if click_engaged and self._in_bounds(pos): self.drag_offset = self._calculate_offset(pos) return True @@ -63,7 +63,7 @@ def _effective_overlay_frame_size(self): def current_mouse_pos(window, camera_render_size, frame_size): content_scale = gl_utils.get_content_scale(window) - x, y = glfw.GLFW.glfwGetCursorPos(glfw.GLFW.glfwGetCurrentContext()) + x, y = glfw.get_cursor_pos(glfw.get_current_context()) pos = x * content_scale, y * content_scale pos = normalize(pos, camera_render_size) # Position in img pixels diff --git a/pupil_src/shared_modules/vis_watermark.py b/pupil_src/shared_modules/vis_watermark.py index 3f5be16891..e8d3da673c 100644 --- a/pupil_src/shared_modules/vis_watermark.py +++ b/pupil_src/shared_modules/vis_watermark.py @@ -81,10 +81,8 @@ def recent_events(self, events): if not frame: return if self.drag_offset is not None: - pos = glfw.GLFW.glfwGetCursorPos(glfw.GLFW.glfwGetCurrentContext()) - pos = normalize( - pos, glfw.GLFW.glfwGetWindowSize(glfw.GLFW.glfwGetCurrentContext()) - ) + pos = glfw.get_cursor_pos(glfw.get_current_context()) + pos = normalize(pos, glfw.get_window_size(glfw.get_current_context())) pos = denormalize( pos, (frame.img.shape[1], frame.img.shape[0]) ) # Position in img pixels diff --git a/pupil_src/shared_modules/visualizer.py b/pupil_src/shared_modules/visualizer.py index df4b285602..024d40dc2a 100644 --- a/pupil_src/shared_modules/visualizer.py +++ b/pupil_src/shared_modules/visualizer.py @@ -49,21 +49,21 @@ def __init__(self, g_pool, name="Visualizer", run_independently=False): def begin_update_window(self): if self.window: - if glfw.GLFW.glfwWindowShouldClose(self.window): + if glfw.window_should_close(self.window): self.close_window() return - self.other_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(self.window) + self.other_window = glfw.get_current_context() + glfw.make_context_current(self.window) def update_window(self): pass def end_update_window(self): if self.window: - glfw.GLFW.glfwSwapBuffers(self.window) - glfw.GLFW.glfwPollEvents() - glfw.GLFW.glfwMakeContextCurrent(self.other_window) + glfw.swap_buffers(self.window) + glfw.poll_events() + glfw.make_context_current(self.other_window) ############## DRAWING FUNCTIONS ############################## @@ -167,9 +167,7 @@ def open_window(self): # get glfw started if self.run_independently: gl_utils.legacy_glfw_init() - glfw.GLFW.glfwWindowHint( - glfw.GLFW.GLFW_SCALE_TO_MONITOR, glfw.GLFW.GLFW_TRUE - ) + glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) self.window = gl_utils.legacy_glfw_create_window( self.window_size[0], self.window_size[1], self.name, None ) @@ -179,14 +177,14 @@ def open_window(self): self.window_size[1], self.name, None, - share=glfw.GLFW.glfwGetCurrentContext(), + share=glfw.get_current_context(), ) - self.other_window = glfw.GLFW.glfwGetCurrentContext() + self.other_window = glfw.get_current_context() - glfw.GLFW.glfwMakeContextCurrent(self.window) - glfw.GLFW.glfwSwapInterval(0) - glfw.GLFW.glfwSetWindowPos( + glfw.make_context_current(self.window) + glfw.swap_interval(0) + glfw.set_window_pos( self.window, window_position_default[0], window_position_default[1] ) # Register callbacks window @@ -215,8 +213,8 @@ def open_window(self): self.glfont.add_font("opensans", get_opensans_font_path()) self.glfont.set_size(18) self.glfont.set_color_float((0.2, 0.5, 0.9, 1.0)) - self.on_resize(self.window, *glfw.GLFW.glfwGetFramebufferSize(self.window)) - glfw.GLFW.glfwMakeContextCurrent(self.other_window) + self.on_resize(self.window, *glfw.get_framebuffer_size(self.window)) + glfw.make_context_current(self.other_window) ############ window callbacks ################# def on_resize(self, window, w, h): @@ -224,17 +222,17 @@ def on_resize(self, window, w, h): w = max(w, 1) self.window_size = (w, h) - active_window = glfw.GLFW.glfwGetCurrentContext() - glfw.GLFW.glfwMakeContextCurrent(window) + active_window = glfw.get_current_context() + glfw.make_context_current(window) self.adjust_gl_view(w, h) - glfw.GLFW.glfwMakeContextCurrent(active_window) + glfw.make_context_current(active_window) def on_window_mouse_button(self, window, button, action, mods): # self.gui.update_button(button,action,mods) - if action == glfw.GLFW.GLFW_PRESS: + if action == glfw.PRESS: self.input["button"] = button - self.input["mouse"] = glfw.GLFW.glfwGetCursorPos(window) - if action == glfw.GLFW.GLFW_RELEASE: + self.input["mouse"] = glfw.get_cursor_pos(window) + if action == glfw.RELEASE: self.input["button"] = None def on_pos(self, window, x, y): @@ -242,11 +240,11 @@ def on_pos(self, window, x, y): window, x, y, cached_scale=None ) # self.gui.update_mouse(x,y) - if self.input["button"] == glfw.GLFW.GLFW_MOUSE_BUTTON_RIGHT: + if self.input["button"] == glfw.MOUSE_BUTTON_RIGHT: old_x, old_y = self.input["mouse"] self.trackball.drag_to(x - old_x, y - old_y) self.input["mouse"] = x, y - if self.input["button"] == glfw.GLFW.GLFW_MOUSE_BUTTON_LEFT: + if self.input["button"] == glfw.MOUSE_BUTTON_LEFT: old_x, old_y = self.input["mouse"] self.trackball.pan_to(x - old_x, y - old_y) self.input["mouse"] = x, y From 1454585fb4ff61a76d73ae8d8529f9f5933c761b Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 29 Sep 2020 03:01:07 +0200 Subject: [PATCH 10/57] Replace legacy glfw calls with regular function calls --- pupil_src/launchables/eye.py | 28 +- pupil_src/launchables/player.py | 32 +-- pupil_src/launchables/world.py | 24 +- .../controller/gui_monitor.py | 11 +- .../controller/gui_window.py | 18 +- .../camera_intrinsics_estimation.py | 22 +- pupil_src/shared_modules/gl_utils/__init__.py | 20 -- .../shared_modules/gl_utils/glfw_legacy.py | 239 ------------------ .../head_pose_tracker/ui/gl_window.py | 33 ++- pupil_src/shared_modules/service_ui.py | 20 +- .../shared_modules/surface_tracker/gui.py | 24 +- pupil_src/shared_modules/visualizer.py | 32 +-- 12 files changed, 110 insertions(+), 393 deletions(-) delete mode 100644 pupil_src/shared_modules/gl_utils/glfw_legacy.py diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index 80e090c360..0a048a0be7 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -404,7 +404,7 @@ def toggle_general_settings(collapsed): general_settings.collapsed = collapsed # Initialize glfw - gl_utils.legacy_glfw_init() + glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) if hide_ui: glfw.window_hint(glfw.VISIBLE, 0) # hide window @@ -417,9 +417,7 @@ def toggle_general_settings(collapsed): default_window_size = 500 + icon_bar_width, 500 width, height = session_settings.get("window_size", default_window_size) - main_window = gl_utils.legacy_glfw_create_window( - width, height, title, None, None - ) + main_window = glfw.create_window(width, height, title, None, None) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( @@ -526,16 +524,14 @@ def set_window_size(): g_pool.rec_path = None # Register callbacks main_window - gl_utils.legacy_glfw_set_framebuffer_size_callback(main_window, on_resize) - gl_utils.legacy_glfw_set_window_iconify_callback(main_window, on_iconify) - gl_utils.legacy_glfw_set_key_callback(main_window, on_window_key) - gl_utils.legacy_glfw_set_char_callback(main_window, on_window_char) - gl_utils.legacy_glfw_set_mouse_button_callback( - main_window, on_window_mouse_button - ) - gl_utils.legacy_glfw_set_cursor_pos_callback(main_window, on_pos) - gl_utils.legacy_glfw_set_scroll_callback(main_window, on_scroll) - gl_utils.legacy_glfw_set_drop_callback(main_window, on_drop) + glfw.set_framebuffer_size_callback(main_window, on_resize) + glfw.set_window_iconify_callback(main_window, on_iconify) + glfw.set_key_callback(main_window, on_window_key) + glfw.set_char_callback(main_window, on_window_char) + glfw.set_mouse_button_callback(main_window, on_window_mouse_button) + glfw.set_cursor_pos_callback(main_window, on_pos) + glfw.set_scroll_callback(main_window, on_scroll) + glfw.set_drop_callback(main_window, on_drop) # load last gui configuration g_pool.gui.configuration = session_settings.get("ui_config", {}) @@ -758,9 +754,9 @@ def window_should_update(): plugin.alive = False g_pool.plugins.clean() - gl_utils.legacy_glfw_destroy_window(main_window) + glfw.destroy_window(main_window) g_pool.gui.terminate() - glfw.GLFW.glfwTerminate() + glfw.terminate() logger.info("Process shutting down.") diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index 77a22a734b..ba7f4ade4b 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -363,11 +363,9 @@ def get_dt(): window_name = f"Pupil Player: {meta_info.recording_name} - {rec_dir}" - gl_utils.legacy_glfw_init() + glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) - main_window = gl_utils.legacy_glfw_create_window( - width, height, window_name, None, None - ) + main_window = glfw.create_window(width, height, window_name, None, None) window_position_manager = gl_utils.WindowPositionManager() window_pos = window_position_manager.new_window_position( @@ -610,15 +608,13 @@ def set_window_size(): ) # Register callbacks main_window - gl_utils.legacy_glfw_set_framebuffer_size_callback(main_window, on_resize) - gl_utils.legacy_glfw_set_key_callback(main_window, on_window_key) - gl_utils.legacy_glfw_set_char_callback(main_window, on_window_char) - gl_utils.legacy_glfw_set_mouse_button_callback( - main_window, on_window_mouse_button - ) - gl_utils.legacy_glfw_set_cursor_pos_callback(main_window, on_pos) - gl_utils.legacy_glfw_set_scroll_callback(main_window, on_scroll) - gl_utils.legacy_glfw_set_drop_callback(main_window, on_drop) + glfw.set_framebuffer_size_callback(main_window, on_resize) + glfw.set_key_callback(main_window, on_window_key) + glfw.set_char_callback(main_window, on_window_char) + glfw.set_mouse_button_callback(main_window, on_window_mouse_button) + glfw.set_cursor_pos_callback(main_window, on_pos) + glfw.set_scroll_callback(main_window, on_scroll) + glfw.set_drop_callback(main_window, on_drop) toggle_general_settings(True) @@ -766,7 +762,7 @@ def handle_notifications(n): g_pool.plugins.clean() g_pool.gui.terminate() - gl_utils.legacy_glfw_destroy_window(main_window) + glfw.destroy_window(main_window) except Exception: import traceback @@ -852,10 +848,10 @@ def on_drop(window, count, paths): session_settings.clear() w, h = session_settings.get("window_size", (1280, 720)) - gl_utils.legacy_glfw_init() + glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) glfw.window_hint(glfw.RESIZABLE, 0) - window = gl_utils.legacy_glfw_create_window(w, h, "Pupil Player") + window = glfw.create_window(w, h, "Pupil Player", None, None) glfw.window_hint(glfw.RESIZABLE, 1) glfw.make_context_current(window) @@ -868,7 +864,7 @@ def on_drop(window, count, paths): ) glfw.set_window_pos(window, window_pos[0], window_pos[1]) - gl_utils.legacy_glfw_set_drop_callback(window, on_drop) + glfw.set_drop_callback(window, on_drop) glfont = fontstash.Context() glfont.add_font("roboto", get_roboto_font_path()) @@ -949,7 +945,7 @@ def display_string(string, font_size, center_y): session_settings["window_position"] = glfw.get_window_pos(window) session_settings.close() - gl_utils.legacy_glfw_destroy_window(window) + glfw.destroy_window(window) if rec_dir: ipc_pub.notify( {"subject": "player_process.should_start", "rec_dir": rec_dir} diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index 0f2ce31ac6..e007472fa2 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -514,12 +514,12 @@ def handle_notifications(noti): ) # window and gl setup - gl_utils.legacy_glfw_init() + glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) if hide_ui: glfw.window_hint(glfw.VISIBLE, 0) # hide window - main_window = gl_utils.legacy_glfw_create_window( - width, height, "Pupil Capture - World" + main_window = glfw.create_window( + width, height, "Pupil Capture - World", None, None ) window_position_manager = gl_utils.WindowPositionManager() @@ -662,15 +662,13 @@ def set_window_size(): ) # Register callbacks main_window - gl_utils.legacy_glfw_set_framebuffer_size_callback(main_window, on_resize) - gl_utils.legacy_glfw_set_key_callback(main_window, on_window_key) - gl_utils.legacy_glfw_set_char_callback(main_window, on_window_char) - gl_utils.legacy_glfw_set_mouse_button_callback( - main_window, on_window_mouse_button - ) - gl_utils.legacy_glfw_set_cursor_pos_callback(main_window, on_pos) - gl_utils.legacy_glfw_set_scroll_callback(main_window, on_scroll) - gl_utils.legacy_glfw_set_drop_callback(main_window, on_drop) + glfw.set_framebuffer_size_callback(main_window, on_resize) + glfw.set_key_callback(main_window, on_window_key) + glfw.set_char_callback(main_window, on_window_char) + glfw.set_mouse_button_callback(main_window, on_window_mouse_button) + glfw.set_cursor_pos_callback(main_window, on_pos) + glfw.set_scroll_callback(main_window, on_scroll) + glfw.set_drop_callback(main_window, on_drop) # gl_state settings gl_utils.basic_gl_setup() @@ -828,7 +826,7 @@ def window_should_update(): g_pool.plugins.clean() g_pool.gui.terminate() - gl_utils.legacy_glfw_destroy_window(main_window) + glfw.destroy_window(main_window) glfw.terminate() except Exception: diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py index aebf2edfc6..253f3b6c61 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py @@ -57,8 +57,15 @@ def refresh_rate(self) -> int: @property def current_video_mode(self) -> "GUIMonitor.VideoMode": - gl_video_mode = gl_utils.legacy_glfw_get_video_mode(self.__gl_handle) - return GUIMonitor.VideoMode(*gl_video_mode) + gl_video_mode = glfw.get_video_mode(self.__gl_handle) + return GUIMonitor.VideoMode( + width=gl_video_mode.width, + height=gl_video_mode.height, + red_bits=gl_video_mode.red_bits, + green_bits=gl_video_mode.green_bits, + blue_bits=gl_video_mode.blue_bits, + refresh_rate=gl_video_mode.refresh_rate, + ) @property def is_available(self) -> bool: diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py index a854e966f6..43b7911026 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py @@ -86,21 +86,17 @@ def open( # windows you might experience a black screen for up to 1 sec when creating # a blank window directly in fullscreen mode. By creating it windowed and # then switching to fullscreen it will stay white the entire time. - self.__gl_handle = gl_utils.legacy_glfw_create_window( - *size, title, share=glfw.get_current_context() + self.__gl_handle = glfw.create_window( + *size, title, None, glfw.get_current_context() ) if not is_fullscreen: glfw.set_window_pos(self.__gl_handle, *position) # Register callbacks - gl_utils.legacy_glfw_set_framebuffer_size_callback( - self.__gl_handle, self.on_resize - ) - gl_utils.legacy_glfw_set_key_callback(self.__gl_handle, self.on_key) - gl_utils.legacy_glfw_set_mouse_button_callback( - self.__gl_handle, self.on_mouse_button - ) + glfw.set_framebuffer_size_callback(self.__gl_handle, self.on_resize) + glfw.set_key_callback(self.__gl_handle, self.on_key) + glfw.set_mouse_button_callback(self.__gl_handle, self.on_mouse_button) self.on_resize(self.__gl_handle, *glfw.get_framebuffer_size(self.__gl_handle)) # gl_state settings @@ -109,7 +105,7 @@ def open( glfw.swap_interval(0) if is_fullscreen: - # Switch to full screen here. See NOTE above at legacy_glfw_create_window(). + # Switch to full screen here. See NOTE above at glfw.create_window(). glfw.set_window_monitor( self.__gl_handle, gui_monitor.unsafe_handle, @@ -124,7 +120,7 @@ def close(self): return with self._switch_to_current_context(): glfw.set_input_mode(self.__gl_handle, glfw.CURSOR, glfw.CURSOR_NORMAL) - gl_utils.legacy_glfw_destroy_window(self.__gl_handle) + glfw.destroy_window(self.__gl_handle) self.__gl_handle = None @contextlib.contextmanager diff --git a/pupil_src/shared_modules/camera_intrinsics_estimation.py b/pupil_src/shared_modules/camera_intrinsics_estimation.py index e73ac69902..22d7861f73 100644 --- a/pupil_src/shared_modules/camera_intrinsics_estimation.py +++ b/pupil_src/shared_modules/camera_intrinsics_estimation.py @@ -190,30 +190,28 @@ def open_window(self): ) self.monitor_idx = 0 monitor = glfw.get_monitors()[self.monitor_idx] - mode = gl_utils.legacy_glfw_get_video_mode(monitor) - height, width = mode[0], mode[1] + mode = glfw.get_video_mode(monitor) + height, width = mode.height, mode.width else: monitor = None height, width = 640, 480 - self._window = gl_utils.legacy_glfw_create_window( + self._window = glfw.create_window( height, width, "Calibration", - monitor=monitor, - share=glfw.get_current_context(), + monitor, + glfw.get_current_context(), ) if not self.fullscreen: # move to y = 31 for windows os glfw.set_window_pos(self._window, 200, 31) # Register callbacks - gl_utils.legacy_glfw_set_framebuffer_size_callback(self._window, on_resize) - gl_utils.legacy_glfw_set_key_callback(self._window, self.on_window_key) - gl_utils.legacy_glfw_set_window_close_callback(self._window, self.on_close) - gl_utils.legacy_glfw_set_mouse_button_callback( - self._window, self.on_window_mouse_button - ) + glfw.set_framebuffer_size_callback(self._window, on_resize) + glfw.set_key_callback(self._window, self.on_window_key) + glfw.set_window_close_callback(self._window, self.on_close) + glfw.set_mouse_button_callback(self._window, self.on_window_mouse_button) on_resize(self._window, *glfw.get_framebuffer_size(self._window)) @@ -242,7 +240,7 @@ def on_close(self, window=None): def close_window(self): self.window_should_close = False if self._window: - gl_utils.legacy_glfw_destroy_window(self._window) + glfw.destroy_window(self._window) self._window = None def calculate(self): diff --git a/pupil_src/shared_modules/gl_utils/__init__.py b/pupil_src/shared_modules/gl_utils/__init__.py index a58c93ba8f..6473d08d3e 100644 --- a/pupil_src/shared_modules/gl_utils/__init__.py +++ b/pupil_src/shared_modules/gl_utils/__init__.py @@ -12,23 +12,3 @@ from .utils import * from .trackball import * from .window_position_manager import WindowPositionManager - -# TODO: Remove calls to legacy functions -from .glfw_legacy import ( - legacy_glfw_get_video_mode, - legacy_glfw_get_error, - legacy_glfw_init, - legacy_glfw_create_window, - legacy_glfw_destroy_window, - legacy_glfw_set_window_pos_callback, - legacy_glfw_set_window_size_callback, - legacy_glfw_set_window_close_callback, - legacy_glfw_set_window_iconify_callback, - legacy_glfw_set_framebuffer_size_callback, - legacy_glfw_set_key_callback, - legacy_glfw_set_char_callback, - legacy_glfw_set_mouse_button_callback, - legacy_glfw_set_cursor_pos_callback, - legacy_glfw_set_scroll_callback, - legacy_glfw_set_drop_callback -) diff --git a/pupil_src/shared_modules/gl_utils/glfw_legacy.py b/pupil_src/shared_modules/gl_utils/glfw_legacy.py deleted file mode 100644 index 5e7c19c0ad..0000000000 --- a/pupil_src/shared_modules/gl_utils/glfw_legacy.py +++ /dev/null @@ -1,239 +0,0 @@ -import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API -import logging - - -logger = logging.getLogger(__name__) - - -__windows__ = [] -__c_callbacks__ = {} -__py_callbacks__ = {} - - -def legacy_glfw_get_video_mode(monitor): - mode_struct = glfw.get_video_mode(monitor) - return ( - mode_struct.width, - mode_struct.height, - mode_struct.red_bits, - mode_struct.blue_bits, - mode_struct.green_bits, - mode_struct.refresh_rate, - ) - - -def legacy_glfw_get_error(): - code, msg = glfw.get_error() - if code: - return msg.value.decode() - - -def legacy_glfw_init(): - res = glfw.init() - if res < 0: - raise Exception(f"GLFW could not be initialized: {legacy_glfw_get_error()}") - - -def legacy_glfw_create_window( - width=640, height=480, title="GLFW Window", monitor=None, share=None -): - - window = glfw.create_window(width, height, title, monitor, share) - - if window: - __windows__.append(window) - index = __windows__.index(window) - __c_callbacks__[index] = {} - __py_callbacks__[index] = { - "window_pos_fun": None, - "window_size_fun": None, - "window_close_fun": None, - "window_iconify_fun": None, - "framebuffer_size_fun": None, - "key_fun": None, - "char_fun": None, - "mouse_button_fun": None, - "cursor_pos_fun": None, - "scroll_fun": None, - "drop_fun": None, - } - return window - else: - raise Exception(f"GLFW window failed to create: {legacy_glfw_get_error()}") - - -def legacy_glfw_destroy_window(window): - index = __windows__.index(window) - try: - __c_callbacks__[index] - except KeyError: - logger.error("Window already destroyed.") - else: - glfw.destroy_window(window) - # We do not delete window from the list (or it would impact windows numbering) - # del __windows__[index] - del __c_callbacks__[index] - del __py_callbacks__[index] - - -### CALLBACKS - -import ctypes - - -def __set_window_callback( - window, callback, key: str, c_func_type, glfw_callback_setter -): - index = __windows__.index(window) - old_callback = __py_callbacks__[index][key] - __py_callbacks__[index][key] = callback - - if callback: - callback = c_func_type(callback) - - __c_callbacks__[index][key] = callback - glfw_callback_setter(window, callback) - return old_callback - - -def legacy_glfw_set_window_pos_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="window_pos_fun", - c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int - ), - glfw_callback_setter=glfw.set_window_posCallback, - ) - - -def legacy_glfw_set_window_size_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="window_size_fun", - c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int - ), - glfw_callback_setter=glfw.set_window_sizeCallback, - ) - - -def legacy_glfw_set_window_close_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="window_close_fun", - c_func_type=ctypes.CFUNCTYPE(None, ctypes.POINTER(glfw._GLFWwindow)), - glfw_callback_setter=glfw.set_window_close_callback, - ) - - -def legacy_glfw_set_window_iconify_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="window_iconify_fun", - c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int - ), - glfw_callback_setter=glfw.set_window_iconify_callback, - ) - - -def legacy_glfw_set_framebuffer_size_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="framebuffer_size_fun", - c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int, ctypes.c_int - ), - glfw_callback_setter=glfw.set_framebuffer_size_callback, - ) - - -def legacy_glfw_set_key_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="key_fun", - c_func_type=ctypes.CFUNCTYPE( - None, - ctypes.POINTER(glfw._GLFWwindow), - ctypes.c_int, - ctypes.c_int, - ctypes.c_int, - ctypes.c_int, - ), - glfw_callback_setter=glfw.set_key_callback, - ) - - -def legacy_glfw_set_char_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="char_fun", - c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_int - ), - glfw_callback_setter=glfw.set_char_callback, - ) - - -def legacy_glfw_set_mouse_button_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="mouse_button_fun", - c_func_type=ctypes.CFUNCTYPE( - None, - ctypes.POINTER(glfw._GLFWwindow), - ctypes.c_int, - ctypes.c_int, - ctypes.c_int, - ), - glfw_callback_setter=glfw.set_mouse_button_callback, - ) - - -def legacy_glfw_set_cursor_pos_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="cursor_pos_fun", - c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_double, ctypes.c_double - ), - glfw_callback_setter=glfw.set_cursor_pos_callback, - ) - - -def legacy_glfw_set_scroll_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="scroll_fun", - c_func_type=ctypes.CFUNCTYPE( - None, ctypes.POINTER(glfw._GLFWwindow), ctypes.c_double, ctypes.c_double - ), - glfw_callback_setter=glfw.set_scroll_callback, - ) - - -def legacy_glfw_set_drop_callback(window, callback=None): - __set_window_callback( - window=window, - callback=callback, - key="drop_fun", - c_func_type=ctypes.CFUNCTYPE( - None, - ctypes.POINTER(glfw._GLFWwindow), - ctypes.c_int, - ctypes.POINTER(ctypes.c_char_p), - ), - glfw_callback_setter=glfw.set_drop_callback, - ) diff --git a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py index f33ea48f55..6000a53726 100644 --- a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py +++ b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py @@ -62,11 +62,14 @@ def _init_trackball(): return trackball def _glfw_init(self): - gl_utils.legacy_glfw_init() + glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) - window = gl_utils.legacy_glfw_create_window( - title="Head Pose Tracker Visualizer", - share=glfw.get_current_context(), + window = glfw.create_window( + 640, + 480, + "Head Pose Tracker Visualizer", + None, + glfw.get_current_context(), ) return window @@ -80,19 +83,13 @@ def _gl_state_settings(window): glfw.make_context_current(active_window) def _register_callbacks(self, window): - gl_utils.legacy_glfw_set_window_size_callback(window, self._on_set_window_size) - gl_utils.legacy_glfw_set_window_pos_callback(window, self._on_set_window_pos) - gl_utils.legacy_glfw_set_framebuffer_size_callback( - window, self._on_set_frame_buffer_size - ) - gl_utils.legacy_glfw_set_mouse_button_callback( - window, self._on_set_mouse_button - ) - gl_utils.legacy_glfw_set_cursor_pos_callback(window, self._on_set_cursor_pos) - gl_utils.legacy_glfw_set_scroll_callback(window, self._on_set_scroll) - gl_utils.legacy_glfw_set_window_close_callback( - window, self._on_set_window_close - ) + glfw.set_window_size_callback(window, self._on_set_window_size) + glfw.set_window_pos_callback(window, self._on_set_window_pos) + glfw.set_framebuffer_size_callback(window, self._on_set_frame_buffer_size) + glfw.set_mouse_button_callback(window, self._on_set_mouse_button) + glfw.set_cursor_pos_callback(window, self._on_set_cursor_pos) + glfw.set_scroll_callback(window, self._on_set_scroll) + glfw.set_window_close_callback(window, self._on_set_window_close) def _set_initial_window_state(self): glfw.set_window_pos(self._window, *self._general_settings.window_position) @@ -140,7 +137,7 @@ def _close(self): self._glfw_deinit(self._window) def _glfw_deinit(self, window): - gl_utils.legacy_glfw_destroy_window(window) + glfw.destroy_window(window) self._window = None def _on_gl_display(self): diff --git a/pupil_src/shared_modules/service_ui.py b/pupil_src/shared_modules/service_ui.py index 3724b9c2ac..a506693ba9 100644 --- a/pupil_src/shared_modules/service_ui.py +++ b/pupil_src/shared_modules/service_ui.py @@ -49,11 +49,11 @@ def __init__( self.texture = np.zeros((1, 1, 3), dtype=np.uint8) + 128 - gl_utils.legacy_glfw_init() + glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) if g_pool.hide_ui: glfw.window_hint(glfw.VISIBLE, 0) # hide window - main_window = gl_utils.legacy_glfw_create_window(*window_size, "Pupil Service") + main_window = glfw.create_window(*window_size, "Pupil Service", None, None) window_position_manager = gl_utils.WindowPositionManager() window_position = window_position_manager.new_window_position( @@ -166,14 +166,12 @@ def reset_restart(): g_pool.menubar.append(ui.Button("Restart with default settings", reset_restart)) # Register callbacks main_window - gl_utils.legacy_glfw_set_framebuffer_size_callback(main_window, on_resize) - gl_utils.legacy_glfw_set_key_callback(main_window, on_window_key) - gl_utils.legacy_glfw_set_char_callback(main_window, on_window_char) - gl_utils.legacy_glfw_set_mouse_button_callback( - main_window, on_window_mouse_button - ) - gl_utils.legacy_glfw_set_cursor_pos_callback(main_window, on_pos) - gl_utils.legacy_glfw_set_scroll_callback(main_window, on_scroll) + glfw.set_framebuffer_size_callback(main_window, on_resize) + glfw.set_key_callback(main_window, on_window_key) + glfw.set_char_callback(main_window, on_window_char) + glfw.set_mouse_button_callback(main_window, on_window_mouse_button) + glfw.set_cursor_pos_callback(main_window, on_pos) + glfw.set_scroll_callback(main_window, on_scroll) g_pool.gui.configuration = ui_config gl_utils.basic_gl_setup() @@ -222,7 +220,7 @@ def cleanup(self): self.g_pool.gui.remove(self.g_pool.menubar) self.g_pool.gui.terminate() - gl_utils.legacy_glfw_destroy_window(self.g_pool.main_window) + glfw.destroy_window(self.g_pool.main_window) glfw.terminate() del self.g_pool.gui diff --git a/pupil_src/shared_modules/surface_tracker/gui.py b/pupil_src/shared_modules/surface_tracker/gui.py index c51abf69b5..6353d51c62 100644 --- a/pupil_src/shared_modules/surface_tracker/gui.py +++ b/pupil_src/shared_modules/surface_tracker/gui.py @@ -559,12 +559,12 @@ def open_window(self): win_h = 640 win_w = int(win_h / surface_aspect_ratio) - self._window = gl_utils.legacy_glfw_create_window( + self._window = glfw.create_window( win_h, win_w, "Reference Surface: " + self.surface.name, - monitor=monitor, - share=glfw.get_current_context(), + monitor, + glfw.get_current_context(), ) glfw.set_window_pos( @@ -577,16 +577,12 @@ def open_window(self): self.input = {"down": False, "mouse": (0, 0)} # Register callbacks - gl_utils.legacy_glfw_set_framebuffer_size_callback( - self._window, self.on_resize - ) - gl_utils.legacy_glfw_set_key_callback(self._window, self.on_window_key) - gl_utils.legacy_glfw_set_window_close_callback(self._window, self.on_close) - gl_utils.legacy_glfw_set_mouse_button_callback( - self._window, self.on_window_mouse_button - ) - gl_utils.legacy_glfw_set_cursor_pos_callback(self._window, self.on_pos) - gl_utils.legacy_glfw_set_scroll_callback(self._window, self.on_scroll) + glfw.set_framebuffer_size_callback(self._window, self.on_resize) + glfw.set_key_callback(self._window, self.on_window_key) + glfw.set_window_close_callback(self._window, self.on_close) + glfw.set_mouse_button_callback(self._window, self.on_window_mouse_button) + glfw.set_cursor_pos_callback(self._window, self.on_pos) + glfw.set_scroll_callback(self._window, self.on_scroll) self.on_resize(self._window, *glfw.get_framebuffer_size(self._window)) @@ -603,7 +599,7 @@ def open_window(self): def close_window(self): if self._window: - gl_utils.legacy_glfw_destroy_window(self._window) + glfw.destroy_window(self._window) self._window = None self.window_should_close = False diff --git a/pupil_src/shared_modules/visualizer.py b/pupil_src/shared_modules/visualizer.py index 024d40dc2a..cad7c23c77 100644 --- a/pupil_src/shared_modules/visualizer.py +++ b/pupil_src/shared_modules/visualizer.py @@ -157,7 +157,7 @@ def clear_gl_screen(self): def close_window(self): if self.window: - gl_utils.legacy_glfw_destroy_window(self.window) + glfw.destroy_window(self.window) self.window = None def open_window(self): @@ -166,18 +166,18 @@ def open_window(self): # get glfw started if self.run_independently: - gl_utils.legacy_glfw_init() + glfw.init() glfw.window_hint(glfw.SCALE_TO_MONITOR, glfw.TRUE) - self.window = gl_utils.legacy_glfw_create_window( - self.window_size[0], self.window_size[1], self.name, None + self.window = glfw.create_window( + self.window_size[0], self.window_size[1], self.name, None, None ) else: - self.window = gl_utils.legacy_glfw_create_window( + self.window = glfw.create_window( self.window_size[0], self.window_size[1], self.name, None, - share=glfw.get_current_context(), + glfw.get_current_context(), ) self.other_window = glfw.get_current_context() @@ -188,19 +188,13 @@ def open_window(self): self.window, window_position_default[0], window_position_default[1] ) # Register callbacks window - gl_utils.legacy_glfw_set_framebuffer_size_callback( - self.window, self.on_resize - ) - gl_utils.legacy_glfw_set_window_iconify_callback( - self.window, self.on_iconify - ) - gl_utils.legacy_glfw_set_key_callback(self.window, self.on_window_key) - gl_utils.legacy_glfw_set_char_callback(self.window, self.on_window_char) - gl_utils.legacy_glfw_set_mouse_button_callback( - self.window, self.on_window_mouse_button - ) - gl_utils.legacy_glfw_set_cursor_pos_callback(self.window, self.on_pos) - gl_utils.legacy_glfw_set_scroll_callback(self.window, self.on_scroll) + glfw.set_framebuffer_size_callback(self.window, self.on_resize) + glfw.set_window_iconify_callback(self.window, self.on_iconify) + glfw.set_key_callback(self.window, self.on_window_key) + glfw.set_char_callback(self.window, self.on_window_char) + glfw.set_mouse_button_callback(self.window, self.on_window_mouse_button) + glfw.set_cursor_pos_callback(self.window, self.on_pos) + glfw.set_scroll_callback(self.window, self.on_scroll) # get glfw started if self.run_independently: From 0c3b2dc5d672e8c67d482ff73321bd6428057398 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 29 Sep 2020 09:50:56 +0200 Subject: [PATCH 11/57] Remove unused glfw.GLFW imports --- pupil_src/launchables/eye.py | 1 - pupil_src/launchables/player.py | 2 -- pupil_src/launchables/world.py | 1 - .../calibration_choreography/controller/gui_monitor.py | 1 - .../calibration_choreography/controller/gui_window.py | 1 - .../calibration_choreography/natural_feature_plugin.py | 1 - .../calibration_choreography/screen_marker_plugin.py | 1 - .../calibration_choreography/single_marker_plugin.py | 1 - pupil_src/shared_modules/camera_intrinsics_estimation.py | 1 - .../gaze_producer/controller/reference_location_controllers.py | 1 - pupil_src/shared_modules/gl_utils/utils.py | 1 - pupil_src/shared_modules/gl_utils/window_position_manager.py | 1 - pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py | 1 - pupil_src/shared_modules/log_display.py | 1 - pupil_src/shared_modules/marker_auto_trim_marks.py | 1 - .../shared_modules/pupil_detector_plugins/detector_2d_plugin.py | 1 - pupil_src/shared_modules/roi.py | 1 - pupil_src/shared_modules/service_ui.py | 1 - pupil_src/shared_modules/surface_tracker/gui.py | 1 - pupil_src/shared_modules/system_graphs.py | 1 - pupil_src/shared_modules/video_overlay/ui/interactions.py | 1 - pupil_src/shared_modules/vis_watermark.py | 1 - pupil_src/shared_modules/visualizer.py | 1 - 23 files changed, 24 deletions(-) diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index 0a048a0be7..bfe6921b72 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -123,7 +123,6 @@ def eye( # display import glfw - import glfw.GLFW # TODO: Remove when switching to pyglfw API from pyglui import ui, graph, cygl from pyglui.cygl.utils import draw_points, RGBA, draw_polyline from pyglui.cygl.utils import Named_Texture diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index ba7f4ade4b..ad0aa42a74 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -71,7 +71,6 @@ def player( # display import glfw - import glfw.GLFW # TODO: Remove when switching to pyglfw API # check versions for our own depedencies as they are fast-changing from pyglui import __version__ as pyglui_version @@ -801,7 +800,6 @@ def player_drop( try: import glfw - import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from OpenGL.GL import glClearColor from version_utils import parse_version diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index e007472fa2..0ee88ee160 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -118,7 +118,6 @@ def detection_enabled_setter(is_on: bool): # display import glfw - import glfw.GLFW # TODO: Remove when switching to pyglfw API from version_utils import parse_version from pyglui import ui, cygl, __version__ as pyglui_version diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py index 253f3b6c61..ed5b8fb3f1 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py @@ -2,7 +2,6 @@ import typing as T import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API try: from typing import OrderedDict as T_OrderedDict # Python 3.7.2 diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py index 43b7911026..fd2b553366 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py @@ -5,7 +5,6 @@ import OpenGL.GL as gl import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from pyglui.cygl.utils import draw_polyline diff --git a/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py b/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py index 2c95fdbdfb..1e4d9f2e5c 100644 --- a/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py @@ -16,7 +16,6 @@ import numpy as np import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API from methods import normalize from pyglui import ui diff --git a/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py b/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py index d1d33f24df..a088d80a58 100644 --- a/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py @@ -17,7 +17,6 @@ import OpenGL.GL as gl import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API from circle_detector import CircleTracker from platform import system diff --git a/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py b/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py index 9e5905252c..37ae538963 100644 --- a/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py @@ -27,7 +27,6 @@ import OpenGL.GL as gl import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API from .mixin import MonitorSelectionMixin from .controller import ( diff --git a/pupil_src/shared_modules/camera_intrinsics_estimation.py b/pupil_src/shared_modules/camera_intrinsics_estimation.py index 22d7861f73..addc2d3781 100644 --- a/pupil_src/shared_modules/camera_intrinsics_estimation.py +++ b/pupil_src/shared_modules/camera_intrinsics_estimation.py @@ -27,7 +27,6 @@ from pyglui.ui import get_opensans_font_path import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from plugin import Plugin diff --git a/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py b/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py index fcf1d15fd0..447792743c 100644 --- a/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py +++ b/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py @@ -14,7 +14,6 @@ import numpy as np import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import tasklib from gaze_producer import model, worker from observable import Observable diff --git a/pupil_src/shared_modules/gl_utils/utils.py b/pupil_src/shared_modules/gl_utils/utils.py index 2940c5eac1..fd8e9a735e 100644 --- a/pupil_src/shared_modules/gl_utils/utils.py +++ b/pupil_src/shared_modules/gl_utils/utils.py @@ -19,7 +19,6 @@ from OpenGL.GLU import gluPerspective, gluErrorString import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API # OpenGL.FULL_LOGGING = True OpenGL.ERROR_LOGGING = False diff --git a/pupil_src/shared_modules/gl_utils/window_position_manager.py b/pupil_src/shared_modules/gl_utils/window_position_manager.py index 9af748f6fb..c01edbb89a 100644 --- a/pupil_src/shared_modules/gl_utils/window_position_manager.py +++ b/pupil_src/shared_modules/gl_utils/window_position_manager.py @@ -13,7 +13,6 @@ import typing as T import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils diff --git a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py index 6000a53726..c83a9ac40b 100644 --- a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py +++ b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py @@ -16,7 +16,6 @@ import gl_utils import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API from observable import Observable # FOR SMOOTH RENDERING diff --git a/pupil_src/shared_modules/log_display.py b/pupil_src/shared_modules/log_display.py index 970ffb46dc..154d134f8e 100644 --- a/pupil_src/shared_modules/log_display.py +++ b/pupil_src/shared_modules/log_display.py @@ -16,7 +16,6 @@ from pyglui.pyfontstash import fontstash from pyglui.ui import get_opensans_font_path import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils diff --git a/pupil_src/shared_modules/marker_auto_trim_marks.py b/pupil_src/shared_modules/marker_auto_trim_marks.py index f16f6bd7f9..4d62b84f9c 100644 --- a/pupil_src/shared_modules/marker_auto_trim_marks.py +++ b/pupil_src/shared_modules/marker_auto_trim_marks.py @@ -24,7 +24,6 @@ from OpenGL.GL import * import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import numpy as np from itertools import groupby diff --git a/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py index dbe248d533..418af9da11 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py @@ -15,7 +15,6 @@ from pyglui.cygl.utils import draw_gl_texture import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API from gl_utils import ( adjust_gl_view, basic_gl_setup, diff --git a/pupil_src/shared_modules/roi.py b/pupil_src/shared_modules/roi.py index f7d61de42a..6b0e659be5 100644 --- a/pupil_src/shared_modules/roi.py +++ b/pupil_src/shared_modules/roi.py @@ -19,7 +19,6 @@ from pyglui.cygl.utils import draw_polyline as cygl_draw_polyline import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API from methods import denormalize, normalize from observable import Observable from plugin import Plugin diff --git a/pupil_src/shared_modules/service_ui.py b/pupil_src/shared_modules/service_ui.py index a506693ba9..eb8897fcb2 100644 --- a/pupil_src/shared_modules/service_ui.py +++ b/pupil_src/shared_modules/service_ui.py @@ -16,7 +16,6 @@ import numpy as np import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from pyglui import ui, cygl from plugin import System_Plugin_Base diff --git a/pupil_src/shared_modules/surface_tracker/gui.py b/pupil_src/shared_modules/surface_tracker/gui.py index 6353d51c62..62e0c862a1 100644 --- a/pupil_src/shared_modules/surface_tracker/gui.py +++ b/pupil_src/shared_modules/surface_tracker/gui.py @@ -21,7 +21,6 @@ import gl_utils import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API from .surface_marker import Surface_Marker_Type diff --git a/pupil_src/shared_modules/system_graphs.py b/pupil_src/shared_modules/system_graphs.py index 375402a009..00e6e1b7a7 100644 --- a/pupil_src/shared_modules/system_graphs.py +++ b/pupil_src/shared_modules/system_graphs.py @@ -12,7 +12,6 @@ import os import psutil import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from pyglui import ui, graph from pyglui.cygl.utils import RGBA, mix_smooth diff --git a/pupil_src/shared_modules/video_overlay/ui/interactions.py b/pupil_src/shared_modules/video_overlay/ui/interactions.py index 867c27b0d4..6b3e0416d2 100644 --- a/pupil_src/shared_modules/video_overlay/ui/interactions.py +++ b/pupil_src/shared_modules/video_overlay/ui/interactions.py @@ -9,7 +9,6 @@ ---------------------------------------------------------------------------~(*) """ import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from methods import normalize, denormalize diff --git a/pupil_src/shared_modules/vis_watermark.py b/pupil_src/shared_modules/vis_watermark.py index e8d3da673c..d27bf018a0 100644 --- a/pupil_src/shared_modules/vis_watermark.py +++ b/pupil_src/shared_modules/vis_watermark.py @@ -18,7 +18,6 @@ from pyglui import ui import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API from methods import normalize, denormalize import logging diff --git a/pupil_src/shared_modules/visualizer.py b/pupil_src/shared_modules/visualizer.py index cad7c23c77..c775824660 100644 --- a/pupil_src/shared_modules/visualizer.py +++ b/pupil_src/shared_modules/visualizer.py @@ -10,7 +10,6 @@ """ import glfw -import glfw.GLFW # TODO: Remove when switching to pyglfw API import gl_utils from OpenGL.GL import * from platform import system From 1a0cd579af41fdf6f7ade7d6d9d4295883709e33 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 29 Sep 2020 10:36:46 +0200 Subject: [PATCH 12/57] Fix glfw video mode struct properties --- .../calibration_choreography/controller/gui_monitor.py | 10 +++++----- .../shared_modules/camera_intrinsics_estimation.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py index ed5b8fb3f1..86170fdc63 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py @@ -58,11 +58,11 @@ def refresh_rate(self) -> int: def current_video_mode(self) -> "GUIMonitor.VideoMode": gl_video_mode = glfw.get_video_mode(self.__gl_handle) return GUIMonitor.VideoMode( - width=gl_video_mode.width, - height=gl_video_mode.height, - red_bits=gl_video_mode.red_bits, - green_bits=gl_video_mode.green_bits, - blue_bits=gl_video_mode.blue_bits, + width=gl_video_mode.size.width, + height=gl_video_mode.size.height, + red_bits=gl_video_mode.bits.red, + green_bits=gl_video_mode.bits.green, + blue_bits=gl_video_mode.bits.blue, refresh_rate=gl_video_mode.refresh_rate, ) diff --git a/pupil_src/shared_modules/camera_intrinsics_estimation.py b/pupil_src/shared_modules/camera_intrinsics_estimation.py index addc2d3781..e8d702374c 100644 --- a/pupil_src/shared_modules/camera_intrinsics_estimation.py +++ b/pupil_src/shared_modules/camera_intrinsics_estimation.py @@ -190,7 +190,7 @@ def open_window(self): self.monitor_idx = 0 monitor = glfw.get_monitors()[self.monitor_idx] mode = glfw.get_video_mode(monitor) - height, width = mode.height, mode.width + height, width = mode.size.height, mode.size.width else: monitor = None height, width = 640, 480 From c7e4e5c58e8025b4ac53caec3d79ebdfb128bc08 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 29 Sep 2020 10:44:16 +0200 Subject: [PATCH 13/57] Fix on_drop callback definitions --- pupil_src/launchables/eye.py | 3 +-- pupil_src/launchables/player.py | 7 +++---- pupil_src/launchables/world.py | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index bfe6921b72..423a34eff1 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -362,8 +362,7 @@ def on_pos(window, x, y): def on_scroll(window, x, y): g_pool.gui.update_scroll(x, y * scroll_factor) - def on_drop(window, count, paths): - paths = [paths[x].decode("utf-8") for x in range(count)] + def on_drop(window, paths): for plugin in g_pool.plugins: if plugin.on_drop(paths): break diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index ad0aa42a74..651c91c7da 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -288,8 +288,7 @@ def on_pos(window, x, y): def on_scroll(window, x, y): g_pool.gui.update_scroll(x, y * scroll_factor) - def on_drop(window, count, paths): - paths = [paths[x].decode("utf-8") for x in range(count)] + def on_drop(window, paths): for path in paths: try: assert_valid_recording_type(path) @@ -825,9 +824,9 @@ def interrupt_handler(sig, frame): signal.signal(signal.SIGINT, interrupt_handler) - def on_drop(window, count, paths): + def on_drop(window, paths): nonlocal rec_dir - rec_dir = paths[0].decode("utf-8") + rec_dir = paths[0] if rec_dir: try: diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index 0ee88ee160..26bdb5156d 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -430,8 +430,7 @@ def on_pos(window, x, y): def on_scroll(window, x, y): g_pool.gui.update_scroll(x, y * scroll_factor) - def on_drop(window, count, paths): - paths = [paths[x].decode("utf-8") for x in range(count)] + def on_drop(window, paths): for plugin in g_pool.plugins: if plugin.on_drop(paths): break From b2aed92b5c4cfed058286c6bfa91045b8b2b627f Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 29 Sep 2020 17:44:50 +0200 Subject: [PATCH 14/57] Update docs with external pyGLFW dependency --- docs/dependencies-macos.md | 2 +- docs/dependencies-ubuntu17.md | 3 ++- docs/dependencies-ubuntu18.md | 3 ++- docs/dependencies-windows.md | 7 +------ 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docs/dependencies-macos.md b/docs/dependencies-macos.md index 35467521b8..f53866159d 100644 --- a/docs/dependencies-macos.md +++ b/docs/dependencies-macos.md @@ -46,7 +46,6 @@ brew install portaudio # tbb is included by default with https://github.com/Homebrew/homebrew-core/pull/20101 brew install opencv brew install glew -brew install glfw3 # dependencies for 2d_3d c++ detector brew install ceres-solver ``` @@ -80,6 +79,7 @@ pip install pyopengl pip install pyzmq pip install scikit-learn pip install scipy +pip install glfw pip install git+https://github.com/zeromq/pyre pip install pupil-apriltags diff --git a/docs/dependencies-ubuntu17.md b/docs/dependencies-ubuntu17.md index 28835e2272..d0c3bb5b3c 100644 --- a/docs/dependencies-ubuntu17.md +++ b/docs/dependencies-ubuntu17.md @@ -9,7 +9,7 @@ Pupil requires Python 3.6 or higher. Please check this [resource](https://askubu ```sh sudo apt-get update -sudo apt install -y pkg-config git cmake build-essential nasm wget python3-setuptools libusb-1.0-0-dev python3-dev python3-pip python3-numpy python3-scipy libglew-dev libglfw3-dev libtbb-dev +sudo apt install -y pkg-config git cmake build-essential nasm wget python3-setuptools libusb-1.0-0-dev python3-dev python3-pip python3-numpy python3-scipy libglew-dev libtbb-dev ``` ## ffmpeg3 @@ -169,6 +169,7 @@ pip install pyopengl pip install pyzmq pip install scikit-learn pip install scipy +pip install glfw pip install git+https://github.com/zeromq/pyre pip install pupil-apriltags diff --git a/docs/dependencies-ubuntu18.md b/docs/dependencies-ubuntu18.md index 2108dc64e4..bebc9f722e 100644 --- a/docs/dependencies-ubuntu18.md +++ b/docs/dependencies-ubuntu18.md @@ -7,7 +7,7 @@ Most of this works via **apt**! Just copy paste into the terminal and listen to ## General Dependencies ```sh -sudo apt install -y pkg-config git cmake build-essential nasm wget python3-setuptools libusb-1.0-0-dev python3-dev python3-pip python3-numpy python3-scipy libglew-dev libglfw3-dev libtbb-dev +sudo apt install -y pkg-config git cmake build-essential nasm wget python3-setuptools libusb-1.0-0-dev python3-dev python3-pip python3-numpy python3-scipy libglew-dev libtbb-dev # ffmpeg >= 3.2 sudo apt install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev ffmpeg x264 x265 libportaudio2 portaudio19-dev @@ -80,6 +80,7 @@ pip install pyopengl pip install pyzmq pip install scikit-learn pip install scipy +pip install glfw pip install git+https://github.com/zeromq/pyre pip install pupil-apriltags diff --git a/docs/dependencies-windows.md b/docs/dependencies-windows.md index f37571265e..4a12899454 100644 --- a/docs/dependencies-windows.md +++ b/docs/dependencies-windows.md @@ -68,6 +68,7 @@ pip install pyopengl pip install pyzmq pip install scikit-learn pip install scipy +pip install glfw pip install win_inet_pton pip install git+https://github.com/zeromq/pyre @@ -121,12 +122,6 @@ The following steps require you to store dynamic libraries in the `pupil_externa - Unzip GLEW in your work dir - Copy `glew32.dll` to `pupil_external` -#### GLFW - -- Download GLFW Windows binaries from [glfw.org](http://www.glfw.org/download.html) -- Unzip GLFW to your work dir -- Copy `glfw3.dll` from `lib-vc2015` to `pupil_external` - #### FFMPEG - Download FFMPEG v4.0 Windows shared binaries from [ffmpeg](http://ffmpeg.zeranoe.com/builds/) From 10ae79c73787986ad962d3712d37912ddc757c28 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 29 Sep 2020 17:45:12 +0200 Subject: [PATCH 15/57] Add pyGLFW dependency to travis test script --- .travis/run_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis/run_tests.sh b/.travis/run_tests.sh index b5fea38733..f5abc0bed5 100644 --- a/.travis/run_tests.sh +++ b/.travis/run_tests.sh @@ -3,6 +3,7 @@ python -m pip install -U pip pip install -U git+https://github.com/pupil-labs/pyndsi pip install -U git+https://github.com/pupil-labs/PyAV pip install scikit-learn +pip install glfw pip install pytest==5.2.2 pytest From c64aaaf2e2b36febf781636aa66ade21c1528367 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 29 Sep 2020 17:45:32 +0200 Subject: [PATCH 16/57] Exclude glfw.py from update_license_header.py --- update_license_header.py | 1 - 1 file changed, 1 deletion(-) diff --git a/update_license_header.py b/update_license_header.py index c2703e57a1..bdf3b9abd1 100644 --- a/update_license_header.py +++ b/update_license_header.py @@ -42,7 +42,6 @@ "transformations.py", "libuvcc*", ".gitignore", - "glfw.py", "version_utils.py", "update_license_header.py", ] From 6fac714fb5f8dab99fd1f881741c1c4354d415a6 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Wed, 30 Sep 2020 10:09:26 +0200 Subject: [PATCH 17/57] Remove obsolete comment --- pupil_src/shared_modules/gl_utils/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pupil_src/shared_modules/gl_utils/utils.py b/pupil_src/shared_modules/gl_utils/utils.py index fd8e9a735e..c90380c41f 100644 --- a/pupil_src/shared_modules/gl_utils/utils.py +++ b/pupil_src/shared_modules/gl_utils/utils.py @@ -256,7 +256,6 @@ def intersection(self, other: "_Rectangle") -> T.Optional["_Rectangle"]: def get_content_scale(window) -> float: - # TODO: Explicitly rename to `get_content_scale_x` return glfw.get_window_content_scale(window)[0] From c1ca570f727d0771c7737648bbb35f07eaadb640 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Wed, 30 Sep 2020 12:50:38 +0200 Subject: [PATCH 18/57] Remove manual libglfw copy from bundle spec --- deployment/deploy_capture/bundle.spec | 1 - deployment/deploy_player/bundle.spec | 1 - deployment/deploy_service/bundle.spec | 1 - 3 files changed, 3 deletions(-) diff --git a/deployment/deploy_capture/bundle.spec b/deployment/deploy_capture/bundle.spec index 044c8de796..bd81048a27 100644 --- a/deployment/deploy_capture/bundle.spec +++ b/deployment/deploy_capture/bundle.spec @@ -63,7 +63,6 @@ if platform.system() == "Darwin": a.binaries - libSystem, a.zipfiles, a.datas, - [("libglfw.dylib", "/usr/local/lib/libglfw.dylib", "BINARY")], [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], diff --git a/deployment/deploy_player/bundle.spec b/deployment/deploy_player/bundle.spec index cb87199a80..19ff25ef60 100644 --- a/deployment/deploy_player/bundle.spec +++ b/deployment/deploy_player/bundle.spec @@ -64,7 +64,6 @@ if platform.system() == "Darwin": a.binaries - libSystem, a.zipfiles, a.datas, - [("libglfw.dylib", "/usr/local/lib/libglfw.dylib", "BINARY")], [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], diff --git a/deployment/deploy_service/bundle.spec b/deployment/deploy_service/bundle.spec index aac3427ad1..36611ad2a1 100644 --- a/deployment/deploy_service/bundle.spec +++ b/deployment/deploy_service/bundle.spec @@ -48,7 +48,6 @@ if platform.system() == "Darwin": a.binaries - libSystem, a.zipfiles, a.datas, - [("libglfw.dylib", "/usr/local/lib/libglfw.dylib", "BINARY")], [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], From 8fb24125a84651844beb61cba13157b177e4be7c Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Wed, 30 Sep 2020 13:19:14 +0200 Subject: [PATCH 19/57] Remove manual libgflw copy from Linux/Windows bundle spec --- deployment/deploy_capture/bundle.spec | 2 -- deployment/deploy_player/bundle.spec | 2 -- deployment/deploy_service/bundle.spec | 2 -- 3 files changed, 6 deletions(-) diff --git a/deployment/deploy_capture/bundle.spec b/deployment/deploy_capture/bundle.spec index bd81048a27..34be5b2115 100644 --- a/deployment/deploy_capture/bundle.spec +++ b/deployment/deploy_capture/bundle.spec @@ -124,7 +124,6 @@ elif platform.system() == "Linux": binaries, a.zipfiles, a.datas, - [("libglfw.so", "/usr/local/lib/libglfw.so", "BINARY")], [("libGLEW.so", "/usr/lib/x86_64-linux-gnu/libGLEW.so", "BINARY")], [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], @@ -193,7 +192,6 @@ elif platform.system() == "Windows": a.zipfiles, a.datas, [("PupilDrvInst.exe", "../../pupil_external/PupilDrvInst.exe", "BINARY")], - [("glfw3.dll", "../../pupil_external/glfw3.dll", "BINARY")], [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], diff --git a/deployment/deploy_player/bundle.spec b/deployment/deploy_player/bundle.spec index 19ff25ef60..bd2fd3a9cd 100644 --- a/deployment/deploy_player/bundle.spec +++ b/deployment/deploy_player/bundle.spec @@ -126,7 +126,6 @@ elif platform.system() == "Linux": binaries, a.zipfiles, a.datas, - [("libglfw.so", "/usr/local/lib/libglfw.so", "BINARY")], [("libGLEW.so", "/usr/lib/x86_64-linux-gnu/libGLEW.so", "BINARY")], [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], @@ -190,7 +189,6 @@ elif platform.system() == "Windows": a.binaries, a.zipfiles, a.datas, - [("glfw3.dll", "../../pupil_external/glfw3.dll", "BINARY")], [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], diff --git a/deployment/deploy_service/bundle.spec b/deployment/deploy_service/bundle.spec index 36611ad2a1..5c85b36cb9 100644 --- a/deployment/deploy_service/bundle.spec +++ b/deployment/deploy_service/bundle.spec @@ -104,7 +104,6 @@ elif platform.system() == "Linux": binaries, a.zipfiles, a.datas, - [("libglfw.so", "/usr/local/lib/libglfw.so", "BINARY")], [("libGLEW.so", "/usr/lib/x86_64-linux-gnu/libGLEW.so", "BINARY")], [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], @@ -167,7 +166,6 @@ elif platform.system() == "Windows": a.zipfiles, a.datas, [("PupilDrvInst.exe", "../../pupil_external/PupilDrvInst.exe", "BINARY")], - [("glfw3.dll", "../../pupil_external/glfw3.dll", "BINARY")], [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], From 37521276eb9eea9a73d8879d8367b1a03e3c7cf5 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Wed, 30 Sep 2020 14:44:28 +0200 Subject: [PATCH 20/57] bundle spec files: Sort imports --- deployment/deploy_capture/bundle.spec | 15 ++++++++++++--- deployment/deploy_player/bundle.spec | 16 +++++++++++++--- deployment/deploy_service/bundle.spec | 13 +++++++++++-- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/deployment/deploy_capture/bundle.spec b/deployment/deploy_capture/bundle.spec index 34be5b2115..95bedbfe0b 100644 --- a/deployment/deploy_capture/bundle.spec +++ b/deployment/deploy_capture/bundle.spec @@ -1,7 +1,14 @@ # -*- mode: python -*- -import platform, sys, os, os.path, numpy, glob, pathlib +import glob +import os +import os.path +import pathlib +import platform +import sys + +import numpy from PyInstaller.utils.hooks import collect_submodules hidden_imports = [] @@ -14,8 +21,8 @@ hidden_imports += collect_submodules("pyglui") hidden_imports += collect_submodules("pupil_apriltags") hidden_imports += collect_submodules("sklearn") -from pyglui import ui import pupil_apriltags +from pyglui import ui apriltag_lib_path = pathlib.Path(pupil_apriltags.__file__).parent @@ -135,7 +142,9 @@ elif platform.system() == "Linux": ) elif platform.system() == "Windows": - import sys, os, os.path + import os + import os.path + import sys np_path = os.path.dirname(numpy.__file__) np_dlls = glob.glob(np_path + "/core/*.dll") diff --git a/deployment/deploy_player/bundle.spec b/deployment/deploy_player/bundle.spec index bd2fd3a9cd..112d5ba094 100644 --- a/deployment/deploy_player/bundle.spec +++ b/deployment/deploy_player/bundle.spec @@ -1,7 +1,15 @@ # -*- mode: python -*- -import platform, sys, os, os.path, zmq, glob, numpy, pathlib +import glob +import os +import os.path +import pathlib +import platform +import sys + +import numpy +import zmq from PyInstaller.utils.hooks import collect_submodules hidden_imports = [] @@ -14,8 +22,8 @@ hidden_imports += collect_submodules("pyglui") hidden_imports += collect_submodules("pupil_apriltags") hidden_imports += collect_submodules("sklearn") -from pyglui import ui import pupil_apriltags +from pyglui import ui apriltag_lib_path = pathlib.Path(pupil_apriltags.__file__).parent @@ -137,7 +145,9 @@ elif platform.system() == "Linux": ) elif platform.system() == "Windows": - import sys, os, os.path + import os + import os.path + import sys np_path = os.path.dirname(numpy.__file__) np_dlls = glob.glob(np_path + "/core/*.dll") diff --git a/deployment/deploy_service/bundle.spec b/deployment/deploy_service/bundle.spec index 5c85b36cb9..821e508b0c 100644 --- a/deployment/deploy_service/bundle.spec +++ b/deployment/deploy_service/bundle.spec @@ -1,7 +1,14 @@ # -*- mode: python -*- -import platform, sys, os, os.path, numpy, glob, pathlib +import glob +import os +import os.path +import pathlib +import platform +import sys + +import numpy from PyInstaller.utils.hooks import collect_submodules hidden_imports = [] @@ -114,7 +121,9 @@ elif platform.system() == "Linux": ) elif platform.system() == "Windows": - import sys, os, os.path + import os + import os.path + import sys np_path = os.path.dirname(numpy.__file__) np_dlls = glob.glob(np_path + "/core/*.dll") From 3c14ff91970b181d3ed1399be103d5bf35dd75ca Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Wed, 30 Sep 2020 14:45:49 +0200 Subject: [PATCH 21/57] bundle spec files: Remove unused imports --- deployment/deploy_player/bundle.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/deployment/deploy_player/bundle.spec b/deployment/deploy_player/bundle.spec index 112d5ba094..5cb81163cf 100644 --- a/deployment/deploy_player/bundle.spec +++ b/deployment/deploy_player/bundle.spec @@ -9,7 +9,6 @@ import platform import sys import numpy -import zmq from PyInstaller.utils.hooks import collect_submodules hidden_imports = [] From c721b31471b40b08a5df3bc08b230ecd8d7406c5 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Wed, 30 Sep 2020 15:51:04 +0200 Subject: [PATCH 22/57] Bundles: Support pyglfw --- deployment/deploy_capture/bundle.spec | 11 +++++++++++ deployment/deploy_player/bundle.spec | 11 +++++++++++ deployment/deploy_service/bundle.spec | 11 +++++++++++ pupil_src/main.py | 12 ++++++++++++ 4 files changed, 45 insertions(+) diff --git a/deployment/deploy_capture/bundle.spec b/deployment/deploy_capture/bundle.spec index 95bedbfe0b..a8bf2433e1 100644 --- a/deployment/deploy_capture/bundle.spec +++ b/deployment/deploy_capture/bundle.spec @@ -9,6 +9,7 @@ import platform import sys import numpy +import pkg_resources from PyInstaller.utils.hooks import collect_submodules hidden_imports = [] @@ -21,6 +22,7 @@ hidden_imports += collect_submodules("pyglui") hidden_imports += collect_submodules("pupil_apriltags") hidden_imports += collect_submodules("sklearn") +import glfw import pupil_apriltags from pyglui import ui @@ -32,6 +34,12 @@ def apriltag_relative_path(absolute_path): return os.path.join(*absolute_path.parts[-3:]) +glfw_name = glfw._glfw._name +glfw_path = pathlib.Path(glfw_name) +if not glfw_path.exists(): + glfw_path = pathlib.Path(pkg_resources.resource_filename("glfw", glfw_name)) +glfw_binaries = [(glfw_path.name, str(glfw_path), "BINARY")] + if platform.system() == "Darwin": sys.path.append(".") from version import pupil_version @@ -74,6 +82,7 @@ if platform.system() == "Darwin": [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], apriltag_libs, + glfw_binaries, strip=None, upx=True, name="Pupil Capture", @@ -136,6 +145,7 @@ elif platform.system() == "Linux": [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], apriltag_libs, + glfw_binaries, strip=True, upx=True, name="pupil_capture", @@ -205,6 +215,7 @@ elif platform.system() == "Windows": [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], apriltag_libs, + glfw_binaries, vc_redist_libs, np_dll_list, strip=False, diff --git a/deployment/deploy_player/bundle.spec b/deployment/deploy_player/bundle.spec index 5cb81163cf..773b9e185a 100644 --- a/deployment/deploy_player/bundle.spec +++ b/deployment/deploy_player/bundle.spec @@ -9,6 +9,7 @@ import platform import sys import numpy +import pkg_resources from PyInstaller.utils.hooks import collect_submodules hidden_imports = [] @@ -21,6 +22,7 @@ hidden_imports += collect_submodules("pyglui") hidden_imports += collect_submodules("pupil_apriltags") hidden_imports += collect_submodules("sklearn") +import glfw import pupil_apriltags from pyglui import ui @@ -32,6 +34,12 @@ def apriltag_relative_path(absolute_path): return os.path.join(*absolute_path.parts[-3:]) +glfw_name = glfw._glfw._name +glfw_path = pathlib.Path(glfw_name) +if not glfw_path.exists(): + glfw_path = pathlib.Path(pkg_resources.resource_filename("glfw", glfw_name)) +glfw_binaries = [(glfw_path.name, str(glfw_path), "BINARY")] + if platform.system() == "Darwin": sys.path.append(".") from version import pupil_version @@ -75,6 +83,7 @@ if platform.system() == "Darwin": [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], apriltag_libs, + glfw_binaries, strip=None, upx=True, name="Pupil Player", @@ -138,6 +147,7 @@ elif platform.system() == "Linux": [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], apriltag_libs, + glfw_binaries, strip=True, upx=True, name="pupil_player", @@ -202,6 +212,7 @@ elif platform.system() == "Windows": [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], apriltag_libs, + glfw_binaries, vc_redist_libs, np_dll_list, strip=None, diff --git a/deployment/deploy_service/bundle.spec b/deployment/deploy_service/bundle.spec index 821e508b0c..f9a3a3e8bf 100644 --- a/deployment/deploy_service/bundle.spec +++ b/deployment/deploy_service/bundle.spec @@ -9,6 +9,7 @@ import platform import sys import numpy +import pkg_resources from PyInstaller.utils.hooks import collect_submodules hidden_imports = [] @@ -20,8 +21,15 @@ if platform.system() != "Windows": hidden_imports += collect_submodules("pyglui") hidden_imports += collect_submodules("sklearn") +import glfw from pyglui import ui +glfw_name = glfw._glfw._name +glfw_path = pathlib.Path(glfw_name) +if not glfw_path.exists(): + glfw_path = pathlib.Path(pkg_resources.resource_filename("glfw", glfw_name)) +glfw_binaries = [(glfw_path.name, str(glfw_path), "BINARY")] + if platform.system() == "Darwin": sys.path.append(".") from version import pupil_version @@ -58,6 +66,7 @@ if platform.system() == "Darwin": [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], + glfw_binaries, strip=None, upx=True, name="Pupil Service", @@ -115,6 +124,7 @@ elif platform.system() == "Linux": [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], + glfw_binaries, strip=True, upx=True, name="pupil_service", @@ -178,6 +188,7 @@ elif platform.system() == "Windows": [("pyglui/OpenSans-Regular.ttf", ui.get_opensans_font_path(), "DATA")], [("pyglui/Roboto-Regular.ttf", ui.get_roboto_font_path(), "DATA")], [("pyglui/pupil_icons.ttf", ui.get_pupil_icons_font_path(), "DATA")], + glfw_binaries, np_dll_list, vc_redist_libs, strip=False, diff --git a/pupil_src/main.py b/pupil_src/main.py index c59d74efc9..0266c1ce53 100644 --- a/pupil_src/main.py +++ b/pupil_src/main.py @@ -42,10 +42,22 @@ print(version_message) sys.exit() + +def set_bundled_glfw_environ_var(): + import pathlib + + meipass = pathlib.Path(sys._MEIPASS) + lib_path = next(meipass.glob("*glfw*"), None) + os.environ["PYGLFW_LIBRARY"] = str(lib_path) + + if running_from_bundle: # Specifiy user dir. folder_name = "pupil_{}_settings".format(parsed_args.app) user_dir = os.path.expanduser(os.path.join("~", folder_name)) + + # set libglfw env variable to prevent endless version check loop within pyglfw + set_bundled_glfw_environ_var() else: # Specifiy user dir. user_dir = os.path.join(pupil_base_dir, "{}_settings".format(parsed_args.app)) From 69ddc80b38a668d99ce7987da2c313d55c15ec3f Mon Sep 17 00:00:00 2001 From: Patrick Faion Date: Thu, 1 Oct 2020 17:17:36 +0200 Subject: [PATCH 23/57] WIP --- .../pupil_detector_plugins/pye3d_plugin.py | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py index 6473ae5ae4..dc02b982fd 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py @@ -12,11 +12,10 @@ from pye3d.detector_3d import Detector3D from pyglui import ui -from matplotlib import pyplot as plt import pyqtgraph as pq from .detector_base_plugin import PupilDetectorPlugin -from .visualizer_2d import draw_eyeball_outline, draw_pupil_outline +from .visualizer_2d import draw_eyeball_outline, draw_pupil_outline, draw_ellipse from .visualizer_pye3d import Eye_Visualizer logger = logging.getLogger(__name__) @@ -109,8 +108,26 @@ def init_ui(self): def gl_display(self): self.debug_window_update() if self._recent_detection_result: - draw_eyeball_outline(self._recent_detection_result) - draw_pupil_outline(self._recent_detection_result) + # draw_eyeball_outline(self._recent_detection_result) + # draw_pupil_outline(self._recent_detection_result) + result = self._recent_detection_result + debug_info = result["debug_info"] + + draw_ellipse( + ellipse=debug_info["projected_ultra_long_term"], + rgba=(0.5, 0, 0, 1), + thickness=2, + ) + draw_ellipse( + ellipse=debug_info["projected_long_term"], + rgba=(0.8, 0.8, 0, 1), + thickness=2, + ) + draw_ellipse( + ellipse=debug_info["projected_short_term"], + rgba=(0, 1, 0, 1), + thickness=2, + ) def cleanup(self): self.debug_window_close() # if we change detectors, be sure debug window is also closed From 15dd6ea939f05183551a7a2d43ad51f59add14f7 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Thu, 1 Oct 2020 17:42:15 +0200 Subject: [PATCH 24/57] Handle GLFWError when calling glfw.get_clipboard_string --- pupil_src/launchables/eye.py | 3 ++- pupil_src/launchables/player.py | 6 ++++-- pupil_src/launchables/world.py | 6 ++++-- pupil_src/shared_modules/service_ui.py | 3 ++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index 423a34eff1..2f47c6cecb 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -249,7 +249,8 @@ def consume_events_and_render_buffer(): # render GUI try: clipboard = glfw.get_clipboard_string(main_window).decode() - except AttributeError: # clipboard is None, might happen on startup + except (AttributeError, glfw.GLFWError): + # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index 651c91c7da..f82d9e3469 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -193,7 +193,8 @@ def consume_events_and_render_buffer(): try: clipboard = glfw.get_clipboard_string(main_window).decode() - except AttributeError: # clipbaord is None, might happen on startup + except (AttributeError, glfw.GLFWError): + # clipbaord is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() @@ -696,7 +697,8 @@ def handle_notifications(n): try: clipboard = glfw.get_clipboard_string(main_window).decode() - except AttributeError: # clipbaord is None, might happen on startup + except (AttributeError, glfw.GLFWError): + # clipbaord is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index 26bdb5156d..5b3091302c 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -333,7 +333,8 @@ def consume_events_and_render_buffer(): gl_utils.glViewport(0, 0, *window_size) try: clipboard = glfw.get_clipboard_string(main_window).decode() - except AttributeError: # clipboard is None, might happen on startup + except (AttributeError, glfw.GLFWError): + # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() @@ -757,7 +758,8 @@ def window_should_update(): gl_utils.glViewport(0, 0, *window_size) try: clipboard = glfw.get_clipboard_string(main_window).decode() - except AttributeError: # clipboard is None, might happen on startup + except (AttributeError, glfw.GLFWError): + # clipboard is None, might happen on startup clipboard = "" g_pool.gui.update_clipboard(clipboard) user_input = g_pool.gui.update() diff --git a/pupil_src/shared_modules/service_ui.py b/pupil_src/shared_modules/service_ui.py index eb8897fcb2..78838e860e 100644 --- a/pupil_src/shared_modules/service_ui.py +++ b/pupil_src/shared_modules/service_ui.py @@ -190,7 +190,8 @@ def update_ui(self): self.gl_display() try: clipboard = glfw.get_clipboard_string(self.g_pool.main_window).decode() - except AttributeError: # clipbaord is None, might happen on startup + except (AttributeError, glfw.GLFWError): + # clipbaord is None, might happen on startup clipboard = "" self.g_pool.gui.update_clipboard(clipboard) user_input = self.g_pool.gui.update() From f38bafcdfe26859a4e6885709a9dd7acb44e971d Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Thu, 1 Oct 2020 18:56:41 +0200 Subject: [PATCH 25/57] Ensure valid confidence value in video_overlay.utils.image_manipulation --- .../video_overlay/utils/image_manipulation.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pupil_src/shared_modules/video_overlay/utils/image_manipulation.py b/pupil_src/shared_modules/video_overlay/utils/image_manipulation.py index 9403611db2..b7be201689 100644 --- a/pupil_src/shared_modules/video_overlay/utils/image_manipulation.py +++ b/pupil_src/shared_modules/video_overlay/utils/image_manipulation.py @@ -18,6 +18,10 @@ logger = logging.getLogger(__name__) +def float_to_int(value: float) -> int: + return int(value) if np.isfinite(value) else 0 + + class ImageManipulator(metaclass=abc.ABCMeta): @abc.abstractmethod def apply_to(self, image, parameter, **kwargs): @@ -73,7 +77,9 @@ def render_pupil_2d(self, image, pupil_position): def render_pupil_3d(self, image, pupil_position): el = pupil_position["ellipse"] - conf = int(pupil_position["confidence"] * 255) + conf = pupil_position["confidence"] * 255 + conf = float_to_int(conf) + self.render_ellipse(image, el, color=(0, 0, 255, conf)) if pupil_position["model_confidence"] <= 0.0: @@ -112,7 +118,8 @@ def render_ellipse(self, image, ellipse, color): outline = [np.asarray(outline, dtype="i")] cv2.polylines(image, outline, True, color, thickness=1) - center = (int(ellipse["center"][0]), int(ellipse["center"][1])) + center = ellipse["center"] + center = (float_to_int(center[0]), float_to_int(center[1])) cv2.circle(image, center, 5, color, thickness=-1) @staticmethod From f1f6fb50cc95ed591cb58eea970386258dcca9d9 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Thu, 1 Oct 2020 18:57:01 +0200 Subject: [PATCH 26/57] Add helper eye_id method to PupilRecordings.FileFilter --- pupil_src/shared_modules/pupil_recording/recording.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pupil_src/shared_modules/pupil_recording/recording.py b/pupil_src/shared_modules/pupil_recording/recording.py index 27647dbd56..7a4bcf4d81 100644 --- a/pupil_src/shared_modules/pupil_recording/recording.py +++ b/pupil_src/shared_modules/pupil_recording/recording.py @@ -113,6 +113,9 @@ def eyes(self) -> FilterType: "eye0", "eye1", mode=PupilRecording.FileFilter.FilterMode.UNION ) + def eye_id(self, eye_id: int) -> FilterType: + return self.filter(f"eye{eye_id}") + def videos(self) -> FilterType: return self.filter("videos") From 09540f818d75d8f7c96761f504396d618c816c30 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Thu, 1 Oct 2020 18:57:25 +0200 Subject: [PATCH 27/57] Update _video_path_for_eye method to use PupilRecording.FileFilter --- .../video_overlay/plugins/eye_overlay.py | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/pupil_src/shared_modules/video_overlay/plugins/eye_overlay.py b/pupil_src/shared_modules/video_overlay/plugins/eye_overlay.py index ab42b081ff..1a100e6e79 100644 --- a/pupil_src/shared_modules/video_overlay/plugins/eye_overlay.py +++ b/pupil_src/shared_modules/video_overlay/plugins/eye_overlay.py @@ -21,6 +21,8 @@ from video_overlay.ui.management import UIManagementEyes from video_overlay.utils.constraints import ConstraintedValue, BooleanConstraint +from pupil_recording import PupilRecording + class Eye_Overlay(Observable, Plugin): icon_chr = chr(0xEC02) @@ -94,14 +96,20 @@ def _setup_eye(self, eye_id, prefilled_config): ) return overlay - def _video_path_for_eye(self, eye_id): + def _video_path_for_eye(self, eye_id: int) -> str: rec_dir = self.g_pool.rec_dir - video_file_pattern = "eye{}.*".format(eye_id) - video_path_pattern = os.path.join(rec_dir, video_file_pattern) - try: - video_path_candidates = glob.iglob(video_path_pattern) - return next(video_path_candidates) - except StopIteration: + + # Create eye video file filter for eye_id + file_filter = PupilRecording.FileFilter(rec_dir) + file_filter = file_filter.eye_id(eye_id) + file_filter = file_filter.videos() + + # Get all eye videos for eye_id + eye_videos = list(file_filter) + + if eye_videos: + return str(eye_videos[0]) + else: return "/not/found/eye{}.mp4".format(eye_id) def get_init_dict(self): From 6b78998802e1ab8e121a16aa06f39b746c2ea44e Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 6 Oct 2020 10:43:26 +0200 Subject: [PATCH 28/57] Change default glfw.ERROR_REPORTING to "raise" --- pupil_src/launchables/eye.py | 3 +++ pupil_src/launchables/player.py | 5 +++++ pupil_src/launchables/world.py | 3 +++ .../calibration_choreography/controller/gui_monitor.py | 2 ++ .../calibration_choreography/controller/gui_window.py | 3 +++ .../calibration_choreography/natural_feature_plugin.py | 2 ++ .../calibration_choreography/screen_marker_plugin.py | 3 +++ .../calibration_choreography/single_marker_plugin.py | 2 ++ pupil_src/shared_modules/camera_intrinsics_estimation.py | 3 +++ .../controller/reference_location_controllers.py | 3 +++ pupil_src/shared_modules/gl_utils/utils.py | 2 ++ pupil_src/shared_modules/gl_utils/window_position_manager.py | 3 +++ pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py | 3 +++ pupil_src/shared_modules/log_display.py | 3 +++ pupil_src/shared_modules/marker_auto_trim_marks.py | 2 ++ .../pupil_detector_plugins/detector_2d_plugin.py | 3 +++ pupil_src/shared_modules/roi.py | 3 +++ pupil_src/shared_modules/service_ui.py | 3 +++ pupil_src/shared_modules/surface_tracker/gui.py | 2 ++ pupil_src/shared_modules/system_graphs.py | 3 +++ pupil_src/shared_modules/video_overlay/ui/interactions.py | 2 ++ pupil_src/shared_modules/vis_watermark.py | 3 +++ pupil_src/shared_modules/visualizer.py | 3 +++ 23 files changed, 64 insertions(+) diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index 2f47c6cecb..f62ad6504c 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -123,6 +123,9 @@ def eye( # display import glfw + + glfw.ERROR_REPORTING = "raise" + from pyglui import ui, graph, cygl from pyglui.cygl.utils import draw_points, RGBA, draw_polyline from pyglui.cygl.utils import Named_Texture diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index f82d9e3469..21266ee8ae 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -72,6 +72,8 @@ def player( # display import glfw + glfw.ERROR_REPORTING = "raise" + # check versions for our own depedencies as they are fast-changing from pyglui import __version__ as pyglui_version @@ -801,6 +803,9 @@ def player_drop( try: import glfw + + glfw.ERROR_REPORTING = "raise" + import gl_utils from OpenGL.GL import glClearColor from version_utils import parse_version diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index 5b3091302c..6089d80904 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -118,6 +118,9 @@ def detection_enabled_setter(is_on: bool): # display import glfw + + glfw.ERROR_REPORTING = "raise" + from version_utils import parse_version from pyglui import ui, cygl, __version__ as pyglui_version diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py index 86170fdc63..0e2e3b25d8 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_monitor.py @@ -3,6 +3,8 @@ import glfw +glfw.ERROR_REPORTING = "raise" + try: from typing import OrderedDict as T_OrderedDict # Python 3.7.2 except ImportError: diff --git a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py index fd2b553366..363947f330 100644 --- a/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py +++ b/pupil_src/shared_modules/calibration_choreography/controller/gui_window.py @@ -5,6 +5,9 @@ import OpenGL.GL as gl import glfw + +glfw.ERROR_REPORTING = "raise" + import gl_utils from pyglui.cygl.utils import draw_polyline diff --git a/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py b/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py index 1e4d9f2e5c..09c5acec27 100644 --- a/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/natural_feature_plugin.py @@ -17,6 +17,8 @@ import glfw +glfw.ERROR_REPORTING = "raise" + from methods import normalize from pyglui import ui from pyglui.cygl.utils import draw_points_norm, RGBA diff --git a/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py b/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py index a088d80a58..19e70aa91b 100644 --- a/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/screen_marker_plugin.py @@ -17,6 +17,9 @@ import OpenGL.GL as gl import glfw + +glfw.ERROR_REPORTING = "raise" + from circle_detector import CircleTracker from platform import system diff --git a/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py b/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py index 37ae538963..3876a0019f 100644 --- a/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py +++ b/pupil_src/shared_modules/calibration_choreography/single_marker_plugin.py @@ -28,6 +28,8 @@ import glfw +glfw.ERROR_REPORTING = "raise" + from .mixin import MonitorSelectionMixin from .controller import ( GUIMonitor, diff --git a/pupil_src/shared_modules/camera_intrinsics_estimation.py b/pupil_src/shared_modules/camera_intrinsics_estimation.py index e8d702374c..01ecbf8ea6 100644 --- a/pupil_src/shared_modules/camera_intrinsics_estimation.py +++ b/pupil_src/shared_modules/camera_intrinsics_estimation.py @@ -27,6 +27,9 @@ from pyglui.ui import get_opensans_font_path import glfw + +glfw.ERROR_REPORTING = "raise" + import gl_utils from plugin import Plugin diff --git a/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py b/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py index 447792743c..14c10d5f41 100644 --- a/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py +++ b/pupil_src/shared_modules/gaze_producer/controller/reference_location_controllers.py @@ -14,6 +14,9 @@ import numpy as np import glfw + +glfw.ERROR_REPORTING = "raise" + import tasklib from gaze_producer import model, worker from observable import Observable diff --git a/pupil_src/shared_modules/gl_utils/utils.py b/pupil_src/shared_modules/gl_utils/utils.py index c90380c41f..f31580897d 100644 --- a/pupil_src/shared_modules/gl_utils/utils.py +++ b/pupil_src/shared_modules/gl_utils/utils.py @@ -20,6 +20,8 @@ import glfw +glfw.ERROR_REPORTING = "raise" + # OpenGL.FULL_LOGGING = True OpenGL.ERROR_LOGGING = False diff --git a/pupil_src/shared_modules/gl_utils/window_position_manager.py b/pupil_src/shared_modules/gl_utils/window_position_manager.py index c01edbb89a..3c5fbfaf90 100644 --- a/pupil_src/shared_modules/gl_utils/window_position_manager.py +++ b/pupil_src/shared_modules/gl_utils/window_position_manager.py @@ -13,6 +13,9 @@ import typing as T import glfw + +glfw.ERROR_REPORTING = "raise" + import gl_utils diff --git a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py index c83a9ac40b..3625da2be5 100644 --- a/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py +++ b/pupil_src/shared_modules/head_pose_tracker/ui/gl_window.py @@ -16,6 +16,9 @@ import gl_utils import glfw + +glfw.ERROR_REPORTING = "raise" + from observable import Observable # FOR SMOOTH RENDERING diff --git a/pupil_src/shared_modules/log_display.py b/pupil_src/shared_modules/log_display.py index 154d134f8e..6526623e14 100644 --- a/pupil_src/shared_modules/log_display.py +++ b/pupil_src/shared_modules/log_display.py @@ -16,6 +16,9 @@ from pyglui.pyfontstash import fontstash from pyglui.ui import get_opensans_font_path import glfw + +glfw.ERROR_REPORTING = "raise" + import gl_utils diff --git a/pupil_src/shared_modules/marker_auto_trim_marks.py b/pupil_src/shared_modules/marker_auto_trim_marks.py index 4d62b84f9c..c09c5830b1 100644 --- a/pupil_src/shared_modules/marker_auto_trim_marks.py +++ b/pupil_src/shared_modules/marker_auto_trim_marks.py @@ -25,6 +25,8 @@ import glfw +glfw.ERROR_REPORTING = "raise" + import numpy as np from itertools import groupby diff --git a/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py index 418af9da11..3ea8ffab95 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/detector_2d_plugin.py @@ -15,6 +15,9 @@ from pyglui.cygl.utils import draw_gl_texture import glfw + +glfw.ERROR_REPORTING = "raise" + from gl_utils import ( adjust_gl_view, basic_gl_setup, diff --git a/pupil_src/shared_modules/roi.py b/pupil_src/shared_modules/roi.py index 6b0e659be5..03b5900726 100644 --- a/pupil_src/shared_modules/roi.py +++ b/pupil_src/shared_modules/roi.py @@ -19,6 +19,9 @@ from pyglui.cygl.utils import draw_polyline as cygl_draw_polyline import glfw + +glfw.ERROR_REPORTING = "raise" + from methods import denormalize, normalize from observable import Observable from plugin import Plugin diff --git a/pupil_src/shared_modules/service_ui.py b/pupil_src/shared_modules/service_ui.py index 78838e860e..b5c544ce6b 100644 --- a/pupil_src/shared_modules/service_ui.py +++ b/pupil_src/shared_modules/service_ui.py @@ -16,6 +16,9 @@ import numpy as np import glfw + +glfw.ERROR_REPORTING = "raise" + import gl_utils from pyglui import ui, cygl from plugin import System_Plugin_Base diff --git a/pupil_src/shared_modules/surface_tracker/gui.py b/pupil_src/shared_modules/surface_tracker/gui.py index 62e0c862a1..3094d046e6 100644 --- a/pupil_src/shared_modules/surface_tracker/gui.py +++ b/pupil_src/shared_modules/surface_tracker/gui.py @@ -22,6 +22,8 @@ import gl_utils import glfw +glfw.ERROR_REPORTING = "raise" + from .surface_marker import Surface_Marker_Type diff --git a/pupil_src/shared_modules/system_graphs.py b/pupil_src/shared_modules/system_graphs.py index 00e6e1b7a7..4a2a4af074 100644 --- a/pupil_src/shared_modules/system_graphs.py +++ b/pupil_src/shared_modules/system_graphs.py @@ -12,6 +12,9 @@ import os import psutil import glfw + +glfw.ERROR_REPORTING = "raise" + import gl_utils from pyglui import ui, graph from pyglui.cygl.utils import RGBA, mix_smooth diff --git a/pupil_src/shared_modules/video_overlay/ui/interactions.py b/pupil_src/shared_modules/video_overlay/ui/interactions.py index 6b3e0416d2..259cf96b22 100644 --- a/pupil_src/shared_modules/video_overlay/ui/interactions.py +++ b/pupil_src/shared_modules/video_overlay/ui/interactions.py @@ -10,6 +10,8 @@ """ import glfw +glfw.ERROR_REPORTING = "raise" + import gl_utils from methods import normalize, denormalize diff --git a/pupil_src/shared_modules/vis_watermark.py b/pupil_src/shared_modules/vis_watermark.py index d27bf018a0..e2e0fcbc5e 100644 --- a/pupil_src/shared_modules/vis_watermark.py +++ b/pupil_src/shared_modules/vis_watermark.py @@ -18,6 +18,9 @@ from pyglui import ui import glfw + +glfw.ERROR_REPORTING = "raise" + from methods import normalize, denormalize import logging diff --git a/pupil_src/shared_modules/visualizer.py b/pupil_src/shared_modules/visualizer.py index c775824660..84ed8b1556 100644 --- a/pupil_src/shared_modules/visualizer.py +++ b/pupil_src/shared_modules/visualizer.py @@ -10,6 +10,9 @@ """ import glfw + +glfw.ERROR_REPORTING = "raise" + import gl_utils from OpenGL.GL import * from platform import system From 093598889d870f30dcce1302574727c8651aacff Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 6 Oct 2020 10:48:25 +0200 Subject: [PATCH 29/57] Make getting eye video files from PupilRecording consistent with other parts of the codebase --- .../video_overlay/plugins/eye_overlay.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pupil_src/shared_modules/video_overlay/plugins/eye_overlay.py b/pupil_src/shared_modules/video_overlay/plugins/eye_overlay.py index 1a100e6e79..e91172b0e1 100644 --- a/pupil_src/shared_modules/video_overlay/plugins/eye_overlay.py +++ b/pupil_src/shared_modules/video_overlay/plugins/eye_overlay.py @@ -97,15 +97,9 @@ def _setup_eye(self, eye_id, prefilled_config): return overlay def _video_path_for_eye(self, eye_id: int) -> str: - rec_dir = self.g_pool.rec_dir - - # Create eye video file filter for eye_id - file_filter = PupilRecording.FileFilter(rec_dir) - file_filter = file_filter.eye_id(eye_id) - file_filter = file_filter.videos() - # Get all eye videos for eye_id - eye_videos = list(file_filter) + recording = PupilRecording(self.g_pool.rec_dir) + eye_videos = list(recording.files().videos().eye_id(eye_id)) if eye_videos: return str(eye_videos[0]) From 4545f5160801f0c0eeb1eceebdd81cec00cb6b5d Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 6 Oct 2020 11:04:42 +0200 Subject: [PATCH 30/57] Make sure all numeric values are finite in render_ellipse --- .../video_overlay/utils/image_manipulation.py | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/pupil_src/shared_modules/video_overlay/utils/image_manipulation.py b/pupil_src/shared_modules/video_overlay/utils/image_manipulation.py index b7be201689..a1ee1ab5d8 100644 --- a/pupil_src/shared_modules/video_overlay/utils/image_manipulation.py +++ b/pupil_src/shared_modules/video_overlay/utils/image_manipulation.py @@ -71,8 +71,11 @@ def apply_to(self, image, parameter, *, is_fake_frame, **kwargs): def render_pupil_2d(self, image, pupil_position): el = pupil_position["ellipse"] - conf = int(pupil_position["confidence"] * 255) - self.render_ellipse(image, el, color=(255, 127, 0, conf)) + conf = pupil_position["confidence"] * 255 + conf = float_to_int(conf) + + if conf > 0: + self.render_ellipse(image, el, color=(255, 127, 0, conf)) def render_pupil_3d(self, image, pupil_position): el = pupil_position["ellipse"] @@ -80,7 +83,8 @@ def render_pupil_3d(self, image, pupil_position): conf = pupil_position["confidence"] * 255 conf = float_to_int(conf) - self.render_ellipse(image, el, color=(0, 0, 255, conf)) + if conf > 0: + self.render_ellipse(image, el, color=(0, 0, 255, conf)) if pupil_position["model_confidence"] <= 0.0: # NOTE: if 'model_confidence' == 0, some values of the 'projected_sphere' @@ -112,14 +116,20 @@ def render_pupil_3d(self, image, pupil_position): ) def render_ellipse(self, image, ellipse, color): + if not all(np.isfinite(ellipse["center"])): + return + if not all(np.isfinite(ellipse["axes"])): + return + if not np.isfinite(ellipse["angle"]): + return + outline = self.get_ellipse_points( ellipse["center"], ellipse["axes"], ellipse["angle"] ) outline = [np.asarray(outline, dtype="i")] cv2.polylines(image, outline, True, color, thickness=1) - center = ellipse["center"] - center = (float_to_int(center[0]), float_to_int(center[1])) + center = (int(ellipse["center"][0]), int(ellipse["center"][1])) cv2.circle(image, center, 5, color, thickness=-1) @staticmethod From 1ca13889d9c8acb4902f387c9caef7c20dd7c1ab Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Tue, 6 Oct 2020 22:17:06 +0200 Subject: [PATCH 31/57] Pass string instead of bytes to glfw.set_clipboard_string --- pupil_src/launchables/eye.py | 2 +- pupil_src/launchables/player.py | 6 ++---- pupil_src/launchables/world.py | 6 ++---- pupil_src/shared_modules/service_ui.py | 4 +--- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index f62ad6504c..6e0f697cce 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -259,7 +259,7 @@ def consume_events_and_render_buffer(): user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.set_clipboard_string(main_window, user_input.clipboard.encode()) + glfw.set_clipboard_string(main_window, user_input.clipboard) for button, action, mods in user_input.buttons: x, y = glfw.get_cursor_pos(main_window) diff --git a/pupil_src/launchables/player.py b/pupil_src/launchables/player.py index 21266ee8ae..b6aa076c07 100644 --- a/pupil_src/launchables/player.py +++ b/pupil_src/launchables/player.py @@ -202,7 +202,7 @@ def consume_events_and_render_buffer(): user_input = g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.set_clipboard_string(main_window, user_input.clipboard.encode()) + glfw.set_clipboard_string(main_window, user_input.clipboard) for b in user_input.buttons: button, action, mods = b @@ -706,9 +706,7 @@ def handle_notifications(n): user_input = g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.set_clipboard_string( - main_window, user_input.clipboard.encode() - ) + glfw.set_clipboard_string(main_window, user_input.clipboard) for b in user_input.buttons: button, action, mods = b diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index 6089d80904..7f75f9421a 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -343,7 +343,7 @@ def consume_events_and_render_buffer(): user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.set_clipboard_string(main_window, user_input.clipboard.encode()) + glfw.set_clipboard_string(main_window, user_input.clipboard) for button, action, mods in user_input.buttons: x, y = glfw.get_cursor_pos(main_window) @@ -768,9 +768,7 @@ def window_should_update(): user_input = g_pool.gui.update() if user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.set_clipboard_string( - main_window, user_input.clipboard.encode() - ) + glfw.set_clipboard_string(main_window, user_input.clipboard) for button, action, mods in user_input.buttons: x, y = glfw.get_cursor_pos(main_window) diff --git a/pupil_src/shared_modules/service_ui.py b/pupil_src/shared_modules/service_ui.py index b5c544ce6b..9c286e79f0 100644 --- a/pupil_src/shared_modules/service_ui.py +++ b/pupil_src/shared_modules/service_ui.py @@ -200,9 +200,7 @@ def update_ui(self): user_input = self.g_pool.gui.update() if user_input.clipboard and user_input.clipboard != clipboard: # only write to clipboard if content changed - glfw.set_clipboard_string( - self.g_pool.main_window, user_input.clipboard.encode() - ) + glfw.set_clipboard_string(self.g_pool.main_window, user_input.clipboard) glfw.swap_buffers(self.g_pool.main_window) else: From 50d42ca6628a42173f111fc543fc8dfed8468401 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Wed, 7 Oct 2020 12:14:45 +0200 Subject: [PATCH 32/57] Update default Pupil Cam1 ID2 intrinsics with new wide-angle intrinsics --- pupil_src/shared_modules/camera_models.py | 52 ++++++++++++++--------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/pupil_src/shared_modules/camera_models.py b/pupil_src/shared_modules/camera_models.py index 7d8fa26701..379fde6f0a 100644 --- a/pupil_src/shared_modules/camera_models.py +++ b/pupil_src/shared_modules/camera_models.py @@ -26,52 +26,64 @@ # setup. Its always better to estimate intrinsics for each camera again. default_intrinsics = { "Pupil Cam1 ID2": { + "version": 1, "(640, 480)": { "dist_coefs": [ [ - -0.4261945257015305, - 0.18094740350081978, - 0.0007881996581097361, - 0.00026392537649318074, - -0.0367144553787145, + -0.2430487205352619, + 0.1623502095383119, + 0.0001632500987373085, + 8.322130878440475e-05, + 0.017859803336754784, + 0.1969284124154412, + 0.00577741263771627, + 0.09892258337410824, ] ], "camera_matrix": [ - [406.74054872359386, 0.0, 332.0196776862145], - [0.0, 392.27339466867005, 242.29314229816816], + [395.60662814306596, 0.0, 316.72212558212516], + [0.0, 395.56975615889445, 259.206579702132], [0.0, 0.0, 1.0], ], + "resolution": [640, 480], "cam_type": "radial", }, "(1280, 720)": { "dist_coefs": [ [ - -0.43738542863224966, - 0.190570781428104, - -0.00125233833830639, - 0.0018723428760170056, - -0.039219091259637684, + -0.3758628065070806, + 0.1643326166951343, + 0.00012182540692089567, + 0.00013422608638039466, + 0.03343691733865076, + 0.08235235770849726, + -0.08225804883227375, + 0.14463365333602152, ] ], "camera_matrix": [ - [829.3510515270362, 0.0, 659.9293047259697], - [0.0, 799.5709408845464, 373.0776462356668], + [794.3311439869655, 0.0, 633.0104437728625], + [0.0, 793.5290139393004, 397.36927353414865], [0.0, 0.0, 1.0], ], + "resolution": [1280, 720], "cam_type": "radial", }, "(1920, 1080)": { "dist_coefs": [ - [-0.1804359422372346], - [0.042312699050507684], - [-0.048304496525298606], - [0.022210236517363622], + [ + -0.13648546769272826, + -0.0033787366635030644, + -0.002343859061730869, + 0.001926274947199097, + ] ], "camera_matrix": [ - [843.364676204713, 0.0, 983.8920955744197], - [0.0, 819.1042187528645, 537.1633514857654], + [793.8052697386686, 0.0, 953.2237035923064], + [0.0, 792.3104221704713, 572.5036513432223], [0.0, 0.0, 1.0], ], + "resolution": [1920, 1080], "cam_type": "fisheye", }, }, From 33100a8fa707fae76e7850f4400ba416c590b0ba Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Thu, 8 Oct 2020 11:55:43 +0200 Subject: [PATCH 33/57] Remove duplicated resolution values --- pupil_src/shared_modules/camera_models.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pupil_src/shared_modules/camera_models.py b/pupil_src/shared_modules/camera_models.py index 379fde6f0a..9f1ac82ea6 100644 --- a/pupil_src/shared_modules/camera_models.py +++ b/pupil_src/shared_modules/camera_models.py @@ -45,7 +45,6 @@ [0.0, 395.56975615889445, 259.206579702132], [0.0, 0.0, 1.0], ], - "resolution": [640, 480], "cam_type": "radial", }, "(1280, 720)": { @@ -66,7 +65,6 @@ [0.0, 793.5290139393004, 397.36927353414865], [0.0, 0.0, 1.0], ], - "resolution": [1280, 720], "cam_type": "radial", }, "(1920, 1080)": { @@ -83,7 +81,6 @@ [0.0, 792.3104221704713, 572.5036513432223], [0.0, 0.0, 1.0], ], - "resolution": [1920, 1080], "cam_type": "fisheye", }, }, From ee4e7fb802277b4d0836240a29bd597d47dee74b Mon Sep 17 00:00:00 2001 From: Patrick Faion Date: Fri, 9 Oct 2020 13:28:06 +0200 Subject: [PATCH 34/57] Remove pye3d debug code --- .../pupil_detector_plugins/pye3d_plugin.py | 71 ++++++++----------- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py index dc02b982fd..0b4f4e41af 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py @@ -12,7 +12,6 @@ from pye3d.detector_3d import Detector3D from pyglui import ui -import pyqtgraph as pq from .detector_base_plugin import PupilDetectorPlugin from .visualizer_2d import draw_eyeball_outline, draw_pupil_outline, draw_ellipse @@ -37,9 +36,6 @@ def __init__(self, g_pool): g_pool, self.detector.settings["focal_length"] ) - self.data = [] - self.ts = [] - def detect(self, frame, **kwargs): previous_detection_results = kwargs.get("previous_detection_results", []) for datum in previous_detection_results: @@ -51,7 +47,9 @@ def detect(self, frame, **kwargs): raise RuntimeError("No 2D detection result! Needed for pye3D!") datum_2d["raw_edges"] = [] - result = self.detector.update_and_detect(datum_2d, frame.gray, debug=True) + result = self.detector.update_and_detect( + datum_2d, frame.gray, debug=self.is_debug_window_open + ) eye_id = self.g_pool.eye_id result["timestamp"] = frame.timestamp @@ -59,23 +57,6 @@ def detect(self, frame, **kwargs): result["id"] = eye_id result["method"] = "3d c++" - if result["confidence"] > 0.6: - hist = 400 - self.data.append(result["diameter_3d"]) - self.ts.append(frame.timestamp) - self.data = self.data[-hist:] - self.ts = self.ts[-hist:] - - global plotWidget - try: - plotWidget - except NameError: - plotWidget = pq.plot(title=f"Test {self.g_pool.eye_id}") - - plotWidget.clear() - plotWidget.plot(self.ts, self.data) - plotWidget.setYRange(0.5, 4.5) - return result def on_notify(self, notification): @@ -107,27 +88,31 @@ def init_ui(self): def gl_display(self): self.debug_window_update() - if self._recent_detection_result: - # draw_eyeball_outline(self._recent_detection_result) - # draw_pupil_outline(self._recent_detection_result) - result = self._recent_detection_result - debug_info = result["debug_info"] - - draw_ellipse( - ellipse=debug_info["projected_ultra_long_term"], - rgba=(0.5, 0, 0, 1), - thickness=2, - ) - draw_ellipse( - ellipse=debug_info["projected_long_term"], - rgba=(0.8, 0.8, 0, 1), - thickness=2, - ) - draw_ellipse( - ellipse=debug_info["projected_short_term"], - rgba=(0, 1, 0, 1), - thickness=2, - ) + result = self._recent_detection_result + if result is not None: + if not self.is_debug_window_open: + # normal drawing + draw_eyeball_outline(result) + draw_pupil_outline(result) + + elif "debug_info" in result: + # debug drawing + debug_info = result["debug_info"] + draw_ellipse( + ellipse=debug_info["projected_ultra_long_term"], + rgba=(0.5, 0, 0, 1), + thickness=2, + ) + draw_ellipse( + ellipse=debug_info["projected_long_term"], + rgba=(0.8, 0.8, 0, 1), + thickness=2, + ) + draw_ellipse( + ellipse=debug_info["projected_short_term"], + rgba=(0, 1, 0, 1), + thickness=2, + ) def cleanup(self): self.debug_window_close() # if we change detectors, be sure debug window is also closed From 254dd6ee7c1d0c0642b725919208858434ef8557 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 14:26:21 +0200 Subject: [PATCH 35/57] Add NamedTuple for cache relevant detector parameters --- .../surface_tracker/surface_tracker_offline.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py index d5f1571084..c690b320f8 100644 --- a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py +++ b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py @@ -15,6 +15,7 @@ import os import platform import time +import typing as T import cv2 import numpy as np @@ -51,6 +52,12 @@ mp_context = multiprocessing.get_context() +class _CacheRelevantDetectorParams(T.NamedTuple): + inverted_markers: bool + quad_decimate: float + sharpening: float + + class Surface_Tracker_Offline(Observable, Surface_Tracker, Plugin): """ The Surface_Tracker_Offline does marker based AOI tracking in a recording. All From 3238564a1f08e2116725ede71a75ec4e45dd4ba7 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 14:36:18 +0200 Subject: [PATCH 36/57] _init_marker_cache: Better variable naming `previous_cache` is a dict, while `cache` was a list. --- .../surface_tracker/surface_tracker_offline.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py index c690b320f8..e140230ae9 100644 --- a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py +++ b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py @@ -142,21 +142,23 @@ def _init_marker_detection_modes(self): self.marker_detector.marker_detector_mode = marker_detector_mode def _init_marker_cache(self): - previous_cache = file_methods.Persistent_Dict( + previous_cache_config = file_methods.Persistent_Dict( os.path.join(self.g_pool.rec_dir, "square_marker_cache") ) - version = previous_cache.get("version", 0) - cache = previous_cache.get("marker_cache_unfiltered", None) + version = previous_cache_config.get("version", 0) self._set_detector_params_from_previous_cache(previous_cache) + cached_markers_unfiltered = previous_cache_config.get( + "marker_cache_unfiltered", None + ) - if cache is None: + if cached_markers_unfiltered is None: self._recalculate_marker_cache() elif version != self.MARKER_CACHE_VERSION: logger.debug("Marker cache version missmatch. Rebuilding marker cache.") self._recalculate_marker_cache() else: marker_cache_unfiltered = [] - for markers in cache: + for markers in cached_markers_unfiltered: # Loaded markers are either False, [] or a list of dictionaries. We # need to convert the dictionaries into Surface_Marker objects. if markers: From cd658804193f44e8ed9906f74107d159a189693a Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 14:38:34 +0200 Subject: [PATCH 37/57] Always recalculate cache with current configuration Fixes inverted legacy marker detection --- .../surface_tracker/surface_tracker_offline.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py index e140230ae9..1a70a28a0d 100644 --- a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py +++ b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py @@ -146,7 +146,6 @@ def _init_marker_cache(self): os.path.join(self.g_pool.rec_dir, "square_marker_cache") ) version = previous_cache_config.get("version", 0) - self._set_detector_params_from_previous_cache(previous_cache) cached_markers_unfiltered = previous_cache_config.get( "marker_cache_unfiltered", None ) @@ -172,12 +171,20 @@ def _init_marker_cache(self): self._recalculate_marker_cache(previous_state=marker_cache_unfiltered) logger.debug("Restored previous marker cache.") - def _set_detector_params_from_previous_cache(self, previous_cache): - self.inverted_markers = previous_cache.get("inverted_markers", False) - self.quad_decimate = previous_cache.get("quad_decimate", APRILTAG_HIGH_RES_ON) - self.sharpening = previous_cache.get("sharpening", APRILTAG_SHARPENING_ON) + def _set_detector_params(self, params: _CacheRelevantDetectorParams): + self.inverted_markers = params.inverted_markers + self.quad_decimate = params.quad_decimate + self.sharpening = params.sharpening + + def _cache_relevant_params_from_controller(self) -> _CacheRelevantDetectorParams: + return _CacheRelevantDetectorParams( + inverted_markers=self.marker_detector.inverted_markers, + quad_decimate=self.marker_detector.apriltag_quad_decimate, + sharpening=self.marker_detector.apriltag_decode_sharpening, + ) def _recalculate_marker_cache(self, previous_state=None): + self._set_detector_params(self._cache_relevant_params_from_controller()) if previous_state is None: previous_state = [None for _ in self.g_pool.timestamps] From 5cf9ac0cfaa7164251097daf892e5bd1ded1c289 Mon Sep 17 00:00:00 2001 From: Patrick Faion Date: Fri, 9 Oct 2020 14:54:00 +0200 Subject: [PATCH 38/57] Handle camera model changes --- .../pupil_detector_plugins/pye3d_plugin.py | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py index 0b4f4e41af..65cc2d9288 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py @@ -10,7 +10,7 @@ """ import logging -from pye3d.detector_3d import Detector3D +from pye3d.detector_3d import Detector3D, CameraModel from pyglui import ui from .detector_base_plugin import PupilDetectorPlugin @@ -29,14 +29,44 @@ class Pye3DPlugin(PupilDetectorPlugin): identifier = "3d" order = 0.101 - def __init__(self, g_pool): - super().__init__(g_pool) - self.detector = Detector3D() - self.debugVisualizer3D = Eye_Visualizer( - g_pool, self.detector.settings["focal_length"] + def __init__(self, g_pool=None): + super().__init__(g_pool=g_pool) + self.camera = CameraModel( + focal_length=self.g_pool.capture.intrinsics.focal_length, + resolution=self.g_pool.capture.intrinsics.resolution, ) + self.detector = Detector3D(camera=self.camera) + self.debugVisualizer3D = Eye_Visualizer(self.g_pool, self.camera.focal_length) + + def _process_camera_changes(self): + camera = CameraModel( + focal_length=self.g_pool.capture.intrinsics.focal_length, + resolution=self.g_pool.capture.intrinsics.resolution, + ) + if self.camera == camera: + return + + logger.debug(f"Camera model change detected: {camera}. Resetting 3D detector.") + self.camera = camera + self.detector.reset_camera(self.camera) + + # Debug window also depends on focal_length, need to replace it with a new + # instance. Make sure debug window is closed at this point or we leak the opengl + # window. + debug_window_was_opened = self.is_debug_window_open + self.debug_window_close() + self.debugVisualizer3D = Eye_Visualizer(self.g_pool, self.camera.focal_length) + if debug_window_was_opened: + self.debug_window_open() + + def on_resolution_change(self, old_size, new_size): + # TODO: the logic for old 2D/3D resetting does not fit here anymore, but was + # included in the PupilDetectorPlugin base class. This needs some cleaning up. + pass def detect(self, frame, **kwargs): + self._process_camera_changes() + previous_detection_results = kwargs.get("previous_detection_results", []) for datum in previous_detection_results: if datum.get("method", "") == "2d c++": @@ -80,7 +110,7 @@ def init_ui(self): self.menu.label = self.pretty_class_name self.menu.append(ui.Button("Reset 3D model", self.reset_model)) - self.menu.append(ui.Button("Open debug window", self.debug_window_toggle)) + self.menu.append(ui.Button("Toggle debug window", self.debug_window_toggle)) # self.menu.append( # ui.Switch(TODO, label="Freeze model") From 9967f80b77e79a939001187e3a3cf2a5e41279ff Mon Sep 17 00:00:00 2001 From: Patrick Faion Date: Fri, 9 Oct 2020 14:55:21 +0200 Subject: [PATCH 39/57] Improve TODO message --- .../shared_modules/pupil_detector_plugins/pye3d_plugin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py index 65cc2d9288..4139cd26f1 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py @@ -73,7 +73,8 @@ def detect(self, frame, **kwargs): datum_2d = datum break else: - # TODO: make this more stable! + # TODO: Should we handle this more gracefully? Can this even happen? What + # could we return in that case? raise RuntimeError("No 2D detection result! Needed for pye3D!") datum_2d["raw_edges"] = [] From 00f116b525416e44ccc7744cfe32ee3de94eabde Mon Sep 17 00:00:00 2001 From: Patrick Faion Date: Fri, 9 Oct 2020 15:03:54 +0200 Subject: [PATCH 40/57] Remove unused raw_edges key in data --- pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py index 4139cd26f1..32f8ca7de9 100644 --- a/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py +++ b/pupil_src/shared_modules/pupil_detector_plugins/pye3d_plugin.py @@ -77,7 +77,6 @@ def detect(self, frame, **kwargs): # could we return in that case? raise RuntimeError("No 2D detection result! Needed for pye3D!") - datum_2d["raw_edges"] = [] result = self.detector.update_and_detect( datum_2d, frame.gray, debug=self.is_debug_window_open ) From b16da3a360838b087854b26de17f5af71f288dc4 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 16:50:52 +0200 Subject: [PATCH 41/57] MarkerDetectorMode: Use typing.NamedTuple --- .../surface_tracker/surface_marker_detector.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pupil_src/shared_modules/surface_tracker/surface_marker_detector.py b/pupil_src/shared_modules/surface_tracker/surface_marker_detector.py index 7e277e47f6..a87d74a20a 100644 --- a/pupil_src/shared_modules/surface_tracker/surface_marker_detector.py +++ b/pupil_src/shared_modules/surface_tracker/surface_marker_detector.py @@ -13,7 +13,6 @@ import enum import logging import typing as T -from collections import namedtuple import square_marker_detect import pupil_apriltags @@ -47,11 +46,10 @@ class ApriltagFamily(enum.Enum): tagStandard52h13 = "tagStandard52h13" -# TODO: Use T.NamedTuple as soon as we increase Python version requirement to 3.6.1+ -_MarkerDetectorMode = namedtuple("_MarkerDetectorMode", ["marker_type", "family"]) +class MarkerDetectorMode(T.NamedTuple): + marker_type: Surface_Marker_Type + family: T.Optional[str] - -class MarkerDetectorMode(_MarkerDetectorMode): @classmethod def all_supported_cases(cls) -> T.Set["MarkerDetectorMode"]: all_square = {cls(MarkerType.SQUARE_MARKER, None)} From 90b6431b3353cbb421849a0c695c88df1866c15d Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 16:51:21 +0200 Subject: [PATCH 42/57] Add marker_detection_callable.from_detector --- .../shared_modules/surface_tracker/offline_utils.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pupil_src/shared_modules/surface_tracker/offline_utils.py b/pupil_src/shared_modules/surface_tracker/offline_utils.py index 807e524b30..6103c44a4b 100644 --- a/pupil_src/shared_modules/surface_tracker/offline_utils.py +++ b/pupil_src/shared_modules/surface_tracker/offline_utils.py @@ -14,6 +14,18 @@ class marker_detection_callable(MarkerDetectorController): + @classmethod + def from_detector(cls, detector: MarkerDetectorController, marker_min_perimeter): + return cls( + marker_detector_mode=detector.marker_detector_mode, + marker_min_perimeter=marker_min_perimeter, + square_marker_inverted_markers=detector.inverted_markers, + square_marker_use_online_mode=False, + apriltag_nthreads=detector._apriltag_nthreads, + apriltag_quad_decimate=detector.apriltag_quad_decimate, + apriltag_decode_sharpening=detector.apriltag_decode_sharpening, + ) + def __call__(self, frame): return self.detect_markers(gray_img=frame.gray, frame_index=frame.index) From b8ba2fd0b31139826b2777aeff324835db97761c Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 16:58:44 +0200 Subject: [PATCH 43/57] Load cache-relevant params from cache --- .../surface_tracker_offline.py | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py index 1a70a28a0d..1763f16ad0 100644 --- a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py +++ b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py @@ -82,8 +82,6 @@ def __init__(self, g_pool, *args, **kwargs): self.last_cache_update_ts = time.perf_counter() self.CACHE_UPDATE_INTERVAL_SEC = 5 - self._init_marker_detection_modes() - self.gaze_on_surf_buffer = None self.gaze_on_surf_buffer_filler = None @@ -122,24 +120,26 @@ def ui_info_text(self): def supported_heatmap_modes(self): return [Heatmap_Mode.WITHIN_SURFACE, Heatmap_Mode.ACROSS_SURFACES] - def _init_marker_detection_modes(self): - # This method should be called after `_init_marker_cache` to ensure that the cache is filled in. - assert self.marker_cache is not None + @staticmethod + def _marker_detector_mode_from_cache( + marker_cache, + ) -> T.Optional[MarkerDetectorMode]: + assert marker_cache is not None # Filter out non-filled frames where the cache entry is None. # Chain the remaining entries (which are lists) to get a flat sequence. - filled_out_marker_cache = filter(lambda x: x is not None, self.marker_cache) + filled_out_marker_cache = filter(lambda x: x is not None, marker_cache) cached_surface_marker_sequence = itertools.chain.from_iterable( filled_out_marker_cache ) - # Get the first surface marker from the sequence, and set the detection mode according to it. - first_cached_surface_marker = next(cached_surface_marker_sequence, None) - if first_cached_surface_marker is not None: - marker_detector_mode = MarkerDetectorMode.from_marker( - first_cached_surface_marker - ) - self.marker_detector.marker_detector_mode = marker_detector_mode + # Get the first surface marker from the sequence, and set the detection mode + # according to it. + first_cached_surface_marker_args = next(cached_surface_marker_sequence, None) + if first_cached_surface_marker_args is not None: + marker = Surface_Marker.deserialize(first_cached_surface_marker_args) + marker_detector_mode = MarkerDetectorMode.from_marker(marker) + return marker_detector_mode def _init_marker_cache(self): previous_cache_config = file_methods.Persistent_Dict( @@ -175,6 +175,25 @@ def _set_detector_params(self, params: _CacheRelevantDetectorParams): self.inverted_markers = params.inverted_markers self.quad_decimate = params.quad_decimate self.sharpening = params.sharpening + @staticmethod + def _cache_relevant_params_from_cache( + previous_cache, + ) -> T.Optional[_CacheRelevantDetectorParams]: + marker_cache_unfiltered = previous_cache.get("marker_cache_unfiltered", None) + if marker_cache_unfiltered is None: + return + + mode = Surface_Tracker_Offline._marker_detector_mode_from_cache( + marker_cache_unfiltered + ) + if mode is None: + return + + return _CacheRelevantDetectorParams( + inverted_markers=previous_cache.get("inverted_markers", False), + quad_decimate=previous_cache.get("quad_decimate", APRILTAG_HIGH_RES_ON), + sharpening=previous_cache.get("sharpening", APRILTAG_SHARPENING_ON), + ) def _cache_relevant_params_from_controller(self) -> _CacheRelevantDetectorParams: return _CacheRelevantDetectorParams( From f091cadfd7e1314bf2b779b541932e6bce442abc Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 16:59:37 +0200 Subject: [PATCH 44/57] Add detector mode to cache-relevant params --- .../shared_modules/surface_tracker/surface_tracker_offline.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py index 1763f16ad0..a0af9afd05 100644 --- a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py +++ b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py @@ -53,6 +53,7 @@ class _CacheRelevantDetectorParams(T.NamedTuple): + mode: MarkerDetectorMode inverted_markers: bool quad_decimate: float sharpening: float @@ -190,6 +191,7 @@ def _cache_relevant_params_from_cache( return return _CacheRelevantDetectorParams( + mode=mode, inverted_markers=previous_cache.get("inverted_markers", False), quad_decimate=previous_cache.get("quad_decimate", APRILTAG_HIGH_RES_ON), sharpening=previous_cache.get("sharpening", APRILTAG_SHARPENING_ON), @@ -197,6 +199,7 @@ def _cache_relevant_params_from_cache( def _cache_relevant_params_from_controller(self) -> _CacheRelevantDetectorParams: return _CacheRelevantDetectorParams( + mode=self.marker_detector.marker_detector_mode, inverted_markers=self.marker_detector.inverted_markers, quad_decimate=self.marker_detector.apriltag_quad_decimate, sharpening=self.marker_detector.apriltag_decode_sharpening, From 6f1a131405d617882ef4e72152691772789aeccd Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 17:00:55 +0200 Subject: [PATCH 45/57] Use controller as storage for current configuration --- .../surface_tracker/surface_tracker_offline.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py index a0af9afd05..e784ee4889 100644 --- a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py +++ b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py @@ -173,9 +173,12 @@ def _init_marker_cache(self): logger.debug("Restored previous marker cache.") def _set_detector_params(self, params: _CacheRelevantDetectorParams): - self.inverted_markers = params.inverted_markers - self.quad_decimate = params.quad_decimate - self.sharpening = params.sharpening + self.marker_detector._marker_detector_mode = params.mode + self.marker_detector._square_marker_inverted_markers = params.inverted_markers + self.marker_detector._apriltag_quad_decimate = params.quad_decimate + self.marker_detector._apriltag_decode_sharpening = params.sharpening + self.marker_detector.init_detector() + @staticmethod def _cache_relevant_params_from_cache( previous_cache, @@ -613,7 +616,9 @@ def _save_marker_cache(self): self.marker_cache_unfiltered ) marker_cache_file["version"] = self.MARKER_CACHE_VERSION - marker_cache_file["inverted_markers"] = self.inverted_markers - marker_cache_file["quad_decimate"] = self.quad_decimate - marker_cache_file["sharpening"] = self.sharpening + + current_config = self._cache_relevant_params_from_controller() + marker_cache_file["inverted_markers"] = current_config.inverted_markers + marker_cache_file["quad_decimate"] = current_config.quad_decimate + marker_cache_file["sharpening"] = current_config.sharpening marker_cache_file.save() From 7cb79f72dafaa4675622da872f9023ba4cdae004 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 17:01:17 +0200 Subject: [PATCH 46/57] Initialize background detector based on foreground detector --- .../surface_tracker/surface_tracker_offline.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py index e784ee4889..0e8bad554d 100644 --- a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py +++ b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py @@ -225,15 +225,11 @@ def _recalculate_marker_cache(self, previous_state=None): if self.cache_filler is not None: self.cache_filler.cancel() + self.cache_filler = background_tasks.background_video_processor( self.g_pool.capture.source_path, - offline_utils.marker_detection_callable( - marker_detector_mode=self.marker_detector.marker_detector_mode, - marker_min_perimeter=self.CACHE_MIN_MARKER_PERIMETER, - square_marker_inverted_markers=self.inverted_markers, - square_marker_use_online_mode=False, - apriltag_quad_decimate=self.quad_decimate, - apriltag_decode_sharpening=self.sharpening, + offline_utils.marker_detection_callable.from_detector( + self.marker_detector, self.CACHE_MIN_MARKER_PERIMETER ), list(self.marker_cache), self.cache_seek_idx, From 8fcdf5b429da5565f6cffbfe2da75334b623c66b Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Fri, 9 Oct 2020 17:04:21 +0200 Subject: [PATCH 47/57] Ensure consistent marker detector configuration Fixes #1806 The issue comes up if the plugins session settings conflict with the previous cache. Preferable behaviour should be: - If there is no previous cache use the plugin's current settings - If there is a previous cache - if cache is of correct version use cache config - if cache is of incorrect version use plugin's current settings - If user changes plugin settings redetect with plugin's current settings --- .../surface_tracker_offline.py | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py index 0e8bad554d..901e4f3dd6 100644 --- a/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py +++ b/pupil_src/shared_modules/surface_tracker/surface_tracker_offline.py @@ -147,18 +147,18 @@ def _init_marker_cache(self): os.path.join(self.g_pool.rec_dir, "square_marker_cache") ) version = previous_cache_config.get("version", 0) - cached_markers_unfiltered = previous_cache_config.get( - "marker_cache_unfiltered", None - ) - if cached_markers_unfiltered is None: - self._recalculate_marker_cache() + previous_params = self._cache_relevant_params_from_cache(previous_cache_config) + current_params = self._cache_relevant_params_from_controller() + + if previous_params is None: + self._recalculate_marker_cache(parameters=current_params) elif version != self.MARKER_CACHE_VERSION: logger.debug("Marker cache version missmatch. Rebuilding marker cache.") - self._recalculate_marker_cache() + self._recalculate_marker_cache(parameters=current_params) else: marker_cache_unfiltered = [] - for markers in cached_markers_unfiltered: + for markers in previous_cache_config["marker_cache_unfiltered"]: # Loaded markers are either False, [] or a list of dictionaries. We # need to convert the dictionaries into Surface_Marker objects. if markers: @@ -169,7 +169,9 @@ def _init_marker_cache(self): ] marker_cache_unfiltered.append(markers) - self._recalculate_marker_cache(previous_state=marker_cache_unfiltered) + self._recalculate_marker_cache( + parameters=previous_params, previous_state=marker_cache_unfiltered + ) logger.debug("Restored previous marker cache.") def _set_detector_params(self, params: _CacheRelevantDetectorParams): @@ -208,8 +210,11 @@ def _cache_relevant_params_from_controller(self) -> _CacheRelevantDetectorParams sharpening=self.marker_detector.apriltag_decode_sharpening, ) - def _recalculate_marker_cache(self, previous_state=None): - self._set_detector_params(self._cache_relevant_params_from_controller()) + def _recalculate_marker_cache( + self, parameters: _CacheRelevantDetectorParams, previous_state=None + ): + # Ensures consistency across foreground and background detectors + self._set_detector_params(parameters) if previous_state is None: previous_state = [None for _ in self.g_pool.timestamps] @@ -519,7 +524,8 @@ def on_notify(self, notification): super().on_notify(notification) if notification["subject"] == "surface_tracker.marker_detection_params_changed": - self._recalculate_marker_cache() + current_params = self._cache_relevant_params_from_controller() + self._recalculate_marker_cache(parameters=current_params) elif notification["subject"] == "surface_tracker.marker_min_perimeter_changed": marker_type = self.marker_detector.marker_detector_mode.marker_type From 0f5a72ade3ad9f18e6a396e414fe81c5ddcd5513 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Mon, 12 Oct 2020 11:37:13 +0200 Subject: [PATCH 48/57] Fix an edge case in _fix_negative_time_jumps() when the last TS is zero When the last timestamp is zero, `timestamps[invalid_idc + 2]` causes an index error. As a workaround, we handle this edge case separately. --- pupil_src/shared_modules/video_capture/utils.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pupil_src/shared_modules/video_capture/utils.py b/pupil_src/shared_modules/video_capture/utils.py index f4879f660c..cf5d3380db 100644 --- a/pupil_src/shared_modules/video_capture/utils.py +++ b/pupil_src/shared_modules/video_capture/utils.py @@ -263,9 +263,25 @@ def _fix_negative_time_jumps(timestamps: np.ndarray) -> np.ndarray: # TODO: what if adjacent timestamps are negative/zero as well? time_diff = np.diff(timestamps) invalid_idc = np.flatnonzero(time_diff < 0) + + # Check edge case where last timestamp causes negative jump + last_ts_is_invalid = invalid_idc[-1] == timestamps.shape[0] - 2 + if last_ts_is_invalid: + # We cannot calculate the mean of adjacent timestamps as the last timestamp + # only has a single neighbour. Therefore, we will exclude it from the + # general time interpolation and handle this special case afterward. + invalid_idc = invalid_idc[:-1] + timestamps[invalid_idc + 1] = np.mean( (timestamps[invalid_idc + 2], timestamps[invalid_idc]), axis=0 ) + + if last_ts_is_invalid: + # After fixing all previous timestamps, we will now fix the last one + last_minus_two, last_minus_one = timestamps[[-3, -2]] + time_diff = last_minus_one - last_minus_two + timestamps[-1] = last_minus_one + time_diff + return timestamps From 1a06262e93cec245ba3e3e081628cf42a60ce3f2 Mon Sep 17 00:00:00 2001 From: Chris Kay Baumann Date: Tue, 6 Oct 2020 14:39:01 +0200 Subject: [PATCH 49/57] Allow observing of monkey patched methods --- pupil_src/shared_modules/observable.py | 128 +++++++++++++------------ pupil_src/tests/test_observable.py | 50 +++++++++- 2 files changed, 114 insertions(+), 64 deletions(-) diff --git a/pupil_src/shared_modules/observable.py b/pupil_src/shared_modules/observable.py index 2ec64c88c6..e83fa6871b 100644 --- a/pupil_src/shared_modules/observable.py +++ b/pupil_src/shared_modules/observable.py @@ -130,9 +130,9 @@ def add_observer(obj, method_name, observer): Observable and use the corresponding method there. """ - observable = _get_wrapper_and_create_if_not_exists(obj, method_name) - observable.add_observer(observer) - _install_protection_descriptor_if_not_exists(obj, method_name) + wrapper = _get_wrapper_and_create_if_not_exists(obj, method_name) + wrapper.add_observer(observer) + _install_protection_descriptor_if_not_exists(wrapper) def _get_wrapper_and_create_if_not_exists(obj, method_name): @@ -152,12 +152,6 @@ def _get_wrapper_and_create_if_not_exists(obj, method_name): f"Attribute '{method_name}' of object {obj} is a class method and, thus, " "cannot be observed!" ) - elif _method_was_modified(obj, method_name): - raise TypeError( - f"Attribute '{method_name}' of object {obj} cannot be observed because it " - "is not part of the original class definition or has been assigned to a " - "method of a different object!" - ) else: return _ObservableMethodWrapper(obj, method_name) @@ -170,27 +164,17 @@ def _is_classmethod(obj, method_name): return False -def _method_was_modified(obj, method_name): - method_in_original_class = hasattr(obj.__class__, method_name) - if not method_in_original_class: - return True - expected_func = getattr(obj.__class__, method_name) - expected_self = obj - - method = getattr(obj, method_name) - bound_func = method.__func__ - bound_self = method.__self__ - - return expected_self is not bound_self or expected_func is not bound_func - - -def _install_protection_descriptor_if_not_exists(obj, method_name): - type_ = type(obj) - already_installed = isinstance( - getattr(type_, method_name), _WrapperProtectionDescriptor - ) +def _install_protection_descriptor_if_not_exists(wrapper): + # we need to get class and method name from the wrapped method, not the observed + # method. Let's say we have objects a = A() and b = B(). We monkey patch a.a = b.b + # and observe a.a. Then we need to install the descriptor for B.b (the wrapped + # method) and not for A.a (the observed method) + wrapped_method = wrapper.get_wrapped_bound_method() + cls_ = type(wrapped_method.__self__) + name = wrapped_method.__func__.__name__ + already_installed = isinstance(getattr(cls_, name), _WrapperProtectionDescriptor) if not already_installed: - setattr(type_, method_name, _WrapperProtectionDescriptor(type_, method_name)) + setattr(cls_, name, _WrapperProtectionDescriptor(cls_, name)) class _WrapperProtectionDescriptor: @@ -272,39 +256,45 @@ def _get_wrapper_or_raise_if_not_exists(obj, method_name): class _ObservableMethodWrapper: def __init__(self, obj, method_name): + wrapped_method = getattr(obj, method_name) + # the wrapper should not block garbage collection by reference counting for the # observable object. Hence, we need to avoid strong references to the object, - # which would lead to cyclic references: - # - The object is only referenced weakly - # - The original wrapped method is only stored as an unbound method + # which would lead to cyclic references. Consequently, the object the wrapper + # belongs to and the original wrapped method are only referenced weakly self._obj_ref = weakref.ref(obj) - self._wrapped_func = getattr(obj.__class__, method_name) + # deref_by_name=False because otherwise we would get the wrapper when + # dereferencing + self._wrapped_method_ref = _WeakReferenceToMethod( + wrapped_method, deref_by_name=False + ) self._method_name = method_name self._observers = [] self._was_removed = False - self._patch_method_to_call_wrapper_instead() - def _patch_method_to_call_wrapper_instead(self): - functools.update_wrapper(self, self._wrapped_func) + self._patch_wrapper_to_look_like_original_method(wrapped_method) + self._patch_object_to_call_wrapper_instead() + + def _patch_wrapper_to_look_like_original_method(self, wrapped_method): + functools.update_wrapper(self, wrapped_method) # functools adds a reference to the wrapped method that we need to delete # to avoid cyclic references self.__wrapped__ = None + + def _patch_object_to_call_wrapper_instead(self): setattr(self._obj_ref(), self._method_name, self) def remove_wrapper(self): try: setattr( - self._obj_ref(), self._method_name, self._get_wrapped_bound_method() + self._obj_ref(), self._method_name, self.get_wrapped_bound_method(), ) except ReplaceWrapperError: pass self._was_removed = True - def _get_wrapped_bound_method(self): - obj = self._obj_ref() - # see https://stackoverflow.com/a/1015405 - original_bound_method = self._wrapped_func.__get__(obj, obj.__class__) - return original_bound_method + def get_wrapped_bound_method(self): + return self._wrapped_method_ref.deref_method() def add_observer(self, observer): # Observers that are bound methods are referenced weakly. That means, @@ -315,7 +305,9 @@ def add_observer(self, observer): # referenced strongly. Otherwise, lambdas or callables would get garbage # collected instantly. if inspect.ismethod(observer): - observer_ref = _WeakReferenceToMethod(observer) + # deref_by_name=True to allow observers to be observed + # (see test case test_observers_can_be_observed for a longer explanation) + observer_ref = _WeakReferenceToMethod(observer, deref_by_name=True) else: observer_ref = _StrongReferenceToCallable(observer) self._observers.append(observer_ref) @@ -339,7 +331,7 @@ def __call__(self, *args, **kwargs): "elsewhere and called via this reference after you " "removed the wrapper!" ) - wrapped_bound_method = self._get_wrapped_bound_method() + wrapped_bound_method = self.get_wrapped_bound_method() try: return wrapped_bound_method(*args, **kwargs) except Exception: @@ -385,42 +377,58 @@ class _WeakReferenceToMethod: # gets deleted instantly with weakref (see https://stackoverflow.com/a/19443624 # for more details). # That's why we store two weak refs, one to the method's object and one to the - # unbound class method. Later, we can get the "actual" method via getattr (see e.g. - # https://stackoverflow.com/a/6975682) - def __init__(self, observer): - self._obj_ref = weakref.ref(observer.__self__) - self._func_ref = weakref.ref(observer.__func__) + # unbound class method. Later, we can get the "actual" method via getattr or by + # using the descriptor interface + def __init__(self, method, deref_by_name): + """ + Args: + method: Bound method being referenced. + deref_by_name (bool): If True, the method is dereferenced by its name, i.e. + if the method was replaced in the meantime by a different one, you would + get the new one when dereferencing. If False, you always get the original method even if it was replaced (if it still exists in memory). + """ + self._obj_ref = weakref.ref(method.__self__) + self._func_ref = weakref.ref(method.__func__) + self._deref_by_name = deref_by_name # Sanity check. Try to dereference method, to make sure that the arguments # are valid. Otherwise, in some cases (e.g. methods starting with '__') # trying to call the method will fail with _ReferenceNoLongerValidError, # and the observer will get silently removed. This check ensures that # the method is valid on creation. - _ = self._deref_method() + _ = self.deref_method() def __call__(self, *args, **kwargs): - try: - method = self._deref_method() - except AttributeError: - raise _ReferenceNoLongerValidError + method = self.deref_method() return method(*args, **kwargs) - def __eq__(self, other_observer): - if inspect.ismethod(other_observer): + def __eq__(self, other): + if inspect.ismethod(other): obj_deref = self._obj_ref() func_deref = self._func_ref() if self._method_still_exists(func_deref, obj_deref): - equal_obj = obj_deref == other_observer.__self__ - equal_func = func_deref == other_observer.__func__ + equal_obj = obj_deref == other.__self__ + equal_func = func_deref == other.__func__ return equal_obj and equal_func else: return False else: return False - def _deref_method(self): + def deref_method(self): obj_deref = self._obj_ref() func_deref = self._func_ref() - return getattr(obj_deref, func_deref.__name__) + if obj_deref is None or func_deref is None: + raise _ReferenceNoLongerValidError + if self._deref_by_name: + # see https://stackoverflow.com/a/6975682) + try: + deref_method = getattr(obj_deref, func_deref.__name__) + except AttributeError: + raise _ReferenceNoLongerValidError from None + else: + # see https://stackoverflow.com/a/1015405 + deref_method = func_deref.__get__(obj_deref, obj_deref.__class__) + return deref_method @staticmethod def _method_still_exists(func_deref, obj_deref): diff --git a/pupil_src/tests/test_observable.py b/pupil_src/tests/test_observable.py index 59f8e6aa28..cd4c3cd4e4 100644 --- a/pupil_src/tests/test_observable.py +++ b/pupil_src/tests/test_observable.py @@ -64,16 +64,26 @@ def test_class_method_is_not_observable(self, observable, observer): with pytest.raises(TypeError): observable.add_observer("class_method", observer) - def test_modified_methods_are_not_observable(self, observable, observer): + def test_monkey_patched_methods_are_observable(self, observable, observer): class FakeClass: def fake_method(self): pass fake_class_instance = FakeClass() - observable.modified_method = fake_class_instance.fake_method + observable.bound_method = fake_class_instance.fake_method - with pytest.raises(TypeError): - observable.add_observer("modified_method", observer) + observable.add_observer("bound_method", observer) + + def test_new_methods_are_observable(self, observable, observer): + class FakeClass: + def fake_method(self): + pass + + fake_class_instance = FakeClass() + # new_method is not part of FakeObservable + observable.new_method = fake_class_instance.fake_method + + observable.add_observer("new_method", observer) class TestDifferentKindsOfObservers: @@ -182,6 +192,19 @@ def test_multiple_observers_are_called(self, observable): # no guarantees for the actual order! assert observer1_called and observer2_called and observer3_called + def test_observers_of_monkey_patched_methods_are_called(self, observable): + observer = mock.Mock() + + class FakeClass: + def fake_method(self, arg1, arg2): + pass + + fake_object = FakeClass() + observable.bound_method_with_arguments = fake_object.fake_method + observable.add_observer("bound_method_with_arguments", observer) + observable.bound_method_with_arguments(1, "test") + observer.assert_called_once_with(1, "test") + class TestWrappedMethodCalls: def test_wrapped_functions_are_called_with_right_arguments(self): @@ -210,6 +233,25 @@ def method(self): assert ret_val == 1 + def test_wrapped_monkey_patched_functions_are_called_with_right_arguments( + self, observable + ): + mock_function = mock.Mock() + + class FakeClass: + # we choose a name that is also in FakeObservable to check that the + # two methods are not confused with each other + def bound_method_with_arguments(self, arg1, arg2): + mock_function(arg1, arg2) + + fake_object = FakeClass() + observable.bound_method_with_arguments = fake_object.bound_method_with_arguments + observable.add_observer("bound_method_with_arguments", lambda arg1, arg2: None) + + observable.bound_method_with_arguments(1, 2) + + mock_function.assert_called_once_with(1, 2) + class TestRemovingObservers: def test_observers_that_are_functions_can_be_removed(self, observable): From 41d2c6ba47ea75f12dce3c605c15693aa5d00004 Mon Sep 17 00:00:00 2001 From: Chris Kay Baumann Date: Thu, 8 Oct 2020 17:16:05 +0200 Subject: [PATCH 50/57] Fix issue when wrapper was the only object referencing the wrapped method --- pupil_src/shared_modules/observable.py | 76 ++++++++++++++------------ pupil_src/tests/test_observable.py | 60 +++++++++++++++++++- 2 files changed, 101 insertions(+), 35 deletions(-) diff --git a/pupil_src/shared_modules/observable.py b/pupil_src/shared_modules/observable.py index e83fa6871b..87d79ba7f9 100644 --- a/pupil_src/shared_modules/observable.py +++ b/pupil_src/shared_modules/observable.py @@ -11,6 +11,7 @@ import functools import inspect +import types import weakref @@ -172,6 +173,10 @@ def _install_protection_descriptor_if_not_exists(wrapper): wrapped_method = wrapper.get_wrapped_bound_method() cls_ = type(wrapped_method.__self__) name = wrapped_method.__func__.__name__ + # this can happen when the method was artificially created like, for example, in + # test_wrapped_monkey_patched_methods_not_referenced_elsewhere_are_called + if not hasattr(cls_, name): + return already_installed = isinstance(getattr(cls_, name), _WrapperProtectionDescriptor) if not already_installed: setattr(cls_, name, _WrapperProtectionDescriptor(cls_, name)) @@ -256,18 +261,28 @@ def _get_wrapper_or_raise_if_not_exists(obj, method_name): class _ObservableMethodWrapper: def __init__(self, obj, method_name): - wrapped_method = getattr(obj, method_name) - # the wrapper should not block garbage collection by reference counting for the # observable object. Hence, we need to avoid strong references to the object, - # which would lead to cyclic references. Consequently, the object the wrapper - # belongs to and the original wrapped method are only referenced weakly + # which would lead to cyclic references: + # - The object is only referenced weakly. This is ok, because the wrapper + # only needs to function as long as the object exists, so there is no need + # to keep it alive with a strong reference. + # - The original wrapped method is only stored as an unbound method + # - In case the originally wrapped method was monkey patched, we also need to + # store the object it belongs to. This object we have to reference strongly + # as the wrapper might be (or become) the only object referencing it. This + # likely causes cyclic references hindering fast garbage collection in many + # cases, but it cannot be avoided. self._obj_ref = weakref.ref(obj) - # deref_by_name=False because otherwise we would get the wrapper when - # dereferencing - self._wrapped_method_ref = _WeakReferenceToMethod( - wrapped_method, deref_by_name=False - ) + + wrapped_method = getattr(obj, method_name) + wrapped_method_self = wrapped_method.__self__ + if wrapped_method_self is obj: + self._wrapped_method_self = None + else: + self._wrapped_method_self = wrapped_method_self + self._wrapped_method_func = wrapped_method.__func__ + self._method_name = method_name self._observers = [] self._was_removed = False @@ -294,7 +309,11 @@ def remove_wrapper(self): self._was_removed = True def get_wrapped_bound_method(self): - return self._wrapped_method_ref.deref_method() + if self._wrapped_method_self is None: + wrapped_method_self = self._obj_ref() + else: + wrapped_method_self = self._wrapped_method_self + return types.MethodType(self._wrapped_method_func, wrapped_method_self) def add_observer(self, observer): # Observers that are bound methods are referenced weakly. That means, @@ -305,9 +324,7 @@ def add_observer(self, observer): # referenced strongly. Otherwise, lambdas or callables would get garbage # collected instantly. if inspect.ismethod(observer): - # deref_by_name=True to allow observers to be observed - # (see test case test_observers_can_be_observed for a longer explanation) - observer_ref = _WeakReferenceToMethod(observer, deref_by_name=True) + observer_ref = _WeakReferenceToMethodByName(observer) else: observer_ref = _StrongReferenceToCallable(observer) self._observers.append(observer_ref) @@ -371,25 +388,20 @@ def __eq__(self, other_observer): return self._observer == other_observer -class _WeakReferenceToMethod: +class _WeakReferenceToMethodByName: # One cannot create weakrefs to bound class methods directly, because Python # returns a new reference each time some method is accessed and that reference # gets deleted instantly with weakref (see https://stackoverflow.com/a/19443624 # for more details). # That's why we store two weak refs, one to the method's object and one to the - # unbound class method. Later, we can get the "actual" method via getattr or by - # using the descriptor interface - def __init__(self, method, deref_by_name): - """ - Args: - method: Bound method being referenced. - deref_by_name (bool): If True, the method is dereferenced by its name, i.e. - if the method was replaced in the meantime by a different one, you would - get the new one when dereferencing. If False, you always get the original method even if it was replaced (if it still exists in memory). - """ + # unbound class method. Later, we can get the "actual" method via getattr. + # The method is dereferenced by its name, i.e. if the method was replaced in the + # meantime by a different one, you would get the new one when dereferencing. + # This is to allow observers to be observed (see test case + # test_observers_can_be_observed for a longer explanation) + def __init__(self, method): self._obj_ref = weakref.ref(method.__self__) self._func_ref = weakref.ref(method.__func__) - self._deref_by_name = deref_by_name # Sanity check. Try to dereference method, to make sure that the arguments # are valid. Otherwise, in some cases (e.g. methods starting with '__') # trying to call the method will fail with _ReferenceNoLongerValidError, @@ -419,15 +431,11 @@ def deref_method(self): func_deref = self._func_ref() if obj_deref is None or func_deref is None: raise _ReferenceNoLongerValidError - if self._deref_by_name: - # see https://stackoverflow.com/a/6975682) - try: - deref_method = getattr(obj_deref, func_deref.__name__) - except AttributeError: - raise _ReferenceNoLongerValidError from None - else: - # see https://stackoverflow.com/a/1015405 - deref_method = func_deref.__get__(obj_deref, obj_deref.__class__) + # see https://stackoverflow.com/a/6975682) + try: + deref_method = getattr(obj_deref, func_deref.__name__) + except AttributeError: + raise _ReferenceNoLongerValidError from None return deref_method @staticmethod diff --git a/pupil_src/tests/test_observable.py b/pupil_src/tests/test_observable.py index cd4c3cd4e4..dd91a63bbd 100644 --- a/pupil_src/tests/test_observable.py +++ b/pupil_src/tests/test_observable.py @@ -10,6 +10,7 @@ """ import gc +import types from unittest import mock import pytest @@ -252,6 +253,52 @@ def bound_method_with_arguments(self, arg1, arg2): mock_function.assert_called_once_with(1, 2) + def test_wrapped_monkey_patched_methods_not_referenced_elsewhere_are_called_part1( + self, observable + ): + mock_function = mock.Mock() + + def patch(obj): + def fake_method(self): + mock_function() + + obj.bound_method = types.MethodType(fake_method, obj) + + patch(observable) + + # This tests that observer wrappers reference the wrapped method strongly. + # If it is only referenced weakly, it will get garbage collected as soon as + # the wrapper replaces obj.bound_method. At this point, obj.bound_method is + # the only reference to this instance of fake_method, because it was only + # defined inside patch(), which just ended. + observable.add_observer("bound_method", lambda: None) + observable.bound_method() + + mock_function.assert_called_once() + + def test_wrapped_monkey_patched_methods_not_referenced_elsewhere_are_called_part2( + self, observable + ): + mock_function = mock.Mock() + + def patch(obj): + class FakeClass: + def fake_method(self): + mock_function() + + fake_object = FakeClass() + obj.bound_method = fake_object.fake_method + + patch(observable) + + # Similarly to part 1 of this test, the monkey patched method is now only + # referenced in observable. What's different is that in this part also the + # class the method belongs to is at risk of being garbage collected. + observable.add_observer("bound_method", lambda: None) + observable.bound_method() + + mock_function.assert_called_once() + class TestRemovingObservers: def test_observers_that_are_functions_can_be_removed(self, observable): @@ -443,7 +490,18 @@ def on_bound_method(self): class TestWrapperProtectionDescriptor: - def test_wrapped_functions_cannot_be_set(self, observable): + def test_wrappers_of_methods_cannot_be_set(self, observable): + observable.add_observer("bound_method", lambda: None) + with pytest.raises(ReplaceWrapperError): + observable.bound_method = 42 + + def test_wrappers_of_monkey_patched_methods_cannot_be_set(self, observable): + class FakeClass: + def fake_method(self): + pass + + fake_object = FakeClass() + observable.bound_method = fake_object.fake_method observable.add_observer("bound_method", lambda: None) with pytest.raises(ReplaceWrapperError): observable.bound_method = 42 From 61604d3df165cde54b140a13e4f17cabd293a387 Mon Sep 17 00:00:00 2001 From: Chris Kay Baumann Date: Mon, 12 Oct 2020 11:46:56 +0200 Subject: [PATCH 51/57] Improve error when observer is private, add test --- pupil_src/shared_modules/observable.py | 18 +++++++++++++----- pupil_src/tests/test_observable.py | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/pupil_src/shared_modules/observable.py b/pupil_src/shared_modules/observable.py index 87d79ba7f9..2ad18dac5e 100644 --- a/pupil_src/shared_modules/observable.py +++ b/pupil_src/shared_modules/observable.py @@ -62,7 +62,7 @@ def add_observer(self, method_name, observer): Args: method_name (String): The name of a bound method to which the observer will be added. Unbound methods (i.e. static and class methods) are NOT - supported. + supported. Additionally, private methods are not supported. observer (Callable): Will be called every time the method is invoked. Raises: @@ -70,7 +70,8 @@ def add_observer(self, method_name, observer): the class TypeError: The attribute specified by method_name is 1) no method, or - 2) a class or static method. + 2) a class or static method, or + 3) a private method. """ add_observer(self, method_name, observer) @@ -407,10 +408,17 @@ def __init__(self, method): # trying to call the method will fail with _ReferenceNoLongerValidError, # and the observer will get silently removed. This check ensures that # the method is valid on creation. - _ = self.deref_method() + try: + _ = self._deref_method() + except _ReferenceNoLongerValidError: + raise TypeError( + f"The method {method} cannot be an observer, because it cannot be " + "referenced by its name. Most likely, you tried to add a private method" + " (starting with __) for which name mangling prevents referencing." + ) def __call__(self, *args, **kwargs): - method = self.deref_method() + method = self._deref_method() return method(*args, **kwargs) def __eq__(self, other): @@ -426,7 +434,7 @@ def __eq__(self, other): else: return False - def deref_method(self): + def _deref_method(self): obj_deref = self._obj_ref() func_deref = self._func_ref() if obj_deref is None or func_deref is None: diff --git a/pupil_src/tests/test_observable.py b/pupil_src/tests/test_observable.py index dd91a63bbd..2cb5972e6f 100644 --- a/pupil_src/tests/test_observable.py +++ b/pupil_src/tests/test_observable.py @@ -152,6 +152,20 @@ def my_function(): observable.bound_method() mock_function.assert_called_once() + def test_private_method_cannot_be_observer(self, observable): + class FakeController: + def __private_method(self): + pass + + controller = FakeController() + with pytest.raises(TypeError): + # in your own class you would just write self.__private_method, + # but here we need to give the mangled name, otherwise python tries to + # access controller._TestDifferentKindsOfObservers__private_method + observable.add_observer( + "bound_method", controller._FakeController__private_method + ) + class TestObserverCalls: def test_observers_are_called_with_the_same_arguments(self, observable): From 7e74cf3ac54bb4a7a5eb0ed155e33332654c75d8 Mon Sep 17 00:00:00 2001 From: Chris Kay Baumann Date: Mon, 12 Oct 2020 14:43:25 +0200 Subject: [PATCH 52/57] protection descriptors also if method not in class definition --- pupil_src/shared_modules/observable.py | 26 +++++++++++++++++++------- pupil_src/tests/test_observable.py | 12 ++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/pupil_src/shared_modules/observable.py b/pupil_src/shared_modules/observable.py index 2ad18dac5e..12f34e0bd7 100644 --- a/pupil_src/shared_modules/observable.py +++ b/pupil_src/shared_modules/observable.py @@ -174,11 +174,14 @@ def _install_protection_descriptor_if_not_exists(wrapper): wrapped_method = wrapper.get_wrapped_bound_method() cls_ = type(wrapped_method.__self__) name = wrapped_method.__func__.__name__ - # this can happen when the method was artificially created like, for example, in - # test_wrapped_monkey_patched_methods_not_referenced_elsewhere_are_called - if not hasattr(cls_, name): - return - already_installed = isinstance(getattr(cls_, name), _WrapperProtectionDescriptor) + if hasattr(cls_, name): + already_installed = isinstance( + getattr(cls_, name), _WrapperProtectionDescriptor + ) + else: + # this can happen when the method was artificially created like, for example, in + # test_wrapped_monkey_patched_methods_not_referenced_elsewhere_are_called + already_installed = False if not already_installed: setattr(cls_, name, _WrapperProtectionDescriptor(cls_, name)) @@ -190,7 +193,7 @@ class _WrapperProtectionDescriptor: """ def __init__(self, type, name): - self.original = getattr(type, name) + self.original = getattr(type, name, None) assert not inspect.isdatadescriptor(self.original) self.name = name @@ -203,10 +206,19 @@ def __get__(self, obj, type=None): # 3.) original is in object's class or some of its parents: We don't need to # worry about if it's in the class or some parent, this is covered by # getattr() in __init__ + # 4.) if there is no original we raise the correct AttributeError if obj is not None and self.name in obj.__dict__: return obj.__dict__[self.name] - else: + elif self.original is not None: return self.original.__get__(obj, type) + elif type is None: + raise AttributeError( + f"type object '{obj.__name__}' has no attribute '{self.name}'" + ) + else: + raise AttributeError( + f"'{type.__name__}' object has no attribute '{self.name}'" + ) def __set__(self, obj, value): instance_method_wrapped = isinstance( diff --git a/pupil_src/tests/test_observable.py b/pupil_src/tests/test_observable.py index 2cb5972e6f..e2be3a25d6 100644 --- a/pupil_src/tests/test_observable.py +++ b/pupil_src/tests/test_observable.py @@ -520,6 +520,18 @@ def fake_method(self): with pytest.raises(ReplaceWrapperError): observable.bound_method = 42 + def test_wrappers_not_in_class_cannot_be_set(self, observable): + def fake_method(self): + pass + + observable.bound_method = types.MethodType(fake_method, observable) + observable.add_observer("bound_method", lambda: None) + + # fake_method is not part of FakeObservable, so the installation of the + # protection descriptor needs to account for that + with pytest.raises(ReplaceWrapperError): + observable.bound_method = 42 + def test_other_instances_without_wrapper_can_be_set(self, observable): observable.add_observer("bound_method", lambda: None) unwrapped_observable = FakeObservable() From 301dc202a9d021eed47df1f351fa302684435db2 Mon Sep 17 00:00:00 2001 From: Chris Kay Baumann Date: Tue, 13 Oct 2020 10:39:28 +0200 Subject: [PATCH 53/57] Add test for adding private methods as observers from within classes --- pupil_src/tests/test_observable.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pupil_src/tests/test_observable.py b/pupil_src/tests/test_observable.py index e2be3a25d6..11feae98a9 100644 --- a/pupil_src/tests/test_observable.py +++ b/pupil_src/tests/test_observable.py @@ -152,7 +152,19 @@ def my_function(): observable.bound_method() mock_function.assert_called_once() - def test_private_method_cannot_be_observer(self, observable): + def test_private_method_cannot_be_observer_from_inside(self, observable): + class FakeController: + def __private_method(self): + pass + + def add_private_observer(self, observable): + observable.add_observer("bound_method", self.__private_method) + + controller = FakeController() + with pytest.raises(TypeError): + controller.add_private_observer(observable) + + def test_private_method_cannot_be_observer_from_outside(self, observable): class FakeController: def __private_method(self): pass From df766109273b6709517b04fd1c4e389870c26ec0 Mon Sep 17 00:00:00 2001 From: Chris Kay Baumann Date: Tue, 13 Oct 2020 12:16:46 +0200 Subject: [PATCH 54/57] Apply black --- pupil_src/shared_modules/observable.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pupil_src/shared_modules/observable.py b/pupil_src/shared_modules/observable.py index 12f34e0bd7..2cd136d8ea 100644 --- a/pupil_src/shared_modules/observable.py +++ b/pupil_src/shared_modules/observable.py @@ -315,7 +315,9 @@ def _patch_object_to_call_wrapper_instead(self): def remove_wrapper(self): try: setattr( - self._obj_ref(), self._method_name, self.get_wrapped_bound_method(), + self._obj_ref(), + self._method_name, + self.get_wrapped_bound_method(), ) except ReplaceWrapperError: pass From 20b7c9ad36e48a64ed69f7c170095ddc6cdd1e12 Mon Sep 17 00:00:00 2001 From: Roman Roibu Date: Wed, 14 Oct 2020 00:40:47 +0200 Subject: [PATCH 55/57] Fix FPS drops on macOS when Capture window is occluded --- pupil_src/launchables/eye.py | 10 ++++++++++ pupil_src/launchables/world.py | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/pupil_src/launchables/eye.py b/pupil_src/launchables/eye.py index 6e0f697cce..fb5254068e 100644 --- a/pupil_src/launchables/eye.py +++ b/pupil_src/launchables/eye.py @@ -577,6 +577,16 @@ def window_should_update(): frame = None + if platform.system() == "Darwin": + # On macOS, calls to glfw.swap_buffers() deliberately take longer in case of + # occluded windows, based on the swap interval value. This causes an FPS drop + # and leads to problems when recording. To side-step this behaviour, the swap + # interval is set to zero. + # + # Read more about window occlusion on macOS here: + # https://developer.apple.com/library/archive/documentation/Performance/Conceptual/power_efficiency_guidelines_osx/WorkWhenVisible.html + glfw.swap_interval(0) + # Event loop while not glfw.window_should_close(main_window): diff --git a/pupil_src/launchables/world.py b/pupil_src/launchables/world.py index 7f75f9421a..c9139bff85 100644 --- a/pupil_src/launchables/world.py +++ b/pupil_src/launchables/world.py @@ -703,6 +703,16 @@ def window_should_update(): ipc_pub.notify({"subject": "world_process.started"}) logger.warning("Process started.") + if platform.system() == "Darwin": + # On macOS, calls to glfw.swap_buffers() deliberately take longer in case of + # occluded windows, based on the swap interval value. This causes an FPS drop + # and leads to problems when recording. To side-step this behaviour, the swap + # interval is set to zero. + # + # Read more about window occlusion on macOS here: + # https://developer.apple.com/library/archive/documentation/Performance/Conceptual/power_efficiency_guidelines_osx/WorkWhenVisible.html + glfw.swap_interval(0) + # Event loop while not glfw.window_should_close(main_window) and not process_was_interrupted: From fda384c9a9a2fd7be72826d917b489c0277815b9 Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Thu, 15 Oct 2020 16:40:01 +0200 Subject: [PATCH 56/57] TS Lookup Table: Return unmodified ts if no invalid ts were found Fixes regression in #2026 ts =timestamps --- pupil_src/shared_modules/video_capture/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pupil_src/shared_modules/video_capture/utils.py b/pupil_src/shared_modules/video_capture/utils.py index cf5d3380db..b056997548 100644 --- a/pupil_src/shared_modules/video_capture/utils.py +++ b/pupil_src/shared_modules/video_capture/utils.py @@ -264,6 +264,10 @@ def _fix_negative_time_jumps(timestamps: np.ndarray) -> np.ndarray: time_diff = np.diff(timestamps) invalid_idc = np.flatnonzero(time_diff < 0) + has_invalid_idc = invalid_idc.shape[0] > 0 + if not has_invalid_idc: + return timestamps + # Check edge case where last timestamp causes negative jump last_ts_is_invalid = invalid_idc[-1] == timestamps.shape[0] - 2 if last_ts_is_invalid: From fdb4c5650c21a6515ff55bb0cb2a2546fd151ece Mon Sep 17 00:00:00 2001 From: Pablo Prietz Date: Mon, 19 Oct 2020 11:32:19 +0200 Subject: [PATCH 57/57] Revert manual libglfw installation instruction due to pyglfw usage --- docs/dependencies-ubuntu17.md | 15 --------------- docs/dependencies-ubuntu18.md | 15 --------------- 2 files changed, 30 deletions(-) diff --git a/docs/dependencies-ubuntu17.md b/docs/dependencies-ubuntu17.md index 558b7d4743..d0c3bb5b3c 100644 --- a/docs/dependencies-ubuntu17.md +++ b/docs/dependencies-ubuntu17.md @@ -12,21 +12,6 @@ sudo apt-get update sudo apt install -y pkg-config git cmake build-essential nasm wget python3-setuptools libusb-1.0-0-dev python3-dev python3-pip python3-numpy python3-scipy libglew-dev libtbb-dev ``` -## glfw -Pupil requires glfw v3.3.2, which you can install from source with: -```sh -sudo apt install xorg-dev -git clone https://github.com/glfw/glfw -cd glfw -git checkout 3.3.2 -mkdir build -cd build -cmake -DBUILD_SHARED_LIBS=ON .. -make -sudo make install -sudo ldconfig -``` - ## ffmpeg3 Install ffmpeg3 from jonathonf's ppa: diff --git a/docs/dependencies-ubuntu18.md b/docs/dependencies-ubuntu18.md index a8a18b0f80..bebc9f722e 100644 --- a/docs/dependencies-ubuntu18.md +++ b/docs/dependencies-ubuntu18.md @@ -20,21 +20,6 @@ sudo apt install -y libgoogle-glog-dev libatlas-base-dev libeigen3-dev sudo apt install -y libceres-dev ``` -## glfw -Pupil requires glfw v3.3.2, which you can install from source with: -```sh -sudo apt install xorg-dev -git clone https://github.com/glfw/glfw -cd glfw -git checkout 3.3.2 -mkdir build -cd build -cmake -DBUILD_SHARED_LIBS=ON .. -make -sudo make install -sudo ldconfig -``` - ## Turbojpeg ```sh