diff --git a/DrawVisitor.cpp b/DrawVisitor.cpp index 3e8c9b3..2cc4031 100644 --- a/DrawVisitor.cpp +++ b/DrawVisitor.cpp @@ -6,7 +6,7 @@ #include "Scene.h" -DrawVisitor::DrawVisitor(Node *nodetodraw, glm::mat4 projection) +DrawVisitor::DrawVisitor(Node *nodetodraw, glm::mat4 projection, bool force): force_(force) { target_ = nodetodraw; modelview_ = glm::identity(); @@ -52,7 +52,7 @@ void DrawVisitor::visit(Group &n) // traverse children glm::mat4 mv = modelview_; for (NodeSet::iterator node = n.begin(); !done_ && node != n.end(); node++) { - if ( (*node)->visible_ ) + if ( (*node)->visible_ || force_) (*node)->accept(*this); modelview_ = mv; } diff --git a/DrawVisitor.h b/DrawVisitor.h index 968d742..4f7fbc7 100644 --- a/DrawVisitor.h +++ b/DrawVisitor.h @@ -10,11 +10,12 @@ class DrawVisitor : public Visitor glm::mat4 projection_; Node *target_; bool done_; + bool force_; int num_duplicat_; glm::mat4 transform_duplicat_; public: - DrawVisitor(Node *nodetodraw, glm::mat4 projection); + DrawVisitor(Node *nodetodraw, glm::mat4 projection, bool force = false); void loop(int num, glm::mat4 transform); diff --git a/Mixer.cpp b/Mixer.cpp index 1d2c1e9..06504a9 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -606,7 +606,8 @@ void Mixer::setCurrentSource(uint64_t id) void Mixer::setCurrentSource(Node *node) { - setCurrentSource( session_->find(node) ); + if (node!=nullptr) + setCurrentSource( session_->find(node) ); } void Mixer::setCurrentSource(std::string namesource) @@ -616,7 +617,8 @@ void Mixer::setCurrentSource(std::string namesource) void Mixer::setCurrentSource(Source *s) { - setCurrentSource( session_->find(s) ); + if (s!=nullptr) + setCurrentSource( session_->find(s) ); } void Mixer::setCurrentIndex(int index) diff --git a/PickingVisitor.cpp b/PickingVisitor.cpp index 9b35e6b..00905b5 100644 --- a/PickingVisitor.cpp +++ b/PickingVisitor.cpp @@ -11,13 +11,13 @@ #include -PickingVisitor::PickingVisitor(glm::vec3 coordinates) : Visitor() +PickingVisitor::PickingVisitor(glm::vec3 coordinates, bool force) : Visitor(), force_(force) { modelview_ = glm::mat4(1.f); 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); points_.push_back( selectionstart ); @@ -32,12 +32,12 @@ void PickingVisitor::visit(Node &n) void PickingVisitor::visit(Group &n) { - if (!n.visible_) + if (!n.visible_ && !force_) return; glm::mat4 mv = modelview_; for (NodeSet::iterator node = n.begin(); node != n.end(); node++) { - if ( (*node)->visible_ ) + if ( (*node)->visible_ || force_) (*node)->accept(*this); modelview_ = mv; } @@ -45,7 +45,7 @@ void PickingVisitor::visit(Group &n) void PickingVisitor::visit(Switch &n) { - if (!n.visible_ || n.numChildren()<1) + if ((!n.visible_ && !force_) || n.numChildren()<1) return; glm::mat4 mv = modelview_; @@ -60,7 +60,7 @@ void PickingVisitor::visit(Primitive &) void PickingVisitor::visit(Surface &n) { - if (!n.visible_) + if (!n.visible_ && !force_) return; // if more than one point given for testing: test overlap @@ -100,7 +100,7 @@ void PickingVisitor::visit(Surface &n) void PickingVisitor::visit(Disk &n) { // 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; // apply inverse transform to the point of interest @@ -116,7 +116,7 @@ void PickingVisitor::visit(Disk &n) void PickingVisitor::visit(Handles &n) { // 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; // apply inverse transform to the point of interest diff --git a/PickingVisitor.h b/PickingVisitor.h index eda682a..8a7d16e 100644 --- a/PickingVisitor.h +++ b/PickingVisitor.h @@ -21,11 +21,12 @@ class PickingVisitor: public Visitor std::vector points_; glm::mat4 modelview_; std::vector< std::pair > nodes_; + bool force_; public: - PickingVisitor(glm::vec3 coordinates); - PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end); + PickingVisitor(glm::vec3 coordinates, bool force = false); + PickingVisitor(glm::vec3 selectionstart, glm::vec3 selection_end, bool force = false); bool empty() const {return nodes_.empty(); } std::pair back() const { return nodes_.back(); } diff --git a/View.cpp b/View.cpp index 3f65865..9abd191 100644 --- a/View.cpp +++ b/View.cpp @@ -846,7 +846,6 @@ void GeometryView::draw() // draw scene of this view View::draw(); -// scene.root()->draw(glm::identity(), Rendering::manager().Projection()); // re-draw frames of all sources on top // (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) { View::update(dt); @@ -1874,96 +1850,79 @@ int AppearanceView::size () void AppearanceView::selectAll() { - need_edit_update_ = true; + Mixer::manager().setCurrentSource( getEditOrCurrentSource() ); } 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 >::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 AppearanceView::pick(glm::vec2 P) { - // get picking from generic View - std::pair pick = View::pick(P); + // prepare empty return value + std::pair 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) { - if (picked == edit_source_) { - if (pick.first == edit_source_->handles_[mode_][Handles::MENU] ) - // show context menu - show_context_menu_ = true; + // find if the edit 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; + } } - else { - picked = nullptr; + // 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_ = true; } } + + // not the edit source (or no edit source) + if (s == nullptr) { + // cancel pick + pick = { nullptr, glm::vec2(0.f) }; + } + } - if (picked == nullptr){ - // make sure the source to edit is always picked - if (edit_source_) - pick.first = edit_source_->frames_[mode_]; - } - - -// // prepare empty return value -// std::pair 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; } @@ -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() { // edit view needs to be updated (source changed) - if ( need_edit_update_ ) { + if ( need_edit_update_ ) + { need_edit_update_ = false; // now, follow the change of current source // & remember source to edit - edit_source_ = EditCurrent(); + edit_source_ = getEditOrCurrentSource(); // update background and frame to match editsource adjustBackground(); @@ -2013,38 +1991,43 @@ void AppearanceView::draw() } 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); - 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(); - } +// if ( edit_source_ != nullptr ) { - ImGui::PopFont(); - ImGui::End(); - } +// glm::vec2 P = Rendering::manager().project(glm::vec3(1.1f, 1.14f, 0.f), scene.root()->transform_, false); +// 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; View::draw(); 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 pick) diff --git a/View.h b/View.h index 3997720..60362bd 100644 --- a/View.h +++ b/View.h @@ -243,7 +243,7 @@ private: Source *edit_source_; bool need_edit_update_; - Source *EditCurrent(); + Source *getEditOrCurrentSource(); void adjustBackground(); diff --git a/defines.h b/defines.h index 8651211..5ed2500 100644 --- a/defines.h +++ b/defines.h @@ -34,13 +34,13 @@ #define MIXING_MAX_SCALE 7.0f #define MIXING_ICON_SCALE 0.15f, 0.15f, 1.f #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 LAYER_DEFAULT_SCALE 0.8f #define LAYER_MIN_SCALE 0.4f #define LAYER_MAX_SCALE 1.7f #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 TRANSITION_DEFAULT_SCALE 5.0f #define TRANSITION_MIN_DURATION 0.2f