Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/gpencil/gpencil_interpolate.c
| Show First 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | for (int i = 0; i < new_stroke->totpoints; i++) { | ||||
| pt = &new_stroke->points[i]; | pt = &new_stroke->points[i]; | ||||
| next = &gps_to->points[i]; | next = &gps_to->points[i]; | ||||
| /* Interpolate all values */ | /* Interpolate all values */ | ||||
| interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor); | interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor); | ||||
| pt->pressure = interpf(prev->pressure, next->pressure, 1.0f - factor); | pt->pressure = interpf(prev->pressure, next->pressure, 1.0f - factor); | ||||
| pt->strength = interpf(prev->strength, next->strength, 1.0f - factor); | pt->strength = interpf(prev->strength, next->strength, 1.0f - factor); | ||||
| CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); | CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); | ||||
| pt->totweight = 0; | |||||
| pt->weights = NULL; | |||||
| } | } | ||||
| } | } | ||||
| /* ****************** Interpolate Interactive *********************** */ | /* ****************** Interpolate Interactive *********************** */ | ||||
| /* Helper: Update all strokes interpolated */ | /* Helper: Update all strokes interpolated */ | ||||
| static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi) | static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi) | ||||
| { | { | ||||
| bGPdata *gpd = tgpi->gpd; | |||||
| tGPDinterpolate_layer *tgpil; | tGPDinterpolate_layer *tgpil; | ||||
| const float shift = tgpi->shift; | const float shift = tgpi->shift; | ||||
| for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) { | for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) { | ||||
| bGPDstroke *new_stroke; | bGPDstroke *new_stroke; | ||||
| const float factor = tgpil->factor + shift; | const float factor = tgpil->factor + shift; | ||||
| for (new_stroke = tgpil->interFrame->strokes.first; new_stroke; new_stroke = new_stroke->next) { | for (new_stroke = tgpil->interFrame->strokes.first; new_stroke; new_stroke = new_stroke->next) { | ||||
| Show All 12 Lines | for (new_stroke = tgpil->interFrame->strokes.first; new_stroke; new_stroke = new_stroke->next) { | ||||
| /* update points position */ | /* update points position */ | ||||
| if ((gps_from) && (gps_to)) { | if ((gps_from) && (gps_to)) { | ||||
| gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor); | gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BKE_gpencil_batch_cache_dirty(gpd); | |||||
| WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); | WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); | ||||
| } | } | ||||
| /* Helper: Verify valid strokes for interpolation */ | /* Helper: Verify valid strokes for interpolation */ | ||||
| static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd) | static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd) | ||||
| { | { | ||||
| ToolSettings *ts = CTX_data_tool_settings(C); | ToolSettings *ts = CTX_data_tool_settings(C); | ||||
| eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag; | eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag; | ||||
| ▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | for (bGPDstroke *gps_from = tgpil->prevFrame->strokes.first; gps_from; gps_from = gps_from->next) { | ||||
| gps_to = BLI_findlink(&tgpil->nextFrame->strokes, fFrame); | gps_to = BLI_findlink(&tgpil->nextFrame->strokes, fFrame); | ||||
| if (gps_to == NULL) { | if (gps_to == NULL) { | ||||
| valid = false; | valid = false; | ||||
| } | } | ||||
| /* create new stroke */ | /* create new stroke */ | ||||
| new_stroke = MEM_dupallocN(gps_from); | new_stroke = MEM_dupallocN(gps_from); | ||||
| new_stroke->points = MEM_dupallocN(gps_from->points); | new_stroke->points = MEM_dupallocN(gps_from->points); | ||||
| BKE_gpencil_stroke_weights_duplicate(gps_from, new_stroke); | |||||
| new_stroke->triangles = MEM_dupallocN(gps_from->triangles); | new_stroke->triangles = MEM_dupallocN(gps_from->triangles); | ||||
| new_stroke->tot_triangles = 0; | new_stroke->tot_triangles = 0; | ||||
| new_stroke->flag |= GP_STROKE_RECALC_CACHES; | new_stroke->flag |= GP_STROKE_RECALC_CACHES; | ||||
| if (valid) { | if (valid) { | ||||
| /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */ | /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */ | ||||
| if (gps_from->totpoints > gps_to->totpoints) { | if (gps_from->totpoints > gps_to->totpoints) { | ||||
| new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints); | new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints); | ||||
| Show All 18 Lines | for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* ----------------------- */ | /* ----------------------- */ | ||||
| /* Drawing Callbacks */ | /* Drawing Callbacks */ | ||||
| /* Drawing callback for modal operator in screen mode */ | /* Drawing callback for modal operator in screen mode */ | ||||
| static void gpencil_interpolate_draw_screen(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg) | static void gpencil_interpolate_draw_screen(const struct bContext *C, ARegion *UNUSED(ar), void *arg) | ||||
| { | { | ||||
| tGPDinterpolate *tgpi = (tGPDinterpolate *)arg; | tGPDinterpolate *tgpi = (tGPDinterpolate *)arg; | ||||
| ED_gp_draw_interpolation(tgpi, REGION_DRAW_POST_PIXEL); | ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_PIXEL); | ||||
| } | } | ||||
| /* Drawing callback for modal operator in 3d mode */ | /* Drawing callback for modal operator in 3d mode */ | ||||
| static void gpencil_interpolate_draw_3d(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg) | static void gpencil_interpolate_draw_3d(const bContext *C, ARegion *UNUSED(ar), void *arg) | ||||
| { | { | ||||
| tGPDinterpolate *tgpi = (tGPDinterpolate *)arg; | tGPDinterpolate *tgpi = (tGPDinterpolate *)arg; | ||||
| ED_gp_draw_interpolation(tgpi, REGION_DRAW_POST_VIEW); | ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_VIEW); | ||||
| } | } | ||||
| /* ----------------------- */ | /* ----------------------- */ | ||||
| /* Helper: calculate shift based on position of mouse (we only use x-axis for now. | /* Helper: calculate shift based on position of mouse (we only use x-axis for now. | ||||
| * since this is more convenient for users to do), and store new shift value | * since this is more convenient for users to do), and store new shift value | ||||
| */ | */ | ||||
| static void gpencil_mouse_update_shift(tGPDinterpolate *tgpi, wmOperator *op, const wmEvent *event) | static void gpencil_mouse_update_shift(tGPDinterpolate *tgpi, wmOperator *op, const wmEvent *event) | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
| /* ----------------------- */ | /* ----------------------- */ | ||||
| /* Exit and free memory */ | /* Exit and free memory */ | ||||
| static void gpencil_interpolate_exit(bContext *C, wmOperator *op) | static void gpencil_interpolate_exit(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| tGPDinterpolate *tgpi = op->customdata; | tGPDinterpolate *tgpi = op->customdata; | ||||
| tGPDinterpolate_layer *tgpil; | tGPDinterpolate_layer *tgpil; | ||||
| bGPdata *gpd = tgpi->gpd; | |||||
| /* don't assume that operator data exists at all */ | /* don't assume that operator data exists at all */ | ||||
| if (tgpi) { | if (tgpi) { | ||||
| /* remove drawing handler */ | /* remove drawing handler */ | ||||
| if (tgpi->draw_handle_screen) { | if (tgpi->draw_handle_screen) { | ||||
| ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_screen); | ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_screen); | ||||
| } | } | ||||
| if (tgpi->draw_handle_3d) { | if (tgpi->draw_handle_3d) { | ||||
| ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d); | ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d); | ||||
| } | } | ||||
| /* clear status message area */ | /* clear status message area */ | ||||
| ED_area_headerprint(tgpi->sa, NULL); | ED_area_headerprint(tgpi->sa, NULL); | ||||
| /* finally, free memory used by temp data */ | /* finally, free memory used by temp data */ | ||||
| for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) { | for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) { | ||||
| BKE_gpencil_free_strokes(tgpil->interFrame); | BKE_gpencil_free_strokes(tgpil->interFrame); | ||||
| MEM_freeN(tgpil->interFrame); | MEM_freeN(tgpil->interFrame); | ||||
| } | } | ||||
| BLI_freelistN(&tgpi->ilayers); | BLI_freelistN(&tgpi->ilayers); | ||||
| MEM_freeN(tgpi); | MEM_freeN(tgpi); | ||||
| } | } | ||||
| BKE_gpencil_batch_cache_dirty(gpd); | |||||
| WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); | WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); | ||||
| /* clear pointer */ | /* clear pointer */ | ||||
| op->customdata = NULL; | op->customdata = NULL; | ||||
| } | } | ||||
| /* Init new temporary interpolation data */ | /* Init new temporary interpolation data */ | ||||
| static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinterpolate *tgpi) | static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinterpolate *tgpi) | ||||
| ▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | ||||
| tgpi->draw_handle_screen = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_screen, tgpi, REGION_DRAW_POST_PIXEL); | tgpi->draw_handle_screen = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_screen, tgpi, REGION_DRAW_POST_PIXEL); | ||||
| tgpi->draw_handle_3d = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_3d, tgpi, REGION_DRAW_POST_VIEW); | tgpi->draw_handle_3d = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_3d, tgpi, REGION_DRAW_POST_VIEW); | ||||
| /* set cursor to indicate modal */ | /* set cursor to indicate modal */ | ||||
| WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR); | WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR); | ||||
| /* update shift indicator in header */ | /* update shift indicator in header */ | ||||
| gpencil_interpolate_status_indicators(tgpi); | gpencil_interpolate_status_indicators(tgpi); | ||||
| BKE_gpencil_batch_cache_dirty(gpd); | |||||
| WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); | WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); | ||||
| /* add a modal handler for this operator */ | /* add a modal handler for this operator */ | ||||
| WM_event_add_modal_handler(C, op); | WM_event_add_modal_handler(C, op); | ||||
| return OPERATOR_RUNNING_MODAL; | return OPERATOR_RUNNING_MODAL; | ||||
| } | } | ||||
| Show All 25 Lines | case RETKEY: | ||||
| for (gps_src = tgpil->interFrame->strokes.first; gps_src; gps_src = gps_src->next) { | for (gps_src = tgpil->interFrame->strokes.first; gps_src; gps_src = gps_src->next) { | ||||
| if (gps_src->totpoints == 0) { | if (gps_src->totpoints == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* make copy of source stroke, then adjust pointer to points too */ | /* make copy of source stroke, then adjust pointer to points too */ | ||||
| gps_dst = MEM_dupallocN(gps_src); | gps_dst = MEM_dupallocN(gps_src); | ||||
| gps_dst->points = MEM_dupallocN(gps_src->points); | gps_dst->points = MEM_dupallocN(gps_src->points); | ||||
| BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst); | |||||
| gps_dst->triangles = MEM_dupallocN(gps_src->triangles); | gps_dst->triangles = MEM_dupallocN(gps_src->triangles); | ||||
| gps_dst->flag |= GP_STROKE_RECALC_CACHES; | gps_dst->flag |= GP_STROKE_RECALC_CACHES; | ||||
| BLI_addtail(&gpf_dst->strokes, gps_dst); | BLI_addtail(&gpf_dst->strokes, gps_dst); | ||||
| } | } | ||||
| } | } | ||||
| /* clean up temp data */ | /* clean up temp data */ | ||||
| gpencil_interpolate_exit(C, op); | gpencil_interpolate_exit(C, op); | ||||
| ▲ Show 20 Lines • Show All 404 Lines • ▼ Show 20 Lines | for (cframe = prevFrame->framenum + 1; cframe < nextFrame->framenum; cframe++) { | ||||
| if (interFrame == NULL) { | if (interFrame == NULL) { | ||||
| interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW); | interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW); | ||||
| interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN; | interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN; | ||||
| } | } | ||||
| /* create new stroke */ | /* create new stroke */ | ||||
| new_stroke = MEM_dupallocN(gps_from); | new_stroke = MEM_dupallocN(gps_from); | ||||
| new_stroke->points = MEM_dupallocN(gps_from->points); | new_stroke->points = MEM_dupallocN(gps_from->points); | ||||
| BKE_gpencil_stroke_weights_duplicate(gps_from, new_stroke); | |||||
| new_stroke->triangles = MEM_dupallocN(gps_from->triangles); | new_stroke->triangles = MEM_dupallocN(gps_from->triangles); | ||||
| new_stroke->tot_triangles = 0; | new_stroke->tot_triangles = 0; | ||||
| new_stroke->flag |= GP_STROKE_RECALC_CACHES; | new_stroke->flag |= GP_STROKE_RECALC_CACHES; | ||||
| /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */ | /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */ | ||||
| if (gps_from->totpoints > gps_to->totpoints) { | if (gps_from->totpoints > gps_to->totpoints) { | ||||
| /* free weights of removed points */ | |||||
| for (int i = gps_to->totpoints; i < gps_from->totpoints; ++i) { | |||||
| bGPDspoint *pt = &gps_from->points[i]; | |||||
| BKE_gpencil_free_point_weights(pt); | |||||
| } | |||||
| new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints); | new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints); | ||||
| new_stroke->totpoints = gps_to->totpoints; | new_stroke->totpoints = gps_to->totpoints; | ||||
| new_stroke->tot_triangles = 0; | new_stroke->tot_triangles = 0; | ||||
| new_stroke->flag |= GP_STROKE_RECALC_CACHES; | new_stroke->flag |= GP_STROKE_RECALC_CACHES; | ||||
| } | } | ||||
| /* update points position */ | /* update points position */ | ||||
| gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor); | gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor); | ||||
| /* add to strokes */ | /* add to strokes */ | ||||
| BLI_addtail(&interFrame->strokes, new_stroke); | BLI_addtail(&interFrame->strokes, new_stroke); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* notifiers */ | /* notifiers */ | ||||
| BKE_gpencil_batch_cache_dirty(gpd); | |||||
| 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; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) | void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| Show All 25 Lines | if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op)) | static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op)) | ||||
| { | { | ||||
| bGPdata *gpd = ED_gpencil_data_get_active(C); | |||||
| /* Go through each layer, deleting the breakdowns around the current frame, | /* Go through each layer, deleting the breakdowns around the current frame, | ||||
| * but only if there is a keyframe nearby to stop at | * but only if there is a keyframe nearby to stop at | ||||
| */ | */ | ||||
| CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) | CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) | ||||
| { | { | ||||
| bGPDframe *start_key = NULL; | bGPDframe *start_key = NULL; | ||||
| bGPDframe *end_key = NULL; | bGPDframe *end_key = NULL; | ||||
| bGPDframe *gpf, *gpfn; | bGPDframe *gpf, *gpfn; | ||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | if ((start_key && end_key) && | ||||
| /* Now free the last one... */ | /* Now free the last one... */ | ||||
| BKE_gpencil_free_strokes(end_key); | BKE_gpencil_free_strokes(end_key); | ||||
| BLI_freelinkN(&gpl->frames, end_key); | BLI_freelinkN(&gpl->frames, end_key); | ||||
| } | } | ||||
| } | } | ||||
| CTX_DATA_END; | CTX_DATA_END; | ||||
| /* notifiers */ | /* notifiers */ | ||||
| BKE_gpencil_batch_cache_dirty(gpd); | |||||
| 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; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void GPENCIL_OT_interpolate_reverse(wmOperatorType *ot) | void GPENCIL_OT_interpolate_reverse(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| Show All 13 Lines | |||||