4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
21 * All rights reserved.
24 * Contributor(s): Joshua Leung (major recode)
26 * ***** END GPL LICENSE BLOCK *****
35 #include "DNA_listBase.h"
36 #include "DNA_anim_types.h"
37 #include "DNA_action_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_camera_types.h"
40 #include "DNA_curve_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_screen_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_space_types.h"
45 #include "DNA_constraint_types.h"
46 #include "DNA_key_types.h"
47 #include "DNA_lamp_types.h"
48 #include "DNA_material_types.h"
49 #include "DNA_meta_types.h"
50 #include "DNA_particle_types.h"
51 #include "DNA_userdef_types.h"
52 #include "DNA_windowmanager_types.h"
53 #include "DNA_world_types.h"
54 #include "DNA_vec_types.h"
56 #include "MEM_guardedalloc.h"
58 #include "BLI_blenlib.h"
59 #include "BLI_arithb.h"
61 #include "BLI_dlrbTree.h"
63 #include "BKE_animsys.h"
64 #include "BKE_fcurve.h"
66 #include "BKE_context.h"
67 #include "BKE_screen.h"
68 #include "BKE_utildefines.h"
70 #include "ED_anim_api.h"
71 #include "ED_keyframes_draw.h"
72 #include "ED_space_api.h"
73 #include "ED_screen.h"
76 #include "BIF_glutil.h"
81 #include "UI_interface.h"
82 #include "UI_interface_icons.h"
83 #include "UI_resources.h"
84 #include "UI_view2d.h"
86 #include "ED_markers.h"
88 #include "nla_intern.h" // own include
91 extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
92 extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
94 /* *********************************************** */
97 /* Action-Line ---------------------- */
99 /* get colors for drawing Action-Line
100 * NOTE: color returned includes fine-tuned alpha!
102 static void nla_action_get_color (AnimData *adt, bAction *act, float color[4])
104 // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
105 if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
106 // greenish color (same as tweaking strip) - hardcoded for now
114 // reddish color - hardcoded for now
121 // greyish-red color - hardcoded for now
130 /* draw the keyframes in the specified Action */
131 static void nla_action_draw_keyframes (AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax)
135 float xscale, f1, f2;
138 /* get a list of the keyframes with NLA-scaling applied */
139 BLI_dlrbTree_init(&keys);
140 action_to_keylist(adt, act, &keys, NULL);
141 BLI_dlrbTree_linkedlist_sync(&keys);
143 if ELEM(NULL, act, keys.first)
146 /* draw a darkened region behind the strips
147 * - get and reset the background color, this time without the alpha to stand out better
149 nla_action_get_color(adt, act, color);
151 /* - draw a rect from the first to the last frame (no extra overlaps for now)
152 * that is slightly stumpier than the track background (hardcoded 2-units here)
154 f1= ((ActKeyColumn *)keys.first)->cfra;
155 f2= ((ActKeyColumn *)keys.last)->cfra;
157 glRectf(f1, ymin+2, f2, ymax-2);
160 /* get View2D scaling factor */
161 UI_view2d_getscale(v2d, &xscale, NULL);
163 /* for now, color is hardcoded to be black */
164 glColor3f(0.0f, 0.0f, 0.0f);
166 /* just draw each keyframe as a simple dot (regardless of the selection status)
167 * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
169 for (ak= keys.first; ak; ak= ak->next)
170 draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, KEYFRAME_SHAPE_FRAME);
173 BLI_dlrbTree_free(&keys);
176 /* Strips (Proper) ---------------------- */
178 /* get colors for drawing NLA-Strips */
179 static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float color[3])
181 if (strip->type == NLASTRIP_TYPE_TRANSITION) {
182 /* Transition Clip */
183 if (strip->flag & NLASTRIP_FLAG_SELECT) {
184 /* selected - use a bright blue color */
185 // FIXME: hardcoded temp-hack colors
191 /* normal, unselected strip - use (hardly noticable) blue tinge */
192 // FIXME: hardcoded temp-hack colors
198 else if (strip->type == NLASTRIP_TYPE_META) {
200 // TODO: should temporary metas get different colours too?
201 if (strip->flag & NLASTRIP_FLAG_SELECT) {
202 /* selected - use a bold purple color */
203 // FIXME: hardcoded temp-hack colors
209 /* normal, unselected strip - use (hardly noticable) dark purple tinge */
210 // FIXME: hardcoded temp-hack colors
217 /* Action Clip (default/normal type of strip) */
218 if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) {
219 /* active strip should be drawn green when it is acting as the tweaking strip.
220 * however, this case should be skipped for when not in EditMode...
222 // FIXME: hardcoded temp-hack colors
227 else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) {
228 /* alert user that this strip is also used by the tweaking track (this is set when going into
229 * 'editmode' for that strip), since the edits made here may not be what the user anticipated
231 // FIXME: hardcoded temp-hack colors
236 else if (strip->flag & NLASTRIP_FLAG_SELECT) {
237 /* selected strip - use theme color for selected */
238 UI_GetThemeColor3fv(TH_STRIP_SELECT, color);
241 /* normal, unselected strip - use standard strip theme color */
242 UI_GetThemeColor3fv(TH_STRIP, color);
247 /* helper call for drawing influence/time control curves for a given NLA-strip */
248 static void nla_draw_strip_curves (NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
250 const float yheight = ymaxc - yminc;
252 /* drawing color is simply a light-grey */
253 // TODO: is this color suitable?
254 // XXX nasty hacked color for now... which looks quite bad too...
255 glColor3f(0.7f, 0.7f, 0.7f);
257 /* draw with AA'd line */
258 glEnable(GL_LINE_SMOOTH);
261 /* influence -------------------------- */
262 if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
263 FCurve *fcu= list_find_fcurve(&strip->fcurves, "influence", 0);
266 /* plot the curve (over the strip's main region) */
267 glBegin(GL_LINE_STRIP);
268 /* sample at 1 frame intervals, and draw
269 * - min y-val is yminc, max is y-maxc, so clamp in those regions
271 for (cfra= strip->start; cfra <= strip->end; cfra += 1.0f) {
272 float y= evaluate_fcurve(fcu, cfra); // assume this to be in 0-1 range
273 glVertex2f(cfra, ((y*yheight)+yminc));
275 glEnd(); // GL_LINE_STRIP
278 /* use blend in/out values only if both aren't zero */
279 if ((IS_EQ(strip->blendin, 0.0f) && IS_EQ(strip->blendout, 0.0f))==0) {
280 glBegin(GL_LINE_STRIP);
281 /* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */
282 if (IS_EQ(strip->blendin, 0.0f) == 0) {
283 glVertex2f(strip->start, yminc);
284 glVertex2f(strip->start + strip->blendin, ymaxc);
287 glVertex2f(strip->start, ymaxc);
290 if (IS_EQ(strip->blendout, 0.0f) == 0) {
291 glVertex2f(strip->end - strip->blendout, ymaxc);
292 glVertex2f(strip->end, yminc);
295 glVertex2f(strip->end, ymaxc);
296 glEnd(); // GL_LINE_STRIP
300 /* time -------------------------- */
301 // XXX do we want to draw this curve? in a different colour too?
303 /* turn off AA'd lines */
304 glDisable(GL_LINE_SMOOTH);
308 /* main call for drawing a single NLA-strip */
309 static void nla_draw_strip (SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
313 /* get color of strip */
314 nla_strip_get_color_inside(adt, strip, color);
316 /* draw extrapolation info first (as backdrop) */
317 if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
318 /* enable transparency... */
319 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
322 switch (strip->extendmode) {
323 /* since this does both sides, only do the 'before' side, and leave the rest to the next case */
324 case NLASTRIP_EXTEND_HOLD:
325 /* only need to draw here if there's no strip before since
326 * it only applies in such a situation
328 if (strip->prev == NULL) {
329 /* set the drawing color to the color of the strip, but with very faint alpha */
330 glColor4f(color[0], color[1], color[2], 0.15f);
332 /* draw the rect to the edge of the screen */
334 glVertex2f(v2d->cur.xmin, yminc);
335 glVertex2f(v2d->cur.xmin, ymaxc);
336 glVertex2f(strip->start, ymaxc);
337 glVertex2f(strip->start, yminc);
340 /* no break needed... */
342 /* this only draws after the strip */
343 case NLASTRIP_EXTEND_HOLD_FORWARD:
344 /* only need to try and draw if the next strip doesn't occur immediately after */
345 if ((strip->next == NULL) || (IS_EQ(strip->next->start, strip->end)==0)) {
346 /* set the drawing color to the color of the strip, but this time less faint */
347 glColor4f(color[0], color[1], color[2], 0.3f);
349 /* draw the rect to the next strip or the edge of the screen */
351 glVertex2f(strip->end, yminc);
352 glVertex2f(strip->end, ymaxc);
355 glVertex2f(strip->next->start, ymaxc);
356 glVertex2f(strip->next->start, yminc);
359 glVertex2f(v2d->cur.xmax, ymaxc);
360 glVertex2f(v2d->cur.xmax, yminc);
370 /* draw 'inside' of strip itself */
372 uiSetRoundBox(15); /* all corners rounded */
373 gl_round_box_shade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
376 /* draw strip's control 'curves'
377 * - only if user hasn't hidden them...
379 if ((snla->flag & SNLA_NOSTRIPCURVES) == 0)
380 nla_draw_strip_curves(strip, v2d, yminc, ymaxc);
382 /* draw strip outline
383 * - color used here is to indicate active vs non-active
385 if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
386 /* strip should appear 'sunken', so draw a light border around it */
387 glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors
390 /* strip should appear to stand out, so draw a dark border around it */
391 glColor3f(0.0f, 0.0f, 0.0f);
394 /* - line style: dotted for muted */
395 if (strip->flag & NLASTRIP_FLAG_MUTED)
399 gl_round_box_shade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
401 /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */
402 if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQ(strip->repeat, 1.0f)==0) {
403 float repeatLen = (strip->actend - strip->actstart) * strip->scale;
406 /* only draw lines for whole-numbered repeats, starting from the first full-repeat
407 * up to the last full repeat (but not if it lies on the end of the strip)
409 for (i = 1; i < strip->repeat; i++) {
410 float repeatPos = strip->start + (repeatLen * i);
412 /* don't draw if line would end up on or after the end of the strip */
413 if (repeatPos < strip->end)
414 fdrawline(repeatPos, yminc+4, repeatPos, ymaxc-4);
417 /* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */
418 else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) {
420 float y= (ymaxc-yminc)/2.0f + yminc;
422 /* only draw first-level of child-strips, but don't draw any lines on the endpoints */
423 for (cs= strip->strips.first; cs; cs= cs->next) {
424 /* draw start-line if not same as end of previous (and only if not the first strip)
425 * - on upper half of strip
427 if ((cs->prev) && IS_EQ(cs->prev->end, cs->start)==0)
428 fdrawline(cs->start, y, cs->start, ymaxc);
430 /* draw end-line if not the last strip
431 * - on lower half of strip
434 fdrawline(cs->end, yminc, cs->end, y);
438 /* reset linestyle */
442 /* add the relevant text to the cache of text-strings to draw in pixelspace */
443 static void nla_draw_strip_text (NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc)
445 char str[256], dir[3];
448 /* 'dir' - direction that strip is played in */
449 if (strip->flag & NLASTRIP_FLAG_REVERSE)
454 /* just print the name and the range */
455 if (strip->flag & NLASTRIP_FLAG_TEMP_META)
456 sprintf(str, "Temp-Meta | %.2f %s %.2f", strip->start, dir, strip->end);
458 sprintf(str, "%s | %.2f %s %.2f", strip->name, strip->start, dir, strip->end);
460 /* set text colour - if colours (see above) are light, draw black text, otherwise draw white */
461 if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER))
462 glColor3f(0.0f, 0.0f, 0.0f);
464 glColor3f(1.0f, 1.0f, 1.0f);
466 /* set bounding-box for text
467 * - padding of 2 'units' on either side
469 // TODO: make this centered?
470 rect.xmin= strip->start + 0.5f;
472 rect.xmax= strip->end - 0.5f;
475 /* add this string to the cache of texts to draw*/
476 UI_view2d_text_cache_rectf(v2d, &rect, str);
479 /* ---------------------- */
481 void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
483 ListBase anim_data = {NULL, NULL};
487 View2D *v2d= &ar->v2d;
491 /* build list of channels to draw */
492 filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
493 items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
495 /* Update max-extent of channels here (taking into account scrollers):
496 * - this is done to allow the channel list to be scrollable, but must be done here
497 * to avoid regenerating the list again and/or also because channels list is drawn first
498 * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
499 * start of list offset, and the second is as a correction for the scrollers.
501 height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2));
502 /* don't use totrect set, as the width stays the same
503 * (NOTE: this is ok here, the configuration is pretty straightforward)
505 v2d->tot.ymin= (float)(-height);
506 /* need to do a view-sync here, so that the strips area doesn't jump around */
507 UI_view2d_sync(NULL, ac->sa, v2d, V2D_VIEWSYNC_AREA_VERTICAL);
509 /* loop through channels, and set up drawing depending on their type */
510 y= (float)(-NLACHANNEL_HEIGHT);
512 for (ale= anim_data.first; ale; ale= ale->next) {
513 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF);
514 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF);
516 /* check if visible */
517 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
518 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
520 /* data to draw depends on the type of channel */
522 case ANIMTYPE_NLATRACK:
524 AnimData *adt= ale->adt;
525 NlaTrack *nlt= (NlaTrack *)ale->data;
529 /* draw each strip in the track (if visible) */
530 for (strip=nlt->strips.first, index=1; strip; strip=strip->next, index++) {
531 if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
532 /* draw the visualisation of the strip */
533 nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc);
535 /* add the text for this strip to the cache */
536 nla_draw_strip_text(nlt, strip, index, v2d, yminc, ymaxc);
542 case ANIMTYPE_NLAACTION:
544 AnimData *adt= ale->adt;
547 /* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
548 * and a second darker rect within which we draw keyframe indicator dots if there's data
550 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
553 /* get colors for drawing */
554 nla_action_get_color(adt, ale->data, color);
557 /* draw slightly shifted up for greater separation from standard channels,
558 * but also slightly shorter for some more contrast when viewing the strips
560 glRectf(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
562 /* draw keyframes in the action */
563 nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc+NLACHANNEL_SKIP, ymaxc-NLACHANNEL_SKIP);
565 /* draw 'embossed' lines above and below the strip for effect */
566 /* white base-lines */
568 glColor4f(1.0f, 1.0f, 1.0f, 0.3);
569 fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP);
570 fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
572 /* black top-lines */
574 glColor3f(0.0f, 0.0f, 0.0f);
575 fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP);
576 fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
584 /* adjust y-position for next one */
585 y -= NLACHANNEL_STEP;
588 /* free tempolary channels */
589 BLI_freelistN(&anim_data);
592 /* *********************************************** */
595 /* old code for drawing NLA channels using GL only */
596 // TODO: depreceate this code...
597 static void draw_nla_channel_list_gl (bAnimContext *ac, ListBase *anim_data, View2D *v2d, float y)
602 /* loop through channels, and set up drawing depending on their type */
603 for (ale= anim_data->first; ale; ale= ale->next) {
604 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF);
605 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF);
606 const float ydatac= (float)(y - 7);
608 /* check if visible */
609 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
610 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
612 short indent= 0, offset= 0, sel= 0, group= 0;
613 int expand= -1, protect = -1, special= -1, mute = -1;
617 /* determine what needs to be drawn */
619 case ANIMTYPE_NLATRACK: /* NLA Track */
621 NlaTrack *nlt= (NlaTrack *)ale->data;
626 /* special exception for materials and particles */
627 if (ELEM(GS(ale->id->name),ID_MA,ID_PA)) {
637 /* FIXME: 'solo' as the 'special' button?
638 * - need special icons for these
640 if (nlt->flag & NLATRACK_SOLO)
641 special= ICON_LAYER_ACTIVE;
643 special= ICON_LAYER_USED;
645 /* if this track is active and we're tweaking it, don't draw these toggles */
646 // TODO: need a special macro for this...
647 if ( ((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0 )
649 if (nlt->flag & NLATRACK_MUTED)
650 mute = ICON_MUTE_IPO_ON;
652 mute = ICON_MUTE_IPO_OFF;
654 if (EDITABLE_NLT(nlt))
655 protect = ICON_UNLOCKED;
657 protect = ICON_LOCKED;
661 strcpy(name, nlt->name);
663 // draw manually still
667 case ANIMTYPE_NLAACTION: /* NLA Action-Line */
669 bAction *act= (bAction *)ale->data;
674 /* special exception for materials and particles */
675 if (ELEM(GS(ale->id->name),ID_MA,ID_PA)) {
685 special = ICON_ACTION;
688 sprintf(name, "ActAction: <%s>", act->id.name+2);
690 sprintf(name, "<No Action>");
692 // draw manually still
697 default: /* handled by standard channel-drawing API */
698 // draw backdrops only...
699 ANIM_channel_draw(ac, ale, yminc, ymaxc);
703 /* if special types, draw manually for now... */
705 /* now, start drawing based on this information */
706 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
709 /* draw backing strip behind channel name */
712 AnimData *adt= ale->adt;
714 // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
715 if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
716 // greenish color (same as tweaking strip) - hardcoded for now
717 glColor3f(0.3f, 0.95f, 0.1f);
721 glColor3f(0.8f, 0.2f, 0.0f); // reddish color - hardcoded for now
723 glColor3f(0.6f, 0.5f, 0.5f); // greyish-red color - hardcoded for now
726 offset += 7 * indent;
728 /* only on top two corners, to show that this channel sits on top of the preceeding ones */
729 uiSetRoundBox((1|2));
731 /* draw slightly shifted up vertically to look like it has more separtion from other channels,
732 * but we then need to slightly shorten it so that it doesn't look like it overlaps
734 gl_round_box(GL_POLYGON, x+offset, yminc+NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc+NLACHANNEL_SKIP-1, 8);
736 /* clear group value, otherwise we cause errors... */
740 /* for normal channels
741 * - use 3 shades of color group/standard color for 3 indention level
743 UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
746 offset += 7 * indent;
748 glVertex2f(x+offset, yminc);
749 glVertex2f(x+offset, ymaxc);
750 glVertex2f((float)v2d->cur.xmax, ymaxc);
751 glVertex2f((float)v2d->cur.xmax, yminc);
755 /* draw expand/collapse triangle */
757 UI_icon_draw(x+offset, ydatac, expand);
761 /* draw special icon indicating certain data-types */
763 /* for normal channels */
764 UI_icon_draw(x+offset, ydatac, special);
771 UI_ThemeColor(TH_TEXT_HI);
773 UI_ThemeColor(TH_TEXT);
775 UI_DrawString(x+offset, y-4, name);
777 /* reset offset - for RHS of panel */
780 /* set blending again, as text drawing may clear it */
781 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
784 /* draw protect 'lock' */
787 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, protect);
790 /* draw mute 'eye' */
793 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, mute);
796 /* draw NLA-action line 'status-icons' - only when there's an action */
797 if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) {
798 AnimData *adt= ale->adt;
802 /* now draw some indicator icons */
803 if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
804 /* toggle for tweaking with mapping/no-mapping (i.e. 'in place editing' toggle) */
805 // for now, use pin icon to symbolise this
806 if (adt->flag & ADT_NLA_EDIT_NOMAP)
807 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_PINNED);
809 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_UNPINNED);
811 fdrawline((float)(v2d->cur.xmax-offset), yminc,
812 (float)(v2d->cur.xmax-offset), ymaxc);
815 /* 'tweaking action' indicator - not a button */
816 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_EDIT);
819 /* XXX firstly draw a little rect to help identify that it's different from the toggles */
820 glBegin(GL_LINE_LOOP);
821 glVertex2f((float)v2d->cur.xmax-offset-1, y-7);
822 glVertex2f((float)v2d->cur.xmax-offset-1, y+9);
823 glVertex2f((float)v2d->cur.xmax-1, y+9);
824 glVertex2f((float)v2d->cur.xmax-1, y-7);
827 /* 'push down' icon for normal active-actions */
828 UI_icon_draw((float)NLACHANNEL_NAMEWIDTH-offset, ydatac, ICON_FREEZE);
836 /* adjust y-position for next one */
837 y -= NLACHANNEL_STEP;
841 void draw_nla_channel_list (bContext *C, bAnimContext *ac, SpaceNla *snla, ARegion *ar)
843 ListBase anim_data = {NULL, NULL};
847 View2D *v2d= &ar->v2d;
851 /* build list of channels to draw */
852 filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
853 items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
855 /* Update max-extent of channels here (taking into account scrollers):
856 * - this is done to allow the channel list to be scrollable, but must be done here
857 * to avoid regenerating the list again and/or also because channels list is drawn first
858 * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
859 * start of list offset, and the second is as a correction for the scrollers.
861 height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2));
862 /* don't use totrect set, as the width stays the same
863 * (NOTE: this is ok here, the configuration is pretty straightforward)
865 v2d->tot.ymin= (float)(-height);
868 { /* first pass: backdrops + oldstyle drawing */
869 y= (float)(-NLACHANNEL_HEIGHT);
871 draw_nla_channel_list_gl(ac, &anim_data, v2d, y);
873 { /* second pass: UI widgets */
874 uiBlock *block= uiBeginBlock(C, ar, "NLA channel buttons", UI_EMBOSS);
876 y= (float)(-NLACHANNEL_HEIGHT);
878 /* set blending again, as may not be set in previous step */
879 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
882 /* loop through channels, and set up drawing depending on their type */
883 for (ale= anim_data.first; ale; ale= ale->next) {
884 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF);
885 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF);
887 /* check if visible */
888 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
889 IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
891 /* draw all channels using standard channel-drawing API */
892 ANIM_channel_draw_widgets(ac, ale, block, yminc, ymaxc);
895 /* adjust y-position for next one */
896 y -= NLACHANNEL_STEP;
899 uiEndBlock(C, block);
900 uiDrawBlock(C, block);
905 /* free tempolary channels */
906 BLI_freelistN(&anim_data);
909 /* *********************************************** */