|
Blender
V2.59
|
00001 /* 00002 * $Id: gpencil.c 35247 2011-02-27 20:40:57Z jesterking $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2008, Blender Foundation 00021 * This is a new part of Blender 00022 * 00023 * Contributor(s): Joshua Leung 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <stdio.h> 00034 #include <string.h> 00035 #include <stdlib.h> 00036 #include <stddef.h> 00037 #include <math.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "BLI_blenlib.h" 00042 #include "BLI_utildefines.h" 00043 00044 #include "DNA_gpencil_types.h" 00045 00046 #include "BKE_global.h" 00047 #include "BKE_gpencil.h" 00048 #include "BKE_library.h" 00049 #include "BKE_main.h" 00050 00051 00052 00053 /* ************************************************** */ 00054 /* GENERAL STUFF */ 00055 00056 /* --------- Memory Management ------------ */ 00057 00058 /* Free strokes belonging to a gp-frame */ 00059 void free_gpencil_strokes (bGPDframe *gpf) 00060 { 00061 bGPDstroke *gps, *gpsn; 00062 00063 /* error checking */ 00064 if (gpf == NULL) return; 00065 00066 /* free strokes */ 00067 for (gps= gpf->strokes.first; gps; gps= gpsn) { 00068 gpsn= gps->next; 00069 00070 /* free stroke memory arrays, then stroke itself */ 00071 if (gps->points) MEM_freeN(gps->points); 00072 BLI_freelinkN(&gpf->strokes, gps); 00073 } 00074 } 00075 00076 /* Free all of a gp-layer's frames */ 00077 void free_gpencil_frames (bGPDlayer *gpl) 00078 { 00079 bGPDframe *gpf, *gpfn; 00080 00081 /* error checking */ 00082 if (gpl == NULL) return; 00083 00084 /* free frames */ 00085 for (gpf= gpl->frames.first; gpf; gpf= gpfn) { 00086 gpfn= gpf->next; 00087 00088 /* free strokes and their associated memory */ 00089 free_gpencil_strokes(gpf); 00090 BLI_freelinkN(&gpl->frames, gpf); 00091 } 00092 } 00093 00094 /* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */ 00095 void free_gpencil_layers (ListBase *list) 00096 { 00097 bGPDlayer *gpl, *gpln; 00098 00099 /* error checking */ 00100 if (list == NULL) return; 00101 00102 /* delete layers*/ 00103 for (gpl= list->first; gpl; gpl= gpln) { 00104 gpln= gpl->next; 00105 00106 /* free layers and their data */ 00107 free_gpencil_frames(gpl); 00108 BLI_freelinkN(list, gpl); 00109 } 00110 } 00111 00112 /* Free all of GPencil datablock's related data, but not the block itself */ 00113 void free_gpencil_data (bGPdata *gpd) 00114 { 00115 /* free layers */ 00116 free_gpencil_layers(&gpd->layers); 00117 } 00118 00119 /* -------- Container Creation ---------- */ 00120 00121 /* add a new gp-frame to the given layer */ 00122 bGPDframe *gpencil_frame_addnew (bGPDlayer *gpl, int cframe) 00123 { 00124 bGPDframe *gpf, *gf; 00125 short state=0; 00126 00127 /* error checking */ 00128 if ((gpl == NULL) || (cframe <= 0)) 00129 return NULL; 00130 00131 /* allocate memory for this frame */ 00132 gpf= MEM_callocN(sizeof(bGPDframe), "bGPDframe"); 00133 gpf->framenum= cframe; 00134 00135 /* find appropriate place to add frame */ 00136 if (gpl->frames.first) { 00137 for (gf= gpl->frames.first; gf; gf= gf->next) { 00138 /* check if frame matches one that is supposed to be added */ 00139 if (gf->framenum == cframe) { 00140 state= -1; 00141 break; 00142 } 00143 00144 /* if current frame has already exceeded the frame to add, add before */ 00145 if (gf->framenum > cframe) { 00146 BLI_insertlinkbefore(&gpl->frames, gf, gpf); 00147 state= 1; 00148 break; 00149 } 00150 } 00151 } 00152 00153 /* check whether frame was added successfully */ 00154 if (state == -1) { 00155 MEM_freeN(gpf); 00156 printf("Error: frame (%d) existed already for this layer \n", cframe); 00157 } 00158 else if (state == 0) { 00159 /* add to end then! */ 00160 BLI_addtail(&gpl->frames, gpf); 00161 } 00162 00163 /* return frame */ 00164 return gpf; 00165 } 00166 00167 /* add a new gp-layer and make it the active layer */ 00168 bGPDlayer *gpencil_layer_addnew (bGPdata *gpd) 00169 { 00170 bGPDlayer *gpl; 00171 00172 /* check that list is ok */ 00173 if (gpd == NULL) 00174 return NULL; 00175 00176 /* allocate memory for frame and add to end of list */ 00177 gpl= MEM_callocN(sizeof(bGPDlayer), "bGPDlayer"); 00178 00179 /* add to datablock */ 00180 BLI_addtail(&gpd->layers, gpl); 00181 00182 /* set basic settings */ 00183 gpl->color[3]= 0.9f; 00184 gpl->thickness = 3; 00185 00186 /* auto-name */ 00187 sprintf(gpl->info, "GP_Layer"); 00188 BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info[0]), sizeof(gpl->info)); 00189 00190 /* make this one the active one */ 00191 gpencil_layer_setactive(gpd, gpl); 00192 00193 /* return layer */ 00194 return gpl; 00195 } 00196 00197 /* add a new gp-datablock */ 00198 bGPdata *gpencil_data_addnew (const char name[]) 00199 { 00200 bGPdata *gpd; 00201 00202 /* allocate memory for a new block */ 00203 gpd= alloc_libblock(&G.main->gpencil, ID_GD, name); 00204 00205 /* initial settings */ 00206 gpd->flag = (GP_DATA_DISPINFO|GP_DATA_EXPAND); 00207 00208 /* for now, stick to view is also enabled by default 00209 * since this is more useful... 00210 */ 00211 gpd->flag |= GP_DATA_VIEWALIGN; 00212 00213 return gpd; 00214 } 00215 00216 /* -------- Data Duplication ---------- */ 00217 00218 /* make a copy of a given gpencil frame */ 00219 bGPDframe *gpencil_frame_duplicate (bGPDframe *src) 00220 { 00221 bGPDstroke *gps, *gpsd; 00222 bGPDframe *dst; 00223 00224 /* error checking */ 00225 if (src == NULL) 00226 return NULL; 00227 00228 /* make a copy of the source frame */ 00229 dst= MEM_dupallocN(src); 00230 dst->prev= dst->next= NULL; 00231 00232 /* copy strokes */ 00233 dst->strokes.first = dst->strokes.last= NULL; 00234 for (gps= src->strokes.first; gps; gps= gps->next) { 00235 /* make copy of source stroke, then adjust pointer to points too */ 00236 gpsd= MEM_dupallocN(gps); 00237 gpsd->points= MEM_dupallocN(gps->points); 00238 00239 BLI_addtail(&dst->strokes, gpsd); 00240 } 00241 00242 /* return new frame */ 00243 return dst; 00244 } 00245 00246 /* make a copy of a given gpencil layer */ 00247 bGPDlayer *gpencil_layer_duplicate (bGPDlayer *src) 00248 { 00249 bGPDframe *gpf, *gpfd; 00250 bGPDlayer *dst; 00251 00252 /* error checking */ 00253 if (src == NULL) 00254 return NULL; 00255 00256 /* make a copy of source layer */ 00257 dst= MEM_dupallocN(src); 00258 dst->prev= dst->next= NULL; 00259 00260 /* copy frames */ 00261 dst->frames.first= dst->frames.last= NULL; 00262 for (gpf= src->frames.first; gpf; gpf= gpf->next) { 00263 /* make a copy of source frame */ 00264 gpfd= gpencil_frame_duplicate(gpf); 00265 BLI_addtail(&dst->frames, gpfd); 00266 00267 /* if source frame was the current layer's 'active' frame, reassign that too */ 00268 if (gpf == dst->actframe) 00269 dst->actframe= gpfd; 00270 } 00271 00272 /* return new layer */ 00273 return dst; 00274 } 00275 00276 /* make a copy of a given gpencil datablock */ 00277 bGPdata *gpencil_data_duplicate (bGPdata *src) 00278 { 00279 bGPDlayer *gpl, *gpld; 00280 bGPdata *dst; 00281 00282 /* error checking */ 00283 if (src == NULL) 00284 return NULL; 00285 00286 /* make a copy of the base-data */ 00287 dst= MEM_dupallocN(src); 00288 00289 /* copy layers */ 00290 dst->layers.first= dst->layers.last= NULL; 00291 for (gpl= src->layers.first; gpl; gpl= gpl->next) { 00292 /* make a copy of source layer and its data */ 00293 gpld= gpencil_layer_duplicate(gpl); 00294 BLI_addtail(&dst->layers, gpld); 00295 } 00296 00297 /* return new */ 00298 return dst; 00299 } 00300 00301 /* -------- GP-Frame API ---------- */ 00302 00303 /* delete the last stroke of the given frame */ 00304 void gpencil_frame_delete_laststroke (bGPDlayer *gpl, bGPDframe *gpf) 00305 { 00306 bGPDstroke *gps= (gpf) ? gpf->strokes.last : NULL; 00307 int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */ 00308 00309 /* error checking */ 00310 if (ELEM(NULL, gpf, gps)) 00311 return; 00312 00313 /* free the stroke and its data */ 00314 MEM_freeN(gps->points); 00315 BLI_freelinkN(&gpf->strokes, gps); 00316 00317 /* if frame has no strokes after this, delete it */ 00318 if (gpf->strokes.first == NULL) { 00319 gpencil_layer_delframe(gpl, gpf); 00320 gpencil_layer_getframe(gpl, cfra, 0); 00321 } 00322 } 00323 00324 /* -------- GP-Layer API ---------- */ 00325 00326 /* get the appropriate gp-frame from a given layer 00327 * - this sets the layer's actframe var (if allowed to) 00328 * - extension beyond range (if first gp-frame is after all frame in interest and cannot add) 00329 */ 00330 bGPDframe *gpencil_layer_getframe (bGPDlayer *gpl, int cframe, short addnew) 00331 { 00332 bGPDframe *gpf = NULL; 00333 short found = 0; 00334 00335 /* error checking */ 00336 if (gpl == NULL) return NULL; 00337 if (cframe <= 0) cframe = 1; 00338 00339 /* check if there is already an active frame */ 00340 if (gpl->actframe) { 00341 gpf= gpl->actframe; 00342 00343 /* do not allow any changes to layer's active frame if layer is locked from changes 00344 * or if the layer has been set to stay on the current frame 00345 */ 00346 if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_FRAMELOCK)) 00347 return gpf; 00348 /* do not allow any changes to actframe if frame has painting tag attached to it */ 00349 if (gpf->flag & GP_FRAME_PAINT) 00350 return gpf; 00351 00352 /* try to find matching frame */ 00353 if (gpf->framenum < cframe) { 00354 for (; gpf; gpf= gpf->next) { 00355 if (gpf->framenum == cframe) { 00356 found= 1; 00357 break; 00358 } 00359 else if ((gpf->next) && (gpf->next->framenum > cframe)) { 00360 found= 1; 00361 break; 00362 } 00363 } 00364 00365 /* set the appropriate frame */ 00366 if (addnew) { 00367 if ((found) && (gpf->framenum == cframe)) 00368 gpl->actframe= gpf; 00369 else 00370 gpl->actframe= gpencil_frame_addnew(gpl, cframe); 00371 } 00372 else if (found) 00373 gpl->actframe= gpf; 00374 else 00375 gpl->actframe= gpl->frames.last; 00376 } 00377 else { 00378 for (; gpf; gpf= gpf->prev) { 00379 if (gpf->framenum <= cframe) { 00380 found= 1; 00381 break; 00382 } 00383 } 00384 00385 /* set the appropriate frame */ 00386 if (addnew) { 00387 if ((found) && (gpf->framenum == cframe)) 00388 gpl->actframe= gpf; 00389 else 00390 gpl->actframe= gpencil_frame_addnew(gpl, cframe); 00391 } 00392 else if (found) 00393 gpl->actframe= gpf; 00394 else 00395 gpl->actframe= gpl->frames.first; 00396 } 00397 } 00398 else if (gpl->frames.first) { 00399 /* check which of the ends to start checking from */ 00400 const int first= ((bGPDframe *)(gpl->frames.first))->framenum; 00401 const int last= ((bGPDframe *)(gpl->frames.last))->framenum; 00402 00403 if (abs(cframe-first) > abs(cframe-last)) { 00404 /* find gp-frame which is less than or equal to cframe */ 00405 for (gpf= gpl->frames.last; gpf; gpf= gpf->prev) { 00406 if (gpf->framenum <= cframe) { 00407 found= 1; 00408 break; 00409 } 00410 } 00411 } 00412 else { 00413 /* find gp-frame which is less than or equal to cframe */ 00414 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { 00415 if (gpf->framenum <= cframe) { 00416 found= 1; 00417 break; 00418 } 00419 } 00420 } 00421 00422 /* set the appropriate frame */ 00423 if (addnew) { 00424 if ((found) && (gpf->framenum == cframe)) 00425 gpl->actframe= gpf; 00426 else 00427 gpl->actframe= gpencil_frame_addnew(gpl, cframe); 00428 } 00429 else if (found) 00430 gpl->actframe= gpf; 00431 else { 00432 /* unresolved errogenous situation! */ 00433 printf("Error: cannot find appropriate gp-frame \n"); 00434 /* gpl->actframe should still be NULL */ 00435 } 00436 } 00437 else { 00438 /* currently no frames (add if allowed to) */ 00439 if (addnew) 00440 gpl->actframe= gpencil_frame_addnew(gpl, cframe); 00441 else { 00442 /* don't do anything... this may be when no frames yet! */ 00443 /* gpl->actframe should still be NULL */ 00444 } 00445 } 00446 00447 /* return */ 00448 return gpl->actframe; 00449 } 00450 00451 /* delete the given frame from a layer */ 00452 void gpencil_layer_delframe (bGPDlayer *gpl, bGPDframe *gpf) 00453 { 00454 /* error checking */ 00455 if (ELEM(NULL, gpl, gpf)) 00456 return; 00457 00458 /* free the frame and its data */ 00459 free_gpencil_strokes(gpf); 00460 BLI_freelinkN(&gpl->frames, gpf); 00461 gpl->actframe = NULL; 00462 } 00463 00464 /* get the active gp-layer for editing */ 00465 bGPDlayer *gpencil_layer_getactive (bGPdata *gpd) 00466 { 00467 bGPDlayer *gpl; 00468 00469 /* error checking */ 00470 if (ELEM(NULL, gpd, gpd->layers.first)) 00471 return NULL; 00472 00473 /* loop over layers until found (assume only one active) */ 00474 for (gpl=gpd->layers.first; gpl; gpl=gpl->next) { 00475 if (gpl->flag & GP_LAYER_ACTIVE) 00476 return gpl; 00477 } 00478 00479 /* no active layer found */ 00480 return NULL; 00481 } 00482 00483 /* set the active gp-layer */ 00484 void gpencil_layer_setactive (bGPdata *gpd, bGPDlayer *active) 00485 { 00486 bGPDlayer *gpl; 00487 00488 /* error checking */ 00489 if (ELEM3(NULL, gpd, gpd->layers.first, active)) 00490 return; 00491 00492 /* loop over layers deactivating all */ 00493 for (gpl=gpd->layers.first; gpl; gpl=gpl->next) 00494 gpl->flag &= ~GP_LAYER_ACTIVE; 00495 00496 /* set as active one */ 00497 active->flag |= GP_LAYER_ACTIVE; 00498 } 00499 00500 /* delete the active gp-layer */ 00501 void gpencil_layer_delactive (bGPdata *gpd) 00502 { 00503 bGPDlayer *gpl= gpencil_layer_getactive(gpd); 00504 00505 /* error checking */ 00506 if (ELEM(NULL, gpd, gpl)) 00507 return; 00508 00509 /* free layer */ 00510 free_gpencil_frames(gpl); 00511 BLI_freelinkN(&gpd->layers, gpl); 00512 } 00513 00514 /* ************************************************** */