Bugfix timeline display array

This commit is contained in:
Bruno
2021-06-06 14:54:55 +02:00
parent d1841f2863
commit 45653b52b5
4 changed files with 68 additions and 51 deletions

View File

@@ -475,8 +475,9 @@ bool ImGuiToolkit::TimelineSlider(const char* label, guint64 *time, guint64 star
ImRect slider_bbox( timeline_bbox.GetTL() + ImVec2(-cursor_width + 2.f, cursor_width + 4.f ), timeline_bbox.GetBR() + ImVec2( cursor_width - 2.f, 0.f ) );
// units conversion: from time to float (calculation made with higher precision first)
float time_ = static_cast<float> ( static_cast<double>(*time - start) / static_cast<double>(end) );
float step_ = static_cast<float> ( static_cast<double>(step) / static_cast<double>(end) );
guint64 duration = end - start;
float time_ = static_cast<float> ( static_cast<double>(*time - start) / static_cast<double>(duration) );
float step_ = static_cast<float> ( static_cast<double>(step) / static_cast<double>(duration) );
//
// SECOND GET USER INPUT AND PERFORM CHANGES AND DECISIONS
@@ -548,7 +549,7 @@ bool ImGuiToolkit::TimelineSlider(const char* label, guint64 *time, guint64 star
tick_step = optimal_tick_marks[i];
large_tick_step = optimal_tick_marks[i+LARGE_TICK_INCREMENT];
label_tick_step = optimal_tick_marks[i+LABEL_TICK_INCREMENT];
tick_step_pixels = timeline_bbox.GetWidth() * static_cast<float> ( static_cast<double>(tick_step) / static_cast<double>(end) );
tick_step_pixels = timeline_bbox.GetWidth() * static_cast<float> ( static_cast<double>(tick_step) / static_cast<double>(duration) );
}
}
@@ -567,7 +568,7 @@ bool ImGuiToolkit::TimelineSlider(const char* label, guint64 *time, guint64 star
ImGui::RenderTextClipped( duration_label, bbox.Max, overlay_buf, NULL, &overlay_size);
// render tick marks
while ( tick < end)
while ( tick < duration )
{
// large tick mark
float tick_length = !(tick%large_tick_step) ? fontsize - style.FramePadding.y : style.FramePadding.y;
@@ -575,7 +576,7 @@ bool ImGuiToolkit::TimelineSlider(const char* label, guint64 *time, guint64 star
// label tick mark
if ( !(tick%label_tick_step) ) {
tick_length = fontsize;
guint64 ticklabel = 100 * (guint64) round( (double)( tick ) / 100.0); // round value to avoid '0.99' and alike
guint64 ticklabel = 100 * (guint64) round( (double)( tick + start ) / 100.0); // round value to avoid '0.99' and alike
ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%s",
GstToolkit::time_to_string(ticklabel, GstToolkit::TIME_STRING_MINIMAL).c_str());
overlay_size = ImGui::CalcTextSize(overlay_buf, NULL);
@@ -591,7 +592,7 @@ bool ImGuiToolkit::TimelineSlider(const char* label, guint64 *time, guint64 star
// next tick
tick += tick_step;
float tick_percent = static_cast<float> ( static_cast<double>(tick) / static_cast<double>(end) );
float tick_percent = static_cast<float> ( static_cast<double>(tick) / static_cast<double>(duration) );
pos = ImLerp(timeline_bbox.GetTL(), timeline_bbox.GetTR(), tick_percent);
}
@@ -656,8 +657,9 @@ void ImGuiToolkit::Timeline (const char* label, guint64 time, guint64 start, gui
// ImRect slider_bbox( timeline_bbox.GetTL() + ImVec2(-cursor_width + 2.f, cursor_width + 4.f ), timeline_bbox.GetBR() + ImVec2( cursor_width - 2.f, 0.f ) );
// units conversion: from time to float (calculation made with higher precision first)
float time_ = static_cast<float> ( static_cast<double>(time - start) / static_cast<double>(end) );
float step_ = static_cast<float> ( static_cast<double>(step) / static_cast<double>(end) );
guint64 duration = end - start;
float time_ = static_cast<float> ( static_cast<double>(time - start) / static_cast<double>(duration) );
float step_ = static_cast<float> ( static_cast<double>(step) / static_cast<double>(duration) );
//
// THIRD RENDER
@@ -695,7 +697,7 @@ void ImGuiToolkit::Timeline (const char* label, guint64 time, guint64 start, gui
tick_step = optimal_tick_marks[i];
large_tick_step = optimal_tick_marks[i+LARGE_TICK_INCREMENT];
label_tick_step = optimal_tick_marks[i+LABEL_TICK_INCREMENT];
tick_step_pixels = timeline_bbox.GetWidth() * static_cast<float> ( static_cast<double>(tick_step) / static_cast<double>(end) );
tick_step_pixels = timeline_bbox.GetWidth() * static_cast<float> ( static_cast<double>(tick_step) / static_cast<double>(duration) );
}
}
@@ -709,12 +711,12 @@ void ImGuiToolkit::Timeline (const char* label, guint64 time, guint64 start, gui
ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%s",
GstToolkit::time_to_string(end, GstToolkit::TIME_STRING_MINIMAL).c_str());
ImVec2 overlay_size = ImGui::CalcTextSize(overlay_buf, NULL);
ImVec2 duration_label = bbox.GetBR() - overlay_size - ImVec2(3.f, 3.f);
ImVec2 duration_label = bbox.GetBR() - overlay_size - ImVec2(3.f, 5.f);
if (overlay_size.x > 0.0f)
ImGui::RenderTextClipped( duration_label, bbox.Max, overlay_buf, NULL, &overlay_size);
// render tick marks
while ( tick < end)
while ( tick < duration )
{
// large tick mark
float tick_length = !(tick%large_tick_step) ? fontsize - style.FramePadding.y : style.FramePadding.y;
@@ -722,7 +724,7 @@ void ImGuiToolkit::Timeline (const char* label, guint64 time, guint64 start, gui
// label tick mark
if ( !(tick%label_tick_step) ) {
tick_length = fontsize;
guint64 ticklabel = 100 * (guint64) round( (double)( tick ) / 100.0); // round value to avoid '0.99' and alike
guint64 ticklabel = 100 * (guint64) round( (double)( tick + start) / 100.0); // round value to avoid '0.99' and alike
ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%s",
GstToolkit::time_to_string(ticklabel, GstToolkit::TIME_STRING_MINIMAL).c_str());
overlay_size = ImGui::CalcTextSize(overlay_buf, NULL);
@@ -738,7 +740,7 @@ void ImGuiToolkit::Timeline (const char* label, guint64 time, guint64 start, gui
// next tick
tick += tick_step;
float tick_percent = static_cast<float> ( static_cast<double>(tick) / static_cast<double>(end) );
float tick_percent = static_cast<float> ( static_cast<double>(tick) / static_cast<double>(duration) );
pos = ImLerp(timeline_bbox.GetTL(), timeline_bbox.GetTR(), tick_percent);
}
@@ -758,7 +760,7 @@ void ImGuiToolkit::Timeline (const char* label, guint64 time, guint64 start, gui
// }
// draw the cursor
if ( time_ > 0.f && time_ < 1.f ) {
if ( time_ > -FLT_EPSILON && time_ < 1.f ) {
color = ImGui::GetColorU32(style.Colors[ImGuiCol_SliderGrab]);
pos = ImLerp(timeline_bbox.GetTL(), timeline_bbox.GetTR(), time_) - ImVec2(cursor_width, 2.f);
ImGui::RenderArrow(window->DrawList, pos, color, ImGuiDir_Up, cursor_scale);
@@ -984,12 +986,12 @@ bool ImGuiToolkit::EditPlotHistoLines(const char* label, float *histogram_array,
// keep active area while mouse is pressed
static bool active = false;
static uint previous_index = UINT32_MAX;
static size_t previous_index = UINT32_MAX;
if (mouse_press)
{
float x = (float) values_count * (mouse_pos_in_canvas.x - _h_space) / (size.x - 2.f * _h_space);
uint index = CLAMP( (int) floor(x), 0, values_count-1);
size_t index = CLAMP( (int) floor(x), 0, values_count);
float y = mouse_pos_in_canvas.y / bbox.GetHeight();
y = CLAMP( (y * (values_max-values_min)) + values_min, values_min, values_max);
@@ -997,8 +999,8 @@ bool ImGuiToolkit::EditPlotHistoLines(const char* label, float *histogram_array,
if (previous_index == UINT32_MAX)
previous_index = index;
const uint left = MIN(previous_index, index);
const uint right = MAX(previous_index, index);
const size_t left = MIN(previous_index, index);
const size_t right = MAX(previous_index, index);
if (edit_histogram){
static float target_value = values_min;
@@ -1009,13 +1011,13 @@ bool ImGuiToolkit::EditPlotHistoLines(const char* label, float *histogram_array,
active = true;
}
for (uint i = left; i < right; ++i)
for (size_t i = left; i < right; ++i)
histogram_array[i] = target_value;
}
else {
const float target_value = values_max - y;
for (uint i = left; i < right; ++i)
for (size_t i = left; i < right; ++i)
lines_array[i] = target_value;
}

View File

@@ -120,6 +120,11 @@ void Timeline::update()
gaps_array_need_update_ = false;
}
void Timeline::refresh()
{
fillArrayFromGaps(gapsArray_, MAX_TIMELINE_ARRAY);
}
bool Timeline::gapAt(const GstClockTime t, TimeInterval &gap) const
{
TimeIntervalSet::const_iterator g = std::find_if(gaps_.begin(), gaps_.end(), includesTime(t));
@@ -354,8 +359,10 @@ void Timeline::autoFading(uint milisecond)
{
// get index of begining of section
size_t s = ( (*it).begin * MAX_TIMELINE_ARRAY ) / timing_.end;
s += 1;
// get index of ending of section
size_t e = ( (*it).end * MAX_TIMELINE_ARRAY ) / timing_.end;
e -= 1;
// calculate size of the smooth transition in [s e] interval
uint n = MIN( (e-s)/3, N );
@@ -405,14 +412,16 @@ void Timeline::updateGapsFromArray(float *array, size_t array_size)
// detect a change of value between two slots
if ( array[i] != status) {
// compute time of the event in array
GstClockTime t = (timing_.duration() * i) / array_size;
GstClockTime t = (timing_.duration() * i) / (array_size-1);
// change from 0.f to 1.f : begin of a gap
if (array[i] > 0.f) {
begin_gap = t;
}
// change from 1.f to 0.f : end of a gap
else {
addGap( begin_gap, t );
TimeInterval d (begin_gap, t) ;
if (d.is_valid() && d.duration() > step_)
addGap(d);
begin_gap = GST_CLOCK_TIME_NONE;
}
// swap
@@ -420,10 +429,14 @@ void Timeline::updateGapsFromArray(float *array, size_t array_size)
}
}
// end a potentially pending gap if reached end of array with no end of gap
if (begin_gap != GST_CLOCK_TIME_NONE)
addGap( begin_gap, timing_.end );
if (begin_gap != GST_CLOCK_TIME_NONE) {
TimeInterval d (begin_gap, timing_.end) ;
if (d.is_valid() && d.duration() > step_)
addGap(d);
}
}
}
void Timeline::fillArrayFromGaps(float *array, size_t array_size)
@@ -435,10 +448,11 @@ void Timeline::fillArrayFromGaps(float *array, size_t array_size)
memcpy(gapsArray_, empty_gaps, MAX_TIMELINE_ARRAY * sizeof(float));
// for each gap
GstClockTime d = timing_.duration();
for (auto it = gaps_.begin(); it != gaps_.end(); ++it)
{
size_t s = ( (*it).begin * array_size ) / timing_.end;
size_t e = ( (*it).end * array_size ) / timing_.end;
size_t s = ( (*it).begin * array_size ) / d;
size_t e = ( (*it).end * array_size ) / d;
// fill with 1 where there is a gap
for (size_t i = s; i < e; ++i) {

View File

@@ -85,6 +85,7 @@ public:
bool is_valid();
void update();
void refresh();
// global properties of the timeline
// timeline is valid only if all 3 are set

View File

@@ -2147,7 +2147,6 @@ void SourceController::RenderSelection(size_t i)
// size_t numsteps = tl->fillSectionsArrays(gaps, fade) - 1;
ImVec2 size(rendersize.x - framesize.x - _h_space - _scrollbar, 1.5f * _timeline_height);
GstClockTime playtime = 0;
// GstClockTime d = tl->sectionsDuration();
// size.x = size.x * d / ( maxduration * mp->playSpeed() );
@@ -2155,6 +2154,7 @@ void SourceController::RenderSelection(size_t i)
// ImGuiToolkit::ShowPlotHistoLines("##TimelineArray2", gaps, fade, numsteps, 0.f, 1.f, size);
TimeIntervalSet se = tl->sections();
GstClockTime playtime = tl->sectionsDuration();
for (auto section = se.begin(); section != se.end(); ++section) {
GstClockTime d = section->duration();
@@ -2162,7 +2162,7 @@ void SourceController::RenderSelection(size_t i)
ImGuiToolkit::Timeline("##timeline2", mp->position(), section->begin, section->end, tl->step(), w);
ImGui::SameLine(0,1);
playtime += d;
}
// ImGuiToolkit::Timeline("##timeline2", mp->position(), tl->begin(), tl->end(), tl->step(), size.x);
@@ -2170,7 +2170,9 @@ void SourceController::RenderSelection(size_t i)
// text below timeline to show info
ImGui::SetCursorPos(image_top + ImVec2( framesize.x + _h_space, 1.5f * _timeline_height + _v_space));
GstClockTime t = (GstClockTime) ( (double) playtime / mp->playSpeed() );
ImGui::Text("%s play time / %.2f speed = %s (effective duration)", GstToolkit::time_to_string(playtime).c_str(), mp->playSpeed(), GstToolkit::time_to_string(t).c_str());
ImGui::Text("%d sections, %s play time / %.2f speed = %s (effective duration)",
se.size(), GstToolkit::time_to_string(playtime).c_str(),
mp->playSpeed(), GstToolkit::time_to_string(t).c_str());
}
// next line position
@@ -2516,16 +2518,23 @@ void SourceController::RenderMediaPlayer(MediaPlayer *mp)
ImGui::SetCursorScreenPos(top + ImVec2(framesize.x - ImGui::GetTextLineHeightWithSpacing(), _v_space));
ImGui::Text(ICON_FA_INFO_CIRCLE);
if (ImGui::IsItemHovered()){
// information visitor
mp->accept(info_);
float tooltip_height = 3.f * ImGui::GetTextLineHeightWithSpacing();
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->AddRectFilled(top, top + ImVec2(framesize.x, tooltip_height), IMGUI_COLOR_OVERLAY);
ImGui::SetCursorScreenPos(top + ImVec2(_h_space, _v_space));
ImGui::Text("%s", info_.str().c_str());
if (mp->isPlaying()) {
ImGui::SetCursorScreenPos(top + ImVec2( framesize.x - 1.5f * _buttons_height, 0.666f * tooltip_height));
// Icon to inform hardware decoding
if ( !mp->hardwareDecoderName().empty()) {
ImGui::SetCursorScreenPos(top + ImVec2( framesize.x - ImGui::GetTextLineHeightWithSpacing(), 0.35f * tooltip_height));
ImGui::Text(ICON_FA_MICROCHIP);
}
// refresh frequency
if ( mp->isPlaying()) {
ImGui::SetCursorScreenPos(top + ImVec2( framesize.x - 1.5f * _buttons_height, 0.667f * tooltip_height));
ImGui::Text("%.1f Hz", mp->updateFrameRate());
}
}
@@ -2599,40 +2608,29 @@ void SourceController::RenderMediaPlayer(MediaPlayer *mp)
ImGui::OpenPopup( "MenuTimeline" );
if (ImGui::BeginPopup( "MenuTimeline" ))
{
if (ImGui::MenuItem("Reset Speed" )){
if (ImGui::MenuItem(UNICODE_MULTIPLY " " ICON_FA_CARET_RIGHT " Reset Speed" )){
speed = 1.f;
mp->setPlaySpeed( static_cast<double>(speed) );
}
if (ImGui::MenuItem( "Reset Timeline" )){
if (ImGui::MenuItem(ICON_FA_WINDOW_CLOSE " Reset Timeline" )){
timeline_zoom = 1.f;
mp->timeline()->clearFading();
mp->timeline()->clearGaps();
Action::manager().store("Timeline Reset");
}
// if (ImGui::BeginMenu("Smooth curve"))
// {
// const char* names[] = { "Just a little", "A bit more", "Quite a lot"};
// for (int i = 0; i < IM_ARRAYSIZE(names); ++i) {
// if (ImGui::MenuItem(names[i])) {
// mp->timeline()->smoothFading( 10 * (int) pow(4, i) );
// Action::manager().store("Timeline Smooth curve");
// }
// }
// ImGui::EndMenu();
// }
if (ImGui::BeginMenu("Auto fading"))
if (ImGui::BeginMenu(ICON_FA_RANDOM " Auto fading"))
{
const char* names[] = { "250 ms", "500 ms", "1 second", "2 seconds"};
for (int i = 0; i < IM_ARRAYSIZE(names); ++i) {
if (ImGui::MenuItem(names[i])) {
mp->timeline()->autoFading( 250 * (int ) pow(2, i) );
mp->timeline()->smoothFading( 10 * (i + 1) );
mp->timeline()->smoothFading( 2 * (i + 1) );
Action::manager().store("Timeline Auto fading");
}
}
ImGui::EndMenu();
}
if (Settings::application.render.gpu_decoding && ImGui::BeginMenu("Hardware Decoding"))
if (Settings::application.render.gpu_decoding && ImGui::BeginMenu(ICON_FA_MICROCHIP " Hardware Decoding"))
{
bool hwdec = !mp->softwareDecodingForced();
if (ImGui::MenuItem("Auto", "", &hwdec ))
@@ -2669,16 +2667,18 @@ void SourceController::RenderMediaPlayer(MediaPlayer *mp)
ImVec2 size = ImGui::CalcItemSize(ImVec2(-FLT_MIN, 0.0f), ImGui::CalcItemWidth(), _timeline_height -1);
size.x *= timeline_zoom;
bool released = false;
Timeline *tl = mp->timeline();
if (tl->is_valid())
{
bool released = false;
if ( ImGuiToolkit::EditPlotHistoLines("##TimelineArray", tl->gapsArray(), tl->fadingArray(),
MAX_TIMELINE_ARRAY, 0.f, 1.f,
Settings::application.widget.timeline_editmode, &released, size) ) {
tl->update();
}
else if (released) {
else if (released)
{
tl->refresh();
Action::manager().store("Timeline change");
}
@@ -3990,7 +3990,7 @@ void Navigator::RenderMainPannelSettings()
change |= ImGuiToolkit::ButtonSwitch( "Vertical synchronization", &vsync);
change |= ImGuiToolkit::ButtonSwitch( "Blit framebuffer", &blit);
change |= ImGuiToolkit::ButtonSwitch( "Antialiasing framebuffer", &multi);
change |= ImGuiToolkit::ButtonSwitch( "Hardware video decoding", &gpu);
change |= ImGuiToolkit::ButtonSwitch( ICON_FA_MICROCHIP " Hardware video decoding", &gpu);
if (change) {
need_restart = ( vsync != (Settings::application.render.vsync > 0) ||