1 #include "bezierauto.h"
2 #include "bezierautos.h"
6 #include "transportque.inc"
9 BezierAutos::BezierAutos(EDL *edl,
21 old_selected = new BezierAuto(edl, 0);
22 new_selected = new BezierAuto(edl, 0);
23 this->center_x = center_x;
24 this->center_y = center_y;
25 this->center_z = center_z;
26 this->virtual_w = virtual_w;
27 this->virtual_h = virtual_h;
34 Auto* BezierAutos::new_auto()
36 return new BezierAuto(edl, this);
39 BezierAutos::~BezierAutos()
45 int BezierAutos::paste_derived(FileXML *xml, int64_t start)
47 int64_t frame = xml->tag.get_property("FRAME", 0);
48 BezierAuto* current = (BezierAuto*)add_auto(frame + start, 0, 0, 1);
50 current->position += start; // fix the position loaded by load()
53 int BezierAutos::draw(BC_SubWindow *canvas,
56 float units_per_pixel,
63 int BezierAutos::get_auto_pixel(int64_t position, float view_start, float units_per_pixel, int frame_half)
67 result = (int)((position - view_start) / units_per_pixel) + frame_half;
72 int64_t BezierAutos::get_auto_frame(int position, float view_start, float units_per_pixel, int frame_half)
76 result = (int64_t)((position) * units_per_pixel + view_start);
81 int BezierAutos::get_frame_half(float scale, int vertical, float units_per_pixel)
83 int result = (int)(.5 * scale * (vertical ? frame_h : frame_w));
84 if(1 / units_per_pixel / 2 < result) result = (int)(1 / units_per_pixel / 2);
88 int BezierAutos::get_center(float &x,
96 frame = (direction == PLAY_FORWARD) ? frame : (frame - 1);
97 get_neighbors(frame, frame, (Auto**)before, (Auto**)after);
99 // printf("BezierAutos::get_center %lld %p %p\n", frame, *before, *after);
100 // printf("BezierAutos::get_center %lld %lld\n",
101 // *before ? (*before)->position : -1,
102 // *after ? (*after)->position : -1);
103 if(*before == 0 && *after == 0)
105 x = ((BezierAuto*)default_auto)->center_x;
106 y = ((BezierAuto*)default_auto)->center_y;
107 z = ((BezierAuto*)default_auto)->center_z;
108 //printf("BezierAutos::get_center %f %f %f\n", x, y, z);
112 if(*before == *after)
114 x = ((BezierAuto*)*before)->center_x;
115 y = ((BezierAuto*)*before)->center_y;
116 z = ((BezierAuto*)*before)->center_z;
117 //printf("BezierAutos::get_center %lld %lld %f %f %f\n",
118 //frame, (*before)->position, x, y, z);
122 float x0, x1, x2, x3;
123 float y0, y1, y2, y3;
124 float z0, z1, z2, z3;
125 float frame0, frame1;
129 x0 = (*before)->center_x;
130 y0 = (*before)->center_y;
131 z0 = (*before)->center_z;
132 // printf("BezierAutos::get_center 1 %f %f %f\n",
136 frame0 = (float)(*before)->position;
138 if(*after == 0 || frame == frame0)
146 x1 = (*before)->control_out_x + x0;
147 y1 = (*before)->control_out_y + y0;
148 z1 = (*before)->control_out_z + z0;
153 x3 = (*after)->center_x;
154 y3 = (*after)->center_y;
155 z3 = (*after)->center_z;
156 // printf("BezierAutos::get_center 2 %f %f %f\n",
160 frame1 = (float)(*after)->position;
162 if(*before == 0 || frame == frame1)
170 x2 = (*after)->control_in_x + x3;
171 y2 = (*after)->control_in_y + y3;
172 z2 = (*after)->control_in_z + z3;
175 float t = (frame - frame0) / (frame1 - frame0);
177 float tpow3 = t * t * t;
179 float invtpow2 = invt * invt;
180 float invtpow3 = invt * invt * invt;
183 + 3 * t * invtpow2 * x1
184 + 3 * tpow2 * invt * x2
188 + 3 * t * invtpow2 * y1
189 + 3 * tpow2 * invt * y2
192 // Z is defined as linear for now to simplify the user interface
193 z = t * (z3 - z0) + z0;
195 // z = ( invtpow3 * z0
196 // + 3 * t * invtpow2 * z1
197 // + 3 * tpow2 * invt * z2
202 // printf("BezierAutos::get_center 3 %d %f %f %f\n",
210 int BezierAutos::swap_out_selected()
214 BezierAuto *bezier_selected = (BezierAuto*)selected;
215 new_selected->position = bezier_selected->position;
216 new_selected->center_x = bezier_selected->center_x;
217 new_selected->control_in_x = bezier_selected->control_in_x;
218 new_selected->control_out_x = bezier_selected->control_out_x;
219 new_selected->center_y = bezier_selected->center_y;
220 new_selected->control_in_y = bezier_selected->control_in_y;
221 new_selected->control_out_y = bezier_selected->control_out_y;
222 new_selected->center_z = bezier_selected->center_z;
223 new_selected->control_in_z = bezier_selected->control_in_z;
224 new_selected->control_out_z = bezier_selected->control_out_z;
226 bezier_selected->position = old_selected->position;
227 bezier_selected->center_x = old_selected->center_x;
228 bezier_selected->control_in_x = old_selected->control_in_x;
229 bezier_selected->control_out_x = old_selected->control_out_x;
230 bezier_selected->center_y = old_selected->center_y;
231 bezier_selected->control_in_y = old_selected->control_in_y;
232 bezier_selected->control_out_y = old_selected->control_out_y;
233 bezier_selected->center_z = old_selected->center_z;
234 bezier_selected->control_in_z = old_selected->control_in_z;
235 bezier_selected->control_out_z = old_selected->control_out_z;
239 int BezierAutos::swap_in_selected()
243 BezierAuto *bezier_selected = (BezierAuto*)selected;
244 bezier_selected->position = new_selected->position;
245 bezier_selected->center_x = new_selected->center_x;
246 bezier_selected->control_in_x = new_selected->control_in_x;
247 bezier_selected->control_out_x = new_selected->control_out_x;
248 bezier_selected->center_y = new_selected->center_y;
249 bezier_selected->control_in_y = new_selected->control_in_y;
250 bezier_selected->control_out_y = new_selected->control_out_y;
251 bezier_selected->center_z = new_selected->center_z;
252 bezier_selected->control_in_z = new_selected->control_in_z;
253 bezier_selected->control_out_z = new_selected->control_out_z;
257 int BezierAutos::draw_floating_autos(BC_SubWindow *canvas,
260 float units_per_pixel,
267 BezierAuto *before = 0, *after = 0;
268 float frame1, frame2, frame;
272 int x, x1, y1, x2, y2;
275 skip = selected->skip;
278 center_pixel = pixel + zoom_track / 2;
279 view_end = view_start + units_per_pixel * (vertical ? canvas->get_h() : canvas->get_w());
280 scale = (float)zoom_track / (vertical ? frame_w : frame_h);
282 before = (BezierAuto*)selected->previous;
283 after = (BezierAuto*)selected->next;
285 frame1 = before ? before->position : view_start;
286 frame2 = after ? after->position : view_end;
287 if(frame1 < view_start) frame1 = view_start;
288 if(frame2 > view_end) frame2 = view_end;
289 x = get_auto_pixel((int64_t)frame1, view_start, units_per_pixel, get_frame_half(scale, vertical, units_per_pixel));
293 canvas->set_inverse();
294 canvas->set_color(WHITE);
296 // skip drawing line for now
297 // get_center(x1, y1, z1, frame1 - units_per_pixel, 0, &before, &after);
300 // x1 = (int)(x1 * scale + center_pixel);
304 // y1 = (int)(y1 * scale + center_pixel);
307 // for(frame = frame1; frame < frame2; frame += units_per_pixel, x++)
309 // get_center(x2, y2, z2, frame, 0, &before, &after);
313 // x2 = (int)(x2 * scale + center_pixel);
314 // canvas->draw_line(x1, x - 1, x2, x);
318 // y2 = (int)(y2 * scale + center_pixel);
319 // canvas->draw_line(y1, x - 1, y2, x);
326 x = get_auto_pixel(selected->position, view_start, units_per_pixel, get_frame_half(scale, vertical, units_per_pixel));
328 ((BezierAuto*)selected)->draw(canvas, x, center_pixel, scale, vertical, 1);
330 canvas->set_opaque();
331 selected->skip = skip;
336 canvas->flash(pixel, 0, zoom_track, canvas->get_h());
338 canvas->flash(0, pixel, canvas->get_w(), zoom_track);
344 int BezierAutos::select_auto(BC_SubWindow *canvas,
347 float units_per_pixel,
356 // cursor_x is relative to frame number
357 BezierAuto *before = 0, *after = 0;
362 float x, y, miny, maxy;
366 center_pixel = pixel + zoom_track / 2;
367 view_end = view_start + units_per_pixel * (vertical ? canvas->get_h() : canvas->get_w());
368 scale = (float)zoom_track / (vertical ? frame_w : frame_h);
370 frame = get_auto_frame(cursor_x, view_start, units_per_pixel, vertical);
372 // test autos for selection
373 current = (BezierAuto*)autoof((int64_t)view_start);
374 while(current && current->position <= view_end && !selection_type)
376 x = get_auto_pixel(current->position, view_start, units_per_pixel, get_frame_half(scale, vertical, units_per_pixel));
378 selection_type = ((BezierAuto*)current)->select(canvas,
394 current = (BezierAuto*)NEXT;
397 // test line for selection
398 if(!selection_type && !shift_down)
400 // don't use auto line for now
401 // get_center(x, y, frame, 0, &before, &after);
403 // if(vertical) y = x;
405 // miny = (int)(y * scale + center_pixel - 5);
408 miny = center_pixel - 5;
409 maxy = center_pixel + 5;
411 if(cursor_y > miny && cursor_y < maxy)
413 selected = add_auto((int64_t)frame, center_x, center_y, center_z);
415 // copy values from neighbor if possible
416 BezierAuto *neighbor = 0, *bezier_selected = (BezierAuto*)selected;
417 if(selected->previous)
419 neighbor = (BezierAuto*)selected->previous;
424 neighbor = (BezierAuto*)selected->next;
429 // center point should be copied.
430 // Control points should be zero.
431 bezier_selected->center_x = neighbor->center_x;
432 bezier_selected->center_y = neighbor->center_y;
433 bezier_selected->center_z = neighbor->center_z;
434 // bezier_selected->control_in_x = neighbor->control_in_x;
435 // bezier_selected->control_in_y = neighbor->control_in_y;
436 // bezier_selected->control_in_z = neighbor->control_in_z;
437 // bezier_selected->control_out_x = neighbor->control_out_x;
438 // bezier_selected->control_out_y = neighbor->control_out_y;
439 // bezier_selected->control_out_z = neighbor->control_out_z;
442 // default to sample selection
450 draw_floating_autos(canvas,
458 get_virtual_center(virtual_center_x, virtual_center_y, cursor_x, cursor_y, vertical, scale);
461 return selection_type;
464 int BezierAutos::get_virtual_center(float &x, float &y, int cursor_x, int cursor_y, int vertical, float scale)
466 // get virtual center relative to track canvas
469 BezierAuto *current = (BezierAuto*)selected;
470 float selected_x = 0;
471 float selected_y = 0;
472 switch(selection_type)
475 selected_x = current->center_x;
476 selected_y = current->center_y;
480 selected_y = current->center_z * virtual_h;
483 selected_x = current->control_in_x;
484 selected_y = current->control_in_y;
487 selected_x = current->control_out_x;
488 selected_y = current->control_out_y;
492 selected_y = current->control_in_z * virtual_h;
496 selected_y = current->control_out_z * virtual_h;
504 // control points are independant of vertical tracks
507 cursor_x ^= cursor_y;
508 cursor_y ^= cursor_x;
509 cursor_x ^= cursor_y;
513 x = center_x + cursor_x - selected_x;
517 y = center_y + cursor_y - selected_y;
521 int BezierAutos::move_auto(BC_SubWindow *canvas,
524 float units_per_pixel,
534 BezierAuto* current = (BezierAuto*)selected;
536 float scale = (float)zoom_track / (vertical ? frame_w : frame_h);
538 position = get_auto_frame(cursor_x, view_start, units_per_pixel, vertical);
539 if(position < 0) position = 0;
541 if(selection_type == 1)
544 if(position != current->position) result = 1;
545 current->position = position;
553 real_x = (float)((vertical ? cursor_y : cursor_x) - virtual_center_x);
557 float real_y = (float)((vertical ? cursor_x : cursor_y) - virtual_center_y);
559 switch(selection_type)
562 current->center_x = real_x;
563 current->center_y = real_y;
566 current->center_z = real_y / virtual_h;
569 current->control_in_x = real_x;
570 current->control_in_y = real_y;
573 current->control_out_x = real_x;
574 current->control_out_y = real_y;
577 current->control_in_z = real_y / virtual_h;
580 current->control_out_z = real_y / virtual_h;
589 int BezierAutos::release_auto_derived()
595 Auto* BezierAutos::add_auto(int64_t frame, float x, float y, float z)
597 BezierAuto* current = (BezierAuto*)autoof(frame);
598 BezierAuto* new_auto;
600 insert_before(current, new_auto = new BezierAuto(edl, this));
601 new_auto->position = frame;
602 new_auto->control_in_x = new_auto->control_out_x = 0;
603 new_auto->control_in_y = new_auto->control_out_y = 0;
604 new_auto->control_in_z = new_auto->control_out_z = 0;
605 new_auto->center_x = x;
606 new_auto->center_y = y;
607 new_auto->center_z = z;
609 //printf("BezierAutos::add_auto %lld\n", new_auto->position);
610 return (Auto*)new_auto;
613 Auto* BezierAutos::append_auto()
615 return append(new BezierAuto(edl, this));
618 int BezierAutos::scale_video(float scale, int *offsets)
620 for(BezierAuto *current = (BezierAuto*)first;
622 current = (BezierAuto*)NEXT)
624 current->center_x -= offsets[0];
625 current->center_y -= offsets[1];
626 current->center_z *= scale;
631 int BezierAutos::dump()
633 printf(" BezierAutos::dump %p\n", this);
634 printf(" Default: position %lld x %f y %f z %f\n",
635 default_auto->position,
636 ((BezierAuto*)default_auto)->center_x,
637 ((BezierAuto*)default_auto)->center_y,
638 ((BezierAuto*)default_auto)->center_z);
639 for(Auto* current = first; current; current = NEXT)
641 printf(" position %lld x %f y %f z %f\n",
643 ((BezierAuto*)current)->center_x,
644 ((BezierAuto*)current)->center_y,
645 ((BezierAuto*)current)->center_z);