thread->data_type);
// Construct listbox items
- for(int i = 0; i < plugin_locations.total; i++)
+ for(int i = 0; i < plugin_locations.total; )
{
Track *track = mwindow->edl->tracks->number(plugin_locations.values[i]->module);
char *track_title = track->title;
int number = plugin_locations.values[i]->plugin;
double start = mwindow->edl->local_session->get_selectionstart(1);
Plugin *plugin = track->get_current_plugin(start, number, PLAY_FORWARD, 1, 0);
- if( !plugin ) continue;
+ if( !plugin ) { plugin_locations.remove_object_number(i); continue; }
char string[BCTEXTLEN];
const char *plugin_title = _(plugin->title);
snprintf(string, sizeof(string), "%s: %s", track_title, plugin_title);
shared_data.append(new BC_ListBoxItem(string));
+ ++i;
}
for(int i = 0; i < module_locations.total; i++)
{
if(source_track)
{
Plugin *source_plugin = source_track->get_current_plugin(
- edl->local_session->get_selectionstart(),
+ edl->local_session->get_selectionstart(1),
shared_location->plugin,
PLAY_FORWARD,
1,
{
data_type = TRACK_VIDEO;
transition_temp = 0;
- overlayer = new OverlayFrame(renderengine->preferences->processors);
+ overlayer = new OverlayFrame(renderengine->preferences->project_smp);
input_temp = 0;
vmodule_render_fragment = 0;
playback_buffer = 0;
F_tlut2
F_vectorscope
F_vignette
+ F_vibrance
- Motion
Motion
Motion 2 Point
F_atadenoise
F_bitplanenoise
F_dctdnoiz
+ F_fftdnoiz
F_hqdn3d
F_nlmeans
F_noise
#aevalsrc 0
afade
#afftfilt 1-clip((b/nb)*b,0,1)
-#afifo
+#afifo ###will not work within cin
aformat sample_fmts=u8|s16:channel_layouts=stereo
agate
#ahistogram dmode=single:r=25:s=hd720:scale=log:ascale=log:slide=replace
#alphaextract
#alphamerge
#amerge
-#ametadata mode=print:file=ametadata.txt
+ametadata mode=print:file=/tmp/ametadata.txt
#amix
#amovie
#anequalizer c0 f=200 w=100 g=-10 t=1|c1 f=200 w=100 g=-10 t=1
#anull
#anullsink
#anullsrc
-#apad pad_len=1024
+#apad ###not part of frame data
aperms
#aphasemeter r=25:s=800x400:rc=2:gc=7:bc=1
aphaser
#aselect
#asendcmd
#asetnsamples
-#asetpts PTS-STARTPTS
+#asetpts ###not part of frame data
asetrate r=48000
#asettb
-#ashowinfo
+#ashowinfo ###not part of frame data
#asidedata
#asplit
astats
#fieldhint
#fieldmatch
fieldorder
-#fifo
+#fifo ###will not work within cin
fillborders
#find_rect
#firequalizer delay=0.1:fixed=on:zero_phase=on
gblur
#geq
gradfun
-#haldclut
-#haldclutsrc
+#haldclut ###not working due to need for multiple video streams
+haldclutsrc
#hdcd
hflip
highpass
mcdeint
#mergeplanes 0x03010200:yuva444p
mestimate
-#metadata mode=print:file=metadata.txt
+metadata mode=print:file=/tmp/metadata.txt
#midequalizer
#minterpolate
#movie
negate
nlmeans r=15:p=7:s=2
#nnedi
-#noformat pix_fmts=yuv420p
+#noformat ###not part of frame data
noise
#null
#nullsink
pad
#palettegen
#paletteuse
-#pan 1c|c0=0.9*c0+0.1*c1
+pan 1c|c0=0.9*c0+0.1*c1
perms
perspective
phase
prewitt
#psnr PSNR=10*log10(MAX^2/MSE)
#pullup
-#qp 2+2*sin(PI*qp)
+#qp ###not part of frame data
#random seed=-1
readeia608
readvitc
#selectivecolor greens=.5 0 -.33 0:blues=0 .27
#sendcmd
separatefields
-#setdar dar=16/9
-#setfield mode=auto
-#setpts PTS-STARTPTS
-#setsar sar=10/11
+#setdar ###will not work because Format already set
+#setfield ###not part of frame data
+#setpts ###not part of frame data
+#setsar ###will not work because Format already set
#settb
#showcqt
#showfreqs
-showinfo
+#showinfo ###not part of frame data
showpalette s=30
#showspectrum s=1280x480:scale=log
#showspectrumpic
shuffleplanes
#sidechaincompress
#sidechaingate
-#sidedata mode=delete
+#sidedata mode=add
signalstats
#signature
-#silencedetect n=0.001
+#silencedetect n=0.001 ###does not appear to work
silenceremove
sine
smartblur
-#smptebars
-#smptehdbars
+smptebars
+smptehdbars
sobel
#spectrumsynth
#split
#tonemap
#vmafmotion
; new in 4.0
-#acontrast Contrast=33
+acontrast
#afir
#convolve
#deconvolve
#adeclick
#adeclip
aderivative
-afftdn
+#afftdn
aintegral
amplify
chromahold
-cue
+#cue ###freeze
deblock
fttdnoiz
-#graphmonitor
+graphmonitor
greyedge
#highshelf
#lowshelf
pal75bars
pal100bars
setparams
-#sinc
+#sinc ###freeze
tmix
vibrance
; broken in 4.1
#acrossover
#aiir
#amultiply
-#bm3d
+#bm3d sigma=3:block=4:bstep=2:group=1:estim=basic
#sr
#xstack
#agraphmonitor
yposition = item->text_y - top_item->text_y - view_h / 2;
}
}
+ if( yposition < 0 ) yposition = 0;
return 1;
}
}
// Select single item
else {
- if( !current_item->selected ) {
+ if( !current_item->selected || !new_value ) {
set_all_selected(data, 0);
- set_selected(data,
- selection_number,
- 1);
+ set_selected(data, selection_number, 1);
}
new_value = 1;
}
if( (display_format == LISTBOX_TEXT ||
display_format == LISTBOX_ICON_LIST) &&
shift_down() ) {
-// Deselect everything.
- set_all_selected(data, 0);
-
// Select just the items
redraw = expand_selection(0, selection_number);
}
#
# Description of FFmpeg Video Plugins
#
+F_amplify: Amplify changes between successive video frames.
F_atadenoise: Apply an Adaptive Temporal Averaging Denoiser.
F_avgblur: Apply average blur filter.
F_bbox: Compute bounding box for each frame.
able to change the power and the
radius of the boxblur applied to luma, chroma and alpha.
F_bwdif: Deinterlaces the input image.
+F_chromahold: Turns a certain color range into gray.
F_chromakey: Turns a certain color into
transparency. Operates on YUV colors.
F_ciescope: Video CIE scope.
F_datascope: Video data analysis.
F_dctdnoiz: Denoise frames using 2D DCT.
F_deband: Debands video.
+F_deblock: Deblock video.
F_deflate: Applies deflate effect.
F_deflicker: Remove temporal frame luminance variations.
F_dejudder: Removes judder produced by pullup.
F_entropy: Measure video frames entropy.
F_erosion: Applies erosion effect.
F_fade: Fade in/out input video.
+F_fftdnoiz: Denoise rames using 3D FFT.
F_fftfilt: Apply arbitrary expressions to pixels in frequency domain.
F_field: Extract a field from the input video.
F_fieldorder: Set the field order.
F_format: Convert the input video to one of the specified pixel formats.
F_framerate: Upsamples or downsamples progressive
source between specified frame rates.
+F_framestep: Select one frame every N frames.
F_fspp: Applies Fast Simple Post-processing filter.
F_gblur: Apply Gaussian Blur filter.
F_gradfun: Debands video quickly using gradients.
+F_graphmonitor: Show various filtergraph stats.
+F_greyedge: Estimates scene illumination by grey edge assumption.
+F_haldclutsrc: Provide an identity Hald CLUT.
F_hflip: Horizontally flips the input video.
F_histeq: Applies global color histogram equalization.
F_histogram: Computes and draws a histogram.
F_interlace: Convert progressive video into interlaced.
F_kerndeint: Applies kernel deinterlacing to the input.
F_lenscorrection: Rectifies the image by correcting for lens distortion.
-F_Life: Generate a life pattern.
+F_life: Generate a life pattern.
F_limiter: Limit pixels components to the specified range.
F_loop: Loops video frames.
F_lumakey: Turns a certain luma into transparency.
F_lut: Compute and apply a lookup
table to the RGB/YUV input video.
+F_lut1d: Adjust colors using a 1D LUT.
F_lut3d: Apply a 3D LUT (look up table) to an input video.
F_lutrgb: Compute and apply a lookup table to the RGB input video.
F_lutyuv: Combine and apply a lookup table to the YUV input video.
F_mandelbrot: Render a Mandelbrot fractal.
F_mcdeint: Applies motion compensating deinterlacing.
F_mestimate: Generate motion vectors.
+F_metadata: Manipulate video frame metadata.
F_mpdecimate: Remove near-duplicate frames.
F_mptestsrc: Generate various test pattern.
F_negate: Negates input video.
F_oscilloscope: 2D video oscilloscope. Useful to measure spatial impulse,
step responses, and chroma delays.
F_owndenoise: Denoises using wavelets.
-F_Pad: Add paddings to the input image, and place the original
+F_pad: Add paddings to the input image, and place the original
input at the provided x, y coordinates.
+F_pal100bars: Generate PAL 100% color bars.
+F_pal75bars: Generate PAL 75% color bars.
F_perms: Set permissions for the output video frame.
F_perspective: Corrects the perspective of video.
F_phase: Phases shift fields.
F_sab: Applies shape adaptive blur.
F_scale: Scale the input video size and/or convert the image format.
F_separatefields: Split input video frames into fields.
+F_setparams: Force field, or color property for the output video frame.
F_setrange: Force color range for the output video frame.
F_showinfo: Show textual information for each video frame.
F_showpalette: Display frame palette.
the outlines. Through the settings you can
select the radius,
the strength and the threshold of luma and chroma.
+F_smptebars: Generate SMPTE color bars.
+F_smptehdbars: Generate SMPTE HD color bars.
F_sobel: Applies sobel operator.
F_spp: Applies a simple post processing filter.
F_stereo3d: Converts video stereoscopic 3D view.
F_tile: Tile several successive frames together.
F_tinterlace: Performs temporal field interlacing.
F_tlut2: Compute and apply a lookup table from 2 successive frames.
+F_tmix: Mix successive video frames.
F_transpose: Transposes input video.
F_unsharp: Sharpen or blur the input video.
F_uspp: Applies Ultra Simple/Slow Post-processing filter.
F_vectorscope: Video vectorscope.
F_vflip: Flips the input video vertically.
F_vfrdet: Variable frame rate detect filter.
+F_vibrance: Boost or alter saturation.
F_vignette: Makes or reverses a vignette effect.
Through the settings you can set the circle center
position on a X-Y axis,choose the angle,
F_acompressor: Audio compressor.
F_acontrast: Simple audio dynamic range compression/expansion filter.
F_acrusher: Reduces audio bit resolution.
+F_acue: Delay filtering to match a cue.
F_adelay: Delays one or more audio channels.
+F_aderivative: Compute derivative of input audio.
F_aecho: Adds echoing to the audio.
F_aemphasis: Audio emphasis.
F_aeval: Filters audio signal according to a specific expression.
F_agate: Audio gate.
F_aiir: Apply infinite Impulse Response filter with supplied
coefficients.
+F_aintegral: Compute integral of input audio.
F_allpass: Applies a two-pole all-pass filter.
F_aloop: Loops audio samples.
+F_ametadata: Manipulate audio frame metadata.
F_anoisesrc: Generates a noise audio signal.
F_aperms: Set permissions for the output audio frame.
F_aphaser: Adds a phasing effect to the audio.
F_mcompand: Multiband compress or expand audiodynamic range. The input audio
is divided into bands which is like the crossover of a loudspeaker,
resulting in flat frequency response when absent compander action.
+F_pan: Remix channels with coefficients (panning).
F_silenceremove: Removes silence.
F_sine: Generate sine wave audio signal.
F_stereotools: Applies various stereo tools. When using this plugin,
#include "language.h"
#include "vframe.h"
-void SketcherPoint::init(int id, int x, int y)
+void SketcherPoint::init(int id, int pty, int x, int y)
{
- this->id = id;
+ this->id = id; this->pty = pty;
this->x = x; this->y = y;
}
SketcherPoint::SketcherPoint(int id)
{
- init(id, 0, 0);
+ init(id, PTY_LINE, 0, 0);
}
-SketcherPoint::SketcherPoint(int id, int x, int y)
+SketcherPoint::SketcherPoint(int id, int pty, int x, int y)
{
- init(id, x, y);
+ init(id, pty, x, y);
}
SketcherPoint::~SketcherPoint()
{
int SketcherPoint::equivalent(SketcherPoint &that)
{
return this->id == that.id &&
+ this->pty == that.pty &&
this->x == that.x &&
this->y == that.y ? 1 : 0;
}
void SketcherPoint::copy_from(SketcherPoint &that)
{
- this->id = that.id;
+ this->id = that.id; this->pty = that.pty;
this->x = that.x; this->y = that.y;
}
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("X", x);
output.tag.set_property("Y", y);
output.append_tag();
void SketcherPoint::read_data(FileXML &input)
{
id = atoi(input.tag.get_title() + 6);
+ pty = input.tag.get_property("TYPE", PTY_OFF);
x = input.tag.get_property("X", 0.f);
y = input.tag.get_property("Y", 0.f);
+ bclamp(pty, 0, PTY_SZ-1);
}
-void SketcherCurve::init(int id, int ty, int radius, int pen, int color)
+void SketcherCurve::init(int id, int pen, int radius, int color)
{
this->id = id;
- this->ty = ty;
this->radius = radius;
this->pen = pen;
this->color = color;
}
SketcherCurve::SketcherCurve(int id)
{
- init(id, 0, 1, 0, BLACK);
+ init(id, 1, PTY_LINE, CV_COLOR);
}
-SketcherCurve::SketcherCurve(int id, int ty, int radius,int pen, int color)
+SketcherCurve::SketcherCurve(int id, int pen, int radius, int color)
{
- init(id, ty, radius, pen, color);
+ init(id, pen, radius, color);
}
SketcherCurve::~SketcherCurve()
{
int SketcherCurve::equivalent(SketcherCurve &that)
{
if( this->id != that.id ) return 0;
- if( this->ty != that.ty ) return 0;
- if( this->radius != that.radius ) return 0;
if( this->pen != that.pen ) return 0;
+ if( this->radius != that.radius ) return 0;
if( this->color != that.color ) return 0;
int n = this->points.size();
if( n != that.points.size() ) return 0;
void SketcherCurve::copy_from(SketcherCurve &that)
{
this->id = that.id;
- this->ty = that.ty;
- this->radius = that.radius;
this->pen = that.pen;
+ this->radius = that.radius;
this->color = that.color;
int m = points.size(), n = that.points.size();
while( m > n ) points.remove_object_number(--m);
}
void SketcherCurve::save_data(FileXML &output)
{
- this->ty = ty;
this->pen = pen; this->color = color;
char curve[BCSTRLEN];
sprintf(curve,"/CURVE_%d",id);
output.tag.set_title(curve+1);
- output.tag.set_property("TYPE", ty);
- output.tag.set_property("RADIUS", radius);
output.tag.set_property("PEN", pen);
+ output.tag.set_property("RADIUS", radius);
output.tag.set_property("COLOR", color);
output.append_tag();
output.append_newline();
void SketcherCurve::read_data(FileXML &input)
{
id = atoi(input.tag.get_title() + 6);
- ty = input.tag.get_property("TYPE", 0);
+ pen = input.tag.get_property("PEN", PTY_OFF);
radius = input.tag.get_property("RADIUS", 1.);
- pen = input.tag.get_property("PEN", 0);
- color = input.tag.get_property("COLOR", BLACK);
+ color = input.tag.get_property("COLOR", CV_COLOR);
+ bclamp(pen, 0, PEN_SZ-1);
}
-int Sketcher::new_curve(int ty, int radius, int pen, int color)
+int Sketcher::new_curve(int pen, int radius, int color)
{
SketcherCurves &curves = config.curves;
int k = curves.size(), id = 1;
int n = config.curves[i]->id;
if( n >= id ) id = n + 1;
}
- SketcherCurve *cv = new SketcherCurve(id, ty, radius, pen, color);
+ SketcherCurve *cv = new SketcherCurve(id, pen, radius, color);
curves.append(cv);
config.cv_selected = k;
return k;
int Sketcher::new_curve()
{
- return new_curve(0, 1, 0, BLACK);
+ return new_curve(PEN_XLANT, 1, CV_COLOR);
}
-int Sketcher::new_point(SketcherCurve *cv, int x, int y)
+int Sketcher::new_point(SketcherCurve *cv, int pty, int x, int y, int idx)
{
- int k = cv->points.size(), id = 1;
- for( int i=k; --i>=0; ) {
+ 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, x, y);
- cv->points.append(pt);
- return k;
+ SketcherPoint *pt = new SketcherPoint(id, pty, 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 Sketcher::new_point(int idx)
{
int ci = config.cv_selected;
if( ci < 0 || ci >= config.curves.size() )
EDLSession *session = get_edlsession();
int x = !session ? 0.f : session->output_w / 2.f;
int y = !session ? 0.f : session->output_h / 2.f;
- return new_point(cv, x, y);
+ return new_point(cv, PTY_LINE, x, y, idx);
}
REGISTER_PLUGIN(Sketcher)
while( --k >= 0 && pcv->id != (ncv=next.curves[k])->id );
if( k >= 0 ) {
cv->id = pcv->id;
- cv->ty = pcv->ty;
- cv->radius = pcv->radius;
cv->pen = pcv->pen;
+ cv->radius = pcv->radius;
cv->color = pcv->color;
int prev_pt_sz = pcv->points.size(), next_pt_sz = ncv->points.size();
for( int j=0; j<prev_pt_sz; ++j ) {
x = x * prev_scale + nt->x * next_scale;
y = y * prev_scale + nt->y * next_scale;
}
- cv->points.append(new SketcherPoint(pt.id, x, y));
+ cv->points.append(new SketcherPoint(pt.id, pt.pty, x, y));
}
}
else
output.tag.set_title("SKETCHER");
output.tag.set_property("DRAG", config.drag);
- output.tag.set_property("CURVE_SELECTED", config.cv_selected);
- output.tag.set_property("POINT_SELECTED", config.pt_selected);
+ output.tag.set_property("CV_SELECTED", config.cv_selected);
+ output.tag.set_property("PT_SELECTED", config.pt_selected);
output.append_tag();
output.append_newline();
for( int i=0,n=config.curves.size(); i<n; ++i ) {
}
}
- if( !config.curves.size() ) {
- new_curve(0, 1, 0, BLACK);
- }
+ if( !config.curves.size() )
+ new_curve();
config.limits();
}
void Sketcher::draw_point(VFrame *vfrm, SketcherPoint *pt, int color, int d)
{
int r = d/2+1, x = pt->x, y = pt->y;
+ vfrm->set_pixel_color(color);
vfrm->draw_smooth(x-r,y+0, x-r, y-r, x+0,y-r);
vfrm->draw_smooth(x+0,y-r, x+r, y-r, x+r,y+0);
vfrm->draw_smooth(x+r,y+0, x+r, y+r, x+0,y+r);
vfrm->draw_smooth(x+0,y+r, x-r, y+r, x-r,y+0);
- vfrm->set_pixel_color(color);
vfrm->draw_x(pt->x, pt->y, d);
}
void Sketcher::draw_point(VFrame *vfrm, SketcherPoint *pt, int color)
return 0;
}
-void SketcherCurve::draw_line(VFrame *out)
+static int intersects_at(float &x, float &y,
+ float ax,float ay, float bx, float by, float cx,float cy, // line slope ab thru c
+ float dx,float dy, float ex, float ey, float fx,float fy, // line slope de thru f
+ float mx=0)
{
- SketcherPoint *pt0 = points[0];
- VFrame *vpen = new_vpen(out);
- out->set_pixel_color(color);
- int n = points.size();
- if( n >= 2 ) {
- for( int pi=1; pi<n; ++pi ) {
- SketcherPoint *pt1 = points[pi];
- vpen->draw_line(pt0->x, pt0->y, pt1->x, pt1->y);
- pt0 = pt1;
- }
- }
- else
- vpen->draw_pixel(pt0->x, pt0->y);
- delete vpen;
+ float badx = bx - ax, bady = by - ay;
+ float eddx = ex - dx, eddy = ey - dy;
+ float d = badx*eddy - bady*eddx;
+ int ret = 0;
+ if( fabsf(d) < 1 ) { ret = 1; d = signbit(d) ? -1 : 1; }
+ x = (badx*cy*eddx - badx*eddx*fy + badx*eddy*fx - bady*cx*eddx) / d;
+ y = (badx*cy*eddy - bady*cx*eddy - bady*eddx*fy + bady*eddy*fx) / d;
+ if( mx > 0 ) { bclamp(x, -mx,mx); bclamp(y, -mx,mx); }
+ return ret;
}
-/*
-# python
-from sympy import *
-var("x,y, ax,ay, bx,by, cx,cy, dx,dy")
-
-var("abdx,abdy, acdx,acdy, bddx,bddy, cddx,cddy");
-abdx = bx-ax; abdy = by-ay;
-acdx = cx-ax; acdy = cy-ay;
-bddx = dx-bx; bddy = dy-by;
-cddx = dx-cx; cddy = dy-cy;
-
-var("xc,yc, xd,yd, sx,sy");
-xc = (bx+dx)/2; yc = (by+dy)/2;
-xd = cx-xc; yd = cy-yc;
-ax = xc-xd; ay = yc-yd;
-# line thru b with slope (c-a) intersects line thru c with slope (d-b)
-sx = solve(((x - bx) * acdy/acdx + by) - ((x - cx) * bddy/bddx + cy),x)
-sy = solve(((y - by) * acdx/acdy + bx) - ((y - cy) * bddx/bddy + cx),y)
-
-var("zx,zy, zdx,zdy, sx,sy, px,py, qx,qy");
-# point z = (b+c)/2
-zx = (bx+cx)/2; zy = (by+cy)/2;
-zdx = (abdx+cddx)/2; zdy = (abdy+cddy)/2;
-# line thru z with slope (d-a) intersects line thru b with slope (c-a)
-px = solve(((x-zx)*zdy/zdx + zy) - ((x-bx) * acdy/acdx + by),x);
-py = solve(((y-zy)*zdx/zdy + zx) - ((y-by) * acdx/acdy + bx),y);
-# line thru z with slope (c-a + d-b)/2 intersects line thru c with slope (d-b)
-qx = solve(((x-zx)*zdy/zdx + zy) - ((x-cx) * bddy/bddx + cy),x);
-qy = solve(((y-zy)*zdx/zdy + zx) - ((y-cy) * bddx/bddy + cx),y);
-*/
-
-static void smooth_sxy(
- float ax, float ay, float bx, float by,
- float cx, float cy, float dx, float dy,
- float &sx, float &sy)
+static void smooth_axy(float &ax, float &ay,
+ float bx, float by, float cx, float cy, float dx, float dy)
{
- float acdx = cx-ax, acdy = cy-ay;
- float bddx = dx-bx, bddy = dy-by;
- float d = acdx*bddy - acdy*bddx;
- if( fabsf(d) < 1 ) d = 1;
- sx = (acdx*bddx*by - acdx*bddx*cy + acdx*bddy*cx - acdy*bddx*bx) / d;
- sy = (acdx*bddy*by - acdy*bddx*cy - acdy*bddy*bx + acdy*bddy*cx) / d;
- bclamp(sx, -4095.f, 4095.f);
- bclamp(sy, -4095.f, 4095.f);
-}
-
-static void smooth_pxy(
- float ax, float ay, float bx, float by,
- float cx, float cy, float dx, float dy,
- float &px, float &py)
-{
- float abdx = bx - ax, abdy = by - ay;
- float acdx = cx - ax, acdy = cy - ay;
- float cddx = dx - cx, cddy = dy - cy;
- float d = (2*(abdx*acdy - abdy*acdx - acdx*cddy + acdy*cddx));
- if( fabsf(d) < 1 ) d = 1;
- px = (-abdx*acdx*by + abdx*acdx*cy + 2*abdx*acdy*bx - abdy*acdx*bx - abdy*acdx*cx -
- acdx*bx*cddy - acdx*by*cddx + acdx*cddx*cy - acdx*cddy*cx + 2*acdy*bx*cddx) / d;
- py = (abdx*acdy*by + abdx*acdy*cy - 2*abdy*acdx*by + abdy*acdy*bx - abdy*acdy*cx -
- 2*acdx*by*cddy + acdy*bx*cddy + acdy*by*cddx + acdy*cddx*cy - acdy*cddy*cx) / d;
- bclamp(px, -4095.f, 4095.f);
- bclamp(py, -4095.f, 4095.f);
-}
-static void smooth_qxy(
- float ax, float ay, float bx, float by,
- float cx, float cy, float dx, float dy,
- float &qx, float &qy)
-{
- float abdx = bx - ax, abdy = by - ay;
- float bddx = dx - bx, bddy = dy - by;
- float cddx = dx - cx, cddy = dy - cy;
- float d = (2*(abdx*bddy - abdy*bddx - bddx*cddy + bddy*cddx));
- if( fabsf(d) < 1 ) d = 1;
- qx = (abdx*bddx*by - abdx*bddx*cy + 2*abdx*bddy*cx - abdy*bddx*bx - abdy*bddx*cx -
- bddx*bx*cddy + bddx*by*cddx - bddx*cddx*cy - bddx*cddy*cx + 2*bddy*cddx*cx) / d;
- qy = (abdx*bddy*by + abdx*bddy*cy - 2*abdy*bddx*cy - abdy*bddy*bx + abdy*bddy*cx -
- 2*bddx*cddy*cy - bddy*bx*cddy + bddy*by*cddx + bddy*cddx*cy + bddy*cddy*cx) / d;
- bclamp(qx, -4095.f, 4095.f);
- bclamp(qy, -4095.f, 4095.f);
+//middle of bd reflected around ctr
+// point ctr = b+d/2, dv=c-ctr, a=ctr-dv;
+ float xc = (bx+dx)*.5f, yc = (by+dy)*.5f;
+ float xd = cx - xc, yd = cy - yc;
+ ax = xc - xd; ay = yc - yd;
+}
+static void smooth_dxy(float &dx, float &dy,
+ float ax, float ay, float bx, float by, float cx, float cy)
+{
+//middle of ac reflected around ctr
+// point ctr = a+c/2, dv=c-ctr, d=ctr-dv;
+ float xc = (ax+cx)*.5f, yc = (ay+cy)*.5f;
+ float xd = bx - xc, yd = by - yc;
+ 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)
{
- float abdx = bx - ax, abdy = by - ay;
- float acdx = cx - ax, acdy = cy - ay;
- float bcdx = cx - bx, bcdy = cy - by;
- float bddx = dx - bx, bddy = dy - by;
+ float abdx = bx-ax, abdy = by-ay;
+ float acdx = cx-ax, acdy = cy-ay;
+ float bcdx = cx-bx, bcdy = cy-by;
+ float bddx = dx-bx, bddy = dy-by;
float abc = abdx*acdy - abdy*acdx;
float bcd = bcdx*bddy - bcdy*bddx;
float v = abc * bcd;
return !v ? 0 : v>0 ? 1 : -1;
}
+#endif
-void SketcherCurve::draw_smooth(VFrame *out)
+void SketcherCurve::draw(VFrame *out)
{
+ const float fmx = 16383;
VFrame *vpen = new_vpen(out);
out->set_pixel_color(color);
int n = points.size();
if( !n ) return;
if( n > 2 ) {
- SketcherPoint *pt0 = points[0], *pt1 = points[1], *pt2 = points[2];
- float bx = pt0->x, by = pt0->y;
- float cx = pt1->x, cy = pt1->y;
- float dx = pt2->x, dy = pt2->y;
- float xc = (bx+dx)/2.f, yc = (by+dy)/2.f;
- float xd = cx - xc, yd = cy - yc;
- float ax = xc - xd, ay = yc - yd;
- float sx, sy;
- for( int pi=0,n2=n-2; pi<n2; ++pi ) {
- float dx = points[pi+2]->x, dy = points[pi+2]->y;
- if( convex(ax,ay, bx,by, cx,cy, dx,dy) >= 0 ) {
- smooth_sxy(ax,ay, bx,by, cx,cy, dx,dy, sx, sy);
+ int n2 = n - 2;
+ SketcherPoint *pt0 = points[0];
+ SketcherPoint *pt1 = points[1];
+ SketcherPoint *pt2 = points[2];
+ float ax,ay, bx,by, cx,cy, dx,dy, sx,sy;
+ bx = pt0->x; by = pt0->y;
+ cx = pt1->x; cy = pt1->y;
+ dx = pt2->x; dy = pt2->y;
+ smooth_axy(ax,ay, bx,by, cx,cy, dx,dy);
+ for( int pi=0; pi<n2; ++pi ) {
+ int pty = points[pi]->pty;
+ dx = points[pi+2]->x; dy = points[pi+2]->y;
+ switch( pty ) {
+ case PTY_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);
- }
- else {
- float zx = (bx+cx)/2.f, zy = (by+cy)/2.f;
- smooth_pxy(ax,ay, bx,by, cx,cy, dx,dy, sx,sy);
- vpen->draw_smooth(bx,by, sx,sy, zx,zy);
- smooth_qxy(ax,ay, bx,by, cx,cy, dx,dy, sx,sy);
- vpen->draw_smooth(zx,zy, sx,sy, cx,cy);
+ break; }
}
ax = bx; ay = by;
bx = cx; by = cy;
cx = dx; cy = dy;
}
- xc = (ax+cx)/2.f; yc = (ay+cy)/2.f;
- xd = bx - xc, yd = by - yc;
- dx = xc - xd, dy = yc - yd;
- smooth_sxy(ax, ay, bx, by, cx, cy, dx, dy, sx, sy);
- vpen->draw_smooth(bx, by, sx, sy, cx, cy);
+ switch( points[n2]->pty ) {
+ case PTY_LINE:
+ vpen->draw_line(bx, by, cx, cy);
+ break;
+ case PTY_CURVE: {
+ smooth_dxy(dx,dy, ax,ay, bx,by, cx,cy);
+ 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; }
+ }
}
else if( n == 2 ) {
SketcherPoint *pt0 = points[0], *pt1 = points[1];
for( int ci=0, n=config.curves.size(); ci<n; ++ci ) {
SketcherCurve *cv = config.curves[ci];
int m = cv->points.size();
- if( !m ) continue;
- switch( cv->ty ) {
- case TYP_OFF:
- break;
- case TYP_SKETCHER:
- cv->draw_line(output);
- break;
- case TYP_SMOOTH:
- cv->draw_smooth(output);
- break;
- }
+ if( !m || cv->pen == PTY_OFF ) continue;
+ cv->draw(output);
}
if( config.drag ) {
for( int ci=0, n=config.curves.size(); ci<n; ++ci ) {
SketcherCurve *cv = config.curves[ci];
- for( int pi=0,m=cv->points.size(); pi<m; ++pi )
- draw_point(output, cv->points[pi], cv->color);
+ for( int pi=0,m=cv->points.size(); pi<m; ++pi ) {
+ int color = ci==config.cv_selected && pi==config.pt_selected ?
+ RED : cv->color ;
+ draw_point(output, cv->points[pi], color);
+ }
}
}
{
for( int i=0; i<size(); ++i ) {
SketcherCurve *cv = get(i);
- printf("Curve %d, id=%d, ty=%s, r=%d, pen=%s, color=%02x%02x%02x\n",
- i, cv->id, cv_type[cv->ty], cv->radius, cv_pen[cv->pen],
+ printf("Curve %d, id=%d, pen=%s, r=%d, color=%02x%02x%02x\n",
+ i, cv->id, cv_pen[cv->pen], cv->radius,
(cv->color>>16)&0xff, (cv->color>>8)&0xff, (cv->color>>0)&0xff);
cv->points.dump();
}
{
for( int i=0; i<size(); ++i ) {
SketcherPoint *pt = get(i);
- printf(" Pt %d, id=%d, x=%d, y=%d\n", i, pt->id, pt->x, pt->y);
+ printf(" Pt %d, id=%d, pty=%s, x=%d, y=%d\n",
+ i, pt->id, pt_type[pt->pty], pt->x, pt->y);
}
}
class Sketcher;
-enum { PT_ID, PT_X, PT_Y, PT_SZ };
-enum { CV_ID, CV_TY, CV_RAD, CV_PEN, CV_CLR, CV_SZ };
-enum { TYP_OFF, TYP_SKETCHER, TYP_SMOOTH, TYP_SZ };
-enum { PEN_SQUARE, PEN_PLUS, PEN_SLANT, PEN_XLANT, PEN_SZ };
+#define pt_type SketcherPoint::types
+#define cv_pen SketcherCurve::pens
+#define CV_COLOR WHITE
+
+enum { PT_ID, PT_TY, PT_X, PT_Y, PT_SZ };
+enum { CV_ID, CV_RAD, CV_PEN, CV_CLR, CV_SZ };
+enum { PTY_OFF, PTY_LINE, PTY_CURVE, PTY_SZ };
+enum { PEN_OFF, PEN_SQUARE, PEN_PLUS, PEN_SLANT, PEN_XLANT, PEN_SZ };
class SketcherVPen : public VFrame
{
class SketcherPoint
{
public:
- int id;
+ int id, pty;
int x, y;
- void init(int id, int x, int y);
- SketcherPoint(int id, int x, int y);
+ void init(int id, int pty, int x, int y);
+ SketcherPoint(int id, int pty, int x, int y);
SketcherPoint(int id=-1);
SketcherPoint(SketcherPoint &pt);
~SketcherPoint();
void copy_from(SketcherPoint &that);
void save_data(FileXML &output);
void read_data(FileXML &input);
+ static const char *types[PTY_SZ];
};
class SketcherPoints : public ArrayList<SketcherPoint *>
{
void dump();
};
-#define cv_type SketcherCurve::types
-#define cv_pen SketcherCurve::pens
class SketcherCurve
{
public:
- int id, ty, radius, pen, color;
- static const char *types[TYP_SZ];
+ int id, pen, radius, color;
static const char *pens[PEN_SZ];
SketcherPoints points;
- void init(int id, int ty, int radius, int pen, int color);
- SketcherCurve(int id, int ty, int radius, int pen, int color);
+ void init(int id, int pen, int radius, int color);
+ SketcherCurve(int id, int pen, int radius, int color);
SketcherCurve(int id=-1);
~SketcherCurve();
SketcherCurve(SketcherCurve &cv);
void save_data(FileXML &output);
void read_data(FileXML &input);
VFrame *new_vpen(VFrame *out);
- void draw_line(VFrame *out);
- void draw_smooth(VFrame *out);
+ void draw(VFrame *out);
};
class SketcherCurves : public ArrayList<SketcherCurve *>
{
public:
Sketcher(PluginServer *server);
~Sketcher();
-// required for all realtime plugins
PLUGIN_CLASS_MEMBERS2(SketcherConfig)
int is_realtime();
void update_gui();
void save_data(KeyFrame *keyframe);
void read_data(KeyFrame *keyframe);
- int new_curve(int ty, int radius, int pen, int color);
+ int new_curve(int pen, int radius, int color);
int new_curve();
- int new_point(SketcherCurve *cv, int x, int y);
- int new_point();
+ int new_point(SketcherCurve *cv, int pty, int x, int y, int idx=-1);
+ int new_point(int idx=-1);
int process_realtime(VFrame *input, VFrame *output);
static void draw_point(VFrame *vfrm, SketcherPoint *pt, int color, int d);
void draw_point(VFrame *vfrm, SketcherPoint *pt, int color);
#include "theme.h"
#include "track.h"
-#define COLOR_W 30
-#define COLOR_H 30
+#define AltMask Mod1Mask
-const char *SketcherCurve::types[] = {
+#define COLOR_W 32
+#define COLOR_H 24
+
+const char *SketcherPoint::types[] = {
N_("off"),
N_("line"),
- N_("smooth"),
+ N_("curve"),
};
const char *SketcherCurve::pens[] = {
+ N_("off"),
N_("box"),
N_("+"),
N_("/"),
N_("X"),
};
-SketcherCurveTypeItem::SketcherCurveTypeItem(int ty)
- : BC_MenuItem(_(cv_type[ty]))
-{
- this->ty = ty;
-}
-int SketcherCurveTypeItem::handle_event()
-{
- SketcherCurveType *popup = (SketcherCurveType*)get_popup_menu();
- popup->update(ty);
- SketcherWindow *gui = popup->gui;
- SketcherConfig &config = gui->plugin->config;
- int ci = config.cv_selected;
- if( ci >= 0 && ci < config.curves.size() ) {
- SketcherCurve *cv = config.curves[ci];
- cv->ty = ty;
- gui->curve_list->update(ci);
- gui->send_configure_change();
- }
- return 1;
-}
-
-SketcherCurveType::SketcherCurveType(SketcherWindow *gui, int x, int y, int ty)
- : BC_PopupMenu(x,y,64,_(cv_type[ty]))
-{
- this->gui = gui;
-}
-void SketcherCurveType::create_objects()
-{
- int n = sizeof(cv_type)/sizeof(cv_type[0]);
- for( int ty=0; ty<n; ++ty )
- add_item(new SketcherCurveTypeItem(ty));
-}
-void SketcherCurveType::update(int ty)
-{
- set_text(_(cv_type[ty]));
-}
-
SketcherCurvePenItem::SketcherCurvePenItem(int pen)
- : BC_MenuItem(_(cv_pen[pen]))
+ : BC_MenuItem(_(SketcherCurve::pens[pen]))
{
this->pen = pen;
}
}
-SketcherCurveColor::SketcherCurveColor(SketcherWindow *gui, int x, int y, int w)
+SketcherCurveColor::SketcherCurveColor(SketcherWindow *gui, int x, int y, int w, int h)
: BC_Button(x, y, w, vframes)
{
this->gui = gui;
- this->color = BLACK;
+ this->color = CV_COLOR;
for( int i=0; i<3; ++i ) {
- vframes[i] = new VFrame(w, w, BC_RGBA8888);
+ vframes[i] = new VFrame(w, h, BC_RGB888);
vframes[i]->clear_frame();
}
}
for( int i=0; i<3; ++i ) {
VFrame *vframe = vframes[i];
int ww = vframe->get_w(), hh = vframe->get_h();
- int cx = (ww+1)/2, cy = hh/2;
- double cc = (cx*cx + cy*cy) / 4.;
- uint8_t *bp = vframe->get_data(), *dp = bp;
- uint8_t *ep = dp + vframe->get_data_size();
+ uint8_t **rows = vframe->get_rows();
int rr = r, gg = g, bb = b;
- int bpl = vframe->get_bytes_per_line();
switch( i ) {
case BUTTON_UP:
break;
if( (bb-=48) < 0x00 ) bb = 0x00;
break;
}
- while( dp < ep ) {
- int yy = (dp-bp) / bpl, xx = ((dp-bp) % bpl) >> 2;
- int dy = cy - yy, dx = cx - xx;
- double s = dx*dx + dy*dy - cc;
- double ss = s < 0 ? 1 : s >= cc ? 0 : 1 - s/cc;
- int aa = ss * 0xff;
- *dp++ = rr; *dp++ = gg; *dp++ = bb; *dp++ = aa;
+ for( int y=0; y<hh; ++y ) {
+ uint8_t *rp = rows[y];
+ for( int x=0; x<ww; ++x ) {
+ *rp++ = rr; *rp++ = gg; *rp++ = bb;
+ }
}
}
set_images(vframes);
if( ci >= 0 && ci < config.curves.size() ) {
SketcherCurve *cv = config.curves[ci];
SketcherPointList *point_list = gui->point_list;
- int hot_point = point_list->get_selection_number(0, 0);
+ int pi = config.pt_selected;
SketcherPoints &points = cv->points;
- if( hot_point >= 0 && hot_point < points.size() ) {
+ if( pi >= 0 && pi < points.size() ) {
int v = atoi(get_text());
- points[hot_point]->x = v;
- point_list->set_point(hot_point, PT_X, v);
- point_list->update_list(hot_point);
+ points[pi]->x = v;
+ point_list->set_point(pi, PT_X, v);
+ point_list->update_list(pi);
gui->send_configure_change();
}
}
if( ci >= 0 && ci < config.curves.size() ) {
SketcherCurve *cv = config.curves[ci];
SketcherPointList *point_list = gui->point_list;
- int hot_point = point_list->get_selection_number(0, 0);
+ int pi = config.pt_selected;
SketcherPoints &points = cv->points;
- if( hot_point >= 0 && hot_point < points.size() ) {
+ if( pi >= 0 && pi < points.size() ) {
int v = atoi(get_text());
- points[hot_point]->y = v;
- point_list->set_point(hot_point, PT_Y, v);
- point_list->update_list(hot_point);
+ points[pi]->y = v;
+ point_list->set_point(pi, PT_Y, v);
+ point_list->update_list(pi);
gui->send_configure_change();
}
}
: PluginClientWindow(plugin, 380, 580, 380, 580, 0)
{
this->plugin = plugin;
- this->title_type = 0; this->curve_type = 0;
this->title_pen = 0; this->curve_pen = 0;
this->title_color = 0; this->curve_color = 0;
this->color_picker = 0; this->new_points = 0;
void SketcherWindow::create_objects()
{
- int x = 10, y = 10, x1, y1;
+ int x = 10, y = 10, dy = 0, x1, y1;
int margin = plugin->get_theme()->widget_border;
BC_Title *title;
int ci = plugin->config.cv_selected;
if( ci < 0 || ci >= plugin->config.curves.size() )
- ci = plugin->new_curve(0, 1, 0, BLACK);
+ ci = plugin->new_curve();
SketcherCurve *cv = plugin->config.curves[ci];
- add_subwindow(reset_curves = new SketcherResetCurves(this, plugin, x1=x, y+3));
+
+ reset_curves = new SketcherResetCurves(this, plugin, x1=x, y+3);
+ add_subwindow(reset_curves); dy = bmax(dy,reset_curves->get_h());
x1 += reset_curves->get_w() + 2*margin;
const char *curve_text = _("Curve");
- add_subwindow(title_radius = new BC_Title(x1, y, _("Width:")));
+ title_radius = new BC_Title(x1, y, _("Width:"));
+ add_subwindow(title_radius); dy = bmax(dy,title_radius->get_h());
x1 += title_radius->get_w() + margin;
curve_radius = new SketcherCurveRadius(this, x1, y, cv->radius);
curve_radius->create_objects();
- y += reset_curves->get_h() + 2*margin;
+ y += dy + 2*margin; dy = 0;
+
x1 = get_w()-x - BC_Title::calculate_w(this, curve_text, LARGEFONT);
y1 = y-margin - BC_Title::calculate_h(this, curve_text, LARGEFONT);
- add_subwindow(title = new BC_Title(x1, y1, curve_text, LARGEFONT,
- get_resources()->menu_highlighted_fontcolor));
- add_subwindow(curve_list = new SketcherCurveList(this, plugin, x, y));
- y += curve_list->get_h() + margin;
- add_subwindow(title_type = new BC_Title(x, y, _("Type:")));
- x1 = x + title_type->get_w() + margin;
- add_subwindow(curve_type = new SketcherCurveType(this, x1, y, cv->ty));
- curve_type->create_objects();
- x1 += curve_type->get_w() + margin;
- add_subwindow(new_curve = new SketcherNewCurve(this, plugin, x1, y));
+ title = new BC_Title(x1, y1, curve_text, LARGEFONT,
+ get_resources()->menu_highlighted_fontcolor);
+ add_subwindow(title); dy = bmax(dy,title->get_h());
+ curve_list = new SketcherCurveList(this, plugin, x, y);
+ add_subwindow(curve_list); dy = bmax(dy,curve_list->get_h());
+ y += dy + margin; dy = 0;
+
+ new_curve = new SketcherNewCurve(this, plugin, x1=x, y);
+ add_subwindow(new_curve); dy = bmax(dy,new_curve->get_h());
x1 += new_curve->get_w() + margin;
- add_subwindow(curve_up = new SketcherCurveUp(this, x1, y));
- x1 += curve_up->get_w() + 2*margin;
- add_subwindow(title_color = new BC_Title(x1, y, _("Color:")));
- y += curve_type->get_h() + margin;
-
- add_subwindow(title_pen = new BC_Title(x, y, _("Pen:")));
- x1 = x + title_pen->get_w() + margin;
- add_subwindow(curve_pen = new SketcherCurvePen(this, x1, y, cv->pen));
- curve_pen->create_objects();
- x1 += curve_pen->get_w() + margin;
- add_subwindow(del_curve = new SketcherDelCurve(this, plugin, x1, y));
+ curve_up = new SketcherCurveUp(this, x1, y);
+ add_subwindow(curve_up); dy = bmax(dy,curve_up->get_h());
+ x1 += curve_up->get_w() + 4*margin;
+ title_pen = new BC_Title(x1+30, y, _("Pen:"));
+ add_subwindow(title_pen); dy = bmax(dy,title_pen->get_h());
+ int x2 = (get_w()+x1)/2;
+ title_color = new BC_Title(x2+10, y, _("Color:"));
+ add_subwindow(title_color); dy = bmax(dy,title_color->get_h());
+ y += dy + margin; dy = 0;
+
+ del_curve = new SketcherDelCurve(this, plugin, x1=x, y);
+ add_subwindow(del_curve); dy = bmax(dy,del_curve->get_h());
x1 += del_curve->get_w() + margin;
- add_subwindow(curve_dn = new SketcherCurveDn(this, x1, y));
- x1 += curve_dn->get_w() + 2*margin;
- add_subwindow(curve_color = new SketcherCurveColor(this, x1, y, COLOR_W));
- curve_color->create_objects();
+ curve_dn = new SketcherCurveDn(this, x1, y);
+ add_subwindow(curve_dn); dy = bmax(dy,curve_dn->get_h());
+ x1 += curve_dn->get_w() + 4*margin;
+ curve_pen = new SketcherCurvePen(this, x1, y, cv->pen);
+ add_subwindow(curve_pen); dy = bmax(dy,curve_pen->get_h());
+ curve_pen->create_objects();
+ curve_color = new SketcherCurveColor(this, x2+20, y, COLOR_W, COLOR_H);
+ add_subwindow(curve_color); dy = bmax(dy,curve_color->get_h());
curve_color->set_color(cv->color);
curve_color->draw_face();
- y += COLOR_H + margin;
+ y += dy + margin; dy = 0;
curve_list->update(ci);
BC_Bar *bar;
- add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
- y += bar->get_h() + 2*margin;
+ bar = new BC_Bar(x, y, get_w()-2*x);
+ add_subwindow(bar); dy = bmax(dy,bar->get_h());
+ y += dy + 2*margin;
int pi = plugin->config.pt_selected;
SketcherPoint *pt = pi >= 0 && pi < cv->points.size() ? cv->points[pi] : 0;
- add_subwindow(reset_points = new SketcherResetPoints(this, plugin, x1=x, y+3));
- x1 += reset_points->get_w() + 2*margin;
- add_subwindow(drag = new SketcherDrag(this, x1, y));
- y += drag->get_h() + margin;
+ reset_points = new SketcherResetPoints(this, plugin, x1=x, y+3);
+ add_subwindow(reset_points); dy = bmax(dy,reset_points->get_h());
+ x1 += reset_points->get_w() + 2*margin;
if( plugin->config.drag ) {
- if( !grab(plugin->server->mwindow->cwindow->gui) )
+ if( !grab(plugin->server->mwindow->cwindow->gui) ) {
eprintf("drag enabled, but compositor already grabbed\n");
+ plugin->config.drag = 0;
+ }
}
+ drag = new SketcherDrag(this, x1, y);
+ add_subwindow(drag); dy = bmax(dy,drag->get_h());
+ x1 += drag->get_w() + 2*margin;
+ int pty = pt ? pt->pty : PTY_LINE;
+ point_type = new SketcherPointType(this, x1, y, pty);
+ add_subwindow(point_type); dy = bmax(dy,point_type->get_h());
+ point_type->create_objects();
+ y += dy + margin; dy = 0;
+
const char *point_text = _("Point");
x1 = get_w()-x - BC_Title::calculate_w(this, point_text, LARGEFONT);
y1 = y-margin - BC_Title::calculate_h(this, point_text, LARGEFONT);
add_subwindow(title = new BC_Title(x1, y1, point_text, LARGEFONT,
get_resources()->menu_highlighted_fontcolor));
- add_subwindow(point_list = new SketcherPointList(this, plugin, x, y));
+ point_list = new SketcherPointList(this, plugin, x, y);
+ add_subwindow(point_list); dy = bmax(dy,point_list->get_h());
+ y += dy + margin; dy = 0;
- y += point_list->get_h() + margin;
- add_subwindow(title_x = new BC_Title(x, y, _("X:")));
- x1 = x + title_x->get_w() + margin;
- point_x = new SketcherPointX(this, x1, y, !pt ? 0.f : pt->x);
- point_x->create_objects();
- x1 += point_x->get_w() + 2*margin;
- add_subwindow(new_point = new SketcherNewPoint(this, plugin, x1, y));
+ new_point = new SketcherNewPoint(this, plugin, x1=x, y);
+ add_subwindow(new_point); dy = bmax(dy,new_point->get_h());
x1 += new_point->get_w() + margin;
- add_subwindow(point_up = new SketcherPointUp(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 SketcherPointY(this, x1, y, !pt ? 0.f : pt->y);
- point_y->create_objects();
- x1 += point_y->get_w() + 2*margin;
- add_subwindow(del_point = new SketcherDelPoint(this, plugin, x1, y));
+ point_up = new SketcherPointUp(this, x1, y);
+ add_subwindow(point_up); dy = bmax(dy,point_up->get_h());
+ x1 += point_up->get_w() + 2*margin;
+ title_x = new BC_Title(x1, y, _("X:"));
+ add_subwindow(title_x); dy = bmax(dy,title_x->get_h());
+ x1 += title_x->get_w() + margin;
+ point_x = new SketcherPointX(this, x1, y, !pt ? 0.f : pt->x);
+ point_x->create_objects(); dy = bmax(dy, point_x->get_h());
+ y += dy + margin; dy = 0;
+
+ del_point = new SketcherDelPoint(this, plugin, x1=x, y);
+ add_subwindow(del_point); dy = bmax(dy,del_point->get_h());
x1 += del_point->get_w() + margin;
- add_subwindow(point_dn = new SketcherPointDn(this, x1, y));
- y += point_y->get_h() + margin + 10;
+ point_dn = new SketcherPointDn(this, x1, y);
+ add_subwindow(point_dn); dy = bmax(dy,point_dn->get_h());
+ x1 += point_dn->get_w() + 2*margin;
+ title_y = new BC_Title(x1, y, _("Y:"));
+ add_subwindow(title_y); dy = bmax(dy,title_y->get_h());
+ x1 += title_y->get_w() + margin;
+ point_y = new SketcherPointY(this, x1, y, !pt ? 0.f : pt->y);
+ point_y->create_objects(); dy = bmax(dy, point_y->get_h());
+ y += dy + margin + 5;
point_list->update(pi);
add_subwindow(notes0 = new BC_Title(x, y,
_("\n"
- "LMB=\n"
- "Alt+LMB=\n"
- "MMB=\n"
+ "Shift=\n"
+ "None=\n"
+ "Ctrl=\n"
+ "Alt=\n"
"DEL=\n")));
add_subwindow(notes1 = new BC_Title(x+80, y,
- _(" No Shift\n"
+ _(" LMB\n"
+ "new line point\n"
"select point\n"
- "drag curve\n"
- "next curve type\n"
+ "drag point\n"
+ "new curve\n"
"deletes point\n")));
add_subwindow(notes2 = new BC_Title(x+200, y,
- _(" Shift\n"
- "append new points\n"
- "drag image\n"
- "append new curve\n"
- "delete curve\n")));
+ _(" RMB\n"
+ "new arc point\n"
+ "select curve\n"
+ "drag curve\n"
+ "drag all curves\n"
+ "deletes curve\n")));
show_window(1);
}
if( keysym_lookup(event) > 0 ) {
switch( get_keysym() ) {
case XK_Delete:
+ pending_config = 1;
return (event->xkey.state & ShiftMask) ?
del_curve->handle_event() :
del_point->handle_event() ;
switch( event->type ) {
case ButtonPress:
if( dragging ) return 0;
- dragging = event->xbutton.state & Mod1Mask ? -1 : 1; // alt_down
+ dragging = 1;
break;
case ButtonRelease:
case MotionNotify:
return 0;
}
-
- int ci = plugin->config.cv_selected;
+ SketcherConfig &config = plugin->config;
+ int ci = config.cv_selected;
if( ci < 0 || ci >= plugin->config.curves.size() )
return 1;
+ SketcherCurves &curves = config.curves;
+ SketcherCurve *cv = curves[ci];
+ int pi = config.pt_selected;
float cursor_x = cx, cursor_y = cy;
canvas->canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
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;
- SketcherCurve *cv = plugin->config.curves[ci];
SketcherPoints &points = cv->points;
int state = event->xmotion.state;
switch( event->type ) {
case ButtonPress: {
- if( dragging < 0 ) break;
- int hot_point = -1;
int button_no = event->xbutton.button;
- if( button_no == LEFT_BUTTON ) {
-// create new point string
- if( (state & ShiftMask) ) {
+ switch( button_no ) {
+ case LEFT_BUTTON: {
+ if( (state & ShiftMask) ) { // create new point/string
++new_points;
- hot_point = plugin->new_point(cv, output_x, output_y);
- point_list->update(hot_point);
+ pi = plugin->new_point(cv, PTY_LINE, output_x, output_y, pi+1);
+ point_list->update(pi);
+ break;
}
- else {
-// select point
- int sz = points.size();
- int last_point = hot_point;
- if( sz > 0 ) {
- SketcherPoint *pt = points[hot_point=0];
- double dist = DISTANCE(output_x,output_y, pt->x,pt->y);
- for( int i=1; i<sz; ++i ) {
- pt = points[i];
- double d = DISTANCE(output_x,output_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);
- if( dist >= HANDLE_W ) hot_point = -1;
- }
- if( hot_point != last_point ) {
- SketcherPoint *pt = 0;
- if( hot_point >= 0 && hot_point < sz ) {
- 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);
+ if( (state & AltMask) ) { // create new curve
+ ci = plugin->new_curve(cv->pen, cv->radius, cv->color);
+ curve_list->update(ci);
+ point_list->update(-1);
+ break;
+ }
+ SketcherPoint *pt = 0; // select point
+ int last_point = pi; pi = -1;
+ int n = points.size();
+ double dist = DBL_MAX;
+ for( int i=0; i<n; ++i ) {
+ SketcherPoint *p = points[i];
+ double d = DISTANCE(output_x,output_y, p->x,p->y);
+ if( d < dist ) { dist = d; pi = i; pt = p; }
+ }
+ if( pt ) {
+ float px = (pt->x - track_w / 2) * projector_z + projector_x;
+ float py = (pt->y - track_h / 2) * projector_z + projector_y;
+ float pix = DISTANCE(px, py, cursor_x,cursor_y);
+ if( pix >= HANDLE_W ) { pi = -1; pt = 0; }
+ }
+ if( pi != last_point )
+ point_list->set_selected(pi);
+ break; }
+ case RIGHT_BUTTON: {
+ if( (state & ShiftMask) ) { // create new curve point
+ ++new_points;
+ pi = plugin->new_point(cv, PTY_CURVE,
+ output_x, output_y, pi+1);
+ point_list->update(pi);
+ break;
+ }
+ SketcherPoint *pt = 0; // select point
+ double dist = DBL_MAX;
+ ci = -1;
+ for( int i=0; i<curves.size(); ++i ) {
+ SketcherCurve *crv = curves[i];
+ int pts = crv->points.size();
+ for( int k=0; k<pts; ++k ) {
+ SketcherPoint *p = crv->points[k];
+ double d = DISTANCE(output_x,output_y, p->x,p->y);
+ if( d < dist ) {
+ dist = d;
+ pt = p; pi = k;
+ cv = crv; ci = i;
}
- point_list->update_list(hot_point);
- point_x->update(pt ? pt->x : 0.f);
- point_y->update(pt ? pt->y : 0.f);
}
}
- }
- else if( button_no == MIDDLE_BUTTON ) {
- if( (state & ShiftMask) ) {
- int ci = plugin->new_curve(cv->ty, cv->radius, cv->pen, cv->color);
- curve_list->update(ci);
- point_list->update(-1);
+ if( pt ) {
+ float px = (pt->x - track_w / 2) * projector_z + projector_x;
+ float py = (pt->y - track_h / 2) * projector_z + projector_y;
+ float pix = DISTANCE(px, py, cursor_x,cursor_y);
+ if( pix >= HANDLE_W ) { pi = -1; pt = 0; }
}
- else {
- int ty = cv->ty + 1;
- if( ty >= TYP_SZ ) ty = 0;
- cv->ty = ty;
- curve_type->update(ty);
+ if( pi >= 0 ) {
curve_list->update(ci);
+ point_list->update(pi);
}
+ break; }
}
break; }
case MotionNotify: {
- int hot_point = point_list->get_selection_number(0, 0);
- if( dragging < 0 ) {
- SketcherCurves &curves = plugin->config.curves;
- int dx = round(output_x - last_x);
- int dy = round(output_y - last_y);
- int mnc = (state & ShiftMask) || ci<0 ? 0 : ci;
- int mxc = (state & ShiftMask) ? curves.size() : ci+1;
- for( int i=mnc; i<mxc; ++i ) {
- SketcherCurve *crv = plugin->config.curves[i];
- int pts = crv->points.size();
- for( int k=0; k<pts; ++k ) {
- SketcherPoint *pt = crv->points[k];
- pt->x += dx; pt->y += dy;
+ if( (state & ShiftMask) ) { // string of points
+ if( (state & (Button1Mask|Button3Mask)) ) {
+ if( pi < 0 ) pi = points.size()-1;
+ if( pi >= 0 ) {
+ SketcherPoint *pt = pi >= 0 && pi < points.size() ? points[pi] : 0;
+ float frac_w = DISTANCE(pt->x, pt->y, output_x, output_y) / get_w();
+ if( frac_w < 0.01 ) break; // 1 percent w
}
+ ++new_points;
+ int pty = (state & Button1Mask) ? PTY_LINE : PTY_CURVE;
+ pi = plugin->new_point(cv, pty, output_x, output_y, pi+1);
+ point_list->update(pi);
+ break;
}
- SketcherPoint *pt = hot_point >= 0 && hot_point < points.size() ?
- points[hot_point] : 0;
- point_x->update(pt ? pt->x : 0.f);
- point_y->update(pt ? pt->y : 0.f);
- point_list->update(hot_point);
- break;
}
if( (state & Button1Mask) ) {
- SketcherPoint *pt = hot_point >= 0 && hot_point < points.size() ?
- points[hot_point] : 0;
- if( pt && pt->x == output_x && pt->y == output_y ) break;
- if( new_points ) {
+ if( (state & ControlMask) ) { // drag selected point
+ SketcherPoint *pt = pi >= 0 && pi < points.size() ? points[pi] : 0;
if( pt ) {
- float frac_w = DISTANCE(pt->x, pt->y, output_x, output_y) / get_w();
- if( frac_w < 0.01 ) break; // 1 percent w
- }
- if( (state & ShiftMask) ) {
- ++new_points;
- hot_point = plugin->new_point(cv, output_x, output_y);
- point_list->update(hot_point);
+ point_list->set_point(pi, PT_X, pt->x = output_x);
+ point_list->set_point(pi, PT_Y, pt->y = output_y);
+ point_list->update_list(pi);
+ point_x->update(pt->x);
+ point_y->update(pt->y);
}
+ break;
}
- else if( pt ) {
- 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->update_list(hot_point);
- point_x->update(pt->x);
- point_y->update(pt->y);
+ }
+ if( (state & Button3Mask) ) {
+ if( (state & (ControlMask | AltMask)) ) { // drag selected curve(s)
+ SketcherCurves &curves = plugin->config.curves;
+ int dx = round(output_x - last_x);
+ int dy = round(output_y - last_y);
+ int mnc = (state & AltMask) || ci<0 ? 0 : ci;
+ int mxc = (state & AltMask) ? curves.size() : ci+1;
+ for( int i=mnc; i<mxc; ++i ) {
+ SketcherCurve *crv = plugin->config.curves[i];
+ int pts = crv->points.size();
+ for( int k=0; k<pts; ++k ) {
+ SketcherPoint *pt = crv->points[k];
+ pt->x += dx; pt->y += dy;
+ }
+ }
+ SketcherPoint *pt = pi >= 0 && pi < points.size() ?
+ points[pi] : 0;
+ point_x->update(pt ? pt->x : 0.f);
+ point_y->update(pt ? pt->y : 0.f);
+ point_list->update(pi);
+ break;
}
}
break; }
unlock_window();
delete color_picker;
color_picker = new SketcherCurveColorPicker(this, color_button);
- int color = BLACK, ci = plugin->config.cv_selected;
+ int color = CV_COLOR, ci = plugin->config.cv_selected;
if( ci >= 0 && ci < plugin->config.curves.size() ) {
SketcherCurve *cv = plugin->config.curves[ci];
color = cv->color;
this->gui = gui;
this->plugin = plugin;
titles[CV_ID] = _("id"); widths[CV_ID] = 64;
- titles[CV_TY] = _("type"); widths[CV_TY] = 64;
titles[CV_RAD] = _("radius"); widths[CV_RAD] = 64;
titles[CV_PEN] = _("pen"); widths[CV_PEN] = 64;
titles[CV_CLR] = _("color"); widths[CV_CLR] = 64;
return 1;
}
+void SketcherCurveList::set_curve(int i, int c, const char *cp)
+{
+ cols[c].get(i)->set_text(cp);
+}
+
void SketcherCurveList::set_selected(int k)
{
int ci = -1;
if( k >= 0 && k < plugin->config.curves.size() ) {
SketcherCurve *cv = plugin->config.curves[k];
- gui->curve_type->update(cv->ty);
gui->curve_radius->update(cv->radius);
gui->curve_pen->update(cv->pen);
gui->curve_color->update_gui(cv->color);
ci = k;
}
plugin->config.cv_selected = ci;
- update_selection(&cols[0], ci);
- update_list(-1);
+ update_list(ci);
}
void SketcherCurveList::update_list(int k)
{
int xpos = get_xposition(), ypos = get_yposition();
- if( k < 0 ) k = get_selection_number(0, 0);
- update_selection(&cols[0], k);
+ if( k >= 0 ) update_selection(&cols[0], k);
BC_ListBox::update(&cols[0], &titles[0],&widths[0],CV_SZ, xpos,ypos,k);
center_selection();
}
for( int i=0; i<sz; ++i ) {
SketcherCurve *cv = curves[i];
char itxt[BCSTRLEN]; sprintf(itxt,"%d", cv->id);
- char ttxt[BCSTRLEN]; sprintf(ttxt,"%s", cv_type[cv->ty]);
- char rtxt[BCSTRLEN]; sprintf(rtxt,"%d", cv->radius);
char ptxt[BCSTRLEN]; sprintf(ptxt,"%s", cv_pen[cv->pen]);
+ char rtxt[BCSTRLEN]; sprintf(rtxt,"%d", cv->radius);
int color = cv->color;
int r = (color>>16)&0xff, g = (color>>8)&0xff, b = (color>>0)&0xff;
char ctxt[BCSTRLEN]; sprintf(ctxt,"#%02x%02x%02x", r, g, b);
- add_curve(itxt, ttxt, rtxt, ptxt, ctxt);
+ add_curve(itxt, ptxt, rtxt, ctxt);
}
set_selected(k);
}
-void SketcherCurveList::add_curve(const char *id, const char *type,
- const char *radius, const char *pen, const char *color)
+void SketcherCurveList::add_curve(const char *id, const char *pen,
+ const char *radius, const char *color)
{
cols[CV_ID].append(new BC_ListBoxItem(id));
- cols[CV_TY].append(new BC_ListBoxItem(type));
cols[CV_RAD].append(new BC_ListBoxItem(radius));
cols[CV_PEN].append(new BC_ListBoxItem(pen));
cols[CV_CLR].append(new BC_ListBoxItem(color));
}
int SketcherNewCurve::handle_event()
{
- int ty = 1, pen = 0, color = 0, radius = 1;
+ int pen = PTY_LINE, radius = 1, color = CV_COLOR;
int ci = plugin->config.cv_selected;
if( ci >= 0 && ci < plugin->config.curves.size() ) {
SketcherCurve *cv = plugin->config.curves[ci];
- ty = cv->ty; pen = cv->pen;
- color = cv->color; radius = cv->radius;
+ pen = cv->pen; radius = cv->radius; color = cv->color;
}
- int k = plugin->new_curve(ty, radius, pen, color);
- gui->curve_list->update(k);
+ ci = plugin->new_curve(pen, radius, color);
+ gui->curve_list->update(ci);
gui->point_list->update(-1);
gui->send_configure_change();
return 1;
}
int SketcherDelCurve::handle_event()
{
- int hot_curve = gui->curve_list->get_selection_number(0, 0);
- SketcherCurves &curves = plugin->config.curves;
- if( hot_curve >= 0 && hot_curve < curves.size() ) {
- curves.remove_object_number(hot_curve);
- if( --hot_curve < 0 )
- hot_curve = plugin->new_curve(0, 1, 0, BLACK);
- gui->curve_list->update(hot_curve);
+ SketcherConfig &config = plugin->config;
+ int ci = config.cv_selected;
+ SketcherCurves &curves = config.curves;
+ if( ci >= 0 && ci < curves.size() ) {
+ curves.remove_object_number(ci--);
+ if( ci < 0 ) ci = 0;
+ if( !curves.size() )
+ ci = plugin->new_curve();
+ gui->curve_list->update(ci);
gui->point_list->update(-1);
gui->send_configure_change();
}
int SketcherCurveUp::handle_event()
{
- SketcherCurves &curves = gui->plugin->config.curves;
- int hot_curve = gui->curve_list->get_selection_number(0, 0);
-
- if( hot_curve > 0 && hot_curve < curves.size() ) {
- SketcherCurve *&cv0 = curves[hot_curve];
- SketcherCurve *&cv1 = curves[--hot_curve];
+ SketcherConfig &config = gui->plugin->config;
+ int ci = config.cv_selected;
+ SketcherCurves &curves = config.curves;
+ if( ci > 0 && ci < curves.size() ) {
+ SketcherCurve *&cv0 = curves[ci];
+ SketcherCurve *&cv1 = curves[--ci];
SketcherCurve *t = cv0; cv0 = cv1; cv1 = t;
- gui->curve_list->update(hot_curve);
+ gui->curve_list->update(ci);
}
gui->send_configure_change();
return 1;
int SketcherCurveDn::handle_event()
{
- SketcherCurves &curves = gui->plugin->config.curves;
- int hot_curve = gui->curve_list->get_selection_number(0, 0);
-
- if( hot_curve >= 0 && hot_curve < curves.size()-1 ) {
- SketcherCurve *&cv0 = curves[hot_curve];
- SketcherCurve *&cv1 = curves[++hot_curve];
+ SketcherConfig &config = gui->plugin->config;
+ int ci = config.cv_selected;
+ SketcherCurves &curves = config.curves;
+ if( ci >= 0 && ci < curves.size()-1 ) {
+ SketcherCurve *&cv0 = curves[ci];
+ SketcherCurve *&cv1 = curves[++ci];
SketcherCurve *t = cv0; cv0 = cv1; cv1 = t;
- gui->curve_list->update(hot_curve);
+ gui->curve_list->update(ci);
}
gui->send_configure_change();
return 1;
}
+SketcherPointTypeItem::SketcherPointTypeItem(int pty)
+ : BC_MenuItem(_(pt_type[pty]))
+{
+ this->pty = pty;
+}
+int SketcherPointTypeItem::handle_event()
+{
+ SketcherPointType *popup = (SketcherPointType*)get_popup_menu();
+ popup->update(pty);
+ SketcherWindow *gui = popup->gui;
+ SketcherConfig &config = gui->plugin->config;
+ SketcherCurves &curves = config.curves;
+ int ci = config.cv_selected;
+ if( ci < 0 || ci >= curves.size() )
+ return 1;
+ SketcherCurve *cv = curves[ci];
+ SketcherPoints &points = cv->points;
+ int pi = config.pt_selected;
+
+ ArrayList<int> selected;
+ for( int v,i=0; (v=gui->point_list->get_selection_number(0, i))>=0; ++i )
+ selected.append(v);
+
+ for( int i=selected.size(); --i>=0; ) {
+ int k = selected[i];
+ if( k < 0 || k >= points.size() ) continue;
+ SketcherPoint *pt = cv->points[k];
+ pt->pty = pty;
+ gui->point_list->set_point(k, PT_TY, _(pt_type[pty]));
+ }
+
+ gui->point_list->update_list(pi);
+ gui->send_configure_change();
+ return 1;
+}
+
+SketcherPointType::SketcherPointType(SketcherWindow *gui, int x, int y, int pty)
+ : BC_PopupMenu(x,y,64,_(pt_type[pty]))
+{
+ this->gui = gui;
+}
+void SketcherPointType::create_objects()
+{
+ for( int pty=0; pty<PT_SZ; ++pty )
+ add_item(new SketcherPointTypeItem(pty));
+}
+void SketcherPointType::update(int pty)
+{
+ set_text(_(pt_type[pty]));
+}
+
+
SketcherPointList::SketcherPointList(SketcherWindow *gui, Sketcher *plugin, int x, int y)
: BC_ListBox(x, y, 360, 130, LISTBOX_TEXT)
{
this->gui = gui;
this->plugin = plugin;
- titles[PT_X] = _("X"); widths[PT_X] = 90;
- titles[PT_Y] = _("Y"); widths[PT_Y] = 90;
- titles[PT_ID] = _("ID"); widths[PT_ID] = 50;
+ titles[PT_ID] = _("ID"); widths[PT_ID] = 50;
+ titles[PT_TY] = _("Type"); widths[PT_TY] = 80;
+ titles[PT_X] = _("X"); widths[PT_X] = 90;
+ titles[PT_Y] = _("Y"); widths[PT_Y] = 90;
+ set_selection_mode(LISTBOX_MULTIPLE);
}
SketcherPointList::~SketcherPointList()
{
int SketcherPointList::handle_event()
{
int pi = get_selection_number(0, 0);
+ if( get_selection_number(0, 1) >= 0 ) pi = -1;
set_selected(pi);
gui->send_configure_change();
return 1;
return 1;
}
-void SketcherPointList::add_point(const char *id, const char *xp, const char *yp)
+void SketcherPointList::add_point(const char *id, const char *ty, const char *xp, const char *yp)
{
cols[PT_ID].append(new BC_ListBoxItem(id));
+ cols[PT_TY].append(new BC_ListBoxItem(ty));
cols[PT_X].append(new BC_ListBoxItem(xp));
cols[PT_Y].append(new BC_ListBoxItem(yp));
}
SketcherCurve *cv = plugin->config.curves[ci];
pt = k >= 0 && k < cv->points.size() ? cv->points[pi=k] : 0;
}
+ gui->point_type->update(pt ? pt->pty : PTY_OFF);
gui->point_x->update(pt ? pt->x : 0.f);
gui->point_y->update(pt ? pt->y : 0.f);
plugin->config.pt_selected = pi;
- update_selection(&cols[0], pi);
- update_list(k);
+ update_list(pi);
}
void SketcherPointList::update_list(int k)
{
int xpos = get_xposition(), ypos = get_yposition();
- if( k < 0 ) k = get_selection_number(0, 0);
- update_selection(&cols[0], k);
+ if( k >= 0 ) update_selection(&cols[0], k);
BC_ListBox::update(&cols[0], &titles[0],&widths[0],PT_SZ, xpos,ypos,k);
center_selection();
}
for( int i=0; i<sz; ++i ) {
SketcherPoint *pt = points[i];
char itxt[BCSTRLEN]; sprintf(itxt,"%d", pt->id);
+ char ttxt[BCSTRLEN]; sprintf(ttxt,"%s", _(pt_type[pt->pty]));
char xtxt[BCSTRLEN]; sprintf(xtxt,"%d", pt->x);
char ytxt[BCSTRLEN]; sprintf(ytxt,"%d", pt->y);
- add_point(itxt, xtxt, ytxt);
+ add_point(itxt, ttxt, xtxt, ytxt);
}
}
set_selected(k);
point_list->update(pi);
SketcherCurve *cv = ci >= 0 ? config.curves[ci] : 0;
curve_radius->update(cv ? cv->radius : 1);
- curve_type->update(cv ? cv->ty : TYP_OFF);
curve_pen->update(cv ? cv->pen : PEN_SQUARE);
- curve_color->set_color(cv ? cv->color : BLACK);
+ curve_color->set_color(cv ? cv->color : CV_COLOR);
SketcherPoint *pt = pi >= 0 ? cv->points[pi] : 0;
point_x->update(pt ? pt->x : 0);
point_y->update(pt ? pt->y : 0);
return 1;
SketcherCurve *cv = config.curves[ci];
SketcherPoints &points = cv->points;
- int sz = points.size();
- int hot_point = gui->point_list->get_selection_number(0, 0);
+ if( points.size() < 2 )
+ return 1;
+ int pi = config.pt_selected;
+
+ ArrayList<int> selected;
+ for( int v,i=0; (v=gui->point_list->get_selection_number(0, i))>=0; ++i )
+ selected.append(v);
- if( sz > 1 && hot_point > 0 ) {
- SketcherPoint *&pt0 = points[hot_point];
- SketcherPoint *&pt1 = points[--hot_point];
+ for( int i=0; i<selected.size(); ++i ) {
+ int k = selected[i];
+ if( k <= 0 ) continue;
+ if( k == pi ) --pi;
+ SketcherPoint *&pt0 = points[k];
+ SketcherPoint *&pt1 = points[--k];
SketcherPoint *t = pt0; pt0 = pt1; pt1 = t;
- gui->point_list->update(hot_point);
}
+ gui->point_list->update(pi);
gui->send_configure_change();
return 1;
}
return 1;
SketcherCurve *cv = config.curves[ci];
SketcherPoints &points = cv->points;
- int sz = points.size();
- int hot_point = gui->point_list->get_selection_number(0, 0);
- if( sz > 1 && hot_point < sz-1 ) {
- SketcherPoint *&pt0 = points[hot_point];
- SketcherPoint *&pt1 = points[++hot_point];
+ int sz1 = points.size()-1;
+ if( sz1 < 1 )
+ return 1;
+ int pi = config.pt_selected;
+
+ ArrayList<int> selected;
+ for( int v,i=0; (v=gui->point_list->get_selection_number(0, i))>=0; ++i )
+ selected.append(v);
+
+ for( int i=selected.size(); --i>=0; ) {
+ int k = selected[i];
+ if( k >= sz1 ) continue;
+ if( k == pi ) ++pi;
+ SketcherPoint *&pt0 = points[k];
+ SketcherPoint *&pt1 = points[++k];
SketcherPoint *t = pt0; pt0 = pt1; pt1 = t;
- gui->point_list->update(hot_point);
}
+ gui->point_list->update(pi);
gui->send_configure_change();
return 1;
}
}
int SketcherNewPoint::handle_event()
{
- int k = plugin->new_point();
+ int pi = plugin->config.pt_selected;
+ int k = plugin->new_point(pi+1);
gui->point_list->update(k);
gui->send_configure_change();
return 1;
int SketcherDelPoint::handle_event()
{
SketcherConfig &config = gui->plugin->config;
+ SketcherCurves &curves = config.curves;
int ci = config.cv_selected;
- if( ci >= 0 && ci < config.curves.size() ) {
- SketcherCurve *cv = config.curves[ci];
- SketcherPoints &points = cv->points;
- int hot_point = gui->point_list->get_selection_number(0, 0);
- if( hot_point >= 0 && hot_point < points.size() ) {
- points.remove_object_number(hot_point);
- gui->point_list->update(--hot_point);
- gui->send_configure_change();
- }
+ if( ci < 0 || ci >= curves.size() )
+ return 1;
+ SketcherCurve *cv = curves[ci];
+ SketcherPoints &points = cv->points;
+ int pi = config.pt_selected;
+
+ ArrayList<int> selected;
+ for( int v,i=0; (v=gui->point_list->get_selection_number(0, i))>=0; ++i )
+ selected.append(v);
+
+ for( int i=selected.size(); --i>=0; ) {
+ int k = selected[i];
+ if( k < 0 || k >= points.size() ) continue;
+ points.remove_object_number(k);
+ if( k == pi && --pi < 0 && points.size() > 0 ) pi = 0;
}
+ gui->point_list->update(pi);
+ gui->send_configure_change();
return 1;
}
{
SketcherConfig &config = plugin->config;
config.curves.remove_all_objects();
- int ci = plugin->new_curve(0, 1, 0, BLACK);
+ int ci = plugin->new_curve();
gui->curve_list->update(ci);
gui->point_list->update(-1);
gui->send_configure_change();
class SketcherPointX;
class SketcherPointY;
class SketcherDrag;
+class SketcherPointTypeItem;
+class SketcherPointType;
class SketcherPointList;
class SketcherNewPoint;
class SketcherDelPoint;
class SketcherResetPoints;
class SketcherWindow;
+
class SketcherNum : public BC_TumbleTextBox
{
public:
int update(int v) { return BC_TumbleTextBox::update((int64_t)v); }
};
-class SketcherCurveTypeItem : public BC_MenuItem
-{
-public:
- SketcherCurveTypeItem(int ty);
- int handle_event();
- int ty;
-};
-
-class SketcherCurveType : public BC_PopupMenu
-{
-public:
- SketcherCurveType(SketcherWindow *gui, int x, int y, int ty);
- void create_objects();
- void update(int ty);
-
- SketcherWindow *gui;
-};
-
class SketcherCurvePenItem : public BC_MenuItem
{
public:
public:
SketcherCurvePen(SketcherWindow *gui, int x, int y, int pen);
void create_objects();
- void update(int ty);
+ void update(int pen);
SketcherWindow *gui;
};
class SketcherCurveColor : public BC_Button
{
public:
- SketcherCurveColor(SketcherWindow *gui, int x, int y, int w);
+ SketcherCurveColor(SketcherWindow *gui, int x, int y, int w, int h);
~SketcherCurveColor();
void set_color(int color);
int column_resize_event();
ArrayList<BC_ListBoxItem*> cols[CV_SZ];
void clear();
- void add_curve(const char *id, const char *type,
- const char *radius, const char *pen, const char *color);
+ void add_curve(const char *id, const char *pen,
+ const char *radius, const char *color);
void del_curve(int i);
+ void set_curve(int i, int c, const char *cp);
void set_selected(int k);
void update(int k);
void update_list(int k);
SketcherWindow *gui;
};
+class SketcherPointTypeItem : public BC_MenuItem
+{
+public:
+ SketcherPointTypeItem(int pty);
+ int handle_event();
+ int pty;
+};
+
+class SketcherPointType : public BC_PopupMenu
+{
+public:
+ SketcherPointType(SketcherWindow *gui, int x, int y, int pty);
+ void create_objects();
+ void update(int pty);
+
+ SketcherWindow *gui;
+};
+
class SketcherPointList : public BC_ListBox
{
int column_resize_event();
ArrayList<BC_ListBoxItem*> cols[PT_SZ];
void clear();
- void add_point(const char *id, const char *xp, const char *yp);
+ void add_point(const char *id, const char *ty, const char *xp, const char *yp);
void set_point(int i, int c, int v);
void set_point(int i, int c, const char *cp);
void set_selected(int k);
Sketcher *plugin;
- BC_Title *title_type, *title_pen;
- BC_Title *title_color, *title_radius;
+ BC_Title *title_pen, *title_color, *title_radius;
SketcherCurveType *curve_type;
SketcherCurvePen *curve_pen;
SketcherCurveColor *curve_color;
SketcherCurveList *curve_list;
SketcherResetCurves *reset_curves;
+ SketcherResetPoints *reset_points;
+ SketcherDrag *drag;
+ SketcherPointType *point_type;
+ SketcherPointList *point_list;
BC_Title *title_x, *title_y;
SketcherPointX *point_x;
SketcherPointY *point_y;
int dragging, pending_config;
int new_points;
float last_x, last_y;
- SketcherDrag *drag;
- SketcherPointList *point_list;
- SketcherResetPoints *reset_points;
BC_Title *notes0, *notes1, *notes2;
};
#endif