Improved creation of source: selection of file generates a new source,

displayed in preview, and inserted when validated.
This commit is contained in:
brunoherbelin
2020-05-23 19:13:05 +02:00
parent 2cc45edfbd
commit 614fa1247d
9 changed files with 146 additions and 76 deletions

View File

@@ -792,6 +792,11 @@ ImVec4 ImGuiToolkit::GetHighlightColor()
void ImGuiToolkit::SetAccentColor(accent_color color) void ImGuiToolkit::SetAccentColor(accent_color color)
{ {
// hack : preload texture icon to prevent slow-down of rendering when creating a new icon for the first time
if (textureicons == 0)
textureicons = Resource::getTextureDDS("images/icons.dds");
ImVec4* colors = ImGui::GetStyle().Colors; ImVec4* colors = ImGui::GetStyle().Colors;
if (color == ImGuiToolkit::ACCENT_ORANGE) { if (color == ImGuiToolkit::ACCENT_ORANGE) {

View File

@@ -10,7 +10,6 @@
namespace ImGuiToolkit namespace ImGuiToolkit
{ {
// Icons from resource icon.dds // Icons from resource icon.dds
void Icon(int i, int j); void Icon(int i, int j);
void ShowIconsWindow(bool* p_open); void ShowIconsWindow(bool* p_open);

View File

@@ -265,8 +265,6 @@ void ImGuiVisitor::visit (Source& s)
// geometry direct control // geometry direct control
s.groupNode(View::GEOMETRY)->accept(*this); s.groupNode(View::GEOMETRY)->accept(*this);
// Action on source
// ImGui::Button("Clone", ImVec2(IMGUI_RIGHT_ALIGN, 0));
} }
void ImGuiVisitor::visit (MediaSource& s) void ImGuiVisitor::visit (MediaSource& s)

View File

@@ -258,7 +258,10 @@ void Mixer::insertSource(Source *s)
geometry_.scene.ws()->attach(s->group(View::GEOMETRY)); geometry_.scene.ws()->attach(s->group(View::GEOMETRY));
layer_.scene.ws()->attach(s->group(View::LAYER)); layer_.scene.ws()->attach(s->group(View::LAYER));
// set a default depth to the new source
layer_.setDepth(s); layer_.setDepth(s);
current_view_->update(0);
} }
} }
@@ -357,6 +360,16 @@ void Mixer::unsetCurrentSource()
current_source_index_ = -1; current_source_index_ = -1;
} }
void Mixer::cloneCurrentSource()
{
if ( current_source_ != session_->end() )
{
Source *s = createSourceClone( (*current_source_)->name() );
insertSource(s);
}
}
int Mixer::indexCurrentSource() int Mixer::indexCurrentSource()
{ {
return current_source_index_; return current_source_index_;

View File

@@ -49,6 +49,7 @@ public:
void setCurrentSource(int index); void setCurrentSource(int index);
void setCurrentSource(Source *s); void setCurrentSource(Source *s);
void unsetCurrentSource(); void unsetCurrentSource();
void cloneCurrentSource();
void deleteCurrentSource(); void deleteCurrentSource();
Source * currentSource(); Source * currentSource();
int indexCurrentSource(); int indexCurrentSource();

View File

@@ -136,6 +136,15 @@ void Source::setOverlayVisible(bool on)
(*o).second->visible_ = on; (*o).second->visible_ = on;
} }
void Source::setVisible(bool on)
{
// make visible
groups_[View::RENDERING]->visible_ = on;
groups_[View::MIXING]->visible_ = on;
groups_[View::GEOMETRY]->visible_ = on;
groups_[View::LAYER]->visible_ = on;
}
void Source::attach(FrameBuffer *renderbuffer) void Source::attach(FrameBuffer *renderbuffer)
{ {
renderbuffer_ = renderbuffer; renderbuffer_ = renderbuffer;
@@ -169,11 +178,7 @@ void Source::attach(FrameBuffer *renderbuffer)
(*node)->scale_.x = renderbuffer_->aspectRatio(); (*node)->scale_.x = renderbuffer_->aspectRatio();
} }
// make visible setVisible(true);
groups_[View::RENDERING]->visible_ = true;
groups_[View::MIXING]->visible_ = true;
groups_[View::GEOMETRY]->visible_ = true;
groups_[View::LAYER]->visible_ = true;
} }
void Source::update(float dt) void Source::update(float dt)

