~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to source/blender/editors/mask/mask_ops.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ***** BEGIN GPL LICENSE BLOCK *****
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License
 
6
 * as published by the Free Software Foundation; either version 2
 
7
 * of the License, or (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software Foundation,
 
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 *
 
18
 * The Original Code is Copyright (C) 2012 Blender Foundation.
 
19
 * All rights reserved.
 
20
 *
 
21
 *
 
22
 * Contributor(s): Blender Foundation,
 
23
 *                 Sergey Sharybin
 
24
 *
 
25
 * ***** END GPL LICENSE BLOCK *****
 
26
 */
 
27
 
 
28
/** \file blender/editors/mask/mask_ops.c
 
29
 *  \ingroup edmask
 
30
 */
 
31
 
 
32
#include "MEM_guardedalloc.h"
 
33
 
 
34
#include "BLI_listbase.h"
 
35
#include "BLI_math.h"
 
36
 
 
37
#include "BKE_context.h"
 
38
#include "BKE_depsgraph.h"
 
39
#include "BKE_main.h"
 
40
#include "BKE_mask.h"
 
41
 
 
42
#include "DNA_scene_types.h"
 
43
#include "DNA_mask_types.h"
 
44
#include "DNA_object_types.h"  /* SELECT */
 
45
 
 
46
#include "WM_api.h"
 
47
#include "WM_types.h"
 
48
 
 
49
#include "ED_clip.h"
 
50
#include "ED_image.h"
 
51
#include "ED_keyframing.h"
 
52
#include "ED_mask.h"
 
53
#include "ED_screen.h"
 
54
 
 
55
#include "RNA_access.h"
 
56
#include "RNA_define.h"
 
57
 
 
58
#include "mask_intern.h"  /* own include */
 
59
 
 
60
/******************** utility functions *********************/
 
61
 
 
62
MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, Mask *mask, float normal_co[2], int threshold,
 
63
                                            MaskLayer **masklay_r, MaskSpline **spline_r, int *is_handle_r,
 
64
                                            float *score)
 
65
{
 
66
        ScrArea *sa = CTX_wm_area(C);
 
67
        ARegion *ar = CTX_wm_region(C);
 
68
 
 
69
        MaskLayer *masklay;
 
70
        MaskLayer *point_masklay = NULL;
 
71
        MaskSpline *point_spline = NULL;
 
72
        MaskSplinePoint *point = NULL;
 
73
        float co[2];
 
74
        float len = FLT_MAX, scalex, scaley;
 
75
        int is_handle = FALSE, width, height;
 
76
 
 
77
        ED_mask_get_size(sa, &width, &height);
 
78
        ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
 
79
 
 
80
        co[0] = normal_co[0] * scalex;
 
81
        co[1] = normal_co[1] * scaley;
 
82
 
 
83
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
84
                MaskSpline *spline;
 
85
 
 
86
                if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
 
87
                        continue;
 
88
                }
 
89
 
 
90
                for (spline = masklay->splines.first; spline; spline = spline->next) {
 
91
                        MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
 
92
 
 
93
                        int i;
 
94
 
 
95
                        for (i = 0; i < spline->tot_point; i++) {
 
96
                                MaskSplinePoint *cur_point = &spline->points[i];
 
97
                                MaskSplinePoint *cur_point_deform = &points_array[i];
 
98
                                float cur_len, vec[2], handle[2];
 
99
 
 
100
                                vec[0] = cur_point_deform->bezt.vec[1][0] * scalex;
 
101
                                vec[1] = cur_point_deform->bezt.vec[1][1] * scaley;
 
102
 
 
103
                                if (BKE_mask_point_has_handle(cur_point)) {
 
104
                                        BKE_mask_point_handle(cur_point_deform, handle);
 
105
                                        handle[0] *= scalex;
 
106
                                        handle[1] *= scaley;
 
107
 
 
108
                                        cur_len = len_v2v2(co, handle);
 
109
 
 
110
                                        if (cur_len < len) {
 
111
                                                point_masklay = masklay;
 
112
                                                point_spline = spline;
 
113
                                                point = cur_point;
 
114
                                                len = cur_len;
 
115
                                                is_handle = TRUE;
 
116
                                        }
 
117
                                }
 
118
 
 
119
                                cur_len = len_v2v2(co, vec);
 
120
 
 
121
                                if (cur_len < len) {
 
122
                                        point_spline = spline;
 
123
                                        point_masklay = masklay;
 
124
                                        point = cur_point;
 
125
                                        len = cur_len;
 
126
                                        is_handle = FALSE;
 
127
                                }
 
128
                        }
 
129
                }
 
130
        }
 
131
 
 
132
        if (len < threshold) {
 
133
                if (masklay_r)
 
134
                        *masklay_r = point_masklay;
 
135
 
 
136
                if (spline_r)
 
137
                        *spline_r = point_spline;
 
138
 
 
139
                if (is_handle_r)
 
140
                        *is_handle_r = is_handle;
 
141
 
 
142
                if (score)
 
143
                        *score = len;
 
144
 
 
145
                return point;
 
146
        }
 
147
 
 
148
        if (masklay_r)
 
149
                *masklay_r = NULL;
 
150
 
 
151
        if (spline_r)
 
152
                *spline_r = NULL;
 
153
 
 
154
        if (is_handle_r)
 
155
                *is_handle_r = FALSE;
 
156
 
 
157
        return NULL;
 
158
}
 
159
 
 
160
int ED_mask_feather_find_nearest(const bContext *C, Mask *mask, float normal_co[2], int threshold,
 
161
                                 MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r,
 
162
                                 MaskSplinePointUW **uw_r, float *score)
 
163
{
 
164
        ScrArea *sa = CTX_wm_area(C);
 
165
        ARegion *ar = CTX_wm_region(C);
 
166
 
 
167
        MaskLayer *masklay, *point_masklay = NULL;
 
168
        MaskSpline *point_spline = NULL;
 
169
        MaskSplinePoint *point = NULL;
 
170
        MaskSplinePointUW *uw = NULL;
 
171
        float len = FLT_MAX, co[2];
 
172
        float scalex, scaley;
 
173
        int width, height;
 
174
 
 
175
        ED_mask_get_size(sa, &width, &height);
 
176
        ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
 
177
 
 
178
        co[0] = normal_co[0] * scalex;
 
179
        co[1] = normal_co[1] * scaley;
 
180
 
 
181
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
182
                MaskSpline *spline;
 
183
 
 
184
                for (spline = masklay->splines.first; spline; spline = spline->next) {
 
185
                        //MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
 
186
 
 
187
                        int i, tot_feather_point;
 
188
                        float (*feather_points)[2], (*fp)[2];
 
189
 
 
190
                        if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
 
191
                                continue;
 
192
                        }
 
193
 
 
194
                        feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
 
195
 
 
196
                        for (i = 0; i < spline->tot_point; i++) {
 
197
                                int j;
 
198
                                MaskSplinePoint *cur_point = &spline->points[i];
 
199
 
 
200
                                for (j = 0; j < cur_point->tot_uw + 1; j++) {
 
201
                                        float cur_len, vec[2];
 
202
 
 
203
                                        vec[0] = (*fp)[0] * scalex;
 
204
                                        vec[1] = (*fp)[1] * scaley;
 
205
 
 
206
                                        cur_len = len_v2v2(vec, co);
 
207
 
 
208
                                        if (point == NULL || cur_len < len) {
 
209
                                                if (j == 0)
 
210
                                                        uw = NULL;
 
211
                                                else
 
212
                                                        uw = &cur_point->uw[j - 1];
 
213
 
 
214
                                                point_masklay = masklay;
 
215
                                                point_spline = spline;
 
216
                                                point = cur_point;
 
217
                                                len = cur_len;
 
218
                                        }
 
219
 
 
220
                                        fp++;
 
221
                                }
 
222
                        }
 
223
 
 
224
                        MEM_freeN(feather_points);
 
225
                }
 
