Ejemplo n.º 1
0
void clip_draw_cfra(SpaceClip *sc, ARegion *ar, Scene *scene)
{
	View2D *v2d = &ar->v2d;
	float xscale, yscale;
	float vec[2];

	/* Draw a light green line to indicate current frame */
	vec[0] = (float)(sc->user.framenr * scene->r.framelen);

	UI_ThemeColor(TH_CFRAME);
	glLineWidth(2.0);

	glBegin(GL_LINE_STRIP);
	vec[1] = v2d->cur.ymin;
	glVertex2fv(vec);

	vec[1] = v2d->cur.ymax;
	glVertex2fv(vec);
	glEnd();

	glLineWidth(1.0);

	UI_view2d_view_orthoSpecial(ar, v2d, 1);

	/* because the frame number text is subject to the same scaling as the contents of the view */
	UI_view2d_getscale(v2d, &xscale, &yscale);
	glScalef(1.0f / xscale, 1.0f, 1.0f);

	clip_draw_curfra_label(sc->user.framenr, (float)sc->user.framenr * xscale, 18);

	/* restore view transform */
	glScalef(xscale, 1.0, 1.0);
}
Ejemplo n.º 2
0
/* helper func - draw keyframe vertices only for an F-Curve */
static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
{
	FPoint *first, *last;
	float hsize, xscale, yscale;
	
	/* get view settings */
	hsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
	UI_view2d_getscale(&ar->v2d, &xscale, &yscale);
	
	/* set vertex color */
	if (fcu->flag & (FCURVE_ACTIVE | FCURVE_SELECTED)) UI_ThemeColor(TH_TEXT_HI);
	else UI_ThemeColor(TH_TEXT);
	
	/* get verts */
	first = fcu->fpt;
	last = (first) ? (first + (fcu->totvert - 1)) : (NULL);
	
	/* draw */
	if (first && last) {
		/* anti-aliased lines for more consistent appearance */
		if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
		glEnable(GL_BLEND);
		
		draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize);
		draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize);
		
		glDisable(GL_BLEND);
		if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
	}
}
Ejemplo n.º 3
0
static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
{
	MovieClip *clip= ED_space_clip(sc);
	MovieTracking *tracking= &clip->tracking;
	MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
	int width, height;
	struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } userdata;

	BKE_movieclip_get_size(clip, &sc->user, &width, &height);

	if(!width || !height)
		return;

	/* non-selected knot handles */
	userdata.hsize= UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
	userdata.sel= 0;
	userdata.act_track= act_track;
	UI_view2d_getscale(v2d, &userdata.xscale, &userdata.yscale);
	clip_graph_tracking_values_iterate(sc, &userdata, tracking_segment_knot_cb, NULL, NULL);

	/* draw graph lines */
	glEnable(GL_BLEND);
	clip_graph_tracking_values_iterate(sc, act_track, tracking_segment_point_cb, tracking_segment_start_cb, tracking_segment_end_cb);
	glDisable(GL_BLEND);

	/* selected knot handles on top of curves */
	userdata.sel= 1;
	clip_graph_tracking_values_iterate(sc, &userdata, tracking_segment_knot_cb, NULL, NULL);
}
Ejemplo n.º 4
0
void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *ar, float *scalex, float *scaley)
{
	if (sa && sa->spacedata.first) {
		switch (sa->spacetype) {
			case SPACE_CLIP:
			{
				SpaceClip *sc = sa->spacedata.first;
				float aspx, aspy;

				UI_view2d_getscale(&ar->v2d, scalex, scaley);
				ED_space_clip_get_aspect(sc, &aspx, &aspy);

				*scalex *= aspx;
				*scaley *= aspy;
				break;
			}
			case SPACE_SEQ:
			{
				*scalex = *scaley = 1.0f;  /* MASKTODO? */
				break;
			}
			case SPACE_IMAGE:
			{
				SpaceImage *sima = sa->spacedata.first;
				float aspx, aspy;

				UI_view2d_getscale(&ar->v2d, scalex, scaley);
				ED_space_image_get_aspect(sima, &aspx, &aspy);

				*scalex *= aspx;
				*scaley *= aspy;
				break;
			}
			default:
				/* possible other spaces from which mask editing is available */
				BLI_assert(0);
				*scalex = *scaley = 1.0f;
				break;
		}
	}
	else {
		BLI_assert(0);
		*scalex = *scaley = 1.0f;
	}
}
Ejemplo n.º 5
0
/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2d, short sel, short sel_handle_only, float units_scale)
{
	BezTriple *bezt = fcu->bezt;
	BezTriple *prevbezt = NULL;
	float hsize, xscale, yscale;
	int i;
	
	/* get view settings */
	hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
	UI_view2d_getscale(v2d, &xscale, &yscale);

	/* Compensate OGL scale sued for unit mapping, so circle will be circle, not ellipse */
	yscale *= units_scale;
	
	/* set handle color */
	if (sel) UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
	else UI_ThemeColor(TH_HANDLE_VERTEX);
	
	/* anti-aliased lines for more consistent appearance */
	if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
	glEnable(GL_BLEND);
	
	for (i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) {
		/* Draw the editmode handles for a bezier curve (others don't have handles) 
		 * if their selection status matches the selection status we're drawing for
		 *	- first handle only if previous beztriple was bezier-mode
		 *	- second handle only if current beztriple is bezier-mode
		 *
		 * Also, need to take into account whether the keyframe was selected
		 * if a Graph Editor option to only show handles of selected keys is on.
		 */
		if (!sel_handle_only || BEZSELECTED(bezt)) {
			if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
				if ((bezt->f1 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/
					draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize);
			}
			
			if (bezt->ipo == BEZT_IPO_BEZ) {
				if ((bezt->f3 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/
					draw_fcurve_handle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize);
			}
		}
	}
	
	if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
	glDisable(GL_BLEND);
}
Ejemplo n.º 6
0
/* draw the keyframes in the specified Action */
static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax)
{
	DLRBT_Tree keys;
	ActKeyColumn *ak;
	float xscale, f1, f2;
	float color[4];
	
	/* get a list of the keyframes with NLA-scaling applied */
	BLI_dlrbTree_init(&keys);
	action_to_keylist(adt, act, &keys, NULL);
	BLI_dlrbTree_linkedlist_sync(&keys);
	
	if (ELEM(NULL, act, keys.first))
		return;
	
	/* draw a darkened region behind the strips 
	 *	- get and reset the background color, this time without the alpha to stand out better 
	 *	  (amplified alpha is used instead)
	 */
	nla_action_get_color(adt, act, color);
	color[3] *= 2.5f;
	
	glColor4fv(color);
	/*  - draw a rect from the first to the last frame (no extra overlaps for now)
	 *	  that is slightly stumpier than the track background (hardcoded 2-units here)
	 */
	f1 = ((ActKeyColumn *)keys.first)->cfra;
	f2 = ((ActKeyColumn *)keys.last)->cfra;
	
	glRectf(f1, ymin + 2, f2, ymax - 2);
	
	
	/* get View2D scaling factor */
	UI_view2d_getscale(v2d, &xscale, NULL);
	
	/* for now, color is hardcoded to be black */
	glColor3f(0.0f, 0.0f, 0.0f);
	
	/* just draw each keyframe as a simple dot (regardless of the selection status) 
	 *	- size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
	 */
	for (ak = keys.first; ak; ak = ak->next)
		draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f);
	
	/* free icons */
	BLI_dlrbTree_free(&keys);
}
Ejemplo n.º 7
0
static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
{
	MovieClip *clip = ED_space_clip_get_clip(sc);
	MovieTracking *tracking = &clip->tracking;
	MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
	int width, height;
	TrackMotionCurveUserData userdata;

	BKE_movieclip_get_size(clip, &sc->user, &width, &height);

	if (!width || !height)
		return;

	/* non-selected knot handles */
	userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
	userdata.sel = false;
	userdata.act_track = act_track;
	UI_view2d_getscale(v2d, &userdata.xscale, &userdata.yscale);
	clip_graph_tracking_values_iterate(sc,
	                                   (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
	                                   (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
	                                   &userdata, tracking_segment_knot_cb, NULL, NULL);

	/* draw graph lines */
	glEnable(GL_BLEND);
	clip_graph_tracking_values_iterate(sc,
	                                   (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
	                                   (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
	                                   act_track, tracking_segment_point_cb, tracking_segment_start_cb,
	                                   tracking_segment_end_cb);
	glDisable(GL_BLEND);

	/* selected knot handles on top of curves */
	userdata.sel = TRUE;
	clip_graph_tracking_values_iterate(sc,
	                                   (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
	                                   (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
	                                   &userdata, tracking_segment_knot_cb, NULL, NULL);
}
Ejemplo n.º 8
0
/* Draw current frame number in a little green box beside the current frame indicator */
static void draw_cfra_number(Scene *scene, View2D *v2d, float cfra, short time)
{
	float xscale, yscale, x, y;
	char numstr[32] = "    t";  /* t is the character to start replacing from */
	short slen;
	
	/* because the frame number text is subject to the same scaling as the contents of the view */
	UI_view2d_getscale(v2d, &xscale, &yscale);
	glScalef(1.0f / xscale, 1.0f, 1.0f);
	
	/* get timecode string 
	 *	- padding on str-buf passed so that it doesn't sit on the frame indicator
	 *	- power = 0, gives 'standard' behavior for time
	 *	  but power = 1 is required for frames (to get integer frames)
	 */
	if (time)
		ANIM_timecode_string_from_frame(&numstr[4], scene, 0, time, FRA2TIME(cfra));
	else
		ANIM_timecode_string_from_frame(&numstr[4], scene, 1, time, cfra);
	slen = (short)UI_GetStringWidth(numstr) - 1;
	
	/* get starting coordinates for drawing */
	x = cfra * xscale;
	y = 0.9f * U.widget_unit;
	
	/* draw green box around/behind text */
	UI_ThemeColorShade(TH_CFRAME, 0);
	glRectf(x, y,  x + slen,  y + 0.75f * U.widget_unit);
	
	/* draw current frame number - black text */
	UI_ThemeColor(TH_TEXT);
	UI_DrawString(x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr);
	
	/* restore view transform */
	glScalef(xscale, 1.0, 1.0);
}
Ejemplo n.º 9
0
/* function to draw markers */
static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
{
	float xpos, ypixels, xscale, yscale;
	int icon_id = 0;
	
	xpos = marker->frame;
	
	/* no time correction for framelen! space is drawn with old values */
	ypixels = BLI_rcti_size_y(&v2d->mask);
	UI_view2d_getscale(v2d, &xscale, &yscale);
	
	glScalef(1.0f / xscale, 1.0f, 1.0f);
	
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	
	/* vertical line - dotted */
#ifdef DURIAN_CAMERA_SWITCH
	if ((marker->camera) || (flag & DRAW_MARKERS_LINES))
#else
	if (flag & DRAW_MARKERS_LINES)
#endif
	{
		setlinestyle(3);
		
		if (marker->flag & SELECT)
			glColor4ub(255, 255, 255, 96);
		else
			glColor4ub(0, 0, 0, 96);
		
		glBegin(GL_LINES);
		glVertex2f((xpos * xscale) + 0.5f, 12.0f);
		glVertex2f((xpos * xscale) + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
		glEnd();
		
		setlinestyle(0);
	}
	
	/* 5 px to offset icon to align properly, space / pixels corrects for zoom */
	if (flag & DRAW_MARKERS_LOCAL) {
		icon_id = (marker->flag & ACTIVE) ? ICON_PMARKER_ACT :
		          (marker->flag & SELECT) ? ICON_PMARKER_SEL :
		          ICON_PMARKER;
	}
	else {
		icon_id = (marker->flag & SELECT) ? ICON_MARKER_HLT :
		          ICON_MARKER;
	}
	
	UI_icon_draw(xpos * xscale - 0.45f * UI_DPI_ICON_SIZE, UI_DPI_ICON_SIZE, icon_id);
	
	glDisable(GL_BLEND);
	
	/* and the marker name too, shifted slightly to the top-right */
	if (marker->name && marker->name[0]) {
		float x, y;

		/* minimal y coordinate which wouldn't be occluded by scroll */
		int min_y = 17.0f * UI_DPI_FAC;
		
		if (marker->flag & SELECT) {
			UI_ThemeColor(TH_TEXT_HI);
			x = xpos * xscale + 4.0f * UI_DPI_FAC;
			y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
			y = max_ii(y, min_y);
		}
		else {
			UI_ThemeColor(TH_TEXT);
			if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) {
				x = xpos * xscale + 8.0f * UI_DPI_FAC;
				y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
				y = max_ii(y, min_y);
			}
			else {
				x = xpos * xscale + 8.0f * UI_DPI_FAC;
				y = 17.0f * UI_DPI_FAC;
			}
		}

#ifdef DURIAN_CAMERA_SWITCH
		if (marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) {
			float col[4];
			glGetFloatv(GL_CURRENT_COLOR, col);
			col[3] = 0.4;
			glColor4fv(col);
		}
#endif

		UI_DrawString(x, y, marker->name);
	}
	
	glScalef(xscale, 1.0f, 1.0f);
}
Ejemplo n.º 10
0
/* function to draw markers */
static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
{
	float xpos, ypixels, xscale, yscale;
	int icon_id= 0;
	
	xpos = marker->frame;
	
	/* no time correction for framelen! space is drawn with old values */
	ypixels= v2d->mask.ymax-v2d->mask.ymin;
	UI_view2d_getscale(v2d, &xscale, &yscale);
	
	glScalef(1.0f/xscale, 1.0f, 1.0f);
	
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);			
	
	/* vertical line - dotted */
	// NOTE: currently only used for sequencer 
	if (flag & DRAW_MARKERS_LINES) {
		setlinestyle(3);
		
		if (marker->flag & SELECT)
			glColor4ub(255, 255, 255, 96);
		else
			glColor4ub(0, 0, 0, 96);
		
		glBegin(GL_LINES);
			glVertex2f((xpos*xscale)+0.5f, 12.0f);
			glVertex2f((xpos*xscale)+0.5f, 34.0f*yscale); /* a bit lazy but we know it cant be greater then 34 strips high */
		glEnd();
		
		setlinestyle(0);
	}
	
	/* 5 px to offset icon to align properly, space / pixels corrects for zoom */
	if (flag & DRAW_MARKERS_LOCAL) {
		icon_id= (marker->flag & ACTIVE) ? ICON_PMARKER_ACT : 
		(marker->flag & SELECT) ? ICON_PMARKER_SEL : 
		ICON_PMARKER;
	}
	else {
		icon_id= (marker->flag & SELECT) ? ICON_MARKER_HLT : 
		ICON_MARKER;
	}
	
	UI_icon_draw(xpos*xscale-5.0f, 16.0f, icon_id);
	
	glBlendFunc(GL_ONE, GL_ZERO);
	glDisable(GL_BLEND);
	
	/* and the marker name too, shifted slightly to the top-right */
	if (marker->name && marker->name[0]) {
		float x, y;
		
		if (marker->flag & SELECT) {
			UI_ThemeColor(TH_TEXT_HI);
			x= xpos*xscale + 4.0f;
			y= (ypixels <= 39.0f)? (ypixels-10.0f) : 29.0f;
		}
		else {
			UI_ThemeColor(TH_TEXT);
			if((marker->frame <= cfra) && (marker->frame+5 > cfra)) {
				x= xpos*xscale + 4.0f;
				y= (ypixels <= 39.0f)? (ypixels - 10.0f) : 29.0f;
			}
			else {
				x= xpos*xscale + 4.0f;
				y= 17.0f;
			}
		}
		UI_DrawString(x, y, marker->name);
	}
	
	glScalef(xscale, 1.0f, 1.0f);
}
Ejemplo n.º 11
0
void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
{
	MovieClip *clip = ED_space_clip_get_clip(sc);
	View2D *v2d = &ar->v2d;

	/* frame range */
	clip_draw_sfra_efra(v2d, scene);

	if (clip) {
		MovieTracking *tracking = &clip->tracking;
		MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
		MovieTrackingDopesheetChannel *channel;
		float y, xscale, yscale;
		float strip[4], selected_strip[4];
		float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);

		/* don't use totrect set, as the width stays the same
		 * (NOTE: this is ok here, the configuration is pretty straightforward)
		 */
		v2d->tot.ymin = (float)(-height);

		y = (float) CHANNEL_FIRST;

		UI_view2d_getscale(v2d, &xscale, &yscale);

		/* setup colors for regular and selected strips */
		UI_GetThemeColor3fv(TH_STRIP, strip);
		UI_GetThemeColor3fv(TH_STRIP_SELECT, selected_strip);

		strip[3] = 0.5f;
		selected_strip[3] = 1.0f;

		glEnable(GL_BLEND);

		clip_draw_dopesheet_background(ar, clip);

		for (channel = dopesheet->channels.first; channel; channel = channel->next) {
			float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
			float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);

			/* check if visible */
			if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
			    IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
			{
				MovieTrackingTrack *track = channel->track;
				float alpha;
				int i, sel = track->flag & TRACK_DOPE_SEL;

				/* selection background */
				if (sel) {
					float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
					float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f};

					track_channel_color(track, default_color, color);
					glColor4fv(color);

					glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
					        v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
				}

				alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f;

				/* tracked segments */
				for (i = 0; i < channel->tot_segment; i++) {
					int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]);
					int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]);

					if (sel)
						glColor4fv(selected_strip);
					else
						glColor4fv(strip);

					if (start_frame != end_frame) {
						glRectf(start_frame, (float) y - STRIP_HEIGHT_HALF,
						        end_frame, (float) y + STRIP_HEIGHT_HALF);
						draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha);
						draw_keyframe_shape(end_frame, y, xscale, yscale, sel, alpha);
					}
					else {
						draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha);
					}
				}

				/* keyframes */
				i = 0;
				while (i < track->markersnr) {
					MovieTrackingMarker *marker = &track->markers[i];

					if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
						int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);

						draw_keyframe_shape(framenr, y, xscale, yscale, sel, alpha);
					}

					i++;
				}
			}

			/* adjust y-position for next one */
			y -= CHANNEL_STEP;
		}

		glDisable(GL_BLEND);
	}

	/* current frame */
	clip_draw_cfra(sc, ar, scene);
}
Ejemplo n.º 12
0
/* Draw current frame number in a little green box beside the current frame indicator */
static void draw_cfra_number (Scene *scene, View2D *v2d, float cfra, short time)
{
    float xscale, yscale, x, y;
    char str[32];
    short slen;

    /* because the frame number text is subject to the same scaling as the contents of the view */
    UI_view2d_getscale(v2d, &xscale, &yscale);
    glScalef(1.0f/xscale, 1.0f, 1.0f);

    if (time) {
        /* Timecode:
         *	- In general, minutes and seconds should be shown, as most clips will be
         *	  within this length. Hours will only be included if relevant.
         *	- Only show frames when zoomed in enough for them to be relevant
         *	  (using separator of '!' for frames).
         *	  When showing frames, use slightly different display to avoid confusion with mm:ss format
         * TODO: factor into reusable function.
         * Meanwhile keep in sync:
         *	  source/blender/editors/animation/anim_draw.c
         *	  source/blender/editors/interface/view2d.c
         */
        float val= FRA2TIME(CFRA);
        int hours=0, minutes=0, seconds=0, frames=0;
        char neg[2]= "";

        /* get values */
        if (val < 0) {
            /* correction for negative values */
            sprintf(neg, "-");
            val = -val;
        }
        if (val >= 3600) {
            /* hours */
            /* XXX should we only display a single digit for hours since clips are
             * 	   VERY UNLIKELY to be more than 1-2 hours max? However, that would
             *	   go against conventions...
             */
            hours= (int)val / 3600;
            val= (float)fmod(val, 3600);
        }
        if (val >= 60) {
            /* minutes */
            minutes= (int)val / 60;
            val= (float)fmod(val, 60);
        }
        {
            /* seconds + frames
             *	Frames are derived from 'fraction' of second. We need to perform some additional rounding
             *	to cope with 'half' frames, etc., which should be fine in most cases
             */
            seconds= (int)val;
            frames= (int)floor( ((val - seconds) * FPS) + 0.5f );
        }

        /* print timecode to temp string buffer */
        if (hours) sprintf(str, "   %s%02d:%02d:%02d!%02d", neg, hours, minutes, seconds, frames);
        else if (minutes) sprintf(str, "   %s%02d:%02d!%02d", neg, minutes, seconds, frames);
        else sprintf(str, "   %s%d!%02d", neg, seconds, frames);
    }
    else
        sprintf(str, "   %d", CFRA);
    slen= (short)UI_GetStringWidth(str) - 1;

    /* get starting coordinates for drawing */
    x= cfra * xscale;
    y= 18;

    /* draw green box around/behind text */
    UI_ThemeColorShadeAlpha(TH_CFRAME, 0, -100);
    glRectf(x, y,  x+slen,  y+15);

    /* draw current frame number - black text */
    UI_ThemeColor(TH_TEXT);
    UI_DrawString(x-5, y+3, str); // XXX may need to be updated for font stuff

    /* restore view transform */
    glScalef(xscale, 1.0, 1.0);
}