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"