Picking Nodes in Mixing view and grabbing associated source to modify

alpha
This commit is contained in:
brunoherbelin
2020-04-23 00:36:32 +02:00
parent cbc2eb4bdc
commit 5e58915282
12 changed files with 240 additions and 73 deletions

View File

@@ -218,6 +218,7 @@ set(VMIX_SRCS
RenderingManager.cpp RenderingManager.cpp
UserInterfaceManager.cpp UserInterfaceManager.cpp
PickingVisitor.cpp PickingVisitor.cpp
SearchVisitor.cpp
ImGuiToolkit.cpp ImGuiToolkit.cpp
ImGuiVisitor.cpp ImGuiVisitor.cpp
GstToolkit.cpp GstToolkit.cpp

View File

@@ -64,14 +64,24 @@ void Mixer::createSourceMedia(std::string uri)
current_source_ = Source::begin(); current_source_ = Source::begin();
} }
void Mixer::setCurrentSource(std::string namesource) void Mixer::setCurrentSource(Node *node)
{ {
current_source_ = std::find_if(Source::begin(), Source::end(), hasName(namesource)) ; current_source_ = Source::find(node);
} }
void Mixer::setcurrentSource(Source *s) void Mixer::setCurrentSource(std::string namesource)
{ {
// current_source_ = Source:: current_source_ = Source::find(namesource);
}
void Mixer::setCurrentSource(Source *s)
{
current_source_ = Source::find(s);
}
void Mixer::unsetCurrentSource()
{
current_source_ = Source::end();
} }
Source *Mixer::currentSource() Source *Mixer::currentSource()

View File

@@ -36,7 +36,10 @@ public:
void createSourceMedia(std::string uri); void createSourceMedia(std::string uri);
void setCurrentSource(std::string namesource); void setCurrentSource(std::string namesource);
void setcurrentSource(Source *s); void setCurrentSource(Node *node);
void setCurrentSource(Source *s);
void unsetCurrentSource();
Source *currentSource(); Source *currentSource();
// management of view // management of view

View File

