mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 18:59:59 +01:00
Player Frame capture F10
New feature of Player: capture frame (F10 shortcut). Extending the Screenshot class for reading pixels and saving to PNG. Cleaup of screenshot (now associated to F9).
This commit is contained in:
@@ -557,3 +557,30 @@ bool FrameBuffer::fill(FrameBufferImage *image)
|
||||
}
|
||||
|
||||
|
||||
//void FrameBuffer::writePNG(const std::string &filename)
|
||||
//{
|
||||
// // not ready
|
||||
// if (!framebufferid_)
|
||||
// return;
|
||||
|
||||
// // create a temporary RGBA frame buffer at the resolution of cropped area
|
||||
// int w = attrib_.viewport.x * projection_area_.x;
|
||||
// int h = attrib_.viewport.y * projection_area_.y;
|
||||
// FrameBuffer copy(w, h, FrameBuffer_alpha);
|
||||
|
||||
// // create temporary RAM buffer to store the cropped RGBA
|
||||
// uint8_t *buffer = new uint8_t[w * h * 4];
|
||||
|
||||
// // blit the frame buffer into the copy
|
||||
// blit(©);
|
||||
|
||||
// // get pixels of the copy into buffer
|
||||
// glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); // set buffer target readpixel
|
||||
// copy.readPixels(buffer);
|
||||
|
||||
// // save to file
|
||||
// stbi_write_png(filename.c_str(), w, h, 4, buffer, w * 4);
|
||||
|
||||
// // delete (copy is also deleted)
|
||||
// delete[] buffer;
|
||||
//}
|
||||
|
||||
@@ -340,8 +340,7 @@ void Rendering::draw()
|
||||
|
||||
// perform screenshot if requested
|
||||
if (request_screenshot_) {
|
||||
// glfwMakeContextCurrent(main_window_);
|
||||
screenshot_.captureGL(0, 0, main_.width(), main_.height());
|
||||
screenshot_.captureGL(main_.width(), main_.height());
|
||||
request_screenshot_ = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,14 @@
|
||||
#include <stb_image.h>
|
||||
#include <stb_image_write.h>
|
||||
|
||||
#include "FrameBuffer.h"
|
||||
#include "Screenshot.h"
|
||||
|
||||
|
||||
Screenshot::Screenshot()
|
||||
{
|
||||
Width = Height = 0;
|
||||
bpp = 3;
|
||||
Data = nullptr;
|
||||
Pbo = 0;
|
||||
Pbo_size = 0;
|
||||
@@ -53,12 +55,8 @@ bool Screenshot::isFull()
|
||||
return Pbo_full;
|
||||
}
|
||||
|
||||
void Screenshot::captureGL(int x, int y, int w, int h)
|
||||
void Screenshot::capture()
|
||||
{
|
||||
Width = w - x;
|
||||
Height = h - y;
|
||||
unsigned int size = Width * Height * 3;
|
||||
|
||||
// create BPO
|
||||
if (Pbo == 0)
|
||||
glGenBuffers(1, &Pbo);
|
||||
@@ -67,22 +65,57 @@ void Screenshot::captureGL(int x, int y, int w, int h)
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, Pbo);
|
||||
|
||||
// init
|
||||
unsigned int size = Width * Height * bpp;
|
||||
if (Pbo_size != size) {
|
||||
Pbo_size = size;
|
||||
if (Data) free(Data);
|
||||
if (Data)
|
||||
free(Data);
|
||||
Data = (unsigned char*) malloc(Pbo_size);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, Pbo_size, NULL, GL_STREAM_READ);
|
||||
}
|
||||
|
||||
// screenshot to PBO (fast)
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
||||
Pbo_full = true;
|
||||
glReadPixels(0, 0, Width, Height, bpp > 3 ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
// done
|
||||
Pbo_full = true;
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
void Screenshot::captureGL(int w, int h)
|
||||
{
|
||||
bpp = 3; // screen capture of GL in RGB
|
||||
Width = w;
|
||||
Height = h;
|
||||
|
||||
// do capture
|
||||
capture();
|
||||
}
|
||||
|
||||
void Screenshot::captureFramebuffer(FrameBuffer *fb)
|
||||
{
|
||||
if (!fb)
|
||||
return;
|
||||
|
||||
bpp = 4; // capture of FBO in RGBA
|
||||
Width = fb->width() * fb->projectionArea().x;
|
||||
Height = fb->height() * fb->projectionArea().y;
|
||||
|
||||
// blit the frame buffer into an RBBA copy of cropped size
|
||||
FrameBuffer copy(Width, Height, FrameBuffer::FrameBuffer_alpha);
|
||||
fb->blit(©);
|
||||
|
||||
// get pixels from copy
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, copy.opengl_id());
|
||||
|
||||
// do capture
|
||||
capture();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void Screenshot::save(std::string filename)
|
||||
{
|
||||
// is there something to save?
|
||||
@@ -108,35 +141,6 @@ void Screenshot::save(std::string filename)
|
||||
|
||||
}
|
||||
|
||||
void Screenshot::RemoveAlpha()
|
||||
{
|
||||
unsigned int* p = (unsigned int*)Data;
|
||||
int n = Width * Height;
|
||||
while (n-- > 0)
|
||||
{
|
||||
*p |= 0xFF000000;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
void Screenshot::FlipVertical()
|
||||
{
|
||||
int comp = 4;
|
||||
int stride = Width * comp;
|
||||
unsigned char* line_tmp = new unsigned char[stride];
|
||||
unsigned char* line_a = (unsigned char*)Data;
|
||||
unsigned char* line_b = (unsigned char*)Data + (stride * (Height - 1));
|
||||
while (line_a < line_b)
|
||||
{
|
||||
memcpy(line_tmp, line_a, stride);
|
||||
memcpy(line_a, line_b, stride);
|
||||
memcpy(line_b, line_tmp, stride);
|
||||
line_a += stride;
|
||||
line_b -= stride;
|
||||
}
|
||||
delete[] line_tmp;
|
||||
}
|
||||
|
||||
// Thread to perform slow operation of saving to file
|
||||
void Screenshot::storeToFile(Screenshot *s, std::string filename)
|
||||
{
|
||||
@@ -148,8 +152,9 @@ void Screenshot::storeToFile(Screenshot *s, std::string filename)
|
||||
// got data to save ?
|
||||
if (s && s->Data) {
|
||||
// save file
|
||||
stbi_flip_vertically_on_write(true);
|
||||
stbi_write_png(filename.c_str(), s->Width, s->Height, 3, s->Data, s->Width * 3);
|
||||
if (s->bpp < 4) // hack : inverse screen capture GL
|
||||
stbi_flip_vertically_on_write(true);
|
||||
stbi_write_png(filename.c_str(), s->Width, s->Height, s->bpp, s->Data, s->Width * s->bpp);
|
||||
}
|
||||
ScreenshotSavePending_ = false;
|
||||
}
|
||||
|
||||
@@ -5,15 +5,14 @@
|
||||
|
||||
class Screenshot
|
||||
{
|
||||
int Width, Height;
|
||||
int Width, Height, bpp;
|
||||
unsigned char * Data;
|
||||
unsigned int Pbo;
|
||||
unsigned int Pbo_size;
|
||||
bool Pbo_full;
|
||||
|
||||
void RemoveAlpha();
|
||||
void FlipVertical();
|
||||
static void storeToFile(Screenshot *s, std::string filename);
|
||||
void capture();
|
||||
|
||||
public:
|
||||
Screenshot();
|
||||
@@ -21,7 +20,8 @@ public:
|
||||
|
||||
// Quick usage :
|
||||
// 1) Capture screenshot
|
||||
void captureGL(int x, int y, int w, int h);
|
||||
void captureGL(int w, int h);
|
||||
void captureFramebuffer(class FrameBuffer *fb);
|
||||
// 2) if it is full after capture
|
||||
bool isFull();
|
||||
// 3) then you can save to file
|
||||
|
||||
@@ -170,6 +170,7 @@ void Settings::Save(uint64_t runtime)
|
||||
SourceConfNode->SetAttribute("new_type", application.source.new_type);
|
||||
SourceConfNode->SetAttribute("ratio", application.source.ratio);
|
||||
SourceConfNode->SetAttribute("res", application.source.res);
|
||||
SourceConfNode->SetAttribute("capture_path", application.source.capture_path.c_str());
|
||||
pRoot->InsertEndChild(SourceConfNode);
|
||||
|
||||
// Brush
|
||||
@@ -411,6 +412,12 @@ void Settings::Load()
|
||||
sourceconfnode->QueryIntAttribute("new_type", &application.source.new_type);
|
||||
sourceconfnode->QueryIntAttribute("ratio", &application.source.ratio);
|
||||
sourceconfnode->QueryIntAttribute("res", &application.source.res);
|
||||
|
||||
const char *path_ = recordnode->Attribute("capture_path");
|
||||
if (path_)
|
||||
application.source.capture_path = std::string(path_);
|
||||
else
|
||||
application.source.capture_path = SystemToolkit::home_path();
|
||||
}
|
||||
|
||||
// Transition
|
||||
|
||||
@@ -165,6 +165,7 @@ struct SourceConfig
|
||||
int new_type;
|
||||
int ratio;
|
||||
int res;
|
||||
std::string capture_path;
|
||||
|
||||
SourceConfig() {
|
||||
new_type = 0;
|
||||
|
||||
@@ -319,13 +319,8 @@ void UserInterface::handleKeyboard()
|
||||
Mixer::manager().view()->selectAll();
|
||||
}
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_R, false )) {
|
||||
if (shift_modifier_active) {
|
||||
FrameGrabbing::manager().add(new PNGRecorder);
|
||||
}
|
||||
else {
|
||||
// toggle recording stop / start (or save and continue if + ALT modifier)
|
||||
outputcontrol.ToggleRecord(alt_modifier_active);
|
||||
}
|
||||
// toggle recording stop / start (or save and continue if + ALT modifier)
|
||||
outputcontrol.ToggleRecord(alt_modifier_active);
|
||||
}
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_Z )) {
|
||||
if (shift_modifier_active)
|
||||
@@ -379,8 +374,15 @@ void UserInterface::handleKeyboard()
|
||||
Mixer::manager().setView(View::LAYER);
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_F4, false ))
|
||||
Mixer::manager().setView(View::TEXTURE);
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_F11, false ))
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_F9, false ))
|
||||
StartScreenshot();
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_F10, false ))
|
||||
sourcecontrol.Capture();
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_F11, false ))
|
||||
FrameGrabbing::manager().add(new PNGRecorder);
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_F12, false )) {
|
||||
Settings::application.render.disabled = !Settings::application.render.disabled;
|
||||
}
|
||||
// button home to toggle menu
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_HOME, false ))
|
||||
navigator.togglePannelMenu();
|
||||
@@ -405,9 +407,6 @@ void UserInterface::handleKeyboard()
|
||||
WorkspaceWindow::restoreWorkspace();
|
||||
esc_repeat_ = false;
|
||||
}
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_F12, false )) {
|
||||
Settings::application.render.disabled = !Settings::application.render.disabled;
|
||||
}
|
||||
// Space bar
|
||||
else if (ImGui::IsKeyPressed( GLFW_KEY_SPACE, false ))
|
||||
// Space bar to toggle play / pause
|
||||
@@ -1445,7 +1444,7 @@ void ToolBox::Render()
|
||||
{
|
||||
if (ImGui::BeginMenu("Render"))
|
||||
{
|
||||
if ( ImGui::MenuItem( ICON_FA_CAMERA_RETRO " Screenshot", "F12") )
|
||||
if ( ImGui::MenuItem( ICON_FA_CAMERA_RETRO " View screenshot", "F9") )
|
||||
UserInterface::manager().StartScreenshot();
|
||||
|
||||
ImGui::EndMenu();
|
||||
@@ -2142,6 +2141,8 @@ SourceController::SourceController() : WorkspaceWindow("SourceController"),
|
||||
mediaplayer_active_(nullptr), mediaplayer_edit_fading_(false), mediaplayer_mode_(false), mediaplayer_slider_pressed_(false), mediaplayer_timeline_zoom_(1.f)
|
||||
{
|
||||
info_.setExtendedStringMode();
|
||||
|
||||
captureFolderDialog = new DialogToolkit::OpenFolderDialog("Capture frame Location");
|
||||
}
|
||||
|
||||
|
||||
@@ -2150,10 +2151,11 @@ void SourceController::resetActiveSelection()
|
||||
info_.reset();
|
||||
active_selection_ = -1;
|
||||
active_label_ = LABEL_AUTO_MEDIA_PLAYER;
|
||||
play_toggle_request_ = false;
|
||||
replay_request_ = false;
|
||||
capture_request_ = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SourceController::setVisible(bool on)
|
||||
{
|
||||
// restore workspace to show the window
|
||||
@@ -2202,7 +2204,9 @@ void SourceController::Update()
|
||||
n_play++;
|
||||
}
|
||||
|
||||
// Play button or keyboard [space] was pressed
|
||||
//
|
||||
// Play button or keyboard [Space] was pressed
|
||||
//
|
||||
if ( play_toggle_request_ ) {
|
||||
|
||||
for (auto source = selectedsources.begin(); source != selectedsources.end(); ++source)
|
||||
@@ -2211,7 +2215,9 @@ void SourceController::Update()
|
||||
play_toggle_request_ = false;
|
||||
}
|
||||
|
||||
// Replay / rewind button or keyboard [B] was pressed
|
||||
//
|
||||
// Replay / rewind button or keyboard [CTRL+Space] was pressed
|
||||
//
|
||||
if ( replay_request_ ) {
|
||||
|
||||
for (auto source = selectedsources.begin(); source != selectedsources.end(); ++source)
|
||||
@@ -2220,6 +2226,31 @@ void SourceController::Update()
|
||||
replay_request_ = false;
|
||||
}
|
||||
|
||||
//
|
||||
// return from thread for selecting capture folder
|
||||
//
|
||||
if (captureFolderDialog->closed() && !captureFolderDialog->path().empty())
|
||||
// get the folder from this file dialog
|
||||
Settings::application.source.capture_path = captureFolderDialog->path();
|
||||
|
||||
//
|
||||
// Capture frame on current source
|
||||
//
|
||||
Source *source = Mixer::manager().currentSource();
|
||||
if (source != nullptr) {
|
||||
// back from capture of FBO: can save file
|
||||
if ( capture.isFull() ){
|
||||
std::string filename = SystemToolkit::full_filename( Settings::application.source.capture_path, source->name() + SystemToolkit::date_time_string() + ".png" );
|
||||
capture.save( filename );
|
||||
Log::Notify("Frame saved %s", filename.c_str() );
|
||||
}
|
||||
// request capture : initiate capture of FBO
|
||||
if ( capture_request_ ) {
|
||||
capture.captureFramebuffer(source->frame());
|
||||
capture_request_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
// reset on session change
|
||||
static Session *__session = nullptr;
|
||||
if ( Mixer::manager().session() != __session ) {
|
||||
@@ -2262,26 +2293,56 @@ void SourceController::Render()
|
||||
}
|
||||
if (ImGui::BeginMenu(IMGUI_TITLE_MEDIAPLAYER))
|
||||
{
|
||||
//
|
||||
// Menu section for play control
|
||||
if (ImGui::MenuItem( ICON_FA_FAST_BACKWARD " Restart", CTRL_MOD"Space"))
|
||||
//
|
||||
if (ImGui::MenuItem( ICON_FA_FAST_BACKWARD " Restart", CTRL_MOD "Space", nullptr, !selection_.empty()))
|
||||
replay_request_ = true;
|
||||
if (ImGui::MenuItem( ICON_FA_PLAY " Play | Pause", "Space"))
|
||||
if (ImGui::MenuItem( ICON_FA_PLAY " Play | Pause", "Space", nullptr, !selection_.empty()))
|
||||
play_toggle_request_ = true;
|
||||
ImGui::Separator();
|
||||
|
||||
//
|
||||
// Menu for capture frame
|
||||
//
|
||||
if (ImGui::MenuItem( ICON_FA_CAMERA_RETRO " Capture frame", "F10", nullptr, !selection_.empty()))
|
||||
capture_request_ = true;
|
||||
// path
|
||||
static char* name_path[4] = { nullptr };
|
||||
if ( name_path[0] == nullptr ) {
|
||||
for (int i = 0; i < 4; ++i)
|
||||
name_path[i] = (char *) malloc( 1024 * sizeof(char));
|
||||
sprintf( name_path[1], "%s", ICON_FA_HOME " Home");
|
||||
sprintf( name_path[2], "%s", ICON_FA_FOLDER " Session location");
|
||||
sprintf( name_path[3], "%s", ICON_FA_FOLDER_PLUS " Select");
|
||||
}
|
||||
if (Settings::application.source.capture_path.empty())
|
||||
Settings::application.source.capture_path = SystemToolkit::home_path();
|
||||
sprintf( name_path[0], "%s", Settings::application.source.capture_path.c_str());
|
||||
int selected_path = 0;
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGui::Combo("Path", &selected_path, name_path, 4);
|
||||
if (selected_path > 2)
|
||||
captureFolderDialog->open();
|
||||
else if (selected_path > 1)
|
||||
Settings::application.source.capture_path = SystemToolkit::path_filename( Mixer::manager().session()->filename() );
|
||||
else if (selected_path > 0)
|
||||
Settings::application.source.capture_path = SystemToolkit::home_path();
|
||||
|
||||
ImGui::Separator();
|
||||
// Menu section for displayed image
|
||||
//
|
||||
// Menu section for display
|
||||
//
|
||||
if (ImGui::BeginMenu( ICON_FA_IMAGE " Displayed image"))
|
||||
{
|
||||
if (ImGuiToolkit::MenuItemIcon(8, 9, " Post-processed"))
|
||||
if (ImGuiToolkit::MenuItemIcon(8, 9, " Render"))
|
||||
Settings::application.widget.media_player_slider = 0.0;
|
||||
if (ImGuiToolkit::MenuItemIcon(6, 9, " Split view"))
|
||||
if (ImGuiToolkit::MenuItemIcon(6, 9, " Split"))
|
||||
Settings::application.widget.media_player_slider = 0.5;
|
||||
if (ImGuiToolkit::MenuItemIcon(7, 9, " Pre-processed"))
|
||||
if (ImGuiToolkit::MenuItemIcon(7, 9, " Input"))
|
||||
Settings::application.widget.media_player_slider = 1.0;
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
// Menu section for list
|
||||
if (ImGui::MenuItem( ICON_FA_TH " List all")) {
|
||||
selection_.clear();
|
||||
resetActiveSelection();
|
||||
@@ -2289,13 +2350,15 @@ void SourceController::Render()
|
||||
Mixer::selection().clear();
|
||||
selection_ = playable_only( Mixer::manager().session()->getDepthSortedList() );
|
||||
}
|
||||
if (ImGui::MenuItem( ICON_FA_ELLIPSIS_H " List none")) {
|
||||
if (ImGui::MenuItem( ICON_FA_MINUS " Clear")) {
|
||||
selection_.clear();
|
||||
resetActiveSelection();
|
||||
Mixer::manager().unsetCurrentSource();
|
||||
Mixer::selection().clear();
|
||||
}
|
||||
//
|
||||
// Menu section for window management
|
||||
//
|
||||
ImGui::Separator();
|
||||
bool pinned = Settings::application.widget.media_player_view == Settings::application.current_view;
|
||||
std::string menutext = std::string( ICON_FA_MAP_PIN " Stick to ") + Settings::application.views[Settings::application.current_view].name + " view";
|
||||
@@ -2389,18 +2452,6 @@ void SourceController::Render()
|
||||
mediaplayer_active_->setRewindOnDisabled(true);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
// if (ImGui::BeginMenu(ICON_FA_CUT " Auto cut" ))
|
||||
// {
|
||||
// if (ImGuiToolkit::MenuItemIcon(14, 12, "Cut faded areas" ))
|
||||
// if (mediaplayer_active_->timeline()->autoCut()){
|
||||
// std::ostringstream oss;
|
||||
// oss << SystemToolkit::base_filename( mediaplayer_active_->filename() );
|
||||
// oss << ": Cut faded areas";
|
||||
// Action::manager().store(oss.str());
|
||||
// }
|
||||
// ImGui::EndMenu();
|
||||
// }
|
||||
if (Settings::application.render.gpu_decoding)
|
||||
{
|
||||
ImGui::Separator();
|
||||
@@ -3877,6 +3928,7 @@ void OutputPreview::Render()
|
||||
UserInterface::manager().navigator.showConfig();
|
||||
ImGui::SameLine(0);
|
||||
ImGui::Text("Settings");
|
||||
|
||||
// BASIC OPTIONS
|
||||
static char* name_path[4] = { nullptr };
|
||||
if ( name_path[0] == nullptr ) {
|
||||
@@ -3889,7 +3941,6 @@ void OutputPreview::Render()
|
||||
if (Settings::application.record.path.empty())
|
||||
Settings::application.record.path = SystemToolkit::home_path();
|
||||
sprintf( name_path[0], "%s", Settings::application.record.path.c_str());
|
||||
|
||||
int selected_path = 0;
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGui::Combo("Path", &selected_path, name_path, 4);
|
||||
@@ -3902,6 +3953,7 @@ void OutputPreview::Render()
|
||||
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGuiToolkit::SliderTiming ("Duration", &Settings::application.record.timeout, 1000, RECORD_MAX_TIMEOUT, 1000, "Until stopped");
|
||||
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGui::SliderInt("Trigger", &Settings::application.record.delay, 0, 5,
|
||||
Settings::application.record.delay < 1 ? "Immediate" : "After %d s");
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
#define MENU_RECORDCONT ICON_FA_STOP_CIRCLE " Save & continue"
|
||||
#define SHORTCUT_RECORDCONT CTRL_MOD "Alt+R"
|
||||
#define MENU_CAPTUREFRAME ICON_FA_CAMERA_RETRO " Capture frame"
|
||||
#define SHORTCUT_CAPTUREFRAME CTRL_MOD "Shitf+R"
|
||||
#define SHORTCUT_CAPTUREFRAME "F11"
|
||||
#define MENU_OUTPUTDISABLE ICON_FA_EYE_SLASH " Disable"
|
||||
#define SHORTCUT_OUTPUTDISABLE "F12"
|
||||
#define MENU_OUTPUTFULLSCREEN ICON_FA_EXPAND_ALT " Fullscreen window"
|
||||
@@ -101,6 +101,7 @@
|
||||
#include "DialogToolkit.h"
|
||||
#include "SessionParser.h"
|
||||
#include "ImageFilter.h"
|
||||
#include "Screenshot.h"
|
||||
|
||||
|
||||
struct ImVec2;
|
||||
@@ -269,7 +270,7 @@ class SourceController : public WorkspaceWindow
|
||||
float buttons_width_;
|
||||
float buttons_height_;
|
||||
|
||||
bool play_toggle_request_, replay_request_;
|
||||
bool play_toggle_request_, replay_request_, capture_request_;
|
||||
bool pending_;
|
||||
std::string active_label_;
|
||||
int active_selection_;
|
||||
@@ -303,11 +304,16 @@ class SourceController : public WorkspaceWindow
|
||||
float mediaplayer_timeline_zoom_;
|
||||
void RenderMediaPlayer(MediaSource *ms);
|
||||
|
||||
// dialog to select frame capture location
|
||||
DialogToolkit::OpenFolderDialog *captureFolderDialog;
|
||||
Screenshot capture;
|
||||
|
||||
public:
|
||||
SourceController();
|
||||
|
||||
inline void Play() { play_toggle_request_ = true; }
|
||||
inline void Replay() { replay_request_= true; }
|
||||
inline void Capture(){ capture_request_= true; }
|
||||
void resetActiveSelection();
|
||||
|
||||
void setVisible(bool on);
|
||||
|
||||
Reference in New Issue
Block a user