Improve UI with CollapsingHeader

Session and Settings panels cleaner with collapsing headers that are saved in settings
This commit is contained in:
Bruno Herbelin
2025-03-02 23:15:24 +01:00
parent d01366d069
commit f9463d1149
6 changed files with 471 additions and 444 deletions

View File

@@ -1,7 +1,7 @@
#ifndef GEOMETRYVIEW_H
#define GEOMETRYVIEW_H
// #define ENABLE_CANVAS
#define ENABLE_CANVAS
#include "View.h"

View File

@@ -29,6 +29,8 @@
#include "ImGuiToolkit.h"
#include "imgui_internal.h"
#include <GLFW/glfw3.h>
#include "defines.h"
#include "BaseToolkit.h"
#include "Settings.h"
@@ -703,6 +705,28 @@ void InputMappingWindow::Render()
if ( ImGui::MenuItem( ICON_FA_BACKSPACE " Clear all" ) )
S->clearInputCallbacks();
// Gamepad selection
ImGui::Separator();
float combo_width = ImGui::GetTextLineHeightWithSpacing() * 7.f;
ImGui::SetNextItemWidth(combo_width);
char text_buf[256];
if ( glfwJoystickPresent( Settings::application.gamepad_id ) )
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s", glfwGetJoystickName(Settings::application.gamepad_id));
else
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "Joystick %d", Settings::application.gamepad_id);
if (ImGui::BeginCombo("Gamepad", text_buf, ImGuiComboFlags_None)) {
for( int g = GLFW_JOYSTICK_1; g < GLFW_JOYSTICK_LAST; ++g) {
if ( glfwJoystickPresent( g ) ) {
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s", glfwGetJoystickName(g));
if (ImGui::Selectable(text_buf, Settings::application.gamepad_id == g) ) {
Settings::application.gamepad_id = g;
}
}
}
ImGui::EndCombo();
}
// output manager menu
ImGui::Separator();
bool pinned = Settings::application.widget.inputs_view == Settings::application.current_view;

View File

@@ -323,8 +323,10 @@ void OutputPreviewWindow::Render()
// offer to open config panel from here for more options
ImGui::SameLine(combo_width, IMGUI_SAME_LINE);
if (ImGuiToolkit::IconButton(13, 5, "Advanced settings"))
if (ImGuiToolkit::IconButton(13, 5, "Settings")) {
Settings::application.pannel_settings[0] = true;
UserInterface::manager().navigator.showConfig();
}
// BASIC OPTIONS
static char* name_path[4] = { nullptr };

View File

@@ -156,7 +156,13 @@ void Settings::Save(uint64_t runtime, const std::string &filename)
applicationNode->SetAttribute("accept_connections", application.accept_connections);
applicationNode->SetAttribute("pannel_main_mode", application.pannel_main_mode);
applicationNode->SetAttribute("pannel_playlist_mode", application.pannel_playlist_mode);
applicationNode->SetAttribute("pannel_history_mode", application.pannel_current_session_mode);
applicationNode->SetAttribute("pannel_session_0", application.pannel_session[0]);
applicationNode->SetAttribute("pannel_session_1", application.pannel_session[1]);
applicationNode->SetAttribute("pannel_session_2", application.pannel_session[2]);
applicationNode->SetAttribute("pannel_settings_0", application.pannel_settings[0]);
applicationNode->SetAttribute("pannel_settings_1", application.pannel_settings[1]);
applicationNode->SetAttribute("pannel_settings_2", application.pannel_settings[2]);
applicationNode->SetAttribute("pannel_settings_3", application.pannel_settings[3]);
applicationNode->SetAttribute("pannel_always_visible", application.pannel_always_visible);
applicationNode->SetAttribute("stream_protocol", application.stream_protocol);
applicationNode->SetAttribute("broadcast_port", application.broadcast_port);
@@ -485,7 +491,13 @@ void Settings::Load(const std::string &filename)
applicationNode->QueryBoolAttribute("pannel_always_visible", &application.pannel_always_visible);
applicationNode->QueryIntAttribute("pannel_main_mode", &application.pannel_main_mode);
applicationNode->QueryIntAttribute("pannel_playlist_mode", &application.pannel_playlist_mode);
applicationNode->QueryIntAttribute("pannel_history_mode", &application.pannel_current_session_mode);
applicationNode->QueryBoolAttribute("pannel_session_0", &application.pannel_session[0]);
applicationNode->QueryBoolAttribute("pannel_session_1", &application.pannel_session[1]);
applicationNode->QueryBoolAttribute("pannel_session_2", &application.pannel_session[2]);
applicationNode->QueryBoolAttribute("pannel_settings_0", &application.pannel_settings[0]);
applicationNode->QueryBoolAttribute("pannel_settings_1", &application.pannel_settings[1]);
applicationNode->QueryBoolAttribute("pannel_settings_2", &application.pannel_settings[2]);
applicationNode->QueryBoolAttribute("pannel_settings_3", &application.pannel_settings[3]);
applicationNode->QueryIntAttribute("stream_protocol", &application.stream_protocol);
applicationNode->QueryIntAttribute("broadcast_port", &application.broadcast_port);
applicationNode->QueryIntAttribute("loopback_camera", &application.loopback_camera);

View File

@@ -297,8 +297,9 @@ struct Application
int pannel_main_mode;
int pannel_playlist_mode;
int pannel_current_session_mode;
bool pannel_session[3];
bool pannel_always_visible;
bool pannel_settings[4];
// connection settings
bool accept_connections;
@@ -387,7 +388,9 @@ struct Application
shm_socket_path = "";
pannel_main_mode = 0;
pannel_playlist_mode = 0;
pannel_current_session_mode = 0;
pannel_session[0] = true;
pannel_session[1] = false;
pannel_session[2] = false;
current_view = 1;
current_workspace= 3;
brush = glm::vec3(0.5f, 0.1f, 0.f);

View File

