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