mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 18:59:59 +01:00
Bugfix timeline display array
This commit is contained in:
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
26
Timeline.cpp
26
Timeline.cpp
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) ||
|
||||
|
||||
Reference in New Issue
Block a user