Improve Layers view icons and Workspace management

Added 'Workspace any' in list of workspaces to allow Geometry view to list sources from all workspaces. Updated icon for layers view, in left panel and in view.
This commit is contained in:
Bruno Herbelin
2023-08-30 20:47:14 +02:00
parent de850b39f2
commit 124415363f
12 changed files with 2994 additions and 2856 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -229,11 +229,12 @@ void GeometryView::draw()
// only sources in the current workspace // only sources in the current workspace
std::vector<Node *> surfaces; std::vector<Node *> surfaces;
std::vector<Node *> overlays; std::vector<Node *> overlays;
uint workspaces_counts_[Source::WORKSPACE_ANY+1] = {0};
for (auto source_iter = Mixer::manager().session()->begin(); for (auto source_iter = Mixer::manager().session()->begin();
source_iter != Mixer::manager().session()->end(); ++source_iter) { source_iter != Mixer::manager().session()->end(); ++source_iter) {
// if it is in the current workspace // if it is in the current workspace
if ((*source_iter)->workspace() == Settings::application.current_workspace) { if (Settings::application.current_workspace == Source::WORKSPACE_ANY ||
// if ((*source_iter)->blendingShader()->color.a > 0.f) // TODO: option to hide non visible (*source_iter)->workspace() == Settings::application.current_workspace) {
{ {
// will draw its surface // will draw its surface
surfaces.push_back((*source_iter)->groups_[mode_]); surfaces.push_back((*source_iter)->groups_[mode_]);
@@ -242,6 +243,9 @@ void GeometryView::draw()
overlays.push_back((*source_iter)->locker_); overlays.push_back((*source_iter)->locker_);
} }
} }
// count number of sources per workspace
workspaces_counts_[(*source_iter)->workspace()]++;
workspaces_counts_[Source::WORKSPACE_ANY]++;
} }
// 0. prepare projection for draw visitors // 0. prepare projection for draw visitors
@@ -260,7 +264,8 @@ void GeometryView::draw()
scene.accept(draw_overlays); scene.accept(draw_overlays);
// 4. Draw control overlays of current source on top (if selected) // 4. Draw control overlays of current source on top (if selected)
if (s != nullptr && s->workspace() == Settings::application.current_workspace) { if (s != nullptr && (Settings::application.current_workspace == Source::WORKSPACE_ANY ||
s->workspace() == Settings::application.current_workspace) ) {
DrawVisitor dv(s->overlays_[mode_], projection); DrawVisitor dv(s->overlays_[mode_], projection);
scene.accept(dv); scene.accept(dv);
// Always restore current source after draw // Always restore current source after draw
@@ -296,14 +301,22 @@ void GeometryView::draw()
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.4f, 0.4f, 0.4f, 0.56f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.4f, 0.4f, 0.4f, 0.56f));
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f)); ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f));
static std::vector< std::tuple<int, int, std::string> > _workspaces = { static std::vector< std::string > _tooltips = {
{10, 16, "Only sources in Background layer"}, {"Sources in Background layers"},
{11, 16, "Only sources in Workspace layer"}, {"Sources in Workspace layers"},
{12, 16, "Only sources in Foreground layer"} {"Sources in Foreground layers"},
{"Sources in every layers (total)"}
};
std::vector< std::tuple<int, int, std::string> > _workspaces = {
{ICON_WORKSPACE_BACKGROUND, std::to_string( workspaces_counts_[Source::WORKSPACE_BACKGROUND] )},
{ICON_WORKSPACE_CENTRAL, std::to_string( workspaces_counts_[Source::WORKSPACE_CENTRAL] )},
{ICON_WORKSPACE_FOREGROUND, std::to_string( workspaces_counts_[Source::WORKSPACE_FOREGROUND] )},
{ICON_WORKSPACE, std::to_string( workspaces_counts_[Source::WORKSPACE_ANY] )}
}; };
ImGui::SetNextItemWidth( ImGui::GetTextLineHeight() * 2.6); ImGui::SetNextItemWidth( ImGui::GetTextLineHeight() * 2.6);
if ( ImGuiToolkit::ComboIcon ("##WORKSPACE", &Settings::application.current_workspace, _workspaces, true) ){ if ( ImGuiToolkit::ComboIcon ("##WORKSPACE", &Settings::application.current_workspace, _workspaces, _tooltips) ){
++View::need_deep_update_; // need full update
Mixer::manager().setView(mode_);
} }
ImGui::PopStyleColor(6); ImGui::PopStyleColor(6);
@@ -503,7 +516,8 @@ std::pair<Node *, glm::vec2> GeometryView::pick(glm::vec2 P)
// keep current source active if it is clicked // keep current source active if it is clicked
Source *current = Mixer::manager().currentSource(); Source *current = Mixer::manager().currentSource();
if (current != nullptr) { if (current != nullptr) {
if (current->workspace() != Settings::application.current_workspace){ if (Settings::application.current_workspace < Source::WORKSPACE_ANY &&
current->workspace() != Settings::application.current_workspace){
current = nullptr; current = nullptr;
} }
else { else {
@@ -575,7 +589,8 @@ std::pair<Node *, glm::vec2> GeometryView::pick(glm::vec2 P)
// get if a source was picked // get if a source was picked
Source *s = Mixer::manager().findSource((*itp).first); Source *s = Mixer::manager().findSource((*itp).first);
// accept picked sources in current workspaces // accept picked sources in current workspaces
if ( s!=nullptr && s->workspace() == Settings::application.current_workspace) { if ( s!=nullptr && (Settings::application.current_workspace == Source::WORKSPACE_ANY ||
s->workspace() == Settings::application.current_workspace) ) {
if ( s->locked() && !UserInterface::manager().ctrlModifier() ) if ( s->locked() && !UserInterface::manager().ctrlModifier() )
continue; continue;
// a non-locked source is picked (anywhere) // a non-locked source is picked (anywhere)
@@ -614,7 +629,8 @@ std::pair<Node *, glm::vec2> GeometryView::pick(glm::vec2 P)
bool GeometryView::canSelect(Source *s) { bool GeometryView::canSelect(Source *s) {
return ( s!=nullptr && View::canSelect(s) && s->ready() && s->active() && s->workspace() == Settings::application.current_workspace); return ( s!=nullptr && View::canSelect(s) && s->ready() && s->active() &&
(Settings::application.current_workspace == Source::WORKSPACE_ANY || s->workspace() == Settings::application.current_workspace) );
} }

View File

@@ -556,7 +556,8 @@ bool ImGuiToolkit::ButtonIconMultistate(std::vector<std::pair<int, int> > icons,
return ret; return ret;
} }
bool ImGuiToolkit::ComboIcon (const char* label, int* current_item, std::vector< std::tuple<int, int, std::string> > items, bool tooltiptext) bool ImGuiToolkit::ComboIcon (const char* label, int* current_item,
std::vector< std::tuple<int, int, std::string> > items, std::vector<std::string> tooltips)
{ {
bool ret = false; bool ret = false;
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@@ -571,41 +572,22 @@ bool ImGuiToolkit::ComboIcon (const char* label, int* current_item, std::vector<
space_buf[space_num]='\0'; space_buf[space_num]='\0';
char text_buf[256]; char text_buf[256];
if (tooltiptext) { ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s %s", space_buf, std::get<2>( items.at(*current_item) ).c_str());
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s", space_buf); if ( ImGui::BeginCombo( label, text_buf, ImGuiComboFlags_None) ) {
if ( ImGui::BeginCombo( label, text_buf, ImGuiComboFlags_None) ) { for (int p = 0; p < (int) items.size(); ++p){
for (int p = 0; p < (int) items.size(); ++p){ ImGui::PushID((void*)(intptr_t)p);
ImGui::PushID((void*)(intptr_t)p); if (ImGuiToolkit::SelectableIcon( std::get<0>( items.at(p) ),
if (ImGuiToolkit::SelectableIcon( std::get<0>( items.at(p) ), std::get<1>( items.at(p) ),
std::get<1>( items.at(p) ), std::get<2>( items.at(p) ).c_str(),
"", p == *current_item) ) {
p == *current_item) ) { *current_item = p;
*current_item = p; ret = true;
ret = true;
}
if (ImGui::IsItemHovered())
ImGuiToolkit::ToolTip(std::get<2>( items.at(p) ).c_str());
ImGui::PopID();
} }
ImGui::EndCombo(); if (ImGui::IsItemHovered() && p < (int) tooltips.size() )
} ImGuiToolkit::ToolTip( tooltips.at(p).c_str() );
} ImGui::PopID();
else {
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%s %s", space_buf, std::get<2>( items.at(*current_item) ).c_str());
if ( ImGui::BeginCombo( label, text_buf, ImGuiComboFlags_None) ) {
for (int p = 0; p < (int) items.size(); ++p){
ImGui::PushID((void*)(intptr_t)p);
if (ImGuiToolkit::SelectableIcon( std::get<0>( items.at(p) ),
std::get<1>( items.at(p) ),
std::get<2>( items.at(p) ).c_str(),
p == *current_item) ) {
*current_item = p;
ret = true;
}
ImGui::PopID();
}
ImGui::EndCombo();
} }
ImGui::EndCombo();
} }
// overlay of icon on top of first item // overlay of icon on top of first item

View File

@@ -30,7 +30,7 @@ namespace ImGuiToolkit
bool ButtonIconMultistate (std::vector<std::pair<int, int> > icons, int* state, std::vector<std::string> tooltips); bool ButtonIconMultistate (std::vector<std::pair<int, int> > icons, int* state, std::vector<std::string> tooltips);
bool MenuItemIcon (int i, int j, const char* label, const char* shortcut = nullptr, bool selected = false, bool enabled = true); bool MenuItemIcon (int i, int j, const char* label, const char* shortcut = nullptr, bool selected = false, bool enabled = true);
bool SelectableIcon(int i, int j, const char* label, bool selected, const ImVec2& size_arg = ImVec2(0,0)); bool SelectableIcon(int i, int j, const char* label, bool selected, const ImVec2& size_arg = ImVec2(0,0));
bool ComboIcon (const char* label, int* current_item, std::vector<std::tuple<int, int, std::string> > items, bool tooltiptext = false); bool ComboIcon (const char* label, int* current_item, std::vector<std::tuple<int, int, std::string> > items, std::vector<std::string> tooltips = {});
// buttons // buttons
bool ButtonToggle (const char* label, bool* toggle, const char *tooltip = nullptr); bool ButtonToggle (const char* label, bool* toggle, const char *tooltip = nullptr);

View File

@@ -510,9 +510,9 @@ void ImGuiVisitor::visit (Source& s)
// Inform on workspace // Inform on workspace
ImGui::SetCursorPos( ImVec2(preview_width + 20, pos.y + 2.1f * ImGui::GetFrameHeightWithSpacing()) ); ImGui::SetCursorPos( ImVec2(preview_width + 20, pos.y + 2.1f * ImGui::GetFrameHeightWithSpacing()) );
static std::map< int, std::pair<int, std::string> > workspaces_ { static std::map< int, std::pair<int, std::string> > workspaces_ {
{ Source::BACKGROUND, {10, "in Background"}}, { Source::WORKSPACE_BACKGROUND, {10, "in Background"}},
{ Source::STAGE, {11, "in Workspace"}}, { Source::WORKSPACE_CENTRAL, {11, "in Workspace"}},
{ Source::FOREGROUND, {12, "in Foreground"}} { Source::WORKSPACE_FOREGROUND, {12, "in Foreground"}}
}; };
// in Geometry view, offer to switch current workspace to the source workspace // in Geometry view, offer to switch current workspace to the source workspace
if (Settings::application.current_view == View::GEOMETRY) { if (Settings::application.current_view == View::GEOMETRY) {

View File

@@ -372,7 +372,7 @@ View::Cursor LayerView::over (glm::vec2 pos)
// //
// Source *s = Mixer::manager().findSource(pick.first); // Source *s = Mixer::manager().findSource(pick.first);
Source *s = Mixer::manager().currentSource(); Source *s = Mixer::manager().currentSource();
if (s != nullptr) { if (s != nullptr && s->ready()) {
s->symbol_->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f ); s->symbol_->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f );
const ImVec4 h = ImGuiToolkit::HighlightColor(); const ImVec4 h = ImGuiToolkit::HighlightColor();

View File

@@ -355,7 +355,7 @@ struct Application
shm_socket_path = ""; shm_socket_path = "";
pannel_current_session_mode = 0; pannel_current_session_mode = 0;
current_view = 1; current_view = 1;
current_workspace= 1; current_workspace= 3;
brush = glm::vec3(0.5f, 0.1f, 0.f); brush = glm::vec3(0.5f, 0.1f, 0.f);
num_output_windows = 1; num_output_windows = 1;
windows = std::vector<WindowConfig>(1+MAX_OUTPUT_WINDOW); windows = std::vector<WindowConfig>(1+MAX_OUTPUT_WINDOW);

View File

@@ -116,7 +116,7 @@ SourceCore& SourceCore::operator= (SourceCore const& other)
Source::Source(uint64_t id) : SourceCore(), id_(id), ready_(false), symbol_(nullptr), Source::Source(uint64_t id) : SourceCore(), id_(id), ready_(false), symbol_(nullptr),
active_(true), locked_(false), need_update_(SourceUpdate_None), dt_(16.f), workspace_(STAGE) active_(true), locked_(false), need_update_(SourceUpdate_None), dt_(16.f), workspace_(WORKSPACE_CENTRAL)
{ {
// create unique id // create unique id
if (id_ == 0) if (id_ == 0)
@@ -804,14 +804,14 @@ void Source::update(float dt)
// adjust vertical position of icon depending on workspace // adjust vertical position of icon depending on workspace
if (groups_[View::LAYER]->translation_.x < -LAYER_FOREGROUND) { if (groups_[View::LAYER]->translation_.x < -LAYER_FOREGROUND) {
groups_[View::LAYER]->translation_.y -= 0.3f; groups_[View::LAYER]->translation_.y -= 0.3f;
workspace_ = Source::FOREGROUND; workspace_ = Source::WORKSPACE_FOREGROUND;
} }
else if (groups_[View::LAYER]->translation_.x < -LAYER_BACKGROUND) { else if (groups_[View::LAYER]->translation_.x < -LAYER_BACKGROUND) {
groups_[View::LAYER]->translation_.y -= 0.15f; groups_[View::LAYER]->translation_.y -= 0.15f;
workspace_ = Source::STAGE; workspace_ = Source::WORKSPACE_CENTRAL;
} }
else else
workspace_ = Source::BACKGROUND; workspace_ = Source::WORKSPACE_BACKGROUND;
// MODIFY depth based on LAYER node // MODIFY depth based on LAYER node
groups_[View::MIXING]->translation_.z = groups_[View::LAYER]->translation_.z; groups_[View::MIXING]->translation_.z = groups_[View::LAYER]->translation_.z;

View File

@@ -27,6 +27,10 @@
#define ICON_SOURCE_GSTREAMER 16, 16 #define ICON_SOURCE_GSTREAMER 16, 16
#define ICON_SOURCE_SRT 14, 5 #define ICON_SOURCE_SRT 14, 5
#define ICON_SOURCE 13, 11 #define ICON_SOURCE 13, 11
#define ICON_WORKSPACE_BACKGROUND 10, 16
#define ICON_WORKSPACE_CENTRAL 11, 16
#define ICON_WORKSPACE_FOREGROUND 12, 16
#define ICON_WORKSPACE 13, 16
class Visitor; class Visitor;
class SourceCallback; class SourceCallback;
@@ -167,9 +171,10 @@ public:
// Workspace // Workspace
typedef enum { typedef enum {
BACKGROUND = 0, WORKSPACE_BACKGROUND = 0,
STAGE = 1, WORKSPACE_CENTRAL = 1,
FOREGROUND = 2 WORKSPACE_FOREGROUND = 2,
WORKSPACE_ANY = 3
} Workspace; } Workspace;
inline Workspace workspace () const { return workspace_; } inline Workspace workspace () const { return workspace_; }

View File

@@ -320,7 +320,7 @@ View::Cursor TextureView::over (glm::vec2 pos)
mask_cursor_square_->visible_ = false; mask_cursor_square_->visible_ = false;
mask_cursor_crop_->visible_ = false; mask_cursor_crop_->visible_ = false;
if (edit_source_ != nullptr) if (edit_source_ != nullptr && edit_source_->ready())
{ {
// coordinates of mouse in scene reference frame // coordinates of mouse in scene reference frame
glm::vec3 scene_pos = Rendering::manager().unProject(pos, scene.root()->transform_); glm::vec3 scene_pos = Rendering::manager().unProject(pos, scene.root()->transform_);

View File

@@ -2312,7 +2312,7 @@ void UserInterface::RenderHelp()
ImGui::Text(ICON_FA_OBJECT_UNGROUP " Geometry"); ImGui::NextColumn(); ImGui::Text(ICON_FA_OBJECT_UNGROUP " Geometry"); ImGui::NextColumn();
ImGui::Text ("Move, scale, rotate or crop sources to place them in the output frame."); ImGui::Text ("Move, scale, rotate or crop sources to place them in the output frame.");
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text(ICON_FA_LAYER_GROUP " Layers"); ImGui::NextColumn(); ImGuiToolkit::Icon(ICON_WORKSPACE); ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::Text("Layers"); ImGui::NextColumn();
ImGui::Text ("Organize the rendering order of sources, from background to foreground."); ImGui::Text ("Organize the rendering order of sources, from background to foreground.");
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text(ICON_FA_CHESS_BOARD " Texturing"); ImGui::NextColumn(); ImGui::Text(ICON_FA_CHESS_BOARD " Texturing"); ImGui::NextColumn();
@@ -2499,7 +2499,7 @@ void UserInterface::RenderHelp()
ImGui::Text("F2"); ImGui::NextColumn(); ImGui::Text("F2"); ImGui::NextColumn();
ImGui::Text(ICON_FA_OBJECT_UNGROUP " Geometry view"); ImGui::NextColumn(); ImGui::Text(ICON_FA_OBJECT_UNGROUP " Geometry view"); ImGui::NextColumn();
ImGui::Text("F3"); ImGui::NextColumn(); ImGui::Text("F3"); ImGui::NextColumn();
ImGui::Text(ICON_FA_LAYER_GROUP " Layers view"); ImGui::NextColumn(); ImGuiToolkit::Icon(ICON_WORKSPACE); ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::Text("Layers view"); ImGui::NextColumn();
ImGui::Text("F4"); ImGui::NextColumn(); ImGui::Text("F4"); ImGui::NextColumn();
ImGui::Text(ICON_FA_CHESS_BOARD " Texturing view"); ImGui::NextColumn(); ImGui::Text(ICON_FA_CHESS_BOARD " Texturing view"); ImGui::NextColumn();
ImGui::Text("F5"); ImGui::NextColumn(); ImGui::Text("F5"); ImGui::NextColumn();
@@ -2907,7 +2907,7 @@ void Navigator::Render()
static uint view_options_timeout = 0; static uint view_options_timeout = 0;
static ImVec2 view_options_pos = ImGui::GetCursorScreenPos(); static ImVec2 view_options_pos = ImGui::GetCursorScreenPos();
bool selected_view[View::INVALID] = { }; bool selected_view[View::INVALID] = {0};
selected_view[ Settings::application.current_view ] = true; selected_view[ Settings::application.current_view ] = true;
int previous_view = Settings::application.current_view; int previous_view = Settings::application.current_view;
@@ -2937,8 +2937,9 @@ void Navigator::Render()
view_options_timeout = 0; view_options_timeout = 0;
} }
if (ImGui::Selectable( ICON_FA_LAYER_GROUP, &selected_view[View::LAYER], 0, iconsize)) if (ImGuiToolkit::SelectableIcon(ICON_WORKSPACE, "", selected_view[View::LAYER], iconsize))
{ {
Settings::application.current_view = View::LAYER;
UserInterface::manager().setView(View::LAYER); UserInterface::manager().setView(View::LAYER);
if (previous_view == Settings::application.current_view) { if (previous_view == Settings::application.current_view) {
ImGui::OpenPopup( "PopupViewOptions" ); ImGui::OpenPopup( "PopupViewOptions" );