X-Git-Url: https://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fplugins%2Ftracer%2Ftracerwindow.C;h=653f8624f46e340581526dfe8bad56cc3c0ab10b;hb=81fc9cd689dd964a4736fa1f8986a64db6b4a937;hp=af0ec2f2cc81500d25cb172f4caa4bc1c2e01baa;hpb=f06e8ed85bd5937d704d57b65e0fb26ed288996d;p=goodguy%2Fcinelerra.git diff --git a/cinelerra-5.1/plugins/tracer/tracerwindow.C b/cinelerra-5.1/plugins/tracer/tracerwindow.C index af0ec2f2..653f8624 100644 --- a/cinelerra-5.1/plugins/tracer/tracerwindow.C +++ b/cinelerra-5.1/plugins/tracer/tracerwindow.C @@ -36,11 +36,11 @@ #include "theme.h" #include "track.h" -#define COLOR_W 50 -#define COLOR_H 30 +#define COLOR_W xS(50) +#define COLOR_H yS(30) TracerNum::TracerNum(TracerWindow *gui, int x, int y, float output) - : BC_TumbleTextBox(gui, output, -32767.0f, 32767.0f, x, y, 120) + : BC_TumbleTextBox(gui, output, -32767.0f, 32767.0f, x, y, xS(120)) { this->gui = gui; set_increment(1); @@ -85,7 +85,7 @@ int TracerPointY::handle_event() } TracerWindow::TracerWindow(Tracer *plugin) - : PluginClientWindow(plugin, 400, 300, 400, 300, 0) + : PluginClientWindow(plugin, xS(460), yS(420), xS(460), yS(420), 0) { this->plugin = plugin; this->title_x = 0; this->point_x = 0; @@ -93,9 +93,9 @@ TracerWindow::TracerWindow(Tracer *plugin) this->new_point = 0; this->del_point = 0; this->point_up = 0; this->point_dn = 0; this->drag = 0; this->draw = 0; - this->dragging = 0; + this->button_no = 0; this->invert = 0; this->title_r = 0; this->title_s = 0; - this->radius = 0; this->scale = 0; + this->feather = 0; this->radius = 0; this->last_x = 0; this->last_y = 0; this->point_list = 0; this->pending_config = 0; } @@ -108,54 +108,66 @@ TracerWindow::~TracerWindow() void TracerWindow::create_objects() { - int x = 10, y = 10; + int x = xS(10), y = yS(10); int margin = plugin->get_theme()->widget_border; - TracerPoint *pt = plugin->config.points[plugin->config.selected]; + int hot_point = plugin->selected; add_subwindow(title_x = new BC_Title(x, y, _("X:"))); int x1 = x + title_x->get_w() + margin; - point_x = new TracerPointX(this, x1, y, pt->x); + TracerPoints &points = plugin->config.points; + TracerPoint *pt = hot_point >= 0 && hot_pointx); point_x->create_objects(); - x1 += point_x->get_w() + margin; + x1 += point_x->get_w() + margin + xS(20); add_subwindow(new_point = new TracerNewPoint(this, plugin, x1, y)); - x1 += new_point->get_w() + margin; + x1 += new_point->get_w() + margin + xS(30); add_subwindow(point_up = new TracerPointUp(this, x1, y)); y += point_x->get_h() + margin; add_subwindow(title_y = new BC_Title(x, y, _("Y:"))); x1 = x + title_y->get_w() + margin; - point_y = new TracerPointY(this, x1, y, pt->y); + point_y = new TracerPointY(this, x1, y, !pt ? 0 : pt->y); point_y->create_objects(); - x1 += point_y->get_w() + margin; + x1 += point_y->get_w() + margin + xS(20); add_subwindow(del_point = new TracerDelPoint(this, plugin, x1, y)); - x1 += del_point->get_w() + margin; + x1 += del_point->get_w() + margin + xS(30); add_subwindow(point_dn = new TracerPointDn(this, x1, y)); - y += point_y->get_h() + margin + 10; + y += point_y->get_h() + margin + yS(10); add_subwindow(drag = new TracerDrag(this, x, y)); - if( plugin->config.drag ) { + if( plugin->drag ) { if( !grab(plugin->server->mwindow->cwindow->gui) ) eprintf("drag enabled, but compositor already grabbed\n"); } - x1 = x + drag->get_w() + margin + 20; + x1 = x + drag->get_w() + margin + xS(20); add_subwindow(draw = new TracerDraw(this, x1, y)); - x1 += draw->get_w() + margin + 20; + x1 += draw->get_w() + margin + xS(20); add_subwindow(fill = new TracerFill(this, x1, y)); - x1 += drag->get_w() + margin + 20; - add_subwindow(reset = new TracerReset(this, plugin, x1, y+3)); - y += drag->get_h() + margin; - - add_subwindow(title_r = new BC_Title(x1=x, y, _("Radius:"))); - x1 += title_r->get_w() + margin; - add_subwindow(radius = new TracerRadius(this, x1, y, 100)); - x1 += radius->get_w() + margin + 20; - add_subwindow(title_s = new BC_Title(x1, y, _("Scale:"))); - x1 += title_s->get_w() + margin; - add_subwindow(scale = new TracerScale(this, x1, y, 100)); - y += radius->get_h() + margin + 20; + x1 += drag->get_w() + margin + xS(20); + int y1 = y + yS(3); + add_subwindow(reset = new TracerReset(this, plugin, x1, y1)); + y1 += reset->get_h() + margin; + add_subwindow(invert = new TracerInvert(this, plugin, x1, y1)); + y += drag->get_h() + margin + yS(15); + + x1 = x + xS(80); + add_subwindow(title_r = new BC_Title(x, y, _("Feather:"))); + add_subwindow(feather = new TracerFeather(this, x1, y, xS(150))); + y += feather->get_h() + margin; + add_subwindow(title_s = new BC_Title(x, y, _("Radius:"))); + add_subwindow(radius = new TracerRadius(this, x1, y, xS(150))); + y += radius->get_h() + margin + yS(5); add_subwindow(point_list = new TracerPointList(this, plugin, x, y)); - point_list->update(plugin->config.selected); -// y += point_list->get_h() + 10; - + point_list->update(plugin->selected); + y += point_list->get_h() + yS(10); + + add_subwindow(new BC_Title(x, y, _( + "Btn1: select/drag point\n" + "Btn2: drag all points\n" + "Btn3: add point on nearest line\n" + "Btn3: shift: append point to end\n" + "Wheel: rotate, centered on cursor\n" + "Wheel: shift: scale, centered on cursor\n"))); show_window(1); } @@ -186,102 +198,136 @@ int TracerWindow::do_grab_event(XEvent *event) MWindow *mwindow = plugin->server->mwindow; CWindowGUI *cwindow_gui = mwindow->cwindow->gui; CWindowCanvas *canvas = cwindow_gui->canvas; - int cx, cy; cwindow_gui->get_relative_cursor(cx, cy); - cx -= canvas->view_x; - cy -= canvas->view_y; - - if( !dragging ) { - if( cx < 0 || cx >= canvas->view_w || - cy < 0 || cy >= canvas->view_h ) + int cursor_x, cursor_y; + cwindow_gui->get_relative_cursor(cursor_x, cursor_y); + cursor_x -= canvas->view_x; + cursor_y -= canvas->view_y; + + if( !button_no ) { + if( cursor_x < 0 || cursor_x >= canvas->view_w || + cursor_y < 0 || cursor_y >= canvas->view_h ) return 0; } switch( event->type ) { case ButtonPress: - if( dragging ) return 0; - dragging = event->xbutton.state & ShiftMask ? -1 : 1; + if( button_no ) return 0; + button_no = event->xbutton.button; break; case ButtonRelease: - if( !dragging ) return 0; - dragging = 0; + if( !button_no ) return 0; + button_no = 0; return 1; case MotionNotify: - if( !dragging ) return 0; + if( !button_no ) return 0; break; default: return 0; } - float cursor_x = cx, cursor_y = cy; - canvas->canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y); - int64_t position = plugin->get_source_position(); - float projector_x, projector_y, projector_z; - Track *track = plugin->server->plugin->track; - int track_w = track->track_w, track_h = track->track_h; - track->automation->get_projector( - &projector_x, &projector_y, &projector_z, - position, PLAY_FORWARD); - projector_x += mwindow->edl->session->output_w / 2; - projector_y += mwindow->edl->session->output_h / 2; - float output_x = (cursor_x - projector_x) / projector_z + track_w / 2; - float output_y = (cursor_y - projector_y) / projector_z + track_h / 2; - point_x->update((int64_t)(output_x)); - point_y->update((int64_t)(output_y)); + float output_x = cursor_x, output_y = cursor_y, track_x, track_y; + canvas->canvas_to_output(mwindow->edl, 0, output_x, output_y); + plugin->output_to_track(output_x, output_y, track_x, track_y); + point_x->update((int64_t)track_x); + point_y->update((int64_t)track_y); TracerPoints &points = plugin->config.points; - if( dragging > 0 ) { - switch( event->type ) { - case ButtonPress: { - int button_no = event->xbutton.button; - int hot_point = -1; - if( button_no == RIGHT_BUTTON ) { - hot_point = plugin->new_point(); - TracerPoint *pt = points[hot_point]; - pt->x = output_x; pt->y = output_y; - point_list->update(hot_point); - break; - } + switch( event->type ) { + case ButtonPress: { + float s = 1.02; + float th = M_PI/360.f; // .5 deg per wheel_btn + int shift_down = event->xbutton.state & ShiftMask; + switch( button_no ) { + case WHEEL_DOWN: + s = 0.98; + th = -th; // fall thru + case WHEEL_UP: { + // shift_down scale, !shift_down rotate + float st = sin(th), ct = cos(th); int sz = points.size(); - if( hot_point < 0 && sz > 0 ) { + for( int i=0; ix - track_x, py = pt->y - track_y; + float nx = shift_down ? px*s : px*ct + py*st; + float ny = shift_down ? py*s : py*ct - px*st; + point_list->set_point(i, PT_X, pt->x = nx + track_x); + point_list->set_point(i, PT_Y, pt->y = ny + track_y); + } + point_list->update(-1); + button_no = 0; + break; } + case RIGHT_BUTTON: { + // shift_down adds to end + int sz = !shift_down ? points.size() : 0; + int k = !shift_down ? -1 : points.size()-1; + float mx = FLT_MAX; + for( int i=0; ix, y0 = pt0->y; + float x1 = pt1->x, y1 = pt1->y; + float dx = x1-x0, dy = y1-y0; + float rr = dx*dx + dy*dy; + if( !rr ) continue; + float u = ((x1-track_x)*dx + (y1-track_y)*dy) / rr; + if( u < 0 || u > 1 ) continue; // past endpts + float x = x0*u + x1*(1-u); + float y = y0*u + y1*(1-u); + dx = track_x-x; dy = track_y-y; + float dd = dx*dx + dy*dy; // d**2 closest approach + if( mx > dd ) { mx = dd; k = i; } + } + TracerPoint *pt = points[sz=plugin->new_point()]; + int hot_point = k+1; + for( int i=sz; i>hot_point; --i ) points[i] = points[i-1]; + points[hot_point] = pt; + pt->x = track_x; pt->y = track_y; + point_list->update(hot_point); + break; } + case LEFT_BUTTON: { + int hot_point = -1, sz = points.size(); + if( sz > 0 ) { TracerPoint *pt = points[hot_point=0]; - double dist = DISTANCE(output_x,output_y, pt->x,pt->y); + double dist = DISTANCE(track_x,track_y, pt->x,pt->y); for( int i=1; ix,pt->y); + double d = DISTANCE(track_x,track_y, pt->x,pt->y); if( d >= dist ) continue; dist = d; hot_point = i; } pt = points[hot_point]; - float px = (pt->x - track_w / 2) * projector_z + projector_x; - float py = (pt->y - track_h / 2) * projector_z + projector_y; - dist = DISTANCE(px, py, cursor_x,cursor_y); + float cx, cy; + plugin->track_to_output(pt->x, pt->y, cx, cy); + canvas->output_to_canvas(mwindow->edl, 0, cx, cy); + dist = DISTANCE(cursor_x, cursor_y, cx,cy); if( dist >= HANDLE_W ) hot_point = -1; } if( hot_point >= 0 && sz > 0 ) { TracerPoint *pt = points[hot_point]; - point_list->set_point(hot_point, PT_X, pt->x = output_x); - point_list->set_point(hot_point, PT_Y, pt->y = output_y); + point_list->set_point(hot_point, PT_X, pt->x = track_x); + point_list->set_point(hot_point, PT_Y, pt->y = track_y); point_list->update_list(hot_point); } break; } - case MotionNotify: { + } + break; } + case MotionNotify: { + switch( button_no ) { + case LEFT_BUTTON: { int hot_point = point_list->get_selection_number(0, 0); if( hot_point >= 0 && hot_point < points.size() ) { TracerPoint *pt = points[hot_point]; - if( pt->x == output_x && pt->y == output_y ) break; - point_list->set_point(hot_point, PT_X, pt->x = output_x); - point_list->set_point(hot_point, PT_Y, pt->y = output_y); + if( pt->x == track_x && pt->y == track_y ) break; + point_list->set_point(hot_point, PT_X, pt->x = track_x); + point_list->set_point(hot_point, PT_Y, pt->y = track_y); point_x->update(pt->x); point_y->update(pt->y); point_list->update_list(hot_point); } break; } - } - } - else { - switch( event->type ) { - case MotionNotify: { - float dx = output_x - last_x, dy = output_y - last_y; + case MIDDLE_BUTTON: { + float dx = track_x - last_x, dy = track_y - last_y; int sz = points.size(); for( int i=0; igui = gui; this->plugin = plugin; - titles[PT_X] = _("X"); widths[PT_X] = 90; - titles[PT_Y] = _("Y"); widths[PT_Y] = 90; + titles[PT_X] = _("X"); widths[PT_X] = xS(90); + titles[PT_Y] = _("Y"); widths[PT_Y] = yS(90); } TracerPointList::~TracerPointList() { @@ -391,9 +438,11 @@ int TracerPointList::set_selected(int k) } void TracerPointList::update_list(int k) { - int xpos = get_xposition(), ypos = get_yposition(); - if( k < 0 ) k = get_selection_number(0, 0); + int sz = plugin->config.points.size(); + if( k < 0 || k >= sz ) k = -1; + plugin->selected = k; update_selection(&cols[0], k); + int xpos = get_xposition(), ypos = get_yposition(); BC_ListBox::update(&cols[0], &titles[0],&widths[0],PT_SZ, xpos,ypos,k); center_selection(); } @@ -411,21 +460,19 @@ void TracerPointList::update(int k) if( k >= 0 && k < sz ) { gui->point_x->update(gui->point_list->cols[PT_X].get(k)->get_text()); gui->point_y->update(gui->point_list->cols[PT_Y].get(k)->get_text()); - plugin->config.selected = k; } - update_list(k); } void TracerWindow::update_gui() { TracerConfig &config = plugin->config; - drag->update(config.drag); + drag->update(plugin->drag); draw->update(config.draw); fill->update(config.fill); + feather->update(config.feather); radius->update(config.radius); - scale->update(config.scale); - drag->update(config.drag); + invert->update(config.invert); point_list->update(-1); } @@ -480,7 +527,7 @@ int TracerPointDn::handle_event() } TracerDrag::TracerDrag(TracerWindow *gui, int x, int y) - : BC_CheckBox(x, y, gui->plugin->config.drag, _("Drag")) + : BC_CheckBox(x, y, gui->plugin->drag, _("Drag")) { this->gui = gui; } @@ -496,10 +543,21 @@ int TracerDrag::handle_event() } else gui->ungrab(cwindow_gui); - gui->plugin->config.drag = value; + gui->plugin->drag = value; gui->send_configure_change(); return 1; } +int TracerWindow::handle_ungrab() +{ + CWindowGUI *cwindow_gui = plugin->server->mwindow->cwindow->gui; + int ret = ungrab(cwindow_gui); + if( ret ) { + drag->update(0); + plugin->drag = 0; + } + return ret; +} + TracerDraw::TracerDraw(TracerWindow *gui, int x, int y) : BC_CheckBox(x, y, gui->plugin->config.draw, _("Draw")) @@ -525,32 +583,32 @@ int TracerFill::handle_event() return 1; } -TracerRadius::TracerRadius(TracerWindow *gui, int x, int y, int w) - : BC_ISlider(x,y,0,w,w, -50,50, gui->plugin->config.radius) +TracerFeather::TracerFeather(TracerWindow *gui, int x, int y, int w) + : BC_ISlider(x,y,0,w,w, -50,50, gui->plugin->config.feather) { this->gui = gui; } -int TracerRadius::handle_event() +int TracerFeather::handle_event() { - gui->plugin->config.radius = get_value(); + gui->plugin->config.feather = get_value(); gui->send_configure_change(); return 1; } -TracerScale::TracerScale(TracerWindow *gui, int x, int y, int w) - : BC_FSlider(x,y, 0,w,w, 1.f,10.f, gui->plugin->config.scale) +TracerRadius::TracerRadius(TracerWindow *gui, int x, int y, int w) + : BC_FSlider(x,y, 0,w,w, -5.f,5.f, gui->plugin->config.radius) { this->gui = gui; } -int TracerScale::handle_event() +int TracerRadius::handle_event() { - gui->plugin->config.scale = get_value(); + gui->plugin->config.radius = get_value(); gui->send_configure_change(); return 1; } TracerNewPoint::TracerNewPoint(TracerWindow *gui, Tracer *plugin, int x, int y) - : BC_GenericButton(x, y, 80, _("New")) + : BC_GenericButton(x, y, xS(100), _("New")) { this->gui = gui; this->plugin = plugin; @@ -567,7 +625,7 @@ int TracerNewPoint::handle_event() } TracerDelPoint::TracerDelPoint(TracerWindow *gui, Tracer *plugin, int x, int y) - : BC_GenericButton(x, y, 80, C_("Del")) + : BC_GenericButton(x, y, xS(100), C_("Del")) { this->gui = gui; this->plugin = plugin; @@ -581,10 +639,7 @@ int TracerDelPoint::handle_event() TracerPoints &points = plugin->config.points; if( hot_point >= 0 && hot_point < points.size() ) { plugin->config.del_point(hot_point); - if( !points.size() ) plugin->new_point(); - int sz = points.size(); - if( hot_point >= sz && hot_point > 0 ) --hot_point; - gui->point_list->update(hot_point); + gui->point_list->update(--hot_point); gui->send_configure_change(); } return 1; @@ -602,18 +657,41 @@ TracerReset::~TracerReset() int TracerReset::handle_event() { TracerConfig &config = plugin->config; - config.drag = 0; - config.draw = 0; + if( !plugin->drag ) { + MWindow *mwindow = plugin->server->mwindow; + CWindowGUI *cwindow_gui = mwindow->cwindow->gui; + if( gui->grab(cwindow_gui) ) + plugin->drag = 1; + else + gui->drag->flicker(10,50); + } + config.draw = 1; config.fill = 0; - config.radius = 0; - config.scale = 1; - config.selected = 0; + config.invert = 0; + config.feather = 0; + config.radius = 1; + plugin->selected = -1; TracerPoints &points = plugin->config.points; points.remove_all_objects(); - plugin->new_point(); - gui->point_list->update(0); + gui->point_list->update(-1); gui->update_gui(); gui->send_configure_change(); return 1; } +TracerInvert::TracerInvert(TracerWindow *gui, Tracer *plugin, int x, int y) + : BC_CheckBox(x, y, gui->plugin->config.invert, _("Invert")) +{ + this->gui = gui; + this->plugin = plugin; +} +TracerInvert::~TracerInvert() +{ +} +int TracerInvert::handle_event() +{ + plugin->config.invert = get_value(); + gui->send_configure_change(); + return 1; +} +