mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 15:30:00 +01:00
Compare commits
2 Commits
8d26f5d78a
...
e51781ee1d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e51781ee1d | ||
|
|
84233e46cd |
@@ -21,26 +21,27 @@ uniform vec3 brush;
|
||||
uniform int option;
|
||||
uniform int effect;
|
||||
|
||||
float sdBox( in vec2 p, in float b)
|
||||
float sdBox( in vec2 v1, in vec2 v2, float r )
|
||||
{
|
||||
vec2 q = abs(p) - vec2(b);
|
||||
vec2 ba = v2 - v1;
|
||||
vec2 pa = -v1;
|
||||
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
|
||||
vec2 q = abs(pa -h*ba) - vec2(r);
|
||||
float d = min( max(q.x, q.y), 0.0) + length(max(q,0.0));
|
||||
return 1.0 - abs(d) * step(d, 0.0);
|
||||
return 1.0 - abs( mix( 0.5, 1.0, d) ) * step(d, 0.0);
|
||||
}
|
||||
|
||||
float sdCircle( in vec2 p, in float b)
|
||||
float sdSegment( in vec2 v1, in vec2 v2, float r )
|
||||
{
|
||||
return ( length( p ) / b );
|
||||
vec2 ba = v2 - v1;
|
||||
vec2 pa = -v1;
|
||||
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
|
||||
return length(pa-h*ba) / r;
|
||||
}
|
||||
|
||||
float sdElipse( in vec2 p, in float b)
|
||||
{
|
||||
return ( length( p ) / b );
|
||||
}
|
||||
|
||||
const mat3 KERNEL = mat3( 0.0625, 0.125, 0.0625,
|
||||
0.125, 0.25, 0.125,
|
||||
0.0625, 0.125, 0.0625);
|
||||
const mat3 KERNEL = mat3( 0.0555555, 0.111111, 0.0555555,
|
||||
0.111111, 0.333334, 0.111111,
|
||||
0.0555555, 0.111111, 0.0555555);
|
||||
|
||||
vec3 gaussian()
|
||||
{
|
||||
@@ -71,14 +72,15 @@ void main()
|
||||
// fragment coordinates
|
||||
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
|
||||
// adjust coordinates to match scaling area
|
||||
uv.x *= cursor.z ;
|
||||
uv.y *= cursor.w ;
|
||||
uv.x *= size.x ;
|
||||
uv.y *= size.y ;
|
||||
// cursor coordinates
|
||||
vec2 cursor = vec2(cursor.x, - cursor.y);
|
||||
vec2 cur = vec2(cursor.x, - cursor.y);
|
||||
vec2 cur_prev = vec2(cursor.z, - cursor.w);
|
||||
// use distance function relative to length brush.x (size), depending on brush.z (shape):
|
||||
// - brush.z = 0 : circle shape
|
||||
// - brush.z = 1 : square shape
|
||||
float d = (1.0 -brush.z) * sdCircle(cursor-uv, brush.x) + brush.z * sdBox(uv-cursor, brush.x);
|
||||
float d = (1.0 -brush.z) * sdSegment(cur_prev - uv, cur - uv, brush.x) + brush.z * sdBox(cur_prev - uv, cur - uv, brush.x);
|
||||
|
||||
// modify only the pixels inside the brush
|
||||
if( d < 1.0 )
|
||||
|
||||
@@ -426,66 +426,24 @@ void InputMappingWindow::SliderParametersCallback(SourceCallback *callback, cons
|
||||
bool bd = edited->bidirectional();
|
||||
if ( ImGuiToolkit::IconToggle(2, 13, 3, 13, &bd, press_tooltip ) )
|
||||
edited->setBidirectional(bd);
|
||||
|
||||
// get value (gst time) and convert to hh mm s.ms
|
||||
guint64 ms = GST_TIME_AS_MSECONDS(edited->value());
|
||||
guint64 hh = ms / 3600000;
|
||||
guint64 mm = (ms % 3600000) / 60000;
|
||||
ms -= (hh * 3600000 + mm * 60000);
|
||||
float sec = (float) (ms) / 1000.f;
|
||||
|
||||
// filtering for reading MM:SS.MS text entry
|
||||
static bool valid = true;
|
||||
static std::regex RegExTime("([0-9]+\\:)?([0-9]+\\:)?([0-5][0-9]|[0-9])((\\.|\\,)[0-9]+)?");
|
||||
struct TextFilters { static int FilterTime(ImGuiInputTextCallbackData* data) {
|
||||
if (data->EventChar < 256 && strchr("0123456789.,:", (char)data->EventChar)) return 0; return 1; }
|
||||
};
|
||||
char buf6[64] = "";
|
||||
snprintf(buf6, 64, "%lu:%lu:%.2f", (unsigned long) hh, (unsigned long) mm, sec );
|
||||
|
||||
|
||||
// Text input field for MM:SS:MS seek target time
|
||||
ImGui::SetNextItemWidth(right_align);
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE / 2);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,
|
||||
ImVec4(1.0f, valid ? 1.0f : 0.2f, valid ? 1.0f : 0.2f, 1.f));
|
||||
ImGui::InputText("##CALLBACK_SEEK",
|
||||
buf6,
|
||||
64,
|
||||
ImGuiInputTextFlags_CallbackCharFilter,
|
||||
TextFilters::FilterTime);
|
||||
valid = std::regex_match(buf6, RegExTime);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
if (valid) {
|
||||
ms = 0;
|
||||
sec = 0.f;
|
||||
// user confirmed the entry and the input is valid
|
||||
// split the "HH:MM:SS.ms" string in HH MM SS.ms
|
||||
std::string time(buf6);
|
||||
std::size_t found = time.find_last_of(':');
|
||||
// read the right part SS.ms as a value
|
||||
if (std::string::npos != found && BaseToolkit::is_a_value(time.substr(found + 1), &sec)) {
|
||||
ms = (glm::uint64)(sec * 1000.f);
|
||||
// read right part MM as a number
|
||||
time = time.substr(0, found);
|
||||
found = time.find_last_of(':');
|
||||
int min = 0;
|
||||
if (std::string::npos != found && BaseToolkit::is_a_number(time.substr(found + 1), &min)) {
|
||||
ms += 60000 * (glm::uint64) min;
|
||||
// read right part HH as a number
|
||||
time = time.substr(0, found);
|
||||
int hour = 0;
|
||||
if (std::string::npos != found && BaseToolkit::is_a_number(time, &hour)) {
|
||||
ms += 3600000 * (glm::uint64) hour;
|
||||
}
|
||||
}
|
||||
}
|
||||
// set time in mili seconds
|
||||
edited->setValue( GST_MSECOND * ms );
|
||||
}
|
||||
// force to test validity next frame
|
||||
valid = false;
|
||||
|
||||
guint64 duration = GST_SECOND * 1000;
|
||||
if (Source * const* v = std::get_if<Source *>(&target)) {
|
||||
MediaSource *ms = dynamic_cast<MediaSource*>(*v);
|
||||
if (ms)
|
||||
duration = ms->mediaplayer()->timeline()->duration();
|
||||
}
|
||||
|
||||
static bool valid = false;
|
||||
guint64 target_time = edited->value();
|
||||
if ( ImGuiToolkit::InputTime("##CALLBACK_SEEK", &target_time, duration, &valid) ){
|
||||
if (valid)
|
||||
edited->setValue( target_time );
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE / 3);
|
||||
ImGuiToolkit::Indication("Target time (HH:MM:SS.MS) to set where to jump to in a video source.", 15, 7);
|
||||
|
||||
@@ -406,6 +406,15 @@ Source::Source(uint64_t id) : SourceCore(), id_(id), ready_(false), symbol_(null
|
||||
|
||||
Source::~Source()
|
||||
{
|
||||
// clear and delete callbacks
|
||||
access_callbacks_.lock();
|
||||
for (auto iter=update_callbacks_.begin(); iter != update_callbacks_.end(); ) {
|
||||
SourceCallback *callback = *iter;
|
||||
iter = update_callbacks_.erase(iter);
|
||||
delete callback;
|
||||
}
|
||||
access_callbacks_.unlock();
|
||||
|
||||
// inform links that they lost their target
|
||||
while ( !links_.empty() )
|
||||
links_.front()->disconnect();
|
||||
@@ -431,15 +440,6 @@ Source::~Source()
|
||||
overlays_.clear();
|
||||
frames_.clear();
|
||||
handles_.clear();
|
||||
|
||||
// clear and delete callbacks
|
||||
access_callbacks_.lock();
|
||||
for (auto iter=update_callbacks_.begin(); iter != update_callbacks_.end(); ) {
|
||||
SourceCallback *callback = *iter;
|
||||
iter = update_callbacks_.erase(iter);
|
||||
delete callback;
|
||||
}
|
||||
access_callbacks_.unlock();
|
||||
}
|
||||
|
||||
void Source::setName (const std::string &name)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/constants.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/matrix_access.hpp>
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
@@ -450,6 +451,8 @@ std::pair<Node *, glm::vec2> TextureView::pick(glm::vec2 P)
|
||||
pick = { mask_cursor_circle_, P };
|
||||
// adapt grid to prepare grab action
|
||||
adaptGridToSource(current);
|
||||
// reset previous brush position
|
||||
previous_scene_brush_pos = glm::zero<glm::vec3>();
|
||||
return pick;
|
||||
}
|
||||
// special case for cropping the mask shape
|
||||
@@ -815,8 +818,8 @@ void TextureView::draw()
|
||||
ImGuiToolkit::ToolTip("Size");
|
||||
if (ImGui::BeginPopup("brush_size_popup", ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
int pixel_size_min = int(0.05 * edit_source_->frame()->height() );
|
||||
int pixel_size_max = int(2.0 * edit_source_->frame()->height() );
|
||||
int pixel_size_min = int(BRUSH_MIN_SIZE * edit_source_->frame()->height() );
|
||||
int pixel_size_max = int(BRUSH_MAX_SIZE * edit_source_->frame()->height() );
|
||||
int pixel_size = int(Settings::application.brush.x * edit_source_->frame()->height() );
|
||||
show_cursor_forced_ = true;
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
||||
@@ -1106,16 +1109,26 @@ View::Cursor TextureView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pa
|
||||
// set brush coordinates (used in mouse over)
|
||||
scene_brush_pos = scene_to;
|
||||
|
||||
// no previous brush position : restart at same coordinates
|
||||
if ( glm::length( previous_scene_brush_pos ) < EPSILON)
|
||||
previous_scene_brush_pos = scene_brush_pos;
|
||||
|
||||
if ( pick.first == mask_cursor_circle_ ) {
|
||||
// snap prush coordinates if grid is active
|
||||
if (grid->active())
|
||||
scene_brush_pos = grid->snap(scene_brush_pos);
|
||||
// inform shader of a cursor action : coordinates and crop scaling
|
||||
edit_source_->maskShader()->size = edit_source_->mixingsurface_->scale_;
|
||||
|
||||
// inform shader of a cursor action : coordinates and crop scaling
|
||||
edit_source_->maskShader()->cursor = glm::vec4(scene_brush_pos.x - shift_crop_.x,
|
||||
scene_brush_pos.y - shift_crop_.y,
|
||||
edit_source_->mixingsurface_->scale_.x,
|
||||
edit_source_->mixingsurface_->scale_.y);
|
||||
previous_scene_brush_pos.x - shift_crop_.x,
|
||||
previous_scene_brush_pos.y - shift_crop_.y);
|
||||
edit_source_->touch(Source::SourceUpdate_Mask);
|
||||
|
||||
previous_scene_brush_pos = scene_brush_pos;
|
||||
|
||||
// action label
|
||||
info << MaskShader::mask_names[MaskShader::PAINT] << " changed";
|
||||
// cursor indication - no info, just cursor
|
||||
|
||||
@@ -72,6 +72,7 @@ private:
|
||||
|
||||
void adaptGridToSource(Source *s = nullptr, Node *picked = nullptr);
|
||||
glm::vec3 scene_brush_pos;
|
||||
glm::vec3 previous_scene_brush_pos;
|
||||
TranslationGrid *translation_grid_;
|
||||
RotationGrid *rotation_grid_;
|
||||
};
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
#define APPEARANCE_DEFAULT_SCALE 2.f
|
||||
#define APPEARANCE_MIN_SCALE 0.4f
|
||||
#define APPEARANCE_MAX_SCALE 7.0f
|
||||
#define BRUSH_MIN_SIZE 0.05f
|
||||
#define BRUSH_MIN_SIZE 0.01f
|
||||
#define BRUSH_MAX_SIZE 2.f
|
||||
#define BRUSH_MIN_PRESS 0.005f
|
||||
#define BRUSH_MAX_PRESS 1.f
|
||||
|
||||
Reference in New Issue
Block a user