Beispiel #1
0
void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac)
{
	DLRBT_Tree keys, blocks;
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	ob_to_keylist(ads, ob, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
Beispiel #2
0
void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac)
{
	DLRBT_Tree keys, blocks;
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	scene_to_keylist(ads, sce, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
Beispiel #3
0
void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac)
{
	DLRBT_Tree keys, blocks;
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	summary_to_keylist(ac, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
Beispiel #4
0
/* helper for time_draw_keyframes() */
static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
{
	bDopeSheet ads = {NULL};
	DLRBT_Tree keys;
	ActKeyColumn *ak;

	float fac1 = (GS(id->name) == ID_GD) ? 0.8f : 0.6f; /* draw GPencil keys taller, to help distinguish them */
	float fac2 = 1.0f - fac1;

	float ymin = v2d->tot.ymin;
	float ymax = v2d->tot.ymax * fac1 + ymin * fac2;

	/* init binarytree-list for getting keyframes */
	BLI_dlrbTree_init(&keys);

	/* init dopesheet settings */
	if (onlysel)
		ads.filterflag |= ADS_FILTER_ONLYSEL;

	/* populate tree with keyframe nodes */
	switch (GS(id->name)) {
		case ID_SCE:
			scene_to_keylist(&ads, (Scene *)id, &keys, NULL);
			break;
		case ID_OB:
			ob_to_keylist(&ads, (Object *)id, &keys, NULL);
			break;
		case ID_GD:
			gpencil_to_keylist(&ads, (bGPdata *)id, &keys);
			break;
		case ID_CF:
			cachefile_to_keylist(&ads, (CacheFile *)id, &keys, NULL);
			break;
		default:
			break;
	}

	/* build linked-list for searching */
	BLI_dlrbTree_linkedlist_sync(&keys);

	/* start drawing keyframes
	 *	- we use the binary-search capabilities of the tree to only start from
	 *	  the first visible keyframe (last one can then be easily checked)
	 *	- draw within a single GL block to be faster
	 */
	glBegin(GL_LINES);
	for (ak = time_cfra_find_ak(keys.root, v2d->cur.xmin);
	     (ak) && (ak->cfra <= v2d->cur.xmax);
	     ak = ak->next)
	{
		glVertex2f(ak->cfra, ymin);
		glVertex2f(ak->cfra, ymax);
	}
	glEnd(); // GL_LINES

	/* free temp stuff */
	BLI_dlrbTree_free(&keys);
}
void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
{
	DLRBT_Tree keys, blocks;
	
	short locked = (act && act->id.lib != NULL);
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	action_to_keylist(adt, act, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, locked);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
Beispiel #6
0
void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac)
{
	DLRBT_Tree keys, blocks;

	bool locked = (act && ID_IS_LINKED(act));

	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);

	action_to_keylist(adt, act, &keys, &blocks);

	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);

	draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);

	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
Beispiel #7
0
void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac)
{
	DLRBT_Tree keys, blocks;

	bool locked = (agrp->flag & AGRP_PROTECTED) ||
	              ((adt && adt->action) && ID_IS_LINKED(adt->action));

	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);

	agroup_to_keylist(adt, agrp, &keys, &blocks);

	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);

	draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);

	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos)
{
	DLRBT_Tree keys, blocks;
	
	short locked = (agrp->flag & AGRP_PROTECTED) ||
	               ((adt && adt->action) && (adt->action->id.lib));
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	agroup_to_keylist(adt, agrp, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, locked);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
Beispiel #9
0
void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac)
{
	DLRBT_Tree keys, blocks;
	
	bool locked = (fcu->flag & FCURVE_PROTECTED) ||
	              ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
	              ((adt && adt->action) && ID_IS_LINKED_DATABLOCK(adt->action));
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	fcurve_to_keylist(adt, fcu, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
Beispiel #10
0
/* operator init */
static int pose_slide_init(bContext *C, wmOperator *op, short mode)
{
	tPoseSlideOp *pso;
	bAction *act = NULL;
	
	/* init slide-op data */
	pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp");
	
	/* get info from context */
	pso->scene = CTX_data_scene(C);
	pso->ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
	pso->arm = (pso->ob) ? pso->ob->data : NULL;
	pso->sa = CTX_wm_area(C); /* only really needed when doing modal() */
	pso->ar = CTX_wm_region(C); /* only really needed when doing modal() */
	
	pso->cframe = pso->scene->r.cfra;
	pso->mode = mode;
	
	/* set range info from property values - these may get overridden for the invoke() */
	pso->percentage = RNA_float_get(op->ptr, "percentage");
	pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
	pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
	
	/* check the settings from the context */
	if (ELEM(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
		return 0;
	else
		act = pso->ob->adt->action;
	
	/* for each Pose-Channel which gets affected, get the F-Curves for that channel 
	 * and set the relevant transform flags...
	 */
	poseAnim_mapping_get(C, &pso->pfLinks, pso->ob, act);
	
	/* set depsgraph flags */
	/* make sure the lock is set OK, unlock can be accidentally saved? */
	pso->ob->pose->flag |= POSE_LOCKED;
	pso->ob->pose->flag &= ~POSE_DO_UNLOCK;
	
	/* do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up 
	 * to the caller of this (usually only invoke() will do it, to make things more efficient).
	 */
	BLI_dlrbTree_init(&pso->keys);
	
	/* initialise numeric input */
	initNumInput(&pso->num);
	pso->num.idx_max = 0; /* one axis */
	pso->num.val_flag[0] |= NUM_NO_NEGATIVE;
	pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */
	
	/* return status is whether we've got all the data we were requested to get */
	return 1;
}
void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
{
	DLRBT_Tree keys, blocks;
	
	short locked = (fcu->flag & FCURVE_PROTECTED) ||
	               ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
	               ((adt && adt->action) && (adt->action->id.lib));
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	fcurve_to_keylist(adt, fcu, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, locked);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos)
{
	DLRBT_Tree keys;

	BLI_dlrbTree_init(&keys);

	mask_to_keylist(ads, masklay, &keys);

	BLI_dlrbTree_linkedlist_sync(&keys);

	draw_keylist(v2d, &keys, NULL, ypos, (masklay->flag & MASK_LAYERFLAG_LOCKED));

	BLI_dlrbTree_free(&keys);
}
void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
{
	DLRBT_Tree keys;
	
	BLI_dlrbTree_init(&keys);
	
	gpl_to_keylist(ads, gpl, &keys);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	
	draw_keylist(v2d, &keys, NULL, ypos, (gpl->flag & GP_LAYER_LOCKED));
	
	BLI_dlrbTree_free(&keys);
}
void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos)
{
	DLRBT_Tree keys;
	
	BLI_dlrbTree_init(&keys);
	
	gpencil_to_keylist(ads, gpd, &keys);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	
	draw_keylist(v2d, &keys, NULL, ypos, 0);
	
	BLI_dlrbTree_free(&keys);
}
Beispiel #15
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_scale_get(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);
}
Beispiel #16
0
/* get frame on which the "hold" for the bone ends 
 * XXX: this may not really work that well if a bone moves on some channels and not others
 *      if this happens to be a major issue, scrap this, and just make this happen
 *		independently per F-Curve
 */
static float pose_propagate_get_boneHoldEndFrame(Object *ob, tPChanFCurveLink *pfl, float startFrame)
{
	DLRBT_Tree keys, blocks;
	ActKeyBlock *ab;
	
	AnimData *adt = ob->adt;
	LinkData *ld;
	float endFrame = startFrame;
	
	/* set up optimized data-structures for searching for relevant keyframes + holds */
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	for (ld = pfl->fcurves.first; ld; ld = ld->next) {
		FCurve *fcu = (FCurve *)ld->data;
		fcurve_to_keylist(adt, fcu, &keys, &blocks);
	}
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	/* find the long keyframe (i.e. hold), and hence obtain the endFrame value 
	 *	- the best case would be one that starts on the frame itself
	 */
	ab = (ActKeyBlock *)BLI_dlrbTree_search_exact(&blocks, compare_ab_cfraPtr, &startFrame);
	
	if (actkeyblock_is_valid(ab, &keys) == 0) {
		/* There are only two cases for no-exact match:
		 *  1) the current frame is just before another key but not on a key itself
		 *  2) the current frame is on a key, but that key doesn't link to the next
		 *
		 * If we've got the first case, then we can search for another block, 
		 * otherwise forget it, as we'd be overwriting some valid data.
		 */
		if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &startFrame) == NULL) {
			/* we've got case 1, so try the one after */
			ab = (ActKeyBlock *)BLI_dlrbTree_search_next(&blocks, compare_ab_cfraPtr, &startFrame);
			
			if (actkeyblock_is_valid(ab, &keys) == 0) {
				/* try the block before this frame then as last resort */
				ab = (ActKeyBlock *)BLI_dlrbTree_search_prev(&blocks, compare_ab_cfraPtr, &startFrame);
				
				/* whatever happens, stop searching now... */
				if (actkeyblock_is_valid(ab, &keys) == 0) {
					/* restrict range to just the frame itself 
					 * i.e. everything is in motion, so no holds to safely overwrite
					 */
					ab = NULL;
				}
			}
		}
		else {
			/* we've got case 2 - set ab to NULL just in case, since we shouldn't do anything in this case */
			ab = NULL;
		}
	}
	
	/* check if we can go any further than we've already gone */
	if (ab) {
		/* go to next if it is also valid and meets "extension" criteria */
		while (ab->next) {
			ActKeyBlock *abn = (ActKeyBlock *)ab->next;
			
			/* must be valid */
			if (actkeyblock_is_valid(abn, &keys) == 0)
				break;
			/* should start on the same frame that the last ended on */
			if (ab->end != abn->start)
				break;
			/* should have the same number of curves */
			if (ab->totcurve != abn->totcurve)
				break;
			/* should have the same value 
			 * XXX: this may be a bit fuzzy on larger data sets, so be careful
			 */
			if (ab->val != abn->val)
				break;
				
			/* we can extend the bounds to the end of this "next" block now */
			ab = abn;
		}
		
		/* end frame can now take the value of the end of the block */
		endFrame = ab->end;
	}
	
	/* free temp memory */
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
	
	/* return the end frame we've found */
	return endFrame;
}
Beispiel #17
0
/* draw the keyframes in the specified Action */
static void nla_action_draw_keyframes(
    View2D *v2d, AnimData *adt, bAction *act, float y, float ymin, float ymax)
{
  /* get a list of the keyframes with NLA-scaling applied */
  DLRBT_Tree keys;
  BLI_dlrbTree_init(&keys);
  action_to_keylist(adt, act, &keys, 0);

  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)
   */
  float color[4];
  nla_action_get_color(adt, act, color);
  color[3] *= 2.5f;

  GPUVertFormat *format = immVertexFormat();
  uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);

  immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);

  immUniformColor4fv(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)
   */
  float f1 = ((ActKeyColumn *)keys.first)->cfra;
  float f2 = ((ActKeyColumn *)keys.last)->cfra;

  immRectf(pos_id, f1, ymin + 2, f2, ymax - 2);
  immUnbindProgram();

  /* count keys before drawing */
  /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */
  uint key_len = BLI_listbase_count((ListBase *)&keys);

  if (key_len > 0) {
    format = immVertexFormat();
    pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
    uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
    uint color_id = GPU_vertformat_attr_add(
        format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
    uint outline_color_id = GPU_vertformat_attr_add(
        format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
    uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
    immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
    GPU_program_point_size(true);
    immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
    immBegin(GPU_PRIM_POINTS, key_len);

    /* - disregard the selection status of keyframes so they draw a certain way
     * - size is 6.0f which is smaller than the editable keyframes, so that there is a distinction
     */
    for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) {
      draw_keyframe_shape(ak->cfra,
                          y,
                          6.0f,
                          false,
                          ak->key_type,
                          KEYFRAME_SHAPE_FRAME,
                          1.0f,
                          pos_id,
                          size_id,
                          color_id,
                          outline_color_id,
                          flags_id,
                          KEYFRAME_HANDLE_NONE,
                          KEYFRAME_EXTREME_NONE);
    }

    immEnd();
    GPU_program_point_size(false);
    immUnbindProgram();
  }

  /* free icons */
  BLI_dlrbTree_free(&keys);
}
Beispiel #18
0
/* Draw the given motion path for an Object or a Bone 
 *  - assumes that the viewport has already been initialized properly
 *    i.e. draw_motion_paths_init() has been called
 */
