diff --git a/ImGuiToolkit.cpp b/ImGuiToolkit.cpp index 1d42049..b3ff385 100644 --- a/ImGuiToolkit.cpp +++ b/ImGuiToolkit.cpp @@ -808,8 +808,8 @@ void ImGuiToolkit::ShowStats(bool *p_open, int* p_corner) if (p_open && ImGui::MenuItem("Close")) *p_open = false; ImGui::EndPopup(); } + ImGui::End(); } - ImGui::End(); } ImVec4 ImGuiToolkit::GetHighlightColor() diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 363d966..6c72092 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -77,10 +77,10 @@ void ImGuiVisitor::visit(Group &n) ImGui::SameLine(0, 10); float scale[2] = { n.scale_.x, n.scale_.y} ; ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if ( ImGui::SliderFloat2("Scale", scale, -5.0, 5.0, "%.2f") ) + if ( ImGui::SliderFloat2("Scale", scale, -MAX_SCALE, MAX_SCALE, "%.2f") ) { - n.scale_.x = scale[0]; - n.scale_.y = scale[1]; + n.scale_.x = CLAMP_SCALE(scale[0]); + n.scale_.y = CLAMP_SCALE(scale[1]); } // // loop over members of a group diff --git a/Source.cpp b/Source.cpp index 60e068f..f1b21cd 100644 --- a/Source.cpp +++ b/Source.cpp @@ -205,8 +205,14 @@ void Source::update(float dt) // MODIFY geometry based on GEOMETRY node groups_[View::RENDERING]->translation_ = groups_[View::GEOMETRY]->translation_; - groups_[View::RENDERING]->scale_ = groups_[View::GEOMETRY]->scale_; groups_[View::RENDERING]->rotation_ = groups_[View::GEOMETRY]->rotation_; + // avoid any null scale + glm::vec3 s = groups_[View::GEOMETRY]->scale_; + s.x = CLAMP_SCALE(s.x); + s.y = CLAMP_SCALE(s.y); + s.z = 1.f; + groups_[View::GEOMETRY]->scale_ = s; + groups_[View::RENDERING]->scale_ = s; // MODIFY depth based on LAYER node groups_[View::MIXING]->translation_.z = groups_[View::LAYER]->translation_.z; diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index b3f162d..58b1571 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -330,9 +330,9 @@ void UserInterface::handleMouse() if ( ImGui::IsMouseDragging(ImGuiMouseButton_Right, 10.0f) ) { // right mouse drag => drag current view - int c = Mixer::manager().currentView()->drag( mouseclic[ImGuiMouseButton_Right], mousepos); + View::Cursor c = Mixer::manager().currentView()->drag( mouseclic[ImGuiMouseButton_Right], mousepos); - ImGui::SetMouseCursor(c); + ImGui::SetMouseCursor(c.type); } else { ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow); @@ -355,8 +355,21 @@ void UserInterface::handleMouse() if (current) { // grab current source - int c = Mixer::manager().currentView()->grab( mouseclic[ImGuiMouseButton_Left], mousepos, current, picked); - ImGui::SetMouseCursor(c); + View::Cursor c = Mixer::manager().currentView()->grab( mouseclic[ImGuiMouseButton_Left], mousepos, current, picked); + + ImGui::SetMouseCursor(c.type); + + float d = 0.5f * ImGui::GetFrameHeight() ; + ImVec2 window_pos = ImVec2( mousepos.x - d, mousepos.y - d ); + ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always); + ImGui::SetNextWindowBgAlpha(0.45f); // Transparent background + if (ImGui::Begin("MouseInfoContext", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_MONO); + ImGui::Text(" %s", c.info.c_str()); + ImGui::PopFont(); + ImGui::End(); + } } else { // Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y); diff --git a/View.cpp b/View.cpp index 868194b..873a5b5 100644 --- a/View.cpp +++ b/View.cpp @@ -6,6 +6,8 @@ // memmove #include +#include +#include #include "defines.h" #include "Settings.h" @@ -76,7 +78,7 @@ View::Cursor View::drag (glm::vec2 from, glm::vec2 to) // compute delta translation scene.root()->translation_ = start_translation + gl_Position_to - gl_Position_from; - return Cursor_ResizeAll; + return Cursor(Cursor_ResizeAll); } std::pair View::pick(glm::vec3 point) @@ -133,7 +135,7 @@ void MixingView::zoom( float factor ) View::Cursor MixingView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair) { if (!s) - return Cursor_Arrow; + return Cursor(); Group *sourceNode = s->group(mode_); @@ -155,7 +157,9 @@ View::Cursor MixingView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pai // request update s->touch(); - return Cursor_ResizeAll; + std::ostringstream info; + info << "Alpha " << std::fixed << std::setprecision(3) << s->blendingShader()->color.a; + return Cursor(Cursor_ResizeAll, info.str() ); } uint MixingView::textureMixingQuadratic() @@ -344,7 +348,9 @@ std::pair GeometryView::pick(glm::vec3 point) View::Cursor GeometryView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair pick) { - View::Cursor ret = Cursor_Arrow; + View::Cursor ret = Cursor(); + + std::ostringstream info; // work on the given source if (!s) @@ -396,42 +402,70 @@ View::Cursor GeometryView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::p // select cursor depending on diagonal glm::vec2 axis = glm::sign(pick.second); - ret = axis.x * axis.y > 0.f ? Cursor_ResizeNESW : Cursor_ResizeNWSE; + ret.type = axis.x * axis.y > 0.f ? Cursor_ResizeNESW : Cursor_ResizeNWSE; + info << "Size " << std::fixed << std::setprecision(3) << sourceNode->scale_.x; + info << " x " << sourceNode->scale_.y; } // picking on the resizing handles left or right else if ( pick.first == s->resize_H_handle_ ) { sourceNode->scale_ = start_scale * glm::vec3(S_resize.x, 1.f, 1.f); - ret = Cursor_ResizeEW; + if (UserInterface::manager().keyboardModifier()) + sourceNode->scale_.x = float( int( sourceNode->scale_.x * 10.f ) ) / 10.f; + + ret.type = Cursor_ResizeEW; + info << "Size " << std::fixed << std::setprecision(3) << sourceNode->scale_.x; + info << " x " << sourceNode->scale_.y; } // picking on the resizing handles top or bottom else if ( pick.first == s->resize_V_handle_ ) { sourceNode->scale_ = start_scale * glm::vec3(1.f, S_resize.y, 1.f); - ret = Cursor_ResizeNS; + if (UserInterface::manager().keyboardModifier()) + sourceNode->scale_.y = float( int( sourceNode->scale_.y * 10.f ) ) / 10.f; + + ret.type = Cursor_ResizeNS; + 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->rotate_handle_ ) { float angle = glm::orientedAngle( glm::normalize(glm::vec2(S_from)), glm::normalize(glm::vec2(S_to))); - - if (UserInterface::manager().keyboardModifier()) - angle = float ( int(angle * 30.f) ) / 30.f; sourceNode->rotation_ = start_rotation + glm::vec3(0.f, 0.f, angle); - ret = Cursor_Hand; + + int degrees = int( glm::degrees(sourceNode->rotation_.z) ); + if (UserInterface::manager().keyboardModifier()) { + degrees = (degrees / 10) * 10; + sourceNode->rotation_.z = glm::radians( float(degrees) ); + } + + ret.type = Cursor_Hand; + info << "Angle " << degrees << "\u00b0"; // degree symbol } // picking anywhere but on a handle: user wants to move the source else { sourceNode->translation_ = start_translation + gl_Position_to - gl_Position_from; - ret = Cursor_ResizeAll; + + if (UserInterface::manager().keyboardModifier()) { + sourceNode->translation_.x = float( int( sourceNode->translation_.x * 10.f ) ) / 10.f; + sourceNode->translation_.y = float( int( sourceNode->translation_.y * 10.f ) ) / 10.f; + } + + ret.type = Cursor_ResizeAll; + info << "Position (" << std::fixed << std::setprecision(3) << sourceNode->translation_.x; + info << ", " << sourceNode->translation_.y << ")"; } } // don't have a handle, we can only move the source else { sourceNode->translation_ = start_translation + gl_Position_to - gl_Position_from; - ret = Cursor_ResizeAll; + ret.type = Cursor_ResizeAll; + info << "Position (" << std::fixed << std::setprecision(3) << sourceNode->translation_.x; + info << ", " << sourceNode->translation_.y << ")"; } // request update s->touch(); + ret.info = info.str(); return ret; } @@ -497,10 +531,10 @@ void LayerView::zoom (float factor) } -void LayerView::setDepth (Source *s, float d) +float LayerView::setDepth(Source *s, float d) { if (!s) - return; + return -1.f; float depth = d; @@ -528,12 +562,14 @@ void LayerView::setDepth (Source *s, float d) // request reordering View::need_deep_update_ = true; + + return sourceNode->translation_.z; } View::Cursor LayerView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair pick) { if (!s) - return Cursor_Arrow; + return Cursor(); static glm::vec3 start_translation = glm::vec3(0.f); static glm::vec2 start_position = glm::vec2(0.f); @@ -551,8 +587,10 @@ View::Cursor LayerView::grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair glm::vec3 dest_translation = start_translation + gl_Position_to - gl_Position_from; // apply change - setDepth( s, MAX( -dest_translation.x, 0.f) ); + float d = setDepth( s, MAX( -dest_translation.x, 0.f) ); - return Cursor_ResizeAll; + std::ostringstream info; + info << "Depth " << std::fixed << std::setprecision(2) << d; + return Cursor(Cursor_ResizeAll, info.str() ); } diff --git a/View.h b/View.h index 2b51b70..9a51146 100644 --- a/View.h +++ b/View.h @@ -32,15 +32,22 @@ public: Cursor_ResizeNWSE, Cursor_Hand, Cursor_NotAllowed + } CursorType; + + typedef struct Cursor { + CursorType type; + std::string info; + Cursor() { type = Cursor_Arrow; info = "";} + Cursor(CursorType t, std::string i = "") { type = t; info = i;} } Cursor; virtual std::pair pick(glm::vec3 point); virtual Cursor drag (glm::vec2, glm::vec2); virtual Cursor grab (glm::vec2, glm::vec2, Source*, std::pair) { - return Cursor_Arrow; + return Cursor(); } virtual Cursor over (glm::vec2, Source*, std::pair) { - return Cursor_Arrow; + return Cursor(); } virtual void restoreSettings(); @@ -107,7 +114,7 @@ public: void zoom (float factor) override; Cursor grab (glm::vec2 from, glm::vec2 to, Source *s, std::pair pick) override; - void setDepth (Source *, float d = -1.f); + float setDepth (Source *, float d = -1.f); private: float aspect_ratio; diff --git a/defines.h b/defines.h index 95f6bcc..ec667bc 100644 --- a/defines.h +++ b/defines.h @@ -25,6 +25,9 @@ #define SCENE_UNIT 5.f #define SCENE_DEPTH 12.f #define CIRCLE_SQUARE_DIST(x,y) ( (x*x + y*y) / (SCENE_UNIT * SCENE_UNIT * SCENE_UNIT * SCENE_UNIT) ) +#define MIN_SCALE 0.01f +#define MAX_SCALE 10.f +#define CLAMP_SCALE(x) SIGN(x) * CLAMP( ABS(x), MIN_SCALE, MAX_SCALE) #define IMGUI_TITLE_MAINWINDOW ICON_FA_CIRCLE_NOTCH " vimix" #define IMGUI_TITLE_MEDIAPLAYER ICON_FA_FILM " Media Player" @@ -58,8 +61,6 @@ #define MAX_ICON_SIZE 2.5 #define MIN_DEPTH_LAYER 0.0 #define MAX_DEPTH_LAYER 40.0 -#define MIN_SCALE 0.1 -#define MAX_SCALE 200.0 #define DEPTH_EPSILON 0.1 #define DEPTH_DEFAULT_SPACING 1.0 #define BORDER_SIZE 0.4