Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2008, Blender Foundation 00019 * This is a new part of Blender 00020 * 00021 * Contributor(s): Joshua Leung 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <stdio.h> 00032 #include <string.h> 00033 #include <stdlib.h> 00034 #include <stddef.h> 00035 #include <math.h> 00036 #include <float.h> 00037 00038 #include "BLO_sys_types.h" 00039 00040 #include "IMB_imbuf_types.h" 00041 00042 #include "BLI_math.h" 00043 #include "BLI_blenlib.h" 00044 #include "BLI_utildefines.h" 00045 00046 #include "DNA_gpencil_types.h" 00047 #include "DNA_scene_types.h" 00048 #include "DNA_screen_types.h" 00049 #include "DNA_space_types.h" 00050 #include "DNA_view3d_types.h" 00051 00052 #include "BKE_context.h" 00053 #include "BKE_global.h" 00054 #include "BKE_gpencil.h" 00055 00056 00057 00058 #include "WM_api.h" 00059 00060 #include "BIF_gl.h" 00061 #include "BIF_glutil.h" 00062 00063 #include "ED_gpencil.h" 00064 #include "ED_sequencer.h" 00065 #include "ED_view3d.h" 00066 00067 00068 #include "gpencil_intern.h" 00069 00070 /* ************************************************** */ 00071 /* GREASE PENCIL DRAWING */ 00072 00073 /* ----- General Defines ------ */ 00074 00075 /* flags for sflag */ 00076 typedef enum eDrawStrokeFlags { 00077 GP_DRAWDATA_NOSTATUS = (1<<0), /* don't draw status info */ 00078 GP_DRAWDATA_ONLY3D = (1<<1), /* only draw 3d-strokes */ 00079 GP_DRAWDATA_ONLYV2D = (1<<2), /* only draw 'canvas' strokes */ 00080 GP_DRAWDATA_ONLYI2D = (1<<3), /* only draw 'image' strokes */ 00081 GP_DRAWDATA_IEDITHACK = (1<<4), /* special hack for drawing strokes in Image Editor (weird coordinates) */ 00082 GP_DRAWDATA_NO_XRAY = (1<<5), /* dont draw xray in 3D view (which is default) */ 00083 } eDrawStrokeFlags; 00084 00085 00086 00087 /* thickness above which we should use special drawing */ 00088 #define GP_DRAWTHICKNESS_SPECIAL 3 00089 00090 /* ----- Tool Buffer Drawing ------ */ 00091 00092 /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */ 00093 static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thickness, short dflag, short sflag) 00094 { 00095 tGPspoint *pt; 00096 int i; 00097 00098 /* error checking */ 00099 if ((points == NULL) || (totpoints <= 0)) 00100 return; 00101 00102 /* check if buffer can be drawn */ 00103 if (dflag & (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_ONLYV2D)) 00104 return; 00105 00106 /* if drawing a single point, draw it larger */ 00107 if (totpoints == 1) { 00108 /* draw point */ 00109 glBegin(GL_POINTS); 00110 glVertex2iv(&points->x); 00111 glEnd(); 00112 } 00113 else if (sflag & GP_STROKE_ERASER) { 00114 /* don't draw stroke at all! */ 00115 } 00116 else { 00117 float oldpressure = points[0].pressure; 00118 00119 /* draw stroke curve */ 00120 if (G.f & G_DEBUG) setlinestyle(2); 00121 00122 glLineWidth(oldpressure * thickness); 00123 glBegin(GL_LINE_STRIP); 00124 00125 for (i=0, pt=points; i < totpoints && pt; i++, pt++) { 00126 /* if there was a significant pressure change, stop the curve, change the thickness of the stroke, 00127 * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP) 00128 */ 00129 if (fabsf(pt->pressure - oldpressure) > 0.2f) { 00130 glEnd(); 00131 glLineWidth(pt->pressure * thickness); 00132 glBegin(GL_LINE_STRIP); 00133 00134 /* need to roll-back one point to ensure that there are no gaps in the stroke */ 00135 if (i != 0) glVertex2iv(&(pt - 1)->x); 00136 00137 /* now the point we want... */ 00138 glVertex2iv(&pt->x); 00139 00140 oldpressure = pt->pressure; 00141 } 00142 else 00143 glVertex2iv(&pt->x); 00144 } 00145 glEnd(); 00146 00147 /* reset for predictable OpenGL context */ 00148 glLineWidth(1.0f); 00149 00150 if (G.f & G_DEBUG) setlinestyle(0); 00151 } 00152 } 00153 00154 /* ----- Existing Strokes Drawing (3D and Point) ------ */ 00155 00156 /* draw a given stroke - just a single dot (only one point) */ 00157 static void gp_draw_stroke_point (bGPDspoint *points, short thickness, short dflag, short sflag, int offsx, int offsy, int winx, int winy) 00158 { 00159 /* draw point */ 00160 if (sflag & GP_STROKE_3DSPACE) { 00161 glBegin(GL_POINTS); 00162 glVertex3fv(&points->x); 00163 glEnd(); 00164 } 00165 else { 00166 float co[2]; 00167 00168 /* get coordinates of point */ 00169 if (sflag & GP_STROKE_2DSPACE) { 00170 co[0]= points->x; 00171 co[1]= points->y; 00172 } 00173 else if (sflag & GP_STROKE_2DIMAGE) { 00174 co[0]= (points->x * winx) + offsx; 00175 co[1]= (points->y * winy) + offsy; 00176 } 00177 else { 00178 co[0]= (points->x / 100 * winx) + offsx; 00179 co[1]= (points->y / 100 * winy) + offsy; 00180 } 00181 00182 /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok 00183 * - also mandatory in if Image Editor 'image-based' dot 00184 */ 00185 if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || 00186 ((dflag & GP_DRAWDATA_IEDITHACK) && (sflag & GP_STROKE_2DSPACE)) ) 00187 { 00188 glBegin(GL_POINTS); 00189 glVertex2fv(co); 00190 glEnd(); 00191 } 00192 else 00193 { 00194 /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */ 00195 GLUquadricObj *qobj = gluNewQuadric(); 00196 00197 gluQuadricDrawStyle(qobj, GLU_FILL); 00198 00199 /* need to translate drawing position, but must reset after too! */ 00200 glTranslatef(co[0], co[1], 0.); 00201 gluDisk(qobj, 0.0, thickness, 32, 1); 00202 glTranslatef(-co[0], -co[1], 0.); 00203 00204 gluDeleteQuadric(qobj); 00205 } 00206 } 00207 } 00208 00209 /* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */ 00210 static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thickness, short debug) 00211 { 00212 bGPDspoint *pt; 00213 float oldpressure = 0.0f; 00214 int i; 00215 00216 /* draw stroke curve */ 00217 glBegin(GL_LINE_STRIP); 00218 for (i=0, pt=points; i < totpoints && pt; i++, pt++) { 00219 /* if there was a significant pressure change, stop the curve, change the thickness of the stroke, 00220 * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP) 00221 */ 00222 if (fabsf(pt->pressure - oldpressure) > 0.2f) { 00223 glEnd(); 00224 glLineWidth(pt->pressure * thickness); 00225 glBegin(GL_LINE_STRIP); 00226 00227 /* need to roll-back one point to ensure that there are no gaps in the stroke */ 00228 if (i != 0) glVertex3fv(&(pt - 1)->x); 00229 00230 /* now the point we want... */ 00231 glVertex3fv(&pt->x); 00232 00233 oldpressure = pt->pressure; 00234 } 00235 else { 00236 glVertex3fv(&pt->x); 00237 } 00238 } 00239 glEnd(); 00240 00241 /* draw debug points of curve on top? */ 00242 if (debug) { 00243 glBegin(GL_POINTS); 00244 for (i=0, pt=points; i < totpoints && pt; i++, pt++) 00245 glVertex3fv(&pt->x); 00246 glEnd(); 00247 } 00248 } 00249 00250 /* ----- Fancy 2D-Stroke Drawing ------ */ 00251 00252 /* draw a given stroke in 2d */ 00253 static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag, 00254 short debug, int offsx, int offsy, int winx, int winy) 00255 { 00256 /* otherwise thickness is twice that of the 3D view */ 00257 float thickness= (float)thickness_s * 0.5f; 00258 00259 /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better 00260 * - 'smooth' opengl lines are also required if Image Editor 'image-based' stroke 00261 */ 00262 if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || 00263 ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) ) 00264 { 00265 bGPDspoint *pt; 00266 int i; 00267 00268 glBegin(GL_LINE_STRIP); 00269 for (i=0, pt=points; i < totpoints && pt; i++, pt++) { 00270 if (sflag & GP_STROKE_2DSPACE) { 00271 glVertex2f(pt->x, pt->y); 00272 } 00273 else if (sflag & GP_STROKE_2DIMAGE) { 00274 const float x= (pt->x * winx) + offsx; 00275 const float y= (pt->y * winy) + offsy; 00276 00277 glVertex2f(x, y); 00278 } 00279 else { 00280 const float x= (pt->x / 100 * winx) + offsx; 00281 const float y= (pt->y / 100 * winy) + offsy; 00282 00283 glVertex2f(x, y); 00284 } 00285 } 00286 glEnd(); 00287 } 00288 00289 /* tesselation code - draw stroke as series of connected quads with connection 00290 * edges rotated to minimise shrinking artifacts, and rounded endcaps 00291 */ 00292 else 00293 { 00294 bGPDspoint *pt1, *pt2; 00295 float pm[2]; 00296 int i; 00297 00298 glShadeModel(GL_FLAT); 00299 glBegin(GL_QUADS); 00300 00301 for (i=0, pt1=points, pt2=points+1; i < (totpoints-1); i++, pt1++, pt2++) { 00302 float s0[2], s1[2]; /* segment 'center' points */ 00303 float t0[2], t1[2]; /* tesselated coordinates */ 00304 float m1[2], m2[2]; /* gradient and normal */ 00305 float mt[2], sc[2]; /* gradient for thickness, point for end-cap */ 00306 float pthick; /* thickness at segment point */ 00307 00308 /* get x and y coordinates from points */ 00309 if (sflag & GP_STROKE_2DSPACE) { 00310 s0[0]= pt1->x; s0[1]= pt1->y; 00311 s1[0]= pt2->x; s1[1]= pt2->y; 00312 } 00313 else if (sflag & GP_STROKE_2DIMAGE) { 00314 s0[0]= (pt1->x * winx) + offsx; 00315 s0[1]= (pt1->y * winy) + offsy; 00316 s1[0]= (pt2->x * winx) + offsx; 00317 s1[1]= (pt2->y * winy) + offsy; 00318 } 00319 else { 00320 s0[0]= (pt1->x / 100 * winx) + offsx; 00321 s0[1]= (pt1->y / 100 * winy) + offsy; 00322 s1[0]= (pt2->x / 100 * winx) + offsx; 00323 s1[1]= (pt2->y / 100 * winy) + offsy; 00324 } 00325 00326 /* calculate gradient and normal - 'angle'=(ny/nx) */ 00327 m1[1]= s1[1] - s0[1]; 00328 m1[0]= s1[0] - s0[0]; 00329 normalize_v2(m1); 00330 m2[1]= -m1[0]; 00331 m2[0]= m1[1]; 00332 00333 /* always use pressure from first point here */ 00334 pthick= (pt1->pressure * thickness); 00335 00336 /* if the first segment, start of segment is segment's normal */ 00337 if (i == 0) { 00338 /* draw start cap first 00339 * - make points slightly closer to center (about halfway across) 00340 */ 00341 mt[0]= m2[0] * pthick * 0.5f; 00342 mt[1]= m2[1] * pthick * 0.5f; 00343 sc[0]= s0[0] - (m1[0] * pthick * 0.75f); 00344 sc[1]= s0[1] - (m1[1] * pthick * 0.75f); 00345 00346 t0[0]= sc[0] - mt[0]; 00347 t0[1]= sc[1] - mt[1]; 00348 t1[0]= sc[0] + mt[0]; 00349 t1[1]= sc[1] + mt[1]; 00350 00351 glVertex2fv(t0); 00352 glVertex2fv(t1); 00353 00354 /* calculate points for start of segment */ 00355 mt[0]= m2[0] * pthick; 00356 mt[1]= m2[1] * pthick; 00357 00358 t0[0]= s0[0] - mt[0]; 00359 t0[1]= s0[1] - mt[1]; 00360 t1[0]= s0[0] + mt[0]; 00361 t1[1]= s0[1] + mt[1]; 00362 00363 /* draw this line twice (first to finish off start cap, then for stroke) */ 00364 glVertex2fv(t1); 00365 glVertex2fv(t0); 00366 glVertex2fv(t0); 00367 glVertex2fv(t1); 00368 } 00369 /* if not the first segment, use bisector of angle between segments */ 00370 else { 00371 float mb[2]; /* bisector normal */ 00372 float athick, dfac; /* actual thickness, difference between thicknesses */ 00373 00374 /* calculate gradient of bisector (as average of normals) */ 00375 mb[0]= (pm[0] + m2[0]) / 2; 00376 mb[1]= (pm[1] + m2[1]) / 2; 00377 normalize_v2(mb); 00378 00379 /* calculate gradient to apply 00380 * - as basis, use just pthick * bisector gradient 00381 * - if cross-section not as thick as it should be, add extra padding to fix it 00382 */ 00383 mt[0]= mb[0] * pthick; 00384 mt[1]= mb[1] * pthick; 00385 athick= len_v2(mt); 00386 dfac= pthick - (athick * 2); 00387 if ( ((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick)==0) ) 00388 { 00389 mt[0] += (mb[0] * dfac); 00390 mt[1] += (mb[1] * dfac); 00391 } 00392 00393 /* calculate points for start of segment */ 00394 t0[0]= s0[0] - mt[0]; 00395 t0[1]= s0[1] - mt[1]; 00396 t1[0]= s0[0] + mt[0]; 00397 t1[1]= s0[1] + mt[1]; 00398 00399 /* draw this line twice (once for end of current segment, and once for start of next) */ 00400 glVertex2fv(t1); 00401 glVertex2fv(t0); 00402 glVertex2fv(t0); 00403 glVertex2fv(t1); 00404 } 00405 00406 /* if last segment, also draw end of segment (defined as segment's normal) */ 00407 if (i == totpoints-2) { 00408 /* for once, we use second point's pressure (otherwise it won't be drawn) */ 00409 pthick= (pt2->pressure * thickness); 00410 00411 /* calculate points for end of segment */ 00412 mt[0]= m2[0] * pthick; 00413 mt[1]= m2[1] * pthick; 00414 00415 t0[0]= s1[0] - mt[0]; 00416 t0[1]= s1[1] - mt[1]; 00417 t1[0]= s1[0] + mt[0]; 00418 t1[1]= s1[1] + mt[1]; 00419 00420 /* draw this line twice (once for end of stroke, and once for endcap)*/ 00421 glVertex2fv(t1); 00422 glVertex2fv(t0); 00423 glVertex2fv(t0); 00424 glVertex2fv(t1); 00425 00426 00427 /* draw end cap as last step 00428 * - make points slightly closer to center (about halfway across) 00429 */ 00430 mt[0]= m2[0] * pthick * 0.5f; 00431 mt[1]= m2[1] * pthick * 0.5f; 00432 sc[0]= s1[0] + (m1[0] * pthick * 0.75f); 00433 sc[1]= s1[1] + (m1[1] * pthick * 0.75f); 00434 00435 t0[0]= sc[0] - mt[0]; 00436 t0[1]= sc[1] - mt[1]; 00437 t1[0]= sc[0] + mt[0]; 00438 t1[1]= sc[1] + mt[1]; 00439 00440 glVertex2fv(t1); 00441 glVertex2fv(t0); 00442 } 00443 00444 /* store stroke's 'natural' normal for next stroke to use */ 00445 copy_v2_v2(pm, m2); 00446 } 00447 00448 glEnd(); 00449 } 00450 00451 /* draw debug points of curve on top? (original stroke points) */ 00452 if (debug) { 00453 bGPDspoint *pt; 00454 int i; 00455 00456 glBegin(GL_POINTS); 00457 for (i=0, pt=points; i < totpoints && pt; i++, pt++) { 00458 if (sflag & GP_STROKE_2DSPACE) { 00459 glVertex2fv(&pt->x); 00460 } 00461 else if (sflag & GP_STROKE_2DIMAGE) { 00462 const float x= (float)((pt->x * winx) + offsx); 00463 const float y= (float)((pt->y * winy) + offsy); 00464 00465 glVertex2f(x, y); 00466 } 00467 else { 00468 const float x= (float)(pt->x / 100 * winx) + offsx; 00469 const float y= (float)(pt->y / 100 * winy) + offsy; 00470 00471 glVertex2f(x, y); 00472 } 00473 } 00474 glEnd(); 00475 } 00476 } 00477 00478 /* ----- General Drawing ------ */ 00479 00480 /* draw a set of strokes */ 00481 static void gp_draw_strokes (bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag, 00482 short debug, short lthick, float color[4]) 00483 { 00484 bGPDstroke *gps; 00485 00486 /* set color first (may need to reset it again later too) */ 00487 glColor4fv(color); 00488 00489 for (gps= gpf->strokes.first; gps; gps= gps->next) { 00490 /* check if stroke can be drawn - checks here generally fall into pairs */ 00491 if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE)) 00492 continue; 00493 if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE)) 00494 continue; 00495 if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE)) 00496 continue; 00497 if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE)) 00498 continue; 00499 if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE)) 00500 continue; 00501 if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE)) 00502 continue; 00503 if ((gps->points == NULL) || (gps->totpoints < 1)) 00504 continue; 00505 00506 /* check which stroke-drawer to use */ 00507 if (gps->totpoints == 1) 00508 gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy); 00509 else if (dflag & GP_DRAWDATA_ONLY3D) { 00510 const int no_xray= (dflag & GP_DRAWDATA_NO_XRAY); 00511 int mask_orig = 0; 00512 00513 if (no_xray) { 00514 glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); 00515 glDepthMask(0); 00516 glEnable(GL_DEPTH_TEST); 00517 00518 /* first arg is normally rv3d->dist, but this isnt available here and seems to work quite well without */ 00519 bglPolygonOffset(1.0f, 1.0f); 00520 /* 00521 glEnable(GL_POLYGON_OFFSET_LINE); 00522 glPolygonOffset(-1.0f, -1.0f); 00523 */ 00524 } 00525 00526 gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, debug); 00527 00528 if (no_xray) { 00529 glDepthMask(mask_orig); 00530 glDisable(GL_DEPTH_TEST); 00531 00532 bglPolygonOffset(0.0, 0.0); 00533 /* 00534 glDisable(GL_POLYGON_OFFSET_LINE); 00535 glPolygonOffset(0, 0); 00536 */ 00537 } 00538 } 00539 else if (gps->totpoints > 1) 00540 gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy); 00541 } 00542 } 00543 00544 /* draw grease-pencil datablock */ 00545 static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) 00546 { 00547 bGPDlayer *gpl; 00548 00549 /* reset line drawing style (in case previous user didn't reset) */ 00550 setlinestyle(0); 00551 00552 /* turn on smooth lines (i.e. anti-aliasing) */ 00553 glEnable(GL_LINE_SMOOTH); 00554 00555 /* turn on alpha-blending */ 00556 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00557 glEnable(GL_BLEND); 00558 00559 /* loop over layers, drawing them */ 00560 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { 00561 bGPDframe *gpf; 00562 00563 short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0; 00564 short lthick= gpl->thickness; 00565 float color[4], tcolor[4]; 00566 00567 /* don't draw layer if hidden */ 00568 if (gpl->flag & GP_LAYER_HIDE) 00569 continue; 00570 00571 /* get frame to draw */ 00572 gpf= gpencil_layer_getframe(gpl, cfra, 0); 00573 if (gpf == NULL) 00574 continue; 00575 00576 /* set color, stroke thickness, and point size */ 00577 glLineWidth(lthick); 00578 copy_v4_v4(color, gpl->color); // just for copying 4 array elements 00579 copy_v4_v4(tcolor, gpl->color); // additional copy of color (for ghosting) 00580 glColor4fv(color); 00581 glPointSize((float)(gpl->thickness + 2)); 00582 00583 /* apply xray layer setting */ 00584 if (gpl->flag & GP_LAYER_NO_XRAY) dflag |= GP_DRAWDATA_NO_XRAY; 00585 else dflag &= ~GP_DRAWDATA_NO_XRAY; 00586 00587 /* draw 'onionskins' (frame left + right) */ 00588 if (gpl->flag & GP_LAYER_ONIONSKIN) { 00589 /* drawing method - only immediately surrounding (gstep = 0), or within a frame range on either side (gstep > 0)*/ 00590 if (gpl->gstep) { 00591 bGPDframe *gf; 00592 float fac; 00593 00594 /* draw previous frames first */ 00595 for (gf=gpf->prev; gf; gf=gf->prev) { 00596 /* check if frame is drawable */ 00597 if ((gpf->framenum - gf->framenum) <= gpl->gstep) { 00598 /* alpha decreases with distance from curframe index */ 00599 fac= 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1)); 00600 tcolor[3] = color[3] * fac * 0.66f; 00601 gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); 00602 } 00603 else 00604 break; 00605 } 00606 00607 /* now draw next frames */ 00608 for (gf= gpf->next; gf; gf=gf->next) { 00609 /* check if frame is drawable */ 00610 if ((gf->framenum - gpf->framenum) <= gpl->gstep) { 00611 /* alpha decreases with distance from curframe index */ 00612 fac= 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep + 1)); 00613 tcolor[3] = color[3] * fac * 0.66f; 00614 gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); 00615 } 00616 else 00617 break; 00618 } 00619 00620 /* restore alpha */ 00621 glColor4fv(color); 00622 } 00623 else { 00624 /* draw the strokes for the ghost frames (at half of the alpha set by user) */ 00625 if (gpf->prev) { 00626 tcolor[3] = (color[3] / 7); 00627 gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); 00628 } 00629 00630 if (gpf->next) { 00631 tcolor[3] = (color[3] / 4); 00632 gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); 00633 } 00634 00635 /* restore alpha */ 00636 glColor4fv(color); 00637 } 00638 } 00639 00640 /* draw the strokes already in active frame */ 00641 tcolor[3]= color[3]; 00642 gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); 00643 00644 /* Check if may need to draw the active stroke cache, only if this layer is the active layer 00645 * that is being edited. (Stroke buffer is currently stored in gp-data) 00646 */ 00647 if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) && 00648 (gpf->flag & GP_FRAME_PAINT)) 00649 { 00650 /* Buffer stroke needs to be drawn with a different linestyle to help differentiate them from normal strokes. */ 00651 gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag); 00652 } 00653 } 00654 00655 /* turn off alpha blending, then smooth lines */ 00656 glDisable(GL_BLEND); // alpha blending 00657 glDisable(GL_LINE_SMOOTH); // smooth lines 00658 00659 /* restore initial gl conditions */ 00660 glLineWidth(1.0); 00661 glPointSize(1.0); 00662 glColor4f(0, 0, 0, 1); 00663 } 00664 00665 /* ----- Grease Pencil Sketches Drawing API ------ */ 00666 00667 // ............................ 00668 // XXX 00669 // We need to review the calls below, since they may be/are not that suitable for 00670 // the new ways that we intend to be drawing data... 00671 // ............................ 00672 00673 /* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */ 00674 void draw_gpencil_2dimage (bContext *C, ImBuf *ibuf) 00675 { 00676 ScrArea *sa= CTX_wm_area(C); 00677 ARegion *ar= CTX_wm_region(C); 00678 Scene *scene= CTX_data_scene(C); 00679 bGPdata *gpd; 00680 int offsx, offsy, sizex, sizey; 00681 int dflag = GP_DRAWDATA_NOSTATUS; 00682 00683 /* check that we have grease-pencil stuff to draw */ 00684 if (ELEM(NULL, sa, ibuf)) return; 00685 gpd= gpencil_data_get_active(C); // XXX 00686 if (gpd == NULL) return; 00687 00688 /* calculate rect */ 00689 switch (sa->spacetype) { 00690 case SPACE_IMAGE: /* image */ 00691 case SPACE_CLIP: /* clip */ 00692 { 00693 00694 /* just draw using standard scaling (settings here are currently ignored anyways) */ 00695 // FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled 00696 offsx= 0; 00697 offsy= 0; 00698 sizex= ar->winx; 00699 sizey= ar->winy; 00700 00701 wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax); 00702 00703 dflag |= GP_DRAWDATA_ONLYV2D|GP_DRAWDATA_IEDITHACK; 00704 } 00705 break; 00706 #if 0 /* removed since 2.5x, needs to be added back */ 00707 case SPACE_SEQ: /* sequence */ 00708 { 00709 SpaceSeq *sseq= (SpaceSeq *)sa->spacedata.first; 00710 float zoom, zoomx, zoomy; 00711 00712 /* calculate accessory values */ 00713 zoom= (float)(SEQ_ZOOM_FAC(sseq->zoom)); 00714 if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { 00715 /* XXX sequencer zoom should store it? */ 00716 zoomx = zoom; // * (G.scene->r.xasp / G.scene->r.yasp); 00717 zoomy = zoom; 00718 } 00719 else 00720 zoomx = zoomy = zoom; 00721 00722 /* calculate transforms (Note: we use ibuf here, as we have it) */ 00723 sizex= (int)(zoomx * ibuf->x); 00724 sizey= (int)(zoomy * ibuf->y); 00725 offsx= (int)( (ar->winx-sizex)/2 + sseq->xof ); 00726 offsy= (int)( (ar->winy-sizey)/2 + sseq->yof ); 00727 00728 dflag |= GP_DRAWDATA_ONLYI2D; 00729 } 00730 break; 00731 #endif 00732 default: /* for spacetype not yet handled */ 00733 offsx= 0; 00734 offsy= 0; 00735 sizex= ar->winx; 00736 sizey= ar->winy; 00737 00738 dflag |= GP_DRAWDATA_ONLYI2D; 00739 break; 00740 } 00741 00742 00743 /* draw it! */ 00744 gp_draw_data(gpd, offsx, offsy, sizex, sizey, CFRA, dflag); 00745 } 00746 00747 /* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly 00748 * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, second time with onlyv2d=0 for screen-aligned strokes 00749 */ 00750 void draw_gpencil_view2d (bContext *C, short onlyv2d) 00751 { 00752 ScrArea *sa= CTX_wm_area(C); 00753 ARegion *ar= CTX_wm_region(C); 00754 Scene *scene= CTX_data_scene(C); 00755 bGPdata *gpd; 00756 int dflag = 0; 00757 00758 /* check that we have grease-pencil stuff to draw */ 00759 if (sa == NULL) return; 00760 gpd= gpencil_data_get_active(C); // XXX 00761 if (gpd == NULL) return; 00762 00763 /* special hack for Image Editor */ 00764 // FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled 00765 if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP)) 00766 dflag |= GP_DRAWDATA_IEDITHACK; 00767 00768 /* draw it! */ 00769 if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D|GP_DRAWDATA_NOSTATUS); 00770 gp_draw_data(gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag); 00771 } 00772 00773 /* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly 00774 * Note: this gets called twice - first time with only3d=1 to draw 3d-strokes, second time with only3d=0 for screen-aligned strokes 00775 */ 00776 00777 void draw_gpencil_view3d (Scene *scene, View3D *v3d, ARegion *ar, short only3d) 00778 { 00779 bGPdata *gpd; 00780 int dflag = 0; 00781 rcti rect; 00782 RegionView3D *rv3d= ar->regiondata; 00783 00784 /* check that we have grease-pencil stuff to draw */ 00785 gpd= gpencil_data_get_active_v3d(scene); // XXX 00786 if (gpd == NULL) return; 00787 00788 /* when rendering to the offscreen buffer we dont want to 00789 * deal with the camera border, otherwise map the coords to the camera border. */ 00790 if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) { 00791 rctf rectf; 00792 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, TRUE); /* no shift */ 00793 BLI_copy_rcti_rctf(&rect, &rectf); 00794 } 00795 else { 00796 rect.xmin= 0; 00797 rect.ymin= 0; 00798 rect.xmax= ar->winx; 00799 rect.ymax= ar->winy; 00800 } 00801 00802 /* draw it! */ 00803 if (only3d) dflag |= (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_NOSTATUS); 00804 00805 gp_draw_data(gpd, rect.xmin, rect.ymin, rect.xmax, rect.ymax, CFRA, dflag); 00806 } 00807 00808 /* ************************************************** */