mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-14 11:49:59 +01:00
New MousePointer to change behavior of mouse
Initial implementation, mostly replicating GLMixer features. 5 Modes; default, linear, spring, wiggly and metronome. Save in Settings. Selection in Navigation panel.
This commit is contained in:
Binary file not shown.
@@ -96,6 +96,7 @@ set(VMIX_SRCS
|
|||||||
MultiFileRecorder.cpp
|
MultiFileRecorder.cpp
|
||||||
DisplaysView.cpp
|
DisplaysView.cpp
|
||||||
ScreenCaptureSource.cpp
|
ScreenCaptureSource.cpp
|
||||||
|
MousePointer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#####
|
#####
|
||||||
|
|||||||
@@ -437,6 +437,41 @@ bool ImGuiToolkit::IconToggle(int i, int j, int i_toggle, int j_toggle, bool* to
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ImGuiToolkit::IconToggle(int i, int j, bool* toggle, const char *tooltip, const char* shortcut)
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||||
|
if (window->SkipItems)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ImGui::PushID( i * 20 + j + ( tooltip ? window->GetID(tooltip) : 0) );
|
||||||
|
|
||||||
|
float frame_height = ImGui::GetFrameHeight();
|
||||||
|
ImVec2 draw_pos = ImGui::GetCursorScreenPos();
|
||||||
|
|
||||||
|
// toggle action : operate on the whole area
|
||||||
|
bool ret = false;
|
||||||
|
ImGui::InvisibleButton("##iconijtogglebutton", ImVec2(frame_height, frame_height));
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
*toggle = !*toggle;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
if (tooltip != nullptr && ImGui::IsItemHovered())
|
||||||
|
ImGuiToolkit::ToolTip(tooltip, shortcut);
|
||||||
|
|
||||||
|
ImGui::SetCursorScreenPos(draw_pos);
|
||||||
|
|
||||||
|
// draw with hovered color
|
||||||
|
const ImVec4* colors = ImGui::GetStyle().Colors;
|
||||||
|
ImGui::PushStyleColor( ImGuiCol_Text, *toggle ? colors[ImGuiCol_DragDropTarget] : colors[ImGuiCol_Text] );
|
||||||
|
ImGui::PushStyleColor( ImGuiCol_Text, ImGui::IsItemHovered() ? colors[ImGuiCol_NavHighlight] : colors[ImGuiCol_Text] );
|
||||||
|
// ImGui::Text("%s", icon);
|
||||||
|
Icon(i, j, !ret);
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool ImGuiToolkit::IconToggle(const char* icon, bool* toggle, const char *tooltip, const char* shortcut)
|
bool ImGuiToolkit::IconToggle(const char* icon, bool* toggle, const char *tooltip, const char* shortcut)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace ImGuiToolkit
|
|||||||
bool IconButton (const char* icon, const char *tooltips = nullptr, const char *shortcut = nullptr);
|
bool IconButton (const char* icon, const char *tooltips = nullptr, const char *shortcut = nullptr);
|
||||||
bool IconMultistate (std::vector<std::pair<int, int> > icons, int* state, std::vector<std::string> tooltips);
|
bool IconMultistate (std::vector<std::pair<int, int> > icons, int* state, std::vector<std::string> tooltips);
|
||||||
bool IconToggle (int i, int j, int i_toggle, int j_toggle, bool* toggle, const char *tooltips[] = nullptr);
|
bool IconToggle (int i, int j, int i_toggle, int j_toggle, bool* toggle, const char *tooltips[] = nullptr);
|
||||||
|
bool IconToggle (int i, int j, bool* toggle, const char *tooltip = nullptr, const char *shortcut = nullptr);
|
||||||
bool IconToggle (const char* icon, bool* toggle, const char *tooltip = nullptr, const char *shortcut = nullptr);
|
bool IconToggle (const char* icon, bool* toggle, const char *tooltip = nullptr, const char *shortcut = nullptr);
|
||||||
void ShowIconsWindow(bool* p_open);
|
void ShowIconsWindow(bool* p_open);
|
||||||
|
|
||||||
|
|||||||
247
src/MousePointer.cpp
Normal file
247
src/MousePointer.cpp
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of vimix - video live mixer
|
||||||
|
*
|
||||||
|
* **Copyright** (C) 2019-2023 Bruno Herbelin <bruno.herbelin@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <glm/gtc/random.hpp> // for diskRand
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
|
||||||
|
#include "Metronome.h"
|
||||||
|
#include "MousePointer.h"
|
||||||
|
|
||||||
|
std::vector< std::tuple<int, int, std::string> > Pointer::Modes = {
|
||||||
|
{ ICON_POINTER_DEFAULT, std::string("Default") },
|
||||||
|
{ ICON_POINTER_LINEAR, std::string("Linear") },
|
||||||
|
{ ICON_POINTER_SPRING, std::string("Spring") },
|
||||||
|
{ ICON_POINTER_WIGGLY, std::string("Wiggly") },
|
||||||
|
{ ICON_POINTER_METRONOME, std::string("Metronome") }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define POINTER_LINEAR_MIN_SPEED 40.f
|
||||||
|
#define POINTER_LINEAR_MAX_SPEED 800.f
|
||||||
|
#define POINTER_LINEAR_THICKNESS 4.f
|
||||||
|
#define POINTER_LINEAR_ARROW 40.f
|
||||||
|
|
||||||
|
void PointerLinear::update(glm::vec2 pos, float dt)
|
||||||
|
{
|
||||||
|
float speed = POINTER_LINEAR_MIN_SPEED + (POINTER_LINEAR_MAX_SPEED - POINTER_LINEAR_MIN_SPEED) * strength_;
|
||||||
|
|
||||||
|
glm::vec2 delta = pos - pos_ ;
|
||||||
|
if (glm::length(delta) > 10.f )
|
||||||
|
pos_ += glm::normalize(delta) * (speed * dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerLinear::draw()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
const glm::vec2 start = glm::vec2( io.MousePos.x, io.MousePos.y);
|
||||||
|
const glm::vec2 end = glm::vec2( pos_.x / io.DisplayFramebufferScale.x, pos_.y / io.DisplayFramebufferScale.y );
|
||||||
|
const ImVec2 _end = ImVec2( end.x, end.y );
|
||||||
|
|
||||||
|
// draw line
|
||||||
|
ImGui::GetBackgroundDrawList()->AddLine(io.MousePos, _end, ImGui::GetColorU32(ImGuiCol_HeaderActive), POINTER_LINEAR_THICKNESS);
|
||||||
|
ImGui::GetBackgroundDrawList()->AddCircleFilled(_end, 6.0, ImGui::GetColorU32(ImGuiCol_HeaderActive));
|
||||||
|
|
||||||
|
// direction vector
|
||||||
|
glm::vec2 delta = start - end;
|
||||||
|
float l = glm::length(delta);
|
||||||
|
delta = glm::normalize( delta );
|
||||||
|
|
||||||
|
// draw dots regularly to show speed
|
||||||
|
for (float p = 0.f; p < l; p += 200.f * (strength_ + 0.1f)) {
|
||||||
|
glm::vec2 point = start - delta * p;
|
||||||
|
ImGui::GetBackgroundDrawList()->AddCircleFilled(ImVec2(point.x,point.y), 4.0, ImGui::GetColorU32(ImGuiCol_HeaderActive));
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw arrow head
|
||||||
|
if ( l > POINTER_LINEAR_ARROW * 1.5f) {
|
||||||
|
glm::vec2 ortho = glm::normalize( glm::vec2( glm::cross( glm::vec3(delta, 0.f), glm::vec3(0.f, 0.f, 1.f)) ));
|
||||||
|
ortho *= POINTER_LINEAR_ARROW;
|
||||||
|
delta *= POINTER_LINEAR_ARROW;
|
||||||
|
const glm::vec2 pointA = start - delta + ortho * 0.5f;
|
||||||
|
const glm::vec2 pointB = start - delta - ortho * 0.5f;
|
||||||
|
|
||||||
|
ImGui::GetBackgroundDrawList()->AddTriangleFilled(io.MousePos, ImVec2(pointA.x, pointA.y),
|
||||||
|
ImVec2(pointB.x, pointB.y), ImGui::GetColorU32(ImGuiCol_HeaderActive));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define POINTER_WIGGLY_MIN_RADIUS 30.f
|
||||||
|
#define POINTER_WIGGLY_MAX_RADIUS 300.f
|
||||||
|
#define POINTER_WIGGLY_SMOOTHING 10
|
||||||
|
|
||||||
|
void PointerWiggly::update(glm::vec2 pos, float)
|
||||||
|
{
|
||||||
|
float radius = POINTER_WIGGLY_MIN_RADIUS + (POINTER_WIGGLY_MAX_RADIUS - POINTER_WIGGLY_MIN_RADIUS) * strength_;
|
||||||
|
|
||||||
|
// change pos to a random point in a close radius
|
||||||
|
pos += glm::diskRand( radius );
|
||||||
|
|
||||||
|
// smooth a little and apply
|
||||||
|
const float emaexp = 2.0 / float( POINTER_WIGGLY_SMOOTHING + 1);
|
||||||
|
pos_ = emaexp * pos + (1.f - emaexp) * pos_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerWiggly::draw()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
const ImVec2 _end = ImVec2( pos_.x / io.DisplayFramebufferScale.x, pos_.y / io.DisplayFramebufferScale.y );
|
||||||
|
ImGui::GetBackgroundDrawList()->AddLine(io.MousePos, _end, ImGui::GetColorU32(ImGuiCol_HeaderActive), 5.f);
|
||||||
|
|
||||||
|
const float radius = POINTER_WIGGLY_MIN_RADIUS + (POINTER_WIGGLY_MAX_RADIUS - POINTER_WIGGLY_MIN_RADIUS) * strength_;
|
||||||
|
ImGui::GetBackgroundDrawList()->AddCircle(io.MousePos, radius * 0.5f,
|
||||||
|
ImGui::GetColorU32(ImGuiCol_HeaderActive), 0, 2.f + 4.f * strength_);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define POINTER_METRONOME_RADIUS 30.f
|
||||||
|
|
||||||
|
void PointerMetronome::update(glm::vec2 pos, float dt)
|
||||||
|
{
|
||||||
|
if ( Metronome::manager().timeToBeat() < std::chrono::milliseconds( (uint)floor(dt * 1000.f) )) {
|
||||||
|
pos_ = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerMetronome::draw()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
const ImVec2 end = ImVec2(pos_.x / io.DisplayFramebufferScale.x, pos_.y / io.DisplayFramebufferScale.y);
|
||||||
|
ImGui::GetBackgroundDrawList()->AddLine(io.MousePos, end, ImGui::GetColorU32(ImGuiCol_HeaderActive), 4.f);
|
||||||
|
ImGui::GetBackgroundDrawList()->AddCircle(io.MousePos, POINTER_METRONOME_RADIUS, ImGui::GetColorU32(ImGuiCol_HeaderActive), 0, 3.f);
|
||||||
|
ImGui::GetBackgroundDrawList()->AddCircleFilled(end, 6.0, ImGui::GetColorU32(ImGuiCol_HeaderActive));
|
||||||
|
|
||||||
|
double t = Metronome::manager().phase();
|
||||||
|
t -= floor(t);
|
||||||
|
ImGui::GetBackgroundDrawList()->AddCircleFilled(io.MousePos, t * POINTER_METRONOME_RADIUS, ImGui::GetColorU32(ImGuiCol_HeaderActive), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define POINTER_SPRING_MIN_MASS 6.f
|
||||||
|
#define POINTER_SPRING_MAX_MASS 40.f
|
||||||
|
|
||||||
|
void PointerSpring::initiate(glm::vec2 pos)
|
||||||
|
{
|
||||||
|
Pointer::initiate(pos);
|
||||||
|
velocity_ = glm::vec2(0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerSpring::update(glm::vec2 pos, float dt)
|
||||||
|
{
|
||||||
|
// percentage of loss of energy at every update
|
||||||
|
const float viscousness = 0.75;
|
||||||
|
// force applied on the mass, as percent of the Maximum mass
|
||||||
|
const float stiffness = 0.8;
|
||||||
|
// damping : opposite direction of force, non proportional to mass
|
||||||
|
const float damping = 60.0;
|
||||||
|
// mass as a percentage of min to max
|
||||||
|
const float mass = POINTER_SPRING_MAX_MASS - (POINTER_SPRING_MAX_MASS - POINTER_SPRING_MIN_MASS) * strength_;
|
||||||
|
|
||||||
|
// compute delta betwen initial and current position
|
||||||
|
glm::vec2 delta = pos - pos_;
|
||||||
|
// apply force on velocity : spring stiffness / mass
|
||||||
|
velocity_ += delta * ( (POINTER_SPRING_MAX_MASS * stiffness) / mass );
|
||||||
|
// apply damping dynamics
|
||||||
|
velocity_ -= damping * dt * glm::normalize(delta);
|
||||||
|
// compute new position : add velocity x time
|
||||||
|
pos_ += dt * velocity_;
|
||||||
|
// diminish velocity by viscousness of substrate
|
||||||
|
// (loss of energy between updates)
|
||||||
|
velocity_ *= viscousness;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerSpring::draw()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
glm::vec2 _start = glm::vec2( io.MousePos.x * io.DisplayFramebufferScale.x, io.MousePos.y * io.DisplayFramebufferScale.y );
|
||||||
|
|
||||||
|
const glm::vec2 delta = pos_ - _start;
|
||||||
|
glm::vec2 ortho = glm::normalize( glm::vec2( glm::cross( glm::vec3(delta, 0.f), glm::vec3(0.f, 0.f, 1.f)) ));
|
||||||
|
ortho *= 0.05f * glm::length( velocity_ );
|
||||||
|
|
||||||
|
// draw a wave with 3 bezier
|
||||||
|
glm::vec2 _third = _start + delta * 1.f / 9.f + ortho;
|
||||||
|
glm::vec2 _twothird = _start + delta * 2.f / 9.f - ortho;
|
||||||
|
glm::vec2 _end = _start + delta * 3.f / 9.f;
|
||||||
|
|
||||||
|
ImVec2 start = ImVec2(_start.x / io.DisplayFramebufferScale.x, _start.y / io.DisplayFramebufferScale.y);
|
||||||
|
ImVec2 third = ImVec2(_third.x / io.DisplayFramebufferScale.x, _third.y / io.DisplayFramebufferScale.y);
|
||||||
|
ImVec2 twothird = ImVec2(_twothird.x / io.DisplayFramebufferScale.x, _twothird.y / io.DisplayFramebufferScale.y);
|
||||||
|
ImVec2 end = ImVec2(_end.x / io.DisplayFramebufferScale.x, _end.y / io.DisplayFramebufferScale.y);
|
||||||
|
ImGui::GetBackgroundDrawList()->AddBezierCurve(start, third, twothird, end,
|
||||||
|
ImGui::GetColorU32(ImGuiCol_HeaderActive), 5.f);
|
||||||
|
_start = _end;
|
||||||
|
_third = _start + delta * 1.f / 9.f + ortho;
|
||||||
|
_twothird = _start + delta * 2.f / 9.f - ortho;
|
||||||
|
_end = _start + delta * 3.f / 9.f;
|
||||||
|
|
||||||
|
start = ImVec2(_start.x / io.DisplayFramebufferScale.x, _start.y / io.DisplayFramebufferScale.y);
|
||||||
|
third = ImVec2(_third.x / io.DisplayFramebufferScale.x, _third.y / io.DisplayFramebufferScale.y);
|
||||||
|
twothird = ImVec2(_twothird.x / io.DisplayFramebufferScale.x, _twothird.y / io.DisplayFramebufferScale.y);
|
||||||
|
end = ImVec2(_end.x / io.DisplayFramebufferScale.x, _end.y / io.DisplayFramebufferScale.y);
|
||||||
|
ImGui::GetBackgroundDrawList()->AddBezierCurve(start, third, twothird, end,
|
||||||
|
ImGui::GetColorU32(ImGuiCol_HeaderActive), 5.f);
|
||||||
|
_start = _end;
|
||||||
|
_third = _start + delta * 1.f / 9.f + ortho;
|
||||||
|
_twothird = _start + delta * 2.f / 9.f - ortho;
|
||||||
|
|
||||||
|
start = ImVec2(_start.x / io.DisplayFramebufferScale.x, _start.y / io.DisplayFramebufferScale.y);
|
||||||
|
third = ImVec2(_third.x / io.DisplayFramebufferScale.x, _third.y / io.DisplayFramebufferScale.y);
|
||||||
|
twothird = ImVec2(_twothird.x / io.DisplayFramebufferScale.x, _twothird.y / io.DisplayFramebufferScale.y);
|
||||||
|
end = ImVec2(pos_.x / io.DisplayFramebufferScale.x, pos_.y / io.DisplayFramebufferScale.y);
|
||||||
|
ImGui::GetBackgroundDrawList()->AddBezierCurve(start, third, twothird, end,
|
||||||
|
ImGui::GetColorU32(ImGuiCol_HeaderActive), 5.f);
|
||||||
|
|
||||||
|
// represent the weight with a filled circle
|
||||||
|
float mass = POINTER_SPRING_MAX_MASS - (POINTER_SPRING_MAX_MASS - POINTER_SPRING_MIN_MASS) * strength_;
|
||||||
|
ImGui::GetBackgroundDrawList()->AddCircleFilled(end, mass, ImGui::GetColorU32(ImGuiCol_HeaderActive));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MousePointer::MousePointer() : mode_(Pointer::POINTER_DEFAULT), active_(nullptr)
|
||||||
|
{
|
||||||
|
active_ = new Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MousePointer::setActiveMode(Pointer::Mode m)
|
||||||
|
{
|
||||||
|
if (mode_ != m) {
|
||||||
|
|
||||||
|
mode_ = m;
|
||||||
|
|
||||||
|
if (active_)
|
||||||
|
delete active_;
|
||||||
|
|
||||||
|
switch (mode_) {
|
||||||
|
case Pointer::POINTER_SPRING:
|
||||||
|
active_ = new PointerSpring;
|
||||||
|
break;
|
||||||
|
case Pointer::POINTER_METRONOME:
|
||||||
|
active_ = new PointerMetronome;
|
||||||
|
break;
|
||||||
|
case Pointer::POINTER_LINEAR:
|
||||||
|
active_ = new PointerLinear;
|
||||||
|
break;
|
||||||
|
case Pointer::POINTER_WIGGLY:
|
||||||
|
active_ = new PointerWiggly;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case Pointer::POINTER_DEFAULT:
|
||||||
|
active_ = new Pointer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
106
src/MousePointer.h
Normal file
106
src/MousePointer.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#ifndef POINTER_H
|
||||||
|
#define POINTER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#define ICON_POINTER_DEFAULT 7, 3
|
||||||
|
#define ICON_POINTER_OPTION 12, 9
|
||||||
|
#define ICON_POINTER_SPRING 13, 9
|
||||||
|
#define ICON_POINTER_LINEAR 14, 9
|
||||||
|
#define ICON_POINTER_WIGGLY 10, 3
|
||||||
|
#define ICON_POINTER_METRONOME 6, 13
|
||||||
|
|
||||||
|
class Pointer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef enum {
|
||||||
|
POINTER_DEFAULT = 0,
|
||||||
|
POINTER_LINEAR,
|
||||||
|
POINTER_SPRING,
|
||||||
|
POINTER_WIGGLY,
|
||||||
|
POINTER_METRONOME,
|
||||||
|
POINTER_INVALID
|
||||||
|
} Mode;
|
||||||
|
static std::vector< std::tuple<int, int, std::string> > Modes;
|
||||||
|
|
||||||
|
Pointer() : strength_(0.5) {}
|
||||||
|
virtual ~Pointer() {}
|
||||||
|
inline glm::vec2 pos() { return pos_; }
|
||||||
|
|
||||||
|
virtual void initiate(glm::vec2 pos) { pos_ = pos; }
|
||||||
|
virtual void update(glm::vec2 pos, float) { pos_ = pos; }
|
||||||
|
virtual void draw() {}
|
||||||
|
|
||||||
|
inline void setStrength(float percent) { strength_ = glm::clamp(percent, 0.f, 1.f); }
|
||||||
|
inline float strength() const { return strength_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
glm::vec2 pos_;
|
||||||
|
float strength_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PointerLinear : public Pointer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PointerLinear() {}
|
||||||
|
void update(glm::vec2 pos, float dt) override;
|
||||||
|
void draw() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PointerSpring : public Pointer
|
||||||
|
{
|
||||||
|
glm::vec2 velocity_;
|
||||||
|
public:
|
||||||
|
PointerSpring() {}
|
||||||
|
void initiate(glm::vec2 pos) override;
|
||||||
|
void update(glm::vec2 pos, float dt) override;
|
||||||
|
void draw() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PointerWiggly : public Pointer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PointerWiggly() {}
|
||||||
|
void update(glm::vec2 pos, float) override;
|
||||||
|
void draw() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PointerMetronome : public Pointer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PointerMetronome() {}
|
||||||
|
void update(glm::vec2 pos, float dt) override;
|
||||||
|
void draw() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MousePointer
|
||||||
|
{
|
||||||
|
// Private Constructor
|
||||||
|
MousePointer();
|
||||||
|
MousePointer(MousePointer const& copy) = delete;
|
||||||
|
MousePointer& operator=(MousePointer const& copy) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static MousePointer& manager ()
|
||||||
|
{
|
||||||
|
// The only instance
|
||||||
|
static MousePointer _instance;
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Pointer *active() { return active_; }
|
||||||
|
inline Pointer::Mode activeMode() { return mode_; }
|
||||||
|
|
||||||
|
void setActiveMode(Pointer::Mode m);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Pointer::Mode mode_;
|
||||||
|
Pointer *active_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // POINTER_H
|
||||||
@@ -132,7 +132,6 @@ void Settings::Save(uint64_t runtime)
|
|||||||
applicationNode->SetAttribute("accent_color", application.accent_color);
|
applicationNode->SetAttribute("accent_color", application.accent_color);
|
||||||
applicationNode->SetAttribute("smooth_transition", application.smooth_transition);
|
applicationNode->SetAttribute("smooth_transition", application.smooth_transition);
|
||||||
applicationNode->SetAttribute("save_snapshot", application.save_version_snapshot);
|
applicationNode->SetAttribute("save_snapshot", application.save_version_snapshot);
|
||||||
applicationNode->SetAttribute("smooth_cursor", application.smooth_cursor);
|
|
||||||
applicationNode->SetAttribute("action_history_follow_view", application.action_history_follow_view);
|
applicationNode->SetAttribute("action_history_follow_view", application.action_history_follow_view);
|
||||||
applicationNode->SetAttribute("show_tooptips", application.show_tooptips);
|
applicationNode->SetAttribute("show_tooptips", application.show_tooptips);
|
||||||
applicationNode->SetAttribute("accept_connections", application.accept_connections);
|
applicationNode->SetAttribute("accept_connections", application.accept_connections);
|
||||||
@@ -214,6 +213,15 @@ void Settings::Save(uint64_t runtime)
|
|||||||
BrushNode->InsertEndChild( XMLElementFromGLM(&xmlDoc, application.brush) );
|
BrushNode->InsertEndChild( XMLElementFromGLM(&xmlDoc, application.brush) );
|
||||||
pRoot->InsertEndChild(BrushNode);
|
pRoot->InsertEndChild(BrushNode);
|
||||||
|
|
||||||
|
// Pointer
|
||||||
|
XMLElement *PointerNode = xmlDoc.NewElement( "MousePointer" );
|
||||||
|
PointerNode->SetAttribute("mode", application.mouse_pointer);
|
||||||
|
for (size_t i = 0; i < application.mouse_pointer_strength.size(); ++i ) {
|
||||||
|
float v = application.mouse_pointer_strength[i];
|
||||||
|
PointerNode->InsertEndChild( XMLElementFromGLM(&xmlDoc, glm::vec2((float)i, v)) );
|
||||||
|
}
|
||||||
|
pRoot->InsertEndChild(PointerNode);
|
||||||
|
|
||||||
// bloc views
|
// bloc views
|
||||||
{
|
{
|
||||||
XMLElement *viewsNode = xmlDoc.NewElement( "Views" );
|
XMLElement *viewsNode = xmlDoc.NewElement( "Views" );
|
||||||
@@ -284,8 +292,6 @@ void Settings::Save(uint64_t runtime)
|
|||||||
|
|
||||||
// recent SRT hosts
|
// recent SRT hosts
|
||||||
knownhosts->InsertEndChild( save_knownhost(application.recentSRT, "SRT", xmlDoc));
|
knownhosts->InsertEndChild( save_knownhost(application.recentSRT, "SRT", xmlDoc));
|
||||||
|
|
||||||
|
|
||||||
pRoot->InsertEndChild(knownhosts);
|
pRoot->InsertEndChild(knownhosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,7 +416,6 @@ void Settings::Load()
|
|||||||
applicationNode->QueryIntAttribute("accent_color", &application.accent_color);
|
applicationNode->QueryIntAttribute("accent_color", &application.accent_color);
|
||||||
applicationNode->QueryBoolAttribute("smooth_transition", &application.smooth_transition);
|
applicationNode->QueryBoolAttribute("smooth_transition", &application.smooth_transition);
|
||||||
applicationNode->QueryBoolAttribute("save_snapshot", &application.save_version_snapshot);
|
applicationNode->QueryBoolAttribute("save_snapshot", &application.save_version_snapshot);
|
||||||
applicationNode->QueryBoolAttribute("smooth_cursor", &application.smooth_cursor);
|
|
||||||
applicationNode->QueryBoolAttribute("action_history_follow_view", &application.action_history_follow_view);
|
applicationNode->QueryBoolAttribute("action_history_follow_view", &application.action_history_follow_view);
|
||||||
applicationNode->QueryBoolAttribute("show_tooptips", &application.show_tooptips);
|
applicationNode->QueryBoolAttribute("show_tooptips", &application.show_tooptips);
|
||||||
applicationNode->QueryBoolAttribute("accept_connections", &application.accept_connections);
|
applicationNode->QueryBoolAttribute("accept_connections", &application.accept_connections);
|
||||||
@@ -556,6 +561,20 @@ void Settings::Load()
|
|||||||
tinyxml2::XMLElementToGLM( brushnode->FirstChildElement("vec3"), application.brush);
|
tinyxml2::XMLElementToGLM( brushnode->FirstChildElement("vec3"), application.brush);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pointer
|
||||||
|
XMLElement * pointernode = pRoot->FirstChildElement("MousePointer");
|
||||||
|
if (pointernode != nullptr) {
|
||||||
|
pointernode->QueryIntAttribute("mode", &application.mouse_pointer);
|
||||||
|
|
||||||
|
XMLElement* strengthNode = pointernode->FirstChildElement("vec2");
|
||||||
|
for( ; strengthNode ; strengthNode = strengthNode->NextSiblingElement())
|
||||||
|
{
|
||||||
|
glm::vec2 val;
|
||||||
|
tinyxml2::XMLElementToGLM( strengthNode, val);
|
||||||
|
application.mouse_pointer_strength[ (size_t) ceil(val.x) ] = val.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// bloc views
|
// bloc views
|
||||||
{
|
{
|
||||||
XMLElement * pElement = pRoot->FirstChildElement("Views");
|
XMLElement * pElement = pRoot->FirstChildElement("Views");
|
||||||
|
|||||||
@@ -271,7 +271,8 @@ struct Application
|
|||||||
int accent_color;
|
int accent_color;
|
||||||
bool save_version_snapshot;
|
bool save_version_snapshot;
|
||||||
bool smooth_transition;
|
bool smooth_transition;
|
||||||
bool smooth_cursor;
|
int mouse_pointer;
|
||||||
|
std::vector<float> mouse_pointer_strength;
|
||||||
bool action_history_follow_view;
|
bool action_history_follow_view;
|
||||||
bool show_tooptips;
|
bool show_tooptips;
|
||||||
|
|
||||||
@@ -336,7 +337,8 @@ struct Application
|
|||||||
accent_color = 0;
|
accent_color = 0;
|
||||||
smooth_transition = false;
|
smooth_transition = false;
|
||||||
save_version_snapshot = false;
|
save_version_snapshot = false;
|
||||||
smooth_cursor = false;
|
mouse_pointer = 0;
|
||||||
|
mouse_pointer_strength = {0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f};
|
||||||
action_history_follow_view = false;
|
action_history_follow_view = false;
|
||||||
show_tooptips = true;
|
show_tooptips = true;
|
||||||
accept_connections = false;
|
accept_connections = false;
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
#include "ShmdataBroadcast.h"
|
#include "ShmdataBroadcast.h"
|
||||||
#include "VideoBroadcast.h"
|
#include "VideoBroadcast.h"
|
||||||
#include "MultiFileRecorder.h"
|
#include "MultiFileRecorder.h"
|
||||||
|
#include "MousePointer.h"
|
||||||
|
|
||||||
#include "UserInterfaceManager.h"
|
#include "UserInterfaceManager.h"
|
||||||
|
|
||||||
@@ -442,13 +443,10 @@ void UserInterface::handleKeyboard()
|
|||||||
|
|
||||||
void UserInterface::handleMouse()
|
void UserInterface::handleMouse()
|
||||||
{
|
{
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
glm::vec2 mousepos(io.MousePos.x * io.DisplayFramebufferScale.x, io.MousePos.y * io.DisplayFramebufferScale.y);
|
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));
|
mousepos = glm::clamp(mousepos, glm::vec2(0.f), glm::vec2(io.DisplaySize.x * io.DisplayFramebufferScale.x, io.DisplaySize.y * io.DisplayFramebufferScale.y));
|
||||||
|
|
||||||
static glm::vec2 mouse_smooth = mousepos;
|
|
||||||
|
|
||||||
static glm::vec2 mouseclic[2];
|
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);
|
mouseclic[ImGuiMouseButton_Left] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Left].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Left].y* io.DisplayFramebufferScale.x);
|
||||||
mouseclic[ImGuiMouseButton_Right] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Right].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Right].y* io.DisplayFramebufferScale.x);
|
mouseclic[ImGuiMouseButton_Right] = glm::vec2(io.MouseClickedPos[ImGuiMouseButton_Right].x * io.DisplayFramebufferScale.y, io.MouseClickedPos[ImGuiMouseButton_Right].y* io.DisplayFramebufferScale.x);
|
||||||
@@ -474,15 +472,6 @@ void UserInterface::handleMouse()
|
|||||||
// if not on any window
|
// if not on any window
|
||||||
if ( !ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) && !ImGui::IsWindowFocused(ImGuiHoveredFlags_AnyWindow) )
|
if ( !ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) && !ImGui::IsWindowFocused(ImGuiHoveredFlags_AnyWindow) )
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// Mouse wheel over background
|
|
||||||
//
|
|
||||||
if ( io.MouseWheel != 0) {
|
|
||||||
// scroll => zoom current view
|
|
||||||
Mixer::manager().view()->zoom( io.MouseWheel );
|
|
||||||
}
|
|
||||||
// TODO : zoom with center on source if over current
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// RIGHT Mouse button
|
// RIGHT Mouse button
|
||||||
//
|
//
|
||||||
@@ -512,7 +501,11 @@ void UserInterface::handleMouse()
|
|||||||
if ( !mousedown )
|
if ( !mousedown )
|
||||||
{
|
{
|
||||||
mousedown = true;
|
mousedown = true;
|
||||||
mouse_smooth = mousepos;
|
|
||||||
|
// 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] );
|
||||||
|
MousePointer::manager().active()->initiate(mousepos);
|
||||||
|
|
||||||
// ask the view what was picked
|
// ask the view what was picked
|
||||||
picked = Mixer::manager().view()->pick(mousepos);
|
picked = Mixer::manager().view()->pick(mousepos);
|
||||||
@@ -592,17 +585,8 @@ void UserInterface::handleMouse()
|
|||||||
if (view_drag == Mixer::manager().view()) {
|
if (view_drag == Mixer::manager().view()) {
|
||||||
|
|
||||||
if ( picked.first != nullptr ) {
|
if ( picked.first != nullptr ) {
|
||||||
// Smooth cursor
|
// Apply Mouse pointer filter
|
||||||
if (Settings::application.smooth_cursor) {
|
MousePointer::manager().active()->update(mousepos, 1.f / ( MAX(io.Framerate, 1.f) ));
|
||||||
// TODO : physics implementation
|
|
||||||
float smoothing = 10.f / ( MAX(io.Framerate, 1.f) );
|
|
||||||
glm::vec2 d = mousepos - mouse_smooth;
|
|
||||||
mouse_smooth += smoothing * d;
|
|
||||||
ImVec2 start = ImVec2(mouse_smooth.x / io.DisplayFramebufferScale.x, mouse_smooth.y / io.DisplayFramebufferScale.y);
|
|
||||||
ImGui::GetBackgroundDrawList()->AddLine(io.MousePos, start, ImGui::GetColorU32(ImGuiCol_HeaderActive), 5.f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mouse_smooth = mousepos;
|
|
||||||
|
|
||||||
// action on current source
|
// action on current source
|
||||||
Source *current = Mixer::manager().currentSource();
|
Source *current = Mixer::manager().currentSource();
|
||||||
@@ -612,19 +596,32 @@ void UserInterface::handleMouse()
|
|||||||
// grab others from selection
|
// grab others from selection
|
||||||
for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); ++it) {
|
for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); ++it) {
|
||||||
if ( *it != current && !(*it)->locked() )
|
if ( *it != current && !(*it)->locked() )
|
||||||
Mixer::manager().view()->grab(*it, mouseclic[ImGuiMouseButton_Left], mouse_smooth, picked);
|
Mixer::manager().view()->grab(*it, mouseclic[ImGuiMouseButton_Left],
|
||||||
|
MousePointer::manager().active()->pos(), picked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// grab current sources
|
// grab current sources
|
||||||
View::Cursor c = Mixer::manager().view()->grab(current, mouseclic[ImGuiMouseButton_Left], mouse_smooth, picked);
|
View::Cursor c = Mixer::manager().view()->grab(current, mouseclic[ImGuiMouseButton_Left],
|
||||||
|
MousePointer::manager().active()->pos(), picked);
|
||||||
SetMouseCursor(io.MousePos, c);
|
SetMouseCursor(io.MousePos, c);
|
||||||
|
|
||||||
|
// scrollwheel changes strength of Mouse Pointer
|
||||||
|
if ( io.MouseWheel != 0) {
|
||||||
|
MousePointer::manager().active()->setStrength( MousePointer::manager().active()->strength() + 0.1 * io.MouseWheel);
|
||||||
|
Settings::application.mouse_pointer_strength[Settings::application.mouse_pointer] = MousePointer::manager().active()->strength();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw Mouse pointer effect
|
||||||
|
MousePointer::manager().active()->draw();
|
||||||
}
|
}
|
||||||
// action on other (non-source) elements in the view
|
// action on other (non-source) elements in the view
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
View::Cursor c = Mixer::manager().view()->grab(nullptr, mouseclic[ImGuiMouseButton_Left], mouse_smooth, picked);
|
View::Cursor c = Mixer::manager().view()->grab(nullptr, mouseclic[ImGuiMouseButton_Left], mousepos, picked);
|
||||||
SetMouseCursor(io.MousePos, c);
|
SetMouseCursor(io.MousePos, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// Selection area
|
// Selection area
|
||||||
else {
|
else {
|
||||||
@@ -640,6 +637,13 @@ void UserInterface::handleMouse()
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// Mouse wheel over background without source action
|
||||||
|
//
|
||||||
|
else if ( !mousedown && io.MouseWheel != 0) {
|
||||||
|
// scroll => zoom current view
|
||||||
|
Mixer::manager().view()->zoom( io.MouseWheel );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// cancel all operations on view when interacting on GUI
|
// cancel all operations on view when interacting on GUI
|
||||||
@@ -2770,7 +2774,7 @@ void Navigator::Render()
|
|||||||
height_ = ImGui::GetIO().DisplaySize.y; // cover vertically
|
height_ = ImGui::GetIO().DisplaySize.y; // cover vertically
|
||||||
const float icon_width = width_ - 2.f * style.WindowPadding.x; // icons keep padding
|
const float icon_width = width_ - 2.f * style.WindowPadding.x; // icons keep padding
|
||||||
const ImVec2 iconsize(icon_width, icon_width);
|
const ImVec2 iconsize(icon_width, icon_width);
|
||||||
const float sourcelist_height = height_ - 5.5f * icon_width - 5.f * style.WindowPadding.y; // space for 4 icons of view
|
const float sourcelist_height = height_ - 6.5f * icon_width - 6.f * style.WindowPadding.y; // space for 4 icons of view
|
||||||
|
|
||||||
// hack to show more sources if not enough space; make source icons smaller...
|
// hack to show more sources if not enough space; make source icons smaller...
|
||||||
ImVec2 sourceiconsize(icon_width, icon_width);
|
ImVec2 sourceiconsize(icon_width, icon_width);
|
||||||
@@ -2886,6 +2890,10 @@ void Navigator::Render()
|
|||||||
if (ImGui::Begin("##navigatorViews", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
|
if (ImGui::Begin("##navigatorViews", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
|
||||||
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoScrollWithMouse))
|
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoScrollWithMouse))
|
||||||
{
|
{
|
||||||
|
// Mouse pointer selector
|
||||||
|
RenderMousePointerSelector(iconsize);
|
||||||
|
|
||||||
|
// List of icons for View selection
|
||||||
bool selected_view[View::INVALID] = { };
|
bool selected_view[View::INVALID] = { };
|
||||||
selected_view[ Settings::application.current_view ] = true;
|
selected_view[ Settings::application.current_view ] = true;
|
||||||
int previous_view = Settings::application.current_view;
|
int previous_view = Settings::application.current_view;
|
||||||
@@ -4606,6 +4614,80 @@ void Navigator::RenderMainPannelVimix()
|
|||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Navigator::RenderMousePointerSelector(const ImVec2 &size)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImVec2 top = ImGui::GetCursorPos();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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) ) {
|
||||||
|
|
||||||
|
counter_menu_timeout=0;
|
||||||
|
ImGui::OpenPopup( "MenuMousePointer" );
|
||||||
|
}
|
||||||
|
ImVec2 bottom = ImGui::GetCursorScreenPos();
|
||||||
|
|
||||||
|
// Change color of icons depending on context menu status
|
||||||
|
const ImVec4* colors = ImGui::GetStyle().Colors;
|
||||||
|
ImGui::PushStyleColor( ImGuiCol_Text, ImGui::IsPopupOpen("MenuMousePointer") ? colors[ImGuiCol_DragDropTarget] : colors[ImGuiCol_Text] );
|
||||||
|
|
||||||
|
// Draw centered icon of Mouse pointer
|
||||||
|
ImVec2 margin = (size - ImVec2(g.FontSize, g.FontSize)) * 0.42f;
|
||||||
|
ImGui::SetCursorPos( top + margin );
|
||||||
|
|
||||||
|
if ( Settings::application.mouse_pointer > 0 ) {
|
||||||
|
// icon with corner erased
|
||||||
|
ImGuiToolkit::Icon(ICON_POINTER_OPTION);
|
||||||
|
|
||||||
|
// Draw sub-icon of Mouse pointer type
|
||||||
|
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
||||||
|
ImVec2 t = top + size - ImVec2(g.FontSize, g.FontSize) - ImVec2(g.Style.FramePadding.y, g.Style.FramePadding.y);
|
||||||
|
ImGui::SetCursorPos( t );
|
||||||
|
std::tuple<int, int, std::string> mode = Pointer::Modes.at( (size_t) Settings::application.mouse_pointer);
|
||||||
|
ImGuiToolkit::Icon(std::get<0>(mode), std::get<1>(mode));
|
||||||
|
ImGui::PopFont();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// standard icon
|
||||||
|
ImGuiToolkit::Icon(ICON_POINTER_DEFAULT);
|
||||||
|
|
||||||
|
// Revert
|
||||||
|
ImGui::PopStyleColor(1);
|
||||||
|
ImGui::SetCursorScreenPos(bottom);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Render the Popup menu selector
|
||||||
|
///
|
||||||
|
ImGui::SetNextWindowPos( bottom + ImVec2(size.x + g.Style.WindowPadding.x, -size.y), ImGuiCond_Always );
|
||||||
|
if (ImGui::BeginPopup( "MenuMousePointer" ))
|
||||||
|
{
|
||||||
|
// loop over all mouse pointer modes
|
||||||
|
for ( size_t m = Pointer::POINTER_DEFAULT; m < Pointer::POINTER_INVALID; ++m) {
|
||||||
|
bool on = m == (size_t) Settings::application.mouse_pointer;
|
||||||
|
std::tuple<int, int, std::string> mode = Pointer::Modes.at(m);
|
||||||
|
// show icon of mouse mode and set mouse pointer if selected
|
||||||
|
if (ImGuiToolkit::IconToggle( std::get<0>(mode), std::get<1>(mode), &on, std::get<2>(mode).c_str()) )
|
||||||
|
Settings::application.mouse_pointer = (int) m;
|
||||||
|
// space between icons
|
||||||
|
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// timer to close menu like a tooltip
|
||||||
|
if (ImGui::IsWindowHovered())
|
||||||
|
counter_menu_timeout=0;
|
||||||
|
else if (++counter_menu_timeout > 10)
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Navigator::RenderMainPannelSettings()
|
void Navigator::RenderMainPannelSettings()
|
||||||
@@ -4637,9 +4719,6 @@ void Navigator::RenderMainPannelSettings()
|
|||||||
Settings::application.scale = CLAMP(Settings::application.scale, 0.5f, 2.f);
|
Settings::application.scale = CLAMP(Settings::application.scale, 0.5f, 2.f);
|
||||||
ImGui::GetIO().FontGlobalScale = Settings::application.scale;
|
ImGui::GetIO().FontGlobalScale = Settings::application.scale;
|
||||||
}
|
}
|
||||||
ImGuiToolkit::HelpToolTip("Cursor filter that makes movement smoother when manipulating a source.");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGuiToolkit::ButtonSwitch( ICON_FA_MOUSE_POINTER " Smooth cursor", &Settings::application.smooth_cursor);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Recording preferences
|
// Recording preferences
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ class Navigator
|
|||||||
void RenderTransitionPannel();
|
void RenderTransitionPannel();
|
||||||
void RenderNewPannel();
|
void RenderNewPannel();
|
||||||
void RenderViewPannel(ImVec2 draw_pos, ImVec2 draw_size);
|
void RenderViewPannel(ImVec2 draw_pos, ImVec2 draw_size);
|
||||||
|
void RenderMousePointerSelector(const ImVec2 &size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user