void draw_motion_path_instance(Scene *scene, 
                               Object *ob, bPoseChannel *pchan, bAnimVizSettings *avs, bMotionPath *mpath)
{
	//RegionView3D *rv3d = ar->regiondata;
	bMotionPathVert *mpv, *mpv_start;
	int i, stepsize = avs->path_step;
	int sfra, efra, sind, len;
	
	/* get frame ranges */
	if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
		/* With "Around Current", we only choose frames from around 
		 * the current frame to draw.
		 */
		sfra = CFRA - avs->path_bc;
		efra = CFRA + avs->path_ac;
	}
	else {
		/* Use the current display range */
		sfra = avs->path_sf;
		efra = avs->path_ef;
	}
	
	/* no matter what, we can only show what is in the cache and no more 
	 * - abort if whole range is past ends of path
	 * - otherwise clamp endpoints to extents of path
	 */
	if (sfra < mpath->start_frame) {
		/* start clamp */
		sfra = mpath->start_frame;
	}
	if (efra > mpath->end_frame) {
		/* end clamp */
		efra = mpath->end_frame;
	}
	
	if ((sfra > mpath->end_frame) || (efra < mpath->start_frame)) {
		/* whole path is out of bounds */
		return;
	}
	
	len = efra - sfra;
	
	if ((len <= 0) || (mpath->points == NULL)) {
		return;
	}
	
	/* get pointers to parts of path */
	sind = sfra - mpath->start_frame;
	mpv_start = (mpath->points + sind);
	
	/* draw curve-line of path */
	glShadeModel(GL_SMOOTH);
	
	glBegin(GL_LINE_STRIP);
	for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
		short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
		float intensity;  /* how faint */
		
		int frame = sfra + i;
		int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */
		
		/* set color
		 * - more intense for active/selected bones, less intense for unselected bones
		 * - black for before current frame, green for current frame, blue for after current frame
		 * - intensity decreases as distance from current frame increases
		 */