@@ -17,7 +17,9 @@ PickingVisitor::PickingVisitor(glm::vec2 coordinates) : Visitor(), point_(coordi
void PickingVisitor::visit(Node &n) void PickingVisitor::visit(Node &n)
{ {
modelview_ *= n.transform_;
modelview_ *= n.transform_;
// modelview_ = modelview_ * transform(n.translation_, n.rotation_, n.scale_);
// Log::Info("Node %d", n.id()); // Log::Info("Node %d", n.id());
// Log::Info("%s", glm::to_string(modelview_).c_str()); // Log::Info("%s", glm::to_string(modelview_).c_str());
} }
@@ -25,7 +27,7 @@ void PickingVisitor::visit(Node &n)
void PickingVisitor::visit(Group &n) void PickingVisitor::visit(Group &n)
{ {
glm::mat4 mv = modelview_; glm::mat4 mv = modelview_;
//Log::Info("Group %d", n.id());
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) { for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
(*node)->accept(*this); (*node)->accept(*this);
modelview_ = mv; modelview_ = mv;
@@ -51,6 +53,7 @@ void PickingVisitor::visit(Primitive &n)
void PickingVisitor::visit(Surface &n) void PickingVisitor::visit(Surface &n)
{ {
// Log::Info("Surface %d", n.id());
// apply inverse transform to the point of interest // apply inverse transform to the point of interest
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_, 0.f, 1.f ); glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_, 0.f, 1.f );

41
SearchVisitor.cpp Normal file
View File

@@ -0,0 +1,41 @@
#include "SearchVisitor.h"
#include "Scene.h"
SearchVisitor::SearchVisitor(Node *node) : Visitor(), node_(node), id_(0), found_(false)
{
id_ = node->id();
}
SearchVisitor::SearchVisitor(int id) : Visitor(), node_(nullptr), id_(id), found_(false)
{
}
void SearchVisitor::visit(Node &n)
{
if ( n.id() == id_ ){
found_ = true;
node_ = &n;
}
}
void SearchVisitor::visit(Group &n)
{
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
(*node)->accept(*this);
if (found_)
break;
}
}
void SearchVisitor::visit(Switch &n)
{
(*n.activeChild())->accept(*this);
}
void SearchVisitor::visit(Scene &n)
{
n.root()->accept(*this);
}

42
SearchVisitor.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef SEARCHVISITOR_H
#define SEARCHVISITOR_H
#include "Visitor.h"
class SearchVisitor: public Visitor
{
Node *node_;
int id_;
bool found_;
public:
SearchVisitor(Node *node);
SearchVisitor(int id);
inline bool found() const { return found_; }
inline Node *node() const { return found_ ? node_ : nullptr; }
// Elements of Scene
void visit(Scene& n);
void visit(Node& n);
void visit(Group& n);
void visit(Switch& n);
// already a Node or a Group
void visit(Animation&) {}
void visit(Primitive&) {}
void visit(Surface&) {}
void visit(ImageSurface&) {}
void visit(MediaSurface&) {}
void visit(FrameBufferSurface&) {}
void visit(LineStrip&) {}
void visit(LineSquare&) {}
void visit(LineCircle&) {}
void visit(Mesh&) {}
// not nodes
void visit(MediaPlayer&) {}
void visit(Shader&) {}
void visit(ImageShader&) {}
};
#endif // SEARCHVISITOR_H

View File

@@ -8,6 +8,7 @@
#include "Primitives.h" #include "Primitives.h"
#include "Mesh.h" #include "Mesh.h"
#include "MediaPlayer.h" #include "MediaPlayer.h"
#include "SearchVisitor.h"
// gobal static list of all sources // gobal static list of all sources
@@ -46,6 +47,21 @@ Source::~Source()
sources_.remove(this); sources_.remove(this);
} }
bool hasNode::operator()(const Source* elem) const
{
if (elem)
{
SearchVisitor sv(_n);
elem->group(View::MIXING)->accept(sv);
if (sv.found())
return true;
elem->group(View::RENDERING)->accept(sv);
return sv.found();
}
return false;
}
std::string Source::rename (std::string newname) std::string Source::rename (std::string newname)
{ {
// tentative new name // tentative new name
@@ -81,6 +97,21 @@ SourceList::iterator Source::end()
return sources_.end(); return sources_.end();
} }
SourceList::iterator Source::find(Source *s)
{
return std::find(sources_.begin(), sources_.end(), s);
}
SourceList::iterator Source::find(std::string namesource)
{
return std::find_if(Source::begin(), Source::end(), hasName(namesource));
}
SourceList::iterator Source::find(Node *node)
{
return std::find_if(Source::begin(), Source::end(), hasNode(node));
}
uint Source::numSource() uint Source::numSource()
{ {
return sources_.size(); return sources_.size();
@@ -127,5 +158,7 @@ void MediaSource::render()
} }
// read position of the mixing node and interpret this as transparency change // read position of the mixing node and interpret this as transparency change
float alpha = 1.0 - ABS( groups_[View::MIXING]->translation_.x );
surface_->shader()->color.a = alpha;
} }

View File

@@ -31,7 +31,7 @@ public:
std::string rename (std::string newname); std::string rename (std::string newname);
// 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) { return groups_[m]; } inline Group *group(View::Mode m) const { return groups_.at(m); }
// every Source have a shader to control visual effects // every Source have a shader to control visual effects
virtual Shader *shader() const = 0; virtual Shader *shader() const = 0;
@@ -42,6 +42,9 @@ public:
// global management of list of sources // global management of list of sources
static SourceList::iterator begin(); static SourceList::iterator begin();
static SourceList::iterator end(); static SourceList::iterator end();
static SourceList::iterator find(Source *s);
static SourceList::iterator find(std::string name);
static SourceList::iterator find(Node *node);
static uint numSource(); static uint numSource();
protected: protected:
@@ -58,16 +61,22 @@ protected:
struct hasName: public std::unary_function<Source*, bool> struct hasName: public std::unary_function<Source*, bool>
{ {
inline bool operator()(const Source* elem) const inline bool operator()(const Source* elem) const {
{
return (elem && elem->name() == _n); return (elem && elem->name() == _n);
} }
hasName(std::string n) : _n(n) { } hasName(std::string n) : _n(n) { }
private: private:
std::string _n; std::string _n;
};
struct hasNode: public std::unary_function<Source*, bool>
{
bool operator()(const Source* elem) const;
hasNode(Node *n) : _n(n) { }
private:
Node *_n;
}; };
class MediaSource : public Source class MediaSource : public Source

View File

