mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 02:40:00 +01:00
Mixing and Geometry Selection menu actions
This commit is contained in:
211
GeometryView.cpp
211
GeometryView.cpp
@@ -21,6 +21,7 @@
|
|||||||
#include "Decorations.h"
|
#include "Decorations.h"
|
||||||
#include "UserInterfaceManager.h"
|
#include "UserInterfaceManager.h"
|
||||||
#include "BoundingBoxVisitor.h"
|
#include "BoundingBoxVisitor.h"
|
||||||
|
#include "ActionManager.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
#include "GeometryView.h"
|
#include "GeometryView.h"
|
||||||
@@ -150,7 +151,7 @@ void GeometryView::update(float dt)
|
|||||||
if (Mixer::manager().view() == this )
|
if (Mixer::manager().view() == this )
|
||||||
{
|
{
|
||||||
updateSelectionOverlay();
|
updateSelectionOverlay();
|
||||||
overlay_selection_icon_->visible_ = false;
|
// overlay_selection_icon_->visible_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,34 +269,114 @@ void GeometryView::draw()
|
|||||||
if (ImGui::BeginPopup("GeometrySourceContextMenu")) {
|
if (ImGui::BeginPopup("GeometrySourceContextMenu")) {
|
||||||
Source *s = Mixer::manager().currentSource();
|
Source *s = Mixer::manager().currentSource();
|
||||||
if (s != nullptr) {
|
if (s != nullptr) {
|
||||||
|
if (ImGui::Selectable( ICON_FA_EXPAND " Fit" )){
|
||||||
|
s->group(mode_)->scale_ = glm::vec3(output_surface_->scale_.x/ s->frame()->aspectRatio(), 1.f, 1.f);
|
||||||
|
s->group(mode_)->rotation_.z = 0;
|
||||||
|
s->group(mode_)->translation_ = glm::vec3(0.f);
|
||||||
|
s->touch();
|
||||||
|
Action::manager().store(std::string("Source Fit."), s->id());
|
||||||
|
}
|
||||||
if (ImGui::Selectable( ICON_FA_VECTOR_SQUARE " Reset" )){
|
if (ImGui::Selectable( ICON_FA_VECTOR_SQUARE " Reset" )){
|
||||||
s->group(mode_)->scale_ = glm::vec3(1.f);
|
s->group(mode_)->scale_ = glm::vec3(1.f);
|
||||||
s->group(mode_)->rotation_.z = 0;
|
s->group(mode_)->rotation_.z = 0;
|
||||||
s->group(mode_)->crop_ = glm::vec3(1.f);
|
s->group(mode_)->crop_ = glm::vec3(1.f);
|
||||||
s->group(mode_)->translation_ = glm::vec3(0.f);
|
s->group(mode_)->translation_ = glm::vec3(0.f);
|
||||||
s->touch();
|
s->touch();
|
||||||
|
Action::manager().store(std::string("Source Reset."), s->id());
|
||||||
}
|
}
|
||||||
else if (ImGui::Selectable( ICON_FA_EXPAND " Fit" )){
|
if (ImGui::Selectable( ICON_FA_CROSSHAIRS " Reset position" )){
|
||||||
glm::vec3 scale = glm::vec3(1.f);
|
s->group(mode_)->translation_ = glm::vec3(0.f);
|
||||||
FrameBuffer *output = Mixer::manager().session()->frame();
|
s->touch();
|
||||||
if (output) scale.x = output->aspectRatio() / s->frame()->aspectRatio();
|
Action::manager().store(std::string("Source Reset position."), s->id());
|
||||||
s->group(mode_)->scale_ = scale;
|
}
|
||||||
|
if (ImGui::Selectable( ICON_FA_COMPASS " Reset rotation" )){
|
||||||
s->group(mode_)->rotation_.z = 0;
|
s->group(mode_)->rotation_.z = 0;
|
||||||
s->group(mode_)->translation_ = glm::vec3(0.f);
|
|
||||||
s->touch();
|
s->touch();
|
||||||
|
Action::manager().store(std::string("Source Reset rotation."), s->id());
|
||||||
}
|
}
|
||||||
else if (ImGui::Selectable( ICON_FA_CROSSHAIRS " Center" )){
|
if (ImGui::Selectable( ICON_FA_EXPAND_ALT " Reset aspect ratio" )){
|
||||||
s->group(mode_)->translation_ = glm::vec3(0.f);
|
|
||||||
s->touch();
|
|
||||||
}
|
|
||||||
else if (ImGui::Selectable( ICON_FA_EXPAND_ALT " Restore aspect ratio" )){
|
|
||||||
s->group(mode_)->scale_.x = s->group(mode_)->scale_.y;
|
s->group(mode_)->scale_.x = s->group(mode_)->scale_.y;
|
||||||
s->group(mode_)->scale_.x *= s->group(mode_)->crop_.x / s->group(mode_)->crop_.y;
|
s->group(mode_)->scale_.x *= s->group(mode_)->crop_.x / s->group(mode_)->crop_.y;
|
||||||
s->touch();
|
s->touch();
|
||||||
|
Action::manager().store(std::string("Source aspect ratio."), s->id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
// display popup menu
|
||||||
|
if (show_context_menu_ == MENU_SELECTION) {
|
||||||
|
ImGui::OpenPopup( "GeometrySelectionContextMenu" );
|
||||||
|
show_context_menu_ = MENU_NONE;
|
||||||
|
}
|
||||||
|
if (ImGui::BeginPopup("GeometrySelectionContextMenu")) {
|
||||||
|
|
||||||
|
// colored context menu
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImGuiToolkit::HighlightColor());
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.36f, 0.36f, 0.36f, 0.44f));
|
||||||
|
|
||||||
|
// batch manipulation of sources in Geometry view
|
||||||
|
if (ImGui::Selectable( ICON_FA_EXPAND " Fit all" )){
|
||||||
|
for (auto sit = Mixer::selection().begin(); sit != Mixer::selection().end(); sit++){
|
||||||
|
(*sit)->group(mode_)->scale_ = glm::vec3(output_surface_->scale_.x/ (*sit)->frame()->aspectRatio(), 1.f, 1.f);
|
||||||
|
(*sit)->group(mode_)->rotation_.z = 0;
|
||||||
|
(*sit)->group(mode_)->translation_ = glm::vec3(0.f);
|
||||||
|
(*sit)->touch();
|
||||||
|
}
|
||||||
|
Action::manager().store(std::string("Selection Fit all."), Mixer::selection().front()->id());
|
||||||
|
}
|
||||||
|
if (ImGui::Selectable( ICON_FA_VECTOR_SQUARE " Reset all" )){
|
||||||
|
// apply to every sources in selection
|
||||||
|
for (auto sit = Mixer::selection().begin(); sit != Mixer::selection().end(); sit++){
|
||||||
|
(*sit)->group(mode_)->scale_ = glm::vec3(1.f);
|
||||||
|
(*sit)->group(mode_)->rotation_.z = 0;
|
||||||
|
(*sit)->group(mode_)->crop_ = glm::vec3(1.f);
|
||||||
|
(*sit)->group(mode_)->translation_ = glm::vec3(0.f);
|
||||||
|
(*sit)->touch();
|
||||||
|
}
|
||||||
|
Action::manager().store(std::string("Selection Reset all."), Mixer::selection().front()->id());
|
||||||
|
}
|
||||||
|
if (ImGui::Selectable( ICON_FA_COMPASS " Align all" )){
|
||||||
|
// apply to every sources in selection
|
||||||
|
for (auto sit = Mixer::selection().begin(); sit != Mixer::selection().end(); sit++){
|
||||||
|
(*sit)->group(mode_)->rotation_.z = overlay_selection_->rotation_.z;
|
||||||
|
(*sit)->touch();
|
||||||
|
}
|
||||||
|
Action::manager().store(std::string("Selection Align all."), Mixer::selection().front()->id());
|
||||||
|
}
|
||||||
|
// if (ImGui::Selectable( ICON_FA_TH " Mosaic" )){ // TODO
|
||||||
|
|
||||||
|
// }
|
||||||
|
ImGui::Separator();
|
||||||
|
// manipulation of selection
|
||||||
|
if (ImGui::Selectable( ICON_FA_CROSSHAIRS " Center" )){
|
||||||
|
glm::mat4 T = glm::translate(glm::identity<glm::mat4>(), -overlay_selection_->translation_);
|
||||||
|
initiate();
|
||||||
|
applySelectionTransform(T);
|
||||||
|
Action::manager().store(std::string("Selection Center."), Mixer::selection().front()->id());
|
||||||
|
}
|
||||||
|
if (ImGui::Selectable( ICON_FA_COMPRESS " Best Fit" )){
|
||||||
|
glm::mat4 T = glm::translate(glm::identity<glm::mat4>(), -overlay_selection_->translation_);
|
||||||
|
float factor = 1.f;
|
||||||
|
float angle = -overlay_selection_->rotation_.z;
|
||||||
|
if ( overlay_selection_->scale_.x < overlay_selection_->scale_.y) {
|
||||||
|
factor *= output_surface_->scale_.x / overlay_selection_->scale_.y;
|
||||||
|
angle += glm::pi<float>() / 2.f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
factor *= output_surface_->scale_.x / overlay_selection_->scale_.x;
|
||||||
|
}
|
||||||
|
glm::mat4 S = glm::scale(glm::identity<glm::mat4>(), glm::vec3(factor, factor, 1.f));
|
||||||
|
glm::mat4 R = glm::rotate(glm::identity<glm::mat4>(), angle, glm::vec3(0.f, 0.f, 1.f) );
|
||||||
|
glm::mat4 M = S * R * T;
|
||||||
|
initiate();
|
||||||
|
applySelectionTransform(M);
|
||||||
|
Action::manager().store(std::string("Selection Best Fit."), Mixer::selection().front()->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -392,6 +473,11 @@ std::pair<Node *, glm::vec2> GeometryView::pick(glm::vec2 P)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if ( overlay_selection_icon_ != nullptr && (*itp).first == overlay_selection_icon_ ) {
|
||||||
|
pick = (*itp);
|
||||||
|
openContextMenu(MENU_SELECTION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -407,6 +493,22 @@ bool GeometryView::canSelect(Source *s) {
|
|||||||
return ( View::canSelect(s) && s->active() && s->workspace() == Settings::application.current_workspace);
|
return ( View::canSelect(s) && s->active() && s->workspace() == Settings::application.current_workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GeometryView::applySelectionTransform(glm::mat4 M)
|
||||||
|
{
|
||||||
|
for (auto sit = Mixer::selection().begin(); sit != Mixer::selection().end(); sit++){
|
||||||
|
// recompute all from matrix transform
|
||||||
|
glm::mat4 transform = M * (*sit)->stored_status_->transform_;
|
||||||
|
glm::vec3 tra, rot, sca;
|
||||||
|
GlmToolkit::inverse_transform(transform, tra, rot, sca);
|
||||||
|
(*sit)->group(mode_)->translation_ = tra;
|
||||||
|
(*sit)->group(mode_)->scale_ = sca;
|
||||||
|
(*sit)->group(mode_)->rotation_ = rot;
|
||||||
|
// will have to be updated
|
||||||
|
(*sit)->touch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick)
|
View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick)
|
||||||
{
|
{
|
||||||
View::Cursor ret = Cursor();
|
View::Cursor ret = Cursor();
|
||||||
@@ -431,60 +533,75 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p
|
|||||||
float factor = glm::length( glm::vec2( selection_to ) ) / glm::length( glm::vec2( selection_from ) );
|
float factor = glm::length( glm::vec2( selection_to ) ) / glm::length( glm::vec2( selection_from ) );
|
||||||
glm::mat4 S = glm::scale(glm::identity<glm::mat4>(), glm::vec3(factor, factor, 1.f));
|
glm::mat4 S = glm::scale(glm::identity<glm::mat4>(), glm::vec3(factor, factor, 1.f));
|
||||||
|
|
||||||
// if interaction with selection
|
// if interaction with selection SCALING handle
|
||||||
if (pick.first == overlay_selection_scale_) {
|
if (pick.first == overlay_selection_scale_) {
|
||||||
|
|
||||||
// apply to overlay
|
// show manipulation overlay
|
||||||
|
overlay_scaling_cross_->visible_ = true;
|
||||||
|
overlay_scaling_grid_->visible_ = false;
|
||||||
|
overlay_scaling_->visible_ = true;
|
||||||
|
overlay_scaling_->translation_.x = overlay_selection_stored_status_->translation_.x;
|
||||||
|
overlay_scaling_->translation_.y = overlay_selection_stored_status_->translation_.y;
|
||||||
|
overlay_scaling_->rotation_.z = overlay_selection_stored_status_->rotation_.z;
|
||||||
|
overlay_scaling_->update(0);
|
||||||
|
overlay_scaling_cross_->copyTransform(overlay_scaling_);
|
||||||
|
overlay_scaling_->color = overlay_selection_icon_->color;
|
||||||
|
overlay_scaling_cross_->color = overlay_selection_icon_->color;
|
||||||
|
|
||||||
|
// apply to selection overlay
|
||||||
glm::vec4 vec = S * glm::vec4( overlay_selection_stored_status_->scale_, 0.f );
|
glm::vec4 vec = S * glm::vec4( overlay_selection_stored_status_->scale_, 0.f );
|
||||||
overlay_selection_->scale_ = glm::vec3(vec);
|
overlay_selection_->scale_ = glm::vec3(vec);
|
||||||
|
|
||||||
// Transform sources
|
// apply to selection sources
|
||||||
// complete transform matrix (right to left) : move to center, scale and move back
|
// NB: complete transform matrix (right to left) : move to center, scale and move back
|
||||||
glm::mat4 M = T * S * glm::inverse(T);
|
glm::mat4 M = T * S * glm::inverse(T);
|
||||||
// apply to every sources in selection
|
applySelectionTransform(M);
|
||||||
for (auto sit = Mixer::selection().begin(); sit != Mixer::selection().end(); sit++){
|
|
||||||
// displacement
|
|
||||||
vec = M * glm::vec4( (*sit)->stored_status_->translation_, 1.f );
|
|
||||||
(*sit)->group(mode_)->translation_ = glm::vec3(vec);
|
|
||||||
// scale
|
|
||||||
vec = M * glm::vec4( (*sit)->stored_status_->scale_, 0.f );
|
|
||||||
(*sit)->group(mode_)->scale_ = glm::vec3(vec);
|
|
||||||
// will have to be updated
|
|
||||||
(*sit)->touch();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// store action in history
|
||||||
|
current_action_ = "Scale selection";
|
||||||
|
current_id_ = Mixer::selection().front()->id();
|
||||||
ret.type = Cursor_ResizeNWSE;
|
ret.type = Cursor_ResizeNWSE;
|
||||||
}
|
}
|
||||||
|
// if interaction with selection ROTATION handle
|
||||||
else if (pick.first == overlay_selection_rotate_) {
|
else if (pick.first == overlay_selection_rotate_) {
|
||||||
|
|
||||||
|
// show manipulation overlay
|
||||||
|
overlay_rotation_->visible_ = true;
|
||||||
|
overlay_rotation_->translation_.x = overlay_selection_stored_status_->translation_.x;
|
||||||
|
overlay_rotation_->translation_.y = overlay_selection_stored_status_->translation_.y;
|
||||||
|
overlay_rotation_->update(0);
|
||||||
|
overlay_rotation_->color = overlay_selection_icon_->color;
|
||||||
|
overlay_rotation_fix_->visible_ = false;
|
||||||
|
overlay_rotation_fix_->copyTransform(overlay_rotation_);
|
||||||
|
overlay_rotation_fix_->color = overlay_selection_icon_->color;
|
||||||
|
|
||||||
|
// cancel out scaling with SHIFT modifier key
|
||||||
|
if (UserInterface::manager().shiftModifier()) {
|
||||||
|
overlay_rotation_fix_->visible_ = true;
|
||||||
|
float factor = glm::length( glm::vec2( overlay_selection_->scale_ ) ) / glm::length( glm::vec2( overlay_selection_stored_status_->scale_ ) );
|
||||||
|
S = glm::scale(glm::identity<glm::mat4>(), glm::vec3(factor, factor, 1.f));
|
||||||
|
}
|
||||||
|
|
||||||
// compute rotation angle
|
// compute rotation angle
|
||||||
float angle = glm::orientedAngle( glm::normalize(glm::vec2(selection_from)), glm::normalize(glm::vec2(selection_to)));
|
float angle = glm::orientedAngle( glm::normalize(glm::vec2(selection_from)), glm::normalize(glm::vec2(selection_to)));
|
||||||
glm::mat4 R = glm::rotate(glm::identity<glm::mat4>(), angle, glm::vec3(0.f, 0.f, 1.f) );
|
glm::mat4 R = glm::rotate(glm::identity<glm::mat4>(), angle, glm::vec3(0.f, 0.f, 1.f) );
|
||||||
|
|
||||||
// apply to overlay
|
// apply to selection overlay
|
||||||
glm::vec4 vec = S * glm::vec4( overlay_selection_stored_status_->scale_, 0.f );
|
glm::vec4 vec = S * glm::vec4( overlay_selection_stored_status_->scale_, 0.f );
|
||||||
overlay_selection_->scale_ = glm::vec3(vec);
|
overlay_selection_->scale_ = glm::vec3(vec);
|
||||||
overlay_selection_->rotation_.z = overlay_selection_stored_status_->rotation_.z + angle;
|
overlay_selection_->rotation_.z = overlay_selection_stored_status_->rotation_.z + angle;
|
||||||
|
|
||||||
// Transform sources
|
// apply to selection sources
|
||||||
// complete transform matrix (right to left) : move to center, rotate, scale and move back
|
// NB: complete transform matrix (right to left) : move to center, rotate, scale and move back
|
||||||
glm::mat4 M = T * S * R * glm::inverse(T);
|
glm::mat4 M = T * S * R * glm::inverse(T);
|
||||||
// apply to every sources in selection:
|
applySelectionTransform(M);
|
||||||
for (auto sit = Mixer::selection().begin(); sit != Mixer::selection().end(); sit++){
|
|
||||||
|
|
||||||
glm::mat4 transform = M * (*sit)->stored_status_->transform_;
|
|
||||||
glm::vec3 tra, rot, sca;
|
|
||||||
GlmToolkit::inverse_transform(transform, tra, rot, sca);
|
|
||||||
(*sit)->group(mode_)->translation_ = tra;
|
|
||||||
(*sit)->group(mode_)->scale_ = sca;
|
|
||||||
(*sit)->group(mode_)->rotation_ = rot;
|
|
||||||
|
|
||||||
// will have to be updated
|
|
||||||
(*sit)->touch();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// store action in history
|
||||||
|
current_action_ = "Scale and rotate selection";
|
||||||
|
current_id_ = Mixer::selection().front()->id();
|
||||||
ret.type = Cursor_Hand;
|
ret.type = Cursor_Hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update cursor
|
// update cursor
|
||||||
@@ -751,7 +868,6 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p
|
|||||||
s->handles_[mode_][Handles::SCALE]->visible_ = false;
|
s->handles_[mode_][Handles::SCALE]->visible_ = false;
|
||||||
s->handles_[mode_][Handles::CROP]->visible_ = false;
|
s->handles_[mode_][Handles::CROP]->visible_ = false;
|
||||||
s->handles_[mode_][Handles::MENU]->visible_ = false;
|
s->handles_[mode_][Handles::MENU]->visible_ = false;
|
||||||
|
|
||||||
// ROTATION on CENTER
|
// ROTATION on CENTER
|
||||||
overlay_rotation_->visible_ = true;
|
overlay_rotation_->visible_ = true;
|
||||||
overlay_rotation_->translation_.x = s->stored_status_->translation_.x;
|
overlay_rotation_->translation_.x = s->stored_status_->translation_.x;
|
||||||
@@ -760,7 +876,6 @@ View::Cursor GeometryView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p
|
|||||||
overlay_rotation_fix_->visible_ = true;
|
overlay_rotation_fix_->visible_ = true;
|
||||||
overlay_rotation_fix_->copyTransform(overlay_rotation_);
|
overlay_rotation_fix_->copyTransform(overlay_rotation_);
|
||||||
overlay_rotation_clock_->visible_ = false;
|
overlay_rotation_clock_->visible_ = false;
|
||||||
|
|
||||||
// rotation center to center of source (disregarding scale)
|
// rotation center to center of source (disregarding scale)
|
||||||
glm::mat4 T = glm::translate(glm::identity<glm::mat4>(), s->stored_status_->translation_);
|
glm::mat4 T = glm::translate(glm::identity<glm::mat4>(), s->stored_status_->translation_);
|
||||||
source_from = glm::inverse(T) * glm::vec4( scene_from, 1.f );
|
source_from = glm::inverse(T) * glm::vec4( scene_from, 1.f );
|
||||||
@@ -867,6 +982,11 @@ void GeometryView::terminate()
|
|||||||
overlay_scaling_->visible_ = false;
|
overlay_scaling_->visible_ = false;
|
||||||
overlay_crop_->visible_ = false;
|
overlay_crop_->visible_ = false;
|
||||||
|
|
||||||
|
overlay_rotation_->color = glm::vec4(1.f, 1.f, 1.f, 0.8f);
|
||||||
|
overlay_rotation_fix_->color = glm::vec4(1.f, 1.f, 1.f, 0.8f);
|
||||||
|
overlay_scaling_->color = glm::vec4(1.f, 1.f, 1.f, 0.8f);
|
||||||
|
overlay_scaling_cross_->color = glm::vec4(1.f, 1.f, 1.f, 0.8f);
|
||||||
|
|
||||||
// restore of all handles overlays
|
// restore of all handles overlays
|
||||||
glm::vec2 c(0.f, 0.f);
|
glm::vec2 c(0.f, 0.f);
|
||||||
for (auto sit = Mixer::manager().session()->begin();
|
for (auto sit = Mixer::manager().session()->begin();
|
||||||
@@ -944,3 +1064,4 @@ void GeometryView::updateSelectionOverlay()
|
|||||||
overlay_selection_rotate_->color = overlay_selection_icon_->color;
|
overlay_selection_rotate_->color = overlay_selection_icon_->color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ private:
|
|||||||
Surface *output_surface_;
|
Surface *output_surface_;
|
||||||
Node *overlay_position_;
|
Node *overlay_position_;
|
||||||
Node *overlay_position_cross_;
|
Node *overlay_position_cross_;
|
||||||
Node *overlay_rotation_;
|
Symbol *overlay_rotation_;
|
||||||
Node *overlay_rotation_fix_;
|
Symbol *overlay_rotation_fix_;
|
||||||
Node *overlay_rotation_clock_;
|
Node *overlay_rotation_clock_;
|
||||||
Node *overlay_rotation_clock_hand_;
|
Node *overlay_rotation_clock_hand_;
|
||||||
Node *overlay_scaling_;
|
Symbol *overlay_scaling_;
|
||||||
Node *overlay_scaling_cross_;
|
Symbol *overlay_scaling_cross_;
|
||||||
Node *overlay_scaling_grid_;
|
Node *overlay_scaling_grid_;
|
||||||
Node *overlay_crop_;
|
Node *overlay_crop_;
|
||||||
|
|
||||||
@@ -37,6 +37,8 @@ private:
|
|||||||
Group *overlay_selection_stored_status_;
|
Group *overlay_selection_stored_status_;
|
||||||
Handles *overlay_selection_scale_;
|
Handles *overlay_selection_scale_;
|
||||||
Handles *overlay_selection_rotate_;
|
Handles *overlay_selection_rotate_;
|
||||||
|
|
||||||
|
void applySelectionTransform(glm::mat4 M);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -161,12 +161,43 @@ void MixingView::draw()
|
|||||||
(*it)->group(View::MIXING)->translation_ -= overlay_selection_->translation_;
|
(*it)->group(View::MIXING)->translation_ -= overlay_selection_->translation_;
|
||||||
(*it)->touch();
|
(*it)->touch();
|
||||||
}
|
}
|
||||||
|
Action::manager().store(std::string("Selection Center."), Mixer::selection().front()->id());
|
||||||
}
|
}
|
||||||
if (ImGui::Selectable( ICON_FA_EXPAND_ARROWS_ALT " Expand & Hide" )){
|
if (ImGui::Selectable( ICON_FA_HAYKAL " Distribute" )){
|
||||||
|
SourceList list;
|
||||||
|
glm::vec2 center = glm::vec2(0.f, 0.f);
|
||||||
|
for (SourceList::iterator it = Mixer::selection().begin(); it != Mixer::selection().end(); it++) {
|
||||||
|
list.push_back(*it);
|
||||||
|
// compute barycenter (1)
|
||||||
|
center += glm::vec2((*it)->group(View::MIXING)->translation_);
|
||||||
|
}
|
||||||
|
// compute barycenter (2)
|
||||||
|
center /= list.size();
|
||||||
|
// sort the vector of sources in clockwise order around the center pos_
|
||||||
|
list = mixing_sorted( list, center);
|
||||||
|
// average distance
|
||||||
|
float d = 0.f;
|
||||||
|
for (SourceList::iterator it = list.begin(); it != list.end(); it++) {
|
||||||
|
d += glm::distance(glm::vec2((*it)->group(View::MIXING)->translation_), center);
|
||||||
|
}
|
||||||
|
d /= list.size();
|
||||||
|
// distribute with equal angle
|
||||||
|
float angle = 0.f;
|
||||||
|
for (SourceList::iterator it = list.begin(); it != list.end(); it++) {
|
||||||
|
glm::vec2 P = center + glm::rotate(glm::vec2(0.f, d), angle);
|
||||||
|
(*it)->group(View::MIXING)->translation_.x = P.x;
|
||||||
|
(*it)->group(View::MIXING)->translation_.y = P.y;
|
||||||
|
(*it)->touch();
|
||||||
|
angle -= glm::two_pi<float>() / float(list.size());
|
||||||
|
}
|
||||||
|
Action::manager().store(std::string("Selection Distribute."), Mixer::selection().front()->id());
|
||||||
|
}
|
||||||
|
if (ImGui::Selectable( ICON_FA_EXPAND_ARROWS_ALT " Expand to border" )){
|
||||||
SourceList::iterator it = Mixer::selection().begin();
|
SourceList::iterator it = Mixer::selection().begin();
|
||||||
for (; it != Mixer::selection().end(); it++) {
|
for (; it != Mixer::selection().end(); it++) {
|
||||||
(*it)->setAlpha(0.f);
|
(*it)->setAlpha(0.f);
|
||||||
}
|
}
|
||||||
|
Action::manager().store(std::string("Selection Expand to border."), Mixer::selection().front()->id());
|
||||||
}
|
}
|
||||||
ImGui::PopStyleColor(2);
|
ImGui::PopStyleColor(2);
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
|
|||||||
@@ -834,11 +834,15 @@ void TextureView::draw()
|
|||||||
s->group(mode_)->translation_ = glm::vec3(0.f);
|
s->group(mode_)->translation_ = glm::vec3(0.f);
|
||||||
s->touch();
|
s->touch();
|
||||||
}
|
}
|
||||||
else if (ImGui::Selectable( ICON_FA_CROSSHAIRS " Center" )){
|
if (ImGui::Selectable( ICON_FA_CROSSHAIRS " Reset position" )){
|
||||||
s->group(mode_)->translation_ = glm::vec3(0.f);
|
s->group(mode_)->translation_ = glm::vec3(0.f);
|
||||||
s->touch();
|
s->touch();
|
||||||
}
|
}
|
||||||
else if (ImGui::Selectable( ICON_FA_EXPAND_ALT " Restore aspect ratio" )){
|
if (ImGui::Selectable( ICON_FA_COMPASS " Reset rotation" )){
|
||||||
|
s->group(mode_)->rotation_.z = 0;
|
||||||
|
s->touch();
|
||||||
|
}
|
||||||
|
if (ImGui::Selectable( ICON_FA_EXPAND_ALT " Reset aspect ratio" )){
|
||||||
s->group(mode_)->scale_.x = s->group(mode_)->scale_.y;
|
s->group(mode_)->scale_.x = s->group(mode_)->scale_.y;
|
||||||
s->group(mode_)->scale_.x *= s->group(mode_)->crop_.x / s->group(mode_)->crop_.y;
|
s->group(mode_)->scale_.x *= s->group(mode_)->crop_.x / s->group(mode_)->crop_.y;
|
||||||
s->touch();
|
s->touch();
|
||||||
|
|||||||
@@ -626,13 +626,13 @@ void UserInterface::handleMouse()
|
|||||||
Source *current = Mixer::manager().currentSource();
|
Source *current = Mixer::manager().currentSource();
|
||||||
if (current)
|
if (current)
|
||||||
{
|
{
|
||||||
// grab current sources
|
|
||||||
View::Cursor c = Mixer::manager().view()->grab(current, mouseclic[ImGuiMouseButton_Left], mouse_smooth, picked);
|
|
||||||
// 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 )
|
if ( *it != current )
|
||||||
Mixer::manager().view()->grab(*it, mouseclic[ImGuiMouseButton_Left], mouse_smooth, picked);
|
Mixer::manager().view()->grab(*it, mouseclic[ImGuiMouseButton_Left], mouse_smooth, picked);
|
||||||
}
|
}
|
||||||
|
// grab current sources
|
||||||
|
View::Cursor c = Mixer::manager().view()->grab(current, mouseclic[ImGuiMouseButton_Left], mouse_smooth, picked);
|
||||||
setMouseCursor(io.MousePos, c);
|
setMouseCursor(io.MousePos, c);
|
||||||
}
|
}
|
||||||
// action on other (non-source) elements in the view
|
// action on other (non-source) elements in the view
|
||||||
|
|||||||
Reference in New Issue
Block a user