226
        }
 
227
 
 
228
        if (len < threshold) {
 
229
                if (masklay_r)
 
230
                        *masklay_r = point_masklay;
 
231
 
 
232
                if (spline_r)
 
233
                        *spline_r = point_spline;
 
234
 
 
235
                if (point_r)
 
236
                        *point_r = point;
 
237
 
 
238
                if (uw_r)
 
239
                        *uw_r = uw;
 
240
 
 
241
                if (score)
 
242
                        *score = len;
 
243
 
 
244
                return TRUE;
 
245
        }
 
246
 
 
247
        if (masklay_r)
 
248
                *masklay_r = NULL;
 
249
 
 
250
        if (spline_r)
 
251
                *spline_r = NULL;
 
252
 
 
253
        if (point_r)
 
254
                *point_r = NULL;
 
255
 
 
256
        return FALSE;
 
257
}
 
258
 
 
259
 
 
260
/******************** create new mask *********************/
 
261
 
 
262
Mask *ED_mask_new(bContext *C, const char *name)
 
263
{
 
264
        ScrArea *sa = CTX_wm_area(C);
 
265
        Main *bmain = CTX_data_main(C);
 
266
        Mask *mask;
 
267
 
 
268
        mask = BKE_mask_new(bmain, name);
 
269
 
 
270
        if (sa && sa->spacedata.first) {
 
271
                switch (sa->spacetype) {
 
272
                        case SPACE_CLIP:
 
273
                        {
 
274
                                SpaceClip *sc = sa->spacedata.first;
 
275
                                ED_space_clip_set_mask(C, sc, mask);
 
276
                                break;
 
277
                        }
 
278
                        case SPACE_SEQ:
 
279
                        {
 
280
                                /* do nothing */
 
281
                                break;
 
282
                        }
 
283
                        case SPACE_IMAGE:
 
284
                        {
 
285
                                SpaceImage *sima = sa->spacedata.first;
 
286
                                ED_space_image_set_mask(C, sima, mask);
 
287
                                break;
 
288
                        }
 
289
                }
 
290
        }
 
291
 
 
292
        return mask;
 
293
}
 
294
 
 
295
static int mask_new_exec(bContext *C, wmOperator *op)
 
296
{
 
297
        char name[MAX_ID_NAME - 2];
 
298
 
 
299
        RNA_string_get(op->ptr, "name", name);
 
300
 
 
301
        ED_mask_new(C, name);
 
302
 
 
303
        return OPERATOR_FINISHED;
 
304
}
 
305
 
 
306
void MASK_OT_new(wmOperatorType *ot)
 
307
{
 
308
        /* identifiers */
 
309
        ot->name = "New Mask";
 
310
        ot->description = "Create new mask";
 
311
        ot->idname = "MASK_OT_new";
 
312
 
 
313
        /* flags */
 
314
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
315
 
 
316
        /* api callbacks */
 
317
        ot->exec = mask_new_exec;
 
318
        ot->poll = ED_operator_mask;
 
319
 
 
320
        /* properties */
 
321
        RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask");
 
322
}
 
323
 
 
324
/******************** create new masklay *********************/
 
325
 
 
326
static int masklay_new_exec(bContext *C, wmOperator *op)
 
327
{
 
328
        Mask *mask = CTX_data_edit_mask(C);
 
329
        char name[MAX_ID_NAME - 2];
 
330
 
 
331
        RNA_string_get(op->ptr, "name", name);
 
332
 
 
333
        BKE_mask_layer_new(mask, name);
 
334
        mask->masklay_act = mask->masklay_tot - 1;
 
335
 
 
336
        WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
 
337
 
 
338
        return OPERATOR_FINISHED;
 
339
}
 
340
 
 
341
void MASK_OT_layer_new(wmOperatorType *ot)
 
342
{
 
343
        /* identifiers */
 
344
        ot->name = "Add Mask Layer";
 
345
        ot->description = "Add new mask layer for masking";
 
346
        ot->idname = "MASK_OT_layer_new";
 
347
 
 
348
        /* api callbacks */
 
349
        ot->exec = masklay_new_exec;
 
350
        ot->poll = ED_maskedit_poll;
 
351
 
 
352
        /* flags */
 
353
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
354
 
 
355
        /* properties */
 
356
        RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask layer");
 
357
}
 
358
 
 
359
/******************** remove mask layer *********************/
 
360
 
 
361
static int masklay_remove_exec(bContext *C, wmOperator *UNUSED(op))
 
362
{
 
363
        Mask *mask = CTX_data_edit_mask(C);
 
364
        MaskLayer *masklay = BKE_mask_layer_active(mask);
 
365
 
 
366
        if (masklay) {
 
367
                BKE_mask_layer_remove(mask, masklay);
 
368
 
 
369
                WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
 
370
        }
 
371
 
 
372
        return OPERATOR_FINISHED;
 
373
}
 
374
 
 
375
void MASK_OT_layer_remove(wmOperatorType *ot)
 
376
{
 
377
        /* identifiers */
 
378
        ot->name = "Remove Mask Layer";
 
379
        ot->description = "Remove mask layer";
 
380
        ot->idname = "MASK_OT_layer_remove";
 
381
 
 
382
        /* api callbacks */
 
383
        ot->exec = masklay_remove_exec;
 
384
        ot->poll = ED_maskedit_poll;
 
385
 
 
386
        /* flags */
 
387
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
388
}
 
389
 
 
390
/******************** slide *********************/
 
391
 
 
392
enum {
 
393
        SLIDE_ACTION_NONE    = 0,
 
394
        SLIDE_ACTION_POINT   = 1,
 
395
        SLIDE_ACTION_HANDLE  = 2,
 
396
        SLIDE_ACTION_FEATHER = 3
 
397
};
 
