|
Blender
V2.59
|
00001 /* 00002 * $Id: nla_draw.c 35824 2011-03-27 17:22:04Z campbellbarton $ 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) 2009 Blender Foundation, Joshua Leung 00021 * All rights reserved. 00022 * 00023 * 00024 * Contributor(s): Joshua Leung (major recode) 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include <string.h> 00035 #include <stdio.h> 00036 #include <stdlib.h> 00037 #include <math.h> 00038 #include <float.h> 00039 00040 #include "DNA_anim_types.h" 00041 #include "DNA_screen_types.h" 00042 #include "DNA_space_types.h" 00043 #include "DNA_windowmanager_types.h" 00044 00045 #include "BLI_blenlib.h" 00046 #include "BLI_math.h" 00047 #include "BLI_rand.h" 00048 #include "BLI_dlrbTree.h" 00049 #include "BLI_utildefines.h" 00050 00051 #include "BKE_fcurve.h" 00052 #include "BKE_nla.h" 00053 #include "BKE_context.h" 00054 #include "BKE_screen.h" 00055 00056 #include "ED_anim_api.h" 00057 #include "ED_keyframes_draw.h" 00058 00059 #include "BIF_gl.h" 00060 #include "BIF_glutil.h" 00061 00062 #include "WM_types.h" 00063 00064 #include "UI_interface.h" 00065 #include "UI_interface_icons.h" 00066 #include "UI_resources.h" 00067 #include "UI_view2d.h" 00068 00069 00070 #include "nla_intern.h" // own include 00071 00072 00073 /* *********************************************** */ 00074 /* Strips */ 00075 00076 /* Action-Line ---------------------- */ 00077 00078 /* get colors for drawing Action-Line 00079 * NOTE: color returned includes fine-tuned alpha! 00080 */ 00081 static void nla_action_get_color (AnimData *adt, bAction *act, float color[4]) 00082 { 00083 // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now) 00084 if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { 00085 // greenish color (same as tweaking strip) - hardcoded for now 00086 color[0]= 0.30f; 00087 color[1]= 0.95f; 00088 color[2]= 0.10f; 00089 color[3]= 0.30f; 00090 } 00091 else { 00092 if (act) { 00093 // reddish color - hardcoded for now 00094 color[0]= 0.8f; 00095 color[1]= 0.2f; 00096 color[2]= 0.0f; 00097 color[3]= 0.4f; 00098 } 00099 else { 00100 // greyish-red color - hardcoded for now 00101 color[0]= 0.6f; 00102 color[1]= 0.5f; 00103 color[2]= 0.5f; 00104 color[3]= 0.3f; 00105 } 00106 } 00107 } 00108 00109 /* draw the keyframes in the specified Action */ 00110 static void nla_action_draw_keyframes (AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax) 00111 { 00112 DLRBT_Tree keys; 00113 ActKeyColumn *ak; 00114 float xscale, f1, f2; 00115 float color[4]; 00116 00117 /* get a list of the keyframes with NLA-scaling applied */ 00118 BLI_dlrbTree_init(&keys); 00119 action_to_keylist(adt, act, &keys, NULL); 00120 BLI_dlrbTree_linkedlist_sync(&keys); 00121 00122 if ELEM(NULL, act, keys.first) 00123 return; 00124 00125 /* draw a darkened region behind the strips 00126 * - get and reset the background color, this time without the alpha to stand out better 00127 */ 00128 nla_action_get_color(adt, act, color); 00129 glColor3fv(color); 00130 /* - draw a rect from the first to the last frame (no extra overlaps for now) 00131 * that is slightly stumpier than the track background (hardcoded 2-units here) 00132 */ 00133 f1= ((ActKeyColumn *)keys.first)->cfra; 00134 f2= ((ActKeyColumn *)keys.last)->cfra; 00135 00136 glRectf(f1, ymin+2, f2, ymax-2); 00137 00138 00139 /* get View2D scaling factor */ 00140 UI_view2d_getscale(v2d, &xscale, NULL); 00141 00142 /* for now, color is hardcoded to be black */ 00143 glColor3f(0.0f, 0.0f, 0.0f); 00144 00145 /* just draw each keyframe as a simple dot (regardless of the selection status) 00146 * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction 00147 */ 00148 for (ak= keys.first; ak; ak= ak->next) 00149 draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f); 00150 00151 /* free icons */ 00152 BLI_dlrbTree_free(&keys); 00153 } 00154 00155 /* Strips (Proper) ---------------------- */ 00156 00157 /* get colors for drawing NLA-Strips */ 00158 static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float color[3]) 00159 { 00160 if (strip->type == NLASTRIP_TYPE_TRANSITION) { 00161 /* Transition Clip */ 00162 if (strip->flag & NLASTRIP_FLAG_SELECT) { 00163 /* selected - use a bright blue color */ 00164 // FIXME: hardcoded temp-hack colors 00165 color[0]= 0.18f; 00166 color[1]= 0.46f; 00167 color[2]= 0.86f; 00168 } 00169 else { 00170 /* normal, unselected strip - use (hardly noticable) blue tinge */ 00171 // FIXME: hardcoded temp-hack colors 00172 color[0]= 0.11f; 00173 color[1]= 0.15f; 00174 color[2]= 0.19f; 00175 } 00176 } 00177 else if (strip->type == NLASTRIP_TYPE_META) { 00178 /* Meta Clip */ 00179 // TODO: should temporary metas get different colors too? 00180 if (strip->flag & NLASTRIP_FLAG_SELECT) { 00181 /* selected - use a bold purple color */ 00182 // FIXME: hardcoded temp-hack colors 00183 color[0]= 0.41f; 00184 color[1]= 0.13f; 00185 color[2]= 0.59f; 00186 } 00187 else { 00188 /* normal, unselected strip - use (hardly noticable) dark purple tinge */ 00189 // FIXME: hardcoded temp-hack colors 00190 color[0]= 0.20f; 00191 color[1]= 0.15f; 00192 color[2]= 0.26f; 00193 } 00194 } 00195 else { 00196 /* Action Clip (default/normal type of strip) */ 00197 if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) { 00198 /* active strip should be drawn green when it is acting as the tweaking strip. 00199 * however, this case should be skipped for when not in EditMode... 00200 */ 00201 // FIXME: hardcoded temp-hack colors 00202 color[0]= 0.3f; 00203 color[1]= 0.95f; 00204 color[2]= 0.1f; 00205 } 00206 else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) { 00207 /* alert user that this strip is also used by the tweaking track (this is set when going into 00208 * 'editmode' for that strip), since the edits made here may not be what the user anticipated 00209 */ 00210 // FIXME: hardcoded temp-hack colors 00211 color[0]= 0.85f; 00212 color[1]= 0.0f; 00213 color[2]= 0.0f; 00214 } 00215 else if (strip->flag & NLASTRIP_FLAG_SELECT) { 00216 /* selected strip - use theme color for selected */ 00217 UI_GetThemeColor3fv(TH_STRIP_SELECT, color); 00218 } 00219 else { 00220 /* normal, unselected strip - use standard strip theme color */ 00221 UI_GetThemeColor3fv(TH_STRIP, color); 00222 } 00223 } 00224 } 00225 00226 /* helper call for drawing influence/time control curves for a given NLA-strip */ 00227 static void nla_draw_strip_curves (NlaStrip *strip, float yminc, float ymaxc) 00228 { 00229 const float yheight = ymaxc - yminc; 00230 00231 /* drawing color is simply a light-grey */ 00232 // TODO: is this color suitable? 00233 // XXX nasty hacked color for now... which looks quite bad too... 00234 glColor3f(0.7f, 0.7f, 0.7f); 00235 00236 /* draw with AA'd line */ 00237 glEnable(GL_LINE_SMOOTH); 00238 glEnable(GL_BLEND); 00239 00240 /* influence -------------------------- */ 00241 if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) { 00242 FCurve *fcu= list_find_fcurve(&strip->fcurves, "influence", 0); 00243 float cfra; 00244 00245 /* plot the curve (over the strip's main region) */ 00246 glBegin(GL_LINE_STRIP); 00247 /* sample at 1 frame intervals, and draw 00248 * - min y-val is yminc, max is y-maxc, so clamp in those regions 00249 */ 00250 for (cfra= strip->start; cfra <= strip->end; cfra += 1.0f) { 00251 float y= evaluate_fcurve(fcu, cfra); // assume this to be in 0-1 range 00252 glVertex2f(cfra, ((y*yheight)+yminc)); 00253 } 00254 glEnd(); // GL_LINE_STRIP 00255 } 00256 else { 00257 /* use blend in/out values only if both aren't zero */ 00258 if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f))==0) { 00259 glBegin(GL_LINE_STRIP); 00260 /* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */ 00261 if (IS_EQF(strip->blendin, 0.0f) == 0) { 00262 glVertex2f(strip->start, yminc); 00263 glVertex2f(strip->start + strip->blendin, ymaxc); 00264 } 00265 else 00266 glVertex2f(strip->start, ymaxc); 00267 00268 /* end of strip */ 00269 if (IS_EQF(strip->blendout, 0.0f) == 0) { 00270 glVertex2f(strip->end - strip->blendout, ymaxc); 00271 glVertex2f(strip->end, yminc); 00272 } 00273 else 00274 glVertex2f(strip->end, ymaxc); 00275 glEnd(); // GL_LINE_STRIP 00276 } 00277 } 00278 00279 /* time -------------------------- */ 00280 // XXX do we want to draw this curve? in a different color too? 00281 00282 /* turn off AA'd lines */ 00283 glDisable(GL_LINE_SMOOTH); 00284 glDisable(GL_BLEND); 00285 } 00286 00287 /* main call for drawing a single NLA-strip */ 00288 static void nla_draw_strip (SpaceNla *snla, AnimData *adt, NlaTrack *UNUSED(nlt), NlaStrip *strip, View2D *v2d, float yminc, float ymaxc) 00289 { 00290 float color[3]; 00291 00292 /* get color of strip */ 00293 nla_strip_get_color_inside(adt, strip, color); 00294 00295 /* draw extrapolation info first (as backdrop) */ 00296 if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) { 00297 /* enable transparency... */ 00298 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00299 glEnable(GL_BLEND); 00300 00301 switch (strip->extendmode) { 00302 /* since this does both sides, only do the 'before' side, and leave the rest to the next case */ 00303 case NLASTRIP_EXTEND_HOLD: 00304 /* only need to draw here if there's no strip before since 00305 * it only applies in such a situation 00306 */ 00307 if (strip->prev == NULL) { 00308 /* set the drawing color to the color of the strip, but with very faint alpha */ 00309 glColor4f(color[0], color[1], color[2], 0.15f); 00310 00311 /* draw the rect to the edge of the screen */ 00312 glBegin(GL_QUADS); 00313 glVertex2f(v2d->cur.xmin, yminc); 00314 glVertex2f(v2d->cur.xmin, ymaxc); 00315 glVertex2f(strip->start, ymaxc); 00316 glVertex2f(strip->start, yminc); 00317 glEnd(); 00318 } 00319 /* no break needed... */ 00320 00321 /* this only draws after the strip */ 00322 case NLASTRIP_EXTEND_HOLD_FORWARD: 00323 /* only need to try and draw if the next strip doesn't occur immediately after */ 00324 if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end)==0)) { 00325 /* set the drawing color to the color of the strip, but this time less faint */ 00326 glColor4f(color[0], color[1], color[2], 0.3f); 00327 00328 /* draw the rect to the next strip or the edge of the screen */ 00329 glBegin(GL_QUADS); 00330 glVertex2f(strip->end, yminc); 00331 glVertex2f(strip->end, ymaxc); 00332 00333 if (strip->next) { 00334 glVertex2f(strip->next->start, ymaxc); 00335 glVertex2f(strip->next->start, yminc); 00336 } 00337 else { 00338 glVertex2f(v2d->cur.xmax, ymaxc); 00339 glVertex2f(v2d->cur.xmax, yminc); 00340 } 00341 glEnd(); 00342 } 00343 break; 00344 } 00345 00346 glDisable(GL_BLEND); 00347 } 00348 00349 /* draw 'inside' of strip itself */ 00350 glColor3fv(color); 00351 uiSetRoundBox(15); /* all corners rounded */ 00352 uiDrawBoxShade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1); 00353 00354 00355 /* draw strip's control 'curves' 00356 * - only if user hasn't hidden them... 00357 */ 00358 if ((snla->flag & SNLA_NOSTRIPCURVES) == 0) 00359 nla_draw_strip_curves(strip, yminc, ymaxc); 00360 00361 /* draw strip outline 00362 * - color used here is to indicate active vs non-active 00363 */ 00364 if (strip->flag & NLASTRIP_FLAG_ACTIVE) { 00365 /* strip should appear 'sunken', so draw a light border around it */ 00366 glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors 00367 } 00368 else { 00369 /* strip should appear to stand out, so draw a dark border around it */ 00370 glColor3f(0.0f, 0.0f, 0.0f); 00371 } 00372 00373 /* - line style: dotted for muted */ 00374 if (strip->flag & NLASTRIP_FLAG_MUTED) 00375 setlinestyle(4); 00376 00377 /* draw outline */ 00378 uiDrawBoxShade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1); 00379 00380 /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */ 00381 if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQF(strip->repeat, 1.0f)==0) { 00382 float repeatLen = (strip->actend - strip->actstart) * strip->scale; 00383 int i; 00384 00385 /* only draw lines for whole-numbered repeats, starting from the first full-repeat 00386 * up to the last full repeat (but not if it lies on the end of the strip) 00387 */ 00388 for (i = 1; i < strip->repeat; i++) { 00389 float repeatPos = strip->start + (repeatLen * i); 00390 00391 /* don't draw if line would end up on or after the end of the strip */ 00392 if (repeatPos < strip->end) 00393 fdrawline(repeatPos, yminc+4, repeatPos, ymaxc-4); 00394 } 00395 } 00396 /* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */ 00397 else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) { 00398 NlaStrip *cs; 00399 float y= (ymaxc-yminc)/2.0f + yminc; 00400 00401 /* only draw first-level of child-strips, but don't draw any lines on the endpoints */ 00402 for (cs= strip->strips.first; cs; cs= cs->next) { 00403 /* draw start-line if not same as end of previous (and only if not the first strip) 00404 * - on upper half of strip 00405 */ 00406 if ((cs->prev) && IS_EQF(cs->prev->end, cs->start)==0) 00407 fdrawline(cs->start, y, cs->start, ymaxc); 00408 00409 /* draw end-line if not the last strip 00410 * - on lower half of strip 00411 */ 00412 if (cs->next) 00413 fdrawline(cs->end, yminc, cs->end, y); 00414 } 00415 } 00416 00417 /* reset linestyle */ 00418 setlinestyle(0); 00419 } 00420 00421 /* add the relevant text to the cache of text-strings to draw in pixelspace */ 00422 static void nla_draw_strip_text (NlaTrack *UNUSED(nlt), NlaStrip *strip, int UNUSED(index), View2D *v2d, float yminc, float ymaxc) 00423 { 00424 char str[256], dir[3]; 00425 char col[4]; 00426 rctf rect; 00427 00428 /* 'dir' - direction that strip is played in */ 00429 if (strip->flag & NLASTRIP_FLAG_REVERSE) 00430 sprintf(dir, "<-"); 00431 else 00432 sprintf(dir, "->"); 00433 00434 /* just print the name and the range */ 00435 if (strip->flag & NLASTRIP_FLAG_TEMP_META) 00436 sprintf(str, "Temp-Meta | %.2f %s %.2f", strip->start, dir, strip->end); 00437 else 00438 sprintf(str, "%s | %.2f %s %.2f", strip->name, strip->start, dir, strip->end); 00439 00440 /* set text color - if colors (see above) are light, draw black text, otherwise draw white */ 00441 if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER)) { 00442 col[0]= col[1]= col[2]= 0; 00443 } 00444 else { 00445 col[0]= col[1]= col[2]= 255; 00446 } 00447 col[3]= 1.0; 00448 00449 /* set bounding-box for text 00450 * - padding of 2 'units' on either side 00451 */ 00452 // TODO: make this centered? 00453 rect.xmin= strip->start + 0.5f; 00454 rect.ymin= yminc; 00455 rect.xmax= strip->end - 0.5f; 00456 rect.ymax= ymaxc; 00457 00458 /* add this string to the cache of texts to draw*/ 00459 00460 UI_view2d_text_cache_rectf(v2d, &rect, str, col); 00461 } 00462 00463 /* ---------------------- */ 00464 00465 void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar) 00466 { 00467 ListBase anim_data = {NULL, NULL}; 00468 bAnimListElem *ale; 00469 int filter; 00470 00471 View2D *v2d= &ar->v2d; 00472 float y= 0.0f; 00473 int items, height; 00474 00475 /* build list of channels to draw */ 00476 filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS); 00477 items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00478 00479 /* Update max-extent of channels here (taking into account scrollers): 00480 * - this is done to allow the channel list to be scrollable, but must be done here 00481 * to avoid regenerating the list again and/or also because channels list is drawn first 00482 * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 00483 * start of list offset, and the second is as a correction for the scrollers. 00484 */ 00485 height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2)); 00486 /* don't use totrect set, as the width stays the same 00487 * (NOTE: this is ok here, the configuration is pretty straightforward) 00488 */ 00489 v2d->tot.ymin= (float)(-height); 00490 00491 /* loop through channels, and set up drawing depending on their type */ 00492 y= (float)(-NLACHANNEL_HEIGHT); 00493 00494 for (ale= anim_data.first; ale; ale= ale->next) { 00495 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF); 00496 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF); 00497 00498 /* check if visible */ 00499 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || 00500 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 00501 { 00502 /* data to draw depends on the type of channel */ 00503 switch (ale->type) { 00504 case ANIMTYPE_NLATRACK: 00505 { 00506 AnimData *adt= ale->adt; 00507 NlaTrack *nlt= (NlaTrack *)ale->data; 00508 NlaStrip *strip; 00509 int index; 00510 00511 /* draw each strip in the track (if visible) */ 00512 for (strip=nlt->strips.first, index=1; strip; strip=strip->next, index++) { 00513 if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { 00514 /* draw the visualisation of the strip */ 00515 nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc); 00516 00517 /* add the text for this strip to the cache */ 00518 nla_draw_strip_text(nlt, strip, index, v2d, yminc, ymaxc); 00519 } 00520 } 00521 } 00522 break; 00523 00524 case ANIMTYPE_NLAACTION: 00525 { 00526 AnimData *adt= ale->adt; 00527 float color[4]; 00528 00529 /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, 00530 * and a second darker rect within which we draw keyframe indicator dots if there's data 00531 */ 00532 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00533 glEnable(GL_BLEND); 00534 00535 /* get colors for drawing */ 00536 nla_action_get_color(adt, ale->data, color); 00537 glColor4fv(color); 00538 00539 /* draw slightly shifted up for greater separation from standard channels, 00540 * but also slightly shorter for some more contrast when viewing the strips 00541 */ 00542 glRectf(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP); 00543 00544 /* draw keyframes in the action */ 00545 nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc+NLACHANNEL_SKIP, ymaxc-NLACHANNEL_SKIP); 00546 00547 /* draw 'embossed' lines above and below the strip for effect */ 00548 /* white base-lines */ 00549 glLineWidth(2.0f); 00550 glColor4f(1.0f, 1.0f, 1.0f, 0.3); 00551 fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP); 00552 fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP); 00553 00554 /* black top-lines */ 00555 glLineWidth(1.0f); 00556 glColor3f(0.0f, 0.0f, 0.0f); 00557 fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP); 00558 fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP); 00559 00560 glDisable(GL_BLEND); 00561 } 00562 break; 00563 } 00564 } 00565 00566 /* adjust y-position for next one */ 00567 y -= NLACHANNEL_STEP; 00568 } 00569 00570 /* free tempolary channels */ 00571 BLI_freelistN(&anim_data); 00572 } 00573 00574 /* *********************************************** */ 00575 /* Channel List */ 00576 00577 /* old code for drawing NLA channels using GL only */ 00578 // TODO: depreceate this code... 00579 static void draw_nla_channel_list_gl (bAnimContext *ac, ListBase *anim_data, View2D *v2d, float y) 00580 { 00581 bAnimListElem *ale; 00582 float x = 0.0f; 00583 00584 /* loop through channels, and set up drawing depending on their type */ 00585 for (ale= anim_data->first; ale; ale= ale->next) { 00586 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF); 00587 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF); 00588 const float ydatac= (float)(y - 7); 00589 00590 /* check if visible */ 00591 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || 00592 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 00593 { 00594 short indent= 0, offset= 0, sel= 0, group= 0; 00595 int expand= -1, protect = -1, special= -1, mute = -1; 00596 char name[128]; 00597 short doDraw=0; 00598 00599 /* determine what needs to be drawn */ 00600 switch (ale->type) { 00601 case ANIMTYPE_NLATRACK: /* NLA Track */ 00602 { 00603 NlaTrack *nlt= (NlaTrack *)ale->data; 00604 00605 indent= 0; 00606 00607 if (ale->id) { 00608 /* special exception for materials and particles */ 00609 if (ELEM(GS(ale->id->name),ID_MA,ID_PA)) { 00610 offset= 21; 00611 indent= 1; 00612 } 00613 else 00614 offset= 14; 00615 } 00616 else 00617 offset= 0; 00618 00619 /* FIXME: 'solo' as the 'special' button? 00620 * - need special icons for these 00621 */ 00622 if (nlt->flag & NLATRACK_SOLO) 00623 special= ICON_LAYER_ACTIVE; 00624 else 00625 special= ICON_LAYER_USED; 00626 00627 /* if this track is active and we're tweaking it, don't draw these toggles */ 00628 // TODO: need a special macro for this... 00629 if ( ((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0 ) 00630 { 00631 if (nlt->flag & NLATRACK_MUTED) 00632 mute = ICON_MUTE_IPO_ON; 00633 else 00634 mute = ICON_MUTE_IPO_OFF; 00635 00636 if (EDITABLE_NLT(nlt)) 00637 protect = ICON_UNLOCKED; 00638 else 00639 protect = ICON_LOCKED; 00640 } 00641 00642 sel = SEL_NLT(nlt); 00643 strcpy(name, nlt->name); 00644 00645 // draw manually still 00646 doDraw= 1; 00647 } 00648 break; 00649 case ANIMTYPE_NLAACTION: /* NLA Action-Line */ 00650 { 00651 bAction *act= (bAction *)ale->data; 00652 00653 group = 5; 00654 00655 if (ale->id) { 00656 /* special exception for materials and particles */ 00657 if (ELEM(GS(ale->id->name),ID_MA,ID_PA)) { 00658 offset= 21; 00659 indent= 1; 00660 } 00661 else 00662 offset= 14; 00663 } 00664 else 00665 offset= 0; 00666 00667 special = ICON_ACTION; 00668 00669 if (act) 00670 sprintf(name, "ActAction: <%s>", act->id.name+2); 00671 else 00672 sprintf(name, "<No Action>"); 00673 00674 // draw manually still 00675 doDraw= 1; 00676 } 00677 break; 00678 00679 default: /* handled by standard channel-drawing API */ 00680 // draw backdrops only... 00681 ANIM_channel_draw(ac, ale, yminc, ymaxc); 00682 break; 00683 } 00684 00685 /* if special types, draw manually for now... */ 00686 if (doDraw) { 00687 /* now, start drawing based on this information */ 00688 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00689 glEnable(GL_BLEND); 00690 00691 /* draw backing strip behind channel name */ 00692 if (group == 5) { 00693 /* Action Line */ 00694 AnimData *adt= ale->adt; 00695 00696 // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now) 00697 if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { 00698 // greenish color (same as tweaking strip) - hardcoded for now 00699 glColor3f(0.3f, 0.95f, 0.1f); 00700 } 00701 else { 00702 if (ale->data) 00703 glColor3f(0.8f, 0.2f, 0.0f); // reddish color - hardcoded for now 00704 else 00705 glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now 00706 } 00707 00708 offset += 7 * indent; 00709 00710 /* only on top two corners, to show that this channel sits on top of the preceding ones */ 00711 uiSetRoundBox((1|2)); 00712 00713 /* draw slightly shifted up vertically to look like it has more separtion from other channels, 00714 * but we then need to slightly shorten it so that it doesn't look like it overlaps 00715 */ 00716 uiDrawBox(GL_POLYGON, x+offset, yminc+NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc+NLACHANNEL_SKIP-1, 8); 00717 00718 /* clear group value, otherwise we cause errors... */ 00719 group = 0; 00720 } 00721 else { 00722 /* for normal channels 00723 * - use 3 shades of color group/standard color for 3 indention level 00724 */ 00725 UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40)); 00726 00727 indent += group; 00728 offset += 7 * indent; 00729 glBegin(GL_QUADS); 00730 glVertex2f(x+offset, yminc); 00731 glVertex2f(x+offset, ymaxc); 00732 glVertex2f((float)v2d->cur.xmax, ymaxc); 00733 glVertex2f((float)v2d->cur.xmax, yminc); 00734 glEnd(); 00735 } 00736 00737 /* draw expand/collapse triangle */ 00738 if (expand > 0) { 00739 UI_icon_draw(x+offset, ydatac, expand); 00740 offset += 17; 00741 } 00742 00743 /* draw special icon indicating certain data-types */ 00744 if (special > -1) { 00745 /* for normal channels */ 00746 UI_icon_draw(x+offset, ydatac, special); 00747 offset += 17; 00748 } 00749 glDisable(GL_BLEND); 00750 00751 /* draw name */ 00752 if (sel) 00753 UI_ThemeColor(TH_TEXT_HI); 00754 else 00755 UI_ThemeColor(TH_TEXT); 00756 offset += 3; 00757 UI_DrawString(x+offset, y-4, name); 00758 00759 /* reset offset - for RHS of panel */ 00760 offset = 0; 00761 00762 /* set blending again, as text drawing may clear it */ 00763 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00764 glEnable(GL_BLEND); 00765 00766 /* draw protect 'lock' */ 00767 if (protect > -1) { 00768 offset = 16; 00769 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, protect); 00770 } 00771 00772 /* draw mute 'eye' */ 00773 if (mute > -1) { 00774 offset += 16; 00775 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, mute); 00776 } 00777 00778 /* draw NLA-action line 'status-icons' - only when there's an action */ 00779 if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) { 00780 AnimData *adt= ale->adt; 00781 00782 offset += 16; 00783 00784 /* now draw some indicator icons */ 00785 if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { 00786 /* toggle for tweaking with mapping/no-mapping (i.e. 'in place editing' toggle) */ 00787 // for now, use pin icon to symbolise this 00788 if (adt->flag & ADT_NLA_EDIT_NOMAP) 00789 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_PINNED); 00790 else 00791 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_UNPINNED); 00792 00793 fdrawline((float)(v2d->cur.xmax-offset), yminc, 00794 (float)(v2d->cur.xmax-offset), ymaxc); 00795 offset += 16; 00796 00797 /* 'tweaking action' indicator - not a button */ 00798 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_EDIT); 00799 } 00800 else { 00801 /* XXX firstly draw a little rect to help identify that it's different from the toggles */ 00802 glBegin(GL_LINE_LOOP); 00803 glVertex2f((float)v2d->cur.xmax-offset-1, y-7); 00804 glVertex2f((float)v2d->cur.xmax-offset-1, y+9); 00805 glVertex2f((float)v2d->cur.xmax-1, y+9); 00806 glVertex2f((float)v2d->cur.xmax-1, y-7); 00807 glEnd(); // GL_LINES 00808 00809 /* 'push down' icon for normal active-actions */ 00810 UI_icon_draw((float)v2d->cur.xmax-offset, ydatac, ICON_FREEZE); 00811 } 00812 } 00813 00814 glDisable(GL_BLEND); 00815 } 00816 } 00817 00818 /* adjust y-position for next one */ 00819 y -= NLACHANNEL_STEP; 00820 } 00821 } 00822 00823 void draw_nla_channel_list (bContext *C, bAnimContext *ac, ARegion *ar) 00824 { 00825 ListBase anim_data = {NULL, NULL}; 00826 bAnimListElem *ale; 00827 int filter; 00828 00829 View2D *v2d= &ar->v2d; 00830 float y= 0.0f; 00831 int items, height; 00832 00833 /* build list of channels to draw */ 00834 filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS); 00835 items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); 00836 00837 /* Update max-extent of channels here (taking into account scrollers): 00838 * - this is done to allow the channel list to be scrollable, but must be done here 00839 * to avoid regenerating the list again and/or also because channels list is drawn first 00840 * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 00841 * start of list offset, and the second is as a correction for the scrollers. 00842 */ 00843 height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2)); 00844 /* don't use totrect set, as the width stays the same 00845 * (NOTE: this is ok here, the configuration is pretty straightforward) 00846 */ 00847 v2d->tot.ymin= (float)(-height); 00848 /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */ 00849 UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY); 00850 00851 /* draw channels */ 00852 { /* first pass: backdrops + oldstyle drawing */ 00853 y= (float)(-NLACHANNEL_HEIGHT); 00854 00855 draw_nla_channel_list_gl(ac, &anim_data, v2d, y); 00856 } 00857 { /* second pass: UI widgets */ 00858 uiBlock *block= uiBeginBlock(C, ar, "NLA channel buttons", UI_EMBOSS); 00859 00860 y= (float)(-NLACHANNEL_HEIGHT); 00861 00862 /* set blending again, as may not be set in previous step */ 00863 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 00864 glEnable(GL_BLEND); 00865 00866 /* loop through channels, and set up drawing depending on their type */ 00867 for (ale= anim_data.first; ale; ale= ale->next) { 00868 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF); 00869 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF); 00870 00871 /* check if visible */ 00872 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || 00873 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 00874 { 00875 /* draw all channels using standard channel-drawing API */ 00876 ANIM_channel_draw_widgets(ac, ale, block, yminc, ymaxc); 00877 } 00878 00879 /* adjust y-position for next one */ 00880 y -= NLACHANNEL_STEP; 00881 } 00882 00883 uiEndBlock(C, block); 00884 uiDrawBlock(C, block); 00885 00886 glDisable(GL_BLEND); 00887 } 00888 00889 /* free tempolary channels */ 00890 BLI_freelistN(&anim_data); 00891 } 00892 00893 /* *********************************************** */