zgui/libs/imgui_test_engine/imgui_capture_tool.h

181 lines
12 KiB
C

// dear imgui test engine
// (screen/video capture tool)
// This is usable as a standalone applet or controlled by the test engine.
#pragma once
// Need "imgui_te_engine.h" included for ImFuncPtr
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
// Our types
struct ImGuiCaptureArgs; // Parameters for Capture
struct ImGuiCaptureContext; // State of an active capture tool
struct ImGuiCaptureImageBuf; // Simple helper to store an RGBA image in memory
struct ImGuiCaptureToolUI; // Capture tool instance + UI window
typedef unsigned int ImGuiCaptureFlags; // See enum: ImGuiCaptureFlags_
// Capture function which needs to be provided by user application
typedef bool (ImGuiScreenCaptureFunc)(ImGuiID viewport_id, int x, int y, int w, int h, unsigned int* pixels, void* user_data);
// External types
struct ImGuiWindow; // imgui.h
//-----------------------------------------------------------------------------
// [Internal]
// Helper class for simple bitmap manipulation (not particularly efficient!)
struct IMGUI_API ImGuiCaptureImageBuf
{
int Width;
int Height;
unsigned int* Data; // RGBA8
ImGuiCaptureImageBuf() { Width = Height = 0; Data = NULL; }
~ImGuiCaptureImageBuf() { Clear(); }
void Clear(); // Free allocated memory buffer if such exists.
void CreateEmpty(int w, int h); // Reallocate buffer for pixel data and zero it.
bool SaveFile(const char* filename); // Save pixel data to specified image file.
void RemoveAlpha(); // Clear alpha channel from all pixels.
};
enum ImGuiCaptureFlags_ : unsigned int
{
ImGuiCaptureFlags_None = 0,
ImGuiCaptureFlags_StitchAll = 1 << 0, // Capture entire window scroll area (by scrolling and taking multiple screenshot). Only works for a single window.
ImGuiCaptureFlags_IncludeOtherWindows = 1 << 1, // Disable hiding other windows (when CaptureAddWindow has been called by default other windows are hidden)
ImGuiCaptureFlags_IncludeTooltipsAndPopups = 1 << 2, // Expand capture area to automatically include visible popups and tooltips (use with ImGuiCaptureflags_HideOtherWindows)
ImGuiCaptureFlags_HideMouseCursor = 1 << 3, // Hide render software mouse cursor during capture.
ImGuiCaptureFlags_Instant = 1 << 4, // Perform capture on very same frame. Only works when capturing a rectangular region. Unsupported features: content stitching, window hiding, window relocation.
ImGuiCaptureFlags_NoSave = 1 << 5 // Do not save output image.
};
// Defines input and output arguments for capture process.
// When capturing from tests you can usually use the ImGuiTestContext::CaptureXXX() helpers functions.
struct ImGuiCaptureArgs
{
// [Input]
ImGuiCaptureFlags InFlags = 0; // Flags for customizing behavior of screenshot tool.
ImVector<ImGuiWindow*> InCaptureWindows; // Windows to capture. All other windows will be hidden. May be used with InCaptureRect to capture only some windows in specified rect.
ImRect InCaptureRect; // Screen rect to capture. Does not include padding.
float InPadding = 16.0f; // Extra padding at the edges of the screenshot. Ensure that there is available space around capture rect horizontally, also vertically if ImGuiCaptureFlags_StitchFullContents is not used.
char InOutputFile[256] = ""; // Output will be saved to a file if InOutputImageBuf is NULL.
ImGuiCaptureImageBuf* InOutputImageBuf = NULL; // _OR_ Output will be saved to image buffer if specified.
int InRecordFPSTarget = 30; // FPS target for recording videos.
int InSizeAlign = 0; // Resolution alignment (0 = auto, 1 = no alignment, >= 2 = align width/height to be multiple of given value)
// [Output]
ImVec2 OutImageSize; // Produced image size.
};
enum ImGuiCaptureStatus
{
ImGuiCaptureStatus_InProgress,
ImGuiCaptureStatus_Done,
ImGuiCaptureStatus_Error
};
struct ImGuiCaptureWindowData
{
ImGuiWindow* Window;
ImRect BackupRect;
ImVec2 PosDuringCapture;
};
// Implements functionality for capturing images
struct IMGUI_API ImGuiCaptureContext
{
// IO
ImFuncPtr(ImGuiScreenCaptureFunc) ScreenCaptureFunc = NULL; // Graphics backend specific function that captures specified portion of framebuffer and writes RGBA data to `pixels` buffer.
void* ScreenCaptureUserData = NULL; // Custom user pointer which is passed to ScreenCaptureFunc. (Optional)
char* VideoCaptureEncoderPath = NULL; // Video encoder path (not owned, stored externally).
int VideoCaptureEncoderPathSize = 0; // Optional. Set in order to edit this parameter from UI.
char* VideoCaptureEncoderParams = NULL; // Video encoder params (not owned, stored externally).
int VideoCaptureEncoderParamsSize = 0; // Optional. Set in order to edit this parameter from UI.
char* GifCaptureEncoderParams = NULL; // Video encoder params for GIF output (not owned, stored externally).
int GifCaptureEncoderParamsSize = 0; // Optional. Set in order to edit this parameter from UI.
// [Internal]
ImRect _CaptureRect; // Viewport rect that is being captured.
ImRect _CapturedWindowRect; // Top-left corner of region that covers all windows included in capture. This is not same as _CaptureRect.Min when capturing explicitly specified rect.
int _ChunkNo = 0; // Number of chunk that is being captured when capture spans multiple frames.
int _FrameNo = 0; // Frame number during capture process that spans multiple frames.
ImVec2 _MouseRelativeToWindowPos; // Mouse cursor position relative to captured window (when _StitchAll is in use).
ImGuiWindow* _HoveredWindow = NULL; // Window which was hovered at capture start.
ImGuiCaptureImageBuf _CaptureBuf; // Output image buffer.
const ImGuiCaptureArgs* _CaptureArgs = NULL; // Current capture args. Set only if capture is in progress.
ImVector<ImGuiCaptureWindowData> _WindowsData; // Backup windows that will have their rect modified and restored. args->InCaptureWindows can not be used because popups may get closed during capture and no longer appear in that list.
// [Internal] Video recording
bool _VideoRecording = false; // Flag indicating that video recording is in progress.
double _VideoLastFrameTime = 0; // Time when last video frame was recorded.
FILE* _VideoEncoderPipe = NULL; // File writing to stdin of video encoder process.
// [Internal] Backups
bool _BackupMouseDrawCursor = false; // Initial value of g.IO.MouseDrawCursor
ImVec2 _BackupDisplayWindowPadding; // Backup padding. We set it to {0, 0} during capture.
ImVec2 _BackupDisplaySafeAreaPadding; // Backup padding. We set it to {0, 0} during capture.
//-------------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------------
ImGuiCaptureContext(ImGuiScreenCaptureFunc capture_func = NULL) { ScreenCaptureFunc = capture_func; _MouseRelativeToWindowPos = ImVec2(-FLT_MAX, -FLT_MAX); }
// These functions should be called from appropriate context hooks. See ImGui::AddContextHook() for more info.
// (ImGuiTestEngine automatically calls that for you, so this only apply to independently created instance)
void PreNewFrame();
void PreRender();
void PostRender();
// Update capturing. If this function returns true then it should be called again with same arguments on the next frame.
ImGuiCaptureStatus CaptureUpdate(ImGuiCaptureArgs* args);
void RestoreBackedUpData();
void ClearState();
// Begin video capture. Call CaptureUpdate() every frame afterwards until it returns false.
void BeginVideoCapture(ImGuiCaptureArgs* args);
void EndVideoCapture();
bool IsCapturingVideo();
bool IsCapturing();
};
//-----------------------------------------------------------------------------
// ImGuiCaptureToolUI
//-----------------------------------------------------------------------------
// Implements UI for capturing images
// (when using ImGuiTestEngine scripting API you may not need to use this at all)
struct IMGUI_API ImGuiCaptureToolUI
{
float SnapGridSize = 32.0f; // Size of the grid cell for "snap to grid" functionality.
char OutputLastFilename[256] = ""; // File name of last captured file.
char* VideoCaptureExtension = NULL; // Video file extension (e.g. ".gif" or ".mp4")
int VideoCaptureExtensionSize = 0; // Optional. Set in order to edit this parameter from UI.
ImGuiCaptureArgs _CaptureArgs; // Capture args
bool _StateIsPickingWindow = false;
bool _StateIsCapturing = false;
ImVector<ImGuiID> _SelectedWindows;
char _OutputFileTemplate[256] = ""; //
int _FileCounter = 0; // Counter which may be appended to file name when saving. By default, counting starts from 1. When done this field holds number of saved files.
// Public
ImGuiCaptureToolUI();
void ShowCaptureToolWindow(ImGuiCaptureContext* context, bool* p_open = NULL); // Render a capture tool window with various options and utilities.
// [Internal]
void _CaptureWindowPicker(ImGuiCaptureArgs* args); // Render a window picker that captures picked window to file specified in file_name.
void _CaptureWindowsSelector(ImGuiCaptureContext* context, ImGuiCaptureArgs* args); // Render a selector for selecting multiple windows for capture.
void _SnapWindowsToGrid(float cell_size); // Snap edges of all visible windows to a virtual grid.
bool _InitializeOutputFile(); // Format output file template into capture args struct and ensure target directory exists.
bool _ShowEncoderConfigFields(ImGuiCaptureContext* context);
};
#define IMGUI_CAPTURE_DEFAULT_VIDEO_PARAMS_FOR_FFMPEG "-hide_banner -loglevel error -r $FPS -f rawvideo -pix_fmt rgba -s $WIDTHx$HEIGHT -i - -threads 0 -y -preset ultrafast -pix_fmt yuv420p -crf 20 $OUTPUT"
#define IMGUI_CAPTURE_DEFAULT_GIF_PARAMS_FOR_FFMPEG "-hide_banner -loglevel error -r $FPS -f rawvideo -pix_fmt rgba -s $WIDTHx$HEIGHT -i - -threads 0 -y -filter_complex \"split=2 [a] [b]; [a] palettegen [pal]; [b] [pal] paletteuse\" $OUTPUT"