mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 02:40:00 +01:00
User input unified and fixed for clone source
Fixed slider in player, show filtered image when disabled (outside mixing circle), correct timing for clone source (different for filters).
This commit is contained in:
@@ -111,6 +111,8 @@ void CloneSource::render()
|
||||
|
||||
void CloneSource::setActive (bool on)
|
||||
{
|
||||
bool was_active = active_;
|
||||
|
||||
// try to activate (may fail if source is cloned)
|
||||
Source::setActive(on);
|
||||
|
||||
@@ -119,13 +121,9 @@ void CloneSource::setActive (bool on)
|
||||
if ( mode_ > Source::UNINITIALIZED )
|
||||
origin_->touch();
|
||||
|
||||
// change visibility of active surface (show preview of origin when inactive)
|
||||
if (activesurface_) {
|
||||
if (active_)
|
||||
activesurface_->setTextureIndex(Resource::getTextureTransparent());
|
||||
else
|
||||
activesurface_->setTextureIndex(renderbuffer_->texture());
|
||||
}
|
||||
// enable / disable filtering
|
||||
if ( active_ != was_active )
|
||||
filter_->setEnabled( active_ );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,8 +188,8 @@ void CloneSource::play (bool on)
|
||||
// play / pause filter to suspend clone
|
||||
filter_->setEnabled( on );
|
||||
|
||||
// restart clean if was paused
|
||||
if (paused_)
|
||||
// restart delay if was paused
|
||||
if (paused_ && filter_->type() == FrameBufferFilter::FILTER_DELAY)
|
||||
replay();
|
||||
|
||||
// toggle state
|
||||
@@ -201,24 +199,19 @@ void CloneSource::play (bool on)
|
||||
|
||||
bool CloneSource::playable () const
|
||||
{
|
||||
if (filter_ && filter_->enabled())
|
||||
return true;
|
||||
|
||||
if (origin_)
|
||||
return origin_->playable();
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CloneSource::replay()
|
||||
{
|
||||
// TODO: add reset to Filter
|
||||
|
||||
// reset Filter
|
||||
filter_->reset();
|
||||
}
|
||||
|
||||
guint64 CloneSource::playtime () const
|
||||
{
|
||||
// TODO : get time of ImageFilter? Get Delay ?
|
||||
if (filter_->type() != FrameBufferFilter::FILTER_PASSTHROUGH)
|
||||
return guint64( filter_->updateTime() * GST_SECOND ) ;
|
||||
|
||||
return origin_->playtime();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,29 @@ DelayFilter::~DelayFilter()
|
||||
elapsed_.pop();
|
||||
}
|
||||
|
||||
void DelayFilter::reset ()
|
||||
{
|
||||
// delete all frame buffers
|
||||
while (!frames_.empty()) {
|
||||
if (frames_.front() != nullptr)
|
||||
delete frames_.front();
|
||||
frames_.pop();
|
||||
}
|
||||
|
||||
while (!elapsed_.empty())
|
||||
elapsed_.pop();
|
||||
|
||||
now_ = 0.0;
|
||||
}
|
||||
|
||||
double DelayFilter::updateTime ()
|
||||
{
|
||||
if (!elapsed_.empty())
|
||||
return elapsed_.front();
|
||||
|
||||
return 0.;
|
||||
}
|
||||
|
||||
void DelayFilter::update (float dt)
|
||||
{
|
||||
if (input_) {
|
||||
@@ -96,7 +119,7 @@ void DelayFilter::draw (FrameBuffer *input)
|
||||
{
|
||||
input_ = input;
|
||||
|
||||
if ( enabled() ) // TODO TEST DISABLE
|
||||
if ( enabled() )
|
||||
{
|
||||
// make sure the queue is not empty
|
||||
if ( input_ && !frames_.empty() ) {
|
||||
|
||||
@@ -24,6 +24,8 @@ public:
|
||||
uint texture () const override;
|
||||
glm::vec3 resolution () const override;
|
||||
void update (float dt) override;
|
||||
void reset () override;
|
||||
double updateTime () override;
|
||||
void draw (FrameBuffer *input) override;
|
||||
void accept (Visitor& v) override;
|
||||
|
||||
|
||||
@@ -513,13 +513,6 @@ void DeviceSource::setActive (bool on)
|
||||
|
||||
}
|
||||
|
||||
// change visibility of active surface (show preview of stream when inactive)
|
||||
if (activesurface_) {
|
||||
if (active_)
|
||||
activesurface_->setTextureIndex(Resource::getTextureTransparent());
|
||||
else
|
||||
activesurface_->setTextureIndex(stream_->texture());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ FrameBufferFilter::FrameBufferFilter() : enabled_(true), input_(nullptr)
|
||||
|
||||
void FrameBufferFilter::draw (FrameBuffer *input)
|
||||
{
|
||||
input_ = input;
|
||||
if (input && ( enabled_ || input_ == nullptr ) )
|
||||
input_ = input;
|
||||
}
|
||||
|
||||
void FrameBufferFilter::accept(Visitor& v)
|
||||
|
||||
@@ -50,8 +50,14 @@ public:
|
||||
// get the resolution of the rendered filtered framebuffer
|
||||
virtual glm::vec3 resolution () const = 0;
|
||||
|
||||
// perform update (non rendering)
|
||||
virtual void update (float dt) {}
|
||||
// perform update (non rendering), given dt in milisecond
|
||||
virtual void update (float) {}
|
||||
|
||||
// reset update data and time
|
||||
virtual void reset () {}
|
||||
|
||||
// total time of update, in second
|
||||
virtual double updateTime () { return 0.; }
|
||||
|
||||
// draw the input framebuffer and apply the filter
|
||||
virtual void draw (FrameBuffer *input);
|
||||
@@ -60,8 +66,8 @@ public:
|
||||
virtual void accept (Visitor& v);
|
||||
|
||||
// when enabled, draw is effective
|
||||
inline void setEnabled (bool on) { enabled_ = on; }
|
||||
inline bool enabled () const { return enabled_; }
|
||||
inline void setEnabled (bool on) { enabled_ = on; }
|
||||
inline bool enabled () const { return enabled_; }
|
||||
|
||||
protected:
|
||||
FrameBuffer *input_;
|
||||
|
||||
@@ -173,13 +173,12 @@ class ImageFilteringShader : public ImageShader
|
||||
std::string shader_code_;
|
||||
std::string code_;
|
||||
|
||||
public:
|
||||
// for iTimedelta
|
||||
GTimer *timer_;
|
||||
double iTime_;
|
||||
uint iFrame_;
|
||||
|
||||
public:
|
||||
|
||||
// list of uniforms to control shader
|
||||
std::map< std::string, float > uniforms_;
|
||||
|
||||
@@ -323,6 +322,19 @@ ImageFilter::~ImageFilter ()
|
||||
// NB: shaders_ are removed with surface
|
||||
}
|
||||
|
||||
void ImageFilter::reset ()
|
||||
{
|
||||
shaders_.first->reset();
|
||||
|
||||
if ( program_.isTwoPass() )
|
||||
shaders_.second->reset();
|
||||
}
|
||||
|
||||
double ImageFilter::updateTime ()
|
||||
{
|
||||
return shaders_.first->iTime_;
|
||||
}
|
||||
|
||||
void ImageFilter::update (float dt)
|
||||
{
|
||||
shaders_.first->update(dt);
|
||||
@@ -355,6 +367,8 @@ glm::vec3 ImageFilter::resolution () const
|
||||
|
||||
void ImageFilter::draw (FrameBuffer *input)
|
||||
{
|
||||
bool forced = false;
|
||||
|
||||
// if input changed (typically on first draw)
|
||||
if (input_ != input) {
|
||||
// keep reference to input framebuffer
|
||||
@@ -376,9 +390,11 @@ void ImageFilter::draw (FrameBuffer *input)
|
||||
if (buffers_.second != nullptr)
|
||||
delete buffers_.second;
|
||||
buffers_.second = new FrameBuffer( buffers_.first->resolution(), buffers_.first->flags() );
|
||||
// forced draw
|
||||
forced = true;
|
||||
}
|
||||
|
||||
if ( enabled() )
|
||||
if ( enabled() || forced )
|
||||
{
|
||||
// FIRST PASS
|
||||
// render input surface into frame buffer
|
||||
@@ -482,6 +498,8 @@ void ResampleFilter::setFactor(int factor)
|
||||
|
||||
void ResampleFilter::draw (FrameBuffer *input)
|
||||
{
|
||||
bool forced = false;
|
||||
|
||||
// Default
|
||||
if (factor_ == RESAMPLE_INVALID)
|
||||
setFactor( RESAMPLE_DOUBLE );
|
||||
@@ -524,9 +542,11 @@ void ResampleFilter::draw (FrameBuffer *input)
|
||||
delete buffers_.second;
|
||||
res /= 2.;
|
||||
buffers_.second = new FrameBuffer( res, buffers_.first->flags() );
|
||||
// forced draw
|
||||
forced = true;
|
||||
}
|
||||
|
||||
if ( enabled() )
|
||||
if ( enabled() || forced )
|
||||
{
|
||||
// FIRST PASS
|
||||
// render input surface into frame buffer
|
||||
@@ -592,6 +612,8 @@ void BlurFilter::setMethod(int method)
|
||||
|
||||
void BlurFilter::draw (FrameBuffer *input)
|
||||
{
|
||||
bool forced = false;
|
||||
|
||||
// Default to Gaussian blur
|
||||
if (method_ == BLUR_INVALID)
|
||||
setMethod( BLUR_GAUSSIAN );
|
||||
@@ -630,9 +652,11 @@ void BlurFilter::draw (FrameBuffer *input)
|
||||
if (buffers_.second != nullptr)
|
||||
delete buffers_.second;
|
||||
buffers_.second = new FrameBuffer( input_->resolution(), f );
|
||||
// forced draw
|
||||
forced = true;
|
||||
}
|
||||
|
||||
if ( enabled() )
|
||||
if ( enabled() || forced )
|
||||
{
|
||||
// ZERO PASS
|
||||
// render input surface into frame buffer with Mipmapping (Levels of Details)
|
||||
@@ -676,7 +700,7 @@ const char* SharpenFilter::method_label[SharpenFilter::SHARPEN_INVALID] = {
|
||||
std::vector< FilteringProgram > SharpenFilter::programs_ = {
|
||||
FilteringProgram("UnsharpMask", "shaders/filters/sharpen_1.glsl", "shaders/filters/sharpen_2.glsl", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Sharpen", "shaders/filters/sharpen.glsl", "", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Sharp Edge", "shaders/filters/sharpenedge.glsl","", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Sharp Edge", "shaders/filters/sharpenedge.glsl","", { { "Amount", 0.25} }),
|
||||
FilteringProgram("TopHat", "shaders/filters/erosion.glsl", "shaders/filters/tophat.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("BlackHat", "shaders/filters/dilation.glsl", "shaders/filters/blackhat.glsl", { { "Radius", 0.5} }),
|
||||
};
|
||||
@@ -720,7 +744,7 @@ const char* SmoothFilter::method_label[SmoothFilter::SMOOTH_INVALID] = {
|
||||
|
||||
std::vector< FilteringProgram > SmoothFilter::programs_ = {
|
||||
FilteringProgram("Bilateral","shaders/filters/bilinear.glsl", "", { { "Factor", 0.5} }),
|
||||
FilteringProgram("Kuwahara", "shaders/filters/kuwahara.glsl", "", { { "Radius", 1.0} }),
|
||||
FilteringProgram("Kuwahara", "shaders/filters/kuwahara.glsl", "", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Opening", "shaders/filters/erosion.glsl", "shaders/filters/dilation.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Closing", "shaders/filters/dilation.glsl", "shaders/filters/erosion.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Erosion", "shaders/filters/erosion.glsl", "", { { "Radius", 0.5} }),
|
||||
|
||||
@@ -91,6 +91,8 @@ public:
|
||||
uint texture () const override;
|
||||
glm::vec3 resolution () const override;
|
||||
void update (float dt) override;
|
||||
double updateTime () override;
|
||||
void reset () override;
|
||||
void draw (FrameBuffer *input) override;
|
||||
void accept (Visitor& v) override;
|
||||
|
||||
|
||||
@@ -142,13 +142,6 @@ void MediaSource::setActive (bool on)
|
||||
if ( active_ != was_active )
|
||||
mediaplayer_->enable(active_);
|
||||
|
||||
// change visibility of active surface (show preview of media when inactive)
|
||||
if (activesurface_) {
|
||||
if (active_)
|
||||
activesurface_->setTextureIndex(Resource::getTextureTransparent());
|
||||
else
|
||||
activesurface_->setTextureIndex(mediaplayer_->texture());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -137,14 +137,6 @@ void SessionSource::setActive (bool on)
|
||||
// change status of session (recursive change of internal sources)
|
||||
if (session_) {
|
||||
session_->setActive(active_);
|
||||
|
||||
// change visibility of active surface (show preview of session when inactive)
|
||||
if (activesurface_) {
|
||||
if (active_)
|
||||
activesurface_->setTextureIndex(Resource::getTextureTransparent());
|
||||
else
|
||||
activesurface_->setTextureIndex(session_->frame()->texture());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -523,7 +523,7 @@ void Source::attach(FrameBuffer *renderbuffer)
|
||||
if ( activesurface_ == nullptr) {
|
||||
|
||||
// for views showing a scaled mixing surface, a dedicated transparent surface allows grabbing
|
||||
activesurface_ = new Surface();
|
||||
activesurface_ = new Surface;
|
||||
activesurface_->setTextureIndex(Resource::getTextureTransparent());
|
||||
groups_[View::TEXTURE]->attach(activesurface_);
|
||||
groups_[View::MIXING]->attach(activesurface_);
|
||||
|
||||
@@ -154,13 +154,6 @@ void StreamSource::setActive (bool on)
|
||||
if (active_ != was_active)
|
||||
stream_->enable(active_);
|
||||
|
||||
// change visibility of active surface (show preview of stream when inactive)
|
||||
if (activesurface_) {
|
||||
if (active_)
|
||||
activesurface_->setTextureIndex(Resource::getTextureTransparent());
|
||||
else
|
||||
activesurface_->setTextureIndex(stream_->texture());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1130,10 +1130,10 @@ void UserInterface::showSourceEditor(Source *s)
|
||||
outputcontrol.setVisible(true);
|
||||
return;
|
||||
}
|
||||
CloneSource *cs = dynamic_cast<CloneSource *>(s);
|
||||
if (cs != nullptr) {
|
||||
shadercontrol.setVisible( cs );
|
||||
}
|
||||
// CloneSource *cs = dynamic_cast<CloneSource *>(s);
|
||||
// if (cs != nullptr) {
|
||||
// shadercontrol.setVisible( cs );
|
||||
// }
|
||||
if (s->playable()) {
|
||||
sourcecontrol.setVisible(true);
|
||||
sourcecontrol.resetActiveSelection();
|
||||
@@ -3081,23 +3081,56 @@ void SourceController::RenderSingleSource(Source *s)
|
||||
///
|
||||
/// Image
|
||||
///
|
||||
top += corner;
|
||||
ImGui::SetCursorScreenPos(top);
|
||||
const ImVec2 top_image = top + corner;
|
||||
ImGui::SetCursorScreenPos(top_image);
|
||||
|
||||
ImVec2 crop = ImVec2 ( s->frame()->projectionArea().x, s->frame()->projectionArea().y);
|
||||
CloneSource *cloned = dynamic_cast<CloneSource *>(s);
|
||||
|
||||
if (s->imageProcessingEnabled() || cloned != nullptr) {
|
||||
ImGui::Image((void*)(uintptr_t) s->texture(), framesize * ImVec2(Settings::application.widget.media_player_slider,1.f), ImVec2(0.f,0.f), ImVec2(Settings::application.widget.media_player_slider,1.f));
|
||||
if (s->imageProcessingEnabled() || ImLengthSqr(crop) < 2 || cloned != nullptr) {
|
||||
//
|
||||
// LEFT of slider : original texture
|
||||
//
|
||||
ImVec2 slider = framesize * ImVec2(Settings::application.widget.media_player_slider,1.f);
|
||||
ImGui::Image((void*)(uintptr_t) s->texture(), slider, ImVec2(0.f,0.f), ImVec2(Settings::application.widget.media_player_slider,1.f));
|
||||
|
||||
ImGui::SetCursorScreenPos(top + ImVec2(Settings::application.widget.media_player_slider * framesize.x, 0.f));
|
||||
ImGui::Image((void*)(uintptr_t) s->frame()->texture(), framesize * ImVec2(1.f-Settings::application.widget.media_player_slider,1.f), ImVec2(Settings::application.widget.media_player_slider,0.f), ImVec2(1.f,1.f));
|
||||
//
|
||||
// RIGHT of slider : post-processed image (after crop and color correction)
|
||||
//
|
||||
ImVec2 cropsize = framesize * crop;
|
||||
ImVec2 croptop = (framesize - cropsize) * 0.5f;
|
||||
// no overlap of slider with cropped area
|
||||
if (slider.x < croptop.x) {
|
||||
// draw cropped area
|
||||
ImGui::SetCursorScreenPos(top_image + croptop );
|
||||
ImGui::Image((void*)(uintptr_t) s->frame()->texture(), cropsize, ImVec2(0.f, 0.f), ImVec2(1.f,1.f));
|
||||
}
|
||||
// overlap of slider with cropped area (horizontally)
|
||||
else if (slider.x < croptop.x + cropsize.x ) {
|
||||
// compute slider ratio of cropped area
|
||||
float cropped_slider = (slider.x - croptop.x) / cropsize.x;
|
||||
// top x moves with slider
|
||||
croptop.x = slider.x;
|
||||
ImGui::SetCursorScreenPos(top_image + croptop );
|
||||
// size is reduced by slider
|
||||
cropsize = cropsize * ImVec2(1.f -cropped_slider, 1.f);
|
||||
ImGui::Image((void*)(uintptr_t) s->frame()->texture(), cropsize, ImVec2(cropped_slider, 0.f), ImVec2(1.f,1.f));
|
||||
}
|
||||
// else : no render of cropped area
|
||||
|
||||
draw_list->AddCircleFilled(top + framesize * ImVec2(Settings::application.widget.media_player_slider,0.5f), 20.f, IM_COL32(255, 255, 255, 150), 26);
|
||||
draw_list->AddLine(top + framesize * ImVec2(Settings::application.widget.media_player_slider,0.0f), top + framesize * ImVec2(Settings::application.widget.media_player_slider,1.f), IM_COL32(255, 255, 255, 150), 1);
|
||||
|
||||
ImGui::SetCursorScreenPos(top + ImVec2(0.f, 0.5f * framesize.y - 20.0f));
|
||||
ImGuiToolkit::InvisibleSliderFloat("#filter_slider", &Settings::application.widget.media_player_slider, 0.f, 1.f, ImVec2(framesize.x, 40.0f) );
|
||||
//
|
||||
// SLIDER
|
||||
//
|
||||
// graphical indication of slider
|
||||
draw_list->AddCircleFilled(top_image + slider * ImVec2(1.f, 0.5f), 20.f, IM_COL32(255, 255, 255, 150), 26);
|
||||
draw_list->AddLine(top_image + slider * ImVec2(1.f,0.0f), top_image + slider, IM_COL32(255, 255, 255, 150), 1);
|
||||
// user input : move slider horizontally
|
||||
ImGui::SetCursorScreenPos(top_image + ImVec2(0.f, 0.5f * framesize.y - 20.0f));
|
||||
ImGuiToolkit::InvisibleSliderFloat("#Settings::application.widget.media_player_slider2", &Settings::application.widget.media_player_slider, 0.f, 1.f, ImVec2(framesize.x, 40.0f) );
|
||||
// affordance: cursor change to horizontal arrows
|
||||
if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
||||
|
||||
}
|
||||
else {
|
||||
ImGui::Image((void*)(uintptr_t) s->texture(), framesize);
|
||||
@@ -3106,20 +3139,20 @@ void SourceController::RenderSingleSource(Source *s)
|
||||
///
|
||||
/// Info overlays
|
||||
///
|
||||
ImGui::SetCursorScreenPos(top + ImVec2(framesize.x - ImGui::GetTextLineHeightWithSpacing(), v_space_));
|
||||
ImGui::SetCursorScreenPos(top_image + ImVec2(framesize.x - ImGui::GetTextLineHeightWithSpacing(), v_space_));
|
||||
ImGui::Text(ICON_FA_INFO_CIRCLE);
|
||||
if (ImGui::IsItemHovered()){
|
||||
// fill info string
|
||||
s->accept(info_);
|
||||
// draw overlay frame and text
|
||||
float tooltip_height = 3.f * ImGui::GetTextLineHeightWithSpacing();
|
||||
draw_list->AddRectFilled(top, top + ImVec2(framesize.x, tooltip_height), IMGUI_COLOR_OVERLAY);
|
||||
ImGui::SetCursorScreenPos(top + ImVec2(h_space_, v_space_));
|
||||
draw_list->AddRectFilled(top_image, top_image + ImVec2(framesize.x, tooltip_height), IMGUI_COLOR_OVERLAY);
|
||||
ImGui::SetCursorScreenPos(top_image + ImVec2(h_space_, v_space_));
|
||||
ImGui::Text("%s", info_.str().c_str());
|
||||
// special case Streams: print framerate
|
||||
StreamSource *sts = dynamic_cast<StreamSource*>(s);
|
||||
if (sts && s->playing()) {
|
||||
ImGui::SetCursorScreenPos(top + ImVec2( framesize.x - 1.5f * buttons_height_, 0.5f * tooltip_height));
|
||||
ImGui::SetCursorScreenPos(top_image + ImVec2( framesize.x - 1.5f * buttons_height_, 0.5f * tooltip_height));
|
||||
ImGui::Text("%.1f Hz", sts->stream()->updateFrameRate());
|
||||
}
|
||||
}
|
||||
@@ -3178,20 +3211,53 @@ void SourceController::RenderMediaPlayer(MediaSource *ms)
|
||||
///
|
||||
const ImVec2 top_image = top + corner;
|
||||
ImGui::SetCursorScreenPos(top_image);
|
||||
ImVec2 crop = ImVec2 ( ms->frame()->projectionArea().x, ms->frame()->projectionArea().y);
|
||||
|
||||
if (ms->imageProcessingEnabled()) {
|
||||
ImGui::Image((void*)(uintptr_t) ms->texture(), framesize * ImVec2(Settings::application.widget.media_player_slider,1.f), ImVec2(0.f,0.f), ImVec2(Settings::application.widget.media_player_slider,1.f));
|
||||
if (ms->imageProcessingEnabled() || ImLengthSqr(crop) < 2) {
|
||||
//
|
||||
// LEFT of slider : original texture
|
||||
//
|
||||
ImVec2 slider = framesize * ImVec2(Settings::application.widget.media_player_slider,1.f);
|
||||
ImGui::Image((void*)(uintptr_t) ms->texture(), slider, ImVec2(0.f,0.f), ImVec2(Settings::application.widget.media_player_slider,1.f));
|
||||
|
||||
ImGui::SetCursorScreenPos(top_image + ImVec2(Settings::application.widget.media_player_slider * framesize.x, 0.f));
|
||||
ImGui::Image((void*)(uintptr_t) ms->frame()->texture(), framesize * ImVec2(1.f-Settings::application.widget.media_player_slider,1.f), ImVec2(Settings::application.widget.media_player_slider,0.f), ImVec2(1.f,1.f));
|
||||
|
||||
draw_list->AddCircleFilled(top_image + framesize * ImVec2(Settings::application.widget.media_player_slider,0.5f), 20.f, IM_COL32(255, 255, 255, 150), 26);
|
||||
draw_list->AddLine(top_image + framesize * ImVec2(Settings::application.widget.media_player_slider,0.0f), top_image + framesize * ImVec2(Settings::application.widget.media_player_slider,1.f), IM_COL32(255, 255, 255, 150), 1);
|
||||
//
|
||||
// RIGHT of slider : post-processed image (after crop and color correction)
|
||||
//
|
||||
ImVec2 cropsize = framesize * crop;
|
||||
ImVec2 croptop = (framesize - cropsize) * 0.5f;
|
||||
// no overlap of slider with cropped area
|
||||
if (slider.x < croptop.x) {
|
||||
// draw cropped area
|
||||
ImGui::SetCursorScreenPos(top_image + croptop );
|
||||
ImGui::Image((void*)(uintptr_t) ms->frame()->texture(),
|
||||
cropsize, ImVec2(0.f, 0.f), ImVec2(1.f,1.f));
|
||||
}
|
||||
// overlap of slider with cropped area (horizontally)
|
||||
else if (slider.x < croptop.x + cropsize.x ) {
|
||||
// compute slider ratio of cropped area
|
||||
float cropped_slider = (slider.x - croptop.x) / cropsize.x;
|
||||
// top x moves with slider
|
||||
croptop.x = slider.x;
|
||||
ImGui::SetCursorScreenPos(top_image + croptop );
|
||||
// size is reduced by slider
|
||||
cropsize = cropsize * ImVec2(1.f -cropped_slider, 1.f);
|
||||
ImGui::Image((void*)(uintptr_t) ms->frame()->texture(), cropsize, ImVec2(cropped_slider, 0.f), ImVec2(1.f,1.f));
|
||||
}
|
||||
// else : no render of cropped area
|
||||
|
||||
//
|
||||
// SLIDER
|
||||
//
|
||||
// graphical indication of slider
|
||||
draw_list->AddCircleFilled(top_image + slider * ImVec2(1.f, 0.5f), 20.f, IM_COL32(255, 255, 255, 150), 26);
|
||||
draw_list->AddLine(top_image + slider * ImVec2(1.f,0.0f), top_image + slider, IM_COL32(255, 255, 255, 150), 1);
|
||||
// user input : move slider horizontally
|
||||
ImGui::SetCursorScreenPos(top_image + ImVec2(0.f, 0.5f * framesize.y - 20.0f));
|
||||
ImGuiToolkit::InvisibleSliderFloat("#Settings::application.widget.media_player_slider2", &Settings::application.widget.media_player_slider, 0.f, 1.f, ImVec2(framesize.x, 40.0f) );
|
||||
// affordance: cursor change to horizontal arrows
|
||||
if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
||||
|
||||
}
|
||||
else {
|
||||
ImGui::Image((void*)(uintptr_t) mediaplayer_active_->texture(), framesize);
|
||||
@@ -5397,7 +5463,6 @@ void ShaderEditor::setVisible(CloneSource *cs)
|
||||
// if the filter is an Image Filter
|
||||
if (f && f->type() == FrameBufferFilter::FILTER_IMAGE )
|
||||
setVisible(true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user