mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 23:40:02 +01:00
BugFix Acceptable behavior for media Player timeline panel
First acceptable implementation of timeline editing panel, with cut and fading modes and UI.
This commit is contained in:
Binary file not shown.
@@ -697,17 +697,6 @@ bool EditTimeline(const char *label,
|
||||
hovered = true;
|
||||
cursor_dot = false;
|
||||
|
||||
// if a timing is given, ignore cursor timing
|
||||
if (pl->timing != GST_CLOCK_TIME_NONE) {
|
||||
// replace drop time by payload timing
|
||||
// time = pl->timing;
|
||||
// // replace mouse coordinate by position from time
|
||||
// size_t index = ((pl->timing - begin) * static_cast<guint64>(MAX_TIMELINE_ARRAY)) / end ;
|
||||
// double x = static_cast<double>(index) / static_cast<double>(MAX_TIMELINE_ARRAY);
|
||||
// mouse_pos_in_canvas.x = ( x * (size.x - 2.f * _h_space)) + _h_space;
|
||||
|
||||
}
|
||||
|
||||
// dragged onto the timeline : apply changes on local copy
|
||||
switch (pl->action) {
|
||||
case TimelinePayload::CUT:
|
||||
@@ -751,7 +740,7 @@ bool EditTimeline(const char *label,
|
||||
}
|
||||
|
||||
// dropped into the timeline : confirm change to timeline
|
||||
if (ImGui::AcceptDragDropPayload("DND_TIMELINE")) {
|
||||
if (ImGui::AcceptDragDropPayload("DND_TIMELINE", ImGuiDragDropFlags_AcceptNoDrawDefaultRect)) {
|
||||
// copy temporary timeline into given timeline
|
||||
*tl = _tl;
|
||||
// like a mouse release
|
||||
@@ -2271,75 +2260,45 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
}
|
||||
|
||||
///
|
||||
/// SEPARATOR
|
||||
/// SECTION WITH BUTTONS
|
||||
///
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::Text("|");
|
||||
|
||||
///
|
||||
/// Enter time or percentage of time
|
||||
///
|
||||
/// Enter time value for CUT
|
||||
target_time = MIN(target_time, tl->duration());
|
||||
|
||||
ImGui::SameLine(0, 0);
|
||||
ImVec2 draw_pos = ImGui::GetCursorPos();
|
||||
ImGui::SetCursorPosY(ImGui::GetTextLineHeightWithSpacing() * 0.333 );
|
||||
|
||||
float w = gap_dialog_size.x - 4.f * ImGui::GetTextLineHeightWithSpacing() ;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 11));
|
||||
ImGui::SetNextItemWidth(w - draw_pos.x - IMGUI_SAME_LINE); // VARIABLE WIDTH
|
||||
ImGuiToolkit::InputTime("##Time", &target_time);
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
// ImGui::SetCursorPos(ImVec2(draw_pos.x, draw_pos.y + 35));
|
||||
// ImGuiToolkit::HSliderUInt64("#SliderTime", ImVec2(180, 14), &target_time, 0, tl->duration());
|
||||
|
||||
// static int p = 5;
|
||||
// ImGuiToolkit::HSliderInt("#toto", ImVec2(140, 14), &p, 1, 9);
|
||||
// if (ImGui::IsItemActive()) {
|
||||
// ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
||||
// ImGui::SetTooltip("%d%%", p * 10);
|
||||
// ImGui::PopFont();
|
||||
// }
|
||||
// if (ImGui::IsItemDeactivatedAfterEdit()){
|
||||
|
||||
// }
|
||||
|
||||
// ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
// ImVec2 draw_pos = ImGui::GetCursorPos() + ImVec2(0, v_space_);
|
||||
// ImGui::SetCursorPos(ImVec2(gap_dialog_size.x - ImGui::GetTextLineHeightWithSpacing()- IMGUI_SAME_LINE,
|
||||
// draw_pos.y));
|
||||
// static bool percentage = false;
|
||||
// ImGuiToolkit::IconToggle(19, 10, 3, 7, &percentage);
|
||||
// ImGui::SetCursorPos(draw_pos);
|
||||
// if (percentage) {
|
||||
// int target_percent = (int) ( (100 * target_time) / tl->duration() );
|
||||
// ImGui::SetNextItemWidth(-ImGui::GetTextLineHeightWithSpacing());
|
||||
// ImGui::DragInt("##percent", &target_percent, 1, 0, 100);
|
||||
// target_time = (tl->duration() * (guint64) target_percent) / 100;
|
||||
// }
|
||||
// else {
|
||||
// ImGui::SetNextItemWidth(-ImGui::GetTextLineHeightWithSpacing());
|
||||
// ImGuiToolkit::InputTime("##Time", &target_time);
|
||||
// }
|
||||
|
||||
// Action buttons
|
||||
/// CUT LEFT TIME
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
ImGui::SetCursorPos( ImVec2(w, draw_pos.y));
|
||||
|
||||
// ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
if (ImGuiToolkit::ButtonIcon(17, 3, "Cut left at given time")) {
|
||||
tl->cut(target_time, true);
|
||||
tl->refresh();
|
||||
oss << ": Timeline cut";
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
|
||||
/// CUT RIGHT TIME
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
if (ImGuiToolkit::ButtonIcon(18, 3, "Cut right at given time")){
|
||||
tl->cut(target_time, false);
|
||||
tl->refresh();
|
||||
oss << ": Timeline cut";
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
|
||||
/// CLEAR
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
if (ImGuiToolkit::ButtonIcon(11, 14, "Clear all gaps"))
|
||||
if (ImGuiToolkit::ButtonIcon(11, 14, "Clear all gaps")) {
|
||||
tl->clearGaps();
|
||||
oss << ": Timeline clear gaps";
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
@@ -2365,9 +2324,7 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
{14, 12}};
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
// ImGuiToolkit::ButtonIconMultistate(options_curve, ¤t_curve, tooltips_curve);
|
||||
ImGuiToolkit::IconMultistate(options_curve, ¤t_curve, tooltips_curve);
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
///
|
||||
@@ -2392,12 +2349,6 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
DragButtonIcon(9, 10, "Drop in timeline to insert\nSharp fade in & out",
|
||||
TimelinePayload(TimelinePayload::FADE_IN_OUT, d*GST_MSECOND, Timeline::FADING_SHARP));
|
||||
///
|
||||
/// FADE OUT & IN
|
||||
///
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
DragButtonIcon(10, 10, "Drop in timeline to insert\nSharp fade out & in",
|
||||
TimelinePayload(TimelinePayload::FADE_OUT_IN, d*GST_MSECOND, Timeline::FADING_SHARP));
|
||||
}
|
||||
///
|
||||
/// FADE LINEAR
|
||||
@@ -2421,12 +2372,6 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
DragButtonIcon(7, 10, "Drop in timeline to insert\nLinear fade in & out",
|
||||
TimelinePayload(TimelinePayload::FADE_IN_OUT, d*GST_MSECOND, Timeline::FADING_LINEAR));
|
||||
///
|
||||
/// FADE OUT & IN
|
||||
///
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
DragButtonIcon(8, 10, "Drop in timeline to insert\nLinear fade out & in",
|
||||
TimelinePayload(TimelinePayload::FADE_OUT_IN, d*GST_MSECOND, Timeline::FADING_LINEAR));
|
||||
}
|
||||
///
|
||||
/// FADE SMOOTH
|
||||
@@ -2450,89 +2395,70 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
DragButtonIcon(17, 10, "Drop in timeline to insert\nSmooth fade in & out",
|
||||
TimelinePayload(TimelinePayload::FADE_IN_OUT, d*GST_MSECOND, Timeline::FADING_SMOOTH));
|
||||
///
|
||||
/// FADE OUT & IN
|
||||
///
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
DragButtonIcon(18, 10, "Drop in timeline to insert\nSmooth fade out & in",
|
||||
TimelinePayload(TimelinePayload::FADE_OUT_IN, d*GST_MSECOND, Timeline::FADING_SMOOTH));
|
||||
|
||||
}
|
||||
|
||||
// float md = 10000;
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
|
||||
ImVec2 draw_pos = ImGui::GetCursorPos();
|
||||
float w = gap_dialog_size.x - 3.f * ImGui::GetTextLineHeightWithSpacing() - IMGUI_SAME_LINE;
|
||||
ImGui::SetNextItemWidth(w - draw_pos.x);
|
||||
///
|
||||
/// DURATION SLIDER
|
||||
///
|
||||
float seconds = (float) d / 1000.f;
|
||||
float maxi = (float) GST_TIME_AS_MSECONDS(tl->duration()) / 1000.f;
|
||||
float w = gap_dialog_size.x - 4.f * ImGui::GetTextLineHeightWithSpacing();
|
||||
|
||||
if (current_curve > 0) {
|
||||
// ImGuiToolkit::SliderTiming("##Duration", &d, 60, md+50, 50, "Auto");
|
||||
// if (d > md) d = UINT_MAX;
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
ImVec2 draw_pos = ImGui::GetCursorPos();
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_MONO);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 11));
|
||||
ImGui::SetNextItemWidth(w - draw_pos.x);
|
||||
if (ImGui::SliderFloat("##DurationFading",
|
||||
&seconds,
|
||||
0.05f,
|
||||
60.f,
|
||||
seconds < 59.5f ? "%.2f s" : "Auto")) {
|
||||
if (seconds > 59.5f)
|
||||
maxi,
|
||||
d < UINT_MAX ? "%.2f s" : "Auto")) {
|
||||
if (seconds > maxi - 0.05f)
|
||||
d = UINT_MAX;
|
||||
else
|
||||
d = (uint) floor(seconds * 1000);
|
||||
}
|
||||
} else {
|
||||
// ImGui::TextDisabled("%.2f s", seconds);
|
||||
static char dummy_str[512];
|
||||
if (seconds < 59.5f )
|
||||
snprintf(dummy_str, 512, "%.2f s", seconds);
|
||||
else
|
||||
snprintf(dummy_str, 512, "Auto");
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f));
|
||||
ImGui::InputText("##disabledduration", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Action buttons
|
||||
///
|
||||
/// SECTION WITH BUTTONS
|
||||
///
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
|
||||
///
|
||||
/// SEPARATOR
|
||||
///
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::SetCursorPos( ImVec2(w, draw_pos.y));
|
||||
ImGui::Text("|");
|
||||
|
||||
// action smooth
|
||||
/// SMOOTH Curve
|
||||
static int _actionsmooth = 0;
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::PushButtonRepeat(true);
|
||||
if (ImGuiToolkit::ButtonIcon(2, 7, "Apply smoothing filter")){
|
||||
tl->smoothFading( 5 );
|
||||
tl->smoothFading( 15 );
|
||||
++_actionsmooth;
|
||||
}
|
||||
ImGui::PopButtonRepeat();
|
||||
if (_actionsmooth > 0 && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
||||
oss << ": Timeline opacity smooth";
|
||||
oss << ": Timeline smooth curve";
|
||||
Action::manager().store(oss.str());
|
||||
_actionsmooth = 0;
|
||||
}
|
||||
|
||||
/// CLEANUP
|
||||
ImGui::SameLine(0, 0);
|
||||
if (ImGuiToolkit::ButtonIcon(3, 7, "Clean curve in gaps")) {
|
||||
tl->autoFadeInGaps();
|
||||
oss << ": Timeline cleanup curve";
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
|
||||
// ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
// ImGui::SetNextItemWidth(140); // TODO VARIABLE WIDTH
|
||||
// ImVec2 draw_pos = ImGui::GetCursorPos();
|
||||
// ImGui::SetCursorPosY(draw_pos.y + 8); // TODO VARIABLE H
|
||||
// ImGuiToolkit::InputTime("##Time", &target_time);
|
||||
|
||||
|
||||
///
|
||||
/// CLEAR
|
||||
///
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
if (ImGuiToolkit::ButtonIcon(11, 14, "Clear Fading curve"))
|
||||
ImGui::SameLine(0, 0);
|
||||
if (ImGuiToolkit::ButtonIcon(11, 14, "Clear fading curve")){
|
||||
tl->clearFading();
|
||||
oss << ": Timeline clear fading";
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
|
||||
@@ -40,6 +40,10 @@ float linestep(size_t edge0, size_t edge1, size_t i) {
|
||||
return x;
|
||||
}
|
||||
|
||||
float sharpstep(size_t edge0, size_t edge1, size_t i) {
|
||||
float x = clamp( static_cast<float>(i - edge0) / static_cast<float>(edge1 - edge0));
|
||||
return fabs(x)<1.f ? 0.f : 1.f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -545,7 +549,6 @@ void Timeline::clearFading()
|
||||
fading_array_allones_ = true;
|
||||
}
|
||||
|
||||
|
||||
bool Timeline::fadingIsClear()
|
||||
{
|
||||
if (fading_array_changed_) {
|
||||
@@ -696,18 +699,16 @@ void Timeline::fadeOut(const GstClockTime from, const GstClockTime duration, Fad
|
||||
N = 2;
|
||||
}
|
||||
|
||||
// linear fade out starts at s
|
||||
// fade out starts at s
|
||||
size_t i = s;
|
||||
// float val = fadingArray_[s];
|
||||
for (; i <= s+n; ++i) {
|
||||
const float x = static_cast<float>(e-i) / static_cast<float>(n);
|
||||
// const float x = 1.f - static_cast<float>(i-s) / static_cast<float>(n);
|
||||
if (curve==FADING_LINEAR)
|
||||
fadingArray_[i] = x;
|
||||
fadingArray_[i] = 1.f - linestep(s, s+n, i);
|
||||
else if (curve==FADING_SMOOTH)
|
||||
fadingArray_[i] = 1.f - smootherstep(s, s+n, i);
|
||||
else
|
||||
fadingArray_[i] = 0.f;
|
||||
fadingArray_[i] = sharpstep(s, s+n, i);
|
||||
// fadingArray_[i] *= val;
|
||||
}
|
||||
fading_array_changed_ = true;
|
||||
@@ -746,18 +747,16 @@ void Timeline::fadeIn(const GstClockTime to, const GstClockTime duration, Fading
|
||||
// calculate size of the smooth transition in [s e] interval
|
||||
const size_t n = MIN( e-s, N );
|
||||
|
||||
// linear fade in ends at e
|
||||
// fade in ends at e
|
||||
size_t i = e-n;
|
||||
// float val = fadingArray_[e];
|
||||
for (; i < e; ++i) {
|
||||
// const float x = static_cast<float>(i-s) / static_cast<float>(n);
|
||||
const float x = 1.f - static_cast<float>(e - i) / static_cast<float>(n);
|
||||
if (curve==FADING_LINEAR)
|
||||
fadingArray_[i] = x;
|
||||
fadingArray_[i] = linestep(e-n, e, i);
|
||||
else if (curve==FADING_SMOOTH)
|
||||
fadingArray_[i] = smootherstep(e-n, e, i);
|
||||
else
|
||||
fadingArray_[i] = 0.f;
|
||||
fadingArray_[i] = sharpstep(e-n, e, i);
|
||||
// fadingArray_[i] *= val;
|
||||
}
|
||||
fading_array_changed_ = true;
|
||||
@@ -771,12 +770,7 @@ void Timeline::fadeInOutRange(const GstClockTime t, const GstClockTime duration,
|
||||
// find cuts at left and right of given time
|
||||
for (auto g = gaps_.begin(); g != gaps_.end(); g++) {
|
||||
if (g->begin < t) {
|
||||
if (g->end > t) {
|
||||
// inside a gap
|
||||
range.begin = g->begin;
|
||||
range.end = g->end;
|
||||
break;
|
||||
} else {
|
||||
if (g->end < t) {
|
||||
// after a gap
|
||||
range.begin = g->end;
|
||||
}
|
||||
@@ -794,23 +788,24 @@ void Timeline::fadeInOutRange(const GstClockTime t, const GstClockTime duration,
|
||||
const size_t e = (range.end * MAX_TIMELINE_ARRAY) / timing_.end;
|
||||
|
||||
// get index of time in section
|
||||
const size_t m = (t * MAX_TIMELINE_ARRAY) / timing_.end;
|
||||
|
||||
size_t l = m;
|
||||
size_t r = m;
|
||||
size_t l = ( MIN(t, range.begin + duration) * MAX_TIMELINE_ARRAY) / timing_.end;
|
||||
size_t r = ( MAX(t, range.end - duration) * MAX_TIMELINE_ARRAY) / timing_.end;
|
||||
|
||||
// if duration too short for a linear or smooth
|
||||
if (duration < 2 * step_) {
|
||||
curve = FADING_SHARP;
|
||||
}
|
||||
// if duration allows to fade in and out
|
||||
else if (2 * duration < range.duration()) {
|
||||
l = ( (range.begin + duration) * MAX_TIMELINE_ARRAY) / timing_.end;
|
||||
r = ( (range.end - duration) * MAX_TIMELINE_ARRAY) / timing_.end;
|
||||
else if (duration > range.duration()) {
|
||||
if (curve == FADING_SHARP) {
|
||||
l = s+1;
|
||||
r = e-1;
|
||||
}
|
||||
else
|
||||
l = r = (t * MAX_TIMELINE_ARRAY) / timing_.end;
|
||||
}
|
||||
|
||||
// fill values inside range
|
||||
for (size_t k = s; k < e; ++k) {
|
||||
for (size_t k = s; k <= e; ++k) {
|
||||
|
||||
if (curve == FADING_LINEAR){
|
||||
if (k<l)
|
||||
@@ -829,13 +824,20 @@ void Timeline::fadeInOutRange(const GstClockTime t, const GstClockTime duration,
|
||||
fadingArray_[k] = in_and_out ? 1.f - smootherstep(r, e, k) : smootherstep(r, e, k);
|
||||
}
|
||||
else // curve == FADING_SHARP
|
||||
fadingArray_[k] = in_and_out;
|
||||
{
|
||||
if (k<l)
|
||||
fadingArray_[k] = in_and_out ? 0.f : 1.f ;
|
||||
else if (k<r)
|
||||
fadingArray_[k] = in_and_out ? 1.f : 0.f;
|
||||
else
|
||||
fadingArray_[k] = in_and_out ? 0.f : 1.f ;
|
||||
}
|
||||
}
|
||||
fading_array_changed_ = true;
|
||||
}
|
||||
|
||||
|
||||
bool Timeline::autoCut()
|
||||
bool Timeline::autoGapInFade()
|
||||
{
|
||||
bool changed = false;
|
||||
for (long i = 0; i < MAX_TIMELINE_ARRAY; ++i) {
|
||||
@@ -852,6 +854,21 @@ bool Timeline::autoCut()
|
||||
return changed;
|
||||
}
|
||||
|
||||
void Timeline::autoFadeInGaps()
|
||||
{
|
||||
for (auto it = gaps_.begin(); it != gaps_.end(); ++it)
|
||||
{
|
||||
GstClockTime d = timing_.duration();
|
||||
size_t s = ( (*it).begin * MAX_TIMELINE_ARRAY ) / d;
|
||||
size_t e = ( (*it).end * MAX_TIMELINE_ARRAY ) / d;
|
||||
|
||||
// fill with 1 where there is a gap
|
||||
for (size_t i = s; i < e + 1 ; ++i) {
|
||||
fadingArray_[i] = i > 0 ? fadingArray_[i-1] : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Timeline::updateGapsFromArray(float *array, size_t array_size)
|
||||
{
|
||||
// reset gaps
|
||||
|
||||
@@ -165,7 +165,10 @@ public:
|
||||
void fadeIn(const GstClockTime from, const GstClockTime duration, FadingCurve curve = FADING_SHARP);
|
||||
void fadeOut(const GstClockTime to, const GstClockTime duration, FadingCurve curve = FADING_SHARP);
|
||||
void fadeInOutRange(const GstClockTime t, const GstClockTime duration, bool in_and_out, FadingCurve curve = FADING_SHARP);
|
||||
bool autoCut();
|
||||
|
||||
// link Fading and Gaps
|
||||
bool autoGapInFade();
|
||||
void autoFadeInGaps();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user