aboutsummaryrefslogtreecommitdiff
path: root/vendor/zgui/libs/imgui_test_engine/imgui_capture_tool.h
blob: e5489c58478ebea1503e6b8178e9fe0eb22e1e51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// dear imgui test engine
// (screen/video capture tool)
// This is usable as a standalone applet or controlled by the test engine.

#pragma once

#include "imgui_te_utils.h"             // 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"