@@ -174,16 +174,6 @@ void UserInterface::handleMouse()
// //
// RIGHT Mouse button // RIGHT Mouse button
// //
if ( ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
Log::Info("Right Mouse press (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
glm::vec3 point = Rendering::manager().unProject(glm::vec2(io.MousePos.x, io.MousePos.y),
Mixer::manager().currentView()->scene.root()->transform_ );
Log::Info(" (%.1f,%.1f)", point.x, point.y);
}
if ( ImGui::IsMouseDragging(ImGuiMouseButton_Right, 10.0f) ) if ( ImGui::IsMouseDragging(ImGuiMouseButton_Right, 10.0f) )
{ {
@@ -192,61 +182,79 @@ void UserInterface::handleMouse()
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
} }
else else {
ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow); ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow);
if ( ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
// TODO CONTEXT MENU
// Log::Info("Right Mouse press (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
glm::vec3 point = Rendering::manager().unProject(glm::vec2(io.MousePos.x, io.MousePos.y),
Mixer::manager().currentView()->scene.root()->transform_ );
Log::Info(" (%.1f,%.1f)", point.x, point.y);
}
}
// //
// LEFT Mouse button // LEFT Mouse button
// //
static Node *current = nullptr;
if ( ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
// Log::Info("Mouse press (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
glm::vec3 point = Rendering::manager().unProject(glm::vec2(io.MousePos.x, io.MousePos.y),
Mixer::manager().currentView()->scene.root()->transform_ );
// Log::Info(" (%.1f,%.1f)", point.x, point.y);
PickingVisitor pv(point);
Mixer::manager().currentView()->scene.accept(pv);
if (pv.picked().empty())
current = nullptr;
else {
current = pv.picked().back();
}
Log::Info(" %d picked", pv.picked().size());
}
if ( ImGui::IsMouseDragging(ImGuiMouseButton_Left, 10.0f) ) if ( ImGui::IsMouseDragging(ImGuiMouseButton_Left, 10.0f) )
{ {
Source *current = Mixer::manager().currentSource();
if (current) if (current)
{ {
// // drag current // drag current source
// Log::Info("Dragging %d", current->id()); Mixer::manager().currentView()->grab( glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Left].x, io.MouseClickedPos[ImGuiMouseButton_Left].y), glm::vec2(io.MousePos.x, io.MousePos.y), current);
// current->translation_.x += io.MouseDelta.x * 0.1f;
Mixer::manager().currentView()->grab( glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Left].x, io.MouseClickedPos[ImGuiMouseButton_Left].y), glm::vec2(io.MousePos.x, io.MousePos.y), current);
} }
else { else {
// Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y); // Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y);
// Selection area // Selection area
ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[0], io.MousePos, ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered)); ImGui::GetColorU32(ImGuiCol_ResizeGripHovered));
ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[0], io.MousePos, ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f)); ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f));
} }
} }
else if ( ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
// get coordinate in world view of mouse cursor
glm::vec3 point = Rendering::manager().unProject(glm::vec2(io.MousePos.x, io.MousePos.y));
// picking visitor traverses the scene
PickingVisitor pv(point);
Mixer::manager().currentView()->scene.accept(pv);
// picking visitor found nodes?
if (pv.picked().empty())
Mixer::manager().unsetCurrentSource();
else
Mixer::manager().setCurrentSource(pv.picked().back());
if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) )
{
current = nullptr;
} }
else if ( ImGui::IsMouseReleased(ImGuiMouseButton_Left) )
{
// Log::Info("Mouse press (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
// glm::vec3 point = Rendering::manager().unProject(glm::vec2(io.MousePos.x, io.MousePos.y));
// // Log::Info(" (%.1f,%.1f)", point.x, point.y);
// PickingVisitor pv(point);
// Mixer::manager().currentView()->scene.accept(pv);
// if (pv.picked().empty())
// Mixer::manager().unsetCurrentSource();
// else
// Mixer::manager().setCurrentSource(pv.picked().back());
// // Log::Info(" %d picked", pv.picked().size());
}
} }
} }

View File

