X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fplugins%2Fsketcher%2Fsketcher.C;h=151b42e11a0d6efadbe3a041bfb84d8b0443d7a3;hp=906980467729a76a626162aaa6d5fb840cd72c29;hb=HEAD;hpb=b64142b983e53a7f0bfe8422efc3bb4f4ebb897c diff --git a/cinelerra-5.1/plugins/sketcher/sketcher.C b/cinelerra-5.1/plugins/sketcher/sketcher.C index 90698046..151b42e1 100644 --- a/cinelerra-5.1/plugins/sketcher/sketcher.C +++ b/cinelerra-5.1/plugins/sketcher/sketcher.C @@ -27,28 +27,31 @@ #include "bccmodels.h" #include "bccolors.h" #include "clip.h" +#include "edl.h" #include "edlsession.h" #include "filexml.h" +#include "keyframes.h" #include "overlayframe.h" #include "pluginserver.h" #include "preferences.h" #include "sketcher.h" #include "sketcherwindow.h" +#include "transportque.inc" #include "language.h" #include "vframe.h" -void SketcherPoint::init(int id, int pty, coord x, coord y) +void SketcherPoint::init(int id, int arc, coord x, coord y) { - this->id = id; this->pty = pty; + this->id = id; this->arc = arc; this->x = x; this->y = y; } SketcherPoint::SketcherPoint(int id) { - init(id, PTY_LINE, 0, 0); + init(id, ARC_LINE, 0, 0); } -SketcherPoint::SketcherPoint(int id, int pty, coord x, coord y) +SketcherPoint::SketcherPoint(int id, int arc, coord x, coord y) { - init(id, pty, x, y); + init(id, arc, x, y); } SketcherPoint::~SketcherPoint() { @@ -60,13 +63,13 @@ SketcherPoint::SketcherPoint(SketcherPoint &pt) int SketcherPoint::equivalent(SketcherPoint &that) { return this->id == that.id && - this->pty == that.pty && + this->arc == that.arc && EQUIV(this->x, that.x) && EQUIV(this->y, that.y) ? 1 : 0; } void SketcherPoint::copy_from(SketcherPoint &that) { - this->id = that.id; this->pty = that.pty; + this->id = that.id; this->arc = that.arc; this->x = that.x; this->y = that.y; } void SketcherPoint::save_data(FileXML &output) @@ -74,7 +77,7 @@ void SketcherPoint::save_data(FileXML &output) char point[BCSTRLEN]; sprintf(point,"/POINT_%d",id); output.tag.set_title(point+1); - output.tag.set_property("TYPE", pty); + output.tag.set_property("TYPE", arc); output.tag.set_property("X", x); output.tag.set_property("Y", y); output.append_tag(); @@ -85,10 +88,10 @@ void SketcherPoint::save_data(FileXML &output) void SketcherPoint::read_data(FileXML &input) { id = atoi(input.tag.get_title() + 6); - pty = input.tag.get_property("TYPE", PTY_OFF); + arc = input.tag.get_property("TYPE", ARC_OFF); x = input.tag.get_property("X", (coord)0); y = input.tag.get_property("Y", (coord)0); - bclamp(pty, 0, PTY_SZ-1); + bclamp(arc, 0, ARC_SZ-1); } void SketcherCurve::init(int id, int pen, int width, int color) @@ -100,7 +103,7 @@ void SketcherCurve::init(int id, int pen, int width, int color) } SketcherCurve::SketcherCurve(int id) { - init(id, 1, PTY_LINE, CV_COLOR); + init(id, 1, PEN_SQUARE, CV_COLOR); } SketcherCurve::SketcherCurve(int id, int pen, int width, int color) { @@ -139,7 +142,6 @@ void SketcherCurve::copy_from(SketcherCurve &that) } void SketcherCurve::save_data(FileXML &output) { - this->pen = pen; this->color = color; char curve[BCSTRLEN]; sprintf(curve,"/CURVE_%d",id); output.tag.set_title(curve+1); @@ -157,55 +159,59 @@ void SketcherCurve::save_data(FileXML &output) void SketcherCurve::read_data(FileXML &input) { id = atoi(input.tag.get_title() + 6); - pen = input.tag.get_property("PEN", PTY_OFF); + pen = input.tag.get_property("PEN", PEN_OFF); width = input.tag.get_property("RADIUS", 1.); color = input.tag.get_property("COLOR", CV_COLOR); bclamp(pen, 0, PEN_SZ-1); } -int Sketcher::new_curve(int pen, int width, int color) +int SketcherConfig::new_curve(int pen, int width, int color) { - SketcherCurves &curves = config.curves; int k = curves.size(), id = 1; for( int i=k; --i>=0; ) { - int n = config.curves[i]->id; + int n = curves[i]->id; if( n >= id ) id = n + 1; } SketcherCurve *cv = new SketcherCurve(id, pen, width, color); curves.append(cv); - config.cv_selected = k; return k; } +int Sketcher::new_curve(int pen, int width, int color) +{ + cv_selected = config.new_curve(pen, width, color); + return cv_selected; +} + int Sketcher::new_curve() { return new_curve(PEN_XLANT, 1, CV_COLOR); } -int Sketcher::new_point(SketcherCurve *cv, int pty, coord x, coord y, int idx) +int Sketcher::new_point(SketcherCurve *cv, int arc, coord x, coord y, int idx) { int id = 1; for( int i=cv->points.size(); --i>=0; ) { int n = cv->points[i]->id; if( n >= id ) id = n + 1; } - SketcherPoint *pt = new SketcherPoint(id, pty, x, y); + SketcherPoint *pt = new SketcherPoint(id, arc, x, y); int n = cv->points.size(); if( idx < 0 || idx > n ) idx = n; cv->points.insert(pt, idx); return idx; } -int Sketcher::new_point(int idx) +int Sketcher::new_point(int idx, int arc) { - int ci = config.cv_selected; + int ci = cv_selected; if( ci < 0 || ci >= config.curves.size() ) return -1; SketcherCurve *cv = config.curves[ci]; - EDLSession *session = get_edlsession(); + EDLSession *session = get_edl()->session; coord x = !session ? 0.f : session->output_w / 2.f; coord y = !session ? 0.f : session->output_h / 2.f; - return new_point(cv, PTY_LINE, x, y, idx); + return new_point(cv, arc, x, y, idx); } double SketcherCurve::nearest_point(int &pi, coord x, coord y) @@ -241,9 +247,7 @@ REGISTER_PLUGIN(Sketcher) SketcherConfig::SketcherConfig() { - drag = 1; - cv_selected = 0; - pt_selected = 0; + aliasing = 0; } SketcherConfig::~SketcherConfig() { @@ -251,9 +255,7 @@ SketcherConfig::~SketcherConfig() int SketcherConfig::equivalent(SketcherConfig &that) { - if( this->drag != that.drag ) return 0; - if( this->cv_selected != that.cv_selected ) return 0; - if( this->pt_selected != that.pt_selected ) return 0; + if( this->aliasing != that.aliasing ) return 0; if( this->curves.size() != that.curves.size() ) return 0; for( int i=0, n=curves.size(); iequivalent(*that.curves[i]) ) return 0; @@ -263,9 +265,7 @@ int SketcherConfig::equivalent(SketcherConfig &that) void SketcherConfig::copy_from(SketcherConfig &that) { - this->drag = that.drag; - this->cv_selected = that.cv_selected; - this->pt_selected = that.pt_selected; + this->aliasing = that.aliasing; int m = curves.size(), n = that.curves.size(); while( m > n ) curves.remove_object_number(--m); while( m < n ) { curves.append(new SketcherCurve()); ++m; } @@ -275,9 +275,7 @@ void SketcherConfig::copy_from(SketcherConfig &that) void SketcherConfig::interpolate(SketcherConfig &prev, SketcherConfig &next, long prev_frame, long next_frame, long current_frame) { - this->cv_selected = prev.cv_selected; - this->pt_selected = prev.pt_selected; - this->drag = prev.drag; + this->aliasing = prev.aliasing; double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); @@ -317,7 +315,7 @@ void SketcherConfig::interpolate(SketcherConfig &prev, SketcherConfig &next, if( y != nt->y ) y = y * prev_scale + nt->y * next_scale; } - cv->points.append(new SketcherPoint(pt.id, pt.pty, x, y)); + cv->points.append(new SketcherPoint(pt.id, pt.arc, x, y)); } } else @@ -336,6 +334,10 @@ Sketcher::Sketcher(PluginServer *server) img = 0; out = 0; overlay_frame = 0; + + drag = 1; + cv_selected = 0; + pt_selected = 0; } Sketcher::~Sketcher() @@ -347,24 +349,41 @@ Sketcher::~Sketcher() const char* Sketcher::plugin_title() { return N_("Sketcher"); } int Sketcher::is_realtime() { return 1; } +int Sketcher::is_synthesis() { return 1; } NEW_WINDOW_MACRO(Sketcher, SketcherWindow); LOAD_CONFIGURATION_MACRO(Sketcher, SketcherConfig) -void Sketcher::save_data(KeyFrame *keyframe) +void Sketcher::render_gui(void *data) +{ + Sketcher *sketcher = (Sketcher *)data; + sketcher->drag = drag; + sketcher->cv_selected = cv_selected; + sketcher->pt_selected = pt_selected; +} + +int Sketcher::is_dragging() +{ + drag = 0; + cv_selected = -1; + pt_selected = -1; + send_render_gui(this); + return drag; +} + + +void SketcherConfig::save_data(KeyFrame *keyframe) { FileXML output; // cause data to be stored directly in text output.set_shared_output(keyframe->xbuf); output.tag.set_title("SKETCHER"); - output.tag.set_property("DRAG", config.drag); - output.tag.set_property("CV_SELECTED", config.cv_selected); - output.tag.set_property("PT_SELECTED", config.pt_selected); + output.tag.set_property("ALIASING", aliasing); output.append_tag(); output.append_newline(); - for( int i=0,n=config.curves.size(); isave_data(output); + for( int i=0,n=curves.size(); isave_data(output); } output.tag.set_title("/SKETCHER"); output.append_tag(); @@ -372,24 +391,27 @@ void Sketcher::save_data(KeyFrame *keyframe) output.terminate_string(); } -void Sketcher::read_data(KeyFrame *keyframe) +void Sketcher::save_data(KeyFrame *keyframe) +{ + config.save_data(keyframe); +} + +void SketcherConfig::read_data(KeyFrame *keyframe) { FileXML input; input.set_shared_input(keyframe->xbuf); - config.curves.remove_all_objects(); + curves.remove_all_objects(); int result = 0; SketcherCurve *cv = 0; while( !(result=input.read_tag()) ) { if( input.tag.title_is("SKETCHER") ) { - config.drag = input.tag.get_property("DRAG", config.drag); - config.cv_selected = input.tag.get_property("CV_SELECTED", 0); - config.pt_selected = input.tag.get_property("PT_SELECTED", 0); + aliasing = input.tag.get_property("ALIASING", aliasing); } else if( !strncmp(input.tag.get_title(),"CURVE_",6) ) { cv = new SketcherCurve(); cv->read_data(input); - config.curves.append(cv); + curves.append(cv); } else if( !strncmp(input.tag.get_title(),"/CURVE_",7) ) cv = 0; @@ -400,13 +422,79 @@ void Sketcher::read_data(KeyFrame *keyframe) cv->points.append(pt); } else - printf("Sketcher::read_data: no curve for point\n"); + printf("SketcherConfig::read_data: no curve for point\n"); } } + limits(); +} + +void Sketcher::read_data(KeyFrame *keyframe) +{ + config.read_data(keyframe); if( !config.curves.size() ) new_curve(); - config.limits(); +} + +void SketcherPoint::update_parameter(SketcherPoint *prev, SketcherPoint *src) +{ + if( prev->arc != src->arc ) arc = src->arc; + if( prev->x != src->x ) x = src->x; + if( prev->y != src->y ) y = src->y; +} + +void SketcherCurve::update_parameter(SketcherCurve *prev, SketcherCurve *src) +{ + if( prev->pen != src->pen ) pen = src->pen; + if( prev->width != src->width ) width = src->width; + if( prev->color != src->color ) color = src->color; + int prev_points = prev->points.size(); + int src_points = src->points.size(); + int dst_points = this->points.size(); + int npoints = bmin(prev_points, bmin(src_points, dst_points)); + for( int i=0; ipoints[i]; + SketcherPoint *src_point = src->points[i]; + SketcherPoint *dst_point = this->points[i]; + dst_point->update_parameter(prev_point, src_point); + } +} + +void Sketcher::span_keyframes(KeyFrame *src, int64_t start, int64_t end) +{ + SketcherConfig src_config; + src_config.read_data(src); + KeyFrames *keyframes = (KeyFrames *)src->autos; + KeyFrame *prev = keyframes->get_prev_keyframe(start, PLAY_FORWARD); + SketcherConfig prev_config; + prev_config.read_data(prev); +// Always update the first one + update_parameter(prev_config, src_config, prev); + KeyFrame *curr = (KeyFrame*)prev->next; + while( curr && curr->position < end ) { + update_parameter(prev_config, src_config, curr); + curr = (KeyFrame*)curr->next; + } +} + +void Sketcher::update_parameter(SketcherConfig &prev_config, SketcherConfig &src_config, + KeyFrame *keyframe) +{ + SketcherConfig dst_config; + dst_config.read_data(keyframe); + if( prev_config.aliasing != src_config.aliasing ) + dst_config.aliasing = src_config.aliasing; + int src_curves = src_config.curves.size(); + int dst_curves = dst_config.curves.size(); + int prev_curves = prev_config.curves.size(); + int ncurves = bmin(prev_curves, bmin(src_curves, dst_curves)); + for( int i=0; iupdate_parameter(prev_curve, src_curve); + } + dst_config.save_data(keyframe); } void Sketcher::update_gui() @@ -437,47 +525,58 @@ void Sketcher::draw_point(VFrame *vfrm, SketcherPoint *pt, int color) } -int SketcherVPen::draw_pixel(int x, int y) +int SketcherVPen::draw_mask(int x, int y) { - if( x >= 0 && x < vfrm->get_w() && - y >= 0 && y < vfrm->get_h() ) - msk[vfrm->get_w()*y + x] = 0xff; + int w = vfrm->get_w(), h = vfrm->get_h(); + if( x < 0 || x >= w ) return 1; + if( y < 0 || y >= h ) return 1; + msk[w * y + x] = 0xff; return 0; } -int SketcherPenSquare::draw_pixel(int x, int y) +int SketcherVPen::draw_pixel(float x, float y, float frac, int axis) +{ + draw_mask(x, y); + return VFrame::draw_pixel(x, y, frac, axis); +} + +int SketcherPenSquare::draw_pixel(float x, float y, float a) { + vfrm->set_draw_alpha(a); vfrm->draw_line(x-n, y, x+n, y); for( int i=-n; idraw_line(x-n, y+i, x+n, y+i); - return SketcherVPen::draw_pixel(x, y); + return 0; } -int SketcherPenPlus::draw_pixel(int x, int y) +int SketcherPenPlus::draw_pixel(float x, float y, float a) { + vfrm->set_draw_alpha(a); if( n > 1 ) { vfrm->draw_line(x-n, y, x+n, y); vfrm->draw_line(x, y-n, x, y+n); } else vfrm->draw_pixel(x, y); - return SketcherVPen::draw_pixel(x, y); + return 0; } -int SketcherPenSlant::draw_pixel(int x, int y) +int SketcherPenSlant::draw_pixel(float x, float y, float a) { + vfrm->set_draw_alpha(a); vfrm->draw_line(x-n, y+n, x+n, y-n); vfrm->draw_line(x-n+1, y+n, x+n+1, y-n); vfrm->draw_line(x-n, y+n+1, x+n, y-n+1); - return SketcherVPen::draw_pixel(x, y); + return 0; } -int SketcherPenXlant::draw_pixel(int x, int y) +int SketcherPenXlant::draw_pixel(float x, float y, float a) { + vfrm->set_draw_alpha(a); vfrm->draw_line(x-n, y+n, x+n, y-n); vfrm->draw_line(x-n+1, y+n, x+n+1, y-n); vfrm->draw_line(x-n, y+n+1, x+n, y-n+1); vfrm->draw_line(x-n, y-n, x+n, y+n); vfrm->draw_line(x-n+1, y-n, x+n+1, y+n); vfrm->draw_line(x-n, y-n+1, x+n, y-n+1); - return SketcherVPen::draw_pixel(x, y); + return 0; } @@ -527,7 +626,6 @@ static void smooth_dxy(float &dx, float &dy, dx = xc - xd; dy = yc - yd; } -#if 0 static int convex(float ax,float ay, float bx,float by, float cx,float cy, float dx,float dy) { @@ -540,8 +638,6 @@ static int convex(float ax,float ay, float bx,float by, float v = abc * bcd; return !v ? 0 : v>0 ? 1 : -1; } -#endif - class FillRegion { @@ -565,6 +661,7 @@ class FillRegion public: SketcherPoint *next(); bool exists() { return stack.size() > 0; } + void draw_pixel(int x, int y) { img->draw_pixel(x, y); } void start_at(int x, int y); void run(); FillRegion(SketcherPoints &pts, SketcherVPen *vpen); @@ -593,25 +690,26 @@ void FillRegion::start_at(int x, int y) void FillRegion::run() { + img->set_draw_alpha(1); while( stack.size() > 0 ) { int y, ilt, irt; pop(y, ilt, irt); int ofs = y*w + ilt; for( int x=ilt; x<=irt; ++x,++ofs ) { + draw_pixel(x, y); if( msk[ofs] ) continue; msk[ofs] = 0xff; - img->draw_pixel(x, y); int lt = x, rt = x; int lofs = ofs; for( int i=lt; --i>=0; ) { + draw_pixel(i, y); if( msk[--lofs] ) break; - img->draw_pixel(i, y); msk[lofs] = 0xff; lt = i; } int rofs = ofs; for( int i=rt; ++i< w; ) { + draw_pixel(i, y); if( msk[++rofs] ) break; - img->draw_pixel(i, y); msk[rofs] = 0xff; rt = i; } if( y+1 < h ) push(y+1, lt, rt); @@ -623,20 +721,21 @@ void FillRegion::run() SketcherPoint *FillRegion::next() { while( nxt < points.size() ) { - SketcherPoint *pt = points[nxt]; - if( pt->pty != PTY_FILL ) break; + SketcherPoint *pt = points[nxt++]; + if( pt->arc == ARC_OFF ) continue; + if( pt->arc != ARC_FILL ) return pt; start_at(pt->x, pt->y); - ++nxt; } - return nxt < points.size() ? points[nxt++] : 0; + return 0; } - -void SketcherCurve::draw(VFrame *img) +void SketcherCurve::draw(VFrame *img, int alias) { if( !points.size() ) return; + img->set_pixel_color(color, (~color>>24)&0xff); const float fmx = 16383; SketcherVPen *vpen = new_vpen(img); + vpen->set_draw_flags(alias); FillRegion fill(points, vpen); SketcherPoint *pnt0 = fill.next(); SketcherPoint *pnt1 = pnt0 ? fill.next() : 0; @@ -650,29 +749,31 @@ void SketcherCurve::draw(VFrame *img) smooth_axy(ax,ay, bx,by, cx,cy, dx,dy); while( pt2 ) { dx = pt2->x; dy = pt2->y; - switch( pt0->pty ) { - case PTY_LINE: + switch( pt0->arc ) { + case ARC_CURVE: + if( convex(ax,ay, bx,by, cx,cy, dx,dy) >= 0 ) { + // s = ac thru b x bd thru c + intersects_at(sx,sy, ax,ay,cx,cy,bx,by, bx,by,dx,dy,cx,cy,fmx); + vpen->draw_smooth(bx,by, sx,sy, cx,cy); + break; + } // fall thru + case ARC_LINE: vpen->draw_line(bx, by, cx, cy); break; - case PTY_CURVE: { - // s = ac thru b x bd thru c - intersects_at(sx,sy, ax,ay,cx,cy,bx,by, bx,by,dx,dy,cx,cy,fmx); - vpen->draw_smooth(bx,by, sx,sy, cx,cy); - break; } } ax = bx; ay = by; pt0 = pt1; bx = cx; by = cy; pt1 = pt2; cx = dx; cy = dy; pt2 = fill.next(); } - switch( pt1->pty ) { - case PTY_LINE: + switch( pt1->arc ) { + case ARC_LINE: vpen->draw_line(bx, by, cx, cy); if( fill.exists() ) { dx = pnt0->x; dy = pnt0->y; vpen->draw_line(cx,cy, dx,dy); } break; - case PTY_CURVE: { + case ARC_CURVE: { if( fill.exists() ) { dx = pnt0->x; dy = pnt0->y; intersects_at(sx,sy, ax,ay,cx,cy,bx,by, bx,by,dx,dy,cx,cy,fmx); @@ -694,7 +795,7 @@ void SketcherCurve::draw(VFrame *img) vpen->draw_line(pnt0->x, pnt0->y, pnt1->x, pnt1->y); } else if( pnt0 ) { - vpen->draw_pixel(pnt0->x, pnt0->y); + vpen->draw_pixel(pnt0->x, pnt0->y, 1); } delete vpen; } @@ -736,20 +837,22 @@ int Sketcher::process_realtime(VFrame *input, VFrame *output) for( int ci=0, n=config.curves.size(); cipen == PEN_OFF ) continue; int m = cv->points.size(); - if( !m || cv->pen == PTY_OFF ) continue; + if( !m ) continue; img->clear_frame(); - img->set_pixel_color(cv->color, (~cv->color>>24)&0xff); - cv->draw(img); + int alias = config.aliasing < 0 ? ALIAS_OFF : + config.aliasing > 0 ? ALIAS_DBL : ALIAS_NRM; + cv->draw(img, alias); overlay_frame->overlay(out, img, 0,0,w,h, 0,0,w,h, - 1.f, TRANSFER_NORMAL, NEAREST_NEIGHBOR); + 1.f, TRANSFER_SRC_OVER, NEAREST_NEIGHBOR); } - if( config.drag ) { + if( is_dragging() ) { for( int ci=0, n=config.curves.size(); cipoints.size(); picolor ; draw_point(out, cv->points[pi], color); } @@ -768,8 +871,8 @@ void SketcherPoints::dump() { for( int i=0; iid, pt_type[pt->pty], pt->x, pt->y); + printf(" Pt %d, id=%d, arc=%s, x=%0.1f, y=%0.1f\n", + i, pt->id, pt_type[pt->arc], pt->x, pt->y); } } void SketcherCurves::dump() @@ -785,8 +888,7 @@ void SketcherCurves::dump() } void SketcherConfig::dump() { - printf("Config drag=%d, cv_selected=%d, pt_selected=%d %d curves\n", - drag, cv_selected, pt_selected, curves.size()); + printf("Config %d curves\n", curves.size()); curves.dump(); }