398
 
 
399
typedef struct SlidePointData {
 
400
        int action;
 
401
 
 
402
        float co[2];
 
403
        float vec[3][3];
 
404
 
 
405
        Mask *mask;
 
406
        MaskLayer *masklay;
 
407
        MaskSpline *spline, *orig_spline;
 
408
        MaskSplinePoint *point;
 
409
        MaskSplinePointUW *uw;
 
410
        float handle[2], no[2], feather[2];
 
411
        int width, height;
 
412
        float weight, weight_scalar;
 
413
 
 
414
        short curvature_only, accurate;
 
415
        short initial_feather, overall_feather;
 
416
} SlidePointData;
 
417
 
 
418
static int slide_point_check_initial_feather(MaskSpline *spline)
 
419
{
 
420
        int i;
 
421
 
 
422
        for (i = 0; i < spline->tot_point; i++) {
 
423
                MaskSplinePoint *point = &spline->points[i];
 
424
 
 
425
                if (point->bezt.weight != 0.0f)
 
426
                        return FALSE;
 
427
 
 
428
                /* comment for now. if all bezt weights are zero - this is as good-as initial */
 
429
#if 0
 
430
                int j;
 
431
                for (j = 0; j < point->tot_uw; j++) {
 
432
                        if (point->uw[j].w != 0.0f)
 
433
                                return FALSE;
 
434
                }
 
435
#endif
 
436
        }
 
437
 
 
438
        return TRUE;
 
439
}
 
440
 
 
441
static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event)
 
442
{
 
443
        ScrArea *sa = CTX_wm_area(C);
 
444
        ARegion *ar = CTX_wm_region(C);
 
445
 
 
446
        Mask *mask = CTX_data_edit_mask(C);
 
447
        SlidePointData *customdata = NULL;
 
448
        MaskLayer *masklay, *cv_masklay, *feather_masklay;
 
449
        MaskSpline *spline, *cv_spline, *feather_spline;
 
450
        MaskSplinePoint *point, *cv_point, *feather_point;
 
451
        MaskSplinePointUW *uw = NULL;
 
452
        int is_handle = FALSE, width, height, action = SLIDE_ACTION_NONE;
 
453
        int slide_feather = RNA_boolean_get(op->ptr, "slide_feather");
 
454
        float co[2], cv_score, feather_score;
 
455
        const float threshold = 19;
 
456
 
 
457
        ED_mask_mouse_pos(sa, ar, event->mval, co);
 
458
        ED_mask_get_size(sa, &width, &height);
 
459
 
 
460
        cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &is_handle, &cv_score);
 
461
 
 
462
        if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_masklay, &feather_spline, &feather_point, &uw, &feather_score)) {
 
463
                if (slide_feather || !cv_point || feather_score < cv_score) {
 
464
                        action = SLIDE_ACTION_FEATHER;
 
465
 
 
466
                        masklay = feather_masklay;
 
467
                        spline = feather_spline;
 
468
                        point = feather_point;
 
469
                }
 
470
        }
 
471
 
 
472
        if (cv_point && action == SLIDE_ACTION_NONE) {
 
473
                if (is_handle)
 
474
                        action = SLIDE_ACTION_HANDLE;
 
475
                else
 
476
                        action = SLIDE_ACTION_POINT;
 
477
 
 
478
                masklay = cv_masklay;
 
479
                spline = cv_spline;
 
480
                point = cv_point;
 
481
        }
 
482
 
 
483
        if (action != SLIDE_ACTION_NONE) {
 
484
                customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data");
 
485
 
 
486
                customdata->mask = mask;
 
487
                customdata->masklay = masklay;
 
488
                customdata->spline = spline;
 
489
                customdata->point = point;
 
490
                customdata->width = width;
 
491
                customdata->height = height;
 
492
                customdata->action = action;
 
493
                customdata->uw = uw;
 
494
 
 
495
                if (uw) {
 
496
                        float co_uw[2];
 
497
                        float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u);
 
498
 
 
499
                        customdata->weight = uw->w;
 
500
                        customdata->weight_scalar = weight_scalar;
 
501
                        BKE_mask_point_segment_co(spline, point, uw->u, co_uw);
 
502
                        BKE_mask_point_normal(spline, point, uw->u, customdata->no);
 
503
 
 
504
                        madd_v2_v2v2fl(customdata->feather, co_uw, customdata->no, uw->w * weight_scalar);
 
505
                }
 
506
                else {
 
507
                        BezTriple *bezt = &point->bezt;
 
508
 
 
509
                        customdata->weight = bezt->weight;
 
510
                        customdata->weight_scalar = 1.0f;
 
511
                        BKE_mask_point_normal(spline, point, 0.0f, customdata->no);
 
512
 
 
513
                        madd_v2_v2v2fl(customdata->feather, bezt->vec[1], customdata->no, bezt->weight);
 
514
                }
 
515
 
 
516
                if (customdata->action == SLIDE_ACTION_FEATHER)
 
517
                        customdata->initial_feather = slide_point_check_initial_feather(spline);
 
518
 
 
519
                copy_m3_m3(customdata->vec, point->bezt.vec);
 
520
                if (BKE_mask_point_has_handle(point))
 
521
                        BKE_mask_point_handle(point, customdata->handle);
 
522
                ED_mask_mouse_pos(sa, ar, event->mval, customdata->co);
 
523
        }
 
524
 
 
525
        return customdata;
 
526
}
 
527
 
 
528
static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
529
{
 
530
        SlidePointData *slidedata = slide_point_customdata(C, op, event);
 
531
 
 
532
        if (slidedata) {
 
533
                Mask *mask = CTX_data_edit_mask(C);
 
534
 
 
535
                op->customdata = slidedata;
 
536
 
 
537
                WM_event_add_modal_handler(C, op);
 
538
 
 
539
#if 0
 
540
                if (slidedata->uw) {
 
541
                        if ((slidedata->uw->flag & SELECT) == 0) {
 
542
                                ED_mask_select_toggle_all(mask, SEL_DESELECT);
 
543
 
 
544
                                slidedata->uw->flag |= SELECT;
 
545
 
 
546
                                ED_mask_select_flush_all(mask);
 
547
                        }
 
548
                }
 
549
                else if (!MASKPOINT_ISSEL_ANY(slidedata->point)) {
 
550
                        ED_mask_select_toggle_all(mask, SEL_DESELECT);
 
551
 
 
552
                        BKE_mask_point_select_set(slidedata->point, TRUE);
 
553
 
 
554
                        ED_mask_select_flush_all(mask);
 
555
                }
 
556
#endif
 
557
 
 
558
                slidedata->masklay->act_spline = slidedata->spline;
 
559
                slidedata->masklay->act_point = slidedata->point;
 
560
 
 
561
                WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
 
562
 
 
563
                return OPERATOR_RUNNING_MODAL;
 
564
        }
 
565
 
 
566
        return OPERATOR_PASS_THROUGH;
 
567
}
 
568
 
 
569
static void slide_point_delta_all_feather(SlidePointData *data, float delta)
 
