mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-18 21:59:58 +01:00
Add Alpha fading mode to media player timeline
Fading color (to black) is not useful for media with transparency; there fading of alpha is necessary; the fading mode allows to select fade color or fade alpha. Also the source control window had to be adapted, with a checkerboard to show the alpha effect. The cropping of the image in control window was also fixed.
This commit is contained in:
@@ -72,6 +72,7 @@ MediaPlayer::MediaPlayer()
|
|||||||
video_filter_available_ = true;
|
video_filter_available_ = true;
|
||||||
position_ = GST_CLOCK_TIME_NONE;
|
position_ = GST_CLOCK_TIME_NONE;
|
||||||
loop_ = LoopMode::LOOP_REWIND;
|
loop_ = LoopMode::LOOP_REWIND;
|
||||||
|
fading_mode_ = FadingMode::FADING_COLOR;
|
||||||
|
|
||||||
// default audio disabled
|
// default audio disabled
|
||||||
audio_enabled_ = false;
|
audio_enabled_ = false;
|
||||||
|
|||||||
@@ -206,8 +206,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
Timeline *timeline();
|
Timeline *timeline();
|
||||||
void setTimeline(const Timeline &tl);
|
void setTimeline(const Timeline &tl);
|
||||||
|
/**
|
||||||
|
* Get fading value at current time
|
||||||
|
* */
|
||||||
float currentTimelineFading();
|
float currentTimelineFading();
|
||||||
|
/**
|
||||||
|
* Get fading mode
|
||||||
|
* */
|
||||||
|
typedef enum { FADING_COLOR = 0, FADING_ALPHA = 1 } FadingMode;
|
||||||
|
FadingMode timelineFadingMode() { return fading_mode_; }
|
||||||
|
/**
|
||||||
|
* Set fading mode
|
||||||
|
* */
|
||||||
|
void setTimelineFadingMode(FadingMode m) { fading_mode_ = m; }
|
||||||
/**
|
/**
|
||||||
* Get framerate of the media
|
* Get framerate of the media
|
||||||
* */
|
* */
|
||||||
@@ -314,6 +325,7 @@ private:
|
|||||||
// general properties of media
|
// general properties of media
|
||||||
MediaInfo media_;
|
MediaInfo media_;
|
||||||
Timeline timeline_;
|
Timeline timeline_;
|
||||||
|
FadingMode fading_mode_;
|
||||||
std::future<MediaInfo> discoverer_;
|
std::future<MediaInfo> discoverer_;
|
||||||
|
|
||||||
// GST & Play status
|
// GST & Play status
|
||||||
|
|||||||
@@ -197,7 +197,10 @@ void MediaSource::render()
|
|||||||
// NB: this also applies the color correction shader
|
// NB: this also applies the color correction shader
|
||||||
renderbuffer_->begin();
|
renderbuffer_->begin();
|
||||||
// apply fading
|
// apply fading
|
||||||
texturesurface_->shader()->color = glm::vec4( glm::vec3(mediaplayer_->currentTimelineFading()), 1.f);
|
if (mediaplayer_->timelineFadingMode() != MediaPlayer::FADING_ALPHA)
|
||||||
|
texturesurface_->shader()->color = glm::vec4( glm::vec3(mediaplayer_->currentTimelineFading()), 1.f);
|
||||||
|
else
|
||||||
|
texturesurface_->shader()->color = glm::vec4( glm::vec3(1.f), mediaplayer_->currentTimelineFading());
|
||||||
texturesurface_->draw(glm::identity<glm::mat4>(), renderbuffer_->projection());
|
texturesurface_->draw(glm::identity<glm::mat4>(), renderbuffer_->projection());
|
||||||
renderbuffer_->end();
|
renderbuffer_->end();
|
||||||
ready_ = true;
|
ready_ = true;
|
||||||
|
|||||||
@@ -912,6 +912,9 @@ void SessionLoader::visit(MediaPlayer &n)
|
|||||||
if (fadingselement) {
|
if (fadingselement) {
|
||||||
XMLElement* array = fadingselement->FirstChildElement("array");
|
XMLElement* array = fadingselement->FirstChildElement("array");
|
||||||
XMLElementDecodeArray(array, tl.fadingArray(), MAX_TIMELINE_ARRAY * sizeof(float));
|
XMLElementDecodeArray(array, tl.fadingArray(), MAX_TIMELINE_ARRAY * sizeof(float));
|
||||||
|
uint mode = 0;
|
||||||
|
fadingselement->QueryUnsignedAttribute("mode", &mode);
|
||||||
|
n.setTimelineFadingMode((MediaPlayer::FadingMode) mode);
|
||||||
}
|
}
|
||||||
n.setTimeline(tl);
|
n.setTimeline(tl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -465,6 +465,7 @@ void SessionVisitor::visit(MediaPlayer &n)
|
|||||||
fadingelement->InsertEndChild(array);
|
fadingelement->InsertEndChild(array);
|
||||||
timelineelement->InsertEndChild(fadingelement);
|
timelineelement->InsertEndChild(fadingelement);
|
||||||
newelement->InsertEndChild(timelineelement);
|
newelement->InsertEndChild(timelineelement);
|
||||||
|
fadingelement->SetAttribute("mode", (uint) n.timelineFadingMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlCurrent_->InsertEndChild(newelement);
|
xmlCurrent_->InsertEndChild(newelement);
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
#include "SystemToolkit.h"
|
#include "SystemToolkit.h"
|
||||||
#include "DialogToolkit.h"
|
#include "DialogToolkit.h"
|
||||||
#include "GstToolkit.h"
|
#include "GstToolkit.h"
|
||||||
|
#include "Resource.h"
|
||||||
|
#include "PatternSource.h"
|
||||||
|
|
||||||
#include "Mixer.h"
|
#include "Mixer.h"
|
||||||
#include "CloneSource.h"
|
#include "CloneSource.h"
|
||||||
@@ -43,6 +45,8 @@
|
|||||||
|
|
||||||
#include "SourceControlWindow.h"
|
#include "SourceControlWindow.h"
|
||||||
|
|
||||||
|
#define CHECKER_RESOLUTION 6000
|
||||||
|
class Stream *checker_background_ = new Stream;
|
||||||
void DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider = false, bool withinspector = false);
|
void DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider = false, bool withinspector = false);
|
||||||
ImRect DrawSourceWithSlider(Source *s, ImVec2 top, ImVec2 rendersize, bool with_inspector);
|
ImRect DrawSourceWithSlider(Source *s, ImVec2 top, ImVec2 rendersize, bool with_inspector);
|
||||||
|
|
||||||
@@ -59,6 +63,14 @@ SourceControlWindow::SourceControlWindow() : WorkspaceWindow("SourceController")
|
|||||||
info_.setExtendedStringMode();
|
info_.setExtendedStringMode();
|
||||||
|
|
||||||
captureFolderDialog = new DialogToolkit::OpenFolderDialog("Capture frame Location");
|
captureFolderDialog = new DialogToolkit::OpenFolderDialog("Capture frame Location");
|
||||||
|
|
||||||
|
// initialize checkerboard background texture
|
||||||
|
checker_background_->open("videotestsrc pattern=checkers-8 ! "
|
||||||
|
"videobalance saturation=0 contrast=1",
|
||||||
|
CHECKER_RESOLUTION, CHECKER_RESOLUTION);
|
||||||
|
checker_background_->play(true);
|
||||||
|
while (checker_background_->texture() == Resource::getTextureBlack())
|
||||||
|
checker_background_->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -401,6 +413,13 @@ void SourceControlWindow::Render()
|
|||||||
Action::manager().store(oss.str());
|
Action::manager().store(oss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _alpha_fading = mediaplayer_active_->timelineFadingMode()
|
||||||
|
== MediaPlayer::FADING_ALPHA;
|
||||||
|
if (ImGui::MenuItem(ICON_FA_FONT " Alpha fading", NULL, &_alpha_fading)) {
|
||||||
|
mediaplayer_active_->setTimelineFadingMode(
|
||||||
|
_alpha_fading ? MediaPlayer::FADING_ALPHA : MediaPlayer::FADING_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem(LABEL_EDIT_FADING))
|
if (ImGui::MenuItem(LABEL_EDIT_FADING))
|
||||||
mediaplayer_edit_fading_ = true;
|
mediaplayer_edit_fading_ = true;
|
||||||
|
|
||||||
@@ -1010,9 +1029,19 @@ void DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider,
|
|||||||
{
|
{
|
||||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||||
|
|
||||||
|
// pre-draw background with checkerboard pattern
|
||||||
|
ImGui::Image((void*)(uintptr_t) checker_background_->texture(), framesize,
|
||||||
|
ImVec2(0,0), ImVec2(framesize.x/CHECKER_RESOLUTION, framesize.y/CHECKER_RESOLUTION));
|
||||||
|
|
||||||
|
// get back to top image corner to draw
|
||||||
|
ImGui::SetCursorScreenPos(top_image);
|
||||||
|
|
||||||
// info on source
|
// info on source
|
||||||
CloneSource *cloned = dynamic_cast<CloneSource *>(s);
|
CloneSource *cloned = dynamic_cast<CloneSource *>(s);
|
||||||
|
|
||||||
|
// 100% opacity for the image (ensure true colors)
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.f);
|
||||||
|
|
||||||
// draw pre and post-processed parts if necessary
|
// draw pre and post-processed parts if necessary
|
||||||
if (s->imageProcessingEnabled() || s->textureTransformed() || cloned != nullptr) {
|
if (s->imageProcessingEnabled() || s->textureTransformed() || cloned != nullptr) {
|
||||||
|
|
||||||
@@ -1027,8 +1056,14 @@ void DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider,
|
|||||||
//
|
//
|
||||||
// RIGHT of slider : post-processed image (after crop and color correction)
|
// RIGHT of slider : post-processed image (after crop and color correction)
|
||||||
//
|
//
|
||||||
ImVec2 cropsize = framesize * ImVec2 ( s->frame()->projectionSize().x, s->frame()->projectionSize().y);
|
glm::vec4 _crop = s->frame()->projectionArea();
|
||||||
ImVec2 croptop = (framesize - cropsize) * 0.5f;
|
ImVec2 cropsize = ImVec2(0.5f * (_crop[1] - _crop[0]),
|
||||||
|
0.5f * (_crop[2] - _crop[3]));
|
||||||
|
ImVec2 croptop = ImVec2(0.5f * (1.f + _crop[0]),
|
||||||
|
0.5f * (1.f - _crop[2]) );
|
||||||
|
cropsize = framesize * cropsize;
|
||||||
|
croptop = framesize * croptop;
|
||||||
|
|
||||||
// no overlap of slider with cropped area
|
// no overlap of slider with cropped area
|
||||||
if (slider.x < croptop.x) {
|
if (slider.x < croptop.x) {
|
||||||
// draw cropped area
|
// draw cropped area
|
||||||
@@ -1076,6 +1111,8 @@ void DrawSource(Source *s, ImVec2 framesize, ImVec2 top_image, bool withslider,
|
|||||||
if ( withinspector && ImGui::IsItemHovered() )
|
if ( withinspector && ImGui::IsItemHovered() )
|
||||||
DrawInspector(s->texture(), framesize, framesize, top_image);
|
DrawInspector(s->texture(), framesize, framesize, top_image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImRect DrawSourceWithSlider(Source *s, ImVec2 top, ImVec2 rendersize, bool with_inspector)
|
ImRect DrawSourceWithSlider(Source *s, ImVec2 top, ImVec2 rendersize, bool with_inspector)
|
||||||
@@ -1105,11 +1142,14 @@ ImRect DrawSourceWithSlider(Source *s, ImVec2 top, ImVec2 rendersize, bool with_
|
|||||||
const ImVec2 top_image = top + corner;
|
const ImVec2 top_image = top + corner;
|
||||||
ImGui::SetCursorScreenPos(top_image);
|
ImGui::SetCursorScreenPos(top_image);
|
||||||
|
|
||||||
|
// pre-draw background with checkerboard pattern
|
||||||
|
ImGui::Image((void*)(uintptr_t) checker_background_->texture(), framesize,
|
||||||
|
ImVec2(0,0), ImVec2(framesize.x/CHECKER_RESOLUTION, framesize.y/CHECKER_RESOLUTION));
|
||||||
|
|
||||||
|
// draw source
|
||||||
if (s->ready()) {
|
if (s->ready()) {
|
||||||
// 100% opacity for the image (ensure true colors)
|
ImGui::SetCursorScreenPos(top_image);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.f);
|
|
||||||
DrawSource(s, framesize, top_image, true, with_inspector);
|
DrawSource(s, framesize, top_image, true, with_inspector);
|
||||||
ImGui::PopStyleVar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ImRect( top_image, top_image + framesize);
|
return ImRect( top_image, top_image + framesize);
|
||||||
@@ -1643,14 +1683,14 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
|||||||
bottom += ImVec2(scrollwindow.x + 2.f, 0.f);
|
bottom += ImVec2(scrollwindow.x + 2.f, 0.f);
|
||||||
draw_list->AddRectFilled(bottom, bottom + ImVec2(slider_zoom_width, timeline_height_ -1.f), ImGui::GetColorU32(ImGuiCol_FrameBg));
|
draw_list->AddRectFilled(bottom, bottom + ImVec2(slider_zoom_width, timeline_height_ -1.f), ImGui::GetColorU32(ImGuiCol_FrameBg));
|
||||||
ImGui::SetCursorScreenPos(bottom + ImVec2(1.f, 0.f));
|
ImGui::SetCursorScreenPos(bottom + ImVec2(1.f, 0.f));
|
||||||
const char *tooltip[2] = {"Draw opacity tool", "Cut tool"};
|
const char *tooltip[2] = {"Fading draw tool", "Timeline cut tool"};
|
||||||
ImGuiToolkit::IconToggle(7,4,8,3, &Settings::application.widget.media_player_timeline_editmode, tooltip);
|
ImGuiToolkit::IconToggle(7,4,8,3, &Settings::application.widget.media_player_timeline_editmode, tooltip);
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(bottom + ImVec2(1.f, 0.5f * timeline_height_));
|
ImGui::SetCursorScreenPos(bottom + ImVec2(1.f, 0.5f * timeline_height_));
|
||||||
if (Settings::application.widget.media_player_timeline_editmode) {
|
if (Settings::application.widget.media_player_timeline_editmode) {
|
||||||
// action cut
|
// action cut
|
||||||
if (mediaplayer_active_->isPlaying()) {
|
if (mediaplayer_active_->isPlaying()) {
|
||||||
ImGuiToolkit::Indication("Pause video to enable cut options", 9, 3);
|
ImGuiToolkit::Indication("Pause to enable cut at cursor", 9, 3);
|
||||||
}
|
}
|
||||||
else if (ImGuiToolkit::IconButton(9, 3, "Cut at cursor")) {
|
else if (ImGuiToolkit::IconButton(9, 3, "Cut at cursor")) {
|
||||||
ImGui::OpenPopup("timeline_cut_context_menu");
|
ImGui::OpenPopup("timeline_cut_context_menu");
|
||||||
@@ -1676,7 +1716,7 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
|||||||
|
|
||||||
// action smooth
|
// action smooth
|
||||||
ImGui::PushButtonRepeat(true);
|
ImGui::PushButtonRepeat(true);
|
||||||
if (ImGuiToolkit::IconButton(13, 12, "Smooth")){
|
if (ImGuiToolkit::IconButton(13, 12, "Smooth fading curve")){
|
||||||
mediaplayer_active_->timeline()->smoothFading( 5 );
|
mediaplayer_active_->timeline()->smoothFading( 5 );
|
||||||
++_actionsmooth;
|
++_actionsmooth;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user