diff options
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_edit.c')
-rw-r--r-- | source/blender/editors/gpencil/gpencil_edit.c | 201 |
1 files changed, 101 insertions, 100 deletions
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 63f34917a4d..402174437e9 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -27,6 +27,7 @@ * \ingroup edgpencil */ + #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -96,7 +97,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr */ if (sa) { SpaceLink *sl = sa->spacedata.first; - + switch (sa->spacetype) { case SPACE_VIEW3D: /* 3D-View */ case SPACE_TIME: /* Timeline - XXX: this is a hack to get it to show GP keyframes for 3D view */ @@ -106,7 +107,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr if (scene->toolsettings->gpencil_src == GP_TOOL_SOURCE_OBJECT) { /* legacy behaviour for usage with old addons requiring object-linked to objects */ - + /* just in case no active/selected object... */ if (ob && (ob->flag & SELECT)) { /* for now, as long as there's an object, default to using that in 3D-View */ @@ -196,7 +197,7 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) Scene *scene = CTX_data_scene(C); ScrArea *sa = CTX_wm_area(C); Object *ob = CTX_data_active_object(C); - + return ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, ptr); } @@ -247,7 +248,7 @@ static int gp_active_layer_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); - + return (gpl != NULL); } @@ -319,7 +320,7 @@ static int gp_data_unlink_exec(bContext *C, wmOperator *op) } /* notifiers */ - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -367,9 +368,9 @@ void GPENCIL_OT_layer_add(wmOperatorType *ot) ot->name = "Add New Layer"; ot->idname = "GPENCIL_OT_layer_add"; ot->description = "Add new Grease Pencil layer for the active Grease Pencil datablock"; - + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* callbacks */ ot->exec = gp_layer_add_exec; ot->poll = gp_add_poll; @@ -381,17 +382,17 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); - + /* sanity checks */ if (ELEM(NULL, gpd, gpl)) return OPERATOR_CANCELLED; - + if (gpl->flag & GP_LAYER_LOCKED) { BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers"); return OPERATOR_CANCELLED; - } - - /* make the layer before this the new active layer + } + + /* make the layer before this the new active layer * - use the one after if this is the first * - if this is the only layer, this naturally becomes NULL */ @@ -399,13 +400,13 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op) gpencil_layer_setactive(gpd, gpl->prev); else gpencil_layer_setactive(gpd, gpl->next); - + /* delete the layer now... */ gpencil_layer_delete(gpd, gpl); - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -415,9 +416,9 @@ void GPENCIL_OT_layer_remove(wmOperatorType *ot) ot->name = "Remove Layer"; ot->idname = "GPENCIL_OT_layer_remove"; ot->description = "Remove active Grease Pencil layer"; - + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* callbacks */ ot->exec = gp_layer_remove_exec; ot->poll = gp_active_layer_poll; @@ -434,13 +435,13 @@ static int gp_layer_move_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); - + int direction = RNA_enum_get(op->ptr, "type"); - + /* sanity checks */ if (ELEM(NULL, gpd, gpl)) return OPERATOR_CANCELLED; - + /* up or down? */ if (direction == GP_LAYER_MOVE_UP) { /* up */ @@ -452,10 +453,10 @@ static int gp_layer_move_exec(bContext *C, wmOperator *op) BLI_remlink(&gpd->layers, gpl); BLI_insertlinkafter(&gpd->layers, gpl->next, gpl); } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -499,10 +500,10 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes) { bGPDspoint *pt; int i; - + int start_idx = -1; - - + + /* Step through the original stroke's points: * - We accumulate selected points (from start_idx to current index) * and then convert that to a new stroke @@ -517,8 +518,8 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes) } else { size_t len = 0; - - /* is this the end of current island yet? + + /* is this the end of current island yet? * 1) Point i-1 was the last one that was selected * 2) Point i is the last in the array */ @@ -529,23 +530,23 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes) len = i - start_idx + 1; } //printf("copying from %d to %d = %d\n", start_idx, i, len); - + /* make copies of the relevant data */ if (len) { bGPDstroke *gpsd; - + /* make a stupid copy first of the entire stroke (to get the flags too) */ gpsd = MEM_dupallocN(gps); - + /* now, make a new points array, and copy of the relevant parts */ gpsd->points = MEM_callocN(sizeof(bGPDspoint) * len, "gps stroke points copy"); memcpy(gpsd->points, gps->points + start_idx, sizeof(bGPDspoint) * len); gpsd->totpoints = len; - + /* add to temp buffer */ gpsd->next = gpsd->prev = NULL; BLI_addtail(new_strokes, gpsd); - + /* cleanup + reset for next */ start_idx = -1; } @@ -556,12 +557,12 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes) static int gp_duplicate_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - + if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); return OPERATOR_CANCELLED; } - + /* for each visible (and editable) layer's selected strokes, * copy the strokes into a temporary buffer, then append * once all done @@ -571,21 +572,21 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op) ListBase new_strokes = {NULL, NULL}; bGPDframe *gpf = gpl->actframe; bGPDstroke *gps; - + if (gpf == NULL) continue; - + /* make copies of selected strokes, and deselect these once we're done */ for (gps = gpf->strokes.first; gps; gps = gps->next) { if (gps->flag & GP_STROKE_SELECT) { if (gps->totpoints == 1) { /* Special Case: If there's just a single point in this stroke... */ bGPDstroke *gpsd; - + /* make direct copies of the stroke and its points */ gpsd = MEM_dupallocN(gps); gpsd->points = MEM_dupallocN(gps->points); - + /* add to temp buffer */ gpsd->next = gpsd->prev = NULL; BLI_addtail(&new_strokes, gpsd); @@ -594,23 +595,23 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op) /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */ gp_duplicate_points(gps, &new_strokes); } - - /* deselect original stroke, or else the originals get moved too + + /* deselect original stroke, or else the originals get moved too * (when using the copy + move macro) */ gps->flag &= ~GP_STROKE_SELECT; } } - + /* add all new strokes in temp buffer to the frame (preventing double-copies) */ BLI_movelisttolist(&gpf->strokes, &new_strokes); BLI_assert(new_strokes.first == NULL); } CTX_DATA_END; - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -620,11 +621,11 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot) ot->name = "Duplicate Strokes"; ot->idname = "GPENCIL_OT_duplicate"; ot->description = "Duplicate the selected Grease Pencil strokes"; - + /* callbacks */ ot->exec = gp_duplicate_exec; ot->poll = gp_stroke_edit_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -673,7 +674,7 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot) ot->name = "Delete Active Frame"; ot->idname = "GPENCIL_OT_active_frame_delete"; ot->description = "Delete the active frame for the active Grease Pencil datablock"; - + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ @@ -699,30 +700,30 @@ typedef enum eGP_DeleteMode { static int gp_delete_selected_strokes(bContext *C) { bool changed = false; - + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps, *gpsn; - + if (gpf == NULL) continue; - + /* simply delete strokes which are selected */ for (gps = gpf->strokes.first; gps; gps = gpsn) { gpsn = gps->next; - + if (gps->flag & GP_STROKE_SELECT) { /* free stroke memory arrays, then stroke itself */ if (gps->points) MEM_freeN(gps->points); BLI_freelinkN(&gpf->strokes, gps); - + changed = true; } } } CTX_DATA_END; - + if (changed) { WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -736,27 +737,27 @@ static int gp_delete_selected_strokes(bContext *C) static int gp_dissolve_selected_points(bContext *C) { bool changed = false; - + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps, *gpsn; - + if (gpf == NULL) continue; - + /* simply delete points from selected strokes * NOTE: we may still have to remove the stroke if it ends up having no points! */ for (gps = gpf->strokes.first; gps; gps = gpsn) { gpsn = gps->next; - + if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; int i; - + int tot = gps->totpoints; /* number of points in new buffer */ - + /* First Pass: Count how many points are selected (i.e. how many to remove) */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if (pt->flag & GP_SPOINT_SELECT) { @@ -764,42 +765,42 @@ static int gp_dissolve_selected_points(bContext *C) tot--; } } - + /* if no points are left, we simply delete the entire stroke */ if (tot <= 0) { /* remove the entire stroke */ MEM_freeN(gps->points); BLI_freelinkN(&gpf->strokes, gps); } - else { + else { /* just copy all unselected into a smaller buffer */ bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy"); bGPDspoint *npt = new_points; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if ((pt->flag & GP_SPOINT_SELECT) == 0) { *npt = *pt; npt++; } } - + /* free the old buffer */ MEM_freeN(gps->points); - + /* save the new buffer */ gps->points = new_points; gps->totpoints = tot; - + /* deselect the stroke, since none of its selected points will still be selected */ gps->flag &= ~GP_STROKE_SELECT; } - + changed = true; } } } CTX_DATA_END; - + if (changed) { WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -813,27 +814,27 @@ static int gp_dissolve_selected_points(bContext *C) static int gp_delete_selected_points(bContext *C) { bool changed = false; - + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps, *gpsn; - + if (gpf == NULL) continue; - + /* simply delete strokes which are selected */ for (gps = gpf->strokes.first; gps; gps = gpsn) { gpsn = gps->next; - + if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; int i; - + /* The algorithm used here is as follows: * 1) We firstly identify the number of "islands" of non-selected points * which will all end up being in new strokes. - * - In the most extreme case (i.e. every other vert is a 1-vert island), + * - In the most extreme case (i.e. every other vert is a 1-vert island), * we have at most n / 2 islands * - Once we start having larger islands than that, the number required * becomes much less @@ -843,11 +844,11 @@ static int gp_delete_selected_points(bContext *C) int start_idx; int end_idx; } tGPDeleteIsland; - + tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands"); bool in_island = false; int num_islands = 0; - + /* First Pass: Identify start/end of islands */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if (pt->flag & GP_SPOINT_SELECT) { @@ -857,7 +858,7 @@ static int gp_delete_selected_points(bContext *C) else { /* unselected - start of a new island? */ int idx; - + if (in_island) { /* extend existing island */ idx = num_islands - 1; @@ -867,33 +868,33 @@ static int gp_delete_selected_points(bContext *C) /* start of new island */ in_island = true; num_islands++; - + idx = num_islands - 1; islands[idx].start_idx = islands[idx].end_idx = i; } } } - + /* Watch out for special case where No islands = All points selected = Delete Stroke only */ if (num_islands) { /* there are islands, so create a series of new strokes, adding them before the "next" stroke */ int idx; - + /* deselect old stroke, since it will be used as template for the new strokes */ gps->flag &= ~GP_STROKE_SELECT; - + /* create each new stroke... */ for (idx = 0; idx < num_islands; idx++) { tGPDeleteIsland *island = &islands[idx]; bGPDstroke *new_stroke = MEM_dupallocN(gps); - + /* compute new buffer size (+ 1 needed as the endpoint index is "inclusive") */ new_stroke->totpoints = island->end_idx - island->start_idx + 1; new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, "gp delete stroke fragment"); - + /* copy over the relevant points */ memcpy(new_stroke->points, gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints); - + /* add new stroke to the frame */ if (gpsn) { BLI_insertlinkbefore(&gpf->strokes, gpsn, new_stroke); @@ -903,20 +904,20 @@ static int gp_delete_selected_points(bContext *C) } } } - + /* free islands */ MEM_freeN(islands); - + /* Delete the old stroke */ MEM_freeN(gps->points); BLI_freelinkN(&gpf->strokes, gps); - + changed = true; } } } CTX_DATA_END; - + if (changed) { WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -928,28 +929,28 @@ static int gp_delete_selected_points(bContext *C) static int gp_delete_exec(bContext *C, wmOperator *op) -{ +{ eGP_DeleteMode mode = RNA_enum_get(op->ptr, "type"); int result = OPERATOR_CANCELLED; - + switch (mode) { case GP_DELETEOP_STROKES: /* selected strokes */ result = gp_delete_selected_strokes(C); break; - + case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */ result = gp_delete_selected_points(C); break; - + case GP_DELETEOP_POINTS_DISSOLVE: /* selected points (without splitting the stroke) */ result = gp_dissolve_selected_points(C); break; - + case GP_DELETEOP_FRAME: /* active frame */ result = gp_actframe_delete_exec(C, op); break; } - + return result; } @@ -964,20 +965,20 @@ void GPENCIL_OT_delete(wmOperatorType *ot) "Delete selected points without splitting strokes"}, {0, NULL, 0, NULL, NULL} }; - + /* identifiers */ ot->name = "Delete..."; ot->idname = "GPENCIL_OT_delete"; ot->description = "Delete selected Grease Pencil strokes, vertices, or frames"; - + /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gp_delete_exec; ot->poll = gp_stroke_edit_poll; - + /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; - + /* props */ ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_delete_types, 0, "Type", "Method used for deleting Grease Pencil data"); } @@ -1034,7 +1035,7 @@ static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRN /* --- */ -/* convert the coordinates from the given stroke point into 3d-coordinates +/* convert the coordinates from the given stroke point into 3d-coordinates * - assumes that the active space is the 3D-View */ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoint *pt, float p3d[3], rctf *subrect) @@ -1670,8 +1671,8 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt, } static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, - float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point, - const bool add_end_point, tGpTimingData *gtd) + float minmax_weights[2], const float rad_fac, bool stitch, const bool add_start_point, + const bool add_end_point, tGpTimingData *gtd) { bGPDspoint *pt; Nurb *nu = (curnu) ? *curnu : NULL; @@ -2056,7 +2057,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG } switch (mode) { - case GP_STROKECONVERT_PATH: + case GP_STROKECONVERT_PATH: gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, add_start_point, add_end_point, gtd); break; |