570
{
 
571
        int i;
 
572
 
 
573
        for (i = 0; i < data->spline->tot_point; i++) {
 
574
                MaskSplinePoint *point = &data->spline->points[i];
 
575
                MaskSplinePoint *orig_point = &data->orig_spline->points[i];
 
576
 
 
577
                point->bezt.weight = orig_point->bezt.weight + delta;
 
578
                if (point->bezt.weight < 0.0f)
 
579
                        point->bezt.weight = 0.0f;
 
580
 
 
581
                /* not needed anymore */
 
582
#if 0
 
583
                int j;
 
584
                for (j = 0; j < point->tot_uw; j++) {
 
585
                        point->uw[j].w = orig_point->uw[j].w + delta;
 
586
                        if (point->uw[j].w < 0.0f)
 
587
                                point->uw[j].w = 0.0f;
 
588
                }
 
589
#endif
 
590
        }
 
591
}
 
592
 
 
593
static void slide_point_restore_spline(SlidePointData *data)
 
594
{
 
595
        int i;
 
596
 
 
597
        for (i = 0; i < data->spline->tot_point; i++) {
 
598
                MaskSplinePoint *point = &data->spline->points[i];
 
599
                MaskSplinePoint *orig_point = &data->orig_spline->points[i];
 
600
                int j;
 
601
 
 
602
                point->bezt = orig_point->bezt;
 
603
 
 
604
                for (j = 0; j < point->tot_uw; j++)
 
605
                        point->uw[j] = orig_point->uw[j];
 
606
        }
 
607
}
 
608
 
 
609
static void cancel_slide_point(SlidePointData *data)
 
610
{
 
611
        /* cancel sliding */
 
612
 
 
613
        if (data->orig_spline) {
 
614
                slide_point_restore_spline(data);
 
615
        }
 
616
        else {
 
617
                if (data->action == SLIDE_ACTION_FEATHER) {
 
618
                        if (data->uw)
 
619
                                data->uw->w = data->weight;
 
620
                        else
 
621
                                data->point->bezt.weight = data->weight;
 
622
                }
 
623
                else {
 
624
                        copy_m3_m3(data->point->bezt.vec, data->vec);
 
625
                }
 
626
        }
 
627
}
 
628
 
 
629
static void free_slide_point_data(SlidePointData *data)
 
630
{
 
631
        if (data->orig_spline)
 
632
                BKE_mask_spline_free(data->orig_spline);
 
633
 
 
634
        MEM_freeN(data);
 
635
}
 
636
 
 
637
static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event)
 
638
{
 
639
        SlidePointData *data = (SlidePointData *)op->customdata;
 
640
        BezTriple *bezt = &data->point->bezt;
 
641
        float co[2], dco[2];
 
642
 
 
643
        switch (event->type) {
 
644
                case LEFTALTKEY:
 
645
                case RIGHTALTKEY:
 
646
                case LEFTSHIFTKEY:
 
647
                case RIGHTSHIFTKEY:
 
648
                        if (ELEM(event->type, LEFTALTKEY, RIGHTALTKEY)) {
 
649
                                if (data->action == SLIDE_ACTION_FEATHER)
 
650
                                        data->overall_feather = (event->val == KM_PRESS);
 
651
                                else
 
652
                                        data->curvature_only = (event->val == KM_PRESS);
 
653
                        }
 
654
 
 
655
                        if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
 
656
                                data->accurate = (event->val == KM_PRESS);
 
657
 
 
658
                /* no break! update CV position */
 
659
 
 
660
                case MOUSEMOVE:
 
661
                {
 
662
                        ScrArea *sa = CTX_wm_area(C);
 
663
                        ARegion *ar = CTX_wm_region(C);
 
664
 
 
665
                        ED_mask_mouse_pos(sa, ar, event->mval, co);
 
666
                        sub_v2_v2v2(dco, co, data->co);
 
667
 
 
668
                        if (data->action == SLIDE_ACTION_HANDLE) {
 
669
                                float delta[2], offco[2];
 
670
 
 
671
                                sub_v2_v2v2(delta, data->handle, data->co);
 
672
 
 
673
                                sub_v2_v2v2(offco, co, data->co);
 
674
                                if (data->accurate)
 
675
                                        mul_v2_fl(offco, 0.2f);
 
676
                                add_v2_v2(offco, data->co);
 
677
                                add_v2_v2(offco, delta);
 
678
 
 
679
                                BKE_mask_point_set_handle(data->point, offco, data->curvature_only, data->handle, data->vec);
 
680
                        }
 
681
                        else if (data->action == SLIDE_ACTION_POINT) {
 
682
                                float delta[2];
 
683
 
 
684
                                copy_v2_v2(delta, dco);
 
685
                                if (data->accurate)
 
686
                                        mul_v2_fl(delta, 0.2f);
 
687
 
 
688
                                add_v2_v2v2(bezt->vec[0], data->vec[0], delta);
 
689
                                add_v2_v2v2(bezt->vec[1], data->vec[1], delta);
 
690
                                add_v2_v2v2(bezt->vec[2], data->vec[2], delta);
 
691
                        }
 
692
                        else if (data->action == SLIDE_ACTION_FEATHER) {
 
693
                                float vec[2], no[2], p[2], c[2], w, offco[2];
 
694
                                float *weight = NULL;
 
695
                                float weight_scalar = 1.0f;
 
696
                                int overall_feather = data->overall_feather || data->initial_feather;
 
697
 
 
698
                                add_v2_v2v2(offco, data->feather, dco);
 
699
 
 
700
                                if (data->uw) {
 
701
                                        /* project on both sides and find the closest one,
 
702
                                         * prevents flickering when projecting onto both sides can happen */
 
703
                                        const float u_pos = BKE_mask_spline_project_co(data->spline, data->point,
 
704
                                                                                       data->uw->u, offco, MASK_PROJ_NEG);
 
705
                                        const float u_neg = BKE_mask_spline_project_co(data->spline, data->point,
 
706
                                                                                       data->uw->u, offco, MASK_PROJ_POS);
 
707
                                        float dist_pos = FLT_MAX;
 
708
                                        float dist_neg = FLT_MAX;
 
709
                                        float co_pos[2];
 
710
                                        float co_neg[2];
 
711
                                        float u;
 
712
 
 
713
                                        if (u_pos > 0.0f && u_pos < 1.0f) {
 
714
                                                BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos);
 
715
                                                dist_pos = len_squared_v2v2(offco, co_pos);
 
716
                                        }
 
717
 
 
718
                                        if (u_neg > 0.0f && u_neg < 1.0f) {
 
719
                                                BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg);
 
720
                                                dist_neg = len_squared_v2v2(offco, co_neg);
 
721
                                        }
 
722
 
 
723
                                        u = dist_pos < dist_neg ? u_pos : u_neg;
 
724
 
 
725
                                        if (u > 0.0f && u < 1.0f) {
 
726
                                                data->uw->u = u;
 
727
 
 
728
                                                data->uw = BKE_mask_point_sort_uw(data->point, data->uw);
 
729
                                                weight = &data->uw->w;
 
730
                                                weight_scalar = BKE_mask_point_weight_scalar(data->spline, data->point, u);
 
731
                                                if (weight_scalar != 0.0f) {
 
732
                                                        weight_scalar = 1.0f / weight_scalar;
 
733
                                                }
 
734
 
 
735
                                                BKE_mask_point_normal(data->spline, data->point, data->uw->u, no);
 
736
                                                BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p);
 
737
                                        }
 
738
                                }
 
739
                                else {
 
740
                                        weight = &bezt->weight;
 
741
                                        /* weight_scalar = 1.0f; keep as is */
 
742
                                        copy_v2_v2(no, data->no);
 
743
                                        copy_v2_v2(p, bezt->vec[1]);
 
744
                                }
 
745
 
 
746
                                if (weight) {
 
747
                                        sub_v2_v2v2(c, offco, p);
 
748
                                        project_v2_v2v2(vec, c, no);
 
749
 
 
750
                                        w = len_v2(vec);
 
751
 
 
752
                                        if (overall_feather) {
 
753
                                                float delta;
 
754
 
 
755
                                                if (dot_v2v2(no, vec) <= 0.0f)
 
756
                                                        w = -w;
 
757
 
 
758
                                                delta = w - data->weight * data->weight_scalar;
 
759
 
 
760
                                                if (data->orig_spline == NULL) {
 
761
                                                        /* restore weight for currently sliding point, so orig_spline would be created
 
762
                                                         * with original weights used
 
763
                                                         */
 
764
                                                        *weight = data->weight;
 
765
 
 
766
                                                        data->orig_spline = BKE_mask_spline_copy(data->spline);
 
767
                                                }
 
768
 
 
769
                                                slide_point_delta_all_feather(data, delta);
 
770
                                        }
 
771
                                        else {
 
772
                                                if (dot_v2v2(no, vec) <= 0.0f)
 
773
                                                        w = 0.0f;
 
774
 
 
775
                                                if (data->orig_spline) {
 
776
                                                        /* restore possible overall feather changes */
 
777
                                                        slide_point_restore_spline(data);
 
778
 
 
779
                                                        BKE_mask_spline_free(data->orig_spline);
 
780
                                                        data->orig_spline = NULL;
 
781
                                                }
 
782
 
 
783
                                                if (weight_scalar != 0.0f) {
 
784
                                                        *weight = w * weight_scalar;
 
785
                                                }
 
786
                                        }
 
787
                                }
 
788
                        }
 
