opengl upgrade to 4.3 for masks, mask function/layout rework, make_shader rework
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / maskautos.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "automation.inc"
23 #include "clip.h"
24 #include "edl.h"
25 #include "localsession.h"
26 #include "maskauto.h"
27 #include "maskautos.h"
28 #include "track.h"
29 #include "transportque.inc"
30
31 MaskAutos::MaskAutos(EDL *edl,
32         Track *track)
33  : Autos(edl, track)
34 {
35         type = AUTOMATION_TYPE_MASK;
36 }
37
38 MaskAutos::~MaskAutos()
39 {
40 }
41
42
43
44
45 void MaskAutos::update_parameter(MaskAuto *src)
46 {
47         double selection_start = edl->local_session->get_selectionstart(0);
48         double selection_end = edl->local_session->get_selectionend(0);
49
50 // Selection is always aligned to frame for masks
51
52 // Create new keyframe if auto keyframes or replace entire keyframe.
53         if(selection_start == selection_end)
54         {
55 // Search for keyframe to write to
56                 MaskAuto *dst = (MaskAuto*)get_auto_for_editing();
57
58                 dst->copy_data(src);
59         }
60         else
61 // Replace changed parameter in all selected keyframes.
62         {
63 // Search all keyframes in selection but don't create a new one.
64                 int64_t start = track->to_units(selection_start, 0);
65                 int64_t end = track->to_units(selection_end, 0);
66                 Auto *current_auto = 0;
67                 MaskAuto *current = 0;
68                 current = (MaskAuto*)get_prev_auto(start,
69                         PLAY_FORWARD,
70                         current_auto,
71                         1);
72
73 // The first one determines the changed parameters since it is the one displayed
74 // in the GUI.
75                 MaskAuto *first = current;
76
77 // Update the first one last, so it is available for comparisons to the changed one.
78                 for(current = (MaskAuto*)NEXT;
79                         current && current->position < end;
80                         current = (MaskAuto*)NEXT)
81                 {
82                         current->update_parameter(first,
83                                 src);
84                 }
85                 first->copy_data(src);
86         }
87 }
88
89
90
91 void MaskAutos::get_points(ArrayList<MaskPoint*> *points,
92         int submask,
93         int64_t position,
94         int direction)
95 {
96         MaskAuto *begin = 0, *end = 0;
97         position = (direction == PLAY_FORWARD) ? position : (position - 1);
98
99 // Get auto before and after position
100         for(MaskAuto* current = (MaskAuto*)last;
101                 current;
102                 current = (MaskAuto*)PREVIOUS)
103         {
104                 if(current->position <= position)
105                 {
106                         begin = current;
107                         end = NEXT ? (MaskAuto*)NEXT : current;
108                         break;
109                 }
110         }
111
112 // Nothing before position found
113         if(!begin)
114         {
115                 begin = end = (MaskAuto*)first;
116         }
117
118 // Nothing after position found
119         if(!begin)
120         {
121                 begin = end = (MaskAuto*)default_auto;
122         }
123
124
125         SubMask *mask1 = begin->get_submask(submask);
126         SubMask *mask2 = end->get_submask(submask);
127
128         points->remove_all_objects();
129         int total_points = MAX(mask1->points.size(), mask2->points.size());
130         for(int i = 0; i < total_points; i++)
131         {
132                 MaskPoint *point = new MaskPoint;
133                 MaskPoint point1;
134                 int need_point1 = 1;
135                 MaskPoint point2;
136                 int need_point2 = 1;
137
138                 if(i < mask1->points.size())
139                 {
140                         point1.copy_from(*mask1->points.get(i));
141                         need_point1 = 0;
142                 }
143
144                 if(i < mask2->points.size())
145                 {
146                         point2.copy_from(*mask2->points.get(i));
147                         need_point2 = 0;
148                 }
149
150                 if(need_point1) point1.copy_from(point2);
151                 if(need_point2) point2.copy_from(point1);
152
153                 avg_points(point,
154                         &point1,
155                         &point2,
156                         position,
157                         begin->position,
158                         end->position);
159                 points->append(point);
160         }
161 }
162
163
164 float MaskAutos::get_feather(int64_t position, int i, int direction)
165 {
166         Auto *begin = 0, *end = 0;
167         position = (direction == PLAY_FORWARD) ? position : (position - 1);
168         MaskAuto*prev = (MaskAuto*)get_prev_auto(position, PLAY_FORWARD, begin, 1);
169         MaskAuto*next = (MaskAuto*)get_next_auto(position, PLAY_FORWARD, end, 1);
170         SubMask *prev_mask = prev->get_submask(i), *next_mask = next->get_submask(i);
171
172         double weight = end->position == begin->position ? 0.0 :
173                 (double)(position - begin->position) / (end->position - begin->position);
174
175         int result = prev_mask->feather * (1-weight) + next_mask->feather*weight + 0.5;
176         return result;
177 }
178
179 int MaskAutos::get_fader(int64_t position, int i, int direction)
180 {
181         Auto *begin = 0, *end = 0;
182         position = (direction == PLAY_FORWARD) ? position : (position - 1);
183         MaskAuto*prev = (MaskAuto*)get_prev_auto(position, PLAY_FORWARD, begin, 1);
184         MaskAuto*next = (MaskAuto*)get_next_auto(position, PLAY_FORWARD, end, 1);
185         SubMask *prev_mask = prev->get_submask(i), *next_mask = next->get_submask(i);
186
187         double weight = end->position == begin->position ? 0.0 :
188                 (double)(position - begin->position) / (end->position - begin->position);
189
190         int result = prev_mask->fader * (1-weight) + next_mask->fader*weight + 0.5;
191 // printf("MaskAutos::get_fader %d %d %d %f %d %f %d\n", __LINE__, i,
192 // ((MaskAuto*)begin)->fader, 1.0 - weight, ((MaskAuto*)end)->fader, weight, result);
193         return result;
194 }
195
196
197 void MaskAutos::avg_points(MaskPoint *output, MaskPoint *input1, MaskPoint *input2,
198                 int64_t output_position, int64_t position1, int64_t position2)
199 {
200         if(position2 == position1) {
201                 *output = *input1;
202         }
203         else {
204                 float fraction2 = (float)(output_position - position1) / (position2 - position1);
205                 float fraction1 = 1 - fraction2;
206                 output->x = input1->x * fraction1 + input2->x * fraction2;
207                 output->y = input1->y * fraction1 + input2->y * fraction2;
208                 output->control_x1 = input1->control_x1 * fraction1 + input2->control_x1 * fraction2;
209                 output->control_y1 = input1->control_y1 * fraction1 + input2->control_y1 * fraction2;
210                 output->control_x2 = input1->control_x2 * fraction1 + input2->control_x2 * fraction2;
211                 output->control_y2 = input1->control_y2 * fraction1 + input2->control_y2 * fraction2;
212         }
213
214 }
215
216
217 Auto* MaskAutos::new_auto()
218 {
219         return new MaskAuto(edl, this);
220 }
221
222 void MaskAutos::dump()
223 {
224         printf("        MaskAutos::dump %p\n", this);
225         printf("        Default: position %jd submasks %d\n",
226                 default_auto->position,
227                 ((MaskAuto*)default_auto)->masks.total);
228         ((MaskAuto*)default_auto)->dump();
229         for(Auto* current = first; current; current = NEXT)
230         {
231                 printf("        position %jd masks %d\n",
232                         current->position,
233                         ((MaskAuto*)current)->masks.total);
234                 ((MaskAuto*)current)->dump();
235         }
236 }
237
238 int MaskAutos::mask_exists(int64_t position, int direction)
239 {
240         Auto *current = 0;
241         position = (direction == PLAY_FORWARD) ? position : (position - 1);
242
243         MaskAuto* keyframe = (MaskAuto*)get_prev_auto(position, direction, current);
244
245
246
247         for(int i = 0; i < keyframe->masks.total; i++)
248         {
249                 SubMask *mask = keyframe->get_submask(i);
250                 if(mask->points.total > 1)
251                         return 1;
252         }
253         return 0;
254 }
255
256 int MaskAutos::total_submasks(int64_t position, int direction)
257 {
258         position = (direction == PLAY_FORWARD) ? position : (position - 1);
259         for(MaskAuto* current = (MaskAuto*)last;
260                 current;
261                 current = (MaskAuto*)PREVIOUS)
262         {
263                 if(current->position <= position)
264                 {
265                         return current->masks.total;
266                 }
267         }
268
269         return ((MaskAuto*)default_auto)->masks.total;
270 }
271
272
273 void MaskAutos::translate_masks(float translate_x, float translate_y)
274 {
275         ((MaskAuto *)default_auto)->translate_submasks(translate_x, translate_y);
276         for(MaskAuto* current = (MaskAuto*)first;
277                 current;
278                 current = (MaskAuto*)NEXT)
279         {
280                 current->translate_submasks(translate_x, translate_y);
281         }
282 }
283
284 void MaskAutos::set_proxy(int orig_scale, int new_scale)
285 {
286         ((MaskAuto *)default_auto)->scale_submasks(orig_scale, new_scale);
287         for( MaskAuto* current=(MaskAuto*)first; current; current=(MaskAuto*)NEXT ) {
288                 current->scale_submasks(orig_scale, new_scale);
289         }
290 }
291