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:
authorTon Roosendaal <ton@blender.org>2009-04-20 14:20:18 +0400
committerTon Roosendaal <ton@blender.org>2009-04-20 14:20:18 +0400
commitf2f95caf30977fcca97d168e190f1bdb3176dab4 (patch)
tree4d5a116084094091d92c1f055b458d23bab006b4 /source/blender/blenkernel/intern/gpencil.c
parent74b12d1d6df9d3ff5b9f258c81eda82fa37901cf (diff)
Forgot to add the new gpencil files! :)
Diffstat (limited to 'source/blender/blenkernel/intern/gpencil.c')
-rw-r--r--source/blender/blenkernel/intern/gpencil.c518
1 files changed, 518 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
new file mode 100644
index 00000000000..99ec7ce1cc8
--- /dev/null
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -0,0 +1,518 @@
+/**
+ * $Id: gpencil.c 19758 2009-04-16 13:10:08Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_listBase.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_vec_types.h"
+
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_utildefines.h"
+
+
+/* ************************************************** */
+/* GENERAL STUFF */
+
+/* --------- Memory Management ------------ */
+
+/* Free strokes belonging to a gp-frame */
+void free_gpencil_strokes (bGPDframe *gpf)
+{
+ bGPDstroke *gps, *gpsn;
+
+ /* error checking */
+ if (gpf == NULL) return;
+
+ /* 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);
+ BLI_freelinkN(&gpf->strokes, gps);
+ }
+}
+
+/* Free all of a gp-layer's frames */
+void free_gpencil_frames (bGPDlayer *gpl)
+{
+ bGPDframe *gpf, *gpfn;
+
+ /* error checking */
+ if (gpl == NULL) return;
+
+ /* free frames */
+ for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
+ gpfn= gpf->next;
+
+ /* free strokes and their associated memory */
+ free_gpencil_strokes(gpf);
+ BLI_freelinkN(&gpl->frames, gpf);
+ }
+}
+
+/* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
+void free_gpencil_layers (ListBase *list)
+{
+ bGPDlayer *gpl, *gpln;
+
+ /* error checking */
+ if (list == NULL) return;
+
+ /* delete layers*/
+ for (gpl= list->first; gpl; gpl= gpln) {
+ gpln= gpl->next;
+
+ /* free layers and their data */
+ free_gpencil_frames(gpl);
+ BLI_freelinkN(list, gpl);
+ }
+}
+
+/* Free all of GPencil datablock's related data, but not the block itself */
+void free_gpencil_data (bGPdata *gpd)
+{
+ /* free layers */
+ free_gpencil_layers(&gpd->layers);
+}
+
+/* -------- Container Creation ---------- */
+
+/* add a new gp-frame to the given layer */
+bGPDframe *gpencil_frame_addnew (bGPDlayer *gpl, int cframe)
+{
+ bGPDframe *gpf, *gf;
+ short state=0;
+
+ /* error checking */
+ if ((gpl == NULL) || (cframe <= 0))
+ return NULL;
+
+ /* allocate memory for this frame */
+ gpf= MEM_callocN(sizeof(bGPDframe), "bGPDframe");
+ gpf->framenum= cframe;
+
+ /* find appropriate place to add frame */
+ if (gpl->frames.first) {
+ for (gf= gpl->frames.first; gf; gf= gf->next) {
+ /* check if frame matches one that is supposed to be added */
+ if (gf->framenum == cframe) {
+ state= -1;
+ break;
+ }
+
+ /* if current frame has already exceeded the frame to add, add before */
+ if (gf->framenum > cframe) {
+ BLI_insertlinkbefore(&gpl->frames, gf, gpf);
+ state= 1;
+ break;
+ }
+ }
+ }
+
+ /* check whether frame was added successfully */
+ if (state == -1) {
+ MEM_freeN(gpf);
+ printf("Error: frame (%d) existed already for this layer \n", cframe);
+ }
+ else if (state == 0) {
+ /* add to end then! */
+ BLI_addtail(&gpl->frames, gpf);
+ }
+
+ /* return frame */
+ return gpf;
+}
+
+/* add a new gp-layer and make it the active layer */
+bGPDlayer *gpencil_layer_addnew (bGPdata *gpd)
+{
+ bGPDlayer *gpl;
+
+ /* check that list is ok */
+ if (gpd == NULL)
+ return NULL;
+
+ /* allocate memory for frame and add to end of list */
+ gpl= MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
+
+ /* add to datablock */
+ BLI_addtail(&gpd->layers, gpl);
+
+ /* set basic settings */
+ gpl->color[3]= 0.9f;
+ gpl->thickness = 3;
+
+ /* auto-name */
+ sprintf(gpl->info, "GP_Layer");
+ BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info[0]), 128);
+
+ /* make this one the active one */
+ gpencil_layer_setactive(gpd, gpl);
+
+ /* return layer */
+ return gpl;
+}
+
+/* add a new gp-datablock */
+bGPdata *gpencil_data_addnew (char name[])
+{
+ bGPdata *gpd;
+
+ /* allocate memory for a new block */
+ gpd= alloc_libblock(&G.main->gpencil, ID_GD, name);
+
+ /* initial settings */
+ gpd->flag = (GP_DATA_DISPINFO|GP_DATA_EXPAND);
+
+ return gpd;
+}
+
+/* -------- Data Duplication ---------- */
+
+/* make a copy of a given gpencil frame */
+bGPDframe *gpencil_frame_duplicate (bGPDframe *src)
+{
+ bGPDstroke *gps, *gpsd;
+ bGPDframe *dst;
+
+ /* error checking */
+ if (src == NULL)
+ return NULL;
+
+ /* make a copy of the source frame */
+ dst= MEM_dupallocN(src);
+ dst->prev= dst->next= NULL;
+
+ /* copy strokes */
+ dst->strokes.first = dst->strokes.last= NULL;
+ for (gps= src->strokes.first; gps; gps= gps->next) {
+ /* make copy of source stroke, then adjust pointer to points too */
+ gpsd= MEM_dupallocN(gps);
+ gpsd->points= MEM_dupallocN(gps->points);
+
+ BLI_addtail(&dst->strokes, gpsd);
+ }
+
+ /* return new frame */
+ return dst;
+}
+
+/* make a copy of a given gpencil layer */
+bGPDlayer *gpencil_layer_duplicate (bGPDlayer *src)
+{
+ bGPDframe *gpf, *gpfd;
+ bGPDlayer *dst;
+
+ /* error checking */
+ if (src == NULL)
+ return NULL;
+
+ /* make a copy of source layer */
+ dst= MEM_dupallocN(src);
+ dst->prev= dst->next= NULL;
+
+ /* copy frames */
+ dst->frames.first= dst->frames.last= NULL;
+ for (gpf= src->frames.first; gpf; gpf= gpf->next) {
+ /* make a copy of source frame */
+ gpfd= gpencil_frame_duplicate(gpf);
+ BLI_addtail(&dst->frames, gpfd);
+
+ /* if source frame was the current layer's 'active' frame, reassign that too */
+ if (gpf == dst->actframe)
+ dst->actframe= gpfd;
+ }
+
+ /* return new layer */
+ return dst;
+}
+
+/* make a copy of a given gpencil datablock */
+bGPdata *gpencil_data_duplicate (bGPdata *src)
+{
+ bGPDlayer *gpl, *gpld;
+ bGPdata *dst;
+
+ /* error checking */
+ if (src == NULL)
+ return NULL;
+
+ /* make a copy of the base-data */
+ dst= MEM_dupallocN(src);
+
+ /* copy layers */
+ dst->layers.first= dst->layers.last= NULL;
+ for (gpl= src->layers.first; gpl; gpl= gpl->next) {
+ /* make a copy of source layer and its data */
+ gpld= gpencil_layer_duplicate(gpl);
+ BLI_addtail(&dst->layers, gpld);
+ }
+
+ /* return new */
+ return dst;
+}
+
+/* -------- GP-Frame API ---------- */
+
+/* delete the last stroke of the given frame */
+void gpencil_frame_delete_laststroke (bGPDlayer *gpl, bGPDframe *gpf)
+{
+ bGPDstroke *gps= (gpf) ? gpf->strokes.last : NULL;
+ int cfra = 1; // XXX FIXME!!!
+
+ /* error checking */
+ if (ELEM(NULL, gpf, gps))
+ return;
+
+ /* free the stroke and its data */
+ MEM_freeN(gps->points);
+ BLI_freelinkN(&gpf->strokes, gps);
+
+ /* if frame has no strokes after this, delete it */
+ if (gpf->strokes.first == NULL) {
+ gpencil_layer_delframe(gpl, gpf);
+ gpencil_layer_getframe(gpl, cfra, 0);
+ }
+}
+
+/* -------- GP-Layer API ---------- */
+
+/* get the appropriate gp-frame from a given layer
+ * - 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, short addnew)
+{
+ bGPDframe *gpf = NULL;
+ short found = 0;
+
+ /* error checking */
+ if (gpl == NULL) return NULL;
+ if (cframe <= 0) cframe = 1;
+
+ /* check if there is already an active frame */
+ if (gpl->actframe) {
+ gpf= gpl->actframe;
+
+ /* do not allow any changes to layer's active frame if layer is locked */
+ if (gpl->flag & GP_LAYER_LOCKED)
+ return gpf;
+ /* do not allow any changes to actframe if frame has painting tag attached to it */
+ if (gpf->flag & GP_FRAME_PAINT)
+ return gpf;
+
+ /* try to find matching frame */
+ if (gpf->framenum < cframe) {
+ for (; gpf; gpf= gpf->next) {
+ if (gpf->framenum == cframe) {
+ found= 1;
+ break;
+ }
+ else if ((gpf->next) && (gpf->next->framenum > cframe)) {
+ found= 1;
+ break;
+ }
+ }
+
+ /* set the appropriate frame */
+ if (addnew) {
+ if ((found) && (gpf->framenum == cframe))
+ gpl->actframe= gpf;
+ else
+ gpl->actframe= gpencil_frame_addnew(gpl, cframe);
+ }
+ else if (found)
+ gpl->actframe= gpf;
+ else
+ gpl->actframe= gpl->frames.last;
+ }
+ else {
+ for (; gpf; gpf= gpf->prev) {
+ if (gpf->framenum <= cframe) {
+ found= 1;
+ break;
+ }
+ }
+
+ /* set the appropriate frame */
+ if (addnew) {
+ if ((found) && (gpf->framenum == cframe))
+ gpl->actframe= gpf;
+ else
+ gpl->actframe= gpencil_frame_addnew(gpl, cframe);
+ }
+ else if (found)
+ gpl->actframe= gpf;
+ else
+ gpl->actframe= gpl->frames.first;
+ }
+ }
+ else if (gpl->frames.first) {
+ /* check which of the ends to start checking from */
+ const int first= ((bGPDframe *)(gpl->frames.first))->framenum;
+ const int last= ((bGPDframe *)(gpl->frames.last))->framenum;
+
+ if (abs(cframe-first) > abs(cframe-last)) {
+ /* find gp-frame which is less than or equal to cframe */
+ for (gpf= gpl->frames.last; gpf; gpf= gpf->prev) {
+ if (gpf->framenum <= cframe) {
+ found= 1;
+ break;
+ }
+ }
+ }
+ else {
+ /* find gp-frame which is less than or equal to cframe */
+ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+ if (gpf->framenum <= cframe) {
+ found= 1;
+ break;
+ }
+ }
+ }
+
+ /* set the appropriate frame */
+ if (addnew) {
+ if ((found) && (gpf->framenum == cframe))
+ gpl->actframe= gpf;
+ else
+ gpl->actframe= gpencil_frame_addnew(gpl, cframe);
+ }
+ else if (found)
+ gpl->actframe= gpf;
+ else {
+ /* unresolved errogenous situation! */
+ printf("Error: cannot find appropriate gp-frame \n");
+ /* gpl->actframe should still be NULL */
+ }
+ }
+ else {
+ /* currently no frames (add if allowed to) */
+ if (addnew)
+ gpl->actframe= gpencil_frame_addnew(gpl, cframe);
+ else {
+ /* don't do anything... this may be when no frames yet! */
+ /* gpl->actframe should still be NULL */
+ }
+ }
+
+ /* return */
+ return gpl->actframe;
+}
+
+/* delete the given frame from a layer */
+void gpencil_layer_delframe (bGPDlayer *gpl, bGPDframe *gpf)
+{
+ /* error checking */
+ if (ELEM(NULL, gpl, gpf))
+ return;
+
+ /* free the frame and its data */
+ free_gpencil_strokes(gpf);
+ BLI_freelinkN(&gpl->frames, gpf);
+ gpl->actframe = NULL;
+}
+
+/* get the active gp-layer for editing */
+bGPDlayer *gpencil_layer_getactive (bGPdata *gpd)
+{
+ bGPDlayer *gpl;
+
+ /* error checking */
+ if (ELEM(NULL, gpd, gpd->layers.first))
+ return NULL;
+
+ /* loop over layers until found (assume only one active) */
+ for (gpl=gpd->layers.first; gpl; gpl=gpl->next) {
+ if (gpl->flag & GP_LAYER_ACTIVE)
+ return gpl;
+ }
+
+ /* no active layer found */
+ return NULL;
+}
+
+/* set the active gp-layer */
+void gpencil_layer_setactive (bGPdata *gpd, bGPDlayer *active)
+{
+ bGPDlayer *gpl;
+
+ /* error checking */
+ if (ELEM3(NULL, gpd, gpd->layers.first, active))
+ return;
+
+ /* loop over layers deactivating all */
+ for (gpl=gpd->layers.first; gpl; gpl=gpl->next)
+ gpl->flag &= ~GP_LAYER_ACTIVE;
+
+ /* set as active one */
+ active->flag |= GP_LAYER_ACTIVE;
+}
+
+/* delete the active gp-layer */
+void gpencil_layer_delactive (bGPdata *gpd)
+{
+ bGPDlayer *gpl= gpencil_layer_getactive(gpd);
+
+ /* error checking */
+ if (ELEM(NULL, gpd, gpl))
+ return;
+
+ /* free layer */
+ free_gpencil_frames(gpl);
+ BLI_freelinkN(&gpd->layers, gpl);
+}
+
+/* ************************************************** */