|
1 | 1 | import logging |
2 | 2 | import os |
3 | | -from unittest import mock |
4 | 3 | from unittest.mock import patch |
5 | 4 |
|
6 | 5 | import numpy as np |
|
17 | 16 | OrbitController, |
18 | 17 | PerspectiveCamera, |
19 | 18 | PointerEvent, |
| 19 | + QtWidgets, |
20 | 20 | Renderer, |
21 | 21 | Scene as GfxScene, |
22 | 22 | ScreenCoordsCamera, |
23 | 23 | Texture, |
24 | 24 | TrackballController, |
25 | 25 | have_imgui_bundle, |
| 26 | + have_py_side6, |
26 | 27 | ) |
27 | 28 | from fury.motion import Animation, CameraAnimation, Timeline |
28 | 29 | from fury.ui import Rectangle2D, UIContext |
@@ -395,14 +396,12 @@ def test_show_manager_initialization_default_window(): |
395 | 396 | assert show_m.app is None |
396 | 397 |
|
397 | 398 |
|
398 | | -# @pytest.mark.skipif( |
399 | | -# not (have_py_side6 or have_py_qt6 or have_py_qt5), reason="Needs Qt" |
400 | | -# ) |
401 | | -# def test_show_manager_initialization_qt_window(): |
402 | | -# """Test ShowManager initialization with a Qt window.""" |
403 | | -# show_m = ShowManager(window_type="qt") |
404 | | -# assert show_m._is_qt is True |
405 | | -# assert show_m.app is not None |
| 399 | +@pytest.mark.skipif(not (have_py_side6), reason="Needs Qt") |
| 400 | +def test_show_manager_initialization_qt_window(): |
| 401 | + """Test ShowManager initialization with a Qt window.""" |
| 402 | + show_m = ShowManager(window_type="qt") |
| 403 | + assert show_m._is_qt is True |
| 404 | + assert isinstance(show_m.window, QtWidgets.QWidget) |
406 | 405 |
|
407 | 406 |
|
408 | 407 | def test_show_manager_screen_setup(): |
@@ -925,41 +924,125 @@ def test_show_manager_register_drag(): |
925 | 924 | assert screen.controller.enabled is True |
926 | 925 |
|
927 | 926 |
|
928 | | -def test_offscreen_animation_recording(): |
929 | | - |
930 | | - # Create a simple scene |
| 927 | +def test_offscreen_animation_recording(tmp_path): |
931 | 928 | scene = window.Scene() |
932 | 929 | scene.add(actor.axes(scale=(1, 1, 1))) |
933 | 930 |
|
934 | 931 | show_m = window.ShowManager(scene=scene, size=(200, 200), title="test_anim") |
935 | 932 |
|
936 | | - # to trigger animation logic |
937 | | - def dummy_callback(): |
| 933 | + def noop_callback(): |
938 | 934 | pass |
939 | 935 |
|
940 | | - show_m.register_callback(dummy_callback, time=1.0, repeat=True, name="dummy") |
| 936 | + show_m.register_callback(noop_callback, time=1.0, repeat=True, name="noop") |
941 | 937 |
|
942 | | - # test 1: record animation is FALSE |
943 | | - with mock.patch.dict( |
944 | | - os.environ, {"FURY_OFFSCREEN": "1", "FURY_RECORD_ANIMATION": "0"} |
945 | | - ): |
946 | | - show_m.start() |
947 | | - assert os.path.exists("test_anim.png") |
948 | | - assert not os.path.exists("test_anim.gif") |
| 938 | + original_cwd = os.getcwd() |
| 939 | + original_offscreen = os.environ.get("FURY_OFFSCREEN") |
| 940 | + original_record = os.environ.get("FURY_RECORD_ANIMATION") |
| 941 | + os.chdir(tmp_path) |
| 942 | + os.environ["FURY_OFFSCREEN"] = "1" |
| 943 | + os.environ["FURY_RECORD_ANIMATION"] = "0" |
949 | 944 |
|
950 | | - os.remove("test_anim.png") |
| 945 | + try: |
| 946 | + show_m.start() |
| 947 | + finally: |
| 948 | + os.chdir(original_cwd) |
| 949 | + if original_offscreen is None: |
| 950 | + os.environ.pop("FURY_OFFSCREEN", None) |
| 951 | + else: |
| 952 | + os.environ["FURY_OFFSCREEN"] = original_offscreen |
| 953 | + if original_record is None: |
| 954 | + os.environ.pop("FURY_RECORD_ANIMATION", None) |
| 955 | + else: |
| 956 | + os.environ["FURY_RECORD_ANIMATION"] = original_record |
| 957 | + |
| 958 | + assert (tmp_path / "test_anim.png").exists() |
| 959 | + assert not (tmp_path / "test_anim.gif").exists() |
| 960 | + os.remove(tmp_path / "test_anim.png") |
| 961 | + |
| 962 | + original_cwd = os.getcwd() |
| 963 | + original_offscreen = os.environ.get("FURY_OFFSCREEN") |
| 964 | + original_record = os.environ.get("FURY_RECORD_ANIMATION") |
| 965 | + original_max_frames = os.environ.get("FURY_OFFSCREEN_MAX_FRAMES") |
| 966 | + os.chdir(tmp_path) |
| 967 | + os.environ["FURY_OFFSCREEN"] = "1" |
| 968 | + os.environ["FURY_RECORD_ANIMATION"] = "1" |
| 969 | + os.environ["FURY_OFFSCREEN_MAX_FRAMES"] = "2" |
951 | 970 |
|
952 | | - # test 2: record animation is TRUE |
953 | | - with mock.patch.dict( |
954 | | - os.environ, {"FURY_OFFSCREEN": "1", "FURY_RECORD_ANIMATION": "1"} |
955 | | - ): |
| 971 | + try: |
956 | 972 | show_m2 = window.ShowManager(scene=scene, size=(200, 200), title="test_anim") |
957 | | - show_m2.register_callback(dummy_callback, time=1.0, repeat=True, name="dummy") |
| 973 | + show_m2.register_callback(noop_callback, time=1.0, repeat=True, name="noop") |
958 | 974 | show_m2.start() |
959 | | - assert os.path.exists("test_anim.gif") |
960 | | - assert not os.path.exists("test_anim.png") |
| 975 | + finally: |
| 976 | + os.chdir(original_cwd) |
| 977 | + if original_offscreen is None: |
| 978 | + os.environ.pop("FURY_OFFSCREEN", None) |
| 979 | + else: |
| 980 | + os.environ["FURY_OFFSCREEN"] = original_offscreen |
| 981 | + if original_record is None: |
| 982 | + os.environ.pop("FURY_RECORD_ANIMATION", None) |
| 983 | + else: |
| 984 | + os.environ["FURY_RECORD_ANIMATION"] = original_record |
| 985 | + if original_max_frames is None: |
| 986 | + os.environ.pop("FURY_OFFSCREEN_MAX_FRAMES", None) |
| 987 | + else: |
| 988 | + os.environ["FURY_OFFSCREEN_MAX_FRAMES"] = original_max_frames |
| 989 | + |
| 990 | + assert (tmp_path / "test_anim.gif").exists() |
| 991 | + assert not (tmp_path / "test_anim.png").exists() |
| 992 | + os.remove(tmp_path / "test_anim.gif") |
| 993 | + |
| 994 | + |
| 995 | +@pytest.mark.skipif( |
| 996 | + not (have_py_side6), |
| 997 | + reason="A Qt binding is required for Qt offscreen capture", |
| 998 | +) |
| 999 | +def test_qt_offscreen_capture_saves_parent_widget(tmp_path): |
| 1000 | + app = QtWidgets.QApplication.instance() or QtWidgets.QApplication([]) |
| 1001 | + parent = QtWidgets.QWidget() |
| 1002 | + parent.resize(240, 120) |
961 | 1003 |
|
962 | | - os.remove("test_anim.gif") |
| 1004 | + scene = window.Scene() |
| 1005 | + scene.add(actor.axes(scale=(1, 1, 1))) |
| 1006 | + |
| 1007 | + show_m = window.ShowManager( |
| 1008 | + scene=scene, |
| 1009 | + size=(100, 100), |
| 1010 | + title="qt_capture", |
| 1011 | + window_type="qt", |
| 1012 | + qt_app=app, |
| 1013 | + qt_parent=parent, |
| 1014 | + ) |
| 1015 | + |
| 1016 | + layout = QtWidgets.QHBoxLayout() |
| 1017 | + parent.setLayout(layout) |
| 1018 | + layout.addWidget(QtWidgets.QPushButton("Capture", parent)) |
| 1019 | + layout.addWidget(show_m.window) |
| 1020 | + |
| 1021 | + original_cwd = os.getcwd() |
| 1022 | + original_offscreen = os.environ.get("FURY_OFFSCREEN") |
| 1023 | + original_record = os.environ.get("FURY_RECORD_ANIMATION") |
| 1024 | + os.chdir(tmp_path) |
| 1025 | + os.environ["FURY_OFFSCREEN"] = "1" |
| 1026 | + os.environ["FURY_RECORD_ANIMATION"] = "0" |
| 1027 | + |
| 1028 | + try: |
| 1029 | + show_m.start() |
| 1030 | + finally: |
| 1031 | + os.chdir(original_cwd) |
| 1032 | + if original_offscreen is None: |
| 1033 | + os.environ.pop("FURY_OFFSCREEN", None) |
| 1034 | + else: |
| 1035 | + os.environ["FURY_OFFSCREEN"] = original_offscreen |
| 1036 | + if original_record is None: |
| 1037 | + os.environ.pop("FURY_RECORD_ANIMATION", None) |
| 1038 | + else: |
| 1039 | + os.environ["FURY_RECORD_ANIMATION"] = original_record |
| 1040 | + |
| 1041 | + fname = tmp_path / "qt_capture.png" |
| 1042 | + assert fname.exists() |
| 1043 | + image = load_image(str(fname)) |
| 1044 | + assert image.shape[0] == parent.height() |
| 1045 | + assert image.shape[1] == parent.width() |
963 | 1046 |
|
964 | 1047 |
|
965 | 1048 | def test_show_manager_add_animation_registers_update_callback(timeline): |
|
0 commit comments