From 262c6fd8aba9ce28a11b5eff59fe12c60b6c2644 Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Sun, 27 Aug 2023 17:49:46 +0200 Subject: [PATCH] New ALT key selects alternative mouse Pointer Maintain ALT to activate the selected mouse Pointer. Also possible to ALT LOCK for maintaining the cursor. Local popup window allows selecting. Changed the View options selection to match this popup approach. --- src/DrawVisitor.cpp | 38 +++++---- src/DrawVisitor.h | 22 ++++- src/GeometryView.cpp | 135 +++++++++++++++++++------------ src/LayerView.cpp | 92 ++++++++++----------- src/MixingView.cpp | 128 +++++++++++++++++------------ src/Settings.cpp | 2 + src/Settings.h | 4 +- src/TextureView.cpp | 110 ++++++++++++------------- src/UserInterfaceManager.cpp | 151 ++++++++++++++++++++++++----------- src/UserInterfaceManager.h | 2 +- src/defines.h | 2 +- 11 files changed, 416 insertions(+), 270 deletions(-) diff --git a/src/DrawVisitor.cpp b/src/DrawVisitor.cpp index 6009e4b..794200c 100644 --- a/src/DrawVisitor.cpp +++ b/src/DrawVisitor.cpp @@ -116,20 +116,6 @@ void DrawVisitor::visit(Switch &n) modelview_ = mv; } -void DrawVisitor::visit(Primitive &) -{ -} - - - -ColorVisitor::ColorVisitor(glm::vec4 color): color_(color) -{ - -} -void ColorVisitor::visit(Node &) -{ -} - void ColorVisitor::visit(Group &n) { // traverse children @@ -180,6 +166,30 @@ void ColorVisitor::visit(Character &d) d.color = color_; } +void VisibleVisitor::visit(Node &n) +{ + n.visible_ = visible_; +} + +void VisibleVisitor::visit(Group &n) +{ + // traverse children + for (NodeSet::iterator node = n.begin(); node != n.end(); ++node) { + (*node)->accept(*this); + } +} + +void VisibleVisitor::visit(Scene &n) +{ + n.root()->accept(*this); +} + +void VisibleVisitor::visit(Switch &n) +{ + for (uint c = 0; c < n.numChildren(); ++c) { + n.child(c)->accept(*this); + } +} diff --git a/src/DrawVisitor.h b/src/DrawVisitor.h index b9c5b26..fc8cb47 100644 --- a/src/DrawVisitor.h +++ b/src/DrawVisitor.h @@ -28,9 +28,9 @@ public: void visit(Scene& n) override; void visit(Node& n) override; - void visit(Primitive& ) override; void visit(Group& n) override; void visit(Switch& n) override; + void visit(Primitive& ) override {} }; @@ -44,10 +44,10 @@ class ColorVisitor : public Visitor glm::vec4 color_; public: - ColorVisitor(glm::vec4 color); + ColorVisitor(glm::vec4 color) : color_(color) {} + void visit(Node&) override {} void visit(Scene& n) override; - void visit(Node& n) override; void visit(Group& n) override; void visit(Switch& n) override; @@ -59,5 +59,21 @@ public: void visit(Character& ) override; }; +/// +/// \brief The VisibleVisitor changes the visible flag of +/// all nodes to the given value +/// +class VisibleVisitor : public Visitor +{ + bool visible_; + +public: + VisibleVisitor(bool visible) : visible_(visible) {} + + void visit(Scene& n) override; + void visit(Node& n) override; + void visit(Group& n) override; + void visit(Switch& n) override; +}; #endif // DRAWVISITOR_H diff --git a/src/GeometryView.cpp b/src/GeometryView.cpp index 13969fa..8ed7e6e 100644 --- a/src/GeometryView.cpp +++ b/src/GeometryView.cpp @@ -1238,7 +1238,6 @@ void GeometryView::terminate(bool force) (*sit)->handles_[mode_][Handles::ROTATE]->visible_ = true; (*sit)->handles_[mode_][Handles::CROP]->visible_ = true; (*sit)->handles_[mode_][Handles::MENU]->visible_ = true; - } overlay_selection_active_ = false; @@ -1250,70 +1249,100 @@ void GeometryView::terminate(bool force) void GeometryView::arrow (glm::vec2 movement) { static float accumulator = 0.f; - accumulator += dt_; + accumulator += dt_ * 0.2f; - glm::vec3 gl_Position_from = Rendering::manager().unProject(glm::vec2(0.f), scene.root()->transform_); - glm::vec3 gl_Position_to = Rendering::manager().unProject(movement, scene.root()->transform_); - glm::vec3 gl_delta = gl_Position_to - gl_Position_from; + Source *current = Mixer::manager().currentSource(); - bool first = true; - glm::vec3 delta_translation(0.f); - for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); ++it) { + if (!current && !Mixer::selection().empty()) + Mixer::manager().setCurrentSource( Mixer::selection().back() ); + if (current) { - Group *sourceNode = (*it)->group(mode_); - glm::vec3 dest_translation(0.f); + if (current_action_ongoing_) { - if (first) { - // dest starts at current - dest_translation = sourceNode->translation_; + glm::vec2 Position_from = glm::vec2( Rendering::manager().project(current->stored_status_->translation_, scene.root()->transform_) ); + glm::vec2 Position_to = Position_from + movement * accumulator; - // + ALT : discrete displacement - if (UserInterface::manager().altModifier()) { - if (accumulator > 100.f) { - // precise movement with SHIFT - if ( UserInterface::manager().shiftModifier() ) { - dest_translation += glm::sign(gl_delta) * 0.0011f; - dest_translation.x = ROUND(dest_translation.x, 1000.f); - dest_translation.y = ROUND(dest_translation.y, 1000.f); - } - else { - dest_translation += glm::sign(gl_delta) * 0.11f; - dest_translation.x = ROUND(dest_translation.x, 10.f); - dest_translation.y = ROUND(dest_translation.y, 10.f); - } - accumulator = 0.f; - } - else - break; - } - else - { - // normal case: dest += delta - dest_translation += gl_delta * ARROWS_MOVEMENT_FACTOR * dt_; - accumulator = 0.f; - } + grab(current, Position_from, Position_to, std::make_pair(current->group(mode_), glm::vec2(0.f) ) ); - // store action in history - std::ostringstream info; - info << "Position " << std::fixed << std::setprecision(3) << sourceNode->translation_.x; - info << ", " << sourceNode->translation_.y ; - current_action_ = (*it)->name() + ": " + info.str(); - - // delta for others to follow - delta_translation = dest_translation - sourceNode->translation_; } else { - // dest = current + delta from first - dest_translation = sourceNode->translation_ + delta_translation; + + initiate(); + accumulator = 0.f; + + adaptGridToSource(current); + } - // apply & request update - sourceNode->translation_ = dest_translation; - (*it)->touch(); - - first = false; } + else + terminate(true); + + + +// glm::vec3 gl_Position_from = Rendering::manager().unProject(glm::vec2(0.f), scene.root()->transform_); +// glm::vec3 gl_Position_to = Rendering::manager().unProject(movement, scene.root()->transform_); +// glm::vec3 gl_delta = gl_Position_to - gl_Position_from; + +// bool first = true; +// glm::vec3 delta_translation(0.f); +// for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); ++it) { + + +// Group *sourceNode = (*it)->group(mode_); +// glm::vec3 dest_translation(0.f); + +// if (first) { +// // dest starts at current +// dest_translation = sourceNode->translation_; + +// // + ALT : discrete displacement +// if (UserInterface::manager().altModifier()) { +// if (accumulator > 100.f) { +// // precise movement with SHIFT +// if ( UserInterface::manager().shiftModifier() ) { +// dest_translation += glm::sign(gl_delta) * 0.0011f; +// dest_translation.x = ROUND(dest_translation.x, 1000.f); +// dest_translation.y = ROUND(dest_translation.y, 1000.f); +// } +// else { +// dest_translation += glm::sign(gl_delta) * 0.11f; +// dest_translation.x = ROUND(dest_translation.x, 10.f); +// dest_translation.y = ROUND(dest_translation.y, 10.f); +// } +// accumulator = 0.f; +// } +// else +// break; +// } +// else +// { +// // normal case: dest += delta +// dest_translation += gl_delta * ARROWS_MOVEMENT_FACTOR * dt_; +// accumulator = 0.f; +// } + +// // store action in history +// std::ostringstream info; +// info << "Position " << std::fixed << std::setprecision(3) << sourceNode->translation_.x; +// info << ", " << sourceNode->translation_.y ; +// current_action_ = (*it)->name() + ": " + info.str(); + +// // delta for others to follow +// delta_translation = dest_translation - sourceNode->translation_; +// } +// else { +// // dest = current + delta from first +// dest_translation = sourceNode->translation_ + delta_translation; +// } + +// // apply & request update +// sourceNode->translation_ = dest_translation; +// (*it)->touch(); + +// first = false; +// } } void GeometryView::updateSelectionOverlay(glm::vec4 color) diff --git a/src/LayerView.cpp b/src/LayerView.cpp index cc11a73..2d9fb68 100644 --- a/src/LayerView.cpp +++ b/src/LayerView.cpp @@ -386,62 +386,62 @@ View::Cursor LayerView::over (glm::vec2 pos) void LayerView::arrow (glm::vec2 movement) { - static float accumulator = 0.f; - accumulator += dt_; +// static float accumulator = 0.f; +// accumulator += dt_; - glm::vec3 gl_Position_from = Rendering::manager().unProject(glm::vec2(0.f), scene.root()->transform_); - glm::vec3 gl_Position_to = Rendering::manager().unProject(glm::vec2(movement.x-movement.y, 0.f), scene.root()->transform_); - glm::vec3 gl_delta = gl_Position_to - gl_Position_from; +// glm::vec3 gl_Position_from = Rendering::manager().unProject(glm::vec2(0.f), scene.root()->transform_); +// glm::vec3 gl_Position_to = Rendering::manager().unProject(glm::vec2(movement.x-movement.y, 0.f), scene.root()->transform_); +// glm::vec3 gl_delta = gl_Position_to - gl_Position_from; - bool first = true; - glm::vec3 delta_translation(0.f); - for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); it++) { +// bool first = true; +// glm::vec3 delta_translation(0.f); +// for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); it++) { - // individual move with SHIFT - if ( !Source::isCurrent(*it) && UserInterface::manager().shiftModifier() ) - continue; +// // individual move with SHIFT +// if ( !Source::isCurrent(*it) && UserInterface::manager().shiftModifier() ) +// continue; - Group *sourceNode = (*it)->group(mode_); - glm::vec3 dest_translation(0.f); +// Group *sourceNode = (*it)->group(mode_); +// glm::vec3 dest_translation(0.f); - if (first) { - // dest starts at current - dest_translation = sourceNode->translation_; +// if (first) { +// // dest starts at current +// dest_translation = sourceNode->translation_; - // + ALT : discrete displacement - if (UserInterface::manager().altModifier()) { - if (accumulator > 100.f) { - dest_translation += glm::sign(gl_delta) * 0.21f; - dest_translation.x = ROUND(dest_translation.x, 10.f); - accumulator = 0.f; - } - else - break; - } - else { - // normal case: dest += delta - dest_translation += gl_delta * ARROWS_MOVEMENT_FACTOR * dt_; - accumulator = 0.f; - } +// // + ALT : discrete displacement +// if (UserInterface::manager().altModifier()) { +// if (accumulator > 100.f) { +// dest_translation += glm::sign(gl_delta) * 0.21f; +// dest_translation.x = ROUND(dest_translation.x, 10.f); +// accumulator = 0.f; +// } +// else +// break; +// } +// else { +// // normal case: dest += delta +// dest_translation += gl_delta * ARROWS_MOVEMENT_FACTOR * dt_; +// accumulator = 0.f; +// } - // store action in history - std::ostringstream info; - info << "Depth " << std::fixed << std::setprecision(2) << (*it)->depth() << " "; - current_action_ = (*it)->name() + ": " + info.str(); +// // store action in history +// std::ostringstream info; +// info << "Depth " << std::fixed << std::setprecision(2) << (*it)->depth() << " "; +// current_action_ = (*it)->name() + ": " + info.str(); - // delta for others to follow - delta_translation = dest_translation - sourceNode->translation_; - } - else { - // dest = current + delta from first - dest_translation = sourceNode->translation_ + delta_translation; - } +// // delta for others to follow +// delta_translation = dest_translation - sourceNode->translation_; +// } +// else { +// // dest = current + delta from first +// dest_translation = sourceNode->translation_ + delta_translation; +// } - // apply & request update - setDepth( *it, MAX( -dest_translation.x, 0.f) ); +// // apply & request update +// setDepth( *it, MAX( -dest_translation.x, 0.f) ); - first = false; - } +// first = false; +// } } diff --git a/src/MixingView.cpp b/src/MixingView.cpp index 516db83..639638b 100644 --- a/src/MixingView.cpp +++ b/src/MixingView.cpp @@ -683,68 +683,98 @@ View::Cursor MixingView::over (glm::vec2 pos) void MixingView::arrow (glm::vec2 movement) { static float accumulator = 0.f; - accumulator += dt_; + accumulator += dt_ * 0.2; + Source *current = Mixer::manager().currentSource(); - glm::vec3 gl_Position_from = Rendering::manager().unProject(glm::vec2(0.f), scene.root()->transform_); - glm::vec3 gl_Position_to = Rendering::manager().unProject(movement, scene.root()->transform_); - glm::vec3 gl_delta = gl_Position_to - gl_Position_from; + if (!current && !Mixer::selection().empty()) + Mixer::manager().setCurrentSource( Mixer::selection().back() ); - bool first = true; - glm::vec3 delta_translation(0.f); - for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); ++it) { + if (current) { - // individual move with SHIFT - if ( !Source::isCurrent(*it) && UserInterface::manager().shiftModifier() ) - continue; + if (current_action_ongoing_) { - Group *sourceNode = (*it)->group(mode_); - glm::vec3 dest_translation(0.f); + glm::vec2 Position_from = glm::vec2( Rendering::manager().project(current->stored_status_->translation_, scene.root()->transform_) ); + glm::vec2 Position_to = Position_from + movement * accumulator; - if (first) { - // dest starts at current - dest_translation = sourceNode->translation_; + if ( current->mixinggroup_ != nullptr ) + current->mixinggroup_->setAction( MixingGroup::ACTION_GRAB_ALL ); - // + ALT : discrete displacement - if (UserInterface::manager().altModifier()) { - if (accumulator > 100.f) { - dest_translation += glm::sign(gl_delta) * 0.1f; - dest_translation.x = ROUND(dest_translation.x, 10.f); - dest_translation.y = ROUND(dest_translation.y, 10.f); - accumulator = 0.f; - } - else - break; - } - else { - // normal case: dest += delta - dest_translation += gl_delta * ARROWS_MOVEMENT_FACTOR * dt_; - accumulator = 0.f; - } + grab(current, Position_from, Position_to, std::make_pair(current->group(mode_), glm::vec2(0.f) ) ); - // store action in history - std::ostringstream info; - if ((*it)->active()) { - info << "Alpha " << std::fixed << std::setprecision(3) << (*it)->blendingShader()->color.a << " "; - info << ( ((*it)->blendingShader()->color.a > 0.f) ? ICON_FA_EYE : ICON_FA_EYE_SLASH); - } - else - info << "Inactive " << ICON_FA_SNOWFLAKE; - current_action_ = (*it)->name() + ": " + info.str(); - - // delta for others to follow - delta_translation = dest_translation - sourceNode->translation_; } else { - // dest = current + delta from first - dest_translation = sourceNode->translation_ + delta_translation; + + initiate(); + accumulator = 0.f; } - // apply & request update - sourceNode->translation_ = dest_translation; - (*it)->touch(); - first = false; } + else + terminate(true); + + + // glm::vec3 gl_Position_from = Rendering::manager().unProject(glm::vec2(0.f), scene.root()->transform_); + // glm::vec3 gl_Position_to = Rendering::manager().unProject(movement, scene.root()->transform_); + // glm::vec3 gl_delta = gl_Position_to - gl_Position_from; + + +// bool first = true; +// glm::vec3 delta_translation(0.f); +// for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); ++it) { + +// // individual move with SHIFT +// if ( !Source::isCurrent(*it) && UserInterface::manager().shiftModifier() ) +// continue; + +// Group *sourceNode = (*it)->group(mode_); +// glm::vec3 dest_translation(0.f); + +// if (first) { +// // dest starts at current +// dest_translation = sourceNode->translation_; + +// // + ALT : discrete displacement +// if (UserInterface::manager().altModifier()) { +// if (accumulator > 100.f) { +// dest_translation += glm::sign(gl_delta) * 0.1f; +// dest_translation.x = ROUND(dest_translation.x, 10.f); +// dest_translation.y = ROUND(dest_translation.y, 10.f); +// accumulator = 0.f; +// } +// else +// break; +// } +// else { +// // normal case: dest += delta +// dest_translation += gl_delta * ARROWS_MOVEMENT_FACTOR * dt_; +// accumulator = 0.f; +// } + +// // store action in history +// std::ostringstream info; +// if ((*it)->active()) { +// info << "Alpha " << std::fixed << std::setprecision(3) << (*it)->blendingShader()->color.a << " "; +// info << ( ((*it)->blendingShader()->color.a > 0.f) ? ICON_FA_EYE : ICON_FA_EYE_SLASH); +// } +// else +// info << "Inactive " << ICON_FA_SNOWFLAKE; +// current_action_ = (*it)->name() + ": " + info.str(); + +// // delta for others to follow +// delta_translation = dest_translation - sourceNode->translation_; +// } +// else { +// // dest = current + delta from first +// dest_translation = sourceNode->translation_ + delta_translation; +// } + +// // apply & request update +// sourceNode->translation_ = dest_translation; +// (*it)->touch(); + +// first = false; +// } } diff --git a/src/Settings.cpp b/src/Settings.cpp index f4b8202..5a0cc60 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -216,6 +216,7 @@ void Settings::Save(uint64_t runtime) // Pointer XMLElement *PointerNode = xmlDoc.NewElement( "MousePointer" ); PointerNode->SetAttribute("mode", application.mouse_pointer); + PointerNode->SetAttribute("lock", application.mouse_pointer_lock); PointerNode->SetAttribute("proportional_grid", application.proportional_grid); for (size_t i = 0; i < application.mouse_pointer_strength.size(); ++i ) { float v = application.mouse_pointer_strength[i]; @@ -566,6 +567,7 @@ void Settings::Load() XMLElement * pointernode = pRoot->FirstChildElement("MousePointer"); if (pointernode != nullptr) { pointernode->QueryIntAttribute("mode", &application.mouse_pointer); + pointernode->QueryBoolAttribute("lock", &application.mouse_pointer_lock); pointernode->QueryBoolAttribute("proportional_grid", &application.proportional_grid); XMLElement* strengthNode = pointernode->FirstChildElement("vec2"); diff --git a/src/Settings.h b/src/Settings.h index 250af98..dabd168 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -273,6 +273,7 @@ struct Application bool smooth_transition; bool proportional_grid; int mouse_pointer; + bool mouse_pointer_lock; std::vector mouse_pointer_strength; bool action_history_follow_view; bool show_tooptips; @@ -339,7 +340,8 @@ struct Application smooth_transition = false; save_version_snapshot = false; proportional_grid = true; - mouse_pointer = 0; + mouse_pointer = 1; + mouse_pointer_lock = false; mouse_pointer_strength = {0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; action_history_follow_view = false; show_tooptips = true; diff --git a/src/TextureView.cpp b/src/TextureView.cpp index 9345165..85036e7 100644 --- a/src/TextureView.cpp +++ b/src/TextureView.cpp @@ -1533,63 +1533,63 @@ void TextureView::terminate(bool force) void TextureView::arrow (glm::vec2 movement) { - Source *s = Mixer::manager().currentSource(); - if (s) { - static float accumulator = 0.f; - accumulator += dt_; +// Source *s = Mixer::manager().currentSource(); +// if (s) { +// static float accumulator = 0.f; +// accumulator += dt_; - glm::vec3 gl_Position_from = Rendering::manager().unProject(glm::vec2(0.f), scene.root()->transform_); - glm::vec3 gl_Position_to = Rendering::manager().unProject(movement, scene.root()->transform_); - glm::vec3 gl_delta = gl_Position_to - gl_Position_from; +// glm::vec3 gl_Position_from = Rendering::manager().unProject(glm::vec2(0.f), scene.root()->transform_); +// glm::vec3 gl_Position_to = Rendering::manager().unProject(movement, scene.root()->transform_); +// glm::vec3 gl_delta = gl_Position_to - gl_Position_from; - Group *sourceNode = s->group(mode_); - glm::vec3 alt_move_ = sourceNode->translation_; - if (UserInterface::manager().altModifier()) { - if (accumulator > 100.f) - { - // precise movement with SHIFT - if ( UserInterface::manager().shiftModifier() ) { - alt_move_ += glm::sign(gl_delta) * 0.0011f; - sourceNode->translation_.x = ROUND(alt_move_.x, 1000.f); - sourceNode->translation_.y = ROUND(alt_move_.y, 1000.f); - } - else { - alt_move_ += glm::sign(gl_delta) * 0.11f; - sourceNode->translation_.x = ROUND(alt_move_.x, 10.f); - sourceNode->translation_.y = ROUND(alt_move_.y, 10.f); - } - accumulator = 0.f; - } - } - else { - sourceNode->translation_ += gl_delta * ARROWS_MOVEMENT_FACTOR * dt_; - accumulator = 0.f; - alt_move_ = sourceNode->translation_; - } +// Group *sourceNode = s->group(mode_); +// glm::vec3 alt_move_ = sourceNode->translation_; +// if (UserInterface::manager().altModifier()) { +// if (accumulator > 100.f) +// { +// // precise movement with SHIFT +// if ( UserInterface::manager().shiftModifier() ) { +// alt_move_ += glm::sign(gl_delta) * 0.0011f; +// sourceNode->translation_.x = ROUND(alt_move_.x, 1000.f); +// sourceNode->translation_.y = ROUND(alt_move_.y, 1000.f); +// } +// else { +// alt_move_ += glm::sign(gl_delta) * 0.11f; +// sourceNode->translation_.x = ROUND(alt_move_.x, 10.f); +// sourceNode->translation_.y = ROUND(alt_move_.y, 10.f); +// } +// accumulator = 0.f; +// } +// } +// else { +// sourceNode->translation_ += gl_delta * ARROWS_MOVEMENT_FACTOR * dt_; +// accumulator = 0.f; +// alt_move_ = sourceNode->translation_; +// } - // store action in history - std::ostringstream info; - info << "Texture Shift " << std::fixed << std::setprecision(3) << sourceNode->translation_.x; - info << ", " << sourceNode->translation_.y ; - current_action_ = s->name() + ": " + info.str(); +// // store action in history +// std::ostringstream info; +// info << "Texture Shift " << std::fixed << std::setprecision(3) << sourceNode->translation_.x; +// info << ", " << sourceNode->translation_.y ; +// current_action_ = s->name() + ": " + info.str(); - // request update - s->touch(); - } - else if (edit_source_) { - if (edit_source_->maskShader()->mode == MaskShader::PAINT) { - if (mask_cursor_paint_ > 0) { - glm::vec2 b = 0.02f * movement; - Settings::application.brush.x = CLAMP(Settings::application.brush.x+b.x, BRUSH_MIN_SIZE, BRUSH_MAX_SIZE); - Settings::application.brush.y = CLAMP(Settings::application.brush.y+b.y, BRUSH_MIN_PRESS, BRUSH_MAX_PRESS); - } - } - else if (edit_source_->maskShader()->mode == MaskShader::SHAPE) { - if (mask_cursor_shape_ > 0) { - float b = -0.02f * movement.y; - edit_source_->maskShader()->blur = CLAMP(edit_source_->maskShader()->blur+b, SHAPE_MIN_BLUR, SHAPE_MAX_BLUR); - edit_source_->touch(Source::SourceUpdate_Mask); - } - } - } +// // request update +// s->touch(); +// } +// else if (edit_source_) { +// if (edit_source_->maskShader()->mode == MaskShader::PAINT) { +// if (mask_cursor_paint_ > 0) { +// glm::vec2 b = 0.02f * movement; +// Settings::application.brush.x = CLAMP(Settings::application.brush.x+b.x, BRUSH_MIN_SIZE, BRUSH_MAX_SIZE); +// Settings::application.brush.y = CLAMP(Settings::application.brush.y+b.y, BRUSH_MIN_PRESS, BRUSH_MAX_PRESS); +// } +// } +// else if (edit_source_->maskShader()->mode == MaskShader::SHAPE) { +// if (mask_cursor_shape_ > 0) { +// float b = -0.02f * movement.y; +// edit_source_->maskShader()->blur = CLAMP(edit_source_->maskShader()->blur+b, SHAPE_MIN_BLUR, SHAPE_MAX_BLUR); +// edit_source_->touch(Source::SourceUpdate_Mask); +// } +// } +// } } diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index 77dcadd..3405e25 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -310,8 +310,8 @@ void UserInterface::handleKeyboard() Mixer::manager().view()->selectAll(); } else if (ImGui::IsKeyPressed( Control::layoutKey(GLFW_KEY_R), false )) { - // toggle recording stop / start (or save and continue if + ALT modifier) - outputcontrol.ToggleRecord(alt_modifier_active); + // toggle recording stop / start (or save and continue if + SHIFT modifier) + outputcontrol.ToggleRecord(shift_modifier_active); } else if (ImGui::IsKeyPressed( Control::layoutKey(GLFW_KEY_Z), false )) { if (shift_modifier_active) @@ -444,8 +444,15 @@ void UserInterface::handleKeyboard() void UserInterface::handleMouse() { ImGuiIO& io = ImGui::GetIO(); - glm::vec2 mousepos(io.MousePos.x * io.DisplayFramebufferScale.x, io.MousePos.y * io.DisplayFramebufferScale.y); - mousepos = glm::clamp(mousepos, glm::vec2(0.f), glm::vec2(io.DisplaySize.x * io.DisplayFramebufferScale.x, io.DisplaySize.y * io.DisplayFramebufferScale.y)); + + // get mouse coordinates and prevent invalid values + static glm::vec2 _prev_mousepos = glm::vec2(0.f); + glm::vec2 mousepos = _prev_mousepos; + if (io.MousePos.x > -1 && io.MousePos.y > -1) { + mousepos = glm::vec2 (io.MousePos.x * io.DisplayFramebufferScale.x, io.MousePos.y * io.DisplayFramebufferScale.y); + mousepos = glm::clamp(mousepos, glm::vec2(0.f), glm::vec2(io.DisplaySize.x * io.DisplayFramebufferScale.x, io.DisplaySize.y * io.DisplayFramebufferScale.y)); + _prev_mousepos = mousepos; + } static glm::vec2 mouseclic[2]; mouseclic[ImGuiMouseButton_Left] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Left].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Left].y* io.DisplayFramebufferScale.x); @@ -503,8 +510,12 @@ void UserInterface::handleMouse() mousedown = true; // initiate Mouse pointer from position at mouse down event - MousePointer::manager().setActiveMode( (Pointer::Mode) Settings::application.mouse_pointer ); - MousePointer::manager().active()->setStrength( Settings::application.mouse_pointer_strength[Settings::application.mouse_pointer] ); + if (alt_modifier_active || Settings::application.mouse_pointer_lock) { + MousePointer::manager().setActiveMode( (Pointer::Mode) Settings::application.mouse_pointer ); + MousePointer::manager().active()->setStrength( Settings::application.mouse_pointer_strength[Settings::application.mouse_pointer] ); + } + else + MousePointer::manager().setActiveMode( Pointer::POINTER_DEFAULT ); // ask the view what was picked picked = Mixer::manager().view()->pick(mousepos); @@ -2893,44 +2904,77 @@ void Navigator::Render() RenderMousePointerSelector(iconsize); // List of icons for View selection + static uint view_options_timeout = 0; + static ImVec2 view_options_pos = ImGui::GetCursorScreenPos(); + bool selected_view[View::INVALID] = { }; selected_view[ Settings::application.current_view ] = true; int previous_view = Settings::application.current_view; + if (ImGui::Selectable( ICON_FA_BULLSEYE, &selected_view[View::MIXING], 0, iconsize)) { UserInterface::manager().setView(View::MIXING); - view_pannel_visible = previous_view == Settings::application.current_view; + if (previous_view == Settings::application.current_view) { + ImGui::OpenPopup( "PopupViewOptions" ); + view_options_pos = ImGui::GetCursorScreenPos(); + } } - if (ImGui::IsItemHovered()) + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { tooltip = {"Mixing ", "F1"}; + view_options_timeout = 0; + } + if (ImGui::Selectable( ICON_FA_OBJECT_UNGROUP , &selected_view[View::GEOMETRY], 0, iconsize)) { UserInterface::manager().setView(View::GEOMETRY); - view_pannel_visible = previous_view == Settings::application.current_view; + if (previous_view == Settings::application.current_view) { + ImGui::OpenPopup( "PopupViewOptions" ); + view_options_pos = ImGui::GetCursorScreenPos(); + } } - if (ImGui::IsItemHovered()) + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { tooltip = {"Geometry ", "F2"}; + view_options_timeout = 0; + } + if (ImGui::Selectable( ICON_FA_LAYER_GROUP, &selected_view[View::LAYER], 0, iconsize)) { UserInterface::manager().setView(View::LAYER); - view_pannel_visible = previous_view == Settings::application.current_view; + if (previous_view == Settings::application.current_view) { + ImGui::OpenPopup( "PopupViewOptions" ); + view_options_pos = ImGui::GetCursorScreenPos(); + } } - if (ImGui::IsItemHovered()) + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { tooltip = {"Layers ", "F3"}; + view_options_timeout = 0; + } + if (ImGui::Selectable( ICON_FA_CHESS_BOARD, &selected_view[View::TEXTURE], 0, iconsize)) { UserInterface::manager().setView(View::TEXTURE); - view_pannel_visible = previous_view == Settings::application.current_view; + if (previous_view == Settings::application.current_view) { + ImGui::OpenPopup( "PopupViewOptions" ); + view_options_pos = ImGui::GetCursorScreenPos(); + } } - if (ImGui::IsItemHovered()) + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { tooltip = {"Texturing ", "F4"}; + view_options_timeout = 0; + } + if (ImGui::Selectable( ICON_FA_TV, &selected_view[View::DISPLAYS], 0, iconsize)) { UserInterface::manager().setView(View::DISPLAYS); - view_pannel_visible = previous_view == Settings::application.current_view; + if (previous_view == Settings::application.current_view) { + ImGui::OpenPopup( "PopupViewOptions" ); + view_options_pos = ImGui::GetCursorScreenPos(); + } } - if (ImGui::IsItemHovered()) + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { tooltip = {"Displays ", "F5"}; + view_options_timeout = 0; + } ImVec2 pos = ImGui::GetCursorPos(); ImGui::SetCursorPos(pos + ImVec2(0.f, style.WindowPadding.y)); @@ -2950,6 +2994,9 @@ void Navigator::Render() ImGui::PopFont(); + // render the "PopupViewOptions" + RenderViewOptions(&view_options_timeout, view_options_pos, iconsize); + ImGui::End(); } @@ -2964,10 +3011,6 @@ void Navigator::Render() else _timeout_tooltip = 0; - // Rendering of special side pannel for view zoom - if ( view_pannel_visible && !pannel_visible_ ) - RenderViewPannel( ImVec2(width_, sourcelist_height), ImVec2(width_*0.8f, height_ - sourcelist_height) ); - ImGui::PopStyleVar(); ImGui::PopFont(); @@ -3019,38 +3062,38 @@ void Navigator::Render() } -void Navigator::RenderViewPannel(ImVec2 draw_pos , ImVec2 draw_size) +void Navigator::RenderViewOptions(uint *timeout, const ImVec2 &pos, const ImVec2 &size) { - ImGui::SetNextWindowPos( draw_pos, ImGuiCond_Always ); - ImGui::SetNextWindowSize( draw_size, ImGuiCond_Always ); - ImGui::SetNextWindowBgAlpha(0.95f); // Transparent background - if (ImGui::Begin("##ViewPannel", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNav)) + ImGuiContext& g = *GImGui; + + ImGui::SetNextWindowPos( pos + ImVec2(size.x + g.Style.WindowPadding.x, -size.y), ImGuiCond_Always ); + ImGui::SetNextWindowSize( ImVec2(size.x * 7.f, size.y), ImGuiCond_Always ); + if (ImGui::BeginPopup( "PopupViewOptions" )) { - ImGui::SetCursorPosX(10.f); - ImGui::SetCursorPosY(10.f); + // vertical padding + ImGui::SetCursorPosY( ImGui::GetCursorPosY() + g.Style.WindowPadding.y * 0.5f ); + + // reset zoom if (ImGuiToolkit::IconButton(8,7)) { - // reset zoom Mixer::manager().view((View::Mode)Settings::application.current_view)->recenter(); } - draw_size.x *= 0.5; - ImGui::SetCursorPosX( 10.f); - draw_size.y -= ImGui::GetCursorPosY() + 10.f; + // percent zoom slider int percent_zoom = Mixer::manager().view((View::Mode)Settings::application.current_view)->size(); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.1, 0.1, 0.1, 0.95)); - ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.14, 0.14, 0.14, 0.95)); - ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.14, 0.14, 0.14, 0.95)); - ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.9, 0.9, 0.9, 0.95)); - if (ImGui::VSliderInt("##z", draw_size, &percent_zoom, 0, 100, "") ) - { + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::SetNextItemWidth(-1.f); + if (ImGui::SliderInt("##zoom", &percent_zoom, 0, 100, "%d %%" )) { Mixer::manager().view((View::Mode)Settings::application.current_view)->resize(percent_zoom); } - ImGui::PopStyleColor(4); - if (ImGui::IsItemActive() || ImGui::IsItemHovered()) - ImGui::SetTooltip("Zoom %d %%", percent_zoom); - ImGui::End(); - } + // timer to close popup like a tooltip + if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) + *timeout=0; + else if ( (*timeout)++ > 10) + ImGui::CloseCurrentPopup(); + + ImGui::EndPopup(); + } } // Source pannel : *s was checked before @@ -4626,14 +4669,18 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size) /// interactive button of the given size: show menu if clic or mouse over /// static uint counter_menu_timeout = 0; - if ( ImGui::InvisibleButton("##MenuMousePointerButton", size) || ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) ) { + if ( ImGui::InvisibleButton("##MenuMousePointerButton", size) /*|| ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)*/ ) { - counter_menu_timeout=0; if (enabled) ImGui::OpenPopup( "MenuMousePointer" ); } ImVec2 bottom = ImGui::GetCursorScreenPos(); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { + ImGuiToolkit::ToolTip("Alternative cursor", "ALT"); + counter_menu_timeout=0; + } + // Change color of icons depending on context menu status const ImVec4* colors = ImGui::GetStyle().Colors; if (enabled) @@ -4642,10 +4689,10 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size) ImGui::PushStyleColor( ImGuiCol_Text, colors[ImGuiCol_TextDisabled] ); // Draw centered icon of Mouse pointer - ImVec2 margin = (size - ImVec2(g.FontSize, g.FontSize)) * 0.42f; + ImVec2 margin = (size - ImVec2(g.FontSize, g.FontSize)) * 0.5f; ImGui::SetCursorPos( top + margin ); - if ( Settings::application.mouse_pointer > 0 ) { + if ( UserInterface::manager().altModifier() || Settings::application.mouse_pointer_lock) { // icon with corner erased ImGuiToolkit::Icon(ICON_POINTER_OPTION); @@ -4672,7 +4719,7 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size) if (ImGui::BeginPopup( "MenuMousePointer" )) { // loop over all mouse pointer modes - for ( size_t m = Pointer::POINTER_DEFAULT; m < Pointer::POINTER_INVALID; ++m) { + for ( size_t m = Pointer::POINTER_GRID; m < Pointer::POINTER_INVALID; ++m) { bool on = m == (size_t) Settings::application.mouse_pointer; std::tuple mode = Pointer::Modes.at(m); // show icon of mouse mode and set mouse pointer if selected @@ -4682,6 +4729,16 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size) ImGui::SameLine(0, IMGUI_SAME_LINE); } + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT); + ImGui::SetCursorPosY(margin.y); + ImGui::TextDisabled(" |"); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGuiToolkit::ButtonToggle(Settings::application.mouse_pointer_lock ? ICON_FA_LOCK " ALT LOCK" : ICON_FA_UNLOCK " ALT LOCK", + &Settings::application.mouse_pointer_lock, + "Activate the selected alternative mouse pointer by pressing the ALT key.\n\n" + ICON_FA_LOCK " ALT LOCK keeps the alternative mouse pointer active."); + ImGui::PopFont(); + // timer to close menu like a tooltip if (ImGui::IsWindowHovered()) counter_menu_timeout=0; diff --git a/src/UserInterfaceManager.h b/src/UserInterfaceManager.h index 4ae0a7c..bf66d35 100644 --- a/src/UserInterfaceManager.h +++ b/src/UserInterfaceManager.h @@ -69,7 +69,7 @@ class Navigator void RenderMainPannelSettings(); void RenderTransitionPannel(); void RenderNewPannel(); - void RenderViewPannel(ImVec2 draw_pos, ImVec2 draw_size); + void RenderViewOptions(uint *timeout, const ImVec2 &pos, const ImVec2 &size); void RenderMousePointerSelector(const ImVec2 &size); public: diff --git a/src/defines.h b/src/defines.h index 1dbada5..90c7a0b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -171,7 +171,7 @@ #define MENU_RECORD ICON_FA_CIRCLE " Record" #define SHORTCUT_RECORD CTRL_MOD "R" #define MENU_RECORDCONT ICON_FA_STOP_CIRCLE " Save & continue" -#define SHORTCUT_RECORDCONT CTRL_MOD "Alt+R" +#define SHORTCUT_RECORDCONT CTRL_MOD "Shift+R" #define MENU_CAPTUREFRAME ICON_FA_CAMERA_RETRO " Capture frame" #define SHORTCUT_CAPTURE_DISPLAY "F11" #define SHORTCUT_CAPTURE_PLAYER "F10"