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"
25 #include "edlsession.h"
26 #include "localsession.h"
28 #include "maskautos.h"
30 #include "transportque.inc"
32 MaskAutos::MaskAutos(EDL *edl,
36 type = AUTOMATION_TYPE_MASK;
39 MaskAutos::~MaskAutos()
46 void MaskAutos::update_parameter(MaskAuto *src)
48 double selection_start = edl->local_session->get_selectionstart(0);
49 double selection_end = edl->local_session->get_selectionend(0);
51 // Selection is always aligned to frame for masks
53 // Create new keyframe if auto keyframes or replace entire keyframe.
54 if( !edl->session->span_keyframes ||
55 EQUIV(selection_start, selection_end) )
57 // Search for keyframe to write to
58 MaskAuto *dst = (MaskAuto*)get_auto_for_editing();
63 // Replace changed parameter in all selected keyframes.
65 // Search all keyframes in selection but don't create a new one.
66 int64_t start = track->to_units(selection_start, 0);
67 int64_t end = track->to_units(selection_end, 0);
68 Auto *current_auto = 0;
69 MaskAuto *current = 0;
70 current = (MaskAuto*)get_prev_auto(start,
75 // The first one determines the changed parameters since it is the one displayed
77 MaskAuto *first = current;
79 // Update the first one last, so it is available for comparisons to the changed one.
80 for(current = (MaskAuto*)NEXT;
81 current && current->position < end;
82 current = (MaskAuto*)NEXT)
84 current->update_parameter(first,
87 first->copy_data(src);
93 void MaskAutos::get_points(MaskPoints *points,
98 MaskAuto *begin = 0, *end = 0;
99 position = (direction == PLAY_FORWARD) ? position : (position - 1);
101 // Get auto before and after position
102 for(MaskAuto* current = (MaskAuto*)last;
104 current = (MaskAuto*)PREVIOUS)
106 if(current->position <= position)
109 end = NEXT ? (MaskAuto*)NEXT : current;
114 // Nothing before position found
117 begin = end = (MaskAuto*)first;
120 // Nothing after position found
123 begin = end = (MaskAuto*)default_auto;
127 SubMask *mask1 = begin->get_submask(submask);
128 SubMask *mask2 = end->get_submask(submask);
130 points->remove_all_objects();
131 int total_points = MAX(mask1->points.size(), mask2->points.size());
132 for(int i = 0; i < total_points; i++)
134 MaskPoint *point = new MaskPoint;
140 if(i < mask1->points.size())
142 point1.copy_from(*mask1->points.get(i));
146 if(i < mask2->points.size())
148 point2.copy_from(*mask2->points.get(i));
152 if(need_point1) point1.copy_from(point2);
153 if(need_point2) point2.copy_from(point1);
161 points->append(point);
166 double MaskAutos::get_feather(int64_t position, int i, int direction)
168 Auto *begin = 0, *end = 0;
169 position = (direction == PLAY_FORWARD) ? position : (position - 1);
170 MaskAuto*prev = (MaskAuto*)get_prev_auto(position, PLAY_FORWARD, begin, 1);
171 MaskAuto*next = (MaskAuto*)get_next_auto(position, PLAY_FORWARD, end, 1);
172 SubMask *prev_mask = prev->get_submask(i), *next_mask = next->get_submask(i);
174 double weight = end->position == begin->position ? 0.0 :
175 (double)(position - begin->position) / (end->position - begin->position);
177 double result = prev_mask->feather * (1-weight) + next_mask->feather*weight;
181 double MaskAutos::get_fader(int64_t position, int i, int direction)
183 Auto *begin = 0, *end = 0;
184 position = (direction == PLAY_FORWARD) ? position : (position - 1);
185 MaskAuto*prev = (MaskAuto*)get_prev_auto(position, PLAY_FORWARD, begin, 1);
186 MaskAuto*next = (MaskAuto*)get_next_auto(position, PLAY_FORWARD, end, 1);
187 SubMask *prev_mask = prev->get_submask(i), *next_mask = next->get_submask(i);
189 double weight = end->position == begin->position ? 0.0 :
190 (double)(position - begin->position) / (end->position - begin->position);
192 double result = prev_mask->fader * (1-weight) + next_mask->fader*weight;
193 // printf("MaskAutos::get_fader %d %d %d %f %d %f %d\n", __LINE__, i,
194 // ((MaskAuto*)begin)->fader, 1.0 - weight, ((MaskAuto*)end)->fader, weight, result);
199 void MaskAutos::avg_points(MaskPoint *output, MaskPoint *input1, MaskPoint *input2,
200 int64_t output_position, int64_t position1, int64_t position2)
202 if(position2 == position1) {
206 float fraction2 = (float)(output_position - position1) / (position2 - position1);
207 float fraction1 = 1 - fraction2;
208 output->x = input1->x * fraction1 + input2->x * fraction2;
209 output->y = input1->y * fraction1 + input2->y * fraction2;
210 output->control_x1 = input1->control_x1 * fraction1 + input2->control_x1 * fraction2;
211 output->control_y1 = input1->control_y1 * fraction1 + input2->control_y1 * fraction2;
212 output->control_x2 = input1->control_x2 * fraction1 + input2->control_x2 * fraction2;
213 output->control_y2 = input1->control_y2 * fraction1 + input2->control_y2 * fraction2;
219 Auto* MaskAutos::new_auto()
221 return new MaskAuto(edl, this);
224 void MaskAutos::dump(FILE *fp)
226 fprintf(fp, " MaskAutos::dump %p\n", this);
227 fprintf(fp, " Default: position %jd submasks %d\n",
228 default_auto->position,
229 ((MaskAuto*)default_auto)->masks.total);
230 ((MaskAuto*)default_auto)->dump(fp);
231 for( Auto* current = first; current; current=NEXT ) {
232 fprintf(fp, " position %jd masks %d\n",
234 ((MaskAuto*)current)->masks.total);
235 ((MaskAuto*)current)->dump(fp);
239 int MaskAutos::mask_exists(int64_t position, int direction)
242 position = (direction == PLAY_FORWARD) ? position : (position - 1);
244 MaskAuto* keyframe = (MaskAuto*)get_prev_auto(position, direction, current);
246 for( int i = 0; i < keyframe->masks.total; i++ ) {
247 SubMask *mask = keyframe->get_submask(i);
248 if(mask->points.total > 1)
254 int MaskAutos::total_submasks(int64_t position, int direction)
256 position = (direction == PLAY_FORWARD) ? position : (position - 1);
257 for( MaskAuto* current=(MaskAuto*)last; current; current=(MaskAuto*)PREVIOUS ) {
258 if( current->position <= position ) {
259 return current->masks.total;
263 return ((MaskAuto*)default_auto)->masks.total;
267 void MaskAutos::translate_masks(float translate_x, float translate_y)
269 ((MaskAuto *)default_auto)->translate_submasks(translate_x, translate_y);
270 for( MaskAuto* current=(MaskAuto*)first; current; current=(MaskAuto*)NEXT ) {
271 current->translate_submasks(translate_x, translate_y);
275 void MaskAutos::set_proxy(int orig_scale, int new_scale)
277 ((MaskAuto *)default_auto)->scale_submasks(orig_scale, new_scale);
278 for( MaskAuto* current=(MaskAuto*)first; current; current=(MaskAuto*)NEXT ) {
279 current->scale_submasks(orig_scale, new_scale);