Fixed behavior for current and edit source selection in AppearanceView.

This commit is contained in:
brunoherbelin
2020-11-23 23:35:48 +01:00
parent 7f161a0a49
commit 4a6a110e3d
8 changed files with 127 additions and 140 deletions

View File

@@ -6,7 +6,7 @@
#include "Scene.h" #include "Scene.h"
DrawVisitor::DrawVisitor(Node *nodetodraw, glm::mat4 projection) DrawVisitor::DrawVisitor(Node *nodetodraw, glm::mat4 projection, bool force): force_(force)
{ {
target_ = nodetodraw; target_ = nodetodraw;
modelview_ = glm::identity<glm::mat4>(); modelview_ = glm::identity<glm::mat4>();
@@ -52,7 +52,7 @@ void DrawVisitor::visit(Group &n)
// traverse children // traverse children
glm::mat4 mv = modelview_; glm::mat4 mv = modelview_;
for (NodeSet::iterator node = n.begin(); !done_ && node != n.end(); node++) { for (NodeSet::iterator node = n.begin(); !done_ && node != n.end(); node++) {
if ( (*node)->visible_ ) if ( (*node)->visible_ || force_)
(*node)->accept(*this); (*node)->accept(*this);
modelview_ = mv; modelview_ = mv;
} }

View File

@@ -10,11 +10,12 @@ class DrawVisitor : public Visitor
glm::mat4 projection_; glm::mat4 projection_;
Node *target_; Node *target_;
bool done_; bool done_;
bool force_;
int num_duplicat_; int num_duplicat_;
glm::mat4 transform_duplicat_; glm::mat4 transform_duplicat_;
public: public:
DrawVisitor(Node *nodetodraw, glm::mat4 projection); DrawVisitor(Node *nodetodraw, glm::mat4 projection, bool force = false);
void loop(int num, glm::mat4 transform); void loop(int num, glm::mat4 transform);

View File

@@ -606,6 +606,7 @@ void Mixer::setCurrentSource(uint64_t id)
void Mixer::setCurrentSource(Node *node) void Mixer::setCurrentSource(Node *node)
{ {
if (node!=nullptr)
setCurrentSource( session_->find(node) ); setCurrentSource( session_->find(node) );
} }
@@ -616,6 +617,7 @@ void Mixer::setCurrentSource(std::string namesource)
void Mixer::setCurrentSource(Source *s) void Mixer::setCurrentSource(Source *s)
{ {
if (s!=nullptr)
setCurrentSource( session_->find(s) ); setCurrentSource( session_->find(s) );
} }

View File

@@ -11,13 +11,13 @@
#include <glm/gtx/vector_angle.hpp> #include <glm/gtx/vector_angle.hpp>
PickingVisitor::PickingVisitor(glm::vec3 coordinates) : Visitor() PickingVisitor::PickingVisitor(glm::vec3 coordinates, bool force) : Visitor(), force_(force)
{ {
modelview_ = glm::mat4(1.f); modelview_ = glm::mat4(1.f);
points_.push_back( coordinates ); points_.push_back( coordinates );
} }
PickingVisitor::PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end) : Visitor() PickingVisitor::PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end, bool force) : Visitor(), force_(force)
{ {
modelview_ = glm::mat4(1.f); modelview_ = glm::mat4(1.f);
points_.push_back( selectionstart ); points_.push_back( selectionstart );
@@ -32,12 +32,12 @@ void PickingVisitor::visit(Node &n)
void PickingVisitor::visit(Group &n) void PickingVisitor::visit(Group &n)
{ {
if (!n.visible_) if (!n.visible_ && !force_)
return; return;
glm::mat4 mv = modelview_; glm::mat4 mv = modelview_;
for (NodeSet::iterator node = n.begin(); node != n.end(); node++) { for (NodeSet::iterator node = n.begin(); node != n.end(); node++) {
if ( (*node)->visible_ ) if ( (*node)->visible_ || force_)
(*node)->accept(*this); (*node)->accept(*this);
modelview_ = mv; modelview_ = mv;
} }
@@ -45,7 +45,7 @@ void PickingVisitor::visit(Group &n)
void PickingVisitor::visit(Switch &n) void PickingVisitor::visit(Switch &n)
{ {
if (!n.visible_ || n.numChildren()<1) if ((!n.visible_ && !force_) || n.numChildren()<1)
return; return;
glm::mat4 mv = modelview_; glm::mat4 mv = modelview_;
@@ -60,7 +60,7 @@ void PickingVisitor::visit(Primitive &)
void PickingVisitor::visit(Surface &n) void PickingVisitor::visit(Surface &n)
{ {
if (!n.visible_) if (!n.visible_ && !force_)
return; return;
// if more than one point given for testing: test overlap // if more than one point given for testing: test overlap
@@ -100,7 +100,7 @@ void PickingVisitor::visit(Surface &n)
void PickingVisitor::visit(Disk &n) void PickingVisitor::visit(Disk &n)
{ {
// discard if not visible or if not exactly one point given for picking // discard if not visible or if not exactly one point given for picking
if (!n.visible_ || points_.size() != 1) if ((!n.visible_ && !force_) || points_.size() != 1)
return; return;
// apply inverse transform to the point of interest // apply inverse transform to the point of interest
@@ -116,7 +116,7 @@ void PickingVisitor::visit(Disk &n)
void PickingVisitor::visit(Handles &n) void PickingVisitor::visit(Handles &n)
{ {
// discard if not visible or if not exactly one point given for picking // discard if not visible or if not exactly one point given for picking
if (!n.visible_ || points_.size() != 1) if ((!n.visible_ && !force_) || points_.size() != 1)
return; return;
// apply inverse transform to the point of interest // apply inverse transform to the point of interest

View File

@@ -21,11 +21,12 @@ class PickingVisitor: public Visitor
std::vector<glm::vec3> points_; std::vector<glm::vec3> points_;
glm::mat4 modelview_; glm::mat4 modelview_;
std::vector< std::pair<Node *, glm::vec2> > nodes_; std::vector< std::pair<Node *, glm::vec2> > nodes_;
bool force_;
public: public:
PickingVisitor(glm::vec3 coordinates); PickingVisitor(glm::vec3 coordinates, bool force = false);
PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end); PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end, bool force = false);
bool empty() const {return nodes_.empty(); } bool empty() const {return nodes_.empty(); }
std::pair<Node *, glm::vec2> back() const { return nodes_.back(); } std::pair<Node *, glm::vec2> back() const { return nodes_.back(); }

221
View.cpp
View File

@@ -846,7 +846,6 @@ void GeometryView::draw()
// draw scene of this view // draw scene of this view
View::draw(); View::draw();
// scene.root()->draw(glm::identity<glm::mat4>(), Rendering::manager().Projection());
// re-draw frames of all sources on top // re-draw frames of all sources on top
// (otherwise hidden in stack of sources) // (otherwise hidden in stack of sources)
@@ -1814,29 +1813,6 @@ AppearanceView::AppearanceView() : View(APPEARANCE), edit_source_(nullptr), need
} }
Source *AppearanceView::EditCurrent()
{
Source *current_source = Mixer::manager().currentSource();
// no current source
if (current_source == nullptr) {
// if something can be selected
if ( !Mixer::manager().session()->empty() ) {
// if the edit source exists
if (Mixer::manager().session()->find(edit_source_)!=Mixer::manager().session()->end())
// restore edited source as current
current_source = edit_source_;
else
// pick the first source of the session
current_source = *Mixer::manager().session()->begin();
// apply current source change
Mixer::manager().setCurrentSource(current_source);
}
}
return current_source;
}
void AppearanceView::update(float dt) void AppearanceView::update(float dt)
{ {
View::update(dt); View::update(dt);
@@ -1874,95 +1850,78 @@ int AppearanceView::size ()
void AppearanceView::selectAll() void AppearanceView::selectAll()
{ {
need_edit_update_ = true; Mixer::manager().setCurrentSource( getEditOrCurrentSource() );
} }
void AppearanceView::select(glm::vec2 A, glm::vec2 B) void AppearanceView::select(glm::vec2 A, glm::vec2 B)
{ {
need_edit_update_ = true; // unproject mouse coordinate into scene coordinates
glm::vec3 scene_point_A = Rendering::manager().unProject(A);
glm::vec3 scene_point_B = Rendering::manager().unProject(B);
// picking visitor traverses the scene
PickingVisitor pv(scene_point_A, scene_point_B, true);
scene.accept(pv);
// picking visitor found nodes in the area?
if ( !pv.empty()) {
// loop over sources matching the list of picked nodes
for(std::vector< std::pair<Node *, glm::vec2> >::const_reverse_iterator p = pv.rbegin(); p != pv.rend(); p++){
Source *s = Mixer::manager().findSource( p->first );
// set the edit source as current if selected
if (s != nullptr && s == edit_source_)
Mixer::manager().setCurrentSource( s );
}
}
} }
std::pair<Node *, glm::vec2> AppearanceView::pick(glm::vec2 P) std::pair<Node *, glm::vec2> AppearanceView::pick(glm::vec2 P)
{ {
// get picking from generic View // prepare empty return value
std::pair<Node *, glm::vec2> pick = View::pick(P); std::pair<Node *, glm::vec2> pick = { nullptr, glm::vec2(0.f) };
Source *picked = nullptr; // unproject mouse coordinate into scene coordinates
glm::vec3 scene_point_ = Rendering::manager().unProject(P);
if (pick.first != nullptr) { // picking visitor traverses the scene
PickingVisitor pv(scene_point_, true);
scene.accept(pv);
picked = Mixer::manager().findSource(pick.first); // picking visitor found nodes?
if ( !pv.empty()) {
// keep edit source active if it is clicked
Source *s = edit_source_;
if (s != nullptr) {
if (picked != nullptr) { // find if the edit source was picked
if (picked == edit_source_) { auto itp = pv.rbegin();
if (pick.first == edit_source_->handles_[mode_][Handles::MENU] ) for (; itp != pv.rend(); itp++){
// test if source contains this node
Source::hasNode is_in_source((*itp).first );
if ( is_in_source( s ) ){
// a node in the current source was clicked !
pick = *itp;
break;
}
}
// not found: the edit source was not clicked
if (itp == pv.rend())
s = nullptr;
// picking on the menu handle
else if ( pick.first == s->handles_[mode_][Handles::MENU] ) {
// show context menu // show context menu
show_context_menu_ = true; show_context_menu_ = true;
} }
else {
picked = nullptr;
}
}
} }
if (picked == nullptr){ // not the edit source (or no edit source)
// make sure the source to edit is always picked if (s == nullptr) {
if (edit_source_) // cancel pick
pick.first = edit_source_->frames_[mode_]; pick = { 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(scene_point_);
// scene.accept(pv);
// // picking visitor found nodes?
// if ( !pv.empty() ) {
// // keep edit source active if it is clicked
// Source *s = edit_source_;
// if (s != nullptr) {
// // find if the current source was picked
// auto itp = pv.rbegin();
// for (; itp != pv.rend(); itp++){
// // test if source contains this node
// Source::hasNode is_in_source((*itp).first );
// if ( is_in_source( s ) ){
// // a node in the current source was clicked !
// pick = *itp;
// break;
// }
// }
// // not found: the edit source was not clicked
// if (itp == pv.rend())
// {
// //s = nullptr;
//// Mixer::selection().set(s);
// pick.first = s->frames_[mode_];
// }
// // picking on the edit source
// else {
//// Mixer::selection().clear();
// if ( pick.first == s->handles_[mode_][Handles::MENU] ) // show context menu
// show_context_menu_ = true;
// }
// }
// // no edit source or the clicked source changed
// if (s == nullptr) {
// edit_source_ = EditCurrent();
// if (edit_source_)
// pick.first = edit_source_->frames_[mode_];
// }
// }
// need_edit_update_ = true;
return pick; return pick;
} }
@@ -1992,15 +1951,34 @@ void AppearanceView::adjustBackground()
} }
} }
Source *AppearanceView::getEditOrCurrentSource()
{
// get current source
Source *_source = Mixer::manager().currentSource();
// no current source?
if (_source == nullptr) {
// if something can be selected
if ( !Mixer::manager().session()->empty()) {
// return the edit source, if exists
if (edit_source_ != nullptr)
_source = Mixer::manager().findSource(edit_source_->id());
}
}
return _source;
}
void AppearanceView::draw() void AppearanceView::draw()
{ {
// edit view needs to be updated (source changed) // edit view needs to be updated (source changed)
if ( need_edit_update_ ) { if ( need_edit_update_ )
{
need_edit_update_ = false; need_edit_update_ = false;
// now, follow the change of current source // now, follow the change of current source
// & remember source to edit // & remember source to edit
edit_source_ = EditCurrent(); edit_source_ = getEditOrCurrentSource();
// update background and frame to match editsource // update background and frame to match editsource
adjustBackground(); adjustBackground();
@@ -2013,38 +1991,43 @@ void AppearanceView::draw()
} }
showContextMenu(mode_,"AppearanceContextMenu"); showContextMenu(mode_,"AppearanceContextMenu");
// display interface duration
if ( edit_source_ != nullptr ) {
glm::vec2 P = Rendering::manager().project(glm::vec3(1.1f, 1.14f, 0.f), scene.root()->transform_, false); // if ( edit_source_ != nullptr ) {
ImGui::SetNextWindowPos(ImVec2(P.x, P.y), ImGuiCond_Always);
if (ImGui::Begin("##WIDTH", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground
| ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings
| ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
{
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
ImGui::SetNextItemWidth(100.f);
float crop_width = edit_source_->frame()->projectionAspectRatio();
if ( ImGui::DragFloat("##apppearancewidth", &crop_width, 0.05f, 0.2f, 1.f, "%.1f ") )
{
// crop horizontally
edit_source_->frame()->crop(glm::vec2(crop_width, 1.f));
// TODO scale GEOMETRY and RENDER groups
edit_source_->touch();
// update background and frame
adjustBackground();
}
ImGui::PopFont(); // glm::vec2 P = Rendering::manager().project(glm::vec3(1.1f, 1.14f, 0.f), scene.root()->transform_, false);
ImGui::End(); // ImGui::SetNextWindowPos(ImVec2(P.x, P.y), ImGuiCond_Always);
} // if (ImGui::Begin("##WIDTH", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground
// | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings
// | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
// {
// ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
// ImGui::SetNextItemWidth(100.f);
// float crop_width = edit_source_->frame()->projectionAspectRatio();
// if ( ImGui::DragFloat("##apppearancewidth", &crop_width, 0.05f, 0.2f, 1.f, "%.1f ") )
// {
// // crop horizontally
// edit_source_->frame()->crop(glm::vec2(crop_width, 1.f));
// // TODO scale GEOMETRY and RENDER groups
// edit_source_->touch();
// // update background and frame
// adjustBackground();
// }
} // ImGui::PopFont();
// ImGui::End();
// }
// }
Shader::force_blending_opacity = true; Shader::force_blending_opacity = true;
View::draw(); View::draw();
Shader::force_blending_opacity = false; Shader::force_blending_opacity = false;
if (edit_source_ != nullptr){
// force to redraw the frame of the edit source (even if source is not visible)
DrawVisitor dv(edit_source_->frames_[mode_], Rendering::manager().Projection(), true);
scene.accept(dv);
}
} }
View::Cursor AppearanceView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick) View::Cursor AppearanceView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick)

2
View.h
View File

@@ -243,7 +243,7 @@ private:
Source *edit_source_; Source *edit_source_;
bool need_edit_update_; bool need_edit_update_;
Source *EditCurrent(); Source *getEditOrCurrentSource();
void adjustBackground(); void adjustBackground();

View File

@@ -34,13 +34,13 @@
#define MIXING_MAX_SCALE 7.0f #define MIXING_MAX_SCALE 7.0f
#define MIXING_ICON_SCALE 0.15f, 0.15f, 1.f #define MIXING_ICON_SCALE 0.15f, 0.15f, 1.f
#define GEOMETRY_DEFAULT_SCALE 1.2f #define GEOMETRY_DEFAULT_SCALE 1.2f
#define GEOMETRY_MIN_SCALE 0.2f #define GEOMETRY_MIN_SCALE 0.4f
#define GEOMETRY_MAX_SCALE 10.0f #define GEOMETRY_MAX_SCALE 10.0f
#define LAYER_DEFAULT_SCALE 0.8f #define LAYER_DEFAULT_SCALE 0.8f
#define LAYER_MIN_SCALE 0.4f #define LAYER_MIN_SCALE 0.4f
#define LAYER_MAX_SCALE 1.7f #define LAYER_MAX_SCALE 1.7f
#define APPEARANCE_DEFAULT_SCALE 1.6f #define APPEARANCE_DEFAULT_SCALE 1.6f
#define APPEARANCE_MIN_SCALE 0.5f #define APPEARANCE_MIN_SCALE 0.4f
#define APPEARANCE_MAX_SCALE 10.0f #define APPEARANCE_MAX_SCALE 10.0f
#define TRANSITION_DEFAULT_SCALE 5.0f #define TRANSITION_DEFAULT_SCALE 5.0f
#define TRANSITION_MIN_DURATION 0.2f #define TRANSITION_MIN_DURATION 0.2f