View File

@@ -38,8 +38,11 @@ public:
// cloning mechanism // cloning mechanism
virtual CloneSource *clone(); virtual CloneSource *clone();
// make visible or hidden
void setVisible(bool on);
// an overlay can be displayed on top of the source // an overlay can be displayed on top of the source
virtual void setOverlayVisible(bool on); void setOverlayVisible(bool on);
// get handle on the node used to manipulate the source in a view // get handle on the node used to manipulate the source in a view
inline Group *group(View::Mode m) const { return groups_.at(m); } inline Group *group(View::Mode m) const { return groups_.at(m); }

View File

@@ -105,7 +105,7 @@ static void SessionFileDialogSave(std::string path)
sessionFileDialogSaveFinished_ = true; sessionFileDialogSaveFinished_ = true;
} }
static void ImportFileDialogOpen(char *filename, const std::string &path) static void ImportFileDialogOpen(char *filename, std::atomic<bool> *success, const std::string &path)
{ {
if (fileDialogPending_) if (fileDialogPending_)
return; return;
@@ -115,7 +115,14 @@ static void ImportFileDialogOpen(char *filename, const std::string &path)
char const * open_file_name; char const * open_file_name;
open_file_name = tinyfd_openFileDialog( "Import a file", path.c_str(), 18, open_pattern, "All supported formats", 0); open_file_name = tinyfd_openFileDialog( "Import a file", path.c_str(), 18, open_pattern, "All supported formats", 0);
sprintf(filename, "%s", open_file_name);
if (open_file_name) {
sprintf(filename, "%s", open_file_name);
*success = true;
}
else {
*success = false;
}
fileDialogPending_ = false; fileDialogPending_ = false;
} }
@@ -855,7 +862,6 @@ Navigator::Navigator()
height = 100; height = 100;
padding_width = 100; padding_width = 100;
new_source_type_ = 0; new_source_type_ = 0;
new_source_to_create_ = "";
sprintf(new_source_filename_, " "); sprintf(new_source_filename_, " ");
} }
@@ -874,8 +880,9 @@ void Navigator::clearSelection()
{ {
for(int i=0; i<NAV_COUNT; ++i) for(int i=0; i<NAV_COUNT; ++i)
selected_button[i] = false; selected_button[i] = false;
new_source_to_create_ = "";
sprintf(new_source_filename_, " "); sprintf(new_source_filename_, " ");
new_source_preview_.setSource();
} }
void Navigator::showPannelSource(int index) void Navigator::showPannelSource(int index)
@@ -1053,6 +1060,9 @@ void Navigator::RenderSourcePannel(Source *s)
s->touch(); s->touch();
// delete button // delete button
ImGui::Text(" "); ImGui::Text(" ");
// Action on source
if ( ImGui::Button("Clone", ImVec2(ImGui::GetContentRegionAvail().x, 0)) )
Mixer::manager().cloneCurrentSource();
if ( ImGui::Button("Delete", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) { if ( ImGui::Button("Delete", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) {
Mixer::manager().deleteSource(s); Mixer::manager().deleteSource(s);
} }
@@ -1061,6 +1071,45 @@ void Navigator::RenderSourcePannel(Source *s)
} }
SourcePreview::SourcePreview() : source_(nullptr), label_("")
{
}
void SourcePreview::setSource(Source *s, std::string label)
{
if(source_)
delete source_;
source_ = s;
label_ = label;
}
Source * SourcePreview::getSource()
{
Source *s = source_;
source_ = nullptr;
return s;
}
void SourcePreview::draw(float width)
{
if(source_) {
// cancel if failed
if (source_->failed())
setSource();
else
{
// render framebuffer
source_->render();
// draw preview
ImVec2 preview_size(width, width / source_->frame()->aspectRatio());
ImGui::Image((void*)(uintptr_t) source_->frame()->texture(), preview_size);
ImGui::Text("%s ", label_.c_str());
}
}
}
void Navigator::RenderNewPannel() void Navigator::RenderNewPannel()
{ {
// Next window is a side pannel // Next window is a side pannel
@@ -1078,108 +1127,89 @@ void Navigator::RenderNewPannel()
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("Origin", &new_source_type_, "File\0Software\0Hardware\0"); ImGui::Combo("Origin", &new_source_type_, "File\0Software\0Hardware\0");
// Media Source creation // File Source creation
if (new_source_type_ == 0) { if (new_source_type_ == 0) {
// helper // helper
ImGui::SetCursorPosX(pannel_width - 30 + IMGUI_RIGHT_ALIGN); ImGui::SetCursorPosX(pannel_width - 30 + IMGUI_RIGHT_ALIGN);
ImGuiToolkit::HelpMarker("Create a source from a file:\n- Video (*.mpg, *mov, *.avi, etc.)\n- Image (*.jpg, *.png, etc.)\n- Vector graphics (*.svg)\n- vimix session (*.vmx)\n\nEquivalent to dropping the file in the workspace."); ImGuiToolkit::HelpMarker("Create a source from a file:\n- Video (*.mpg, *mov, *.avi, etc.)\n- Image (*.jpg, *.png, etc.)\n- Vector graphics (*.svg)\n- vimix session (*.vmx)\n\nEquivalent to dropping the file in the workspace.");
// browse for a filename // browse for a filename
if (ImGuiToolkit::ButtonIcon(2, 5)) { static std::atomic<bool> file_selected = false;
std::thread (ImportFileDialogOpen, new_source_filename_, Settings::application.recentImport.path).detach(); if ( ImGui::Button( ICON_FA_FILE_IMPORT " Open", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
// clear string before selection
file_selected = false;
std::thread (ImportFileDialogOpen, new_source_filename_, &file_selected, Settings::application.recentImport.path).detach();
} }
if ( file_selected ) {
file_selected = false;
std::string open_filename(new_source_filename_);
// create a source with this file
std::string label = open_filename.substr( open_filename.size() - MIN( 35, open_filename.size()) );
new_source_preview_.setSource( Mixer::manager().createSourceFile(open_filename), label);
}
// combo of recent media filenames // combo of recent media filenames
ImGui::SameLine(0, 10);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("##RecentImport", "Select recent")) if (ImGui::BeginCombo("##RecentImport", "Select recent"))
{ {
for (auto path = Settings::application.recentImport.filenames.begin(); for (auto path = Settings::application.recentImport.filenames.begin();
path != Settings::application.recentImport.filenames.end(); path++ ) path != Settings::application.recentImport.filenames.end(); path++ )
{ {
int right = MIN( 40, path->size()); std::string label = path->substr( path->size() - MIN( 35, path->size()) );
if (ImGui::Selectable( path->substr( path->size() - right ).c_str() )) { if (ImGui::Selectable( label.c_str() )) {
sprintf(new_source_filename_, "%s", path->c_str()); new_source_preview_.setSource( Mixer::manager().createSourceFile(path->c_str()), label);
} }
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
// filename text entry - [Return] to validate // if a new source was added
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); if (new_source_preview_.ready()) {
Source *s = nullptr; // show preview
if (ImGui::InputText("Path", new_source_filename_, IM_ARRAYSIZE(new_source_filename_), ImGuiInputTextFlags_EnterReturnsTrue) ) { new_source_preview_.draw(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN);
s = Mixer::manager().createSourceFile( std::string(new_source_filename_) ); // or press Validate button
selected_button[NAV_NEW] = false; if ( ImGui::Button("Import", ImVec2(pannel_width - padding_width, 0)) ) {
Mixer::manager().insertSource(new_source_preview_.getSource());
selected_button[NAV_NEW] = false;
}
} }
// or press Validate button
ImGui::Text(" ");
if ( ImGui::Button("Create !", ImVec2(pannel_width - padding_width, 0)) ) {
s = Mixer::manager().createSourceFile( std::string(new_source_filename_) );
selected_button[NAV_NEW] = false;
}
Mixer::manager().insertSource(s);
} }
// Render Source creator // Software Source creator
else if (new_source_type_ == 1){ else if (new_source_type_ == 1){
// helper // helper
ImGui::SetCursorPosX(pannel_width - 30 + IMGUI_RIGHT_ALIGN); ImGui::SetCursorPosX(pannel_width - 30 + IMGUI_RIGHT_ALIGN);
ImGuiToolkit::HelpMarker("Create a source from a software algorithm or from vimix objects."); ImGuiToolkit::HelpMarker("Create a source from a software algorithm or from vimix objects.");
// Selection of a source to create // fill new_source_preview with a new source
static uint texture = 0;
static ImVec2 preview_size;
static ImVec2 preview_uv1, preview_uv2;
static float preview_width = ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN;
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("##Source", "Select source")) if (ImGui::BeginCombo("##Source", "Select input"))
{ {
if (ImGui::Selectable( "Render" )) { std::string label = "Rendering output";
new_source_to_create_ = "Render"; if (ImGui::Selectable( label.c_str() )) {
texture = Mixer::manager().session()->frame()->texture(); new_source_preview_.setSource( Mixer::manager().createSourceRender(), label);
preview_size = ImVec2( preview_width, preview_width / Mixer::manager().session()->frame()->aspectRatio());
preview_uv1 = ImVec2(0.f, 1.f);
preview_uv2 = ImVec2(1.f, 0.f);
} }
SourceList::iterator iter; SourceList::iterator iter;
for (iter = Mixer::manager().session()->begin(); iter != Mixer::manager().session()->end(); iter++) for (iter = Mixer::manager().session()->begin(); iter != Mixer::manager().session()->end(); iter++)
{ {
if (ImGui::Selectable( (*iter)->name().c_str() )) { label = std::string("Clone of ") + (*iter)->name();
new_source_to_create_ = (*iter)->name(); if (ImGui::Selectable( label.c_str() )) {
texture = (*iter)->texture(); new_source_preview_.setSource( Mixer::manager().createSourceClone((*iter)->name()),label);
preview_size = ImVec2( preview_width, preview_width / (*iter)->frame()->aspectRatio());
preview_uv1 = ImVec2(0.f, 0.f);
preview_uv2 = ImVec2(1.f, 1.f);
} }
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
// if a new source was added
if (!new_source_to_create_.empty()) { if (new_source_preview_.ready()) {
// show preview
// preview new_source_preview_.draw(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN);
if (texture != 0) { // ask to import the source in the mixer
ImGui::Image((void*)(uintptr_t) texture, preview_size, preview_uv1, preview_uv2); if ( ImGui::Button("Import", ImVec2(pannel_width - padding_width, 0)) ) {
} Mixer::manager().insertSource(new_source_preview_.getSource());
ImGui::Text("%s ", new_source_to_create_.c_str());
if ( ImGui::Button("Create !", ImVec2(pannel_width - padding_width, 0)) ) {
Source *s = nullptr;
if (new_source_to_create_ == "Render")
s = Mixer::manager().createSourceRender();
else
s = Mixer::manager().createSourceClone(new_source_to_create_);
Mixer::manager().insertSource(s);
// reset for next time // reset for next time
new_source_to_create_ = "";
texture = 0;
selected_button[NAV_NEW] = false; selected_button[NAV_NEW] = false;
} }
} }
} }
// Hardware // Hardware
else { else {

View File

@@ -13,6 +13,21 @@ using namespace std;
struct ImVec2; struct ImVec2;
class Source; class Source;
class SourcePreview {
Source *source_;
std::string label_;
public:
SourcePreview();
void setSource(Source *s = nullptr, std::string label = "");
Source *getSource();
void draw(float width);
inline bool ready() const { return source_ != nullptr; }
};
class Navigator class Navigator
{ {
// geometry left bar // geometry left bar
@@ -34,9 +49,10 @@ class Navigator
void RenderMainPannel(); void RenderMainPannel();
int new_source_type_; int new_source_type_;
std::string new_source_to_create_;
char new_source_filename_[2048]; char new_source_filename_[2048];
SourcePreview new_source_preview_;
public: public:
Navigator(); Navigator();