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
UserInterfaceManager.cpp
PickingVisitor.cpp
SearchVisitor.cpp
ImGuiToolkit.cpp
ImGuiVisitor.cpp
GstToolkit.cpp

View File

@@ -64,14 +64,24 @@ void Mixer::createSourceMedia(std::string uri)
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()

View File

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

View File

@@ -17,7 +17,9 @@ PickingVisitor::PickingVisitor(glm::vec2 coordinates) : Visitor(), point_(coordi
void PickingVisitor::visit(Node &n)
{
modelview_ *= n.transform_;
// modelview_ = modelview_ * transform(n.translation_, n.rotation_, n.scale_);
// Log::Info("Node %d", n.id());
// Log::Info("%s", glm::to_string(modelview_).c_str());
}
@@ -25,7 +27,7 @@ void PickingVisitor::visit(Node &n)
void PickingVisitor::visit(Group &n)
{
glm::mat4 mv = modelview_;
//Log::Info("Group %d", n.id());
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
(*node)->accept(*this);
modelview_ = mv;
@@ -51,6 +53,7 @@ void PickingVisitor::visit(Primitive &n)
void PickingVisitor::visit(Surface &n)
{
// Log::Info("Surface %d", n.id());
// apply inverse transform to the point of interest
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 "Mesh.h"
#include "MediaPlayer.h"
#include "SearchVisitor.h"
// gobal static list of all sources
@@ -46,6 +47,21 @@ Source::~Source()
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)
{
// tentative new name
@@ -81,6 +97,21 @@ SourceList::iterator Source::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()
{
return sources_.size();
@@ -127,5 +158,7 @@ void MediaSource::render()
}
// 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);
// 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
virtual Shader *shader() const = 0;
@@ -42,6 +42,9 @@ public:
// global management of list of sources
static SourceList::iterator begin();
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();
protected:
@@ -58,16 +61,22 @@ protected:
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);
}
hasName(std::string n) : _n(n) { }
private:
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

View File

@@ -174,16 +174,6 @@ void UserInterface::handleMouse()
//
// 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) )
{
@@ -192,61 +182,79 @@ void UserInterface::handleMouse()
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
}
else
else {
ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow);
//
// LEFT Mouse button
//
static Node *current = nullptr;
if ( ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
if ( ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
// Log::Info("Mouse press (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
// 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);
PickingVisitor pv(point);
Mixer::manager().currentView()->scene.accept(pv);
Log::Info(" (%.1f,%.1f)", point.x, point.y);
if (pv.picked().empty())
current = nullptr;
else {
current = pv.picked().back();
}
Log::Info(" %d picked", pv.picked().size());
}
}
//
// LEFT Mouse button
//
if ( ImGui::IsMouseDragging(ImGuiMouseButton_Left, 10.0f) )
{
Source *current = Mixer::manager().currentSource();
if (current)
{
// // drag current
// Log::Info("Dragging %d", current->id());
// current->translation_.x += io.MouseDelta.x * 0.1f;
// drag current source
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 {
// Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y);
// Selection area
ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[0], io.MousePos,
ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
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));
}
}
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 "View.h"
#include "Source.h"
#include "Primitives.h"
#include "Mesh.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::vec2 start_position = glm::vec2(0.f);
if ( start_position != from ) {
start_position = from;
start_translation = node->translation_;
start_translation = sourceNode->translation_;
}
// unproject
glm::vec3 gl_Position_from = Rendering::manager().unProject(from, node->transform_);
glm::vec3 gl_Position_to = Rendering::manager().unProject(to, node->transform_);
// glm::vec3 gl_Position_from = Rendering::manager().unProject(from, sourceNode->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
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"
class FrameBuffer;
class Source;
class View
{
@@ -17,7 +18,7 @@ public:
virtual void draw () = 0;
virtual void zoom (float) {}
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;
@@ -35,7 +36,7 @@ public:
void draw () override;
void zoom (float factor);
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()
{
static bool opened = true;
static GstClockTime begin = GST_CLOCK_TIME_NONE;
static GstClockTime end = GST_CLOCK_TIME_NONE;
if ( !Mixer::manager().currentSource())
return;
bool show = false;
MediaPlayer *mp = nullptr;
if ( Mixer::manager().currentSource()) {
MediaSource *s = static_cast<MediaSource *>(Mixer::manager().currentSource());
if ( !s )
return;
MediaPlayer *mp = s->mediaplayer();
if ( !mp || !mp->isOpen() )
return;
if (s) {
mp = s->mediaplayer();
if (mp && mp->isOpen())
show = true;
}
}
ImGui::SetNextWindowPos(ImVec2(200, 200), 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 spacing = ImGui::GetStyle().ItemInnerSpacing.x;