From 668cce9b45c2abc2e2b2879372093ce3c77b21ed Mon Sep 17 00:00:00 2001 From: kushalkolar Date: Thu, 6 Jul 2023 23:38:12 -0400 Subject: [PATCH 1/2] add more controllers --- fastplotlib/layouts/_base.py | 1 - fastplotlib/layouts/_defaults.py | 48 ++++++++++++++++++++++++-------- fastplotlib/layouts/_plot.py | 2 +- fastplotlib/layouts/_subplot.py | 8 ++++-- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/fastplotlib/layouts/_base.py b/fastplotlib/layouts/_base.py index 5d9d4a6e9..580a81cf8 100644 --- a/fastplotlib/layouts/_base.py +++ b/fastplotlib/layouts/_base.py @@ -87,7 +87,6 @@ def __init__( self._camera = camera self._controller = controller - self.controller.add_camera(self.camera) self.controller.register_events( self.viewport, ) diff --git a/fastplotlib/layouts/_defaults.py b/fastplotlib/layouts/_defaults.py index 9a223855f..1e41712d5 100644 --- a/fastplotlib/layouts/_defaults.py +++ b/fastplotlib/layouts/_defaults.py @@ -6,17 +6,14 @@ "3d": pygfx.PerspectiveCamera, } -controller_types = { - "2d": pygfx.PanZoomController, - "3d": pygfx.OrbitController, - pygfx.OrthographicCamera: pygfx.PanZoomController, - pygfx.PerspectiveCamera: pygfx.OrbitController, -} - def create_camera( - camera_type: str, big_camera: bool = False + camera_type: Union[pygfx.Camera, str], + big_camera: bool = False ) -> Union[pygfx.OrthographicCamera, pygfx.PerspectiveCamera]: + if isinstance(camera_type, (pygfx.OrthographicCamera, pygfx.PerspectiveCamera)): + return camera_type + camera_type = camera_type.split("-") # kinda messy but works for now @@ -40,7 +37,36 @@ def create_camera( return cls() -def create_controller(controller_type: str): - controller_type = controller_type.split("-")[0] +def create_controller( + camera: Union[pygfx.OrthographicCamera, pygfx.PerspectiveCamera], + controller: Union[pygfx.Controller, None, str], +) -> pygfx.Controller: + if isinstance(controller, pygfx.Controller): + return controller + + if controller is None: + # default controllers + if isinstance(camera, pygfx.OrthographicCamera): + return pygfx.PanZoomController(camera) + + elif isinstance(camera, pygfx.PerspectiveCamera): + return pygfx.FlyController(camera) - return controller_types[controller_type]() + # controller specified + if controller == "fly": + return pygfx.FlyController(camera) + + elif controller == "panzoom": + return pygfx.PanZoomController(camera) + + elif controller == "trackball": + return pygfx.TrackballController(camera) + + elif controller == "orbit": + return pygfx.OrbitController(camera) + + else: + raise ValueError( + f"Invalid controller type, valid controllers are instances of `pygfx.Controller` or one of:\n" + f"'panzoom', 'fly', 'trackball', or 'oribit'" + ) diff --git a/fastplotlib/layouts/_plot.py b/fastplotlib/layouts/_plot.py index 2b5cc51b7..653ba6c8a 100644 --- a/fastplotlib/layouts/_plot.py +++ b/fastplotlib/layouts/_plot.py @@ -19,7 +19,7 @@ def __init__( canvas: WgpuCanvas = None, renderer: pygfx.WgpuRenderer = None, camera: str = "2d", - controller: Union[pygfx.PanZoomController, pygfx.OrbitController] = None, + controller: Union[pygfx.Controller, str] = None, size: Tuple[int, int] = (500, 300), **kwargs, ): diff --git a/fastplotlib/layouts/_subplot.py b/fastplotlib/layouts/_subplot.py index a8cd4852b..b8adfd296 100644 --- a/fastplotlib/layouts/_subplot.py +++ b/fastplotlib/layouts/_subplot.py @@ -4,6 +4,7 @@ import numpy as np +import pygfx from pygfx import ( Scene, OrthographicCamera, @@ -30,7 +31,7 @@ def __init__( position: Tuple[int, int] = None, parent_dims: Tuple[int, int] = None, camera: str = "2d", - controller: Union[PanZoomController, OrbitController] = None, + controller: Union[pygfx.Controller] = None, canvas: Union[str, WgpuCanvas, Texture] = None, renderer: WgpuRenderer = None, name: str = None, @@ -84,8 +85,9 @@ def __init__( self.nrows, self.ncols = parent_dims - if controller is None: - controller = create_controller(camera) + # parse camera and controller + camera = create_camera(camera) + controller = create_controller(camera, controller) self._docks = dict() From ee777c1a1f5ecf13abcb0aefdc5672d2e8626ddd Mon Sep 17 00:00:00 2001 From: kushalkolar Date: Fri, 7 Jul 2023 00:07:08 -0400 Subject: [PATCH 2/2] new controller options work, nothing broken --- fastplotlib/layouts/_defaults.py | 6 +++--- fastplotlib/layouts/_gridplot.py | 9 ++++++--- fastplotlib/layouts/_subplot.py | 7 ++++--- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/fastplotlib/layouts/_defaults.py b/fastplotlib/layouts/_defaults.py index 1e41712d5..d563b98c1 100644 --- a/fastplotlib/layouts/_defaults.py +++ b/fastplotlib/layouts/_defaults.py @@ -46,10 +46,10 @@ def create_controller( if controller is None: # default controllers - if isinstance(camera, pygfx.OrthographicCamera): + if camera == "2d" or isinstance(camera, pygfx.OrthographicCamera): return pygfx.PanZoomController(camera) - elif isinstance(camera, pygfx.PerspectiveCamera): + elif camera == "3d" or isinstance(camera, pygfx.PerspectiveCamera): return pygfx.FlyController(camera) # controller specified @@ -68,5 +68,5 @@ def create_controller( else: raise ValueError( f"Invalid controller type, valid controllers are instances of `pygfx.Controller` or one of:\n" - f"'panzoom', 'fly', 'trackball', or 'oribit'" + f"'panzoom', 'fly', 'trackball', or 'orbit'. You have passed: {type(controller)}" ) diff --git a/fastplotlib/layouts/_gridplot.py b/fastplotlib/layouts/_gridplot.py index b339e8659..16d6c9215 100644 --- a/fastplotlib/layouts/_gridplot.py +++ b/fastplotlib/layouts/_gridplot.py @@ -15,7 +15,7 @@ from ipywidgets import HBox, Layout, Button, ToggleButton, VBox, Dropdown from ._utils import make_canvas_and_renderer -from ._defaults import create_controller +from ._defaults import create_camera, create_controller from ._subplot import Subplot from ._record_mixin import RecordMixin @@ -108,7 +108,7 @@ def __init__( if controllers.shape != self.shape: raise ValueError - cameras = to_array(cameras) + cameras = to_array(cameras).astype(object) self._controllers = np.empty(shape=cameras.shape, dtype=object) @@ -130,7 +130,10 @@ def __init__( f"Controller id: {controller} has been assigned to multiple different camera types" ) - self._controllers[controllers == controller] = create_controller(cam[0]) + _cam = create_camera(cam[0]) + cameras[controllers == controller] = _cam + self._controllers[controllers == controller] = create_controller(_cam, controller=None) + # else assume it's a single pygfx.Controller instance or a list of controllers else: if isinstance(controllers, pygfx.Controller): diff --git a/fastplotlib/layouts/_subplot.py b/fastplotlib/layouts/_subplot.py index b8adfd296..378b3f756 100644 --- a/fastplotlib/layouts/_subplot.py +++ b/fastplotlib/layouts/_subplot.py @@ -56,9 +56,10 @@ def __init__( indicates the kind of pygfx camera that will be instantiated, '2d' uses pygfx ``OrthographicCamera`` and '3d' uses pygfx ``PerspectiveCamera`` - controller: PanZoomController or OrbitOrthoController, optional - ``PanZoomController`` type is used for 2D pan-zoom camera control and ``OrbitController`` type is used for - rotating the camera around a center position, used to control the camera + controller: None, str, or a pygfx controller + | if ``None``, uses a PanZoomController for "2d" camera or FlyController for "3d" camera. + | if ``str``, must be one of: `"panzoom", "fly", "trackball", or "orbit"`. + | also accepts a pygfx.Controller instance canvas: WgpuCanvas, Texture, or one of "jupyter", "glfw", "qt", optional Provides surface on which a scene will be rendered. Can optionally provide a WgpuCanvas instance or a str