Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/gpencil.c')
-rw-r--r--source/blender/blenkernel/intern/gpencil.c834
1 files changed, 739 insertions, 95 deletions
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 8621da0d42e..e4bac0a947a 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2008, Blender Foundation
* This is a new part of Blender
*
- * Contributor(s): Joshua Leung
+ * Contributor(s): Joshua Leung, Antonio Vazquez
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -44,10 +44,12 @@
#include "DNA_gpencil_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_scene_types.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
+#include "BKE_colortools.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -57,76 +59,155 @@
/* --------- Memory Management ------------ */
+/* free stroke, doesn't unlink from any listbase */
+void BKE_gpencil_free_stroke(bGPDstroke *gps)
+{
+ if (gps == NULL) {
+ return;
+ }
+
+ /* free stroke memory arrays, then stroke itself */
+ if (gps->points)
+ MEM_freeN(gps->points);
+ if (gps->triangles)
+ MEM_freeN(gps->triangles);
+
+ MEM_freeN(gps);
+}
+
/* Free strokes belonging to a gp-frame */
-bool free_gpencil_strokes(bGPDframe *gpf)
+bool BKE_gpencil_free_strokes(bGPDframe *gpf)
{
- bGPDstroke *gps, *gpsn;
+ bGPDstroke *gps_next;
bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false);
/* free strokes */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
- /* free stroke memory arrays, then stroke itself */
- if (gps->points) MEM_freeN(gps->points);
- if (gps->triangles) MEM_freeN(gps->triangles);
- BLI_freelinkN(&gpf->strokes, gps);
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps_next) {
+ gps_next = gps->next;
+ BKE_gpencil_free_stroke(gps);
}
+ BLI_listbase_clear(&gpf->strokes);
return changed;
}
/* Free all of a gp-layer's frames */
-void free_gpencil_frames(bGPDlayer *gpl)
+void BKE_gpencil_free_frames(bGPDlayer *gpl)
{
- bGPDframe *gpf, *gpfn;
+ bGPDframe *gpf_next;
/* error checking */
if (gpl == NULL) return;
/* free frames */
- for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
- gpfn = gpf->next;
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf_next) {
+ gpf_next = gpf->next;
/* free strokes and their associated memory */
- free_gpencil_strokes(gpf);
+ BKE_gpencil_free_strokes(gpf);
BLI_freelinkN(&gpl->frames, gpf);
}
gpl->actframe = NULL;
}
+/* Free all of a gp-colors */
+static void free_gpencil_colors(bGPDpalette *palette)
+{
+ /* error checking */
+ if (palette == NULL) {
+ return;
+ }
+
+ /* free colors */
+ BLI_freelistN(&palette->colors);
+}
+
+/* Free all of the gp-palettes and colors */
+void BKE_gpencil_free_palettes(ListBase *list)
+{
+ bGPDpalette *palette_next;
+
+ /* error checking */
+ if (list == NULL) {
+ return;
+ }
+
+ /* delete palettes */
+ for (bGPDpalette *palette = list->first; palette; palette = palette_next) {
+ palette_next = palette->next;
+ /* free palette colors */
+ free_gpencil_colors(palette);
+
+ MEM_freeN(palette);
+ }
+ BLI_listbase_clear(list);
+}
+
+/* Free all of the gp-brushes for a viewport (list should be &gpd->brushes or so) */
+void BKE_gpencil_free_brushes(ListBase *list)
+{
+ bGPDbrush *brush_next;
+
+ /* error checking */
+ if (list == NULL) {
+ return;
+ }
+
+ /* delete brushes */
+ for (bGPDbrush *brush = list->first; brush; brush = brush_next) {
+ brush_next = brush->next;
+ /* free curves */
+ if (brush->cur_sensitivity) {
+ curvemapping_free(brush->cur_sensitivity);
+ }
+ if (brush->cur_strength) {
+ curvemapping_free(brush->cur_strength);
+ }
+ if (brush->cur_jitter) {
+ curvemapping_free(brush->cur_jitter);
+ }
+
+ MEM_freeN(brush);
+ }
+ BLI_listbase_clear(list);
+}
+
/* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
-void free_gpencil_layers(ListBase *list)
+void BKE_gpencil_free_layers(ListBase *list)
{
- bGPDlayer *gpl, *gpln;
+ bGPDlayer *gpl_next;
/* error checking */
if (list == NULL) return;
/* delete layers */
- for (gpl = list->first; gpl; gpl = gpln) {
- gpln = gpl->next;
+ for (bGPDlayer *gpl = list->first; gpl; gpl = gpl_next) {
+ gpl_next = gpl->next;
/* free layers and their data */
- free_gpencil_frames(gpl);
+ BKE_gpencil_free_frames(gpl);
BLI_freelinkN(list, gpl);
}
}
-/* Free all of GPencil datablock's related data, but not the block itself */
/** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
-void BKE_gpencil_free(bGPdata *gpd)
+void BKE_gpencil_free(bGPdata *gpd, bool free_palettes)
{
BKE_animdata_free(&gpd->id, false);
/* free layers */
- free_gpencil_layers(&gpd->layers);
+ BKE_gpencil_free_layers(&gpd->layers);
+
+ /* free palettes */
+ if (free_palettes) {
+ BKE_gpencil_free_palettes(&gpd->palettes);
+ }
}
/* -------- Container Creation ---------- */
/* add a new gp-frame to the given layer */
-bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
+bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
{
bGPDframe *gpf = NULL, *gf = NULL;
short state = 0;
@@ -178,9 +259,9 @@ bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
}
/* add a copy of the active gp-frame to the given layer */
-bGPDframe *gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
+bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
{
- bGPDframe *new_frame, *gpf;
+ bGPDframe *new_frame;
bool found = false;
/* Error checking/handling */
@@ -190,14 +271,14 @@ bGPDframe *gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
}
else if (gpl->actframe == NULL) {
/* no active frame, so just create a new one from scratch */
- return gpencil_frame_addnew(gpl, cframe);
+ return BKE_gpencil_frame_addnew(gpl, cframe);
}
/* Create a copy of the frame */
- new_frame = gpencil_frame_duplicate(gpl->actframe);
+ new_frame = BKE_gpencil_frame_duplicate(gpl->actframe);
/* Find frame to insert it before */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
if (gpf->framenum > cframe) {
/* Add it here */
BLI_insertlinkbefore(&gpl->frames, gpf, new_frame);
@@ -209,7 +290,7 @@ bGPDframe *gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
/* This only happens when we're editing with framelock on...
* - Delete the new frame and don't do anything else here...
*/
- free_gpencil_strokes(new_frame);
+ BKE_gpencil_free_strokes(new_frame);
MEM_freeN(new_frame);
new_frame = NULL;
@@ -233,7 +314,7 @@ bGPDframe *gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
}
/* add a new gp-layer and make it the active layer */
-bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
+bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
{
bGPDlayer *gpl;
@@ -249,8 +330,11 @@ bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
/* set basic settings */
copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
- gpl->thickness = 3;
-
+ /* Since GPv2 thickness must be 0 */
+ gpl->thickness = 0;
+
+ gpl->opacity = 1.0f;
+
/* onion-skinning settings */
if (gpd->flag & GP_DATA_SHOW_ONIONSKINS)
gpl->flag |= GP_LAYER_ONIONSKIN;
@@ -263,23 +347,280 @@ bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
/* high quality fill by default */
gpl->flag |= GP_LAYER_HQ_FILL;
- /* default smooth iterations */
- gpl->draw_smoothlvl = 1;
-
/* auto-name */
BLI_strncpy(gpl->info, name, sizeof(gpl->info));
BLI_uniquename(&gpd->layers, gpl, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
/* make this one the active one */
if (setactive)
- gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_setactive(gpd, gpl);
/* return layer */
return gpl;
}
+/* add a new gp-palette and make it the active */
+bGPDpalette *BKE_gpencil_palette_addnew(bGPdata *gpd, const char *name, bool setactive)
+{
+ bGPDpalette *palette;
+
+ /* check that list is ok */
+ if (gpd == NULL) {
+ return NULL;
+ }
+
+ /* allocate memory and add to end of list */
+ palette = MEM_callocN(sizeof(bGPDpalette), "bGPDpalette");
+
+ /* add to datablock */
+ BLI_addtail(&gpd->palettes, palette);
+
+ /* set basic settings */
+ /* auto-name */
+ BLI_strncpy(palette->info, name, sizeof(palette->info));
+ BLI_uniquename(&gpd->palettes, palette, DATA_("GP_Palette"), '.', offsetof(bGPDpalette, info),
+ sizeof(palette->info));
+
+ /* make this one the active one */
+ if (setactive) {
+ BKE_gpencil_palette_setactive(gpd, palette);
+ }
+
+ /* return palette */
+ return palette;
+}
+
+/* create a set of default drawing brushes with predefined presets */
+void BKE_gpencil_brush_init_presets(ToolSettings *ts)
+{
+ bGPDbrush *brush;
+ /* Basic brush */
+ brush = BKE_gpencil_brush_addnew(ts, "Basic", true);
+ brush->thickness = 3.0f;
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
+ brush->draw_sensitivity = 1.0f;
+ brush->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
+ brush->draw_strength = 1.0f;
+ brush->flag |= ~GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->draw_random_press = 0.0f;
+
+ brush->draw_jitter = 0.0f;
+ brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->draw_angle = 0.0f;
+ brush->draw_angle_factor = 0.0f;
+
+ brush->draw_smoothfac = 0.0f;
+ brush->draw_smoothlvl = 1;
+ brush->sublevel = 0;
+ brush->draw_random_sub = 0.0f;
+
+ /* Pencil brush */
+ brush = BKE_gpencil_brush_addnew(ts, "Pencil", false);
+ brush->thickness = 7.0f;
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
+ brush->draw_sensitivity = 1.0f;
+ brush->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
+ brush->draw_strength = 0.7f;
+ brush->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->draw_random_press = 0.0f;
+
+ brush->draw_jitter = 0.0f;
+ brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->draw_angle = 0.0f;
+ brush->draw_angle_factor = 0.0f;
+
+ brush->draw_smoothfac = 1.0f;
+ brush->draw_smoothlvl = 2;
+ brush->sublevel = 2;
+ brush->draw_random_sub = 0.0f;
+
+ /* Ink brush */
+ brush = BKE_gpencil_brush_addnew(ts, "Ink", false);
+ brush->thickness = 7.0f;
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
+ brush->draw_sensitivity = 1.6f;
+ brush->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
+ brush->draw_strength = 1.0f;
+ brush->flag &= ~GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->draw_random_press = 0.0f;
+
+ brush->draw_jitter = 0.0f;
+ brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->draw_angle = 0.0f;
+ brush->draw_angle_factor = 0.0f;
+
+ brush->draw_smoothfac = 1.1f;
+ brush->draw_smoothlvl = 2;
+ brush->sublevel = 2;
+ brush->draw_random_sub = 0.0f;
+
+ /* Ink Noise brush */
+ brush = BKE_gpencil_brush_addnew(ts, "Ink noise", false);
+ brush->thickness = 6.0f;
+ brush->flag |= GP_BRUSH_USE_RANDOM_PRESSURE;
+ brush->draw_sensitivity = 1.611f;
+ brush->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
+ brush->draw_strength = 1.0f;
+ brush->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->draw_random_press = 1.0f;
+
+ brush->draw_jitter = 0.0f;
+ brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->draw_angle = 0.0f;
+ brush->draw_angle_factor = 0.0f;
+
+ brush->draw_smoothfac = 1.1f;
+ brush->draw_smoothlvl = 2;
+ brush->sublevel = 2;
+ brush->draw_random_sub = 0.0f;
+
+ /* Marker brush */
+ brush = BKE_gpencil_brush_addnew(ts, "Marker", false);
+ brush->thickness = 10.0f;
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
+ brush->draw_sensitivity = 2.0f;
+ brush->flag &= ~GP_BRUSH_USE_PRESSURE;
+
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
+ brush->draw_strength = 1.0f;
+ brush->flag &= ~GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->draw_random_press = 0.0f;
+
+ brush->draw_jitter = 0.0f;
+ brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->draw_angle = M_PI_4; /* 45 degrees */
+ brush->draw_angle_factor = 1.0f;
+
+ brush->draw_smoothfac = 1.0f;
+ brush->draw_smoothlvl = 2;
+ brush->sublevel = 2;
+ brush->draw_random_sub = 0.0f;
+
+ /* Crayon brush */
+ brush = BKE_gpencil_brush_addnew(ts, "Crayon", false);
+ brush->thickness = 10.0f;
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_PRESSURE;
+ brush->draw_sensitivity = 3.0f;
+ brush->flag &= ~GP_BRUSH_USE_PRESSURE;
+
+ brush->flag &= ~GP_BRUSH_USE_RANDOM_STRENGTH;
+ brush->draw_strength = 0.140f;
+ brush->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->draw_random_press = 0.0f;
+
+ brush->draw_jitter = 0.0f;
+ brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->draw_angle = 0.0f;
+ brush->draw_angle_factor = 0.0f;
+
+ brush->draw_smoothfac = 0.0f;
+ brush->draw_smoothlvl = 1;
+ brush->sublevel = 2;
+ brush->draw_random_sub = 0.5f;
+
+}
+
+/* add a new gp-brush and make it the active */
+bGPDbrush *BKE_gpencil_brush_addnew(ToolSettings *ts, const char *name, bool setactive)
+{
+ bGPDbrush *brush;
+
+ /* check that list is ok */
+ if (ts == NULL) {
+ return NULL;
+ }
+
+ /* allocate memory and add to end of list */
+ brush = MEM_callocN(sizeof(bGPDbrush), "bGPDbrush");
+
+ /* add to datablock */
+ BLI_addtail(&ts->gp_brushes, brush);
+
+ /* set basic settings */
+ brush->thickness = 3;
+ brush->draw_smoothlvl = 1;
+ brush->flag |= GP_BRUSH_USE_PRESSURE;
+ brush->draw_sensitivity = 1.0f;
+ brush->draw_strength = 1.0f;
+ brush->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->draw_jitter = 0.0f;
+ brush->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ /* curves */
+ brush->cur_sensitivity = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ brush->cur_strength = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ brush->cur_jitter = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+
+ /* auto-name */
+ BLI_strncpy(brush->info, name, sizeof(brush->info));
+ BLI_uniquename(&ts->gp_brushes, brush, DATA_("GP_Brush"), '.', offsetof(bGPDbrush, info), sizeof(brush->info));
+
+ /* make this one the active one */
+ if (setactive) {
+ BKE_gpencil_brush_setactive(ts, brush);
+ }
+
+ /* return brush */
+ return brush;
+}
+
+/* add a new gp-palettecolor and make it the active */
+bGPDpalettecolor *BKE_gpencil_palettecolor_addnew(bGPDpalette *palette, const char *name, bool setactive)
+{
+ bGPDpalettecolor *palcolor;
+
+ /* check that list is ok */
+ if (palette == NULL) {
+ return NULL;
+ }
+
+ /* allocate memory and add to end of list */
+ palcolor = MEM_callocN(sizeof(bGPDpalettecolor), "bGPDpalettecolor");
+
+ /* add to datablock */
+ BLI_addtail(&palette->colors, palcolor);
+
+ /* set basic settings */
+ palcolor->flag |= PC_COLOR_HQ_FILL;
+ copy_v4_v4(palcolor->color, U.gpencil_new_layer_col);
+ ARRAY_SET_ITEMS(palcolor->fill, 1.0f, 1.0f, 1.0f);
+
+ /* auto-name */
+ BLI_strncpy(palcolor->info, name, sizeof(palcolor->info));
+ BLI_uniquename(&palette->colors, palcolor, DATA_("Color"), '.', offsetof(bGPDpalettecolor, info),
+ sizeof(palcolor->info));
+
+ /* make this one the active one */
+ if (setactive) {
+ BKE_gpencil_palettecolor_setactive(palette, palcolor);
+ }
+
+ /* return palette color */
+ return palcolor;
+}
+
/* add a new gp-datablock */
-bGPdata *gpencil_data_addnew(const char name[])
+bGPdata *BKE_gpencil_data_addnew(const char name[])
{
bGPdata *gpd;
@@ -300,94 +641,157 @@ bGPdata *gpencil_data_addnew(const char name[])
/* -------- Data Duplication ---------- */
/* make a copy of a given gpencil frame */
-bGPDframe *gpencil_frame_duplicate(bGPDframe *src)
+bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
{
- bGPDstroke *gps, *gpsd;
- bGPDframe *dst;
+ bGPDstroke *gps_dst;
+ bGPDframe *gpf_dst;
/* error checking */
- if (src == NULL)
+ if (gpf_src == NULL) {
return NULL;
+ }
/* make a copy of the source frame */
- dst = MEM_dupallocN(src);
- dst->prev = dst->next = NULL;
+ gpf_dst = MEM_dupallocN(gpf_src);
+ gpf_dst->prev = gpf_dst->next = NULL;
/* copy strokes */
- BLI_listbase_clear(&dst->strokes);
- for (gps = src->strokes.first; gps; gps = gps->next) {
+ BLI_listbase_clear(&gpf_dst->strokes);
+ for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
/* make copy of source stroke, then adjust pointer to points too */
- gpsd = MEM_dupallocN(gps);
- gpsd->points = MEM_dupallocN(gps->points);
- gpsd->triangles = MEM_dupallocN(gps->triangles);
- gpsd->flag |= GP_STROKE_RECALC_CACHES;
- BLI_addtail(&dst->strokes, gpsd);
+ gps_dst = MEM_dupallocN(gps_src);
+ gps_dst->points = MEM_dupallocN(gps_src->points);
+ gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
+ gps_dst->flag |= GP_STROKE_RECALC_CACHES;
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
}
/* return new frame */
- return dst;
+ return gpf_dst;
+}
+
+/* make a copy of a given gpencil brush */
+bGPDbrush *BKE_gpencil_brush_duplicate(const bGPDbrush *brush_src)
+{
+ bGPDbrush *brush_dst;
+
+ /* error checking */
+ if (brush_src == NULL) {
+ return NULL;
+ }
+
+ /* make a copy of source brush */
+ brush_dst = MEM_dupallocN(brush_src);
+ brush_dst->prev = brush_dst->next = NULL;
+ /* make a copy of curves */
+ brush_dst->cur_sensitivity = curvemapping_copy(brush_src->cur_sensitivity);
+ brush_dst->cur_strength = curvemapping_copy(brush_src->cur_strength);
+ brush_dst->cur_jitter = curvemapping_copy(brush_src->cur_jitter);
+
+ /* return new brush */
+ return brush_dst;
}
+/* make a copy of a given gpencil palette */
+bGPDpalette *BKE_gpencil_palette_duplicate(const bGPDpalette *palette_src)
+{
+ bGPDpalette *palette_dst;
+ const bGPDpalettecolor *palcolor_src;
+ bGPDpalettecolor *palcolord_dst;
+
+ /* error checking */
+ if (palette_src == NULL) {
+ return NULL;
+ }
+
+ /* make a copy of source palette */
+ palette_dst = MEM_dupallocN(palette_src);
+ palette_dst->prev = palette_dst->next = NULL;
+
+ /* copy colors */
+ BLI_listbase_clear(&palette_dst->colors);
+ for (palcolor_src = palette_src->colors.first; palcolor_src; palcolor_src = palcolor_src->next) {
+ /* make a copy of source */
+ palcolord_dst = MEM_dupallocN(palcolor_src);
+ BLI_addtail(&palette_dst->colors, palcolord_dst);
+ }
+
+ /* return new palette */
+ return palette_dst;
+}
/* make a copy of a given gpencil layer */
-bGPDlayer *gpencil_layer_duplicate(bGPDlayer *src)
+bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
{
- bGPDframe *gpf, *gpfd;
- bGPDlayer *dst;
+ const bGPDframe *gpf_src;
+ bGPDframe *gpf_dst;
+ bGPDlayer *gpl_dst;
/* error checking */
- if (src == NULL)
+ if (gpl_src == NULL) {
return NULL;
+ }
/* make a copy of source layer */
- dst = MEM_dupallocN(src);
- dst->prev = dst->next = NULL;
+ gpl_dst = MEM_dupallocN(gpl_src);
+ gpl_dst->prev = gpl_dst->next = NULL;
/* copy frames */
- BLI_listbase_clear(&dst->frames);
- for (gpf = src->frames.first; gpf; gpf = gpf->next) {
+ BLI_listbase_clear(&gpl_dst->frames);
+ for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
/* make a copy of source frame */
- gpfd = gpencil_frame_duplicate(gpf);
- BLI_addtail(&dst->frames, gpfd);
+ gpf_dst = BKE_gpencil_frame_duplicate(gpf_src);
+ BLI_addtail(&gpl_dst->frames, gpf_dst);
/* if source frame was the current layer's 'active' frame, reassign that too */
- if (gpf == dst->actframe)
- dst->actframe = gpfd;
+ if (gpf_src == gpl_dst->actframe)
+ gpl_dst->actframe = gpf_dst;
}
/* return new layer */
- return dst;
+ return gpl_dst;
}
/* make a copy of a given gpencil datablock */
-bGPdata *gpencil_data_duplicate(Main *bmain, bGPdata *src, bool internal_copy)
+bGPdata *BKE_gpencil_data_duplicate(Main *bmain, bGPdata *gpd_src, bool internal_copy)
{
- bGPDlayer *gpl, *gpld;
- bGPdata *dst;
-
+ const bGPDlayer *gpl_src;
+ bGPDlayer *gpl_dst;
+ bGPdata *gpd_dst;
+
/* error checking */
- if (src == NULL)
+ if (gpd_src == NULL) {
return NULL;
+ }
/* make a copy of the base-data */
if (internal_copy) {
/* make a straight copy for undo buffers used during stroke drawing */
- dst = MEM_dupallocN(src);
+ gpd_dst = MEM_dupallocN(gpd_src);
}
else {
/* make a copy when others use this */
- dst = BKE_libblock_copy(bmain, &src->id);
+ gpd_dst = BKE_libblock_copy(bmain, &gpd_src->id);
}
/* copy layers */
- BLI_listbase_clear(&dst->layers);
- for (gpl = src->layers.first; gpl; gpl = gpl->next) {
+ BLI_listbase_clear(&gpd_dst->layers);
+ for (gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
/* make a copy of source layer and its data */
- gpld = gpencil_layer_duplicate(gpl);
- BLI_addtail(&dst->layers, gpld);
+ gpl_dst = BKE_gpencil_layer_duplicate(gpl_src);
+ BLI_addtail(&gpd_dst->layers, gpl_dst);
+ }
+ if (!internal_copy) {
+ /* copy palettes */
+ bGPDpalette *palette_src, *palette_dst;
+ BLI_listbase_clear(&gpd_dst->palettes);
+ for (palette_src = gpd_src->palettes.first; palette_src; palette_src = palette_src->next) {
+ palette_dst = BKE_gpencil_palette_duplicate(palette_src);
+ BLI_addtail(&gpd_dst->palettes, palette_dst);
+ }
}
/* return new */
- return dst;
+ return gpd_dst;
}
void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local)
@@ -398,7 +802,7 @@ void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local)
/* -------- GP-Stroke API --------- */
/* ensure selection status of stroke is in sync with its points */
-void gpencil_stroke_sync_selection(bGPDstroke *gps)
+void BKE_gpencil_stroke_sync_selection(bGPDstroke *gps)
{
bGPDspoint *pt;
int i;
@@ -423,7 +827,7 @@ void gpencil_stroke_sync_selection(bGPDstroke *gps)
/* -------- GP-Frame API ---------- */
/* delete the last stroke of the given frame */
-void gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
+void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
{
bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL;
int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */
@@ -439,8 +843,8 @@ void gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
/* if frame has no strokes after this, delete it */
if (BLI_listbase_is_empty(&gpf->strokes)) {
- gpencil_layer_delframe(gpl, gpf);
- gpencil_layer_getframe(gpl, cfra, 0);
+ BKE_gpencil_layer_delframe(gpl, gpf);
+ BKE_gpencil_layer_getframe(gpl, cfra, 0);
}
}
@@ -458,7 +862,7 @@ bool gpencil_layer_is_editable(const bGPDlayer *gpl)
/* Opacity must be sufficiently high that it is still "visible"
* Otherwise, it's not really "visible" to the user, so no point editing...
*/
- if ((gpl->color[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gpl->fill[3] > GPENCIL_ALPHA_OPACITY_THRESH)) {
+ if (gpl->opacity > GPENCIL_ALPHA_OPACITY_THRESH) {
return true;
}
}
@@ -488,7 +892,7 @@ bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe)
* - this sets the layer's actframe var (if allowed to)
* - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
*/
-bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
+bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
{
bGPDframe *gpf = NULL;
short found = 0;
@@ -527,9 +931,9 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode
if ((found) && (gpf->framenum == cframe))
gpl->actframe = gpf;
else if (addnew == GP_GETFRAME_ADD_COPY)
- gpl->actframe = gpencil_frame_addcopy(gpl, cframe);
+ gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
else
- gpl->actframe = gpencil_frame_addnew(gpl, cframe);
+ gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
}
else if (found)
gpl->actframe = gpf;
@@ -549,9 +953,9 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode
if ((found) && (gpf->framenum == cframe))
gpl->actframe = gpf;
else if (addnew == GP_GETFRAME_ADD_COPY)
- gpl->actframe = gpencil_frame_addcopy(gpl, cframe);
+ gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
else
- gpl->actframe = gpencil_frame_addnew(gpl, cframe);
+ gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
}
else if (found)
gpl->actframe = gpf;
@@ -588,7 +992,7 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode
if ((found) && (gpf->framenum == cframe))
gpl->actframe = gpf;
else
- gpl->actframe = gpencil_frame_addnew(gpl, cframe);
+ gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
}
else if (found)
gpl->actframe = gpf;
@@ -601,7 +1005,7 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode
else {
/* currently no frames (add if allowed to) */
if (addnew)
- gpl->actframe = gpencil_frame_addnew(gpl, cframe);
+ gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
else {
/* don't do anything... this may be when no frames yet! */
/* gpl->actframe should still be NULL */
@@ -613,7 +1017,7 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode
}
/* delete the given frame from a layer */
-bool gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
+bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
{
bool changed = false;
@@ -630,14 +1034,14 @@ bool gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
gpl->actframe = NULL;
/* free the frame and its data */
- changed = free_gpencil_strokes(gpf);
+ changed = BKE_gpencil_free_strokes(gpf);
BLI_freelinkN(&gpl->frames, gpf);
return changed;
}
/* get the active gp-layer for editing */
-bGPDlayer *gpencil_layer_getactive(bGPdata *gpd)
+bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd)
{
bGPDlayer *gpl;
@@ -656,7 +1060,7 @@ bGPDlayer *gpencil_layer_getactive(bGPdata *gpd)
}
/* set the active gp-layer */
-void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
+void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
{
bGPDlayer *gpl;
@@ -673,15 +1077,255 @@ void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
}
/* delete the active gp-layer */
-void gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
+void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
{
/* error checking */
if (ELEM(NULL, gpd, gpl))
return;
/* free layer */
- free_gpencil_frames(gpl);
+ BKE_gpencil_free_frames(gpl);
BLI_freelinkN(&gpd->layers, gpl);
}
/* ************************************************** */
+/* get the active gp-brush for editing */
+bGPDbrush *BKE_gpencil_brush_getactive(ToolSettings *ts)
+{
+ bGPDbrush *brush;
+
+ /* error checking */
+ if (ELEM(NULL, ts, ts->gp_brushes.first)) {
+ return NULL;
+ }
+
+ /* loop over brushes until found (assume only one active) */
+ for (brush = ts->gp_brushes.first; brush; brush = brush->next) {
+ if (brush->flag & GP_BRUSH_ACTIVE) {
+ return brush;
+ }
+ }
+
+ /* no active brush found */
+ return NULL;
+}
+
+/* set the active gp-brush */
+void BKE_gpencil_brush_setactive(ToolSettings *ts, bGPDbrush *active)
+{
+ bGPDbrush *brush;
+
+ /* error checking */
+ if (ELEM(NULL, ts, ts->gp_brushes.first, active)) {
+ return;
+ }
+
+ /* loop over brushes deactivating all */
+ for (brush = ts->gp_brushes.first; brush; brush = brush->next) {
+ brush->flag &= ~GP_BRUSH_ACTIVE;
+ }
+
+ /* set as active one */
+ active->flag |= GP_BRUSH_ACTIVE;
+}
+
+/* delete the active gp-brush */
+void BKE_gpencil_brush_delete(ToolSettings *ts, bGPDbrush *brush)
+{
+ /* error checking */
+ if (ELEM(NULL, ts, brush)) {
+ return;
+ }
+
+ /* free curves */
+ if (brush->cur_sensitivity) {
+ curvemapping_free(brush->cur_sensitivity);
+ }
+ if (brush->cur_strength) {
+ curvemapping_free(brush->cur_strength);
+ }
+ if (brush->cur_jitter) {
+ curvemapping_free(brush->cur_jitter);
+ }
+
+ /* free */
+ BLI_freelinkN(&ts->gp_brushes, brush);
+}
+
+/* ************************************************** */
+/* get the active gp-palette for editing */
+bGPDpalette *BKE_gpencil_palette_getactive(bGPdata *gpd)
+{
+ bGPDpalette *palette;
+
+ /* error checking */
+ if (ELEM(NULL, gpd, gpd->palettes.first)) {
+ return NULL;
+ }
+
+ /* loop over palettes until found (assume only one active) */
+ for (palette = gpd->palettes.first; palette; palette = palette->next) {
+ if (palette->flag & PL_PALETTE_ACTIVE)
+ return palette;
+ }
+
+ /* no active palette found */
+ return NULL;
+}
+
+/* set the active gp-palette */
+void BKE_gpencil_palette_setactive(bGPdata *gpd, bGPDpalette *active)
+{
+ bGPDpalette *palette;
+
+ /* error checking */
+ if (ELEM(NULL, gpd, gpd->palettes.first, active)) {
+ return;
+ }
+
+ /* loop over palettes deactivating all */
+ for (palette = gpd->palettes.first; palette; palette = palette->next) {
+ palette->flag &= ~PL_PALETTE_ACTIVE;
+ }
+
+ /* set as active one */
+ active->flag |= PL_PALETTE_ACTIVE;
+ /* force color recalc */
+ BKE_gpencil_palette_change_strokes(gpd);
+}
+
+/* delete the active gp-palette */
+void BKE_gpencil_palette_delete(bGPdata *gpd, bGPDpalette *palette)
+{
+ /* error checking */
+ if (ELEM(NULL, gpd, palette)) {
+ return;
+ }
+
+ /* free colors */
+ free_gpencil_colors(palette);
+ BLI_freelinkN(&gpd->palettes, palette);
+ /* force color recalc */
+ BKE_gpencil_palette_change_strokes(gpd);
+}
+
+/* Set all strokes to recalc the palette color */
+void BKE_gpencil_palette_change_strokes(bGPdata *gpd)
+{
+ bGPDlayer *gpl;
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ gps->flag |= GP_STROKE_RECALC_COLOR;
+ }
+ }
+ }
+}
+
+
+/* get the active gp-palettecolor for editing */
+bGPDpalettecolor *BKE_gpencil_palettecolor_getactive(bGPDpalette *palette)
+{
+ bGPDpalettecolor *palcolor;
+
+ /* error checking */
+ if (ELEM(NULL, palette, palette->colors.first)) {
+ return NULL;
+ }
+
+ /* loop over colors until found (assume only one active) */
+ for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
+ if (palcolor->flag & PC_COLOR_ACTIVE) {
+ return palcolor;
+ }
+ }
+
+ /* no active color found */
+ return NULL;
+}
+/* get the gp-palettecolor looking for name */
+bGPDpalettecolor *BKE_gpencil_palettecolor_getbyname(bGPDpalette *palette, char *name)
+{
+ /* error checking */
+ if (ELEM(NULL, palette, name)) {
+ return NULL;
+ }
+
+ return BLI_findstring(&palette->colors, name, offsetof(bGPDpalettecolor, info));
+}
+
+/* Change color name in all strokes */
+void BKE_gpencil_palettecolor_changename(bGPdata *gpd, char *oldname, const char *newname)
+{
+ bGPDlayer *gpl;
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (STREQ(gps->colorname, oldname)) {
+ strcpy(gps->colorname, newname);
+ }
+ }
+ }
+ }
+
+}
+
+/* Delete all strokes of the color */
+void BKE_gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name)
+{
+ bGPDlayer *gpl;
+ bGPDframe *gpf;
+ bGPDstroke *gps, *gpsn;
+
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (gps = gpf->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+
+ if (STREQ(gps->colorname, name)) {
+ if (gps->points) MEM_freeN(gps->points);
+ if (gps->triangles) MEM_freeN(gps->triangles);
+ BLI_freelinkN(&gpf->strokes, gps);
+ }
+ }
+ }
+ }
+
+}
+
+/* set the active gp-palettecolor */
+void BKE_gpencil_palettecolor_setactive(bGPDpalette *palette, bGPDpalettecolor *active)
+{
+ bGPDpalettecolor *palcolor;
+
+ /* error checking */
+ if (ELEM(NULL, palette, palette->colors.first, active)) {
+ return;
+ }
+
+ /* loop over colors deactivating all */
+ for (palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
+ palcolor->flag &= ~PC_COLOR_ACTIVE;
+ }
+
+ /* set as active one */
+ active->flag |= PC_COLOR_ACTIVE;
+}
+
+/* delete the active gp-palettecolor */
+void BKE_gpencil_palettecolor_delete(bGPDpalette *palette, bGPDpalettecolor *palcolor)
+{
+ /* error checking */
+ if (ELEM(NULL, palette, palcolor)) {
+ return;
+ }
+
+ /* free */
+ BLI_freelinkN(&palette->colors, palcolor);
+}