4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "automation.inc"
26 #include "localsession.h"
28 #include "maskautos.h"
30 #include "transportque.inc"
35 MaskAutos::MaskAutos(EDL *edl,
39 type = AUTOMATION_TYPE_MASK;
42 MaskAutos::~MaskAutos()
49 void MaskAutos::update_parameter(MaskAuto *src)
51 double selection_start = edl->local_session->get_selectionstart(0);
52 double selection_end = edl->local_session->get_selectionend(0);
54 // Selection is always aligned to frame for masks
56 // Create new keyframe if auto keyframes or replace entire keyframe.
57 if(selection_start == selection_end)
59 // Search for keyframe to write to
60 MaskAuto *dst = (MaskAuto*)get_auto_for_editing();
65 // Replace changed parameter in all selected keyframes.
67 // Search all keyframes in selection but don't create a new one.
68 int64_t start = track->to_units(selection_start, 0);
69 int64_t end = track->to_units(selection_end, 0);
70 Auto *current_auto = 0;
71 MaskAuto *current = 0;
72 current = (MaskAuto*)get_prev_auto(start,
77 // The first one determines the changed parameters since it is the one displayed
79 MaskAuto *first = current;
81 // Update the first one last, so it is available for comparisons to the changed one.
82 for(current = (MaskAuto*)NEXT;
83 current && current->position < end;
84 current = (MaskAuto*)NEXT)
86 current->update_parameter(first,
89 first->copy_data(src);
95 void MaskAutos::get_points(ArrayList<MaskPoint*> *points,
100 MaskAuto *begin = 0, *end = 0;
101 position = (direction == PLAY_FORWARD) ? position : (position - 1);
103 // Get auto before and after position
104 for(MaskAuto* current = (MaskAuto*)last;
106 current = (MaskAuto*)PREVIOUS)
108 if(current->position <= position)
111 end = NEXT ? (MaskAuto*)NEXT : current;
116 // Nothing before position found
119 begin = end = (MaskAuto*)first;
122 // Nothing after position found
125 begin = end = (MaskAuto*)default_auto;
129 SubMask *mask1 = begin->get_submask(submask);
130 SubMask *mask2 = end->get_submask(submask);
132 points->remove_all_objects();
133 int total_points = MAX(mask1->points.size(), mask2->points.size());
134 for(int i = 0; i < total_points; i++)
136 MaskPoint *point = new MaskPoint;
142 if(i < mask1->points.size())
144 point1.copy_from(*mask1->points.get(i));
148 if(i < mask2->points.size())
150 point2.copy_from(*mask2->points.get(i));
154 if(need_point1) point1.copy_from(point2);
155 if(need_point2) point2.copy_from(point1);
163 points->append(point);
168 float MaskAutos::get_feather(int64_t position, int direction)
170 Auto *begin = 0, *end = 0;
171 position = (direction == PLAY_FORWARD) ? position : (position - 1);
173 get_prev_auto(position, PLAY_FORWARD, begin, 1);
174 get_next_auto(position, PLAY_FORWARD, end, 1);
177 if(end->position != begin->position)
178 weight = (double)(position - begin->position) / (end->position - begin->position);
180 return ((MaskAuto*)begin)->feather * (1.0 - weight) + ((MaskAuto*)end)->feather * weight;
183 int MaskAutos::get_value(int64_t position, int direction)
185 Auto *begin = 0, *end = 0;
186 position = (direction == PLAY_FORWARD) ? position : (position - 1);
188 get_prev_auto(position, PLAY_FORWARD, begin, 1);
189 get_next_auto(position, PLAY_FORWARD, end, 1);
192 if(end->position != begin->position)
193 weight = (double)(position - begin->position) / (end->position - begin->position);
195 int result = (int)((double)((MaskAuto*)begin)->value * (1.0 - weight) +
196 (double)((MaskAuto*)end)->value * weight + 0.5);
197 // printf("MaskAutos::get_value %d %d %f %d %f %d\n",
199 // ((MaskAuto*)begin)->value,
201 // ((MaskAuto*)end)->value,
208 void MaskAutos::avg_points(MaskPoint *output,
211 int64_t output_position,
215 if(position2 == position1)
221 float fraction2 = (float)(output_position - position1) / (position2 - position1);
222 float fraction1 = 1 - fraction2;
223 output->x = input1->x * fraction1 + input2->x * fraction2;
224 output->y = input1->y * fraction1 + input2->y * fraction2;
225 output->control_x1 = input1->control_x1 * fraction1 + input2->control_x1 * fraction2;
226 output->control_y1 = input1->control_y1 * fraction1 + input2->control_y1 * fraction2;
227 output->control_x2 = input1->control_x2 * fraction1 + input2->control_x2 * fraction2;
228 output->control_y2 = input1->control_y2 * fraction1 + input2->control_y2 * fraction2;
234 Auto* MaskAutos::new_auto()
236 return new MaskAuto(edl, this);
239 void MaskAutos::dump()
241 printf(" MaskAutos::dump %p\n", this);
242 printf(" Default: position " _LD " submasks %d\n",
243 default_auto->position,
244 ((MaskAuto*)default_auto)->masks.total);
245 ((MaskAuto*)default_auto)->dump();
246 for(Auto* current = first; current; current = NEXT)
248 printf(" position " _LD " masks %d\n",
250 ((MaskAuto*)current)->masks.total);
251 ((MaskAuto*)current)->dump();
255 int MaskAutos::mask_exists(int64_t position, int direction)
258 position = (direction == PLAY_FORWARD) ? position : (position - 1);
260 MaskAuto* keyframe = (MaskAuto*)get_prev_auto(position, direction, current);
264 for(int i = 0; i < keyframe->masks.total; i++)
266 SubMask *mask = keyframe->get_submask(i);
267 if(mask->points.total > 1)
273 int MaskAutos::total_submasks(int64_t position, int direction)
275 position = (direction == PLAY_FORWARD) ? position : (position - 1);
276 for(MaskAuto* current = (MaskAuto*)last;
278 current = (MaskAuto*)PREVIOUS)
280 if(current->position <= position)
282 return current->masks.total;
286 return ((MaskAuto*)default_auto)->masks.total;
290 void MaskAutos::translate_masks(float translate_x, float translate_y)
292 ((MaskAuto *)default_auto)->translate_submasks(translate_x, translate_y);
293 for(MaskAuto* current = (MaskAuto*)first;
295 current = (MaskAuto*)NEXT)
297 current->translate_submasks(translate_x, translate_y);