@@ -4841,18 +4841,17 @@ void Navigator::RenderMainPannelSession()
}
}
//
// Menu for actions on current session
ImGui::SetCursorPos( ImVec2( pos.x, pos.y + preview_height));
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("##Selectpanelsession", &Settings::application.pannel_current_session_mode,
ICON_FA_CODE_BRANCH " Versions\0" ICON_FA_HISTORY " Undo history\0" ICON_FA_BORDER_STYLE " Resolution\0");
ImVec2 pos_bot = ImGui::GetCursorPos();
ImVec2 pos_bot = ImGui::GetCursorPos();
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.f,0.f,0.f,0.f));
//
// Current 2. RESOLUTION
// RESOLUTION
//
if (Settings::application.pannel_current_session_mode > 1) {
Settings::application.pannel_session[0] = ImGui::CollapsingHeader("Resolution",
Settings::application.pannel_session[0] ? ImGuiTreeNodeFlags_DefaultOpen : 0);
if (Settings::application.pannel_session[0]) {
// Information and resolution
const FrameBuffer *output = Mixer::manager().session()->frame();
@@ -4927,124 +4926,14 @@ void Navigator::RenderMainPannelSession()
}
}
//
// Current 1. UNDO History
// VERSIONS
//
else if (Settings::application.pannel_current_session_mode > 0) {
static uint _over = 0;
static uint64_t _displayed_over = 0;
static bool _tooltip = 0;
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y -ImGui::GetFrameHeight() ));
if ( Action::manager().current() > Action::manager().min() ) {
if ( ImGuiToolkit::IconButton( ICON_FA_UNDO, "Undo" ) )
Action::manager().undo();
} else
ImGui::TextDisabled( ICON_FA_UNDO );
ImGui::SameLine();
if ( Action::manager().current() < Action::manager().max() ) {
if ( ImGuiToolkit::IconButton( ICON_FA_REDO, "Redo" ))
Action::manager().redo();
} else
ImGui::TextDisabled( ICON_FA_REDO );
// come back...
ImGui::SetCursorPos(pos_bot);
ImVec2 pos_top = ImGui::GetCursorPos();
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::ListBoxHeader("##UndoHistory", Action::manager().max(), CLAMP(Action::manager().max(), 4, 8)) ) {
int count_over = 0;
ImVec2 size = ImVec2( ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeight() );
for (uint i = Action::manager().max();
i >= Action::manager().min(); --i) {
if (ImGui::Selectable( Action::manager().shortlabel(i).c_str(), i == Action::manager().current(), ImGuiSelectableFlags_AllowDoubleClick, size )) {
// go to on double clic
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
Action::manager().stepTo(i);
else
// show tooltip on clic
_tooltip = true;
}
// mouse over
if (ImGui::IsItemHovered())
_over = i;
// if mouse over (only once)
if (_tooltip && _over > 0 && count_over < 1) {
static std::string text = "";
static Thumbnail _undo_thumbnail;
// load label and thumbnail only if current changed
if (_displayed_over != _over) {
_displayed_over = _over;
text = Action::manager().label(_over);
if (text.find_first_of(':') < text.size())
text = text.insert( text.find_first_of(':') + 2, 1, '\n');
FrameBufferImage *im = Action::manager().thumbnail(_over);
if (im) {
// set image content to thumbnail display
_undo_thumbnail.fill( im );
delete im;
}
else
_undo_thumbnail.reset();
}
// draw thumbnail in tooltip
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
ImGui::BeginTooltip();
_undo_thumbnail.Render(size.x);
ImGui::Text("%s", text.c_str());
ImGui::EndTooltip();
ImGui::PopStyleVar();
++count_over; // prevents display twice on item overlap
}
}
ImGui::ListBoxFooter();
}
// cancel tooltip and mouse over on mouse exit
if ( !ImGui::IsItemHovered()) {
_tooltip = false;
_displayed_over = _over = 0;
}
pos_bot = ImGui::GetCursorPos();
// right buttons
if ( Action::manager().max() > 1 ) {
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y ));
if (ImGuiToolkit::IconButton( 12, 14, "Clear history"))
Action::manager().init("Reset");
}
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - 2.f * ImGui::GetFrameHeightWithSpacing()));
ImGuiToolkit::HelpToolTip("History of actions (latest on top). "
"Double-clic on an action to restore its status.\n\n"
ICON_FA_MAP_MARKED_ALT " Enable Show in view to automatically "
"navigate to the view when the action is undone/redone.");
// toggle button for shhow in view
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - ImGui::GetFrameHeightWithSpacing()) );
ImGuiToolkit::ButtonToggle(ICON_FA_MAP_MARKED_ALT, &Settings::application.action_history_follow_view, "Show in view");
}
//
// Current 0. VERSIONS
//
else {
Settings::application.pannel_session[1] = ImGui::CollapsingHeader("Versions",
Settings::application.pannel_session[1] ? ImGuiTreeNodeFlags_DefaultOpen : 0);
if (Settings::application.pannel_session[1]){
static uint64_t _over = 0;
static bool _tooltip = 0;
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y -ImGui::GetFrameHeight() ));
if ( ImGuiToolkit::IconButton( ICON_FA_FILE_DOWNLOAD " +")) {
UserInterface::manager().saveOrSaveAs(true);
}
if (ImGui::IsItemHovered())
ImGuiToolkit::ToolTip("Save & Keep version");
// come back...
ImGui::SetCursorPos(pos_bot);
// list snapshots
std::list<uint64_t> snapshots = Action::manager().snapshots();
ImVec2 pos_top = ImGui::GetCursorPos();
@@ -5163,25 +5052,125 @@ void Navigator::RenderMainPannelSession()
// Right panel buton
pos_bot = ImGui::GetCursorPos();
// right buttons
if (!snapshots.empty()) {
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y ));
if (ImGuiToolkit::IconButton( 12, 14, "Clear list"))
Action::manager().clearSnapshots();
}
// right button
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y ));
if (ImGuiToolkit::IconButton( ICON_FA_CODE_BRANCH " +", "Save & Keep version"))
UserInterface::manager().saveOrSaveAs(true);
// ImGui::SameLine();
// if (!snapshots.empty()) {
// if (ImGuiToolkit::IconButton( 12, 14, "Clear list"))
// Action::manager().clearSnapshots();
// }
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - 2.f * ImGui::GetFrameHeightWithSpacing()));
ImGuiToolkit::HelpToolTip("Previous versions of the session (latest on top). "
"Double-clic on a version to restore it.\n\n"
ICON_FA_CODE_BRANCH " With iterative saving enabled, a new version "
"is kept each time the session is saved.");
"Double-clic on a version to restore it.");
// toggle button for versioning
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - ImGui::GetFrameHeightWithSpacing()) );
ImGuiToolkit::ButtonToggle(" " ICON_FA_CODE_BRANCH " ", &Settings::application.save_version_snapshot,"Iterative saving");
ImGuiToolkit::ButtonToggle(" " ICON_FA_CODE_BRANCH " ", &Settings::application.save_version_snapshot, "With iterative saving enabled, a new version "
"is kept each time the session is saved.");
ImGui::SetCursorPos( pos_bot );
}
//
// UNDO History
//
Settings::application.pannel_session[2] = ImGui::CollapsingHeader("Undo history",
Settings::application.pannel_session[2] ? ImGuiTreeNodeFlags_DefaultOpen : 0);
if (Settings::application.pannel_session[2]){
static uint _over = 0;
static uint64_t _displayed_over = 0;
static bool _tooltip = 0;
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.39f, 0.39f, 0.39f, 0.55f));
ImVec2 pos_top = ImGui::GetCursorPos();
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::ListBoxHeader("##UndoHistory", Action::manager().max(), CLAMP(Action::manager().max(), 4, 8)) ) {
int count_over = 0;
ImVec2 size = ImVec2( ImGui::GetContentRegionAvailWidth(), ImGui::GetTextLineHeight() );
for (uint i = Action::manager().max();
i >= Action::manager().min(); --i) {
if (ImGui::Selectable( Action::manager().shortlabel(i).c_str(), i == Action::manager().current(), ImGuiSelectableFlags_AllowDoubleClick, size )) {
// go to on double clic
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
Action::manager().stepTo(i);
else
// show tooltip on clic
_tooltip = true;
}
// mouse over
if (ImGui::IsItemHovered())
_over = i;
// if mouse over (only once)
if (_tooltip && _over > 0 && count_over < 1) {
static std::string text = "";
static Thumbnail _undo_thumbnail;
// load label and thumbnail only if current changed
if (_displayed_over != _over) {
_displayed_over = _over;
text = Action::manager().label(_over);
if (text.find_first_of(':') < text.size())
text = text.insert( text.find_first_of(':') + 2, 1, '\n');
FrameBufferImage *im = Action::manager().thumbnail(_over);
if (im) {
// set image content to thumbnail display
_undo_thumbnail.fill( im );
delete im;
}
else
_undo_thumbnail.reset();
}
// draw thumbnail in tooltip
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
ImGui::BeginTooltip();
_undo_thumbnail.Render(size.x);
ImGui::Text("%s", text.c_str());
ImGui::EndTooltip();
ImGui::PopStyleVar();
++count_over; // prevents display twice on item overlap
}
}
ImGui::ListBoxFooter();
}
// cancel tooltip and mouse over on mouse exit
if ( !ImGui::IsItemHovered()) {
_tooltip = false;
_displayed_over = _over = 0;
}
ImGui::PopStyleColor(1);
pos_bot = ImGui::GetCursorPos();
// right buttons
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y ));
if ( Action::manager().current() > Action::manager().min() ) {
if ( ImGuiToolkit::IconButton( ICON_FA_UNDO, MENU_UNDO, SHORTCUT_UNDO) )
Action::manager().undo();
} else
ImGui::TextDisabled( ICON_FA_UNDO );
ImGui::SameLine();
if ( Action::manager().current() < Action::manager().max() ) {
if ( ImGuiToolkit::IconButton( ICON_FA_REDO, MENU_REDO, SHORTCUT_REDO ))
Action::manager().redo();
} else
ImGui::TextDisabled( ICON_FA_REDO );
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - 2.f * ImGui::GetFrameHeightWithSpacing()));
ImGuiToolkit::HelpToolTip("History of actions (latest on top). "
"Double-clic on an action to restore its status.");
// toggle button for shhow in view
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - ImGui::GetFrameHeightWithSpacing()) );
ImGuiToolkit::ButtonToggle(ICON_FA_MAP_MARKED_ALT, &Settings::application.action_history_follow_view, "Enable Show in view to automatically "
"navigate to the view where the action was done.");
}
ImGui::PopStyleColor(1);
}
#define PLAYLIST_FAVORITES ICON_FA_HEART " Favorites"
@@ -5690,11 +5679,28 @@ void Navigator::RenderMainPannelPlaylist()
void Navigator::RenderMainPannelSettings()
{
ImGuiContext& g = *GImGui;
float align_x = g.FontSize + g.Style.FramePadding.x * 3;
//
// save settings
//
ImVec2 pos = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(pannel_width_ IMGUI_RIGHT_ALIGN, pos.y - 1.6 * ImGui::GetTextLineHeight()));
if ( ImGuiToolkit::IconButton(ICON_FA_SAVE,"Export settings\nYou can then "
"launch vimix with the option "
"'--settings filename.xml' "
"to restore output windows and configuration.") ){
// launch file dialog to select file to save settings
if (UserInterface::manager().settingsexportdialog)
UserInterface::manager().settingsexportdialog->open();
}
ImGui::SetCursorPos(pos);
//
// Appearance
//
int v = Settings::application.accent_color;
ImGui::SetCursorPosX(0.5f * width_);
if (ImGui::RadioButton("##Color", &v, v)){
Settings::application.accent_color = (v+1)%3;
ImGuiToolkit::SetAccentColor(static_cast<ImGuiToolkit::accent_color>(Settings::application.accent_color));
@@ -5704,7 +5710,7 @@ void Navigator::RenderMainPannelSettings()
if (ImGui::IsItemHovered())
ImGuiToolkit::ToolTip("Change accent color");
ImGui::SameLine();
ImGui::SetCursorPosX(width_);
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::InputFloat("##Scale", &Settings::application.scale, 0.1f, 0.1f, "%.1f")) {
Settings::application.scale = CLAMP(Settings::application.scale, 0.5f, 5.f);
@@ -5716,356 +5722,336 @@ void Navigator::RenderMainPannelSettings()
ImGui::GetIO().FontGlobalScale = Settings::application.scale;
}
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.f,0.f,0.f,0.f));
//
// Recording preferences
//
ImGuiToolkit::Spacing();
ImGui::TextDisabled("Recording");
Settings::application.pannel_settings[0] = ImGui::CollapsingHeader("Recording",
Settings::application.pannel_settings[0] ? ImGuiTreeNodeFlags_DefaultOpen : 0);
// select CODEC and FPS
ImGui::SetCursorPosX(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("##Codec",
&Settings::application.record.profile,
VideoRecorder::profile_name,
IM_ARRAYSIZE(VideoRecorder::profile_name));
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Codec"))
Settings::application.record.profile = 0;
if (Settings::application.pannel_settings[0]){
ImGui::SetCursorPosX(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("##Framerate",
&Settings::application.record.framerate_mode,
VideoRecorder::framerate_preset_name,
IM_ARRAYSIZE(VideoRecorder::framerate_preset_name));
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Framerate"))
Settings::application.record.framerate_mode = 1;
// compute number of frames in buffer and show warning sign if too low
const FrameBuffer *output = Mixer::manager().session()->frame();
if (output) {
guint64 nb = 0;
nb = VideoRecorder::buffering_preset_value[Settings::application.record.buffering_mode] / (output->width() * output->height() * 4);
char buf[512]; snprintf(buf, 512, "Buffer of %s can contain %ld frames (%dx%d), i.e. %.1f sec",
VideoRecorder::buffering_preset_name[Settings::application.record.buffering_mode],
(unsigned long)nb, output->width(), output->height(),
(float)nb / (float) VideoRecorder::framerate_preset_value[Settings::application.record.framerate_mode] );
ImGuiToolkit::Indication(buf, 4, 6);
ImGui::SameLine(0);
}
ImGui::SetCursorPosX(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::SliderInt("##Buffer", &Settings::application.record.buffering_mode, 0,
IM_ARRAYSIZE(VideoRecorder::buffering_preset_name)-1,
VideoRecorder::buffering_preset_name[Settings::application.record.buffering_mode]);
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Buffer"))
Settings::application.record.buffering_mode = 2;
ImGuiToolkit::Indication("Priority when buffer is full and recorder has to skip frames;\n"
ICON_FA_CARET_RIGHT " Duration: Correct duration, variable framerate.\n"
ICON_FA_CARET_RIGHT " Framerate: Correct framerate, shorter duration.",
ICON_FA_CHECK_DOUBLE);
ImGui::SameLine(0);
ImGui::SetCursorPosX(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
const char *prioritylabel[2] = {"Duration", "Framerate"};
if (ImGui::BeginCombo("##Priority", prioritylabel[Settings::application.record.priority_mode])) {
if (ImGui::Selectable(prioritylabel[0], Settings::application.record.priority_mode == 0))
Settings::application.record.priority_mode = 0;
if (!Settings::application.accept_audio || Settings::application.record.audio_device.empty()) {
if (ImGui::Selectable(prioritylabel[1], Settings::application.record.priority_mode == 1))
Settings::application.record.priority_mode = 1;
} else {
ImGui::Selectable(prioritylabel[1], false, ImGuiSelectableFlags_Disabled);
if (ImGui::IsItemHovered())
ImGuiToolkit::ToolTip("Unable to set priority Framerate when recoding with audio.");
}
ImGui::EndCombo();
}
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Priority"))
Settings::application.record.priority_mode = 0;
//
// AUDIO
//
if (Settings::application.accept_audio) {
// Displayed name of current audio device
std::string current_audio = "None";
if (!Settings::application.record.audio_device.empty()) {
if (Audio::manager().exists(Settings::application.record.audio_device))
current_audio = Settings::application.record.audio_device;
else
Settings::application.record.audio_device = "";
}
// help indication
ImGuiToolkit::Indication("Select the audio to merge into the recording;\n"
ICON_FA_MICROPHONE_ALT_SLASH " no audio\n "
ICON_FA_MICROPHONE_ALT " a microphone input\n "
ICON_FA_VOLUME_DOWN " an audio output",
ICON_FA_MUSIC);
ImGui::SameLine(0);
// Combo selector of audio device
ImGui::SetCursorPosX(width_);
// select CODEC and FPS
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("##Audio", current_audio.c_str())) {
// No audio selection
if (ImGui::Selectable(ICON_FA_MICROPHONE_ALT_SLASH " None"))
Settings::application.record.audio_device = "";
// list of devices from Audio manager
for (int d = 0; d < Audio::manager().numDevices(); ++d) {
std::string namedev = Audio::manager().name(d);
std::string labeldev = (Audio::manager().is_monitor(d) ? ICON_FA_VOLUME_DOWN " "
: ICON_FA_MICROPHONE_ALT " ")
+ namedev;
if (ImGui::Selectable(labeldev.c_str())) {
Settings::application.record.audio_device = namedev;
// warning on recording mode
if (Settings::application.record.priority_mode > 0) {
Log::Notify( "When recording with audio, Priority mode must be set to 'Duration'.");
Settings::application.record.priority_mode=0;
}
}
ImGui::Combo("##Codec",
&Settings::application.record.profile,
VideoRecorder::profile_name,
IM_ARRAYSIZE(VideoRecorder::profile_name));
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Codec"))
Settings::application.record.profile = 0;
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("##Framerate",
&Settings::application.record.framerate_mode,
VideoRecorder::framerate_preset_name,
IM_ARRAYSIZE(VideoRecorder::framerate_preset_name));
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Framerate"))
Settings::application.record.framerate_mode = 1;
// compute number of frames in buffer and show warning sign if too low
const FrameBuffer *output = Mixer::manager().session()->frame();
if (output) {
guint64 nb = 0;
nb = VideoRecorder::buffering_preset_value[Settings::application.record.buffering_mode] / (output->width() * output->height() * 4);
char buf[512]; snprintf(buf, 512, "Buffer of %s can contain %ld frames (%dx%d), i.e. %.1f sec",
VideoRecorder::buffering_preset_name[Settings::application.record.buffering_mode],
(unsigned long)nb, output->width(), output->height(),
(float)nb / (float) VideoRecorder::framerate_preset_value[Settings::application.record.framerate_mode] );
ImGuiToolkit::Indication(buf, 4, 6);
ImGui::SameLine(0);
}
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::SliderInt("##Buffer", &Settings::application.record.buffering_mode, 0,
IM_ARRAYSIZE(VideoRecorder::buffering_preset_name)-1,
VideoRecorder::buffering_preset_name[Settings::application.record.buffering_mode]);
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Buffer"))
Settings::application.record.buffering_mode = 2;
ImGuiToolkit::Indication("Priority when buffer is full and recorder has to skip frames;\n"
ICON_FA_CARET_RIGHT " Duration: Correct duration, variable framerate.\n"
ICON_FA_CARET_RIGHT " Framerate: Correct framerate, shorter duration.",
ICON_FA_CHECK_DOUBLE);
ImGui::SameLine(0);
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
const char *prioritylabel[2] = {"Duration", "Framerate"};
if (ImGui::BeginCombo("##Priority", prioritylabel[Settings::application.record.priority_mode])) {
if (ImGui::Selectable(prioritylabel[0], Settings::application.record.priority_mode == 0))
Settings::application.record.priority_mode = 0;
if (!Settings::application.accept_audio || Settings::application.record.audio_device.empty()) {
if (ImGui::Selectable(prioritylabel[1], Settings::application.record.priority_mode == 1))
Settings::application.record.priority_mode = 1;
} else {
ImGui::Selectable(prioritylabel[1], false, ImGuiSelectableFlags_Disabled);
if (ImGui::IsItemHovered())
ImGuiToolkit::ToolTip("Unable to set priority Framerate when recoding with audio.");
}
ImGui::EndCombo();
}
if (!Settings::application.record.audio_device.empty() && ImGui::IsItemHovered())
ImGuiToolkit::ToolTip(current_audio.c_str());
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Audio"))
Settings::application.record.audio_device = "";
if (ImGuiToolkit::TextButton("Priority"))
Settings::application.record.priority_mode = 0;
//
// AUDIO
//
if (Settings::application.accept_audio) {
// Displayed name of current audio device
std::string current_audio = "None";
if (!Settings::application.record.audio_device.empty()) {
if (Audio::manager().exists(Settings::application.record.audio_device))
current_audio = Settings::application.record.audio_device;
else
Settings::application.record.audio_device = "";
}
// help indication
ImGuiToolkit::Indication("Select the audio to merge into the recording;\n"
ICON_FA_MICROPHONE_ALT_SLASH " no audio\n "
ICON_FA_MICROPHONE_ALT " a microphone input\n "
ICON_FA_VOLUME_DOWN " an audio output",
ICON_FA_MUSIC);
ImGui::SameLine(0);
// Combo selector of audio device
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("##Audio", current_audio.c_str())) {
// No audio selection
if (ImGui::Selectable(ICON_FA_MICROPHONE_ALT_SLASH " None"))
Settings::application.record.audio_device = "";
// list of devices from Audio manager
for (int d = 0; d < Audio::manager().numDevices(); ++d) {
std::string namedev = Audio::manager().name(d);
std::string labeldev = (Audio::manager().is_monitor(d) ? ICON_FA_VOLUME_DOWN " "
: ICON_FA_MICROPHONE_ALT " ")
+ namedev;
if (ImGui::Selectable(labeldev.c_str())) {
Settings::application.record.audio_device = namedev;
// warning on recording mode
if (Settings::application.record.priority_mode > 0) {
Log::Notify( "When recording with audio, Priority mode must be set to 'Duration'.");
Settings::application.record.priority_mode=0;
}
}
}
ImGui::EndCombo();
}
if (!Settings::application.record.audio_device.empty() && ImGui::IsItemHovered())
ImGuiToolkit::ToolTip(current_audio.c_str());
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Audio"))
Settings::application.record.audio_device = "";
}
}
//
// Steaming preferences
//
ImGuiToolkit::Spacing();
ImGui::TextDisabled("Stream");
Settings::application.pannel_settings[1] = ImGui::CollapsingHeader("Stream",
Settings::application.pannel_settings[1] ? ImGuiTreeNodeFlags_DefaultOpen : 0);
ImGuiToolkit::Indication("Peer-to-peer sharing local network\n\n"
"vimix can stream JPEG (default) or H264 (less bandwidth, higher encoding cost)", ICON_FA_SHARE_ALT_SQUARE);
ImGui::SameLine(0);
ImGui::SetCursorPosX(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("##P2P codec", &Settings::application.stream_protocol, "JPEG\0H264\0");
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("P2P codec"))
Settings::application.stream_protocol = 0;
if (VideoBroadcast::available()) {
std::ostringstream msg;
msg << "SRT Broadcast" << std::endl << std::endl;
msg << "vimix listens to SRT requests on Port " << Settings::application.broadcast_port << std::endl << std::endl;
msg << "Valid network addresses :" << std::endl;
for (const auto& ips : NetworkToolkit::host_ips()){
msg << "srt://" << ips << ":" << Settings::application.broadcast_port << std::endl;
}
ImGuiToolkit::Indication(msg.str().c_str(), ICON_FA_GLOBE);
if (Settings::application.pannel_settings[1]){
ImGuiToolkit::Indication("Peer-to-peer sharing local network\n\n"
"vimix can stream JPEG (default) or H264 (less bandwidth, higher encoding cost)", ICON_FA_SHARE_ALT_SQUARE);
ImGui::SameLine(0);
ImGui::SetCursorPosX(width_);
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
char bufport[7] = "";
snprintf(bufport, 7, "%d", Settings::application.broadcast_port);
ImGui::InputTextWithHint("##SRT Port", "7070", bufport, 6, ImGuiInputTextFlags_CharsDecimal);
if (ImGui::IsItemDeactivatedAfterEdit()){
if ( BaseToolkit::is_a_number(bufport, &Settings::application.broadcast_port))
Settings::application.broadcast_port = CLAMP(Settings::application.broadcast_port, 1029, 49150);
}
ImGui::Combo("##P2P codec", &Settings::application.stream_protocol, "JPEG\0H264\0");
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("SRT Port"))
Settings::application.broadcast_port = 7070;
}
if (ImGuiToolkit::TextButton("P2P codec"))
Settings::application.stream_protocol = 0;
if (ShmdataBroadcast::available()) {
std::string _shm_socket_file = Settings::application.shm_socket_path;
if (_shm_socket_file.empty() || !SystemToolkit::file_exists(_shm_socket_file))
_shm_socket_file = SystemToolkit::home_path();
_shm_socket_file = SystemToolkit::full_filename(_shm_socket_file, ".shm_vimix" + std::to_string(Settings::application.instance_id));
if (VideoBroadcast::available()) {
char msg[256];
if (ShmdataBroadcast::available(ShmdataBroadcast::SHM_SHMDATASINK)) {
ImFormatString(msg, IM_ARRAYSIZE(msg), "Shared Memory\n\n"
"vimix can share to RAM with "
"gstreamer default 'shmsink' "
"and with 'shmdatasink'.\n\n"
"Socket file to connect to:\n%s\n",
_shm_socket_file.c_str());
}
else {
ImFormatString(msg, IM_ARRAYSIZE(msg), "Shared Memory\n\n"
"vimix can share to RAM with "
"gstreamer 'shmsink'.\n\n"
"Socket file to connect to:\n%s\n",
_shm_socket_file.c_str());
}
ImGuiToolkit::Indication(msg, ICON_FA_MEMORY);
ImGui::SameLine(0);
ImGui::SetCursorPosX(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
char bufsocket[128] = "";
snprintf(bufsocket, 128, "%s", Settings::application.shm_socket_path.c_str());
ImGui::InputTextWithHint("##SHM path", SystemToolkit::home_path().c_str(), bufsocket, 128);
if (ImGui::IsItemDeactivatedAfterEdit()) {
Settings::application.shm_socket_path = bufsocket;
}
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("SHM path"))
Settings::application.shm_socket_path = "";
if (ShmdataBroadcast::available(ShmdataBroadcast::SHM_SHMDATASINK)) {
ImGui::SetCursorPosX(width_);
std::ostringstream msg;
msg << "SRT Broadcast" << std::endl << std::endl;
msg << "vimix listens to SRT requests on Port " << Settings::application.broadcast_port << std::endl << std::endl;
msg << "Valid network addresses :" << std::endl;
for (const auto& ips : NetworkToolkit::host_ips()){
msg << "srt://" << ips << ":" << Settings::application.broadcast_port << std::endl;
}
ImGuiToolkit::Indication(msg.str().c_str(), ICON_FA_GLOBE);
ImGui::SameLine(0);
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("SHM sink", &Settings::application.shm_method, "shmsink\0shmdatasink\0");
char bufport[7] = "";
snprintf(bufport, 7, "%d", Settings::application.broadcast_port);
ImGui::InputTextWithHint("##SRT Port", "7070", bufport, 6, ImGuiInputTextFlags_CharsDecimal);
if (ImGui::IsItemDeactivatedAfterEdit()){
if ( BaseToolkit::is_a_number(bufport, &Settings::application.broadcast_port))
Settings::application.broadcast_port = CLAMP(Settings::application.broadcast_port, 1029, 49150);
}
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("SRT Port"))
Settings::application.broadcast_port = 7070;
}
if (ShmdataBroadcast::available()) {
std::string _shm_socket_file = Settings::application.shm_socket_path;
if (_shm_socket_file.empty() || !SystemToolkit::file_exists(_shm_socket_file))
_shm_socket_file = SystemToolkit::home_path();
_shm_socket_file = SystemToolkit::full_filename(_shm_socket_file, ".shm_vimix" + std::to_string(Settings::application.instance_id));
char msg[256];
if (ShmdataBroadcast::available(ShmdataBroadcast::SHM_SHMDATASINK)) {
ImFormatString(msg, IM_ARRAYSIZE(msg), "Shared Memory\n\n"
"vimix can share to RAM with "
"gstreamer default 'shmsink' "
"and with 'shmdatasink'.\n\n"
"Socket file to connect to:\n%s\n",
_shm_socket_file.c_str());
}
else {
ImFormatString(msg, IM_ARRAYSIZE(msg), "Shared Memory\n\n"
"vimix can share to RAM with "
"gstreamer 'shmsink'.\n\n"
"Socket file to connect to:\n%s\n",
_shm_socket_file.c_str());
}
ImGuiToolkit::Indication(msg, ICON_FA_MEMORY);
ImGui::SameLine(0);
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
char bufsocket[128] = "";
snprintf(bufsocket, 128, "%s", Settings::application.shm_socket_path.c_str());
ImGui::InputTextWithHint("##SHM path", SystemToolkit::home_path().c_str(), bufsocket, 128);
if (ImGui::IsItemDeactivatedAfterEdit()) {
Settings::application.shm_socket_path = bufsocket;
}
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("SHM path"))
Settings::application.shm_socket_path = "";
if (ShmdataBroadcast::available(ShmdataBroadcast::SHM_SHMDATASINK)) {
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("SHM sink", &Settings::application.shm_method, "shmsink\0shmdatasink\0");
}
}
}
//
// OSC preferences
//
ImGuiToolkit::Spacing();
ImGui::TextDisabled("OSC");
Settings::application.pannel_settings[2] = ImGui::CollapsingHeader("OSC",
Settings::application.pannel_settings[2] ? ImGuiTreeNodeFlags_DefaultOpen : 0);
std::ostringstream msg;
msg << "Open Sound Control" << std::endl << std::endl;
msg << "vimix accepts OSC messages sent by UDP on Port " << Settings::application.control.osc_port_receive;
msg << " and replies on Port " << Settings::application.control.osc_port_send << std::endl << std::endl;
msg << "Valid network addresses:" << std::endl;
for (const auto& ips : NetworkToolkit::host_ips()){
msg << "udp://" << ips << ":" << Settings::application.control.osc_port_receive << std::endl;
}
ImGuiToolkit::Indication(msg.str().c_str(), ICON_FA_NETWORK_WIRED);
ImGui::SameLine(0);
if (Settings::application.pannel_settings[2]){
// ImGuiToolkit::Spacing();
// ImGui::TextDisabled("OSC");
ImGui::SetCursorPosX(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
char bufreceive[7] = "";
snprintf(bufreceive, 7, "%d", Settings::application.control.osc_port_receive);
ImGui::InputTextWithHint("##Port in", "7000", bufreceive, 7, ImGuiInputTextFlags_CharsDecimal);
if (ImGui::IsItemDeactivatedAfterEdit()){
if ( BaseToolkit::is_a_number(bufreceive, &Settings::application.control.osc_port_receive)){
Settings::application.control.osc_port_receive = CLAMP(Settings::application.control.osc_port_receive, 1029, 49150);
Control::manager().init();
std::ostringstream msg;
msg << "Open Sound Control" << std::endl << std::endl;
msg << "vimix accepts OSC messages sent by UDP on Port " << Settings::application.control.osc_port_receive;
msg << " and replies on Port " << Settings::application.control.osc_port_send << std::endl << std::endl;
msg << "Valid network addresses:" << std::endl;
for (const auto& ips : NetworkToolkit::host_ips()){
msg << "udp://" << ips << ":" << Settings::application.control.osc_port_receive << std::endl;
}
}
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Port in"))
Settings::application.control.osc_port_receive = OSC_PORT_RECV_DEFAULT;
ImGuiToolkit::Indication(msg.str().c_str(), ICON_FA_NETWORK_WIRED);
ImGui::SameLine(0);
ImGui::SetCursorPosX(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
char bufsend[7] = "";
snprintf(bufsend, 7, "%d", Settings::application.control.osc_port_send);
ImGui::InputTextWithHint("##Port out", "7001", bufsend, 7, ImGuiInputTextFlags_CharsDecimal);
if (ImGui::IsItemDeactivatedAfterEdit()){
if ( BaseToolkit::is_a_number(bufsend, &Settings::application.control.osc_port_send)){
Settings::application.control.osc_port_send = CLAMP(Settings::application.control.osc_port_send, 1029, 49150);
Control::manager().init();
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
char bufreceive[7] = "";
snprintf(bufreceive, 7, "%d", Settings::application.control.osc_port_receive);
ImGui::InputTextWithHint("##Port in", "7000", bufreceive, 7, ImGuiInputTextFlags_CharsDecimal);
if (ImGui::IsItemDeactivatedAfterEdit()){
if ( BaseToolkit::is_a_number(bufreceive, &Settings::application.control.osc_port_receive)){
Settings::application.control.osc_port_receive = CLAMP(Settings::application.control.osc_port_receive, 1029, 49150);
Control::manager().init();
}
}
}
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Port out"))
Settings::application.control.osc_port_send = OSC_PORT_SEND_DEFAULT;
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Port in"))
Settings::application.control.osc_port_receive = OSC_PORT_RECV_DEFAULT;
ImGui::SetCursorPosX(width_);
const float w = IMGUI_RIGHT_ALIGN - ImGui::GetFrameHeightWithSpacing();
ImGuiToolkit::ButtonOpenUrl( "Edit", Settings::application.control.osc_filename.c_str(), ImVec2(w, 0) );
ImGui::SameLine(0, 6);
if ( ImGuiToolkit::IconButton(15, 12, "Reload") )
Control::manager().init();
ImGui::SameLine();
ImGui::Text("Translator");
ImGui::SetCursorPosX(align_x);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
char bufsend[7] = "";
snprintf(bufsend, 7, "%d", Settings::application.control.osc_port_send);
ImGui::InputTextWithHint("##Port out", "7001", bufsend, 7, ImGuiInputTextFlags_CharsDecimal);
if (ImGui::IsItemDeactivatedAfterEdit()){
if ( BaseToolkit::is_a_number(bufsend, &Settings::application.control.osc_port_send)){
Settings::application.control.osc_port_send = CLAMP(Settings::application.control.osc_port_send, 1029, 49150);
Control::manager().init();
}
}
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Port out"))
Settings::application.control.osc_port_send = OSC_PORT_SEND_DEFAULT;
ImGui::SetCursorPosX(align_x);
const float w = IMGUI_RIGHT_ALIGN - ImGui::GetFrameHeightWithSpacing();
ImGuiToolkit::ButtonOpenUrl( "Edit", Settings::application.control.osc_filename.c_str(), ImVec2(w, 0) );
ImGui::SameLine(0, 6);
if ( ImGuiToolkit::IconButton(15, 12, "Reload") )
Control::manager().init();
ImGui::SameLine();
ImGui::Text("Translator");
}
//
// System preferences
//
ImGuiToolkit::Spacing();
ImGui::TextDisabled("System");
ImGui::SameLine();
Settings::application.pannel_settings[3] = ImGui::CollapsingHeader("System",
Settings::application.pannel_settings[3] ? ImGuiTreeNodeFlags_DefaultOpen : 0);
ImGui::SetCursorPosX( pannel_width_ IMGUI_RIGHT_ALIGN);
if ( ImGuiToolkit::IconButton(ICON_FA_SAVE,"Export settings\nYou can then "
"launch vimix with the option "
"'--settings filename.xml' "
"to restore output windows and configuration.") ){
// launch file dialog to select file to save settings
if (UserInterface::manager().settingsexportdialog)
UserInterface::manager().settingsexportdialog->open();
}
ImGui::Spacing();
if (Settings::application.pannel_settings[3]){
static bool need_restart = false;
static bool vsync = (Settings::application.render.vsync > 0);
static bool multi = (Settings::application.render.multisampling > 0);
static bool gpu = Settings::application.render.gpu_decoding;
static bool audio = Settings::application.accept_audio;
bool change = false;
// hardware support deserves more explanation
ImGuiToolkit::Indication("If enabled, tries to find a platform adapted hardware-accelerated "
"driver to decode (read) or encode (record) videos.", gpu ? 13 : 14, 2);
ImGui::SameLine(0);
if (Settings::application.render.gpu_decoding_available)
change |= ImGuiToolkit::ButtonSwitch( "Hardware en/decoding", &gpu);
else
ImGui::TextDisabled("Hardware en/decoding unavailable");
// GAMEPAD
ImGui::SetCursorPosX(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
char text_buf[256];
if ( glfwJoystickPresent( Settings::application.gamepad_id ) )
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s", glfwGetJoystickName(Settings::application.gamepad_id));
else
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "Joystick %d", Settings::application.gamepad_id);
if (ImGui::BeginCombo("Gamepad", text_buf, ImGuiComboFlags_None)) {
for( int g = GLFW_JOYSTICK_1; g < GLFW_JOYSTICK_LAST; ++g) {
if ( glfwJoystickPresent( g ) ) {
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s", glfwGetJoystickName(g));
if (ImGui::Selectable(text_buf, Settings::application.gamepad_id == g) ) {
Settings::application.gamepad_id = g;
}
}
}
ImGui::EndCombo();
}
static bool need_restart = false;
static bool vsync = (Settings::application.render.vsync > 0);
static bool multi = (Settings::application.render.multisampling > 0);
static bool gpu = Settings::application.render.gpu_decoding;
static bool audio = Settings::application.accept_audio;
bool change = false;
// hardware support deserves more explanation
ImGuiToolkit::Indication("If enabled, tries to find a platform adapted hardware-accelerated "
"driver to decode (read) or encode (record) videos.", gpu ? 13 : 14, 2);
ImGui::SameLine(0);
if (Settings::application.render.gpu_decoding_available)
change |= ImGuiToolkit::ButtonSwitch( "Hardware en/decoding", &gpu);
else
ImGui::TextDisabled("Hardware en/decoding unavailable");
// audio support deserves more explanation
ImGuiToolkit::Indication("If enabled, tries to find audio in openned videos "
"and allows recording audio.", audio ? ICON_FA_VOLUME_UP : ICON_FA_VOLUME_MUTE);
ImGui::SameLine(0);
change |= ImGuiToolkit::ButtonSwitch( "Audio (experimental)", &audio);
// audio support deserves more explanation
ImGuiToolkit::Indication("If enabled, tries to find audio in openned videos "
"and allows recording audio.", audio ? ICON_FA_VOLUME_UP : ICON_FA_VOLUME_MUTE);
ImGui::SameLine(0);
change |= ImGuiToolkit::ButtonSwitch( "Audio (experimental)", &audio);
#ifndef NDEBUG
change |= ImGuiToolkit::ButtonSwitch( "Vertical synchronization", &vsync);
change |= ImGuiToolkit::ButtonSwitch( "Multisample antialiasing", &multi);
change |= ImGuiToolkit::ButtonSwitch( "Vertical synchronization", &vsync);
change |= ImGuiToolkit::ButtonSwitch( "Multisample antialiasing", &multi);
#endif
if (change) {
need_restart = ( vsync != (Settings::application.render.vsync > 0) ||
multi != (Settings::application.render.multisampling > 0) ||
gpu != Settings::application.render.gpu_decoding ||
audio != Settings::application.accept_audio );
}
if (need_restart) {
ImGuiToolkit::Spacing();
if (ImGui::Button( ICON_FA_POWER_OFF " Quit & restart to apply", ImVec2(ImGui::GetContentRegionAvail().x - 50, 0))) {
Settings::application.render.vsync = vsync ? 1 : 0;
Settings::application.render.multisampling = multi ? 3 : 0;
Settings::application.render.gpu_decoding = gpu;
Settings::application.accept_audio = audio;
if (UserInterface::manager().TryClose())
Rendering::manager().close();
if (change) {
need_restart = ( vsync != (Settings::application.render.vsync > 0) ||
multi != (Settings::application.render.multisampling > 0) ||
gpu != Settings::application.render.gpu_decoding ||
audio != Settings::application.accept_audio );
}
if (need_restart) {
ImGuiToolkit::Spacing();
if (ImGui::Button( ICON_FA_POWER_OFF " Quit & restart to apply", ImVec2(ImGui::GetContentRegionAvail().x - 50, 0))) {
Settings::application.render.vsync = vsync ? 1 : 0;
Settings::application.render.multisampling = multi ? 3 : 0;
Settings::application.render.gpu_decoding = gpu;
Settings::application.accept_audio = audio;
if (UserInterface::manager().TryClose())
Rendering::manager().close();
}
}
}
ImGui::PopStyleColor(1);
}
void Navigator::RenderTransitionPannel(const ImVec2 &iconsize)