diff --git a/DrawVisitor.cpp b/DrawVisitor.cpp index f4a4a67..c1c14a6 100644 --- a/DrawVisitor.cpp +++ b/DrawVisitor.cpp @@ -1,6 +1,7 @@ #include +#include "defines.h" #include "DrawVisitor.h" #include "Scene.h" @@ -11,14 +12,28 @@ DrawVisitor::DrawVisitor(Node *nodetodraw, glm::mat4 projection) modelview_ = glm::identity(); projection_ = projection; done_ = false; + num_duplicat_ = 1; + transform_duplicat_ = glm::identity(); } +void DrawVisitor::loop(int num, glm::mat4 transform) +{ + num_duplicat_ = CLAMP(num, 1, 10000); + transform_duplicat_ = transform; +} + void DrawVisitor::visit(Node &n) { // draw the target if ( n.id() == target_->id()) { - n.draw(modelview_, projection_); + + for (int i = 0; i < num_duplicat_; ++i) { + // draw multiple copies if requested + n.draw(modelview_, projection_); + modelview_ *= transform_duplicat_; + } + done_ = true; } @@ -59,79 +74,3 @@ void DrawVisitor::visit(Primitive &n) { } - -void DrawVisitor::visit(Surface &n) -{ - -} - -void DrawVisitor::visit(ImageSurface &n) -{ - -} - -void DrawVisitor::visit(FrameBufferSurface &n) -{ - -} - -void DrawVisitor::visit(MediaSurface &n) -{ - -} - -void DrawVisitor::visit(MediaPlayer &n) -{ - -} - -void DrawVisitor::visit(Shader &n) -{ - -} - -void DrawVisitor::visit(ImageShader &n) -{ - -} - -void DrawVisitor::visit(ImageProcessingShader &n) -{ - -} - -void DrawVisitor::visit(LineStrip &n) -{ - -} - -void DrawVisitor::visit(LineSquare &) -{ - -} - -void DrawVisitor::visit(LineCircle &n) -{ - -} - -void DrawVisitor::visit(Mesh &n) -{ - -} - -void DrawVisitor::visit(Frame &n) -{ - -} - - -void DrawVisitor::visit (Source& s) -{ - -} - -void DrawVisitor::visit (MediaSource& s) -{ - -} diff --git a/DrawVisitor.h b/DrawVisitor.h index 834d581..968d742 100644 --- a/DrawVisitor.h +++ b/DrawVisitor.h @@ -10,32 +10,19 @@ class DrawVisitor : public Visitor glm::mat4 projection_; Node *target_; bool done_; + int num_duplicat_; + glm::mat4 transform_duplicat_; public: DrawVisitor(Node *nodetodraw, glm::mat4 projection); + void loop(int num, glm::mat4 transform); + void visit(Scene& n) override; void visit(Node& n) override; + void visit(Primitive& n) override; void visit(Group& n) override; void visit(Switch& n) override; - void visit(Primitive& n) override; - void visit(Surface& n) override; - void visit(ImageSurface& n) override; - void visit(MediaSurface& n) override; - void visit(FrameBufferSurface& n) override; - void visit(LineStrip& n) override; - void visit(LineSquare&) override; - void visit(LineCircle& n) override; - void visit(Mesh& n) override; - void visit(Frame& n) override; - - void visit(MediaPlayer& n) override; - void visit(Shader& n) override; - void visit(ImageShader& n) override; - void visit(ImageProcessingShader& n) override; - - void visit (Source& s) override; - void visit (MediaSource& s) override; }; #endif // DRAWVISITOR_H diff --git a/GarbageVisitor.h b/GarbageVisitor.h index 84b4207..6e3c53e 100644 --- a/GarbageVisitor.h +++ b/GarbageVisitor.h @@ -23,6 +23,7 @@ public: void visit(Group& n) override; void visit(Switch& n) override; void visit(Primitive& n) override; + void visit(Surface& n) override; void visit(ImageSurface& n) override; void visit(MediaSurface& n) override; diff --git a/ImGuiToolkit.cpp b/ImGuiToolkit.cpp index 4545793..b25a003 100644 --- a/ImGuiToolkit.cpp +++ b/ImGuiToolkit.cpp @@ -822,6 +822,58 @@ void ImGuiToolkit::ShowStats(bool *p_open, int* p_corner) } } + +void ImGuiToolkit::WindowText(const char* window_name, ImVec2 window_pos, const char* text) +{ + ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always); + + if (ImGui::Begin(window_name, NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground + | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings + | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); + ImGui::Text(text); + ImGui::PopFont(); + + ImGui::End(); + } +} + +bool ImGuiToolkit::WindowButton(const char* window_name, ImVec2 window_pos, const char* button_text) +{ + bool ret = false; + ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always); + + if (ImGui::Begin(window_name, NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground + | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings + | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); + ret = ImGui::Button(button_text); + ImGui::PopFont(); + + ImGui::End(); + } + return ret; +} + +void ImGuiToolkit::WindowDragFloat(const char* window_name, ImVec2 window_pos, float* v, float v_speed, float v_min, float v_max, const char* format) +{ + ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always); + + if (ImGui::Begin(window_name, NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground + | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings + | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); + ImGui::SetNextItemWidth(100.f); + ImGui::DragFloat("##nolabel", v, v_speed, v_min, v_max, format); + ImGui::PopFont(); + + ImGui::End(); + } +} + ImVec4 ImGuiToolkit::GetHighlightColor() { ImVec4* colors = ImGui::GetStyle().Colors; diff --git a/ImGuiToolkit.h b/ImGuiToolkit.h index 3b16e94..b37709e 100644 --- a/ImGuiToolkit.h +++ b/ImGuiToolkit.h @@ -42,6 +42,11 @@ namespace ImGuiToolkit void SetFont (font_style type, const std::string &ttf_font_name, int pointsize, int oversample = 2); void PushFont (font_style type); + void WindowText(const char* window_name, ImVec2 window_pos, const char* text); + bool WindowButton(const char* window_name, ImVec2 window_pos, const char* text); + void WindowDragFloat(const char* window_name, ImVec2 window_pos, float* v, float v_speed, float v_min, float v_max, const char* format); + + // color of gui items typedef enum { ACCENT_BLUE =0, diff --git a/PickingVisitor.cpp b/PickingVisitor.cpp index 4d05a28..a9c21a6 100644 --- a/PickingVisitor.cpp +++ b/PickingVisitor.cpp @@ -60,7 +60,7 @@ void PickingVisitor::visit(Switch &n) void PickingVisitor::visit(Primitive &n) { - // TODO: generic visitor for primitive with random shape + // TODO: generic visitor for primitive with random shape ? } diff --git a/PickingVisitor.h b/PickingVisitor.h index d669626..5ad1166 100644 --- a/PickingVisitor.h +++ b/PickingVisitor.h @@ -25,6 +25,7 @@ public: void visit(Group& n) override; void visit(Switch& n) override; void visit(Primitive& n) override; + void visit(Surface& n) override; void visit(Frame& n) override; void visit(Handles& n) override; diff --git a/RenderingManager.cpp b/RenderingManager.cpp index 07dd723..a656a09 100644 --- a/RenderingManager.cpp +++ b/RenderingManager.cpp @@ -21,7 +21,6 @@ #include #include // glm::translate, glm::rotate, glm::scale -#include // glm::unproject #include // glm::perspective // Include GStreamer @@ -323,6 +322,15 @@ glm::vec3 Rendering::unProject(glm::vec2 screen_coordinate, glm::mat4 modelview) return point; } + +glm::vec2 Rendering::project(glm::vec3 scene_coordinate, glm::mat4 modelview) +{ + glm::vec4 viewport = glm::vec4( 0.f, 0.f, main_.width(), main_.height()); + glm::vec3 P = glm::project( scene_coordinate, modelview, Projection(), viewport ); + + return glm::vec2(P.x, main_.height() - P.y); +} + void Rendering::FileDropped(GLFWwindow *, int path_count, const char* paths[]) { for (int i = 0; i < path_count; ++i) { diff --git a/RenderingManager.h b/RenderingManager.h index 98ca00a..df7e079 100644 --- a/RenderingManager.h +++ b/RenderingManager.h @@ -132,9 +132,10 @@ public: // get projection matrix (for sharers) => Views glm::mat4 Projection(); - // unproject from window coordinate + // unproject from window coordinate to scene glm::vec3 unProject(glm::vec2 screen_coordinate, glm::mat4 modelview = glm::mat4(1.f)); - + // project from scene coordinate to window + glm::vec2 project(glm::vec3 scene_coordinate, glm::mat4 modelview = glm::mat4(1.f)); private: diff --git a/SessionSource.cpp b/SessionSource.cpp index 038d9b4..8799684 100644 --- a/SessionSource.cpp +++ b/SessionSource.cpp @@ -60,7 +60,7 @@ SessionSource::SessionSource() : Source(), path_("") overlays_[View::TRANSITION] = new Group; overlays_[View::TRANSITION]->translation_.z = 0.1; overlays_[View::TRANSITION]->visible_ = false; - Symbol *center = new Symbol(Symbol::GENERIC, glm::vec3(0.f, 0.f, 0.1f)); + Symbol *center = new Symbol(Symbol::GENERIC, glm::vec3(0.f, -1.05f, 0.1f)); overlays_[View::TRANSITION]->attach(center); groups_[View::TRANSITION]->attach(overlays_[View::TRANSITION]); diff --git a/Settings.cpp b/Settings.cpp index 9c6f08e..49471bf 100644 --- a/Settings.cpp +++ b/Settings.cpp @@ -222,7 +222,7 @@ void Settings::Load() if (transitionnode != nullptr) { transitionnode->QueryBoolAttribute("auto_end", &application.transition.auto_open); transitionnode->QueryBoolAttribute("cross_fade", &application.transition.cross_fade); - transitionnode->QueryIntAttribute("duration", &application.transition.duration); + transitionnode->QueryFloatAttribute("duration", &application.transition.duration); transitionnode->QueryIntAttribute("profile", &application.transition.profile); } diff --git a/Settings.h b/Settings.h index 9d61534..81337dc 100644 --- a/Settings.h +++ b/Settings.h @@ -81,13 +81,13 @@ struct TransitionConfig { bool cross_fade; bool auto_open; - int duration; + float duration; int profile; TransitionConfig() { cross_fade = true; auto_open = true; - duration = 1000; + duration = 1.f; profile = 0; } }; diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index 27baf1e..613db4e 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -1535,15 +1535,15 @@ void Navigator::RenderTransitionPannel() // Transition options ImGui::Text(" "); ImGui::Text("Animation"); - if (ImGuiToolkit::ButtonIcon(4, 13)) Settings::application.transition.duration = 1000; + if (ImGuiToolkit::ButtonIcon(4, 13)) Settings::application.transition.duration = 1.f; ImGui::SameLine(0, 10); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - ImGui::SliderInt("Duration", &Settings::application.transition.duration, 200, 5000, "%d ms"); + ImGui::SliderFloat("Duration", &Settings::application.transition.duration, TRANSITION_MIN_DURATION, TRANSITION_MAX_DURATION, "%.1f s"); if (ImGuiToolkit::ButtonIcon(9, 1)) Settings::application.transition.profile = 0; ImGui::SameLine(0, 10); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::Combo("Curve", &Settings::application.transition.profile, "Linear\0Quadratic\0IExponent\0"); - if ( ImGui::Button( ICON_FA_ARROW_CIRCLE_RIGHT " Start", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) { + if ( ImGui::Button( ICON_FA_PLAY " Start", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) { TransitionView *tv = static_cast(Mixer::manager().view(View::TRANSITION)); if (tv) tv->play(); } diff --git a/View.cpp b/View.cpp index fc547c0..5705ff3 100644 --- a/View.cpp +++ b/View.cpp @@ -4,6 +4,10 @@ #include #include + +#include "imgui.h" +#include "ImGuiToolkit.h" + // memmove #include #include @@ -730,19 +734,23 @@ TransitionView::TransitionView() : View(TRANSITION), transition_source_(nullptr) gradient_ = new Switch; gradient_->attach(new ImageSurface("images/gradient_0.png")); gradient_->attach(new ImageSurface("images/gradient_1.png")); - gradient_->scale_ = glm::vec3(0.502f, 0.008f, 1.f); - gradient_->translation_ = glm::vec3(-0.5f, -0.007f, -0.01f); + gradient_->scale_ = glm::vec3(0.501f, 0.006f, 1.f); + gradient_->translation_ = glm::vec3(-0.5f, -0.005f, -0.01f); scene.fg()->attach(gradient_); - Mesh *horizontal_line = new Mesh("mesh/h_line.ply"); - horizontal_line->shader()->color = glm::vec4( COLOR_TRANSITION_LINES, 0.9f ); - scene.fg()->attach(horizontal_line); +// Mesh *horizontal_line = new Mesh("mesh/h_line.ply"); +// horizontal_line->shader()->color = glm::vec4( COLOR_TRANSITION_LINES, 0.9f ); +// scene.fg()->attach(horizontal_line); + mark_1s_ = new Mesh("mesh/h_mark.ply"); + mark_1s_->translation_ = glm::vec3(-1.f, -0.01f, 0.0f); + mark_1s_->shader()->color = glm::vec4( COLOR_TRANSITION_LINES, 0.9f ); + scene.fg()->attach(mark_1s_); - mark_ = new Mesh("mesh/h_mark.ply"); -// mark_->translation_ = glm::vec3(-0.5f, 0.f, 0.0f); -// mark_->shader()->color = glm::vec4( COLOR_TRANSITION_LINES, 0.9f ); -// mark_->visible_ = false; -// scene.fg()->attach(mark_); + mark_100ms_ = new Mesh("mesh/h_mark.ply"); + mark_100ms_->translation_ = glm::vec3(-1.f, -0.01f, 0.0f); + mark_100ms_->scale_ = glm::vec3(0.5f, 0.5f, 0.0f); + mark_100ms_->shader()->color = glm::vec4( COLOR_TRANSITION_LINES, 0.9f ); + scene.fg()->attach(mark_100ms_); // move the whole forground below the icons scene.fg()->translation_ = glm::vec3(0.f, -0.11f, 0.0f); @@ -774,6 +782,9 @@ void TransitionView::update(float dt) // change alpha of session: identical coordinates in Mixing View transition_source_->group(View::MIXING)->translation_.x = CLAMP(d, -1.f, 0.f); transition_source_->group(View::MIXING)->translation_.y = 0.f; + + // reset / no fading + Mixer::manager().session()->setFading( 0.f ); } // fade to black else @@ -782,7 +793,7 @@ void TransitionView::update(float dt) transition_source_->group(View::MIXING)->translation_.x = d < -0.5f ? -1.f : 0.f; transition_source_->group(View::MIXING)->translation_.y = 0.f; - // crossing the fade : fade-out [-1.0 -0.5], fade-in [-0.5 0.0] + // fade to black at 50% : fade-out [-1.0 -0.5], fade-in [-0.5 0.0] float f = ABS(2.f * d + 1.f); // linear // d = ( 2 * d + 1.f); // quadratic // d *= d; @@ -825,6 +836,38 @@ void TransitionView::draw() // draw scene of this view scene.root()->draw(glm::identity(), Rendering::manager().Projection()); + // 100ms tic marks + int n = static_cast( Settings::application.transition.duration / 0.1f ); + glm::mat4 T = glm::translate(glm::identity(), glm::vec3( 1.f / n, 0.f, 0.f)); + DrawVisitor dv(mark_100ms_, Rendering::manager().Projection()); + dv.loop(n+1, T); + scene.accept(dv); + + // 1s tic marks + int N = static_cast( Settings::application.transition.duration ); + T = glm::translate(glm::identity(), glm::vec3( 10.f / n, 0.f, 0.f)); + DrawVisitor dv2(mark_1s_, Rendering::manager().Projection()); + dv2.loop(N+1, T); + scene.accept(dv2); + + // display interface duration + glm::vec2 P = Rendering::manager().project(glm::vec3(-0.03f, -0.14f, 0.f), scene.root()->transform_); + ImGui::SetNextWindowPos(ImVec2(P.x, P.y), ImGuiCond_Always); + if (ImGui::Begin("##Transition", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground + | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings + | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + { + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); + ImGui::SetNextItemWidth(100.f); + ImGui::DragFloat("##nolabel", &Settings::application.transition.duration, + 0.1f, TRANSITION_MIN_DURATION, TRANSITION_MAX_DURATION, "%.1f s"); + ImGui::SameLine(); + if ( ImGui::Button(ICON_FA_PLAY) ) + play(); + ImGui::PopFont(); + ImGui::End(); + } + } void TransitionView::attach(SessionSource *ts) @@ -865,21 +908,25 @@ Session *TransitionView::detach() void TransitionView::zoom (float factor) { - float d = transition_source_->group(View::TRANSITION)->translation_.x; - d += 0.1f * factor; - transition_source_->group(View::TRANSITION)->translation_.x = CLAMP(d, -1.f, 0.f); + if (transition_source_ != nullptr) { + float d = transition_source_->group(View::TRANSITION)->translation_.x; + d += 0.1f * factor; + transition_source_->group(View::TRANSITION)->translation_.x = CLAMP(d, -1.f, 0.f); + } } std::pair TransitionView::pick(glm::vec2 P) { std::pair pick = View::pick(P); - // start animation when clic on target - if (pick.first == output_surface_) - play(); - // otherwise cancel animation - else - transition_source_->group(View::TRANSITION)->clearCallbacks(); + if (transition_source_ != nullptr) { + // start animation when clic on target + if (pick.first == output_surface_) + play(); + // otherwise cancel animation + else + transition_source_->group(View::TRANSITION)->clearCallbacks(); + } return pick; } @@ -890,13 +937,13 @@ void TransitionView::play() if (transition_source_ != nullptr) { float time = CLAMP(- transition_source_->group(View::TRANSITION)->translation_.x, 0.f, 1.f); - time *= float(Settings::application.transition.duration); + time += 0.2; // extra time to reach transition + time *= Settings::application.transition.duration * 1000.f; // if remaining time is more than 50ms if (time > 50.f) { // start animation MoveToCallback *anim = new MoveToCallback(glm::vec3(0.4f, 0.0, 0.0), time); transition_source_->group(View::TRANSITION)->update_callbacks_.push_back(anim); - // TODO : add time for doing the last 0.4 of translation } // otherwise finish animation else diff --git a/View.h b/View.h index 7c65b5d..13b3989 100644 --- a/View.h +++ b/View.h @@ -167,7 +167,7 @@ public: private: class Surface *output_surface_; - class Mesh *mark_; + class Mesh *mark_100ms_, *mark_1s_; Switch *gradient_; SessionSource *transition_source_; }; diff --git a/Visitor.h b/Visitor.h index 80a4f53..11738a1 100644 --- a/Visitor.h +++ b/Visitor.h @@ -38,9 +38,9 @@ public: virtual void visit (Node&) = 0; virtual void visit (Primitive&) = 0; virtual void visit (Group&) = 0; + virtual void visit (Switch&) = 0; // not mandatory for all others - virtual void visit (Switch&) {} virtual void visit (Surface&) {} virtual void visit (ImageSurface&) {} virtual void visit (MediaSurface&) {} diff --git a/defines.h b/defines.h index 0f7c5fa..73ad340 100644 --- a/defines.h +++ b/defines.h @@ -38,6 +38,8 @@ #define LAYER_MIN_SCALE 0.4f #define LAYER_MAX_SCALE 1.7f #define TRANSITION_DEFAULT_SCALE 3.0f +#define TRANSITION_MIN_DURATION 0.2f +#define TRANSITION_MAX_DURATION 10.f #define IMGUI_TITLE_MAINWINDOW ICON_FA_CIRCLE_NOTCH " vimix" #define IMGUI_TITLE_MEDIAPLAYER ICON_FA_FILM " Media Player" diff --git a/rsc/images/gradient_0.png b/rsc/images/gradient_0.png index 01d7749..9a1f2b8 100644 Binary files a/rsc/images/gradient_0.png and b/rsc/images/gradient_0.png differ diff --git a/rsc/images/gradient_1.png b/rsc/images/gradient_1.png index f3b3b45..50fdacb 100644 Binary files a/rsc/images/gradient_1.png and b/rsc/images/gradient_1.png differ