Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/gpencil/gpencil_utils.c
| Show First 20 Lines • Show All 3,409 Lines • ▼ Show 20 Lines | void ED_gpencil_stroke_close_by_distance(bGPDstroke *gps, const float threshold) | ||||
| const float threshold_sqr = threshold * threshold; | const float threshold_sqr = threshold * threshold; | ||||
| float dist_to_close = len_squared_v3v3(&pt_start->x, &pt_end->x); | float dist_to_close = len_squared_v3v3(&pt_start->x, &pt_end->x); | ||||
| if (dist_to_close < threshold_sqr) { | if (dist_to_close < threshold_sqr) { | ||||
| gps->flag |= GP_STROKE_CYCLIC; | gps->flag |= GP_STROKE_CYCLIC; | ||||
| BKE_gpencil_stroke_close(gps); | BKE_gpencil_stroke_close(gps); | ||||
| } | } | ||||
| } | } | ||||
| /* Merge two layers. */ | |||||
| void ED_gpencil_layer_merge(bGPdata *gpd, | |||||
| bGPDlayer *gpl_src, | |||||
| bGPDlayer *gpl_dst, | |||||
| const bool reverse) | |||||
| { | |||||
| /* Collect frames of gpl_dst in hash table to avoid O(n^2) lookups. */ | |||||
| GHash *gh_frames_dst = BLI_ghash_int_new_ex(__func__, 64); | |||||
| LISTBASE_FOREACH (bGPDframe *, gpf_dst, &gpl_dst->frames) { | |||||
| BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_dst->framenum), gpf_dst); | |||||
| } | |||||
| /* Read all frames from merge layer and add any missing in destination layer, | |||||
| * copying all previous strokes to keep the image equals. | |||||
| * Need to do it in a separated loop to avoid strokes accumulation. */ | |||||
| LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) { | |||||
| /* Try to find frame in destination layer hash table. */ | |||||
| bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum)); | |||||
| if (!gpf_dst) { | |||||
| gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf_src->framenum, GP_GETFRAME_ADD_COPY); | |||||
| /* Use same frame type. */ | |||||
| gpf_dst->key_type = gpf_src->key_type; | |||||
| BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum), gpf_dst); | |||||
| } | |||||
| /* Apply layer attributes. */ | |||||
| LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) { | |||||
| for (int p = 0; p < gps_src->totpoints; p++) { | |||||
| bGPDspoint *pt = &gps_src->points[p]; | |||||
| float factor = (((float)gps_src->thickness * pt->pressure) + (float)gpl_src->line_change) / | |||||
| ((float)gps_src->thickness * pt->pressure); | |||||
| pt->pressure *= factor; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* Read all frames from merge layer and add strokes. */ | |||||
| LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) { | |||||
| /* Try to find frame in destination layer hash table. */ | |||||
| bGPDframe *gpf_dst = BLI_ghash_lookup(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum)); | |||||
| /* Apply layer transformation. */ | |||||
| LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) { | |||||
| for (int p = 0; p < gps_src->totpoints; p++) { | |||||
| bGPDspoint *pt = &gps_src->points[p]; | |||||
| mul_v3_m4v3(&pt->x, gpl_src->layer_mat, &pt->x); | |||||
| } | |||||
| } | |||||
| /* Add to tail all strokes. */ | |||||
| if (gpf_dst) { | |||||
| if (reverse) { | |||||
| BLI_movelisttolist_reverse(&gpf_dst->strokes, &gpf_src->strokes); | |||||
| } | |||||
| else { | |||||
| BLI_movelisttolist(&gpf_dst->strokes, &gpf_src->strokes); | |||||
| } | |||||
| } | |||||
| } | |||||
| /* Add Masks to destination layer. */ | |||||
| LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl_src->mask_layers) { | |||||
| /* Don't add merged layers or missing layer names. */ | |||||
| if (!BKE_gpencil_layer_named_get(gpd, mask->name) || STREQ(mask->name, gpl_src->info) || | |||||
| STREQ(mask->name, gpl_dst->info)) { | |||||
| continue; | |||||
| } | |||||
| if (!BKE_gpencil_layer_mask_named_get(gpl_dst, mask->name)) { | |||||
| bGPDlayer_Mask *mask_new = MEM_dupallocN(mask); | |||||
| BLI_addtail(&gpl_dst->mask_layers, mask_new); | |||||
| gpl_dst->act_mask++; | |||||
| } | |||||
| } | |||||
| /* Set destination layer as active. */ | |||||
| BKE_gpencil_layer_active_set(gpd, gpl_dst); | |||||
| /* Now delete merged layer. */ | |||||
| BKE_gpencil_layer_delete(gpd, gpl_src); | |||||
| BLI_ghash_free(gh_frames_dst, NULL, NULL); | |||||
| /* Reorder masking. */ | |||||
| if (gpl_dst->mask_layers.first) { | |||||
| BKE_gpencil_layer_mask_sort(gpd, gpl_dst); | |||||
| } | |||||
| } | |||||