mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Improved creation of source: selection of file generates a new source,
displayed in preview, and inserted when validated.
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
13
Mixer.cpp
13
Mixer.cpp
@@ -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_;
|
||||||
|
|||||||
1
Mixer.h
1
Mixer.h
@@ -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();
|
||||||
|
|||||||
15
Source.cpp
15
Source.cpp
@@ -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)
|
||||||
|
|||||||
5
Source.h
5
Source.h
@@ -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); }
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
if (open_file_name) {
|
||||||
sprintf(filename, "%s", 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_) );
|
|
||||||
selected_button[NAV_NEW] = false;
|
|
||||||
}
|
|
||||||
// or press Validate button
|
// or press Validate button
|
||||||
ImGui::Text(" ");
|
if ( ImGui::Button("Import", ImVec2(pannel_width - padding_width, 0)) ) {
|
||||||
if ( ImGui::Button("Create !", ImVec2(pannel_width - padding_width, 0)) ) {
|
Mixer::manager().insertSource(new_source_preview_.getSource());
|
||||||
s = Mixer::manager().createSourceFile( std::string(new_source_filename_) );
|
|
||||||
selected_button[NAV_NEW] = false;
|
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 {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user