789
 
 
790
                        WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
 
791
                        DAG_id_tag_update(&data->mask->id, 0);
 
792
 
 
793
                        break;
 
794
                }
 
795
 
 
796
                case LEFTMOUSE:
 
797
                        if (event->val == KM_RELEASE) {
 
798
                                Scene *scene = CTX_data_scene(C);
 
799
 
 
800
                                /* dont key sliding feather uw's */
 
801
                                if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == FALSE) {
 
802
                                        if (IS_AUTOKEY_ON(scene)) {
 
803
                                                ED_mask_layer_shape_auto_key(data->masklay, CFRA);
 
804
                                        }
 
805
                                }
 
806
 
 
807
                                WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
 
808
                                DAG_id_tag_update(&data->mask->id, 0);
 
809
 
 
810
                                free_slide_point_data(op->customdata); /* keep this last! */
 
811
                                return OPERATOR_FINISHED;
 
812
                        }
 
813
 
 
814
                        break;
 
815
 
 
816
                case ESCKEY:
 
817
                        cancel_slide_point(op->customdata);
 
818
 
 
819
                        WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
 
820
                        DAG_id_tag_update(&data->mask->id, 0);
 
821
 
 
822
                        free_slide_point_data(op->customdata); /* keep this last! */
 
823
                        return OPERATOR_CANCELLED;
 
824
        }
 
825
 
 
826
        return OPERATOR_RUNNING_MODAL;
 
827
}
 
828
 
 
829
void MASK_OT_slide_point(wmOperatorType *ot)
 
830
{
 
831
        /* identifiers */
 
832
        ot->name = "Slide Point";
 
833
        ot->description = "Slide control points";
 
834
        ot->idname = "MASK_OT_slide_point";
 
835
 
 
836
        /* api callbacks */
 
837
        ot->invoke = slide_point_invoke;
 
838
        ot->modal = slide_point_modal;
 
839
        ot->poll = ED_maskedit_mask_poll;
 
840
 
 
841
        /* flags */
 
842
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
843
 
 
844
        RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide feather instead of vertex");
 
845
}
 
846
 
 
847
/******************** toggle cyclic *********************/
 
848
 
 
849
static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op))
 
850
{
 
851
        Mask *mask = CTX_data_edit_mask(C);
 
852
        MaskLayer *masklay;
 
853
 
 
854
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
855
                MaskSpline *spline;
 
856
 
 
857
                if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
 
858
                        continue;
 
859
                }
 
860
 
 
861
                for (spline = masklay->splines.first; spline; spline = spline->next) {
 
862
                        if (ED_mask_spline_select_check(spline)) {
 
863
                                spline->flag ^= MASK_SPLINE_CYCLIC;
 
864
                        }
 
865
                }
 
866
        }
 
867
 
 
868
        WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
 
869
 
 
870
        return OPERATOR_FINISHED;
 
871
}
 
872
 
 
873
void MASK_OT_cyclic_toggle(wmOperatorType *ot)
 
874
{
 
875
        /* identifiers */
 
876
        ot->name = "Toggle Cyclic";
 
877
        ot->description = "Toggle cyclic for selected splines";
 
878
        ot->idname = "MASK_OT_cyclic_toggle";
 
879
 
 
880
        /* api callbacks */
 
881
        ot->exec = cyclic_toggle_exec;
 
882
        ot->poll = ED_maskedit_mask_poll;
 
883
 
 
884
        /* flags */
 
885
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
886
}
 
887
 
 
888
/******************** delete *********************/
 
889
 
 
890
static void delete_feather_points(MaskSplinePoint *point)
 
891
{
 
892
        int i, count = 0;
 
893
 
 
894
        if (!point->tot_uw)
 
895
                return;
 
896
 
 
897
        for (i = 0; i < point->tot_uw; i++) {
 
898
                if ((point->uw[i].flag & SELECT) == 0)
 
899
                        count++;
 
900
        }
 
901
 
 
902
        if (count == 0) {
 
903
                MEM_freeN(point->uw);
 
904
                point->uw = NULL;
 
905
                point->tot_uw = 0;
 
906
        }
 
907
        else {
 
908
                MaskSplinePointUW *new_uw;
 
909
                int j = 0;
 
910
 
 
911
                new_uw = MEM_callocN(count * sizeof(MaskSplinePointUW), "new mask uw points");
 
912
 
 
913
                for (i = 0; i < point->tot_uw; i++) {
 
914
                        if ((point->uw[i].flag & SELECT) == 0) {
 
915
                                new_uw[j++] = point->uw[i];
 
916
                        }
 
917
                }
 
918
 
 
919
                MEM_freeN(point->uw);
 
920
 
 
921
                point->uw = new_uw;
 
922
                point->tot_uw = count;
 
923
        }
 
924
}
 
