screenshot_utils.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. """
  2. Copyright (c) Contributors to the Open 3D Engine Project.
  3. For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. SPDX-License-Identifier: Apache-2.0 OR MIT
  5. """
  6. import azlmbr.atom
  7. import azlmbr.legacy.general as general
  8. from editor_python_test_tools.editor_test_helper import EditorTestHelper
  9. DEFAULT_FRAME_WIDTH = 1920
  10. DEFAULT_FRAME_HEIGHT = 1080
  11. FOLDER_PATH = '@user@/PythonTests/Automated/Screenshots'
  12. helper = EditorTestHelper(log_prefix="Atom_ScreenshotHelper")
  13. class ScreenshotHelper(object):
  14. """
  15. A helper to capture screenshots and wait for them.
  16. """
  17. def __init__(self, idle_wait_frames_callback, frame_width=DEFAULT_FRAME_WIDTH, frame_height=DEFAULT_FRAME_HEIGHT):
  18. super().__init__()
  19. self.done = False
  20. self.capturedScreenshot = False
  21. self.max_frames_to_wait = 60
  22. self.prepare_viewport_for_screenshot(frame_width, frame_height)
  23. self.idle_wait_frames_callback = idle_wait_frames_callback
  24. def capture_screenshot_blocking_in_game_mode(self, filename):
  25. helper.enter_game_mode(["", ""])
  26. general.idle_wait_frames(120)
  27. self.capture_screenshot_blocking(filename)
  28. helper.exit_game_mode(["", ""])
  29. def prepare_viewport_for_screenshot(self, frame_width, frame_height):
  30. cur_viewport_size = general.get_viewport_size()
  31. if int(cur_viewport_size.x) != frame_width or int(cur_viewport_size.y) != frame_height:
  32. general.set_viewport_expansion_policy('FixedSize')
  33. general.idle_wait_frames(1)
  34. general.set_viewport_size(frame_width, frame_height)
  35. general.set_cvar_integer('r_DisplayInfo', 0)
  36. general.update_viewport()
  37. general.idle_wait_frames(120)
  38. new_viewport_size = general.get_viewport_size()
  39. if int(new_viewport_size.x) != frame_width or int(new_viewport_size.y) != frame_height:
  40. general.log("Resolution is incorrect!")
  41. general.log(f"width: {int(new_viewport_size.x)}")
  42. general.log(f"height: {int(new_viewport_size.y)}")
  43. def capture_screenshot_blocking(self, filename, folder_path=FOLDER_PATH):
  44. """
  45. Capture a screenshot and block the execution until the screenshot has been written to the disk.
  46. """
  47. self.handler = azlmbr.atom.FrameCaptureNotificationBusHandler()
  48. self.handler.connect()
  49. self.handler.add_callback('OnCaptureFinished', self.on_screenshot_captured)
  50. self.done = False
  51. self.capturedScreenshot = False
  52. success = azlmbr.atom.FrameCaptureRequestBus(
  53. azlmbr.bus.Broadcast, "CaptureScreenshot", f"{folder_path}/{filename}")
  54. if success:
  55. self.wait_until_screenshot()
  56. general.log("Screenshot taken.")
  57. else:
  58. general.log("Screenshot failed")
  59. return self.capturedScreenshot
  60. def on_screenshot_captured(self, parameters):
  61. # the parameters come in as a tuple
  62. if parameters[0] == azlmbr.atom.FrameCaptureResult_Success:
  63. general.log(f"screenshot saved: {parameters[1]}")
  64. self.capturedScreenshot = True
  65. else:
  66. general.log(f"screenshot failed: {parameters[1]}")
  67. self.done = True
  68. self.handler.disconnect()
  69. def wait_until_screenshot(self):
  70. frames_waited = 0
  71. while self.done == False:
  72. self.idle_wait_frames_callback(1)
  73. if frames_waited > self.max_frames_to_wait:
  74. general.log("timeout while waiting for the screenshot to be written")
  75. self.handler.disconnect()
  76. break
  77. else:
  78. frames_waited = frames_waited + 1
  79. general.log(f"(waited {frames_waited} frames)")
  80. def take_screenshot_game_mode(screenshot_name, entity_name=None):
  81. """
  82. Enters game mode & takes a screenshot, then exits game mode after.
  83. :param screenshot_name: name to give the captured screenshot .ppm file.
  84. :param entity_name: name of the entity being tested (for generating unique log lines).
  85. :return: None
  86. """
  87. general.enter_game_mode()
  88. helper.wait_for_condition(lambda: general.is_in_game_mode(), 2.0)
  89. general.log(f"{entity_name}_test: Entered game mode: {general.is_in_game_mode()}")
  90. ScreenshotHelper(general.idle_wait_frames).capture_screenshot_blocking(f"{screenshot_name}.ppm")
  91. general.idle_wait(1.0)
  92. general.exit_game_mode()
  93. helper.wait_for_condition(lambda: not general.is_in_game_mode(), 2.0)
  94. general.log(f"{entity_name}_test: Exit game mode: {not general.is_in_game_mode()}")