#define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min)
		if (frame < CFRA) {
			/* black - before cfra */
			if (sel) {
				/* intensity = 0.5f; */
				intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
			}
			else {
				/* intensity = 0.8f; */
				intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
			}
			UI_ThemeColorBlend(TH_WIRE, blend_base, intensity);
		}
		else if (frame > CFRA) {
			/* blue - after cfra */
			if (sel) {
				/* intensity = 0.5f; */
				intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
			}
			else {
				/* intensity = 0.8f; */
				intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
			}
			UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity);
		}
		else {
			/* green - on cfra */
			if (sel) {
				intensity = 0.5f;
			}
			else {
				intensity = 0.99f;
			}
			UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
		}
#undef SET_INTENSITY

		/* draw a vertex with this color */
		glVertex3fv(mpv->co);
	}
	
	glEnd();
	glShadeModel(GL_FLAT);
	
	glPointSize(1.0);
	
	/* draw little black point at each frame
	 * NOTE: this is not really visible/noticeable
	 */
	glBegin(GL_POINTS);
	for (i = 0, mpv = mpv_start; i < len; i++, mpv++)
		glVertex3fv(mpv->co);
	glEnd();
	
	/* Draw little white dots at each framestep value */
	UI_ThemeColor(TH_TEXT_HI);
	glBegin(GL_POINTS);
	for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize)
		glVertex3fv(mpv->co);
	glEnd();
	
	/* Draw big green dot where the current frame is 
	 * NOTE: this is only done when keyframes are shown, since this adds similar types of clutter
	 */
	if ((avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) &&
	    (sfra < CFRA) && (CFRA <= efra))
	{
		UI_ThemeColor(TH_CFRAME);
		glPointSize(6.0f);
		
		glBegin(GL_POINTS);
		mpv = mpv_start + (CFRA - sfra);
		glVertex3fv(mpv->co);
		glEnd();
		
		UI_ThemeColor(TH_TEXT_HI);
	}
	
	/* XXX, this isn't up to date but probably should be kept so. */
	invert_m4_m4(ob->imat, ob->obmat);
	
	/* Draw frame numbers at each framestep value */
	if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) {
		unsigned char col[4];
		UI_GetThemeColor3ubv(TH_TEXT_HI, col);
		col[3] = 255;
		
		for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) {
			int frame = sfra + i;
			char numstr[32];
			size_t numstr_len;
			float co[3];
			
			/* only draw framenum if several consecutive highlighted points don't occur on same point */
			if (i == 0) {
				numstr_len = sprintf(numstr, " %d", frame);
				mul_v3_m4v3(co, ob->imat, mpv->co);
				view3d_cached_text_draw_add(co, numstr, numstr_len,
				                            0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
			}
			else if ((i >= stepsize) && (i < len - stepsize)) {
				bMotionPathVert *mpvP = (mpv - stepsize);
				bMotionPathVert *mpvN = (mpv + stepsize);
				
				if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
					numstr_len = sprintf(numstr, " %d", frame);
					mul_v3_m4v3(co, ob->imat, mpv->co);
					view3d_cached_text_draw_add(co, numstr, numstr_len,
					                            0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
				}
			}
		}
	}
	
	/* Keyframes - dots and numbers */
	if (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) {
		unsigned char col[4];
		
		AnimData *adt = BKE_animdata_from_id(&ob->id);
		DLRBT_Tree keys;
		
		/* build list of all keyframes in active action for object or pchan */
		BLI_dlrbTree_init(&keys);
		
		if (adt) {
			/* it is assumed that keyframes for bones are all grouped in a single group
			 * unless an option is set to always use the whole action
			 */
			if ((pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
				bActionGroup *agrp = BKE_action_group_find_name(adt->action, pchan->name);
				
				if (agrp) {
					agroup_to_keylist(adt, agrp, &keys, NULL);
					BLI_dlrbTree_linkedlist_sync(&keys);
				}
			}
			else {
				action_to_keylist(adt, adt->action, &keys, NULL);
				BLI_dlrbTree_linkedlist_sync(&keys);
			}
		}
		
		/* Draw slightly-larger yellow dots at each keyframe */
		UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
		col[3] = 255;
		
		glPointSize(4.0f);
		glColor3ubv(col);
		
		glBegin(GL_POINTS);
		for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
			int    frame = sfra + i; 
			float mframe = (float)(frame);
			
			if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe))
				glVertex3fv(mpv->co);
		}
		glEnd();
		
		/* Draw frame numbers of keyframes  */
		if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) {
			float co[3];
			for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
				float mframe = (float)(sfra + i);
				
				if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) {
					char numstr[32];
					size_t numstr_len;
					
					numstr_len = sprintf(numstr, " %d", (sfra + i));
					mul_v3_m4v3(co, ob->imat, mpv->co);
					view3d_cached_text_draw_add(co, numstr, numstr_len,
					                            0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
				}
			}
		}
		
		BLI_dlrbTree_free(&keys);
	}
}
static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra)
{
	Scene *scene = CTX_data_scene(C);
	Object *ob = CTX_data_active_object(C);
	bGPdata *gpd = CTX_data_gpencil_data(C);
	Mask *mask = CTX_data_edit_mask(C);
	bDopeSheet ads = {NULL};
	DLRBT_Tree keys;
	ActKeyColumn *aknext, *akprev;
	float cfranext, cfraprev;
	bool donenext = false, doneprev = false;
	int nextcount = 0, prevcount = 0;

	cfranext = cfraprev = (float)(CFRA);

	/* init binarytree-list for getting keyframes */
	BLI_dlrbTree_init(&keys);

	/* seed up dummy dopesheet context with flags to perform necessary filtering */
	if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) {
		/* only selected channels are included */
		ads.filterflag |= ADS_FILTER_ONLYSEL;
	}

	/* populate tree with keyframe nodes */
	scene_to_keylist(&ads, scene, &keys, NULL);

	if (ob)
		ob_to_keylist(&ads, ob, &keys, NULL);

	gpencil_to_keylist(&ads, gpd, &keys);

	if (mask) {
		MaskLayer *masklay = BKE_mask_layer_active(mask);
		mask_to_keylist(&ads, masklay, &keys);
	}

	/* build linked-list for searching */
	BLI_dlrbTree_linkedlist_sync(&keys);

	/* find matching keyframe in the right direction */
	do {
		aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfranext);

		if (aknext) {
			if (CFRA == (int)aknext->cfra) {
				/* make this the new starting point for the search and ignore */
				cfranext = aknext->cfra;
			}
			else {
				/* this changes the frame, so set the frame and we're done */
				if (++nextcount == U.view_frame_keyframes)
					donenext = true;
			}
			cfranext = aknext->cfra;
		}
	} while ((aknext != NULL) && (donenext == false));

	do {
		akprev = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfraprev);

		if (akprev) {
			if (CFRA == (int)akprev->cfra) {
				/* make this the new starting point for the search */
			}
			else {
				/* this changes the frame, so set the frame and we're done */
				if (++prevcount == U.view_frame_keyframes)
					doneprev = true;
			}
			cfraprev = akprev->cfra;
		}
	} while ((akprev != NULL) && (doneprev == false));

	/* free temp stuff */
	BLI_dlrbTree_free(&keys);

	/* any success? */
	if (doneprev || donenext) {
		if (doneprev)
			*prevfra = cfraprev;
		else
			*prevfra = CFRA - (cfranext - CFRA);

		if (donenext)
			*nextfra = cfranext;
		else
			*nextfra = CFRA + (CFRA - cfraprev);

		return true;
	}

	return false;
}
Beispiel #20
0
/* This tool automagically generates/validates poselib data so that it corresponds to the data 
 * in the action. This is for use in making existing actions usable as poselibs.
 */