925
 
 
926
static int delete_exec(bContext *C, wmOperator *UNUSED(op))
 
927
{
 
928
        Scene *scene = CTX_data_scene(C);
 
929
        Mask *mask = CTX_data_edit_mask(C);
 
930
        MaskLayer *masklay;
 
931
 
 
932
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
933
                MaskSpline *spline;
 
934
                int mask_layer_shape_ofs = 0;
 
935
 
 
936
                if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
 
937
                        continue;
 
938
                }
 
939
 
 
940
                spline = masklay->splines.first;
 
941
 
 
942
                while (spline) {
 
943
                        const int tot_point_orig = spline->tot_point;
 
944
                        int i, count = 0;
 
945
                        MaskSpline *next_spline = spline->next;
 
946
 
 
947
                        /* count unselected points */
 
948
                        for (i = 0; i < spline->tot_point; i++) {
 
949
                                MaskSplinePoint *point = &spline->points[i];
 
950
 
 
951
                                if (!MASKPOINT_ISSEL_ANY(point))
 
952
                                        count++;
 
953
                        }
 
954
 
 
955
                        if (count == 0) {
 
956
 
 
957
                                /* delete the whole spline */
 
958
                                BLI_remlink(&masklay->splines, spline);
 
959
                                BKE_mask_spline_free(spline);
 
960
 
 
961
                                if (spline == masklay->act_spline) {
 
962
                                        masklay->act_spline = NULL;
 
963
                                        masklay->act_point = NULL;
 
964
                                }
 
965
 
 
966
                                BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs, tot_point_orig);
 
967
                        }
 
968
                        else {
 
969
                                MaskSplinePoint *new_points;
 
970
                                int j;
 
971
 
 
972
                                new_points = MEM_callocN(count * sizeof(MaskSplinePoint), "deleteMaskPoints");
 
973
 
 
974
                                for (i = 0, j = 0; i < tot_point_orig; i++) {
 
975
                                        MaskSplinePoint *point = &spline->points[i];
 
976
 
 
977
                                        if (!MASKPOINT_ISSEL_ANY(point)) {
 
978
                                                if (point == masklay->act_point)
 
979
                                                        masklay->act_point = &new_points[j];
 
980
 
 
981
                                                delete_feather_points(point);
 
982
 
 
983
                                                new_points[j] = *point;
 
984
                                                j++;
 
985
                                        }
 
986
                                        else {
 
987
                                                if (point == masklay->act_point)
 
988
                                                        masklay->act_point = NULL;
 
989
 
 
990
                                                BKE_mask_point_free(point);
 
991
                                                spline->tot_point--;
 
992
 
 
993
                                                BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs + j, 1);
 
994
                                        }
 
995
                                }
 
996
 
 
997
                                mask_layer_shape_ofs += spline->tot_point;
 
998
 
 
999
                                MEM_freeN(spline->points);
 
1000
                                spline->points = new_points;
 
1001
 
 
1002
                                ED_mask_select_flush_all(mask);
 
1003
                        }
 
1004
 
 
1005
                        spline = next_spline;
 
1006
                }
 
1007
 
 
1008
                /* not essential but confuses users when there are keys with no data!
 
1009
                 * assume if they delete all data from the layer they also dont care about keys */
 
1010
                if (masklay->splines.first == NULL) {
 
1011
                        BKE_mask_layer_free_shapes(masklay);
 
1012
                }
 
1013
        }
 
1014
 
 
1015
        /* TODO: only update edited splines */
 
1016
        BKE_mask_update_display(mask, CFRA);
 
1017
 
 
1018
        WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
 
1019
 
 
1020
        return OPERATOR_FINISHED;
 
1021
}
 
1022
 
 
1023
void MASK_OT_delete(wmOperatorType *ot)
 
1024
{
 
1025
        /* identifiers */
 
1026
        ot->name = "Delete";
 
1027
        ot->description = "Delete selected control points or splines";
 
1028
        ot->idname = "MASK_OT_delete";
 
1029
 
 
1030
        /* api callbacks */
 
1031
        ot->invoke = WM_operator_confirm;
 
1032
        ot->exec = delete_exec;
 
1033
        ot->poll = ED_maskedit_mask_poll;
 
1034
 
 
1035
        /* flags */
 
1036
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
1037
}
 
1038
 
 
1039
/* *** switch direction *** */
 
1040
static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
 
1041
{
 
1042
        Scene *scene = CTX_data_scene(C);
 
1043
        Mask *mask = CTX_data_edit_mask(C);
 
1044
        MaskLayer *masklay;
 
1045
 
 
1046
        int change = FALSE;
 
1047
 
 
1048
        /* do actual selection */
 
1049
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
1050
                MaskSpline *spline;
 
1051
                int change_layer = FALSE;
 
1052
 
 
1053
                if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
 
1054
                        continue;
 
1055
                }
 
1056
 
 
1057
                for (spline = masklay->splines.first; spline; spline = spline->next) {
 
1058
                        if (ED_mask_spline_select_check(spline)) {
 
1059
                                BKE_mask_spline_direction_switch(masklay, spline);
 
1060
                                change = TRUE;
 
1061
                                change_layer = TRUE;
 
1062
                        }
 
1063
                }
 
1064
 
 
1065
                if (change_layer) {
 
1066
                        if (IS_AUTOKEY_ON(scene)) {
 
1067
                                ED_mask_layer_shape_auto_key(masklay, CFRA);
 
1068
                        }
 
1069
                }
 
1070
        }
 
1071
 
 
1072
        if (change) {
 
1073
                /* TODO: only update this spline */
 
1074
                BKE_mask_update_display(mask, CFRA);
 
1075
 
 
1076
                WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
 
1077
 
 
1078
                return OPERATOR_FINISHED;
 
1079
        }
 
1080
 
 
1081
        return OPERATOR_CANCELLED;
 
1082
}
 
1083
 
 
1084
void MASK_OT_switch_direction(wmOperatorType *ot)
 
1085
{
 
1086
        /* identifiers */
 
1087
        ot->name = "Switch Direction";
 
1088
        ot->description = "Switch direction of selected splines";
 
1089
        ot->idname = "MASK_OT_switch_direction";
 
1090
 
 
1091
        /* api callbacks */
 
1092
        ot->exec = mask_switch_direction_exec;
 
1093
        ot->poll = ED_maskedit_mask_poll;
 
1094
 
 
1095
        /* flags */
 
1096
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
1097
}
 
1098
 
 
1099
 
 
1100
/* *** recalc normals *** */
 
1101
static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op))
 
1102
{
 
1103
        Scene *scene = CTX_data_scene(C);
 
1104
        Mask *mask = CTX_data_edit_mask(C);
 
1105
        MaskLayer *masklay;
 
1106
        int i;
 
1107
 
 
1108
        int change = FALSE;
 
1109
 
 
1110
        /* do actual selection */
 
1111
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
1112
                MaskSpline *spline;
 
1113
                int change_layer = FALSE;
 
1114
 
 
1115
                if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
 
1116
                        continue;
 
1117
                }
 
