From e546214018f81a6cc7b4af2d9e01258bce423cfc Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Sat, 5 Sep 2020 00:19:22 +0200 Subject: [PATCH] New handle in GeometryView for Proportional scaling of source: added drawing of Handle, Picking visitor and View Geometry scaling. --- CMakeLists.txt | 3 +++ Decorations.cpp | 61 +++++++++++++++++++------------------------ Decorations.h | 4 +-- PickingVisitor.cpp | 6 +++++ Source.cpp | 5 ++++ Source.h | 2 +- View.cpp | 64 ++++++++++++++++++++++++++++------------------ defines.h | 1 + 8 files changed, 83 insertions(+), 63 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a19eb8..187c6a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -293,6 +293,7 @@ set(VMIX_RSC_FILES ./rsc/mesh/border_large_round.ply ./rsc/mesh/border_large_top.ply ./rsc/mesh/border_handles_rotation.ply + ./rsc/mesh/border_handles_scale.ply ./rsc/mesh/border_handles_overlay.ply ./rsc/mesh/border_handles_sharp.ply ./rsc/mesh/border_large_sharp.ply @@ -309,6 +310,8 @@ set(VMIX_RSC_FILES ./rsc/mesh/icon_circles.ply ./rsc/mesh/icon_dots.ply ./rsc/mesh/icon_empty.ply + ./rsc/mesh/icon_lock.ply + ./rsc/mesh/icon_unlock.ply ./rsc/mesh/h_line.ply ./rsc/mesh/h_mark.ply ) diff --git a/Decorations.cpp b/Decorations.cpp index 260bc31..ec513de 100644 --- a/Decorations.cpp +++ b/Decorations.cpp @@ -62,32 +62,6 @@ Frame::Frame(CornerType corner, BorderType border, ShadowType shadow) : Node(), break; } -// switch (type) { -// case SHARP_LARGE: -// square_ = sharpframe; -// shadow_ = shadows[0]; -// break; -// case SHARP_THIN: -// square_ = sharpframe; -// break; -// case ROUND_LARGE: -// side_ = frames[2]; -// top_ = frames[3]; -// shadow_ = shadows[1]; -// break; -// default: -// case ROUND_THIN: -// side_ = frames[0]; -// top_ = frames[1]; -// shadow_ = shadows[1]; -// break; -// case ROUND_THIN_PERSPECTIVE: -// side_ = frames[0]; -// top_ = frames[1]; -// shadow_ = shadows[2]; -// break; -// } - color = glm::vec4( 1.f, 1.f, 1.f, 1.f); } @@ -181,12 +155,16 @@ void Frame::accept(Visitor& v) Handles::Handles(Type type) : Node(), type_(type) { - static Mesh *handle_rotation_ = new Mesh("mesh/border_handles_rotation.ply"); - static Mesh *handle_corner = new Mesh("mesh/border_handles_overlay.ply"); + static Mesh *handle_rotation = new Mesh("mesh/border_handles_rotation.ply"); + static Mesh *handle_corner = new Mesh("mesh/border_handles_overlay.ply"); + static Mesh *handle_scale = new Mesh("mesh/border_handles_scale.ply"); color = glm::vec4( 1.f, 1.f, 0.f, 1.f); - if ( type_ == ROTATE ) { - handle_ = handle_rotation_; + if ( type_ == Handles::ROTATE ) { + handle_ = handle_rotation; + } + else if ( type_ == Handles::SCALE ) { + handle_ = handle_scale; } else { handle_ = handle_corner; @@ -227,7 +205,7 @@ void Handles::draw(glm::mat4 modelview, glm::mat4 projection) // Log::Info(" (0,1) becomes (%f, %f)", scale.x, scale.y); - if ( type_ == RESIZE ) { + if ( type_ == Handles::RESIZE ) { // 4 corners vec = modelview * glm::vec4(1.f, -1.f, 0.f, 1.f); @@ -246,7 +224,7 @@ void Handles::draw(glm::mat4 modelview, glm::mat4 projection) ctm = GlmToolkit::transform(vec, rot, glm::vec3(1.f)); handle_->draw( ctm, projection ); } - else if ( type_ == RESIZE_H ){ + else if ( type_ == Handles::RESIZE_H ){ // left and right vec = modelview * glm::vec4(1.f, 0.f, 0.f, 1.f); ctm = GlmToolkit::transform(vec, rot, glm::vec3(1.f)); @@ -256,7 +234,7 @@ void Handles::draw(glm::mat4 modelview, glm::mat4 projection) ctm = GlmToolkit::transform(vec, rot, glm::vec3(1.f)); handle_->draw( ctm, projection ); } - else if ( type_ == RESIZE_V ){ + else if ( type_ == Handles::RESIZE_V ){ // top and bottom vec = modelview * glm::vec4(0.f, 1.f, 0.f, 1.f); ctm = GlmToolkit::transform(vec, rot, glm::vec3(1.f)); @@ -266,7 +244,7 @@ void Handles::draw(glm::mat4 modelview, glm::mat4 projection) ctm = GlmToolkit::transform(vec, rot, glm::vec3(1.f)); handle_->draw( ctm, projection ); } - else if ( type_ == ROTATE ){ + else if ( type_ == Handles::ROTATE ){ // one icon in top right corner // 1. Fixed displacement by (0.12,0.12) along the rotation.. ctm = GlmToolkit::transform(glm::vec4(0.f), rot, glm::vec3(1.f)); @@ -290,6 +268,17 @@ void Handles::draw(glm::mat4 modelview, glm::mat4 projection) handle_->draw( ctm, projection ); } + else if ( type_ == Handles::SCALE ){ + // one icon in top right corner + // 1. Fixed displacement by (0.12,0.12) along the rotation.. + ctm = GlmToolkit::transform(glm::vec4(0.f), rot, glm::vec3(1.f)); + glm::vec4 pos = ctm * glm::vec4(0.12f, -0.12f, 0.f, 1.f); + // 2. ..from the bottom right corner (1,1) + vec = ( modelview * glm::vec4(1.f, -1.f, 0.f, 1.f) ) + pos; + ctm = GlmToolkit::transform(vec, rot, glm::vec3(1.f)); + // 3. draw + handle_->draw( ctm, projection ); + } } } @@ -303,7 +292,7 @@ void Handles::accept(Visitor& v) Symbol::Symbol(Type t, glm::vec3 pos) : Node(), type_(t) { - static Mesh *icons[9] = {nullptr}; + static Mesh *icons[11] = {nullptr}; if (icons[0] == nullptr) { icons[POINT] = new Mesh("mesh/point.ply"); icons[IMAGE] = new Mesh("mesh/icon_image.ply"); @@ -313,6 +302,8 @@ Symbol::Symbol(Type t, glm::vec3 pos) : Node(), type_(t) icons[RENDER] = new Mesh("mesh/icon_render.ply"); icons[DOTS] = new Mesh("mesh/icon_dots.ply"); icons[CIRCLES] = new Mesh("mesh/icon_circles.ply"); + icons[LOCK] = new Mesh("mesh/icon_lock.ply"); + icons[UNLOCK] = new Mesh("mesh/icon_unlock.ply"); icons[EMPTY] = new Mesh("mesh/icon_empty.ply"); } diff --git a/Decorations.h b/Decorations.h index b89bedd..c99c2aa 100644 --- a/Decorations.h +++ b/Decorations.h @@ -36,7 +36,7 @@ protected: class Handles : public Node { public: - typedef enum { RESIZE = 0, RESIZE_H, RESIZE_V, ROTATE } Type; + typedef enum { RESIZE = 0, RESIZE_H, RESIZE_V, ROTATE, SCALE } Type; Handles(Type type); ~Handles(); @@ -57,7 +57,7 @@ protected: class Symbol : public Node { public: - typedef enum { POINT = 0, IMAGE, VIDEO, SESSION, CLONE, RENDER, DOTS, CIRCLES, EMPTY } Type; + typedef enum { POINT = 0, IMAGE, VIDEO, SESSION, CLONE, RENDER, DOTS, CIRCLES, LOCK, UNLOCK, EMPTY } Type; Symbol(Type t = POINT, glm::vec3 pos = glm::vec3(0.f)); ~Symbol(); diff --git a/PickingVisitor.cpp b/PickingVisitor.cpp index 26b2c57..415f162 100644 --- a/PickingVisitor.cpp +++ b/PickingVisitor.cpp @@ -149,6 +149,12 @@ void PickingVisitor::visit(Handles &n) float l = glm::length( glm::vec2(vec) ); picked = glm::length( glm::vec2( 1.f + l, 1.f + l) - glm::vec2(P) ) < 1.5f * scale; } + else if ( n.type() == Handles::SCALE ){ + // the icon for scaling is on the right bottom 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; + } if ( picked ) // add this to the nodes picked diff --git a/Source.cpp b/Source.cpp index 03fc0b7..0673aca 100644 --- a/Source.cpp +++ b/Source.cpp @@ -87,6 +87,11 @@ Source::Source() : initialized_(false), active_(true), need_update_(true) handle_[Handles::ROTATE]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); handle_[Handles::ROTATE]->translation_.z = 0.1; overlays_[View::GEOMETRY]->attach(handle_[Handles::ROTATE]); + handle_[Handles::SCALE] = new Handles(Handles::SCALE); + handle_[Handles::SCALE]->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 1.f); + handle_[Handles::SCALE]->translation_.z = 0.1; + overlays_[View::GEOMETRY]->attach(handle_[Handles::SCALE]); + frame = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE); frame->translation_.z = 0.1; frame->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 0.7f); diff --git a/Source.h b/Source.h index e1e5fd1..b839277 100644 --- a/Source.h +++ b/Source.h @@ -162,7 +162,7 @@ protected: // overlays and frames to be displayed on top of source std::map overlays_; std::map frames_; - Handles *handle_[4]; + Handles *handle_[5]; // update bool active_; diff --git a/View.cpp b/View.cpp index f101a6e..6a21b18 100644 --- a/View.cpp +++ b/View.cpp @@ -771,11 +771,6 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p // operation of scaling in corner reference frame glm::vec3 corner_scaling = glm::vec3(corner_to) / glm::vec3(corner_from); -// if (UserInterface::manager().shiftModifier()) { -// corner_scaling.x = float( int( corner_scaling.x * 10.f ) ) / 10.f; -// corner_scaling.y = float( int( corner_scaling.y * 10.f ) ) / 10.f; -// } - // convert source position in corner reference frame glm::vec4 center = scene_to_corner_transform * glm::vec4( s->stored_status_->translation_, 1.f); @@ -787,8 +782,8 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p sourceNode->scale_ = s->stored_status_->scale_ * source_scaling; // discretized scaling with SHIFT if (UserInterface::manager().shiftModifier()) { - sourceNode->scale_.x = float( int( sourceNode->scale_.x * 10.f ) ) / 10.f; - sourceNode->scale_.y = float( int( sourceNode->scale_.y * 10.f ) ) / 10.f; + sourceNode->scale_.x = ROUND(sourceNode->scale_.x, 10.f); + sourceNode->scale_.y = ROUND(sourceNode->scale_.y, 10.f); } } // normal resize: corner scale @@ -797,12 +792,10 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p sourceNode->scale_ = s->stored_status_->scale_ * corner_scaling; // discretized scaling with SHIFT if (UserInterface::manager().shiftModifier()) { - sourceNode->scale_.x = float( int( sourceNode->scale_.x * 10.f ) ) / 10.f; - sourceNode->scale_.y = float( int( sourceNode->scale_.y * 10.f ) ) / 10.f; - + sourceNode->scale_.x = ROUND(sourceNode->scale_.x, 10.f); + sourceNode->scale_.y = ROUND(sourceNode->scale_.y, 10.f); corner_scaling = sourceNode->scale_ / s->stored_status_->scale_; } - // transform source center (in corner reference frame) center = glm::scale(glm::identity(), corner_scaling) * center; // convert center back into scene reference frame @@ -824,19 +817,19 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p sourceNode->scale_ = s->stored_status_->scale_ * glm::vec3(source_scaling.x, 1.f, 1.f); // discretized scaling with SHIFT if (UserInterface::manager().shiftModifier()) - sourceNode->scale_.x = float( int( sourceNode->scale_.x * 10.f ) ) / 10.f; + sourceNode->scale_.x = ROUND(sourceNode->scale_.x, 10.f); } // normal resize: side scale else { + // HORIZONTAL only + corner_scaling = glm::vec3(corner_scaling.x, 1.f, 1.f); // scale node sourceNode->scale_ = s->stored_status_->scale_ * corner_scaling; // discretized scaling with SHIFT if (UserInterface::manager().shiftModifier()) { - sourceNode->scale_.x = float( int( sourceNode->scale_.x * 10.f ) ) / 10.f; + sourceNode->scale_.x = ROUND(sourceNode->scale_.x, 10.f); corner_scaling = sourceNode->scale_ / s->stored_status_->scale_; } - // HORIZONTAL only - corner_scaling = glm::vec3(corner_scaling.x, 1.f, 1.f); // transform source center (in corner reference frame) center = glm::scale(glm::identity(), corner_scaling) * center; // convert center back into scene reference frame @@ -857,19 +850,19 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p sourceNode->scale_ = s->stored_status_->scale_ * glm::vec3(1.f, source_scaling.y, 1.f); // discretized scaling with SHIFT if (UserInterface::manager().shiftModifier()) - sourceNode->scale_.y = float( int( sourceNode->scale_.y * 10.f ) ) / 10.f; + sourceNode->scale_.y = ROUND(sourceNode->scale_.y, 10.f); } // normal resize: side scale else { + // VERTICAL ONLY + corner_scaling = glm::vec3(1.f, corner_scaling.y, 1.f); // scale sourceNode->scale_ = s->stored_status_->scale_ * corner_scaling; // discretized scaling with SHIFT if (UserInterface::manager().shiftModifier()) { - sourceNode->scale_.y = float( int( sourceNode->scale_.y * 10.f ) ) / 10.f; + sourceNode->scale_.y = ROUND(sourceNode->scale_.y, 10.f); corner_scaling = sourceNode->scale_ / s->stored_status_->scale_; } - // VERTICAL ONLY - corner_scaling = glm::vec3(1.f, corner_scaling.y, 1.f); // transform source center (in corner reference frame) center = glm::scale(glm::identity(), corner_scaling) * center; // convert center back into scene reference frame @@ -882,9 +875,32 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p info << "Size " << std::fixed << std::setprecision(3) << sourceNode->scale_.x; info << " x " << sourceNode->scale_.y; } + // picking on the proportional scaling handle + else if ( pick.first == s->handle_[Handles::SCALE] ) { + // PROPORTIONAL ONLY + source_scaling = glm::vec3(source_scaling.x, source_scaling.x, 1.f); + sourceNode->scale_ = s->stored_status_->scale_ * source_scaling; + // discretized scaling with SHIFT + if (UserInterface::manager().shiftModifier()) { + sourceNode->scale_.x = ROUND(sourceNode->scale_.x, 10.f); + source_scaling.x = sourceNode->scale_.x / s->stored_status_->scale_.x; + + sourceNode->scale_.y = s->stored_status_->scale_.y * source_scaling.x; + } + // ALT resize : scaling original source proportion + if (UserInterface::manager().altModifier()) { + sourceNode->scale_.y = sourceNode->scale_.x ; + } + // show cursor depending on diagonal (corner picked) + ret.type = Cursor_ResizeNWSE; + info << "Size " << std::fixed << std::setprecision(3) << sourceNode->scale_.x; + info << " x " << sourceNode->scale_.y; + + } // picking on the rotating handle else if ( pick.first == s->handle_[Handles::ROTATE] ) { + // sourceNode->scale_ = s->stored_status_->scale_ * source_scaling; // rotation center to center of source glm::mat4 T = glm::translate(glm::identity(), s->stored_status_->translation_); @@ -892,10 +908,9 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p source_to = glm::inverse(T) * glm::vec4( scene_to, 1.f ); // angle float angle = glm::orientedAngle( glm::normalize(glm::vec2(source_from)), glm::normalize(glm::vec2(source_to))); - // apply rotation on Z axis sourceNode->rotation_ = s->stored_status_->rotation_ + glm::vec3(0.f, 0.f, angle); - + // discretized rotation with SHIFT int degrees = int( glm::degrees(sourceNode->rotation_.z) ); if (UserInterface::manager().shiftModifier()) { degrees = (degrees / 10) * 10; @@ -908,12 +923,11 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p // picking anywhere but on a handle: user wants to move the source else { sourceNode->translation_ = s->stored_status_->translation_ + scene_translation; - + // discretized translation with SHIFT if (UserInterface::manager().shiftModifier()) { - sourceNode->translation_.x = float( int( sourceNode->translation_.x * 10.f ) ) / 10.f; - sourceNode->translation_.y = float( int( sourceNode->translation_.y * 10.f ) ) / 10.f; + sourceNode->translation_.x = ROUND(sourceNode->translation_.x, 10.f); + sourceNode->translation_.y = ROUND(sourceNode->translation_.y, 10.f); } - // ALT: single axis movement if (UserInterface::manager().altModifier()) { glm::vec3 dif = s->stored_status_->translation_ - sourceNode->translation_; diff --git a/defines.h b/defines.h index 54750da..c4c2c75 100644 --- a/defines.h +++ b/defines.h @@ -21,6 +21,7 @@ #define LOG100(val) (50.0/log(10.0)*log((float)val + 1.0)) #define EXP100(val) (exp(log(10.0)/50.0*(float)(val))-1.0) #define EUCLIDEAN(P1, P2) sqrt((P1.x() - P2.x()) * (P1.x() - P2.x()) + (P1.y() - P2.y()) * (P1.y() - P2.y())) +#define ROUND(val, factor) float( int( val * factor ) ) / factor; #define SCENE_UNIT 5.f #define SCENE_DEPTH 12.f