@@ -5,6 +5,7 @@
#include "defines.h" #include "defines.h"
#include "View.h" #include "View.h"
#include "Source.h"
#include "Primitives.h" #include "Primitives.h"
#include "Mesh.h" #include "Mesh.h"
#include "FrameBuffer.h" #include "FrameBuffer.h"
@@ -75,23 +76,31 @@ void MixingView::drag (glm::vec2 from, glm::vec2 to)
} }
void MixingView::grab (glm::vec2 from, glm::vec2 to, Node *node) void MixingView::grab (glm::vec2 from, glm::vec2 to, Source *s)
{ {
if (!s)
return;
Group *sourceNode = s->group(View::MIXING);
static glm::vec3 start_translation = glm::vec3(0.f); static glm::vec3 start_translation = glm::vec3(0.f);
static glm::vec2 start_position = glm::vec2(0.f); static glm::vec2 start_position = glm::vec2(0.f);
if ( start_position != from ) { if ( start_position != from ) {
start_position = from; start_position = from;
start_translation = node->translation_; start_translation = sourceNode->translation_;
} }
// unproject // unproject
glm::vec3 gl_Position_from = Rendering::manager().unProject(from, node->transform_); // glm::vec3 gl_Position_from = Rendering::manager().unProject(from, sourceNode->transform_);
glm::vec3 gl_Position_to = Rendering::manager().unProject(to, node->transform_); // glm::vec3 gl_Position_to = Rendering::manager().unProject(to, sourceNode->transform_);
glm::vec3 gl_Position_from = Rendering::manager().unProject(from, sourceNode->parent_->transform_);
glm::vec3 gl_Position_to = Rendering::manager().unProject(to, sourceNode->parent_->transform_);
// compute delta translation // compute delta translation
node->translation_ = start_translation + gl_Position_to - gl_Position_from; // node->translation_ = start_translation + gl_Position_to - gl_Position_from;
sourceNode->translation_ = start_translation + gl_Position_to - gl_Position_from;
} }

5
View.h
View File

@@ -5,6 +5,7 @@
#include "Scene.h" #include "Scene.h"
class FrameBuffer; class FrameBuffer;
class Source;
class View class View
{ {
@@ -17,7 +18,7 @@ public:
virtual void draw () = 0; virtual void draw () = 0;
virtual void zoom (float) {} virtual void zoom (float) {}
virtual void drag (glm::vec2, glm::vec2) {} virtual void drag (glm::vec2, glm::vec2) {}
virtual void grab (glm::vec2, glm::vec2, Node*) {} virtual void grab (glm::vec2, glm::vec2, Source*) {}
Scene scene; Scene scene;
@@ -35,7 +36,7 @@ public:
void draw () override; void draw () override;
void zoom (float factor); void zoom (float factor);
void drag (glm::vec2 from, glm::vec2 to); void drag (glm::vec2 from, glm::vec2 to);
void grab (glm::vec2 from, glm::vec2 to, Node *node); void grab (glm::vec2 from, glm::vec2 to, Source *s);
}; };

View File

@@ -59,23 +59,30 @@
void drawMediaPlayer() void drawMediaPlayer()
{ {
static bool opened = true;
static GstClockTime begin = GST_CLOCK_TIME_NONE; static GstClockTime begin = GST_CLOCK_TIME_NONE;
static GstClockTime end = GST_CLOCK_TIME_NONE; static GstClockTime end = GST_CLOCK_TIME_NONE;
if ( !Mixer::manager().currentSource()) bool show = false;
return; MediaPlayer *mp = nullptr;
if ( Mixer::manager().currentSource()) {
MediaSource *s = static_cast<MediaSource *>(Mixer::manager().currentSource()); MediaSource *s = static_cast<MediaSource *>(Mixer::manager().currentSource());
if ( !s ) if (s) {
return; mp = s->mediaplayer();
if (mp && mp->isOpen())
MediaPlayer *mp = s->mediaplayer(); show = true;
if ( !mp || !mp->isOpen() ) }
return; }
ImGui::SetNextWindowPos(ImVec2(200, 200), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(200, 200), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(300, 300), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(300, 300), ImGuiCond_FirstUseEver);
ImGui::Begin(IMGUI_TITLE_MEDIAPLAYER);
if ( !ImGui::Begin(IMGUI_TITLE_MEDIAPLAYER, &opened) || !show)
{
ImGui::End();
return;
}
float width = ImGui::GetContentRegionAvail().x; float width = ImGui::GetContentRegionAvail().x;
float spacing = ImGui::GetStyle().ItemInnerSpacing.x; float spacing = ImGui::GetStyle().ItemInnerSpacing.x;