#define OVERSAMPLE 8
+#if 1
+// Bresenham's
+void MaskUnit::draw_line_clamped(VFrame *frame,
+ int x1,int y1, int x2,int y2, unsigned char k)
+{
+ int w = frame->get_w(), h = frame->get_h();
+ unsigned char **rows = (unsigned char**)frame->get_rows();
+ int dx = x2-x1, dy = y2-y1;
+//printf("MaskUnit::draw_line_clamped(%d,%d -> %d,%d, 0x%02x\n", x1,y1, x2,y2, k);
+
+ int ax = 2*abs(dx), ay = 2*abs(dy);
+
+ if( ax > ay ) { /* x dominant */
+ if( dx == 0 ) return;
+ if( x1 > x2 ) {
+ int xx = x2; x2 = x1; x1 = xx;
+ int yy = y2; y2 = y1; y1 = yy;
+ }
+ if( x1 >= w || x2 < 0 ) return;
+ if( dx < 0 ) { dx = -dx; dy = -dy; }
+ int x = x1, y = y1, d = dx;
+ int sy = dy < 0 ? -1 : 1;
+ if( x1 < 0 ) {
+ double py = -(double)dy/dx * x1 + y1 + 0.5;
+ x = 0; y = py;
+ d = (py - y) * ay;
+ }
+ for( int y0=-1;;) {
+ if( x >= w ) return;
+ if( y != y0 && y >= 0 && y < h ) {
+ y0 = y;
+ unsigned char *bp = rows[y] + x;
+ *bp = *bp == k ? 0 : k;
+ }
+ if( x == x2 ) return;
+ if( d < 0 ) { d += ax; y += sy; }
+ d -= ay; ++x;
+ }
+ }
+ else { /* y dominant */
+ if( dy == 0 ) return;
+ if( y1 > y2 ) {
+ int xx = x2; x2 = x1; x1 = xx;
+ int yy = y2; y2 = y1; y1 = yy;
+ }
+ if( y1 >= h || y2 < 0 ) return;
+ if( dy < 0 ) { dx = -dx; dy = -dy; }
+ int x = x1, y = y1, d = dy;
+ int sx = dx < 0 ? -1 : 1;
+ if( y1 < 0 ) {
+ double px = -(double)dx/dy * y1 + x1 + 0.5;
+ x = px; y = 0;
+ d = (px - x) * ax;
+ }
+ for(;;) {
+ if( y >= h ) return;
+ if( x >= 0 && x < w ) {
+ unsigned char *bp = rows[y] + x;
+ *bp = *bp == k ? 0 : k;
+ }
+ if( y == y2 ) return;
+ if( d < 0 ) { d += ay; x += sx; }
+ d -= ax; ++y;
+ }
+ }
+}
-
-
-
-
-
-
-
-
-
-
-
+#else
void MaskUnit::draw_line_clamped(VFrame *frame,
- int &x1,
- int &y1,
- int x2,
- int y2,
- unsigned char k)
+ int x1, int y1, int x2, int y2, unsigned char k)
{
- int draw_x1;
- int draw_y1;
- int draw_x2;
- int draw_y2;
+ int draw_x1, draw_y1;
+ int draw_x2, draw_y2;
- if(y2 < y1)
- {
- draw_x1 = x2;
- draw_y1 = y2;
- draw_x2 = x1;
- draw_y2 = y1;
+ if(y2 < y1) {
+ draw_x1 = x2; draw_y1 = y2;
+ draw_x2 = x1; draw_y2 = y1;
}
- else
- {
- draw_x1 = x1;
- draw_y1 = y1;
- draw_x2 = x2;
- draw_y2 = y2;
+ else {
+ draw_x1 = x1; draw_y1 = y1;
+ draw_x2 = x2; draw_y2 = y2;
}
unsigned char **rows = (unsigned char**)frame->get_rows();
- if(draw_y2 != draw_y1)
- {
+ if(draw_y2 != draw_y1) {
float slope = ((float)draw_x2 - draw_x1) / ((float)draw_y2 - draw_y1);
int w = frame->get_w() - 1;
int h = frame->get_h();
- for(float y = draw_y1; y < draw_y2; y++)
- {
- if(y >= 0 && y < h)
- {
+ for(float y = draw_y1; y < draw_y2; y++) {
+ if(y >= 0 && y < h) {
int x = (int)((y - draw_y1) * slope + draw_x1);
int y_i = (int)y;
int x_i = CLIP(x, 0, w);
}
}
+#endif
+
void MaskUnit::blur_strip(double *val_p,
double *val_m,
double *dst,
{
if (buttonpress != 3)
{
- if(i == AUTOMATION_FADE)
+ if(i == AUTOMATION_FADE || i == AUTOMATION_SPEED)
synchronize_autos(0,
track,
(FloatAuto*)mwindow->session->drag_auto,
{
if( 1e-6 > fabs(ref_pos) || isnan(ref_pos))
return 0.0;
- else
- return ref_pos / position;
+ return ref_pos / position;
}
float automation_min = mwindow->edl->local_session->automation_mins[autogrouptype];
float automation_max = mwindow->edl->local_session->automation_maxs[autogrouptype];
float automation_range = automation_max - automation_min;
- if(0 == automation_range || isnan(auto_value) || isinf(auto_value))
+ if( 0 >= automation_range || isnan(auto_value) || isinf(auto_value) )
return 0;
- else
- return (auto_value - automation_min) / automation_range;
+ return (auto_value - automation_min) / automation_range;
}
void TrackCanvas::synchronize_autos(float change,
- Track *skip,
- FloatAuto *fauto,
- int fill_gangs)
+ Track *skip, FloatAuto *fauto, int fill_gangs)
{
// Handles the special case of modifying a fadeauto
// when there are ganged faders on several tracks
// (skip and fauto may be NULL if fill_gangs==-1)
- if (fill_gangs == 1 && skip->gang)
- {
- for(Track *current = mwindow->edl->tracks->first;
- current;
- current = NEXT)
- {
- if(current->data_type == skip->data_type &&
- current->gang &&
- current->record &&
- current != skip)
- {
- FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[AUTOMATION_FADE];
- double position = skip->from_units(fauto->position);
- FloatAuto *previous = 0, *next = 0;
- float init_value = fade_autos->get_value(fauto->position, PLAY_FORWARD, previous, next);
- FloatAuto *keyframe;
- keyframe = (FloatAuto*)fade_autos->get_auto_at_position(position);
-
- if (!keyframe)
- {
+ if( fill_gangs > 0 && skip->gang ) {
+ double position = skip->from_units(fauto->position);
+ int autoidx = fauto->autos->autoidx;
+
+ for(Track *current = mwindow->edl->tracks->first; current; current = NEXT) {
+ if( (current->data_type == skip->data_type || get_double_click()) &&
+ current->gang && current->record && current != skip ) {
+ int64_t current_position = current->to_units(position, 1);
+ FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[autoidx];
+ float auto_min = mwindow->edl->local_session->automation_mins[fade_autos->autogrouptype];
+ float auto_max = mwindow->edl->local_session->automation_maxs[fade_autos->autogrouptype];
+ FloatAuto *previous = 0, *next = 0;
+ FloatAuto *keyframe = (FloatAuto*)fade_autos->get_auto_at_position(current_position);
+ if( !keyframe ) {
// create keyframe on neighbouring track at the point in time given by fauto
- keyframe = (FloatAuto*)fade_autos->insert_auto(fauto->position);
- keyframe->set_value(init_value + change);
+ float init_value = fade_autos->get_value(current_position, PLAY_FORWARD, previous, next);
+ float new_value = init_value + change;
+ CLAMP(new_value, auto_min, auto_max);
+ keyframe = (FloatAuto*)fade_autos->insert_auto(current_position);
+ keyframe->set_value(new_value);
}
- else
- {
+ else {
// keyframe exists, just change it
- keyframe->adjust_to_new_coordinates(fauto->position, keyframe->get_value() + change);
+ float new_value = keyframe->get_value() + change;
+ CLAMP(new_value, auto_min, auto_max);
+ keyframe->adjust_to_new_coordinates(current_position, new_value);
// need to (re)set the position, as the existing node could be on a "equivalent" position (within half a frame)
}
mwindow->session->drag_auto_gang->append((Auto *)keyframe);
}
}
- } else
-// move the gangs
- if (fill_gangs == 0)
- {
-// Move the gang!
- for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
- {
+ }
+ else if( !fill_gangs ) {
+ double position = skip->from_units(fauto->position);
+// Move the gangs
+ for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++) {
FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
-
+ int64_t keyframe_position = keyframe->autos->track->to_units(position, 1);
float new_value = keyframe->get_value() + change;
CLAMP(new_value,
mwindow->edl->local_session->automation_mins[keyframe->autos->autogrouptype],
mwindow->edl->local_session->automation_maxs[keyframe->autos->autogrouptype]);
- keyframe->adjust_to_new_coordinates(fauto->position, new_value);
+ keyframe->adjust_to_new_coordinates(keyframe_position, new_value);
}
}
- else
+ else {
// remove the gangs
- if (fill_gangs == -1)
- {
- for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++)
- {
+ for (int i = 0; i < mwindow->session->drag_auto_gang->total; i++) {
FloatAuto *keyframe = (FloatAuto *)mwindow->session->drag_auto_gang->values[i];
keyframe->autos->remove_nonsequential(
keyframe);
#define UPDATE_DRAG_HEAD(do_clamp) \
- int result = 0; \
+ int result = 0, center_pixel; \
if(!current->autos->track->record) return 0; \
- double view_start; \
- double unit_start; \
- double view_end; \
- double unit_end; \
- double yscale; \
- int center_pixel; \
- double zoom_sample; \
- double zoom_units; \
+ double view_start, unit_start, view_end, unit_end; \
+ double yscale, zoom_sample, zoom_units; \
\
calculate_viewport(current->autos->track, \
- view_start, \
- unit_start, \
- view_end, \
- unit_end, \
- yscale, \
- center_pixel, \
- zoom_sample, \
- zoom_units); \
+ view_start, unit_start, view_end, unit_end, \
+ yscale, center_pixel, zoom_sample, zoom_units); \
\
float percentage = (float)(mwindow->session->drag_origin_y - cursor_y) / \
- yscale + \
- mwindow->session->drag_start_percentage; \
+ yscale + mwindow->session->drag_start_percentage; \
if(do_clamp) CLAMP(percentage, 0, 1); \
\
int64_t position = Units::to_int64(zoom_units * \
(cursor_x - mwindow->session->drag_origin_x) + \
mwindow->session->drag_start_position); \
- \
if((do_clamp) && position < 0) position = 0;
FloatAuto *current = (FloatAuto*)mwindow->session->drag_auto;
UPDATE_DRAG_HEAD(mwindow->session->drag_handle == 0);
- int x = cursor_x - mwindow->session->drag_origin_x; \
- int y = cursor_y - mwindow->session->drag_origin_y; \
-
- float value;
- float old_value;
+ int x = cursor_x - mwindow->session->drag_origin_x;
+ int y = cursor_y - mwindow->session->drag_origin_y;
+ float value, old_value;
+
+ if( mwindow->session->drag_handle == 0 && (ctrl_down() && !shift_down()) ) {
+// not really editing the node, rather start editing the curve
+// tangent is editable and drag movement is significant
+ if( (FloatAuto::FREE == current->curve_mode ||
+ FloatAuto::TFREE==current->curve_mode) &&
+ (fabs(x) > HANDLE_W / 2 || fabs(y) > HANDLE_W / 2))
+ mwindow->session->drag_handle = x < 0 ? 1 : 2;
+ }
- switch(mwindow->session->drag_handle)
- {
-// Center
- case 0:
- if(ctrl_down())
- // not really editing the node, rather start editing the curve
- {
- // tangent is editable and drag movement is significant
- if( (FloatAuto::FREE == current->curve_mode ||
- FloatAuto::TFREE==current->curve_mode) &&
- (fabs(x) > HANDLE_W / 2 || fabs(y) > HANDLE_W / 2))
- mwindow->session->drag_handle = x < 0 ? 1 : 2;
- break;
- }
+ switch(mwindow->session->drag_handle) {
+ case 0: // Center
// Snap to nearby values
- old_value = current->get_value();
- if(shift_down())
- {
- double value1;
- double distance1;
- double value2;
- double distance2;
-
- if(current->previous)
- {
- int autogrouptype = current->previous->autos->autogrouptype;
- value = percentage_to_value(percentage, 0, 0, autogrouptype);
- value1 = ((FloatAuto*)current->previous)->get_value();
- distance1 = fabs(value - value1);
- current->set_value(value1);
- }
+ old_value = current->get_value();
+ if(shift_down()) {
+ double value1, value2, distance1, distance2;
- if(current->next)
- {
- int autogrouptype = current->next->autos->autogrouptype;
- value = percentage_to_value(percentage, 0, 0, autogrouptype);
- value2 = ((FloatAuto*)current->next)->get_value();
- distance2 = fabs(value - value2);
- if(!current->previous || distance2 < distance1)
- {
- current->set_value(value2);
- }
- }
+ if(current->previous) {
+ int autogrouptype = current->previous->autos->autogrouptype;
+ value = percentage_to_value(percentage, 0, 0, autogrouptype);
+ value1 = ((FloatAuto*)current->previous)->get_value();
+ distance1 = fabs(value - value1);
+ current->set_value(value1);
+ }
- if(!current->previous && !current->next)
- {
- current->set_value( ((FloatAutos*)current->autos)->default_);
+ if(current->next) {
+ int autogrouptype = current->next->autos->autogrouptype;
+ value = percentage_to_value(percentage, 0, 0, autogrouptype);
+ value2 = ((FloatAuto*)current->next)->get_value();
+ distance2 = fabs(value - value2);
+ if(!current->previous || distance2 < distance1) {
+ current->set_value(value2);
}
- value = current->get_value();
}
- else
- {
- int autogrouptype = current->autos->autogrouptype;
- value = percentage_to_value(percentage, 0, 0, autogrouptype);
+
+ if(!current->previous && !current->next) {
+ current->set_value( ((FloatAutos*)current->autos)->default_);
}
+ value = current->get_value();
+ }
+ else {
+ int autogrouptype = current->autos->autogrouptype;
+ value = percentage_to_value(percentage, 0, 0, autogrouptype);
+ }
- if(alt_down())
+ if(alt_down() && !shift_down())
// ALT constrains movement: fixed position, only changing the value
- position = mwindow->session->drag_start_position;
+ position = mwindow->session->drag_start_position;
- if(value != old_value || position != current->position)
- {
- result = 1;
- float change = value - old_value;
- current->adjust_to_new_coordinates(position, value);
- synchronize_autos(change, current->autos->track, current, 0);
- show_message(current, 1,", %.2f", current->get_value());
- }
- break;
+ if(value != old_value || position != current->position) {
+ result = 1;
+ float change = value - old_value;
+ current->adjust_to_new_coordinates(position, value);
+ synchronize_autos(change, current->autos->track, current, 0);
+ show_message(current, 1,", %.2f", current->get_value());
+ }
+ break;
// In control
- case 1:
+ case 1: {
+ int autogrouptype = current->autos->autogrouptype;
+ value = percentage_to_value(percentage, 0, current, autogrouptype);
+ if(value != current->get_control_in_value())
{
- int autogrouptype = current->autos->autogrouptype;
- value = percentage_to_value(percentage, 0, current, autogrouptype);
- if(value != current->get_control_in_value())
- {
- result = 1;
- // note: (position,value) need not be at the location of the ctrl point,
- // but could be somewhere in between on the curve (or even outward or
- // on the opposit side). We set the new control point such as
- // to point the curve through (position,value)
- current->set_control_in_value(
- value * levered_position(position - current->position,
- current->get_control_in_position()));
- synchronize_autos(0, current->autos->track, current, 0);
- show_message(current, 1,", %.2f", current->get_control_in_value());
- }
+ result = 1;
+ // note: (position,value) need not be at the location of the ctrl point,
+ // but could be somewhere in between on the curve (or even outward or
+ // on the opposit side). We set the new control point such as
+ // to point the curve through (position,value)
+ current->set_control_in_value(
+ value * levered_position(position - current->position,
+ current->get_control_in_position()));
+ synchronize_autos(0, current->autos->track, current, 0);
+ show_message(current, 1,", %.2f", current->get_control_in_value());
}
- break;
+ break; }
// Out control
- case 2:
- {
- int autogrouptype = current->autos->autogrouptype;
- value = percentage_to_value(percentage, 0, current, autogrouptype);
- if(value != current->get_control_out_value())
- {
- result = 1;
- current->set_control_out_value(
- value * levered_position(position - current->position,
- current->get_control_out_position()));
- synchronize_autos(0, current->autos->track, current, 0);
- show_message(current, 1,", %.2f", current->get_control_out_value());
- }
+ case 2: {
+ int autogrouptype = current->autos->autogrouptype;
+ value = percentage_to_value(percentage, 0, current, autogrouptype);
+ if(value != current->get_control_out_value()) {
+ result = 1;
+ current->set_control_out_value(
+ value * levered_position(position - current->position,
+ current->get_control_out_position()));
+ synchronize_autos(0, current->autos->track, current, 0);
+ show_message(current, 1,", %.2f", current->get_control_out_value());
}
- break;
+ break; }
}
return result;