static int poselib_sanitise_exec (bContext *C, wmOperator *op)
{
	Object *ob = get_poselib_object(C);
	bAction *act = (ob)? ob->poselib : NULL;
	DLRBT_Tree keys;
	ActKeyColumn *ak;
	TimeMarker *marker, *markern;
	
	/* validate action */
	if (act == NULL)  {
		BKE_report(op->reports, RPT_WARNING, "No Action to validate");
		return OPERATOR_CANCELLED;
	}
	
	/* determine which frames have keys */
	BLI_dlrbTree_init(&keys);
		action_to_keylist(NULL, act, &keys, NULL);
	BLI_dlrbTree_linkedlist_sync(&keys);
	
	/* for each key, make sure there is a corresponding pose */
	for (ak= keys.first; ak; ak= ak->next) {
		/* check if any pose matches this */
		// TODO: don't go looking through the list like this every time...
		for (marker= act->markers.first; marker; marker= marker->next) {
			if (IS_EQ(marker->frame, (double)ak->cfra)) {
				marker->flag = -1;
				break;
			}
		}
		
		/* add new if none found */
		if (marker == NULL) {
			/* add pose to poselib */
			marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
			
			BLI_strncpy(marker->name, "Pose", sizeof(marker->name));
			
			marker->frame= (int)ak->cfra;
			marker->flag= -1;
			
			BLI_addtail(&act->markers, marker);
		}
	}
	
	/* remove all untagged poses (unused), and remove all tags */
	for (marker= act->markers.first; marker; marker= markern) {
		markern= marker->next;
		
		if (marker->flag != -1)
			BLI_freelinkN(&act->markers, marker);
		else
			marker->flag = 0;
	}
	
	/* free temp memory */
	BLI_dlrbTree_free(&keys);
	
	/* send notifiers for this - using keyframe editing notifiers, since action 
	 * may be being shown in anim editors as active action 
	 */
	WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
	
	return OPERATOR_FINISHED;
}
Beispiel #21
0
static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_mode, bool column, bool same_channel)
{
	ListBase anim_data = {NULL, NULL};
	DLRBT_Tree anim_keys;
	bAnimListElem *ale;
	int filter;
	
	View2D *v2d = &ac->ar->v2d;
	bDopeSheet *ads = NULL;
	int channel_index;
	bool found = false;
	float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
	float selx = 0.0f;  /* frame of keyframe under mouse */
	float key_hsize;
	float x, y;
	rctf rectf;
	
	/* get dopesheet info */
	if (ac->datatype == ANIMCONT_DOPESHEET)
		ads = ac->data;
	
	/* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
	UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
	UI_view2d_listview_view_to_cell(v2d, 0, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index);
	
	/* x-range to check is +/- 7px for standard keyframe under standard dpi/y-scale (in screen/region-space),
	 * on either side of mouse click (size of keyframe icon)
	 */
	key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f;    /* standard channel height (to allow for some slop) */
	key_hsize = roundf(key_hsize / 2.0f);      /* half-size (for either side), but rounded up to nearest int (for easier targetting) */
	
	UI_view2d_region_to_view(v2d, mval[0] - (int)key_hsize, mval[1], &rectf.xmin, &rectf.ymin);
	UI_view2d_region_to_view(v2d, mval[0] + (int)key_hsize, mval[1], &rectf.xmax, &rectf.ymax);
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* try to get channel */
	ale = BLI_findlink(&anim_data, channel_index);
	if (ale == NULL) {
		/* channel not found */
		printf("Error: animation channel (index = %d) not found in mouse_action_keys()\n", channel_index);
		ANIM_animdata_freelist(&anim_data);
		return;
	}
	else {
		/* found match - must return here... */
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		ActKeyColumn *ak, *akn = NULL;
		
		/* make list of keyframes */
		BLI_dlrbTree_init(&anim_keys);
		
		if (ale->key_data) {
			switch (ale->datatype) {
				case ALE_SCE:
				{
					Scene *scene = (Scene *)ale->key_data;
					scene_to_keylist(ads, scene, &anim_keys, NULL);
					break;
				}
				case ALE_OB:
				{
					Object *ob = (Object *)ale->key_data;
					ob_to_keylist(ads, ob, &anim_keys, NULL);
					break;
				}
				case ALE_ACT:
				{
					bAction *act = (bAction *)ale->key_data;
					action_to_keylist(adt, act, &anim_keys, NULL);
					break;
				}
				case ALE_FCURVE:
				{
					FCurve *fcu = (FCurve *)ale->key_data;
					fcurve_to_keylist(adt, fcu, &anim_keys, NULL);
					break;
				}
			}
		}
		else if (ale->type == ANIMTYPE_SUMMARY) {
			/* dopesheet summary covers everything */
			summary_to_keylist(ac, &anim_keys, NULL);
		}
		else if (ale->type == ANIMTYPE_GROUP) {
			// TODO: why don't we just give groups key_data too?
			bActionGroup *agrp = (bActionGroup *)ale->data;
			agroup_to_keylist(adt, agrp, &anim_keys, NULL);
		}
		else if (ale->type == ANIMTYPE_GPLAYER) {
			// TODO: why don't we just give gplayers key_data too?
			bGPDlayer *gpl = (bGPDlayer *)ale->data;
			gpl_to_keylist(ads, gpl, &anim_keys);
		}
		else if (ale->type == ANIMTYPE_MASKLAYER) {
			// TODO: why don't we just give masklayers key_data too?
			MaskLayer *masklay = (MaskLayer *)ale->data;
			mask_to_keylist(ads, masklay, &anim_keys);
		}

		/* start from keyframe at root of BST, traversing until we find one within the range that was clicked on */
		for (ak = anim_keys.root; ak; ak = akn) {
			if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) {
				/* set the frame to use, and apply inverse-correction for NLA-mapping 
				 * so that the frame will get selected by the selection functions without
				 * requiring to map each frame once again...
				 */
				selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
				frame = ak->cfra;
				found = true;
				break;
			}
			else if (ak->cfra < rectf.xmin)
				akn = ak->right;
			else
				akn = ak->left;
		}
		
		/* remove active channel from list of channels for separate treatment (since it's needed later on) */
		BLI_remlink(&anim_data, ale);
		
		/* cleanup temporary lists */
		BLI_dlrbTree_free(&anim_keys);
		
		/* free list of channels, since it's not used anymore */
		ANIM_animdata_freelist(&anim_data);
	}
	
	/* for replacing selection, firstly need to clear existing selection */
	if (select_mode == SELECT_REPLACE) {
		/* reset selection mode for next steps */
		select_mode = SELECT_ADD;
		
		/* deselect all keyframes */
		deselect_action_keys(ac, 0, SELECT_SUBTRACT);
		
		/* highlight channel clicked on */
		if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
			/* deselect all other channels first */
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
			
			/* Highlight Action-Group or F-Curve? */
			if (ale && ale->data) {
				if (ale->type == ANIMTYPE_GROUP) {
					bActionGroup *agrp = ale->data;
					
					agrp->flag |= AGRP_SELECTED;
					ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
				}
				else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
					FCurve *fcu = ale->data;
					
					fcu->flag |= FCURVE_SELECTED;
					ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
				}
			}
		}
		else if (ac->datatype == ANIMCONT_GPENCIL) {
			/* deselect all other channels first */
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
			
			/* Highlight GPencil Layer */
			if ((ale && ale->data) && (ale->type == ANIMTYPE_GPLAYER)) {
				bGPDlayer *gpl = ale->data;
				
				gpl->flag |= GP_LAYER_SELECT;
				//gpencil_layer_setactive(gpd, gpl);
			}
		}
		else if (ac->datatype == ANIMCONT_MASK) {
			/* deselect all other channels first */
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);

			/* Highlight GPencil Layer */
			if ((ale && ale->data) && (ale->type == ANIMTYPE_MASKLAYER)) {
				MaskLayer *masklay = ale->data;

				masklay->flag |= MASK_LAYERFLAG_SELECT;
				//gpencil_layer_setactive(gpd, gpl);
			}
		}
	}
	
	/* only select keyframes if we clicked on a valid channel and hit something */
	if (ale) {
		if (found) {
			/* apply selection to keyframes */
			if (column) {
				/* select all keyframes in the same frame as the one we hit on the active channel 
				 * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here
				 *            does that itself again as it needs to work on multiple datablocks 
				 */
				actkeys_mselect_column(ac, select_mode, frame);
			}
			else if (same_channel) {
				/* select all keyframes in the active channel */
				actkeys_mselect_channel_only(ac, ale, select_mode);	
			}
			else {
				/* select the nominated keyframe on the given frame */
				actkeys_mselect_single(ac, ale, select_mode, selx);
			}
		}
		
		/* free this channel */
		MEM_freeN(ale);
	}
}