1118
 
 
1119
                for (spline = masklay->splines.first; spline; spline = spline->next) {
 
1120
                        for (i = 0; i < spline->tot_point; i++) {
 
1121
                                MaskSplinePoint *point = &spline->points[i];
 
1122
 
 
1123
                                if (MASKPOINT_ISSEL_ANY(point)) {
 
1124
                                        BKE_mask_calc_handle_point_auto(spline, point, FALSE);
 
1125
                                        change = TRUE;
 
1126
                                        change_layer = TRUE;
 
1127
                                }
 
1128
                        }
 
1129
                }
 
1130
 
 
1131
                if (change_layer) {
 
1132
                        if (IS_AUTOKEY_ON(scene)) {
 
1133
                                ED_mask_layer_shape_auto_key(masklay, CFRA);
 
1134
                        }
 
1135
                }
 
1136
        }
 
1137
 
 
1138
        if (change) {
 
1139
                /* TODO: only update this spline */
 
1140
                BKE_mask_update_display(mask, CFRA);
 
1141
 
 
1142
                WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
 
1143
 
 
1144
                return OPERATOR_FINISHED;
 
1145
        }
 
1146
 
 
1147
        return OPERATOR_CANCELLED;
 
1148
}
 
1149
 
 
1150
/* named to match mesh recalc normals */
 
1151
void MASK_OT_normals_make_consistent(wmOperatorType *ot)
 
1152
{
 
1153
        /* identifiers */
 
1154
        ot->name = "Recalc Normals";
 
1155
        ot->description = "Re-calculate the direction of selected handles";
 
1156
        ot->idname = "MASK_OT_normals_make_consistent";
 
1157
 
 
1158
        /* api callbacks */
 
1159
        ot->exec = mask_normals_make_consistent_exec;
 
1160
        ot->poll = ED_maskedit_mask_poll;
 
1161
 
 
1162
        /* flags */
 
1163
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
1164
}
 
1165
 
 
1166
 
 
1167
/******************** set handle type *********************/
 
1168
 
 
1169
static int set_handle_type_exec(bContext *C, wmOperator *op)
 
1170
{
 
1171
        Mask *mask = CTX_data_edit_mask(C);
 
1172
        MaskLayer *masklay;
 
1173
        int handle_type = RNA_enum_get(op->ptr, "type");
 
1174
 
 
1175
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
1176
                MaskSpline *spline;
 
1177
                int i;
 
1178
 
 
1179
                if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
 
1180
                        continue;
 
1181
                }
 
1182
 
 
1183
                for (spline = masklay->splines.first; spline; spline = spline->next) {
 
1184
                        for (i = 0; i < spline->tot_point; i++) {
 
1185
                                MaskSplinePoint *point = &spline->points[i];
 
1186
 
 
1187
                                if (MASKPOINT_ISSEL_ANY(point)) {
 
1188
                                        BezTriple *bezt = &point->bezt;
 
1189
 
 
1190
                                        bezt->h1 = bezt->h2 = handle_type;
 
1191
                                }
 
1192
                        }
 
1193
                }
 
1194
        }
 
1195
 
 
1196
        WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
 
1197
        DAG_id_tag_update(&mask->id, 0);
 
1198
 
 
1199
        return OPERATOR_FINISHED;
 
1200
}
 
1201
 
 
1202
void MASK_OT_handle_type_set(wmOperatorType *ot)
 
1203
{
 
1204
        static EnumPropertyItem editcurve_handle_type_items[] = {
 
1205
                {HD_AUTO, "AUTO", 0, "Auto", ""},
 
1206
                {HD_VECT, "VECTOR", 0, "Vector", ""},
 
1207
                {HD_ALIGN, "ALIGNED", 0, "Aligned", ""},
 
1208
                {0, NULL, 0, NULL, NULL}
 
1209
        };
 
1210
 
 
1211
        /* identifiers */
 
1212
        ot->name = "Set Handle Type";
 
1213
        ot->description = "Set type of handles for selected control points";
 
1214
        ot->idname = "MASK_OT_handle_type_set";
 
1215
 
 
1216
        /* api callbacks */
 
1217
        ot->invoke = WM_menu_invoke;
 
1218
        ot->exec = set_handle_type_exec;
 
1219
        ot->poll = ED_maskedit_mask_poll;
 
1220
 
 
1221
        /* flags */
 
1222
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
1223
 
 
1224
        /* properties */
 
1225
        ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
 
1226
}
 
1227
 
 
1228
 
 
1229
/* ********* clear/set restrict view *********/
 
1230
static int mask_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
 
1231
{
 
1232
        Mask *mask = CTX_data_edit_mask(C);
 
1233
        MaskLayer *masklay;
 
1234
        int changed = FALSE;
 
1235
 
 
1236
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
1237
 
 
1238
                if (masklay->restrictflag & OB_RESTRICT_VIEW) {
 
1239
                        ED_mask_layer_select_set(masklay, TRUE);
 
1240
                        masklay->restrictflag &= ~OB_RESTRICT_VIEW;
 
1241
                        changed = 1;
 
1242
                }
 
1243
        }
 
1244
 
 
1245
        if (changed) {
 
1246
                WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
 
1247
                DAG_id_tag_update(&mask->id, 0);
 
1248
 
 
1249
                return OPERATOR_FINISHED;
 
1250
        }
 
1251
        else {
 
1252
                return OPERATOR_CANCELLED;
 
1253
        }
 
1254
}
 
1255
 
 
1256
void MASK_OT_hide_view_clear(wmOperatorType *ot)
 
1257
{
 
1258
 
 
1259
        /* identifiers */
 
1260
        ot->name = "Clear Restrict View";
 
1261
        ot->description = "Reveal the layer by setting the hide flag";
 
1262
        ot->idname = "MASK_OT_hide_view_clear";
 
1263
 
 
1264
        /* api callbacks */
 
1265
        ot->exec = mask_hide_view_clear_exec;
 
1266
        ot->poll = ED_maskedit_mask_poll;
 
1267
 
 
1268
        /* flags */
 
1269
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
1270
}
 
1271
 
 
1272
static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
 
