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()
43 int BezierAutos::paste_derived(FileXML *xml, int64_t start)
45 int64_t frame = xml->tag.get_property("FRAME", 0);
46 BezierAuto* current = (BezierAuto*)add_auto(frame + start, 0, 0, 1);
48 current->position += start; // fix the position loaded by load()
51 int BezierAutos::draw(BC_SubWindow *canvas,
54 float units_per_pixel,
61 int BezierAutos::get_auto_pixel(int64_t position, float view_start, float units_per_pixel, int frame_half)
65 result = (int)((position - view_start) / units_per_pixel) + frame_half;
70 int64_t BezierAutos::get_auto_frame(int position, float view_start, float units_per_pixel, int frame_half)
74 result = (int64_t)((position) * units_per_pixel + view_start);
79 int BezierAutos::get_frame_half(float scale, int vertical, float units_per_pixel)
81 int result = (int)(.5 * scale * (vertical ? frame_h : frame_w));
82 if(1 / units_per_pixel / 2 < result) result = (int)(1 / units_per_pixel / 2);
86 int BezierAutos::get_center(float &x,
94 frame = (direction == PLAY_FORWARD) ? frame : (frame - 1);
95 get_neighbors((int64_t)frame, (int64_t)frame, (Auto**)before, (Auto**)after);
97 //printf("BezierAutos::get_center %p %p\n", *before, *after);
98 if(*before == 0 && *after == 0)
100 x = ((BezierAuto*)default_auto)->center_x;
101 y = ((BezierAuto*)default_auto)->center_y;
102 z = ((BezierAuto*)default_auto)->center_z;
103 //printf("BezierAutos::get_center %f %f %f\n", x, y, z);
107 float x0, x1, x2, x3;
108 float y0, y1, y2, y3;
109 float z0, z1, z2, z3;
110 float frame0, frame1;
114 x0 = (*before)->center_x;
115 y0 = (*before)->center_y;
116 z0 = (*before)->center_z;
117 // printf("BezierAutos::get_center 1 %f %f %f\n",
121 frame0 = (float)(*before)->position;
123 if(*after == 0 || frame == frame0)
131 x1 = (*before)->control_out_x + x0;
132 y1 = (*before)->control_out_y + y0;
133 z1 = (*before)->control_out_z + z0;
138 x3 = (*after)->center_x;
139 y3 = (*after)->center_y;
140 z3 = (*after)->center_z;
141 // printf("BezierAutos::get_center 2 %f %f %f\n",
145 frame1 = (float)(*after)->position;
147 if(*before == 0 || frame == frame1)
155 x2 = (*after)->control_in_x + x3;
156 y2 = (*after)->control_in_y + y3;
157 z2 = (*after)->control_in_z + z3;
160 float t = (frame - frame0) / (frame1 - frame0);
162 float tpow3 = t * t * t;
164 float invtpow2 = invt * invt;
165 float invtpow3 = invt * invt * invt;
168 + 3 * t * invtpow2 * x1
169 + 3 * tpow2 * invt * x2
173 + 3 * t * invtpow2 * y1
174 + 3 * tpow2 * invt * y2
177 // Z is defined as linear for now to simplify the user interface
178 z = t * (z3 - z0) + z0;
180 // z = ( invtpow3 * z0
181 // + 3 * t * invtpow2 * z1
182 // + 3 * tpow2 * invt * z2
187 // printf("BezierAutos::get_center 3 %d %f %f %f\n",
195 int BezierAutos::swap_out_selected()
199 BezierAuto *bezier_selected = (BezierAuto*)selected;
200 new_selected->position = bezier_selected->position;
201 new_selected->center_x = bezier_selected->center_x;
202 new_selected->control_in_x = bezier_selected->control_in_x;
203 new_selected->control_out_x = bezier_selected->control_out_x;
204 new_selected->center_y = bezier_selected->center_y;
205 new_selected->control_in_y = bezier_selected->control_in_y;
206 new_selected->control_out_y = bezier_selected->control_out_y;
207 new_selected->center_z = bezier_selected->center_z;
208 new_selected->control_in_z = bezier_selected->control_in_z;
209 new_selected->control_out_z = bezier_selected->control_out_z;
211 bezier_selected->position = old_selected->position;
212 bezier_selected->center_x = old_selected->center_x;
213 bezier_selected->control_in_x = old_selected->control_in_x;
214 bezier_selected->control_out_x = old_selected->control_out_x;
215 bezier_selected->center_y = old_selected->center_y;
216 bezier_selected->control_in_y = old_selected->control_in_y;
217 bezier_selected->control_out_y = old_selected->control_out_y;
218 bezier_selected->center_z = old_selected->center_z;
219 bezier_selected->control_in_z = old_selected->control_in_z;
220 bezier_selected->control_out_z = old_selected->control_out_z;
224 int BezierAutos::swap_in_selected()
228 BezierAuto *bezier_selected = (BezierAuto*)selected;
229 bezier_selected->position = new_selected->position;
230 bezier_selected->center_x = new_selected->center_x;
231 bezier_selected->control_in_x = new_selected->control_in_x;
232 bezier_selected->control_out_x = new_selected->control_out_x;
233 bezier_selected->center_y = new_selected->center_y;
234 bezier_selected->control_in_y = new_selected->control_in_y;
235 bezier_selected->control_out_y = new_selected->control_out_y;
236 bezier_selected->center_z = new_selected->center_z;
237 bezier_selected->control_in_z = new_selected->control_in_z;
238 bezier_selected->control_out_z = new_selected->control_out_z;
242 int BezierAutos::draw_floating_autos(BC_SubWindow *canvas,
245 float units_per_pixel,
252 BezierAuto *before = 0, *after = 0;
253 float frame1, frame2, frame;
257 int x, x1, y1, x2, y2;
260 skip = selected->skip;
263 center_pixel = pixel + zoom_track / 2;
264 view_end = view_start + units_per_pixel * (vertical ? canvas->get_h() : canvas->get_w());
265 scale = (float)zoom_track / (vertical ? frame_w : frame_h);
267 before = (BezierAuto*)selected->previous;
268 after = (BezierAuto*)selected->next;
270 frame1 = before ? before->position : view_start;
271 frame2 = after ? after->position : view_end;
272 if(frame1 < view_start) frame1 = view_start;
273 if(frame2 > view_end) frame2 = view_end;
274 x = get_auto_pixel((int64_t)frame1, view_start, units_per_pixel, get_frame_half(scale, vertical, units_per_pixel));
278 canvas->set_inverse();
279 canvas->set_color(WHITE);
281 // skip drawing line for now
282 // get_center(x1, y1, z1, frame1 - units_per_pixel, 0, &before, &after);
285 // x1 = (int)(x1 * scale + center_pixel);
289 // y1 = (int)(y1 * scale + center_pixel);
292 // for(frame = frame1; frame < frame2; frame += units_per_pixel, x++)
294 // get_center(x2, y2, z2, frame, 0, &before, &after);
298 // x2 = (int)(x2 * scale + center_pixel);
299 // canvas->draw_line(x1, x - 1, x2, x);
303 // y2 = (int)(y2 * scale + center_pixel);
304 // canvas->draw_line(y1, x - 1, y2, x);
311 x = get_auto_pixel(selected->position, view_start, units_per_pixel, get_frame_half(scale, vertical, units_per_pixel));
313 ((BezierAuto*)selected)->draw(canvas, x, center_pixel, scale, vertical, 1);
315 canvas->set_opaque();
316 selected->skip = skip;
321 canvas->flash(pixel, 0, zoom_track, canvas->get_h());
323 canvas->flash(0, pixel, canvas->get_w(), zoom_track);
329 int BezierAutos::select_auto(BC_SubWindow *canvas,
332 float units_per_pixel,
341 // cursor_x is relative to frame number
342 BezierAuto *before = 0, *after = 0;
347 float x, y, miny, maxy;
351 center_pixel = pixel + zoom_track / 2;
352 view_end = view_start + units_per_pixel * (vertical ? canvas->get_h() : canvas->get_w());
353 scale = (float)zoom_track / (vertical ? frame_w : frame_h);
355 frame = get_auto_frame(cursor_x, view_start, units_per_pixel, vertical);
357 // test autos for selection
358 current = (BezierAuto*)autoof((int64_t)view_start);
359 while(current && current->position <= view_end && !selection_type)
361 x = get_auto_pixel(current->position, view_start, units_per_pixel, get_frame_half(scale, vertical, units_per_pixel));
363 selection_type = ((BezierAuto*)current)->select(canvas,
379 current = (BezierAuto*)NEXT;
382 // test line for selection
383 if(!selection_type && !shift_down)
385 // don't use auto line for now
386 // get_center(x, y, frame, 0, &before, &after);
388 // if(vertical) y = x;
390 // miny = (int)(y * scale + center_pixel - 5);
393 miny = center_pixel - 5;
394 maxy = center_pixel + 5;
396 if(cursor_y > miny && cursor_y < maxy)
398 selected = add_auto((int64_t)frame, center_x, center_y, center_z);
400 // copy values from neighbor if possible
401 BezierAuto *neighbor = 0, *bezier_selected = (BezierAuto*)selected;
402 if(selected->previous)
404 neighbor = (BezierAuto*)selected->previous;
409 neighbor = (BezierAuto*)selected->next;
414 // center point should be copied.
415 // Control points should be zero.
416 bezier_selected->center_x = neighbor->center_x;
417 bezier_selected->center_y = neighbor->center_y;
418 bezier_selected->center_z = neighbor->center_z;
419 // bezier_selected->control_in_x = neighbor->control_in_x;
420 // bezier_selected->control_in_y = neighbor->control_in_y;
421 // bezier_selected->control_in_z = neighbor->control_in_z;
422 // bezier_selected->control_out_x = neighbor->control_out_x;
423 // bezier_selected->control_out_y = neighbor->control_out_y;
424 // bezier_selected->control_out_z = neighbor->control_out_z;
427 // default to sample selection
435 draw_floating_autos(canvas,
443 get_virtual_center(virtual_center_x, virtual_center_y, cursor_x, cursor_y, vertical, scale);
446 return selection_type;
449 int BezierAutos::get_virtual_center(float &x, float &y, int cursor_x, int cursor_y, int vertical, float scale)
451 // get virtual center relative to track canvas
454 BezierAuto *current = (BezierAuto*)selected;
455 float selected_x = 0;
456 float selected_y = 0;
457 switch(selection_type)
460 selected_x = current->center_x;
461 selected_y = current->center_y;
465 selected_y = current->center_z * virtual_h;
468 selected_x = current->control_in_x;
469 selected_y = current->control_in_y;
472 selected_x = current->control_out_x;
473 selected_y = current->control_out_y;
477 selected_y = current->control_in_z * virtual_h;
481 selected_y = current->control_out_z * virtual_h;
489 // control points are independant of vertical tracks
492 cursor_x ^= cursor_y;
493 cursor_y ^= cursor_x;
494 cursor_x ^= cursor_y;
498 x = center_x + cursor_x - selected_x;
502 y = center_y + cursor_y - selected_y;
506 int BezierAutos::move_auto(BC_SubWindow *canvas,
509 float units_per_pixel,
519 BezierAuto* current = (BezierAuto*)selected;
521 float scale = (float)zoom_track / (vertical ? frame_w : frame_h);
523 position = get_auto_frame(cursor_x, view_start, units_per_pixel, vertical);
524 if(position < 0) position = 0;
526 if(selection_type == 1)
529 if(position != current->position) result = 1;
530 current->position = position;
538 real_x = (float)((vertical ? cursor_y : cursor_x) - virtual_center_x);
542 float real_y = (float)((vertical ? cursor_x : cursor_y) - virtual_center_y);
544 switch(selection_type)
547 current->center_x = real_x;
548 current->center_y = real_y;
551 current->center_z = real_y / virtual_h;
554 current->control_in_x = real_x;
555 current->control_in_y = real_y;
558 current->control_out_x = real_x;
559 current->control_out_y = real_y;
562 current->control_in_z = real_y / virtual_h;
565 current->control_out_z = real_y / virtual_h;
574 int BezierAutos::release_auto_derived()
580 Auto* BezierAutos::add_auto(int64_t frame, float x, float y, float z)
582 BezierAuto* current = (BezierAuto*)autoof(frame);
583 BezierAuto* new_auto;
585 insert_before(current, new_auto = new BezierAuto(edl, this));
586 new_auto->position = frame;
587 new_auto->control_in_x = new_auto->control_out_x = 0;
588 new_auto->control_in_y = new_auto->control_out_y = 0;
589 new_auto->control_in_z = new_auto->control_out_z = 0;
590 new_auto->center_x = x;
591 new_auto->center_y = y;
592 new_auto->center_z = z;
594 //printf("BezierAutos::add_auto %lld\n", new_auto->position);
595 return (Auto*)new_auto;
598 Auto* BezierAutos::append_auto()
600 return append(new BezierAuto(edl, this));
603 int BezierAutos::scale_video(float scale, int *offsets)
605 for(BezierAuto *current = (BezierAuto*)first;
607 current = (BezierAuto*)NEXT)
609 current->center_x -= offsets[0];
610 current->center_y -= offsets[1];
611 current->center_z *= scale;
616 int BezierAutos::dump()
618 printf(" BezierAutos::dump %p\n", this);
619 printf(" Default: position %lld x %f y %f z %f\n",
620 default_auto->position,
621 ((BezierAuto*)default_auto)->center_x,
622 ((BezierAuto*)default_auto)->center_y,
623 ((BezierAuto*)default_auto)->center_z);
624 for(Auto* current = first; current; current = NEXT)
626 printf(" position %lld x %f y %f z %f\n",
628 ((BezierAuto*)current)->center_x,
629 ((BezierAuto*)current)->center_y,
630 ((BezierAuto*)current)->center_z);