mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-14 03:39:57 +01:00
Implemented selection of multiple sources
This commit is contained in:
@@ -95,7 +95,7 @@ void Frame::draw(glm::mat4 modelview, glm::mat4 projection)
|
||||
|
||||
// shadow (scaled)
|
||||
if(shadow_){
|
||||
shadow_->shader()->color.a = 0.8f;
|
||||
shadow_->shader()->color.a = 0.98f;
|
||||
shadow_->draw( ctm, projection);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ GlmToolkit::AxisAlignedBoundingBox::AxisAlignedBoundingBox() {
|
||||
mMax = glm::vec3(-1.f);
|
||||
}
|
||||
|
||||
void GlmToolkit::AxisAlignedBoundingBox::extend(const glm::vec3& point)
|
||||
void GlmToolkit::AxisAlignedBoundingBox::extend(const glm::vec3& point) // TODO why ref to point?
|
||||
{
|
||||
if (isNull()) {
|
||||
mMin = point;
|
||||
|
||||
@@ -12,9 +12,17 @@
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
|
||||
|
||||
PickingVisitor::PickingVisitor(glm::vec2 coordinates) : Visitor(), point_(coordinates)
|
||||
PickingVisitor::PickingVisitor(glm::vec3 coordinates) : Visitor()
|
||||
{
|
||||
modelview_ = glm::mat4(1.f);
|
||||
points_.push_back( coordinates );
|
||||
}
|
||||
|
||||
PickingVisitor::PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end) : Visitor()
|
||||
{
|
||||
modelview_ = glm::mat4(1.f);
|
||||
points_.push_back( selectionstart );
|
||||
points_.push_back( selection_end );
|
||||
}
|
||||
|
||||
void PickingVisitor::visit(Node &n)
|
||||
@@ -31,6 +39,7 @@ void PickingVisitor::visit(Group &n)
|
||||
{
|
||||
if (!n.visible_)
|
||||
return;
|
||||
|
||||
glm::mat4 mv = modelview_;
|
||||
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
|
||||
if ( (*node)->visible_ )
|
||||
@@ -43,6 +52,7 @@ void PickingVisitor::visit(Switch &n)
|
||||
{
|
||||
if (!n.visible_ || n.numChildren()<1)
|
||||
return;
|
||||
|
||||
glm::mat4 mv = modelview_;
|
||||
n.activeChild()->accept(*this);
|
||||
modelview_ = mv;
|
||||
@@ -59,13 +69,32 @@ void PickingVisitor::visit(Surface &n)
|
||||
if (!n.visible_)
|
||||
return;
|
||||
|
||||
// apply inverse transform to the point of interest
|
||||
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_, 0.f, 1.f );
|
||||
// if more than one point given for testing: test overlap
|
||||
if (points_.size() > 1) {
|
||||
// create bounding box for those points (2 in practice)
|
||||
GlmToolkit::AxisAlignedBoundingBox bb_points;
|
||||
bb_points.extend(points_);
|
||||
|
||||
// test bounding box: it is an exact fit for a resctangular surface
|
||||
if ( n.bbox().contains( glm::vec3(P)) )
|
||||
// add this surface to the nodes picked
|
||||
nodes_.push_back( std::pair(&n, glm::vec2(P)) );
|
||||
// apply inverse transform
|
||||
bb_points = bb_points.transformed(glm::inverse(modelview_)) ;
|
||||
|
||||
// test bounding box for overlap with inverse transform bbox
|
||||
if ( bb_points.intersect( n.bbox() ) )
|
||||
// if ( n.bbox().contains( bb_points ) )
|
||||
// add this surface to the nodes picked
|
||||
nodes_.push_back( std::pair(&n, glm::vec2(0.f)) );
|
||||
}
|
||||
// only one point
|
||||
else if (points_.size() > 0) {
|
||||
|
||||
// apply inverse transform to the point of interest
|
||||
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( points_[0], 1.f );
|
||||
|
||||
// test bounding box for picking from a single point
|
||||
if ( n.bbox().contains( glm::vec3(P)) )
|
||||
// add this surface to the nodes picked
|
||||
nodes_.push_back( std::pair(&n, glm::vec2(P)) );
|
||||
}
|
||||
}
|
||||
|
||||
void PickingVisitor::visit(Frame &n)
|
||||
@@ -76,11 +105,12 @@ void PickingVisitor::visit(Frame &n)
|
||||
|
||||
void PickingVisitor::visit(Handles &n)
|
||||
{
|
||||
if (!n.visible_)
|
||||
// discard if not visible or if not exactly one point given for picking
|
||||
if (!n.visible_ || points_.size() != 1)
|
||||
return;
|
||||
|
||||
// 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( points_[0], 1.f );
|
||||
|
||||
// inverse transform to check the scale
|
||||
glm::vec4 S = glm::inverse(modelview_) * glm::vec4( 0.05f, 0.05f, 0.f, 0.f );
|
||||
@@ -108,7 +138,7 @@ void PickingVisitor::visit(Handles &n)
|
||||
// the icon for rotation is on the right top corner at (0.12, 0.12) in scene coordinates
|
||||
glm::vec4 vec = glm::inverse(modelview_) * glm::vec4( 0.1f, 0.1f, 0.f, 0.f );
|
||||
float l = glm::length( glm::vec2(vec) );
|
||||
picked = glm::length( glm::vec2( 1.f + l, 1.f + l) - glm::vec2(P) ) < 1.5f * scale;
|
||||
picked = glm::length( glm::vec2( 1.f + l, 1.f + l) - glm::vec2(P) ) < 1.5f * scale;
|
||||
}
|
||||
|
||||
if ( picked )
|
||||
@@ -119,26 +149,26 @@ void PickingVisitor::visit(Handles &n)
|
||||
|
||||
void PickingVisitor::visit(LineSquare &)
|
||||
{
|
||||
// apply inverse transform to the point of interest
|
||||
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_, 0.f, 1.f );
|
||||
// // apply inverse transform to the point of interest
|
||||
// glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_A_, 0.f, 1.f );
|
||||
|
||||
// lower left corner
|
||||
glm::vec3 LL = glm::vec3( -1.f, -1.f, 0.f );
|
||||
// up right corner
|
||||
glm::vec3 UR = glm::vec3( 1.f, 1.f, 0.f );
|
||||
// // lower left corner
|
||||
// glm::vec3 LL = glm::vec3( -1.f, -1.f, 0.f );
|
||||
// // up right corner
|
||||
// glm::vec3 UR = glm::vec3( 1.f, 1.f, 0.f );
|
||||
|
||||
// if P is over a line [LL UR] rectangle:
|
||||
// TODO
|
||||
// // if P is over a line [LL UR] rectangle:
|
||||
// // TODO
|
||||
}
|
||||
|
||||
void PickingVisitor::visit(LineCircle &n)
|
||||
{
|
||||
// apply inverse transform to the point of interest
|
||||
glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_, 0.f, 1.f );
|
||||
// // apply inverse transform to the point of interest
|
||||
// glm::vec4 P = glm::inverse(modelview_) * glm::vec4( point_A_, 0.f, 1.f );
|
||||
|
||||
float r = glm::length( glm::vec2(P) );
|
||||
if ( r < 1.02 && r > 0.98)
|
||||
nodes_.push_back( std::pair(&n, glm::vec2(P)) );
|
||||
// float r = glm::length( glm::vec2(P) );
|
||||
// if ( r < 1.02 && r > 0.98)
|
||||
// nodes_.push_back( std::pair(&n, glm::vec2(P)) );
|
||||
}
|
||||
|
||||
void PickingVisitor::visit(Scene &n)
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
|
||||
class PickingVisitor: public Visitor
|
||||
{
|
||||
glm::vec2 point_;
|
||||
std::vector<glm::vec3> points_;
|
||||
glm::mat4 modelview_;
|
||||
std::vector< std::pair<Node *, glm::vec2> > nodes_;
|
||||
|
||||
public:
|
||||
|
||||
PickingVisitor(glm::vec2 coordinates);
|
||||
PickingVisitor(glm::vec3 coordinates);
|
||||
PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end);
|
||||
std::vector< std::pair<Node *, glm::vec2> > picked() { return nodes_; }
|
||||
|
||||
// Elements of Scene
|
||||
|
||||
@@ -14,6 +14,16 @@ void Selection::add(Source *s)
|
||||
s->setMode(Source::ACTIVE);
|
||||
}
|
||||
|
||||
void Selection::set(SourceList l)
|
||||
{
|
||||
clear();
|
||||
|
||||
for(auto it = l.begin(); it != l.end(); it++)
|
||||
(*it)->setMode(Source::ACTIVE);
|
||||
|
||||
selection_ = l;
|
||||
}
|
||||
|
||||
void Selection::add(SourceList l)
|
||||
{
|
||||
for(auto it = l.begin(); it != l.end(); it++)
|
||||
@@ -65,3 +75,13 @@ bool Selection::contains (Source *s)
|
||||
{
|
||||
return (find(s) != selection_.end());
|
||||
}
|
||||
|
||||
SourceList::iterator Selection::begin()
|
||||
{
|
||||
return selection_.begin();
|
||||
}
|
||||
|
||||
SourceList::iterator Selection::end()
|
||||
{
|
||||
return selection_.end();
|
||||
}
|
||||
|
||||
@@ -13,8 +13,12 @@ public:
|
||||
void add (SourceList l);
|
||||
void remove (Source *s);
|
||||
void remove (SourceList l);
|
||||
|
||||
void set (SourceList l);
|
||||
void clear ();
|
||||
|
||||
SourceList::iterator begin ();
|
||||
SourceList::iterator end ();
|
||||
bool contains (Source *s);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -37,7 +37,7 @@ Source::Source() : initialized_(false), need_update_(true)
|
||||
frames_[View::MIXING] = new Switch;
|
||||
Frame *frame = new Frame(Frame::ROUND_THIN);
|
||||
frame->translation_.z = 0.1;
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.7f);
|
||||
frame->color = glm::vec4( COLOR_DEFAULT_SOURCE, 0.9f);
|
||||
frames_[View::MIXING]->attach(frame);
|
||||
frame = new Frame(Frame::ROUND_LARGE);
|
||||
frame->translation_.z = 0.01;
|
||||
|
||||
@@ -383,10 +383,16 @@ void UserInterface::handleMouse()
|
||||
{
|
||||
if (current)
|
||||
{
|
||||
|
||||
// grab current source
|
||||
View::Cursor c = Mixer::manager().currentView()->grab( mouseclic[ImGuiMouseButton_Left], mousepos, current, picked);
|
||||
|
||||
setMouseCursor(c);
|
||||
|
||||
// if ( Mixer::selection().contains(current)) {
|
||||
// for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); it++)
|
||||
// c = Mixer::manager().currentView()->grab( mouseclic[ImGuiMouseButton_Left], mousepos, *it, picked);
|
||||
// }
|
||||
|
||||
}
|
||||
else {
|
||||
// Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y);
|
||||
@@ -405,9 +411,9 @@ void UserInterface::handleMouse()
|
||||
else if ( ImGui::IsMouseDown(ImGuiMouseButton_Left) ) {
|
||||
|
||||
// get coordinate in world coordinate of mouse cursor
|
||||
glm::vec3 point = Rendering::manager().unProject(mousepos);
|
||||
// glm::vec3 point = Rendering::manager().unProject(mousepos);
|
||||
// ask the view what was picked
|
||||
picked = Mixer::manager().currentView()->pick(point);
|
||||
picked = Mixer::manager().currentView()->pick(mousepos);
|
||||
|
||||
// if nothing picked,
|
||||
if ( picked.first == nullptr ) {
|
||||
|
||||
62
View.cpp
62
View.cpp
@@ -82,41 +82,54 @@ View::Cursor View::drag (glm::vec2 from, glm::vec2 to)
|
||||
return Cursor(Cursor_ResizeAll);
|
||||
}
|
||||
|
||||
std::pair<Node *, glm::vec2> View::pick(glm::vec3 point)
|
||||
std::pair<Node *, glm::vec2> View::pick(glm::vec2 P)
|
||||
{
|
||||
std::pair<Node *, glm::vec2> picked = { nullptr, glm::vec2(0.f) };
|
||||
// prepare empty return value
|
||||
std::pair<Node *, glm::vec2> pick = { nullptr, glm::vec2(0.f) };
|
||||
|
||||
// unproject mouse coordinate into scene coordinates
|
||||
glm::vec3 scene_point_ = Rendering::manager().unProject(P);
|
||||
|
||||
// picking visitor traverses the scene
|
||||
PickingVisitor pv(point);
|
||||
PickingVisitor pv(scene_point_);
|
||||
scene.accept(pv);
|
||||
|
||||
// picking visitor found nodes?
|
||||
if ( !pv.picked().empty()) {
|
||||
|
||||
// select top-most Node picked
|
||||
picked = pv.picked().back();
|
||||
|
||||
//DEBUG
|
||||
// select(glm::vec2(-1.f, -1.f), glm::vec2(1.f, 1.f));
|
||||
|
||||
pick = pv.picked().back();
|
||||
|
||||
}
|
||||
// cancel selection on clic in background
|
||||
else {
|
||||
// deselect();
|
||||
}
|
||||
|
||||
return picked;
|
||||
return pick;
|
||||
}
|
||||
|
||||
void GeometryView::select(glm::vec2 A, glm::vec2 B)
|
||||
void View::select(glm::vec2 A, glm::vec2 B)
|
||||
{
|
||||
// for(auto it = scene.ws()->begin(); it != scene.ws()->end(); it++) {
|
||||
// if ( *it != selection_box_)
|
||||
// selection_box_->attach(*it);
|
||||
// }
|
||||
// unproject mouse coordinate into scene coordinates
|
||||
glm::vec3 scene_point_A = Rendering::manager().unProject(A);
|
||||
glm::vec3 scene_point_B = Rendering::manager().unProject(B);
|
||||
|
||||
// selection_box_->visible_ = true;
|
||||
// picking visitor traverses the scene
|
||||
PickingVisitor pv(scene_point_A, scene_point_B);
|
||||
scene.accept(pv);
|
||||
|
||||
// reset selection
|
||||
Mixer::selection().clear();
|
||||
|
||||
// picking visitor found nodes in the area?
|
||||
if ( !pv.picked().empty()) {
|
||||
|
||||
SourceList selection;
|
||||
for(auto p = pv.picked().begin(); p != pv.picked().end(); p++){
|
||||
Source *s = Mixer::manager().findSource( p->first );
|
||||
if (s)
|
||||
selection.push_back( s );
|
||||
}
|
||||
// set the selection with list of picked (overlaped) sources
|
||||
Mixer::selection().add(selection);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -368,12 +381,16 @@ void GeometryView::draw()
|
||||
}
|
||||
|
||||
|
||||
std::pair<Node *, glm::vec2> GeometryView::pick(glm::vec3 point)
|
||||
std::pair<Node *, glm::vec2> GeometryView::pick(glm::vec2 P)
|
||||
{
|
||||
// prepare empty return value
|
||||
std::pair<Node *, glm::vec2> pick = { nullptr, glm::vec2(0.f) };
|
||||
|
||||
// unproject mouse coordinate into scene coordinates
|
||||
glm::vec3 scene_point_ = Rendering::manager().unProject(P);
|
||||
|
||||
// picking visitor traverses the scene
|
||||
PickingVisitor pv(point);
|
||||
PickingVisitor pv(scene_point_);
|
||||
scene.accept(pv);
|
||||
|
||||
// picking visitor found nodes?
|
||||
@@ -631,6 +648,7 @@ float LayerView::setDepth(Source *s, float d)
|
||||
return sourceNode->translation_.z;
|
||||
}
|
||||
|
||||
|
||||
View::Cursor LayerView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair<Node *, glm::vec2> pick)
|
||||
{
|
||||
if (!s)
|
||||
|
||||
14
View.h
14
View.h
@@ -43,8 +43,11 @@ public:
|
||||
Cursor(CursorType t, std::string i = "") { type = t; info = i;}
|
||||
} Cursor;
|
||||
|
||||
// picking of nodes in a view provided a point coordinates in scene reference frame
|
||||
virtual std::pair<Node *, glm::vec2> pick(glm::vec3 point);
|
||||
// picking of nodes in a view provided a point coordinates in screen coordinates
|
||||
virtual std::pair<Node *, glm::vec2> pick(glm::vec2);
|
||||
|
||||
// select sources provided a start and end selection points in screen coordinates
|
||||
virtual void select(glm::vec2, glm::vec2);
|
||||
|
||||
// drag the view provided a start and an end point in screen coordinates
|
||||
virtual Cursor drag (glm::vec2, glm::vec2);
|
||||
@@ -53,12 +56,11 @@ public:
|
||||
virtual Cursor grab (glm::vec2, glm::vec2, Source*, std::pair<Node *, glm::vec2>) {
|
||||
return Cursor();
|
||||
}
|
||||
|
||||
// test mouse over provided a point in screen coordinates and the picking point
|
||||
virtual Cursor over (glm::vec2, Source*, std::pair<Node *, glm::vec2>) {
|
||||
return Cursor();
|
||||
}
|
||||
// select sources provided a start and end selection points in screen coordinates
|
||||
virtual void select(glm::vec2, glm::vec2) {}
|
||||
|
||||
virtual void restoreSettings();
|
||||
virtual void saveSettings();
|
||||
@@ -114,10 +116,10 @@ public:
|
||||
void draw () override;
|
||||
void update (float dt) override;
|
||||
void zoom (float factor) override;
|
||||
std::pair<Node *, glm::vec2> pick(glm::vec3 point) override;
|
||||
std::pair<Node *, glm::vec2> pick(glm::vec2 P) override;
|
||||
Cursor grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair<Node *, glm::vec2> pick) override;
|
||||
Cursor over (glm::vec2, Source*, std::pair<Node *, glm::vec2>) override;
|
||||
void select(glm::vec2, glm::vec2) override;
|
||||
// void select(glm::vec2, glm::vec2) override;
|
||||
|
||||
// class Box *selection_box_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user