1273
{
 
1274
        Mask *mask = CTX_data_edit_mask(C);
 
1275
        MaskLayer *masklay;
 
1276
        const int unselected = RNA_boolean_get(op->ptr, "unselected");
 
1277
        int changed = FALSE;
 
1278
 
 
1279
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
1280
 
 
1281
                if (masklay->restrictflag & MASK_RESTRICT_SELECT) {
 
1282
                        continue;
 
1283
                }
 
1284
 
 
1285
                if (!unselected) {
 
1286
                        if (ED_mask_layer_select_check(masklay)) {
 
1287
                                ED_mask_layer_select_set(masklay, FALSE);
 
1288
 
 
1289
                                masklay->restrictflag |= OB_RESTRICT_VIEW;
 
1290
                                changed = 1;
 
1291
                                if (masklay == BKE_mask_layer_active(mask)) {
 
1292
                                        BKE_mask_layer_active_set(mask, NULL);
 
1293
                                }
 
1294
                        }
 
1295
                }
 
1296
                else {
 
1297
                        if (!ED_mask_layer_select_check(masklay)) {
 
1298
                                masklay->restrictflag |= OB_RESTRICT_VIEW;
 
1299
                                changed = 1;
 
1300
                                if (masklay == BKE_mask_layer_active(mask)) {
 
1301
                                        BKE_mask_layer_active_set(mask, NULL);
 
1302
                                }
 
1303
                        }
 
1304
                }
 
1305
        }
 
1306
 
 
1307
        if (changed) {
 
1308
                WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
 
1309
                DAG_id_tag_update(&mask->id, 0);
 
1310
 
 
1311
                return OPERATOR_FINISHED;
 
1312
        }
 
1313
        else {
 
1314
                return OPERATOR_CANCELLED;
 
1315
        }
 
1316
}
 
1317
 
 
1318
void MASK_OT_hide_view_set(wmOperatorType *ot)
 
1319
{
 
1320
        /* identifiers */
 
1321
        ot->name = "Set Restrict View";
 
1322
        ot->description = "Hide the layer by setting the hide flag";
 
1323
        ot->idname = "MASK_OT_hide_view_set";
 
1324
 
 
1325
        /* api callbacks */
 
1326
        ot->exec = mask_hide_view_set_exec;
 
1327
        ot->poll = ED_maskedit_mask_poll;
 
1328
 
 
1329
        /* flags */
 
1330
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
1331
 
 
1332
        RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
 
1333
}
 
1334
 
 
1335
 
 
1336
static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
 
1337
{
 
1338
        Scene *scene = CTX_data_scene(C);
 
1339
        Mask *mask = CTX_data_edit_mask(C);
 
1340
        MaskLayer *masklay;
 
1341
        int changed = FALSE;
 
1342
        int i;
 
1343
 
 
1344
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
 
1345
                MaskSpline *spline;
 
1346
 
 
1347
                if (masklay->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) {
 
1348
                        continue;
 
1349
                }
 
1350
 
 
1351
                for (spline = masklay->splines.first; spline; spline = spline->next) {
 
1352
                        for (i = 0; i < spline->tot_point; i++) {
 
1353
                                MaskSplinePoint *point = &spline->points[i];
 
1354
 
 
1355
                                if (MASKPOINT_ISSEL_ANY(point)) {
 
1356
                                        BezTriple *bezt = &point->bezt;
 
1357
                                        bezt->weight = 0.0f;
 
1358
                                        changed = TRUE;
 
1359
                                }
 
1360
                        }
 
1361
                }
 
1362
        }
 
1363
 
 
1364
        if (changed) {
 
1365
                /* TODO: only update edited splines */
 
1366
                BKE_mask_update_display(mask, CFRA);
 
1367
 
 
1368
                WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
 
1369
                DAG_id_tag_update(&mask->id, 0);
 
1370
 
 
1371
                return OPERATOR_FINISHED;
 
1372
        }
 
1373
        else {
 
1374
                return OPERATOR_CANCELLED;
 
1375
        }
 
1376
}
 
1377
 
 
1378
void MASK_OT_feather_weight_clear(wmOperatorType *ot)
 
1379
{
 
1380
        /* identifiers */
 
1381
        ot->name = "Clear Feather Weight";
 
1382
        ot->description = "Reset the feather weight to zero";
 
1383
        ot->idname = "MASK_OT_feather_weight_clear";
 
1384
 
 
1385
        /* api callbacks */
 
1386
        ot->exec = mask_feather_weight_clear_exec;
 
1387
        ot->poll = ED_maskedit_mask_poll;
 
1388
 
 
1389
        /* flags */
 
1390
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
1391
}
 
1392
 
 
1393
/******************** move mask layer operator *********************/
 
1394
 
 
1395
static int mask_layer_move_poll(bContext *C)
 
1396
{
 
1397
        if (ED_maskedit_mask_poll(C)) {
 
1398
                Mask *mask = CTX_data_edit_mask(C);
 
1399
 
 
1400
                return mask->masklay_tot > 0;
 
1401
        }
 
1402
 
 
1403
        return FALSE;
 
1404
}
 
1405
 
 
1406
static int mask_layer_move_exec(bContext *C, wmOperator *op)
 
1407
{
 
1408
        Mask *mask = CTX_data_edit_mask(C);
 
1409
        MaskLayer *mask_layer = BLI_findlink(&mask->masklayers, mask->masklay_act);
 
1410
        MaskLayer *mask_layer_other;
 
1411
        int direction = RNA_enum_get(op->ptr, "direction");
 
1412
 
 
1413
        if (!mask_layer)
 
1414
                return OPERATOR_CANCELLED;
 
1415
 
 
1416
        if (direction == -1) {
 
1417
                mask_layer_other = mask_layer->prev;
 
1418
 
 
1419
                if (!mask_layer_other)
 
1420
                        return OPERATOR_CANCELLED;
 
1421
 
 
1422
                BLI_remlink(&mask->masklayers, mask_layer);
 
1423
                BLI_insertlinkbefore(&mask->masklayers, mask_layer_other, mask_layer);
 
1424
                mask->masklay_act--;
 
1425
        }
 
1426
        else if (direction == 1) {
 
1427
                mask_layer_other = mask_layer->next;
 
1428
 
 
1429
                if (!mask_layer_other)
 
1430
                        return OPERATOR_CANCELLED;
 
1431
 
 
1432
                BLI_remlink(&mask->masklayers, mask_layer);
 
1433
                BLI_insertlinkafter(&mask->masklayers, mask_layer_other, mask_layer);
 
1434
                mask->masklay_act++;
 
1435
        }
 
1436
 
 
1437
        return OPERATOR_FINISHED;
 
1438
}
 
1439
 
 
1440
void MASK_OT_layer_move(wmOperatorType *ot)
 
1441
{
 
1442
        static EnumPropertyItem direction_items[] = {
 
1443
                {-1, "UP", 0, "Up", ""},
 
1444
                {1, "DOWN", 0, "Down", ""},
 
1445
                {0, NULL, 0, NULL, NULL}
 
1446
        };
 
1447
 
 
1448
        /* identifiers */
 
1449
        ot->name = "Move Layer";
 
1450
        ot->description = "Move the active layer up/down in the list";
 
1451
        ot->idname = "MASK_OT_layer_move";
 
1452
 
 
1453
        /* api callbacks */
 
1454
        ot->exec = mask_layer_move_exec;
 
1455
        ot->poll = mask_layer_move_poll;
 
1456
 
 
1457
        /* flags */
 
1458
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
1459
 
 
1460
        /* properties */
 
1461
        RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move the active layer");
 
1462
}